Merging from development
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
+12
@@ -99,6 +99,18 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
if (selection.GetSelectedAssetIds().empty())
|
||||
{
|
||||
for (auto& filePath : selection.GetSelectedFilePaths())
|
||||
{
|
||||
if (!filePath.empty())
|
||||
{
|
||||
selectedAsset = true;
|
||||
m_ui->m_assetBrowserTreeViewWidget->SelectFileAtPath(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedAsset)
|
||||
{
|
||||
m_ui->m_assetBrowserTreeViewWidget->SelectFolder(selection.GetDefaultDirectory());
|
||||
|
||||
+60
-9
@@ -10,18 +10,24 @@
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
|
||||
#include <QRegExp>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
#endif
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
namespace
|
||||
{
|
||||
FilterConstType ProductsNoFoldersFilter()
|
||||
FilterConstType EntryTypeNoFoldersFilter(AssetBrowserEntry::AssetEntryType entryType = AssetBrowserEntry::AssetEntryType::Product)
|
||||
{
|
||||
EntryTypeFilter* productFilter = new EntryTypeFilter();
|
||||
productFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Product);
|
||||
EntryTypeFilter* entryTypeFilter = new EntryTypeFilter();
|
||||
entryTypeFilter->SetEntryType(entryType);
|
||||
// in case entry is a source or folder, it may still contain relevant product
|
||||
productFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
entryTypeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
|
||||
EntryTypeFilter* foldersFilter = new EntryTypeFilter();
|
||||
foldersFilter->SetEntryType(AssetBrowserEntry::AssetEntryType::Folder);
|
||||
@@ -30,7 +36,7 @@ namespace AzToolsFramework
|
||||
noFoldersFilter->SetFilter(FilterConstType(foldersFilter));
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
compFilter->AddFilter(FilterConstType(productFilter));
|
||||
compFilter->AddFilter(FilterConstType(entryTypeFilter));
|
||||
compFilter->AddFilter(FilterConstType(noFoldersFilter));
|
||||
|
||||
return FilterConstType(compFilter);
|
||||
@@ -79,15 +85,39 @@ namespace AzToolsFramework
|
||||
|
||||
void AssetSelectionModel::SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds)
|
||||
{
|
||||
m_selectedFilePaths.clear();
|
||||
|
||||
m_selectedAssetIds = selectedAssetIds;
|
||||
}
|
||||
|
||||
void AssetSelectionModel::SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId)
|
||||
{
|
||||
m_selectedFilePaths.clear();
|
||||
|
||||
m_selectedAssetIds.clear();
|
||||
m_selectedAssetIds.push_back(selectedAssetId);
|
||||
}
|
||||
|
||||
const AZStd::vector<AZStd::string>& AssetSelectionModel::GetSelectedFilePaths() const
|
||||
{
|
||||
return m_selectedFilePaths;
|
||||
}
|
||||
|
||||
void AssetSelectionModel::SetSelectedFilePaths(const AZStd::vector<AZStd::string>& selectedFilePaths)
|
||||
{
|
||||
m_selectedAssetIds.clear();
|
||||
|
||||
m_selectedFilePaths = selectedFilePaths;
|
||||
}
|
||||
|
||||
void AssetSelectionModel::SetSelectedFilePath(const AZStd::string& selectedFilePath)
|
||||
{
|
||||
m_selectedAssetIds.clear();
|
||||
|
||||
m_selectedFilePaths.clear();
|
||||
m_selectedFilePaths.push_back(selectedFilePath);
|
||||
}
|
||||
|
||||
void AssetSelectionModel::SetDefaultDirectory(AZStd::string_view defaultDirectory)
|
||||
{
|
||||
m_defaultDirectory = defaultDirectory;
|
||||
@@ -136,7 +166,7 @@ namespace AzToolsFramework
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
compFilter->AddFilter(assetTypeFilterPtr);
|
||||
compFilter->AddFilter(ProductsNoFoldersFilter());
|
||||
compFilter->AddFilter(EntryTypeNoFoldersFilter());
|
||||
|
||||
selection.SetSelectionFilter(FilterConstType(compFilter));
|
||||
selection.SetMultiselect(multiselect);
|
||||
@@ -169,7 +199,7 @@ namespace AzToolsFramework
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
compFilter->AddFilter(anyAssetTypeFilterPtr);
|
||||
compFilter->AddFilter(ProductsNoFoldersFilter());
|
||||
compFilter->AddFilter(EntryTypeNoFoldersFilter());
|
||||
|
||||
selection.SetSelectionFilter(FilterConstType(compFilter));
|
||||
selection.SetMultiselect(multiselect);
|
||||
@@ -190,7 +220,28 @@ namespace AzToolsFramework
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
compFilter->AddFilter(assetGroupFilterPtr);
|
||||
compFilter->AddFilter(ProductsNoFoldersFilter());
|
||||
compFilter->AddFilter(EntryTypeNoFoldersFilter());
|
||||
|
||||
selection.SetSelectionFilter(FilterConstType(compFilter));
|
||||
selection.SetMultiselect(multiselect);
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
AssetSelectionModel AssetSelectionModel::SourceAssetTypeSelection(const QString& pattern, bool multiselect)
|
||||
{
|
||||
AssetSelectionModel selection;
|
||||
|
||||
RegExpFilter* patternFilter = new RegExpFilter();
|
||||
patternFilter->SetFilterPattern(pattern);
|
||||
patternFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
auto patternFilterPtr = FilterConstType(patternFilter);
|
||||
|
||||
selection.SetDisplayFilter(patternFilterPtr);
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::AND);
|
||||
compFilter->AddFilter(patternFilterPtr);
|
||||
compFilter->AddFilter(EntryTypeNoFoldersFilter(AssetBrowserEntry::AssetEntryType::Source));
|
||||
|
||||
selection.SetSelectionFilter(FilterConstType(compFilter));
|
||||
selection.SetMultiselect(multiselect);
|
||||
@@ -204,7 +255,7 @@ namespace AzToolsFramework
|
||||
|
||||
CompositeFilter* compFilter = new CompositeFilter(CompositeFilter::LogicOperatorType::OR);
|
||||
selection.SetDisplayFilter(FilterConstType(compFilter));
|
||||
selection.SetSelectionFilter(ProductsNoFoldersFilter());
|
||||
selection.SetSelectionFilter(EntryTypeNoFoldersFilter());
|
||||
selection.SetMultiselect(multiselect);
|
||||
|
||||
return selection;
|
||||
|
||||
+10
-1
@@ -44,6 +44,10 @@ namespace AzToolsFramework
|
||||
void SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds);
|
||||
void SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId);
|
||||
|
||||
const AZStd::vector<AZStd::string>& GetSelectedFilePaths() const;
|
||||
void SetSelectedFilePaths(const AZStd::vector<AZStd::string>& selectedFilePaths);
|
||||
void SetSelectedFilePath(const AZStd::string& selectedFilePath);
|
||||
|
||||
void SetDefaultDirectory(AZStd::string_view defaultDirectory);
|
||||
AZStd::string_view GetDefaultDirectory() const;
|
||||
|
||||
@@ -60,6 +64,7 @@ namespace AzToolsFramework
|
||||
static AssetSelectionModel AssetTypeSelection(const char* assetTypeName, bool multiselect = false);
|
||||
static AssetSelectionModel AssetTypesSelection(const AZStd::vector<AZ::Data::AssetType>& assetTypes, bool multiselect = false);
|
||||
static AssetSelectionModel AssetGroupSelection(const char* group, bool multiselect = false);
|
||||
static AssetSelectionModel SourceAssetTypeSelection(const QString& pattern, bool multiselect = false);
|
||||
static AssetSelectionModel EverythingSelection(bool multiselect = false);
|
||||
|
||||
private:
|
||||
@@ -68,8 +73,12 @@ namespace AzToolsFramework
|
||||
// some entries like folder should always be displayed, but not always selectable, thus 2 separate filters
|
||||
FilterConstType m_selectionFilter;
|
||||
FilterConstType m_displayFilter;
|
||||
|
||||
|
||||
//! Selection can be based on asset ids (for products), or file paths (for sources)
|
||||
//! These are mututally exclusive
|
||||
AZStd::vector<AZ::Data::AssetId> m_selectedAssetIds;
|
||||
AZStd::vector<AZStd::string> m_selectedFilePaths;
|
||||
|
||||
AZStd::vector<const AssetBrowserEntry*> m_results;
|
||||
AZStd::string m_defaultDirectory;
|
||||
|
||||
|
||||
@@ -251,6 +251,40 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RegExpFilter
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
RegExpFilter::RegExpFilter()
|
||||
: m_filterPattern("")
|
||||
{
|
||||
}
|
||||
|
||||
void RegExpFilter::SetFilterPattern(const QString& filterPattern)
|
||||
{
|
||||
m_filterPattern = filterPattern;
|
||||
Q_EMIT updatedSignal();
|
||||
}
|
||||
|
||||
QString RegExpFilter::GetNameInternal() const
|
||||
{
|
||||
return m_filterPattern;
|
||||
}
|
||||
|
||||
bool RegExpFilter::MatchInternal(const AssetBrowserEntry* entry) const
|
||||
{
|
||||
// no filter pattern matches any asset
|
||||
if (m_filterPattern.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// entry's name matches regular expression pattern
|
||||
QRegExp regExp(m_filterPattern);
|
||||
regExp.setPatternSyntax(QRegExp::Wildcard);
|
||||
|
||||
return regExp.exactMatch(entry->GetDisplayName());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AssetTypeFilter
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -115,6 +115,28 @@ namespace AzToolsFramework
|
||||
QString m_filterString;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RegExpFilter
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! RegExpFilter filters assets based on a regular expression pattern
|
||||
class RegExpFilter
|
||||
: public AssetBrowserEntryFilter
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RegExpFilter();
|
||||
~RegExpFilter() override = default;
|
||||
|
||||
void SetFilterPattern(const QString& filterPattern);
|
||||
|
||||
protected:
|
||||
QString GetNameInternal() const override;
|
||||
bool MatchInternal(const AssetBrowserEntry* entry) const override;
|
||||
|
||||
private:
|
||||
QString m_filterPattern;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AssetTypeFilter
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+2
-2
@@ -37,9 +37,9 @@ namespace AzToolsFramework
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
|
||||
// ReadOnlyEntityPublicNotifications overrides ...
|
||||
// ReadOnlyEntityPublicInterface overrides ...
|
||||
bool IsReadOnly(const AZ::EntityId& entityId) override;
|
||||
|
||||
|
||||
// ReadOnlyEntityQueryInterface overrides ...
|
||||
void RefreshReadOnlyState(const EntityIdList& entityIds) override;
|
||||
void RefreshReadOnlyStateForAllEntities() override;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
void TraceLogger::PrepareLogFile(const AZStd::string& logFileName)
|
||||
void TraceLogger::OpenLogFile(const AZStd::string& logFileName, bool clearLogFile)
|
||||
{
|
||||
using namespace AzFramework;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace AzToolsFramework
|
||||
AZStd::string logPath;
|
||||
StringFunc::Path::Join(logDirectory.c_str(), logFileName.c_str(), logPath);
|
||||
|
||||
m_logFile.reset(aznew LogFile(logPath.c_str()));
|
||||
m_logFile.reset(aznew LogFile(logPath.c_str(), clearLogFile));
|
||||
if (m_logFile)
|
||||
{
|
||||
m_logFile->SetMachineReadable(false);
|
||||
@@ -81,7 +81,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_logFile->AppendLog(LogFile::SEV_NORMAL, message.window.c_str(), message.message.c_str());
|
||||
}
|
||||
m_startupLogSink = {};
|
||||
m_startupLogSink.clear();
|
||||
m_logFile->FlushLog();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace AzToolsFramework
|
||||
~TraceLogger();
|
||||
|
||||
//! Open log file and dump log sink into it
|
||||
void PrepareLogFile(const AZStd::string& logFileName);
|
||||
void OpenLogFile(const AZStd::string& logFileName, bool clearLogFile);
|
||||
|
||||
//! Add filter to ignore messages for windows with matching names
|
||||
void AddWindowFilter(const AZStd::string& filter);
|
||||
@@ -55,7 +55,8 @@ namespace AzToolsFramework
|
||||
AZStd::string window;
|
||||
AZStd::string message;
|
||||
};
|
||||
AZStd::vector<LogMessage> m_startupLogSink;
|
||||
|
||||
AZStd::list<LogMessage> m_startupLogSink;
|
||||
AZStd::unordered_set<AZStd::string> m_windowFilters;
|
||||
AZStd::unordered_set<AZStd::string> m_messageFilters;
|
||||
AZStd::unique_ptr<AzFramework::LogFile> m_logFile;
|
||||
|
||||
+2
-2
@@ -191,8 +191,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_manipulatorView->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay, cameraState,
|
||||
mouseInteraction);
|
||||
ManipulatorState{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
}
|
||||
|
||||
void AngularManipulator::SetAxis(const AZ::Vector3& axis)
|
||||
|
||||
+2
-2
@@ -116,8 +116,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_manipulatorView->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), m_localStart, MouseOver() }, debugDisplay, cameraState,
|
||||
mouseInteraction);
|
||||
ManipulatorState{ TransformUniformScale(GetSpace()), GetNonUniformScale(), m_localStart, MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,8 +239,8 @@ namespace AzToolsFramework
|
||||
|
||||
view->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ ApplySpace(localTransform), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay, cameraState,
|
||||
mouseInteraction);
|
||||
ManipulatorState{ ApplySpace(localTransform), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ namespace AzToolsFramework
|
||||
|
||||
for (const auto& pair : m_manipulatorIdToPtrMap)
|
||||
{
|
||||
pair.second->Draw({ Interacting() }, debugDisplay, cameraState, mouseInteraction);
|
||||
pair.second->Draw(ManipulatorManagerState{ Interacting() }, debugDisplay, cameraState, mouseInteraction);
|
||||
}
|
||||
|
||||
RefreshMouseOverState(mouseInteraction.m_mousePick);
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
AZ::Transform ApplySpace(const AZ::Transform& localTransform, const AZ::Transform& space, const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
AZ::Transform result;
|
||||
result.SetRotation(space.GetRotation() * localTransform.GetRotation());
|
||||
result.SetTranslation(space.TransformPoint(nonUniformScale * localTransform.GetTranslation()));
|
||||
result.SetUniformScale(space.GetUniformScale() * localTransform.GetUniformScale());
|
||||
return result;
|
||||
}
|
||||
|
||||
const AZ::Transform& ManipulatorSpace::GetSpace() const
|
||||
{
|
||||
return m_space;
|
||||
@@ -32,11 +41,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZ::Transform ManipulatorSpace::ApplySpace(const AZ::Transform& localTransform) const
|
||||
{
|
||||
AZ::Transform result;
|
||||
result.SetRotation(m_space.GetRotation() * localTransform.GetRotation());
|
||||
result.SetTranslation(m_space.TransformPoint(m_nonUniformScale * localTransform.GetTranslation()));
|
||||
result.SetUniformScale(m_space.GetUniformScale() * localTransform.GetUniformScale());
|
||||
return result;
|
||||
return AzToolsFramework::ApplySpace(localTransform, m_space, m_nonUniformScale);
|
||||
}
|
||||
|
||||
const AZ::Vector3& ManipulatorSpaceWithLocalPosition::GetLocalPosition() const
|
||||
|
||||
@@ -17,6 +17,8 @@ namespace AZ
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
AZ::Transform ApplySpace(const AZ::Transform& localTransform, const AZ::Transform& space, const AZ::Vector3& nonUniformScale);
|
||||
|
||||
//! Handles location for manipulators which have a global space but no local transformation.
|
||||
class ManipulatorSpace
|
||||
{
|
||||
|
||||
@@ -383,8 +383,8 @@ namespace AzToolsFramework
|
||||
debugDisplay.DrawLine(quadBoundVisual.m_corner1, quadBoundVisual.m_corner2);
|
||||
|
||||
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_axis2Color, m_mouseOverColor).GetAsVector4());
|
||||
debugDisplay.DrawLine(quadBoundVisual.m_corner4, quadBoundVisual.m_corner1);
|
||||
debugDisplay.DrawLine(quadBoundVisual.m_corner2, quadBoundVisual.m_corner3);
|
||||
debugDisplay.DrawLine(quadBoundVisual.m_corner1, quadBoundVisual.m_corner4);
|
||||
|
||||
if (manipulatorState.m_mouseOver)
|
||||
{
|
||||
@@ -738,15 +738,16 @@ namespace AzToolsFramework
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AZStd::unique_ptr<ManipulatorViewQuad> CreateManipulatorViewQuad(
|
||||
const PlanarManipulator& planarManipulator,
|
||||
const AZ::Vector3& axis1,
|
||||
const AZ::Vector3& axis2,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
const AZ::Vector3& offset,
|
||||
const float size)
|
||||
{
|
||||
AZStd::unique_ptr<ManipulatorViewQuad> viewQuad = AZStd::make_unique<ManipulatorViewQuad>();
|
||||
viewQuad->m_axis1 = planarManipulator.GetAxis1();
|
||||
viewQuad->m_axis2 = planarManipulator.GetAxis2();
|
||||
viewQuad->m_axis1 = axis1;
|
||||
viewQuad->m_axis2 = axis2;
|
||||
viewQuad->m_size = size;
|
||||
viewQuad->m_offset = offset;
|
||||
viewQuad->m_axis1Color = axis1Color;
|
||||
|
||||
@@ -382,7 +382,8 @@ namespace AzToolsFramework
|
||||
// Helpers to create various manipulator views.
|
||||
|
||||
AZStd::unique_ptr<ManipulatorViewQuad> CreateManipulatorViewQuad(
|
||||
const PlanarManipulator& planarManipulator,
|
||||
const AZ::Vector3& axis1,
|
||||
const AZ::Vector3& axis2,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
const AZ::Vector3& offset,
|
||||
|
||||
+2
-2
@@ -145,8 +145,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
view->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
ManipulatorState{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() },
|
||||
debugDisplay, cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -202,8 +202,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
view->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
ManipulatorState{ ApplySpace(GetLocalTransform()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() },
|
||||
debugDisplay, cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -90,8 +90,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
view->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay, cameraState,
|
||||
mouseInteraction);
|
||||
ManipulatorState{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -94,8 +94,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_manipulatorView->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
ManipulatorState{ TransformUniformScale(GetSpace()), GetNonUniformScale(), AZ::Vector3::CreateZero(), MouseOver() },
|
||||
debugDisplay, cameraState, mouseInteraction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -166,8 +166,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_manipulatorView->Draw(
|
||||
GetManipulatorManagerId(), managerState, GetManipulatorId(),
|
||||
{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay, cameraState,
|
||||
mouseInteraction);
|
||||
ManipulatorState{ TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalPosition(), MouseOver() }, debugDisplay,
|
||||
cameraState, mouseInteraction);
|
||||
}
|
||||
|
||||
void SurfaceManipulator::InvalidateImpl()
|
||||
|
||||
+58
-22
@@ -19,6 +19,21 @@ namespace AzToolsFramework
|
||||
static const AZ::Color LinearManipulatorZAxisColor = AZ::Color(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
static const AZ::Color SurfaceManipulatorColor = AZ::Color(1.0f, 1.0f, 0.0f, 0.5f);
|
||||
|
||||
static TranslationManipulatorsViewCreateInfo DefaultTranslationManipulatorViewCreateInfo()
|
||||
{
|
||||
TranslationManipulatorsViewCreateInfo createInfo;
|
||||
createInfo.axis1Color = LinearManipulatorXAxisColor;
|
||||
createInfo.axis2Color = LinearManipulatorYAxisColor;
|
||||
createInfo.axis3Color = LinearManipulatorZAxisColor;
|
||||
createInfo.surfaceColor = SurfaceManipulatorColor;
|
||||
createInfo.linearAxisLength = LinearManipulatorAxisLength();
|
||||
createInfo.linearConeLength = LinearManipulatorConeLength();
|
||||
createInfo.linearConeRadius = LinearManipulatorConeRadius();
|
||||
createInfo.planarAxisLength = PlanarManipulatorAxisLength();
|
||||
createInfo.surfaceRadius = SurfaceManipulatorRadius();
|
||||
return createInfo;
|
||||
}
|
||||
|
||||
TranslationManipulators::TranslationManipulators(
|
||||
const Dimensions dimensions, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale)
|
||||
: m_dimensions(dimensions)
|
||||
@@ -231,17 +246,36 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void TranslationManipulators::ConfigureView2d(const TranslationManipulatorsViewCreateInfo& translationManipulatorViewCreateInfo)
|
||||
{
|
||||
ConfigureLinearView(
|
||||
translationManipulatorViewCreateInfo.linearAxisLength, translationManipulatorViewCreateInfo.linearConeLength,
|
||||
translationManipulatorViewCreateInfo.linearConeRadius, translationManipulatorViewCreateInfo.axis1Color,
|
||||
translationManipulatorViewCreateInfo.axis2Color, translationManipulatorViewCreateInfo.axis3Color);
|
||||
ConfigurePlanarView(
|
||||
translationManipulatorViewCreateInfo.planarAxisLength, translationManipulatorViewCreateInfo.linearAxisLength,
|
||||
translationManipulatorViewCreateInfo.linearConeLength, translationManipulatorViewCreateInfo.axis1Color,
|
||||
translationManipulatorViewCreateInfo.axis2Color, translationManipulatorViewCreateInfo.axis3Color);
|
||||
}
|
||||
|
||||
void TranslationManipulators::ConfigureView3d(const TranslationManipulatorsViewCreateInfo& translationManipulatorViewCreateInfo)
|
||||
{
|
||||
ConfigureView2d(translationManipulatorViewCreateInfo);
|
||||
ConfigureSurfaceView(translationManipulatorViewCreateInfo.surfaceRadius, translationManipulatorViewCreateInfo.surfaceColor);
|
||||
}
|
||||
|
||||
void TranslationManipulators::ConfigureLinearView(
|
||||
const float axisLength,
|
||||
const float coneLength,
|
||||
const float coneRadius,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
const AZ::Color& axis3Color /*= AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)*/)
|
||||
{
|
||||
const AZ::Color axesColor[] = { axis1Color, axis2Color, axis3Color };
|
||||
|
||||
const auto configureLinearView =
|
||||
[lineBoundWidth = m_lineBoundWidth, coneLength = LinearManipulatorConeLength(), axisLength,
|
||||
coneRadius = LinearManipulatorConeRadius()](LinearManipulator* linearManipulator, const AZ::Color& color)
|
||||
const auto configureLinearView = [lineBoundWidth = m_lineBoundWidth, coneLength, axisLength,
|
||||
coneRadius](LinearManipulator* linearManipulator, const AZ::Color& color)
|
||||
{
|
||||
const auto lineLength = axisLength - coneLength;
|
||||
|
||||
@@ -259,25 +293,21 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
void TranslationManipulators::ConfigurePlanarView(
|
||||
const float planeSize,
|
||||
const float planarAxisLength,
|
||||
const float linearAxisLength,
|
||||
const float linearConeLength,
|
||||
const AZ::Color& plane1Color,
|
||||
const AZ::Color& plane2Color /*= AZ::Color(0.0f, 1.0f, 0.0f, 0.5f)*/,
|
||||
const AZ::Color& plane3Color /*= AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)*/)
|
||||
{
|
||||
const AZ::Color planesColor[] = { plane1Color, plane2Color, plane3Color };
|
||||
|
||||
const float linearAxisLength = LinearManipulatorAxisLength();
|
||||
const float linearConeLength = LinearManipulatorConeLength();
|
||||
for (size_t manipulatorIndex = 0; manipulatorIndex < m_planarManipulators.size(); ++manipulatorIndex)
|
||||
{
|
||||
const auto& planarManipulator = *m_planarManipulators[manipulatorIndex];
|
||||
const AZStd::shared_ptr<ManipulatorViewQuad> manipulatorView = CreateManipulatorViewQuad(
|
||||
*m_planarManipulators[manipulatorIndex], planesColor[manipulatorIndex], planesColor[(manipulatorIndex + 1) % 3],
|
||||
(planarManipulator.GetAxis1() + planarManipulator.GetAxis2()) *
|
||||
(((linearAxisLength - linearConeLength) * 0.5f) - (planeSize * 0.5f)),
|
||||
planeSize);
|
||||
|
||||
m_planarManipulators[manipulatorIndex]->SetViews(ManipulatorViews{ manipulatorView });
|
||||
m_planarManipulators[manipulatorIndex]->SetViews(ManipulatorViews{ CreateManipulatorViewQuadForPlanarTranslationManipulator(
|
||||
planarManipulator.GetAxis1(), planarManipulator.GetAxis2(), planesColor[manipulatorIndex],
|
||||
planesColor[(manipulatorIndex + 1) % 3], linearAxisLength, linearConeLength, planarAxisLength) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,19 +355,25 @@ namespace AzToolsFramework
|
||||
void ConfigureTranslationManipulatorAppearance3d(TranslationManipulators* translationManipulators)
|
||||
{
|
||||
translationManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
|
||||
translationManipulators->ConfigurePlanarView(
|
||||
PlanarManipulatorAxisLength(), LinearManipulatorXAxisColor, LinearManipulatorYAxisColor, LinearManipulatorZAxisColor);
|
||||
translationManipulators->ConfigureLinearView(
|
||||
LinearManipulatorAxisLength(), LinearManipulatorXAxisColor, LinearManipulatorYAxisColor, LinearManipulatorZAxisColor);
|
||||
translationManipulators->ConfigureSurfaceView(SurfaceManipulatorRadius(), SurfaceManipulatorColor);
|
||||
translationManipulators->ConfigureView3d(DefaultTranslationManipulatorViewCreateInfo());
|
||||
}
|
||||
|
||||
void ConfigureTranslationManipulatorAppearance2d(TranslationManipulators* translationManipulators)
|
||||
{
|
||||
translationManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY());
|
||||
translationManipulators->ConfigurePlanarView(
|
||||
PlanarManipulatorAxisLength(), LinearManipulatorXAxisColor, LinearManipulatorYAxisColor);
|
||||
translationManipulators->ConfigureLinearView(
|
||||
LinearManipulatorAxisLength(), LinearManipulatorXAxisColor, LinearManipulatorYAxisColor);
|
||||
translationManipulators->ConfigureView2d(DefaultTranslationManipulatorViewCreateInfo());
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<ManipulatorViewQuad> CreateManipulatorViewQuadForPlanarTranslationManipulator(
|
||||
const AZ::Vector3& axis1,
|
||||
const AZ::Vector3& axis2,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
const float linearAxisLength,
|
||||
const float linearConeLength,
|
||||
const float planarAxisLength)
|
||||
{
|
||||
const AZ::Vector3 offset = (axis1 + axis2) * (((linearAxisLength - linearConeLength) * 0.5f) - (planarAxisLength * 0.5f));
|
||||
return CreateManipulatorViewQuad(axis1, axis2, axis1Color, axis2Color, offset, planarAxisLength);
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+36
-6
@@ -15,6 +15,20 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
//! Parameters to configure the appearance of the TranslationManipulators view(s).
|
||||
struct TranslationManipulatorsViewCreateInfo
|
||||
{
|
||||
float linearAxisLength;
|
||||
float linearConeLength;
|
||||
float linearConeRadius;
|
||||
float planarAxisLength;
|
||||
float surfaceRadius;
|
||||
AZ::Color axis1Color;
|
||||
AZ::Color axis2Color;
|
||||
AZ::Color axis3Color;
|
||||
AZ::Color surfaceColor;
|
||||
};
|
||||
|
||||
//! TranslationManipulators is an aggregation of 3 linear manipulators, 3 planar manipulators
|
||||
//! and one surface manipulator who share the same transform.
|
||||
class TranslationManipulators : public Manipulators
|
||||
@@ -23,6 +37,9 @@ namespace AzToolsFramework
|
||||
AZ_RTTI(TranslationManipulators, "{D5E49EA2-30E0-42BC-A51D-6A7F87818260}")
|
||||
AZ_CLASS_ALLOCATOR(TranslationManipulators, AZ::SystemAllocator, 0)
|
||||
|
||||
TranslationManipulators(TranslationManipulators&&) = delete;
|
||||
TranslationManipulators& operator=(TranslationManipulators&&) = delete;
|
||||
|
||||
//! How many dimensions does this translation manipulator have.
|
||||
enum class Dimensions
|
||||
{
|
||||
@@ -52,26 +69,31 @@ namespace AzToolsFramework
|
||||
|
||||
void SetAxes(const AZ::Vector3& axis1, const AZ::Vector3& axis2, const AZ::Vector3& axis3 = AZ::Vector3::CreateAxisZ());
|
||||
|
||||
void ConfigureView2d(const TranslationManipulatorsViewCreateInfo& translationManipulatorViewCreateInfo);
|
||||
void ConfigureView3d(const TranslationManipulatorsViewCreateInfo& translationManipulatorViewCreateInfo);
|
||||
|
||||
//! Sets the bound width to use for the line/axis of a linear manipulator.
|
||||
void SetLineBoundWidth(float lineBoundWidth);
|
||||
|
||||
private:
|
||||
void ConfigurePlanarView(
|
||||
float planeSize,
|
||||
float linearAxisLength,
|
||||
float linearConeLength,
|
||||
const AZ::Color& plane1Color,
|
||||
const AZ::Color& plane2Color = AZ::Color(0.0f, 1.0f, 0.0f, 0.5f),
|
||||
const AZ::Color& plane3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
|
||||
|
||||
void ConfigureLinearView(
|
||||
float axisLength,
|
||||
float coneLength,
|
||||
float coneRadius,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
|
||||
|
||||
void ConfigureSurfaceView(float radius, const AZ::Color& color);
|
||||
|
||||
//! Sets the bound width to use for the line/axis of a linear manipulator.
|
||||
void SetLineBoundWidth(float lineBoundWidth);
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(TranslationManipulators)
|
||||
|
||||
// Manipulators
|
||||
void ProcessManipulators(const AZStd::function<void(BaseManipulator*)>&) override;
|
||||
|
||||
@@ -131,4 +153,12 @@ namespace AzToolsFramework
|
||||
void ConfigureTranslationManipulatorAppearance3d(TranslationManipulators* translationManipulators);
|
||||
void ConfigureTranslationManipulatorAppearance2d(TranslationManipulators* translationManipulators);
|
||||
|
||||
AZStd::shared_ptr<ManipulatorViewQuad> CreateManipulatorViewQuadForPlanarTranslationManipulator(
|
||||
const AZ::Vector3& axis1,
|
||||
const AZ::Vector3& axis2,
|
||||
const AZ::Color& axis1Color,
|
||||
const AZ::Color& axis2Color,
|
||||
float linearAxisLength,
|
||||
float linearConeLength,
|
||||
float planarAxisLength);
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -150,6 +150,24 @@ namespace AzToolsFramework
|
||||
return result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success;
|
||||
}
|
||||
|
||||
// some assets may come in from the JSON serialzier with no AssetID, but have an asset hint
|
||||
// this attempts to fix up the assets using the assetHint field
|
||||
void FixUpInvalidAssets(AZ::Data::Asset<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
if (!asset.GetId().IsValid() && !asset.GetHint().empty())
|
||||
{
|
||||
AZ::Data::AssetId assetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, asset.GetHint().c_str(),
|
||||
AZ::Data::s_invalidAssetType, false);
|
||||
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
asset.Create(assetId, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -164,13 +182,17 @@ namespace AzToolsFramework
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
|
||||
auto tracker = AZ::Data::SerializedAssetTracker{};
|
||||
tracker.SetAssetFixUp(&FixUpInvalidAssets);
|
||||
|
||||
AZ::JsonDeserializerSettings settings;
|
||||
// The InstanceEntityIdMapper is registered twice because it's used in several places during deserialization where one is
|
||||
// specific for the InstanceEntityIdMapper and once for the generic JsonEntityIdMapper. Because the Json Serializer's meta
|
||||
// data has strict typing and doesn't look for inheritance both have to be explicitly added so they're found both locations.
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
settings.m_metadata.Add(&entityIdMapper);
|
||||
|
||||
settings.m_metadata.Add(tracker);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
AZ::JsonSerialization::Load(instance, prefabDom, settings);
|
||||
|
||||
@@ -203,13 +225,16 @@ namespace AzToolsFramework
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
|
||||
auto tracker = AZ::Data::SerializedAssetTracker{};
|
||||
tracker.SetAssetFixUp(&FixUpInvalidAssets);
|
||||
|
||||
AZ::JsonDeserializerSettings settings;
|
||||
// The InstanceEntityIdMapper is registered twice because it's used in several places during deserialization where one is
|
||||
// specific for the InstanceEntityIdMapper and once for the generic JsonEntityIdMapper. Because the Json Serializer's meta
|
||||
// data has strict typing and doesn't look for inheritance both have to be explicitly added so they're found both locations.
|
||||
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
|
||||
settings.m_metadata.Add(&entityIdMapper);
|
||||
settings.m_metadata.Create<AZ::Data::SerializedAssetTracker>();
|
||||
settings.m_metadata.Add(tracker);
|
||||
|
||||
AZ::JsonSerializationResult::ResultCode result =
|
||||
AZ::JsonSerialization::Load(instance, prefabDom, settings);
|
||||
@@ -246,29 +271,8 @@ namespace AzToolsFramework
|
||||
entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random);
|
||||
}
|
||||
|
||||
// some assets may come in from the JSON serialzier with no AssetID, but have an asset hint
|
||||
// this attempts to fix up the assets using the assetHint field
|
||||
auto fixUpInvalidAssets = [](AZ::Data::Asset<AZ::Data::AssetData>& asset)
|
||||
{
|
||||
if (!asset.GetId().IsValid() && !asset.GetHint().empty())
|
||||
{
|
||||
AZ::Data::AssetId assetId;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
assetId,
|
||||
&AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath,
|
||||
asset.GetHint().c_str(),
|
||||
AZ::Data::s_invalidAssetType,
|
||||
false);
|
||||
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
asset.Create(assetId, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto tracker = AZ::Data::SerializedAssetTracker{};
|
||||
tracker.SetAssetFixUp(fixUpInvalidAssets);
|
||||
tracker.SetAssetFixUp(&FixUpInvalidAssets);
|
||||
|
||||
AZ::JsonDeserializerSettings settings;
|
||||
// The InstanceEntityIdMapper is registered twice because it's used in several places during deserialization where one is
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AzToolsFramework/ContainerEntity/ContainerEntityInterface.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/Instance.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusNotificationBus.h>
|
||||
@@ -74,6 +75,13 @@ namespace AzToolsFramework::Prefab
|
||||
"Prefab - PrefabFocusHandler - "
|
||||
"Focus Mode Interface could not be found. "
|
||||
"Check that it is being correctly initialized.");
|
||||
|
||||
m_readOnlyEntityQueryInterface = AZ::Interface<ReadOnlyEntityQueryInterface>::Get();
|
||||
AZ_Assert(
|
||||
m_readOnlyEntityQueryInterface,
|
||||
"Prefab - PrefabFocusHandler - "
|
||||
"ReadOnly Entity Query Interface could not be found. "
|
||||
"Check that it is being correctly initialized.");
|
||||
}
|
||||
|
||||
PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId)
|
||||
@@ -186,6 +194,8 @@ namespace AzToolsFramework::Prefab
|
||||
// Close all container entities in the old path.
|
||||
CloseInstanceContainers(m_instanceFocusHierarchy);
|
||||
|
||||
AZ::EntityId previousContainerEntityId = m_focusedInstanceContainerEntityId;
|
||||
|
||||
// Do not store the container for the root instance, use an invalid EntityId instead.
|
||||
m_focusedInstanceContainerEntityId = focusedInstance->get().GetParentInstance().has_value() ? focusedInstance->get().GetContainerEntityId() : AZ::EntityId();
|
||||
m_focusedTemplateId = focusedInstance->get().GetTemplateId();
|
||||
@@ -201,6 +211,12 @@ namespace AzToolsFramework::Prefab
|
||||
m_focusModeInterface->SetFocusRoot(containerEntityId);
|
||||
}
|
||||
|
||||
// Refresh the read-only cache, if the interface is initialized.
|
||||
if (m_readOnlyEntityQueryInterface)
|
||||
{
|
||||
m_readOnlyEntityQueryInterface->RefreshReadOnlyState({ previousContainerEntityId, m_focusedInstanceContainerEntityId });
|
||||
}
|
||||
|
||||
// Refresh path variables.
|
||||
RefreshInstanceFocusList();
|
||||
RefreshInstanceFocusPath();
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
class ContainerEntityInterface;
|
||||
class FocusModeInterface;
|
||||
class ReadOnlyEntityQueryInterface;
|
||||
}
|
||||
|
||||
namespace AzToolsFramework::Prefab
|
||||
@@ -93,6 +94,7 @@ namespace AzToolsFramework::Prefab
|
||||
ContainerEntityInterface* m_containerEntityInterface = nullptr;
|
||||
FocusModeInterface* m_focusModeInterface = nullptr;
|
||||
InstanceEntityMapperInterface* m_instanceEntityMapperInterface = nullptr;
|
||||
ReadOnlyEntityQueryInterface* m_readOnlyEntityQueryInterface = nullptr;
|
||||
};
|
||||
|
||||
} // namespace AzToolsFramework::Prefab
|
||||
|
||||
@@ -918,6 +918,18 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool PrefabPublicHandler::IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const
|
||||
{
|
||||
if (InstanceOptionalReference instanceReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
instanceReference.has_value())
|
||||
{
|
||||
TemplateReference templateReference = m_prefabSystemComponentInterface->FindTemplate(instanceReference->get().GetTemplateId());
|
||||
return (templateReference.has_value()) && (templateReference->get().IsProcedural());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PrefabPublicHandler::IsInstanceContainerEntity(AZ::EntityId entityId) const
|
||||
{
|
||||
InstanceOptionalReference owningInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace AzToolsFramework
|
||||
|
||||
PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) override;
|
||||
|
||||
bool IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const override;
|
||||
bool IsInstanceContainerEntity(AZ::EntityId entityId) const override;
|
||||
bool IsLevelInstanceContainerEntity(AZ::EntityId entityId) const override;
|
||||
AZ::EntityId GetInstanceContainerEntityId(AZ::EntityId entityId) const override;
|
||||
|
||||
@@ -101,6 +101,13 @@ namespace AzToolsFramework
|
||||
*/
|
||||
virtual PrefabOperationResult GenerateUndoNodesForEntityChangeAndUpdateCache(
|
||||
AZ::EntityId entityId, UndoSystem::URSequencePoint* parentUndoBatch) = 0;
|
||||
|
||||
/**
|
||||
* Detects if an entity is owned by a procedural prefab.
|
||||
* @param entityId The entity to query.
|
||||
* @return True if the entity is owned by a procedural prefab instance, false otherwise.
|
||||
*/
|
||||
virtual bool IsOwnedByProceduralPrefabInstance(AZ::EntityId entityId) const = 0;
|
||||
|
||||
/**
|
||||
* Detects if an entity is the container entity for its owning prefab instance.
|
||||
|
||||
+6
-1
@@ -8,10 +8,12 @@
|
||||
|
||||
#include <API/ToolsApplicationAPI.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
|
||||
#include <Prefab/PrefabSystemComponentInterface.h>
|
||||
#include <Prefab/PrefabSystemScriptingHandler.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <Prefab/EditorPrefabComponent.h>
|
||||
#include <ToolsComponents/TransformComponent.h>
|
||||
|
||||
@@ -72,6 +74,9 @@ namespace AzToolsFramework::Prefab
|
||||
entities, commonRoot, &topLevelEntities);
|
||||
|
||||
auto containerEntity = AZStd::make_unique<AZ::Entity>();
|
||||
containerEntity->CreateComponent<Components::TransformComponent>();
|
||||
containerEntity->CreateComponent<Components::EditorLockComponent>();
|
||||
containerEntity->CreateComponent<Components::EditorVisibilityComponent>();
|
||||
containerEntity->CreateComponent<Prefab::EditorPrefabComponent>();
|
||||
|
||||
for (AZ::Entity* entity : topLevelEntities)
|
||||
|
||||
+11
-9
@@ -860,18 +860,20 @@ namespace AzToolsFramework
|
||||
return;
|
||||
}
|
||||
|
||||
bool isDuringUndoRedo = false;
|
||||
EBUS_EVENT_RESULT(isDuringUndoRedo, AzToolsFramework::ToolsApplicationRequests::Bus, IsDuringUndoRedo);
|
||||
if (!isDuringUndoRedo)
|
||||
bool suppressTransformChangedEvent = m_suppressTransformChangedEvent;
|
||||
// temporarily disable calling OnTransformChanged, because CheckApplyCachedWorldTransform is not guaranteed
|
||||
// to call it when m_cachedWorldTransform is identity. We send it manually later.
|
||||
m_suppressTransformChangedEvent = false;
|
||||
// When parent comes online, compute local TM from world TM.
|
||||
CheckApplyCachedWorldTransform(parentTransform->GetWorldTM());
|
||||
if (!m_initialized)
|
||||
{
|
||||
// When parent comes online, compute local TM from world TM.
|
||||
CheckApplyCachedWorldTransform(parentTransform->GetWorldTM());
|
||||
}
|
||||
else
|
||||
{
|
||||
// During undo operations, just apply our local TM.
|
||||
m_initialized = true;
|
||||
// If this is the first time this entity is being activated, manually compute OnTransformChanged
|
||||
// this can occur when either the entity first created or undo/redo command is performed
|
||||
OnTransformChanged(AZ::Transform::Identity(), parentTransform->GetWorldTM());
|
||||
}
|
||||
m_suppressTransformChangedEvent = suppressTransformChangedEvent;
|
||||
|
||||
auto& parentChildIds = GetParentTransformComponent()->m_childrenEntityIds;
|
||||
if (parentChildIds.end() == AZStd::find(parentChildIds.begin(), parentChildIds.end(), GetEntityId()))
|
||||
|
||||
@@ -242,6 +242,9 @@ namespace AzToolsFramework
|
||||
// element is used rather than a data element.
|
||||
bool m_addNonUniformScaleButton = false;
|
||||
|
||||
// Used to check whether entity was just created vs manually reactivated. Set true after OnEntityActivated is called the first time.
|
||||
bool m_initialized = false;
|
||||
|
||||
// Deprecated
|
||||
AZ::InterpolationMode m_interpolatePosition;
|
||||
AZ::InterpolationMode m_interpolateRotation;
|
||||
|
||||
+31
-6
@@ -47,6 +47,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityInfoBus.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
|
||||
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentAssetMimeDataContainer.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
@@ -313,7 +314,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (isEditorOnly)
|
||||
{
|
||||
return QIcon(QString(":/Icons/Entity_Editor_Only.svg"));
|
||||
return QIcon(QString(":/Entity/entity_editoronly.svg"));
|
||||
}
|
||||
|
||||
AZ::Entity* entity = nullptr;
|
||||
@@ -322,10 +323,10 @@ namespace AzToolsFramework
|
||||
|
||||
if (!isInitiallyActive)
|
||||
{
|
||||
return QIcon(QString(":/Icons/Entity_Not_Active.svg"));
|
||||
return QIcon(QString(":/Entity/entity_notactive.svg"));
|
||||
}
|
||||
|
||||
return QIcon(QString(":/Icons/Entity.svg"));
|
||||
return QIcon(QString(":/Entity/entity.svg"));
|
||||
}
|
||||
|
||||
QVariant EntityOutlinerListModel::GetEntityTooltip(const AZ::EntityId& id) const
|
||||
@@ -1994,9 +1995,13 @@ namespace AzToolsFramework
|
||||
, m_lockCheckBoxes(parent, "Lock", EntityOutlinerListModel::PartiallyLockedRole, EntityOutlinerListModel::LockedAncestorRole)
|
||||
{
|
||||
m_editorEntityFrameworkInterface = AZ::Interface<AzToolsFramework::EditorEntityUiInterface>::Get();
|
||||
|
||||
AZ_Assert((m_editorEntityFrameworkInterface != nullptr),
|
||||
"EntityOutlinerItemDelegate requires a EditorEntityFrameworkInterface instance on Construction.");
|
||||
|
||||
m_readOnlyEntityPublicInterface = AZ::Interface<AzToolsFramework::ReadOnlyEntityPublicInterface>::Get();
|
||||
AZ_Assert(
|
||||
(m_readOnlyEntityPublicInterface != nullptr),
|
||||
"EntityOutlinerItemDelegate requires a ReadOnlyEntityPublicInterface instance on Construction.");
|
||||
}
|
||||
|
||||
EntityOutlinerItemDelegate::CheckboxGroup::CheckboxGroup(QWidget* parent, AZStd::string prefix,
|
||||
@@ -2108,6 +2113,12 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
PaintEntityNameAsRichText(painter, customOption, index);
|
||||
|
||||
// Paint Read-Only icon if necessary
|
||||
if (m_readOnlyEntityPublicInterface->IsReadOnly(entityId))
|
||||
{
|
||||
PaintReadOnlyIcon(painter, option, index);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -2166,10 +2177,10 @@ namespace AzToolsFramework
|
||||
|
||||
backgroundPath.addRect(backgroundRect);
|
||||
|
||||
QColor backgroundColor = m_hoverColor;
|
||||
QColor backgroundColor = s_hoverColor;
|
||||
if (isSelected)
|
||||
{
|
||||
backgroundColor = m_selectedColor;
|
||||
backgroundColor = s_selectedColor;
|
||||
}
|
||||
|
||||
painter->fillPath(backgroundPath, backgroundColor);
|
||||
@@ -2336,6 +2347,20 @@ namespace AzToolsFramework
|
||||
EntityOutlinerListModel::s_paintingName = false;
|
||||
}
|
||||
|
||||
void EntityOutlinerItemDelegate::PaintReadOnlyIcon(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const
|
||||
{
|
||||
// Build the rect that will be used to paint the icon
|
||||
QRect readOnlyRect = QRect(option.rect.topLeft() + s_readOnlyOffset, QSize(s_readOnlyRadius * 2, s_readOnlyRadius * 2));
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(s_readOnlyBackgroundColor);
|
||||
painter->drawEllipse(readOnlyRect.center(), s_readOnlyRadius, s_readOnlyRadius);
|
||||
s_readOnlyIcon.paint(painter, readOnlyRect);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QSize EntityOutlinerItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const
|
||||
{
|
||||
// Get the height of a tall character...
|
||||
|
||||
+13
-2
@@ -38,6 +38,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
class EditorEntityUiInterface;
|
||||
class FocusModeInterface;
|
||||
class ReadOnlyEntityPublicInterface;
|
||||
|
||||
namespace EntityOutliner
|
||||
{
|
||||
@@ -344,6 +345,9 @@ namespace AzToolsFramework
|
||||
// Paint the entity name using rich text
|
||||
void PaintEntityNameAsRichText(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
// Paint the read-only icon on the entity
|
||||
void PaintReadOnlyIcon(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
|
||||
struct CheckboxGroup
|
||||
{
|
||||
EntityOutlinerCheckBox m_default;
|
||||
@@ -372,10 +376,17 @@ namespace AzToolsFramework
|
||||
// this is a cache, and is hence mutable
|
||||
mutable QRect m_cachedBoundingRectOfTallCharacter;
|
||||
|
||||
const QColor m_selectedColor = QColor(255, 255, 255, 45);
|
||||
const QColor m_hoverColor = QColor(255, 255, 255, 30);
|
||||
inline static const QColor s_selectedColor = QColor(255, 255, 255, 45);
|
||||
inline static const QColor s_hoverColor = QColor(255, 255, 255, 30);
|
||||
|
||||
inline static const QColor s_readOnlyBackgroundColor = QColor("#444444");
|
||||
inline static const QPoint s_readOnlyOffset = QPoint(10, 10);
|
||||
inline static const int s_readOnlyRadius = 6;
|
||||
|
||||
QIcon s_readOnlyIcon = QIcon(QString(":/Entity/readonly.svg"));
|
||||
|
||||
EditorEntityUiInterface* m_editorEntityFrameworkInterface = nullptr;
|
||||
ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+11
-7
@@ -27,6 +27,7 @@
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceEntityMapperInterface.h>
|
||||
#include <AzToolsFramework/Prefab/Instance/InstanceToTemplateInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
@@ -565,9 +566,7 @@ namespace AzToolsFramework
|
||||
EditorRequestBus::BroadcastResult(position, &EditorRequestBus::Events::GetWorldPositionAtViewportCenter);
|
||||
}
|
||||
|
||||
// Instantiating from context menu always puts the instance at the root level
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(prefabFilePath, parentId, position);
|
||||
|
||||
if (!createPrefabOutcome.IsSuccess())
|
||||
{
|
||||
WarnUserOfError("Prefab Instantiation Error",createPrefabOutcome.GetError());
|
||||
@@ -594,15 +593,13 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
// otherwise return since it needs to be inside an authored prefab
|
||||
return;
|
||||
EditorRequestBus::BroadcastResult(position, &EditorRequestBus::Events::GetWorldPositionAtViewportCenter);
|
||||
}
|
||||
|
||||
// Instantiating from context menu always puts the instance at the root level
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(prefabAssetPath, parentId, position);
|
||||
if (!createPrefabOutcome.IsSuccess())
|
||||
{
|
||||
WarnUserOfError("Prefab Instantiation Error", createPrefabOutcome.GetError());
|
||||
WarnUserOfError("Procedural Prefab Instantiation Error", createPrefabOutcome.GetError());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1268,7 +1265,14 @@ namespace AzToolsFramework
|
||||
}
|
||||
else
|
||||
{
|
||||
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
|
||||
if (s_prefabPublicInterface->IsOwnedByProceduralPrefabInstance(entityId))
|
||||
{
|
||||
s_editorEntityUiInterface->RegisterEntity(entityId, m_proceduralPrefabUiHandler.GetHandlerId());
|
||||
}
|
||||
else
|
||||
{
|
||||
s_editorEntityUiInterface->RegisterEntity(entityId, m_prefabUiHandler.GetHandlerId());
|
||||
}
|
||||
|
||||
// Register entity as a container
|
||||
s_containerEntityInterface->RegisterEntityAsContainer(entityId);
|
||||
|
||||
+10
-3
@@ -18,10 +18,11 @@
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/LevelRootUiHandler.h>
|
||||
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationBus.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabIntegrationInterface.h>
|
||||
#include <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
|
||||
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h>
|
||||
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabUiHandler.h>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/Card.h>
|
||||
|
||||
@@ -92,12 +93,18 @@ namespace AzToolsFramework
|
||||
void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override;
|
||||
|
||||
private:
|
||||
// Used to handle the UI for the level root
|
||||
// Used to handle the UI for the level root.
|
||||
LevelRootUiHandler m_levelRootUiHandler;
|
||||
|
||||
// Used to handle the UI for prefab entities
|
||||
// Used to handle the UI for prefab entities.
|
||||
PrefabUiHandler m_prefabUiHandler;
|
||||
|
||||
// Used to handle the UI for procedural prefab entities.
|
||||
ProceduralPrefabUiHandler m_proceduralPrefabUiHandler;
|
||||
|
||||
// Ensures entities owned by procedural prefab instances are marked as read-only correctly.
|
||||
ProceduralPrefabReadOnlyHandler m_proceduralPrefabReadOnlyHandler;
|
||||
|
||||
// Context menu item handlers
|
||||
static void ContextMenu_CreatePrefab(AzToolsFramework::EntityIdList selectedEntities);
|
||||
static void ContextMenu_InstantiatePrefab();
|
||||
|
||||
@@ -23,17 +23,6 @@ namespace AzToolsFramework
|
||||
{
|
||||
AzFramework::EntityContextId PrefabUiHandler::s_editorEntityContextId = AzFramework::EntityContextId::CreateNull();
|
||||
|
||||
const QColor PrefabUiHandler::m_backgroundColor = QColor("#444444");
|
||||
const QColor PrefabUiHandler::m_backgroundHoverColor = QColor("#5A5A5A");
|
||||
const QColor PrefabUiHandler::m_backgroundSelectedColor = QColor("#656565");
|
||||
const QColor PrefabUiHandler::m_prefabCapsuleColor = QColor("#1E252F");
|
||||
const QColor PrefabUiHandler::m_prefabCapsuleDisabledColor = QColor("#35383C");
|
||||
const QColor PrefabUiHandler::m_prefabCapsuleEditColor = QColor("#4A90E2");
|
||||
const QString PrefabUiHandler::m_prefabIconPath = QString(":/Entity/prefab.svg");
|
||||
const QString PrefabUiHandler::m_prefabEditIconPath = QString(":/Entity/prefab_edit.svg");
|
||||
const QString PrefabUiHandler::m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open.svg");
|
||||
const QString PrefabUiHandler::m_prefabEditCloseIconPath = QString(":/Entity/prefab_edit_close.svg");
|
||||
|
||||
PrefabUiHandler::PrefabUiHandler()
|
||||
{
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace AzToolsFramework
|
||||
void OnOutlinerItemCollapse(const QModelIndex& index) const override;
|
||||
bool OnEntityDoubleClick(AZ::EntityId entityId) const override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
|
||||
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
|
||||
@@ -56,17 +56,17 @@ namespace AzToolsFramework
|
||||
|
||||
static AzFramework::EntityContextId s_editorEntityContextId;
|
||||
|
||||
static constexpr int m_prefabCapsuleRadius = 6;
|
||||
static constexpr int m_prefabBorderThickness = 2;
|
||||
static const QColor m_backgroundColor;
|
||||
static const QColor m_backgroundHoverColor;
|
||||
static const QColor m_backgroundSelectedColor;
|
||||
static const QColor m_prefabCapsuleColor;
|
||||
static const QColor m_prefabCapsuleDisabledColor;
|
||||
static const QColor m_prefabCapsuleEditColor;
|
||||
static const QString m_prefabIconPath;
|
||||
static const QString m_prefabEditIconPath;
|
||||
static const QString m_prefabEditOpenIconPath;
|
||||
static const QString m_prefabEditCloseIconPath;
|
||||
int m_prefabCapsuleRadius = 6;
|
||||
int m_prefabBorderThickness = 2;
|
||||
QColor m_backgroundColor = QColor("#444444");
|
||||
QColor m_backgroundHoverColor = QColor("#5A5A5A");
|
||||
QColor m_backgroundSelectedColor = QColor("#656565");
|
||||
QColor m_prefabCapsuleColor = QColor("#1E252F");
|
||||
QColor m_prefabCapsuleDisabledColor = QColor("#35383C");
|
||||
QColor m_prefabCapsuleEditColor = QColor("#4A90E2");
|
||||
QString m_prefabIconPath = QString(":/Entity/prefab.svg");
|
||||
QString m_prefabEditIconPath = QString(":/Entity/prefab_edit.svg");
|
||||
QString m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open.svg");
|
||||
QString m_prefabEditCloseIconPath = QString(":/Entity/prefab_edit_close.svg");
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h>
|
||||
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
ProceduralPrefabReadOnlyHandler::ProceduralPrefabReadOnlyHandler()
|
||||
{
|
||||
m_prefabPublicInterface = AZ::Interface<PrefabPublicInterface>::Get();
|
||||
AZ_Assert(
|
||||
m_prefabPublicInterface != nullptr,
|
||||
"ProceduralPrefabReadOnlyHandler requires a PrefabPublicInterface instance on Initialize.");
|
||||
|
||||
m_prefabFocusPublicInterface = AZ::Interface<PrefabFocusPublicInterface>::Get();
|
||||
AZ_Assert(
|
||||
m_prefabFocusPublicInterface != nullptr,
|
||||
"ProceduralPrefabReadOnlyHandler requires a PrefabFocusPublicInterface instance on Initialize.");
|
||||
|
||||
AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
|
||||
EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
|
||||
|
||||
ReadOnlyEntityQueryRequestBus::Handler::BusConnect(editorEntityContextId);
|
||||
|
||||
// Refresh the whole read-only cache
|
||||
if (auto readOnlyEntityQueryInterface = AZ::Interface<ReadOnlyEntityQueryInterface>::Get())
|
||||
{
|
||||
readOnlyEntityQueryInterface->RefreshReadOnlyStateForAllEntities();
|
||||
}
|
||||
}
|
||||
|
||||
ProceduralPrefabReadOnlyHandler ::~ProceduralPrefabReadOnlyHandler()
|
||||
{
|
||||
ReadOnlyEntityQueryRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void ProceduralPrefabReadOnlyHandler::IsReadOnly(const AZ::EntityId& entityId, bool& isReadOnly)
|
||||
{
|
||||
if(m_prefabPublicInterface->IsOwnedByProceduralPrefabInstance(entityId))
|
||||
{
|
||||
// All entities nested inside a procedural prefabs should always be marked as read-only.
|
||||
if (!m_prefabPublicInterface->IsInstanceContainerEntity(entityId))
|
||||
{
|
||||
isReadOnly = true;
|
||||
}
|
||||
|
||||
// The container entity of a procedural prefab should only be marked as read-only when the prefab is being edited.
|
||||
if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId))
|
||||
{
|
||||
isReadOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Prefab
|
||||
} // namespace AzToolsFramework
|
||||
+43
@@ -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 <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityBus.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabFocusPublicInterface;
|
||||
class PrefabPublicInterface;
|
||||
|
||||
//! Ensures entities in a procedural prefab are correctly reported as read-only.
|
||||
class ProceduralPrefabReadOnlyHandler
|
||||
: public ReadOnlyEntityQueryRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ProceduralPrefabReadOnlyHandler, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(AzToolsFramework::ProceduralPrefabReadOnlyHandler, "{A2D72461-8CA3-45EE-81D2-4976BC0B6AE9}");
|
||||
|
||||
ProceduralPrefabReadOnlyHandler();
|
||||
~ProceduralPrefabReadOnlyHandler() override;
|
||||
|
||||
// ReadOnlyEntityQueryRequestBus overrides ...
|
||||
void IsReadOnly(const AZ::EntityId& entityId, bool& isReadOnly) override;
|
||||
|
||||
private:
|
||||
PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr;
|
||||
};
|
||||
|
||||
} // namespace Prefab
|
||||
} // namespace AzToolsFramework
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzToolsFramework/UI/Prefab/Procedural/ProceduralPrefabUiHandler.h>
|
||||
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
ProceduralPrefabUiHandler::ProceduralPrefabUiHandler()
|
||||
{
|
||||
m_prefabCapsuleColor = QColor("#361561");
|
||||
m_prefabCapsuleDisabledColor = QColor("#4B3455");
|
||||
m_prefabCapsuleEditColor = QColor("#361561");
|
||||
m_prefabIconPath = QString(":/Entity/prefab_edit.svg");
|
||||
m_prefabEditOpenIconPath = QString(":/Entity/prefab_edit_open_readonly.svg");
|
||||
}
|
||||
|
||||
QString ProceduralPrefabUiHandler::GenerateItemTooltip(AZ::EntityId entityId) const
|
||||
{
|
||||
if (AZ::IO::Path path = m_prefabPublicInterface->GetOwningInstancePrefabPath(entityId); !path.empty())
|
||||
{
|
||||
return QObject::tr("Double click to inspect.\n%1").arg(path.Native().data());
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
+36
@@ -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 <AzToolsFramework/UI/Prefab/PrefabUiHandler.h>
|
||||
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace Prefab
|
||||
{
|
||||
class PrefabFocusPublicInterface;
|
||||
class PrefabPublicInterface;
|
||||
};
|
||||
|
||||
//! Implements the Editor UI for Procedural Prefabs.
|
||||
class ProceduralPrefabUiHandler
|
||||
: public PrefabUiHandler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(ProceduralPrefabUiHandler, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(AzToolsFramework::ProceduralPrefabUiHandler, "{3A3DF9FF-9C2E-4439-B7B4-72173B5A3502}", PrefabUiHandler);
|
||||
|
||||
ProceduralPrefabUiHandler();
|
||||
~ProceduralPrefabUiHandler() override = default;
|
||||
|
||||
QString GenerateItemTooltip(AZ::EntityId entityId) const override;
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
+52
-6
@@ -45,6 +45,7 @@ AZ_POP_DISABLE_WARNING
|
||||
#include <AzToolsFramework/AssetBrowser/EBusFindAssetTypeByName.h>
|
||||
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabFocusPublicInterface.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Slice/SliceDataFlagsCommand.h>
|
||||
@@ -497,6 +498,9 @@ namespace AzToolsFramework
|
||||
m_prefabPublicInterface = AZ::Interface<Prefab::PrefabPublicInterface>::Get();
|
||||
AZ_Assert(m_prefabPublicInterface != nullptr, "EntityPropertyEditor requires a PrefabPublicInterface instance on Initialize.");
|
||||
|
||||
m_readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get();
|
||||
AZ_Assert(m_readOnlyEntityPublicInterface != nullptr, "EntityPropertyEditor requires a ReadOnlyEntityPublicInterface instance on Initialize.");
|
||||
|
||||
setObjectName("EntityPropertyEditor");
|
||||
setAcceptDrops(true);
|
||||
|
||||
@@ -535,10 +539,6 @@ namespace AzToolsFramework
|
||||
model->setItem(row, 0, m_comboItems[row]);
|
||||
}
|
||||
m_gui->m_statusComboBox->setModel(model);
|
||||
m_gui->m_statusComboBox->setStyleSheet("QComboBox {border: 0px; border-radius:3px; background-color:#555555; color:white}"
|
||||
"QComboBox:on {background-color:#e9e9e9; color:black; border:0px}"
|
||||
"QComboBox::down-arrow:on {image: url(:/stylesheet/img/dropdowns/black_down_arrow.png)}"
|
||||
"QComboBox::drop-down {border-radius: 3p}");
|
||||
AzQtComponents::ComboBox::addCustomCheckStateStyle(m_gui->m_statusComboBox);
|
||||
EnableEditor(true);
|
||||
m_sceneIsNew = true;
|
||||
@@ -565,6 +565,12 @@ namespace AzToolsFramework
|
||||
AZ::EntitySystemBus::Handler::BusConnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusConnect();
|
||||
EditorWindowUIRequestBus::Handler::BusConnect();
|
||||
|
||||
AzFramework::EntityContextId editorEntityContextId = AzFramework::EntityContextId::CreateNull();
|
||||
EditorEntityContextRequestBus::BroadcastResult(
|
||||
editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId);
|
||||
ReadOnlyEntityPublicNotificationBus::Handler::BusConnect(editorEntityContextId);
|
||||
|
||||
m_spacer = nullptr;
|
||||
|
||||
m_emptyIcon = QIcon();
|
||||
@@ -614,6 +620,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
qApp->removeEventFilter(this);
|
||||
|
||||
ReadOnlyEntityPublicNotificationBus::Handler::BusDisconnect();
|
||||
EditorWindowUIRequestBus::Handler::BusDisconnect();
|
||||
EntityPropertyEditorRequestBus::Handler::BusDisconnect();
|
||||
ToolsApplicationEvents::Bus::Handler::BusDisconnect();
|
||||
@@ -973,7 +980,7 @@ namespace AzToolsFramework
|
||||
m_gui->m_entityDetailsLabel->setVisible(false);
|
||||
|
||||
// If we're in edit mode, make the name field editable.
|
||||
m_gui->m_entityNameEditor->setReadOnly(!m_gui->m_componentListContents->isEnabled());
|
||||
m_gui->m_entityNameEditor->setReadOnly(!m_gui->m_componentListContents->isEnabled() || m_selectionContainsReadOnlyEntity);
|
||||
|
||||
// get the name of the entity.
|
||||
auto entity = GetSelectedEntityById(entityId);
|
||||
@@ -1062,6 +1069,12 @@ namespace AzToolsFramework
|
||||
|
||||
bool EntityPropertyEditor::CanAddComponentsToSelection(const SelectionEntityTypeInfo& selectionEntityTypeInfo) const
|
||||
{
|
||||
if (m_selectionContainsReadOnlyEntity)
|
||||
{
|
||||
// Can't add components if there is a read only entity in the selection
|
||||
return false;
|
||||
}
|
||||
|
||||
if (selectionEntityTypeInfo == SelectionEntityTypeInfo::Mixed ||
|
||||
selectionEntityTypeInfo == SelectionEntityTypeInfo::None)
|
||||
{
|
||||
@@ -1126,6 +1139,17 @@ namespace AzToolsFramework
|
||||
m_selectedEntityIds.clear();
|
||||
GetSelectedEntities(m_selectedEntityIds);
|
||||
|
||||
// Check if any of the selected entities are marked as read only
|
||||
m_selectionContainsReadOnlyEntity = false;
|
||||
for (const auto& entityId : m_selectedEntityIds)
|
||||
{
|
||||
if (m_readOnlyEntityPublicInterface->IsReadOnly(entityId))
|
||||
{
|
||||
m_selectionContainsReadOnlyEntity = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SourceControlFileInfo scFileInfo;
|
||||
ToolsApplicationRequests::Bus::BroadcastResult(scFileInfo, &ToolsApplicationRequests::GetSceneSourceControlInfo);
|
||||
|
||||
@@ -1681,6 +1705,12 @@ namespace AzToolsFramework
|
||||
componentEditor->UpdateExpandability();
|
||||
componentEditor->InvalidateAll(!componentInFilter ? m_filterString.c_str() : nullptr);
|
||||
|
||||
// If we are in read only mode, then show the components as disabled
|
||||
if (m_selectionContainsReadOnlyEntity)
|
||||
{
|
||||
componentEditor->mockDisabledState(true);
|
||||
}
|
||||
|
||||
if (!componentEditor->GetPropertyEditor()->HasFilteredOutNodes() || componentEditor->GetPropertyEditor()->HasVisibleNodes())
|
||||
{
|
||||
for (AZ::Component* componentInstance : componentInstances)
|
||||
@@ -3077,6 +3107,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
m_gui->m_statusComboBox->setDisabled(m_selectionContainsReadOnlyEntity);
|
||||
m_gui->m_statusComboBox->setVisible(!m_isSystemEntityEditor && !m_isLevelEntityEditor);
|
||||
m_gui->m_statusComboBox->style()->unpolish(m_gui->m_statusComboBox);
|
||||
m_gui->m_statusComboBox->style()->polish(m_gui->m_statusComboBox);
|
||||
@@ -3304,7 +3335,8 @@ namespace AzToolsFramework
|
||||
const auto& componentsToEdit = GetSelectedComponents();
|
||||
|
||||
const bool hasComponents = !m_selectedEntityIds.empty() && !componentsToEdit.empty();
|
||||
const bool allowRemove = hasComponents && AreComponentsRemovable(componentsToEdit);
|
||||
// Don't allow components to be removed/cut/enabled/disabled if read only
|
||||
const bool allowRemove = hasComponents && AreComponentsRemovable(componentsToEdit) && !m_selectionContainsReadOnlyEntity;
|
||||
const bool allowCopy = hasComponents && AreComponentsCopyable(componentsToEdit);
|
||||
|
||||
m_actionToDeleteComponents->setEnabled(allowRemove);
|
||||
@@ -3366,6 +3398,12 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_selectionContainsReadOnlyEntity)
|
||||
{
|
||||
// Can't paste components if there is a read only entity in the selection
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab component data from clipboard, if exists
|
||||
const QMimeData* mimeData = ComponentMimeData::GetComponentMimeDataFromClipboard();
|
||||
|
||||
@@ -5727,6 +5765,14 @@ namespace AzToolsFramework
|
||||
SaveComponentEditorState();
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::OnReadOnlyEntityStatusChanged(const AZ::EntityId& entityId, [[maybe_unused]] bool readOnly)
|
||||
{
|
||||
if (IsEntitySelected(entityId))
|
||||
{
|
||||
UpdateContents();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityPropertyEditor::OnEditorModeActivated(
|
||||
[[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode)
|
||||
{
|
||||
|
||||
+9
@@ -29,6 +29,7 @@
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/ComponentMimeData.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorInspectorComponentBus.h>
|
||||
#include <AzQtComponents/Components/O3DEStylesheet.h>
|
||||
@@ -62,6 +63,7 @@ namespace AzToolsFramework
|
||||
class ComponentPaletteWidget;
|
||||
class ComponentModeCollectionInterface;
|
||||
struct SourceControlFileInfo;
|
||||
class ReadOnlyEntityPublicInterface;
|
||||
|
||||
namespace AssetBrowser
|
||||
{
|
||||
@@ -116,6 +118,7 @@ namespace AzToolsFramework
|
||||
, public AZ::EntitySystemBus::Handler
|
||||
, public AZ::TickBus::Handler
|
||||
, private EditorWindowUIRequestBus::Handler
|
||||
, private ReadOnlyEntityPublicNotificationBus::Handler
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -253,6 +256,9 @@ namespace AzToolsFramework
|
||||
// EditorWindowRequestBus overrides
|
||||
void SetEditorUiEnabled(bool enable) override;
|
||||
|
||||
// ReadOnlyEntityPublicNotificationBus overrides ...
|
||||
void OnReadOnlyEntityStatusChanged(const AZ::EntityId& entityId, bool readOnly) override;
|
||||
|
||||
bool IsEntitySelected(const AZ::EntityId& id) const;
|
||||
bool IsSingleEntitySelected(const AZ::EntityId& id) const;
|
||||
|
||||
@@ -623,6 +629,9 @@ namespace AzToolsFramework
|
||||
Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
bool m_prefabsAreEnabled = false;
|
||||
|
||||
ReadOnlyEntityPublicInterface* m_readOnlyEntityPublicInterface = nullptr;
|
||||
bool m_selectionContainsReadOnlyEntity = false;
|
||||
|
||||
// Reordering row widgets within the RPE.
|
||||
static constexpr float MoveFadeSeconds = 0.5f;
|
||||
|
||||
|
||||
+4
-1
@@ -191,7 +191,7 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color:rgb(51, 51, 51)</string>
|
||||
<string notr="true">QWidget#m_darkBox { background-color:rgb(51, 51, 51) }</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
@@ -444,6 +444,9 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color:rgb(51, 51, 51)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
||||
+22
-6
@@ -39,7 +39,12 @@ namespace AzToolsFramework
|
||||
typeFilter->SetAssetType(filterType);
|
||||
typeFilter->SetFilterPropagation(AssetBrowserEntryFilter::PropagateDirection::Down);
|
||||
|
||||
m_assetBrowserFilterModel->SetFilter(FilterConstType(typeFilter));
|
||||
SetFilter(FilterConstType(typeFilter));
|
||||
}
|
||||
|
||||
void AssetCompleterModel::SetFilter(FilterConstType filter)
|
||||
{
|
||||
m_assetBrowserFilterModel->SetFilter(filter);
|
||||
|
||||
RefreshAssetList();
|
||||
}
|
||||
@@ -120,9 +125,6 @@ namespace AzToolsFramework
|
||||
int rows = m_assetBrowserFilterModel->rowCount(index);
|
||||
if (rows == 0)
|
||||
{
|
||||
if (index != QModelIndex()) {
|
||||
AZ_Error("AssetCompleterModel", false, "No children detected in FetchResources()");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -131,7 +133,7 @@ namespace AzToolsFramework
|
||||
QModelIndex childIndex = m_assetBrowserFilterModel->index(i, 0, index);
|
||||
AssetBrowserEntry* childEntry = GetAssetEntry(m_assetBrowserFilterModel->mapToSource(childIndex));
|
||||
|
||||
if (childEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||
if (childEntry->GetEntryType() == m_entryType)
|
||||
{
|
||||
ProductAssetBrowserEntry* productEntry = static_cast<ProductAssetBrowserEntry*>(childEntry);
|
||||
AZStd::string assetName;
|
||||
@@ -167,7 +169,6 @@ namespace AzToolsFramework
|
||||
return m_assets[index.row()].m_displayName;
|
||||
}
|
||||
|
||||
|
||||
const AZ::Data::AssetId AssetCompleterModel::GetAssetIdFromIndex(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
@@ -177,4 +178,19 @@ namespace AzToolsFramework
|
||||
|
||||
return m_assets[index.row()].m_assetId;
|
||||
}
|
||||
|
||||
const AZStd::string_view AssetCompleterModel::GetPathFromIndex(const QModelIndex& index)
|
||||
{
|
||||
if (!index.isValid())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return m_assets[index.row()].m_path;
|
||||
}
|
||||
|
||||
void AssetCompleterModel::SetFetchEntryType(AssetBrowserEntry::AssetEntryType entryType)
|
||||
{
|
||||
m_entryType = entryType;
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -32,6 +32,7 @@ namespace AzToolsFramework
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void SetFilter(AZ::Data::AssetType filterType);
|
||||
void SetFilter(FilterConstType filter);
|
||||
void RefreshAssetList();
|
||||
void SearchStringHighlight(QString searchString);
|
||||
|
||||
@@ -39,6 +40,9 @@ namespace AzToolsFramework
|
||||
|
||||
const AZStd::string_view GetNameFromIndex(const QModelIndex& index);
|
||||
const AZ::Data::AssetId GetAssetIdFromIndex(const QModelIndex& index);
|
||||
const AZStd::string_view GetPathFromIndex(const QModelIndex& index);
|
||||
|
||||
void SetFetchEntryType(AssetBrowserEntry::AssetEntryType entryType);
|
||||
|
||||
private:
|
||||
struct AssetItem
|
||||
@@ -57,6 +61,8 @@ namespace AzToolsFramework
|
||||
AZStd::vector<AssetItem> m_assets;
|
||||
//! String that will be highlighted in the suggestions
|
||||
QString m_highlightString;
|
||||
|
||||
AssetBrowserEntry::AssetEntryType m_entryType = AssetBrowserEntry::AssetEntryType::Product;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+8
-3
@@ -1288,7 +1288,7 @@ namespace AzToolsFramework
|
||||
return newCtrl;
|
||||
}
|
||||
|
||||
void AssetPropertyHandlerDefault::ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
|
||||
void AssetPropertyHandlerDefault::ConsumeAttributeInternal(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
(void)debugName;
|
||||
|
||||
@@ -1487,6 +1487,11 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
void AssetPropertyHandlerDefault::ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName)
|
||||
{
|
||||
ConsumeAttributeInternal(GUI, attrib, attrValue, debugName);
|
||||
}
|
||||
|
||||
void AssetPropertyHandlerDefault::WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node)
|
||||
{
|
||||
(void)index;
|
||||
@@ -1629,8 +1634,8 @@ namespace AzToolsFramework
|
||||
|
||||
void RegisterAssetPropertyHandler()
|
||||
{
|
||||
EBUS_EVENT(PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew AssetPropertyHandlerDefault());
|
||||
EBUS_EVENT(PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SimpleAssetPropertyHandlerDefault());
|
||||
PropertyTypeRegistrationMessages::Bus::Broadcast(&PropertyTypeRegistrationMessages::RegisterPropertyType, aznew AssetPropertyHandlerDefault());
|
||||
PropertyTypeRegistrationMessages::Bus::Broadcast(&PropertyTypeRegistrationMessages::RegisterPropertyType, aznew SimpleAssetPropertyHandlerDefault());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-5
@@ -175,10 +175,11 @@ namespace AzToolsFramework
|
||||
virtual void SetFolderSelection(const AZStd::string& /* folderPath */) {}
|
||||
virtual void ClearAssetInternal();
|
||||
|
||||
void ConfigureAutocompleter();
|
||||
virtual void ConfigureAutocompleter();
|
||||
void RefreshAutocompleter();
|
||||
void EnableAutocompleter();
|
||||
void DisableAutocompleter();
|
||||
const QModelIndex GetSourceIndex(const QModelIndex& index);
|
||||
|
||||
void HandleFieldClear();
|
||||
AZStd::string AddDefaultSuffix(const AZStd::string& filename);
|
||||
@@ -235,20 +236,19 @@ namespace AzToolsFramework
|
||||
void SetSelectedAssetID(const AZ::Data::AssetId& newID, const AZ::Data::AssetType& newType);
|
||||
void SetCurrentAssetHint(const AZStd::string& hint);
|
||||
void SetDefaultAssetID(const AZ::Data::AssetId& defaultID);
|
||||
void PopupAssetPicker();
|
||||
virtual void PopupAssetPicker();
|
||||
void OnClearButtonClicked();
|
||||
void UpdateAssetDisplay();
|
||||
void OnLineEditFocus(bool focus);
|
||||
virtual void OnEditButtonClicked();
|
||||
void OnThumbnailClicked();
|
||||
void OnCompletionModelReset();
|
||||
void OnAutocomplete(const QModelIndex& index);
|
||||
virtual void OnAutocomplete(const QModelIndex& index);
|
||||
void OnTextChange(const QString& text);
|
||||
void OnReturnPressed();
|
||||
void ShowContextMenu(const QPoint& pos);
|
||||
|
||||
private:
|
||||
const QModelIndex GetSourceIndex(const QModelIndex& index);
|
||||
void UpdateThumbnail();
|
||||
};
|
||||
|
||||
@@ -270,7 +270,8 @@ namespace AzToolsFramework
|
||||
virtual void UpdateWidgetInternalTabbing(PropertyAssetCtrl* widget) override { widget->UpdateTabOrder(); }
|
||||
|
||||
virtual QWidget* CreateGUI(QWidget* pParent) override;
|
||||
virtual void ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
static void ConsumeAttributeInternal(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName);
|
||||
void ConsumeAttribute(PropertyAssetCtrl* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override;
|
||||
virtual void WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node) override;
|
||||
virtual bool ReadValuesIntoGUI(size_t index, PropertyAssetCtrl* GUI, const property_t& instance, InstanceDataNode* node) override;
|
||||
};
|
||||
|
||||
+9
@@ -15,12 +15,14 @@
|
||||
#include <AzCore/Slice/SliceComponent.h>
|
||||
#include <AzCore/std/containers/unordered_map.h>
|
||||
#include <AzCore/std/parallel/binary_semaphore.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
#include <AZTestShared/Utils/Utils.h>
|
||||
#include <AzFramework/UnitTest/TestDebugDisplayRequests.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
@@ -235,6 +237,13 @@ namespace UnitTest
|
||||
return toolsApp;
|
||||
}
|
||||
|
||||
//! It is possible to override this in classes deriving from ToolsApplicationFixture to provide alternate
|
||||
//! implementations of the DebugDisplayRequests interface (e.g. TestDebugDisplayRequests).
|
||||
virtual AZStd::shared_ptr<AzFramework::DebugDisplayRequests> CreateDebugDisplayRequests()
|
||||
{
|
||||
return AZStd::make_shared<NullDebugDisplayRequests>();
|
||||
}
|
||||
|
||||
protected:
|
||||
TestEditorActions m_editorActions;
|
||||
ToolsApplicationMessageHandler m_messageHandler; // used to suppress trace messages in test output
|
||||
|
||||
+23
@@ -21,6 +21,7 @@
|
||||
#include <AzToolsFramework/Commands/EntityManipulatorCommand.h>
|
||||
#include <AzToolsFramework/Commands/SelectionCommand.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityTransformBus.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityInterface.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorSnapping.h>
|
||||
#include <AzToolsFramework/Manipulators/RotationManipulators.h>
|
||||
@@ -1019,6 +1020,7 @@ namespace AzToolsFramework
|
||||
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId);
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusConnect(ViewportUi::DefaultViewportId);
|
||||
ReadOnlyEntityPublicNotificationBus::Handler::BusConnect(entityContextId);
|
||||
|
||||
CreateTransformModeSelectionCluster();
|
||||
CreateSpaceSelectionCluster();
|
||||
@@ -1054,6 +1056,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_pivotOverrideFrame.Reset();
|
||||
|
||||
ReadOnlyEntityPublicNotificationBus::Handler::BusDisconnect();
|
||||
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect();
|
||||
EditorContextMenuBus::Handler::BusConnect();
|
||||
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusDisconnect();
|
||||
@@ -3623,6 +3626,18 @@ namespace AzToolsFramework
|
||||
m_selectedEntityIds.erase(focusRoot);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not create manipulators for any entities marked as read only
|
||||
if (auto readOnlyEntityPublicInterface = AZ::Interface<ReadOnlyEntityPublicInterface>::Get())
|
||||
{
|
||||
AZStd::erase_if(
|
||||
m_selectedEntityIds,
|
||||
[readOnlyEntityPublicInterface](auto entityId)
|
||||
{
|
||||
return readOnlyEntityPublicInterface->IsReadOnly(entityId);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelection::OnTransformChanged(
|
||||
@@ -3830,6 +3845,14 @@ namespace AzToolsFramework
|
||||
m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty());
|
||||
}
|
||||
|
||||
void EditorTransformComponentSelection::OnReadOnlyEntityStatusChanged(const AZ::EntityId& entityId, [[maybe_unused]] bool readOnly)
|
||||
{
|
||||
if (IsEntitySelected(entityId))
|
||||
{
|
||||
RefreshSelectedEntityIdsAndRegenerateManipulators();
|
||||
}
|
||||
}
|
||||
|
||||
namespace ETCS
|
||||
{
|
||||
// little raii wrapper to switch a value from true to false and back
|
||||
|
||||
+5
@@ -20,6 +20,7 @@
|
||||
#include <AzToolsFramework/Commands/EntityManipulatorCommand.h>
|
||||
#include <AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h>
|
||||
#include <AzToolsFramework/Editor/EditorContextMenuBus.h>
|
||||
#include <AzToolsFramework/Entity/ReadOnly/ReadOnlyEntityBus.h>
|
||||
#include <AzToolsFramework/Manipulators/BaseManipulator.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorLockComponentBus.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorVisibilityBus.h>
|
||||
@@ -160,6 +161,7 @@ namespace AzToolsFramework
|
||||
, private EditorManipulatorCommandUndoRedoRequestBus::Handler
|
||||
, private AZ::TransformNotificationBus::MultiHandler
|
||||
, private ViewportInteraction::ViewportSettingsNotificationBus::Handler
|
||||
, private ReadOnlyEntityPublicNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
@@ -297,6 +299,9 @@ namespace AzToolsFramework
|
||||
// ViewportSettingsNotificationBus overrides ...
|
||||
void OnGridSnappingChanged(bool enabled) override;
|
||||
|
||||
// ReadOnlyEntityPublicNotificationBus overrides ...
|
||||
void OnReadOnlyEntityStatusChanged(const AZ::EntityId& entityId, bool readOnly) override;
|
||||
|
||||
// Helpers to safely interact with the TransformBus (requests).
|
||||
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation);
|
||||
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation);
|
||||
|
||||
@@ -768,6 +768,10 @@ set(FILES
|
||||
UI/Prefab/PrefabUiHandler.cpp
|
||||
UI/Prefab/PrefabViewportFocusPathHandler.h
|
||||
UI/Prefab/PrefabViewportFocusPathHandler.cpp
|
||||
UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.h
|
||||
UI/Prefab/Procedural/ProceduralPrefabReadOnlyHandler.cpp
|
||||
UI/Prefab/Procedural/ProceduralPrefabUiHandler.h
|
||||
UI/Prefab/Procedural/ProceduralPrefabUiHandler.cpp
|
||||
UI/Notifications/ToastNotificationsView.cpp
|
||||
UI/Notifications/ToastNotificationsView.h
|
||||
UI/Notifications/ToastBus.h
|
||||
|
||||
@@ -96,4 +96,22 @@ namespace AzToolsFramework
|
||||
// Verify the child entity is no longer marked as read-only
|
||||
EXPECT_FALSE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
|
||||
}
|
||||
|
||||
TEST_F(ReadOnlyEntityFixture, EnsureCacheIsClearedCorrectlyEvenIfUnchanged)
|
||||
{
|
||||
// Create a handler that sets all entities to read-only.
|
||||
ReadOnlyHandlerAlwaysTrue alwaysTrueHandler;
|
||||
|
||||
{
|
||||
// Create a handler that sets the child entity to read-only.
|
||||
ReadOnlyHandlerEntityId entityIdHandler(m_entityMap[ChildEntityName]);
|
||||
|
||||
// Verify the child entity is marked as read-only
|
||||
EXPECT_TRUE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
|
||||
}
|
||||
// When the handler goes out of scope, it calls RefreshReadOnlyStateForAllEntities and refreshes the cache.
|
||||
|
||||
// Verify the child entity is still marked as read-only
|
||||
EXPECT_TRUE(m_readOnlyEntityPublicInterface->IsReadOnly(m_entityMap[ChildEntityName]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,16 @@
|
||||
*/
|
||||
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
#include <AzToolsFramework/Application/ToolsApplication.h>
|
||||
#include <AzToolsFramework/Manipulators/RotationManipulators.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorView.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
|
||||
#include <AzToolsFramework/Manipulators/RotationManipulators.h>
|
||||
#include <AzToolsFramework/Manipulators/TranslationManipulators.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
#include <AzToolsFramework/UnitTest/ToolsTestApplication.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
@@ -21,8 +25,7 @@ namespace UnitTest
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
|
||||
class ManipulatorViewTest
|
||||
: public AllocatorsTestFixture
|
||||
class ManipulatorViewTest : public AllocatorsTestFixture
|
||||
{
|
||||
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
|
||||
|
||||
@@ -32,7 +35,7 @@ namespace UnitTest
|
||||
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
|
||||
m_app.Start(AzFramework::Application::Descriptor());
|
||||
// Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// shared across the whole engine, if multiple tests are run in parallel, the saving could cause a crash
|
||||
// in the unit tests.
|
||||
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
|
||||
}
|
||||
@@ -51,12 +54,9 @@ namespace UnitTest
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Given
|
||||
const AZ::Transform orientation =
|
||||
AZ::Transform::CreateFromQuaternion(
|
||||
AZ::Quaternion::CreateFromAxisAngle(
|
||||
AZ::Vector3::CreateAxisX(), AZ::DegToRad(-90.0f)));
|
||||
AZ::Transform::CreateFromQuaternion(AZ::Quaternion::CreateRotationX(AZ::DegToRad(-90.0f)));
|
||||
|
||||
const AZ::Transform translation =
|
||||
AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 0.0f, 10.0f));
|
||||
const AZ::Transform translation = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 0.0f, 10.0f));
|
||||
|
||||
const AZ::Transform manipulatorSpace = translation * orientation;
|
||||
// create a rotation manipulator in an arbitrary space
|
||||
@@ -67,8 +67,7 @@ namespace UnitTest
|
||||
// When
|
||||
const AZ::Vector3 worldCameraPosition = AZ::Vector3(5.0f, -10.0f, 10.0f);
|
||||
// transform the view direction to the space of the manipulator (space + local transform)
|
||||
const AZ::Vector3 viewDirection =
|
||||
CalculateViewDirection(rotationManipulators, worldCameraPosition);
|
||||
const AZ::Vector3 viewDirection = CalculateViewDirection(rotationManipulators, worldCameraPosition);
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -84,8 +83,7 @@ namespace UnitTest
|
||||
cameraState.m_position = AZ::Vector3::CreateAxisY(20.0f);
|
||||
cameraState.m_forward = -AZ::Vector3::CreateAxisY();
|
||||
|
||||
const float scale =
|
||||
AzToolsFramework::CalculateScreenToWorldMultiplier(AZ::Vector3::CreateZero(), cameraState);
|
||||
const float scale = AzToolsFramework::CalculateScreenToWorldMultiplier(AZ::Vector3::CreateZero(), cameraState);
|
||||
|
||||
EXPECT_NEAR(scale, 2.0f, std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
@@ -96,9 +94,57 @@ namespace UnitTest
|
||||
cameraState.m_position = AZ::Vector3::CreateAxisY(20.0f);
|
||||
cameraState.m_forward = -AZ::Vector3::CreateAxisY();
|
||||
|
||||
const float scale =
|
||||
AzToolsFramework::CalculateScreenToWorldMultiplier(AZ::Vector3::CreateAxisX(-10.0f), cameraState);
|
||||
const float scale = AzToolsFramework::CalculateScreenToWorldMultiplier(AZ::Vector3::CreateAxisX(-10.0f), cameraState);
|
||||
|
||||
EXPECT_NEAR(scale, 2.0f, std::numeric_limits<float>::epsilon());
|
||||
}
|
||||
|
||||
TEST_F(ManipulatorViewTest, ManipulatorViewQuadDrawsAtCorrectPositionWhenManipulatorSpaceIsScaledUniformlyAndNonUniformly)
|
||||
{
|
||||
// Given
|
||||
// simulate a custom manipulator space (e.g. entity transform) and a local offset within that space (e.g. spline vertex position)
|
||||
const AZ::Transform space =
|
||||
AZ::Transform::CreateTranslation(AZ::Vector3(2.0f, -3.0f, -4.0f)) * AZ::Transform::CreateUniformScale(2.0f);
|
||||
const AZ::Vector3 localPosition = AZ::Vector3(2.0f, -2.0f, 0.0f);
|
||||
const AZ::Vector3 nonUniformScale = AZ::Vector3(2.0f, 3.0f, 4.0f);
|
||||
const AZ::Transform combinedTransform =
|
||||
AzToolsFramework::ApplySpace(AZ::Transform::CreateTranslation(localPosition), space, nonUniformScale);
|
||||
|
||||
// create a manipulator state based on the space and local position
|
||||
AzToolsFramework::ManipulatorState manipulatorState{};
|
||||
manipulatorState.m_worldFromLocal = combinedTransform;
|
||||
manipulatorState.m_nonUniformScale = nonUniformScale;
|
||||
// note: This is zero as the localPosition is already encoded in the combinedTransform
|
||||
manipulatorState.m_localPosition = AZ::Vector3::CreateZero();
|
||||
|
||||
// camera (go to position format) - 10.00, -15.00, 6.00, -90.00, 0.00
|
||||
const AzFramework::CameraState cameraState = AzFramework::CreateDefaultCamera(
|
||||
AZ::Transform::CreateFromMatrix3x3AndTranslation(
|
||||
AZ::Matrix3x3::CreateRotationX(AZ::DegToRad(-90.0f)), AZ::Vector3(10.0f, -15.0f, 6.0f)),
|
||||
AZ::Vector2(1280, 720));
|
||||
|
||||
// test debug display instance to record vertices that were output
|
||||
auto testDebugDisplayRequests = AZStd::make_shared<TestDebugDisplayRequests>();
|
||||
auto planarTranslationViewQuad = CreateManipulatorViewQuadForPlanarTranslationManipulator(
|
||||
AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Color::CreateZero(), AZ::Color::CreateZero(), 2.2f, 0.2f, 1.0f);
|
||||
|
||||
// When
|
||||
// draw the quad as it would be for a manipulator
|
||||
planarTranslationViewQuad->Draw(
|
||||
AzToolsFramework::ManipulatorManagerId(1), AzToolsFramework::ManipulatorManagerState{ false },
|
||||
AzToolsFramework::ManipulatorId(1), manipulatorState, *testDebugDisplayRequests, cameraState,
|
||||
AzToolsFramework::ViewportInteraction::MouseInteraction{});
|
||||
|
||||
const AZStd::vector<AZ::Vector3> expectedDisplayPositions = {
|
||||
AZ::Vector3(10.5f, -13.5f, -4.0f), AZ::Vector3(11.5f, -13.5f, -4.0f), AZ::Vector3(10.5f, -14.5f, -4.0f),
|
||||
AZ::Vector3(11.5f, -14.5f, -4.0f), AZ::Vector3(10.5f, -13.5f, -4.0f), AZ::Vector3(10.5f, -14.5f, -4.0f),
|
||||
AZ::Vector3(11.5f, -14.5f, -4.0f), AZ::Vector3(11.5f, -13.5f, -4.0f)
|
||||
};
|
||||
|
||||
// Then
|
||||
const auto points = testDebugDisplayRequests->GetPoints();
|
||||
// quad vertices appear in the expected position (not offset or scaled incorrectly by space scale)
|
||||
using ::testing::UnorderedPointwise;
|
||||
EXPECT_THAT(points, UnorderedPointwise(ContainerIsClose(), expectedDisplayPositions));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* 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 <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/Serialization/Json/JsonUtils.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <Prefab/PrefabTestFixture.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
using PrefabInstantiateTest = PrefabTestFixture;
|
||||
|
||||
struct MockAsset : AZ::Data::AssetData
|
||||
{
|
||||
AZ_RTTI(MockAsset, "{DAB98A3F-1714-4B95-AACB-8C150B0D0628}", AZ::Data::AssetData);
|
||||
|
||||
AZ_CLASS_ALLOCATOR(MockAsset, AZ::SystemAllocator, 0);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<MockAsset>()->Field("data", &MockAsset::m_data);
|
||||
}
|
||||
}
|
||||
float m_data = 1.f;
|
||||
};
|
||||
|
||||
struct MockAssetComponent : AZ::Component
|
||||
{
|
||||
AZ_COMPONENT(MockAssetComponent, "{D81B0D06-B495-479E-832A-A63079FD6D37}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
MockAsset::Reflect(context);
|
||||
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<MockAssetComponent>()
|
||||
->Field("asset", &MockAssetComponent::m_asset);
|
||||
}
|
||||
}
|
||||
|
||||
void Activate() override{}
|
||||
void Deactivate() override{}
|
||||
|
||||
AZ::Data::Asset<MockAsset> m_asset;
|
||||
};
|
||||
|
||||
class MockAssetHandler : public AZ::Data::AssetHandler
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(MockAssetHandler, AZ::SystemAllocator, 0);
|
||||
|
||||
AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override
|
||||
{
|
||||
(void)id;
|
||||
EXPECT_TRUE(type == azrtti_typeid<MockAsset>());
|
||||
if (type == azrtti_typeid<MockAsset>())
|
||||
{
|
||||
return aznew MockAsset();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LoadResult LoadAssetData(const AZ::Data::Asset<AZ::Data::AssetData>&, AZStd::shared_ptr<AZ::Data::AssetDataStream>, const AZ::Data::AssetFilterCB&) override
|
||||
{
|
||||
return LoadResult::Error;
|
||||
}
|
||||
|
||||
void DestroyAsset(AZ::Data::AssetPtr ptr) override
|
||||
{
|
||||
EXPECT_TRUE(ptr->GetType() == azrtti_typeid<MockAsset>());
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
void GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes) override
|
||||
{
|
||||
assetTypes.push_back(azrtti_typeid<MockAsset>());
|
||||
}
|
||||
};
|
||||
|
||||
struct PrefabFixupTest : PrefabInstantiateTest
|
||||
{
|
||||
void SetUpEditorFixtureImpl() override
|
||||
{
|
||||
PrefabInstantiateTest::SetUpEditorFixtureImpl();
|
||||
|
||||
AZ::SerializeContext* context = nullptr;
|
||||
|
||||
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
|
||||
ASSERT_NE(context, nullptr);
|
||||
|
||||
MockAssetComponent::Reflect(context);
|
||||
|
||||
AZ::Data::AssetManager::Instance().RegisterHandler(&m_handler, azrtti_typeid<MockAsset>());
|
||||
|
||||
auto entity = aznew AZ::Entity();
|
||||
auto mockAssetComponent = entity->CreateComponent<MockAssetComponent>();
|
||||
|
||||
mockAssetComponent->m_asset =
|
||||
AZ::Data::Asset<MockAsset>(AZ::Uuid::CreateNull(), AZ::Data::AssetType::CreateNull(), "test.asset");
|
||||
|
||||
auto newInstance = AZ::Interface<PrefabSystemComponentInterface>::Get()->CreatePrefab({ entity }, {}, "test.prefab");
|
||||
|
||||
AZStd::string prefabString;
|
||||
ASSERT_TRUE(m_prefabLoaderInterface->SaveTemplateToString(newInstance->GetTemplateId(), prefabString));
|
||||
m_prefabSystemComponent->RemoveAllTemplates();
|
||||
|
||||
AZ::Outcome<PrefabDom, AZStd::string> readPrefabFileResult = AZ::JsonSerializationUtils::ReadJsonString(prefabString);
|
||||
|
||||
ASSERT_TRUE(readPrefabFileResult.IsSuccess());
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
m_assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, "test.asset", azrtti_typeid<MockAsset>(),
|
||||
true); // True to register the asset and generate an AssetId for lookup
|
||||
|
||||
m_prefabDom = readPrefabFileResult.TakeValue();
|
||||
}
|
||||
|
||||
void TearDownEditorFixtureImpl() override
|
||||
{
|
||||
PrefabInstantiateTest::TearDownEditorFixtureImpl();
|
||||
|
||||
AZ::Data::AssetManager::Instance().UnregisterHandler(&m_handler);
|
||||
}
|
||||
|
||||
void CheckInstance(const Instance& instance)
|
||||
{
|
||||
const AZ::Entity* loadedEntity = nullptr;
|
||||
instance.GetConstEntities(
|
||||
[&loadedEntity](const AZ::Entity& entity)
|
||||
{
|
||||
loadedEntity = &entity;
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
auto loadedComponent = loadedEntity->FindComponent<MockAssetComponent>();
|
||||
|
||||
ASSERT_NE(loadedComponent, nullptr);
|
||||
|
||||
ASSERT_STREQ(loadedComponent->m_asset.GetHint().c_str(), "test.asset");
|
||||
ASSERT_EQ(loadedComponent->m_asset->GetId(), m_assetId);
|
||||
}
|
||||
|
||||
MockAssetHandler m_handler;
|
||||
PrefabDom m_prefabDom;
|
||||
AZ::Data::AssetId m_assetId;
|
||||
};
|
||||
|
||||
TEST_F(PrefabFixupTest, Test_LoadInstanceFromPrefabDom_Overload1)
|
||||
{
|
||||
Instance instance;
|
||||
ASSERT_TRUE(PrefabDomUtils::LoadInstanceFromPrefabDom(instance, m_prefabDom));
|
||||
|
||||
CheckInstance(instance);
|
||||
}
|
||||
|
||||
TEST_F(PrefabFixupTest, Test_LoadInstanceFromPrefabDom_Overload2)
|
||||
{
|
||||
Instance instance;
|
||||
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> referencedAssets;
|
||||
ASSERT_TRUE(PrefabDomUtils::LoadInstanceFromPrefabDom(instance, m_prefabDom, referencedAssets));
|
||||
|
||||
CheckInstance(instance);
|
||||
}
|
||||
|
||||
TEST_F(PrefabFixupTest, Test_LoadInstanceFromPrefabDom_Overload3)
|
||||
{
|
||||
Instance instance;
|
||||
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> referencedAssets;
|
||||
Instance::EntityList entityList;
|
||||
(PrefabDomUtils::LoadInstanceFromPrefabDom(instance, entityList, m_prefabDom));
|
||||
|
||||
CheckInstance(instance);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabLoaderInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <Prefab/PrefabTestComponent.h>
|
||||
#include <Prefab/PrefabTestDomUtils.h>
|
||||
|
||||
@@ -50,6 +52,15 @@ namespace UnitTest
|
||||
|
||||
GetApplication()->RegisterComponentDescriptor(PrefabTestComponent::CreateDescriptor());
|
||||
GetApplication()->RegisterComponentDescriptor(PrefabTestComponentWithUnReflectedTypeMember::CreateDescriptor());
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
m_undoStack, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetUndoStack);
|
||||
AZ_Assert(m_undoStack, "Failed to look up undo stack from tools application");
|
||||
}
|
||||
|
||||
void PrefabTestFixture::TearDownEditorFixtureImpl()
|
||||
{
|
||||
m_undoStack = nullptr;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<ToolsTestApplication> PrefabTestFixture::CreateTestApplication()
|
||||
@@ -57,12 +68,25 @@ namespace UnitTest
|
||||
return AZStd::make_unique<PrefabTestToolsApplication>("PrefabTestApplication");
|
||||
}
|
||||
|
||||
void PrefabTestFixture::CreateRootPrefab()
|
||||
{
|
||||
auto entityOwnershipService = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
ASSERT_TRUE(entityOwnershipService != nullptr);
|
||||
entityOwnershipService->CreateNewLevelPrefab("UnitTestRoot.prefab", "");
|
||||
auto rootEntityReference = entityOwnershipService->GetRootPrefabInstance()->get().GetContainerEntity();
|
||||
ASSERT_TRUE(rootEntityReference.has_value());
|
||||
auto& rootEntity = rootEntityReference->get();
|
||||
rootEntity.Deactivate();
|
||||
rootEntity.CreateComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
rootEntity.Activate();
|
||||
}
|
||||
|
||||
void PrefabTestFixture::PropagateAllTemplateChanges()
|
||||
{
|
||||
m_prefabSystemComponent->OnSystemTick();
|
||||
}
|
||||
|
||||
AZ::Entity* PrefabTestFixture::CreateEntity(const char* entityName, const bool shouldActivate)
|
||||
AZ::Entity* PrefabTestFixture::CreateEntity(AZStd::string entityName, const bool shouldActivate)
|
||||
{
|
||||
// Circumvent the EntityContext system and generate a new entity with a transformcomponent
|
||||
AZ::Entity* newEntity = aznew AZ::Entity(entityName);
|
||||
@@ -76,8 +100,43 @@ namespace UnitTest
|
||||
return newEntity;
|
||||
}
|
||||
|
||||
AZ::EntityId PrefabTestFixture::CreateEntityUnderRootPrefab(AZStd::string name, AZ::EntityId parentId)
|
||||
{
|
||||
auto createResult = m_prefabPublicInterface->CreateEntity(parentId, AZ::Vector3());
|
||||
AZ_Assert(createResult.IsSuccess(), "Failed to create entity: %s", createResult.GetError().c_str());
|
||||
AZ::EntityId entityId = createResult.GetValue();
|
||||
|
||||
AZ::Entity* entity = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId);
|
||||
|
||||
entity->Deactivate();
|
||||
|
||||
entity->SetName(name);
|
||||
|
||||
// Normally, in invalid parent ID should automatically parent us to the root prefab, but currently in the unit test
|
||||
// environment entities aren't created with a default transform component, so CreateEntity won't correctly parent.
|
||||
// We get the actual target parent ID here, then create our missing transform component.
|
||||
if (!parentId.IsValid())
|
||||
{
|
||||
auto prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
parentId = prefabEditorEntityOwnershipInterface->GetRootPrefabInstance()->get().GetContainerEntityId();
|
||||
}
|
||||
|
||||
auto transform = aznew AzToolsFramework::Components::TransformComponent;
|
||||
transform->SetParent(parentId);
|
||||
entity->AddComponent(transform);
|
||||
|
||||
entity->Activate();
|
||||
|
||||
// Update our undo cache entry to include the rename / reparent as one atomic operation.
|
||||
m_prefabPublicInterface->GenerateUndoNodesForEntityChangeAndUpdateCache(entityId, m_undoStack->GetTop());
|
||||
m_prefabSystemComponent->OnSystemTick();
|
||||
|
||||
return entityId;
|
||||
}
|
||||
|
||||
void PrefabTestFixture::CompareInstances(const AzToolsFramework::Prefab::Instance& instanceA,
|
||||
const AzToolsFramework::Prefab::Instance& instanceB, bool shouldCompareLinkIds, bool shouldCompareContainerEntities)
|
||||
const AzToolsFramework::Prefab::Instance& instanceB, bool shouldCompareLinkIds, bool shouldCompareContainerEntities)
|
||||
{
|
||||
AzToolsFramework::Prefab::TemplateId templateAId = instanceA.GetTemplateId();
|
||||
AzToolsFramework::Prefab::TemplateId templateBId = instanceB.GetTemplateId();
|
||||
@@ -131,6 +190,24 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabTestFixture::ProcessDeferredUpdates()
|
||||
{
|
||||
// Force a prefab propagation for updates that are deferred to the next tick.
|
||||
m_prefabSystemComponent->OnSystemTick();
|
||||
}
|
||||
|
||||
void PrefabTestFixture::Undo()
|
||||
{
|
||||
m_undoStack->Undo();
|
||||
ProcessDeferredUpdates();
|
||||
}
|
||||
|
||||
void PrefabTestFixture::Redo()
|
||||
{
|
||||
m_undoStack->Redo();
|
||||
ProcessDeferredUpdates();
|
||||
}
|
||||
|
||||
void PrefabTestFixture::AddRequiredEditorComponents(AZ::Entity* entity)
|
||||
{
|
||||
ASSERT_TRUE(entity != nullptr);
|
||||
|
||||
@@ -49,13 +49,15 @@ namespace UnitTest
|
||||
inline static const char* CarPrefabMockFilePath = "SomePathToCar";
|
||||
|
||||
void SetUpEditorFixtureImpl() override;
|
||||
void TearDownEditorFixtureImpl() override;
|
||||
|
||||
AZStd::unique_ptr<ToolsTestApplication> CreateTestApplication() override;
|
||||
|
||||
void CreateRootPrefab();
|
||||
AZ::Entity* CreateEntity(AZStd::string entityName, const bool shouldActivate = true);
|
||||
AZ::EntityId CreateEntityUnderRootPrefab(AZStd::string name, AZ::EntityId parentId = AZ::EntityId());
|
||||
void PropagateAllTemplateChanges();
|
||||
|
||||
AZ::Entity* CreateEntity(const char* entityName, const bool shouldActivate = true);
|
||||
|
||||
void CompareInstances(const Instance& instanceA, const Instance& instanceB, bool shouldCompareLinkIds = true,
|
||||
bool shouldCompareContainerEntities = true);
|
||||
|
||||
@@ -64,6 +66,15 @@ namespace UnitTest
|
||||
//! Validates that all entities within a prefab instance are in 'Active' state.
|
||||
void ValidateInstanceEntitiesActive(Instance& instance);
|
||||
|
||||
// Kicks off any updates scheduled for the next tick
|
||||
virtual void ProcessDeferredUpdates();
|
||||
|
||||
// Performs an undo operation and ensures the tick-scheduled updates happen
|
||||
void Undo();
|
||||
|
||||
// Performs a redo operation and ensures the tick-scheduled updates happen
|
||||
void Redo();
|
||||
|
||||
void AddRequiredEditorComponents(AZ::Entity* entity);
|
||||
|
||||
PrefabSystemComponent* m_prefabSystemComponent = nullptr;
|
||||
@@ -71,5 +82,6 @@ namespace UnitTest
|
||||
PrefabPublicInterface* m_prefabPublicInterface = nullptr;
|
||||
InstanceUpdateExecutorInterface* m_instanceUpdateExecutorInterface = nullptr;
|
||||
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
|
||||
AzToolsFramework::UndoSystem::UndoStack* m_undoStack = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,16 +37,11 @@ namespace UnitTest
|
||||
m_model->Initialize();
|
||||
m_modelTester =
|
||||
AZStd::make_unique<QAbstractItemModelTester>(m_model.get(), QAbstractItemModelTester::FailureReportingMode::Fatal);
|
||||
|
||||
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
|
||||
m_undoStack, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetUndoStack);
|
||||
AZ_Assert(m_undoStack, "Failed to look up undo stack from tools application");
|
||||
|
||||
|
||||
// Create a new root prefab - the synthetic "NewLevel.prefab" that comes in by default isn't suitable for outliner tests
|
||||
// because it's created before the EditorEntityModel that our EntityOutlinerListModel subscribes to, and we want to
|
||||
// recreate it as part of the fixture regardless.
|
||||
auto entityOwnershipService = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
|
||||
entityOwnershipService->CreateNewLevelPrefab("UnitTestRoot.prefab", "");
|
||||
CreateRootPrefab();
|
||||
}
|
||||
|
||||
void TearDownEditorFixtureImpl() override
|
||||
@@ -125,7 +120,7 @@ namespace UnitTest
|
||||
}
|
||||
|
||||
// Kicks off any updates scheduled for the next tick
|
||||
void ProcessDeferredUpdates()
|
||||
void ProcessDeferredUpdates() override
|
||||
{
|
||||
// Force a prefab propagation for updates that are deferred to the next tick.
|
||||
PropagateAllTemplateChanges();
|
||||
@@ -133,24 +128,9 @@ namespace UnitTest
|
||||
// Ensure the model process its entity update queue
|
||||
m_model->ProcessEntityUpdates();
|
||||
}
|
||||
|
||||
// Performs an undo operation and ensures the tick-scheduled updates happen
|
||||
void Undo()
|
||||
{
|
||||
m_undoStack->Undo();
|
||||
ProcessDeferredUpdates();
|
||||
}
|
||||
|
||||
// Performs a redo operation and ensures the tick-scheduled updates happen
|
||||
void Redo()
|
||||
{
|
||||
m_undoStack->Redo();
|
||||
ProcessDeferredUpdates();
|
||||
}
|
||||
|
||||
|
||||
AZStd::unique_ptr<AzToolsFramework::EntityOutlinerListModel> m_model;
|
||||
AZStd::unique_ptr<QAbstractItemModelTester> m_modelTester;
|
||||
AzToolsFramework::UndoSystem::UndoStack* m_undoStack = nullptr;
|
||||
};
|
||||
|
||||
TEST_F(EntityOutlinerTest, TestCreateFlatHierarchyUndoAndRedoWorks)
|
||||
|
||||
@@ -74,7 +74,7 @@ set(FILES
|
||||
Prefab/PrefabEntityAliasTests.cpp
|
||||
Prefab/PrefabInstanceToTemplatePropagatorTests.cpp
|
||||
Prefab/PrefabInstantiateTests.cpp
|
||||
Prefab/PrefabInstantiateTests.cpp
|
||||
Prefab/PrefabAssetFixupTests.cpp
|
||||
Prefab/PrefabLoadTemplateTests.cpp
|
||||
Prefab/PrefabTestComponent.cpp
|
||||
Prefab/PrefabTestComponent.h
|
||||
|
||||
Reference in New Issue
Block a user