Merge branch 'main' of https://github.com/aws-lumberyard/o3de into Prefab/Create/PositionFix

# Conflicts:
#	Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp
This commit is contained in:
daimini
2021-05-17 13:26:04 -07:00
586 changed files with 4079 additions and 23100 deletions
@@ -42,6 +42,7 @@ namespace AzToolsFramework
~LinearManipulator() = default;
/// A Manipulator must only be created and managed through a shared_ptr.
/// @note worldFromLocal should not contain scale.
static AZStd::shared_ptr<LinearManipulator> MakeShared(const AZ::Transform& worldFromLocal);
/// Unchanging data set once for the linear manipulator.
@@ -199,6 +199,43 @@ namespace AzToolsFramework
return true;
}
void GetTemplateSourcePaths(const PrefabDomValue& prefabDom, AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths)
{
PrefabDomValueConstReference findSourceResult = PrefabDomUtils::FindPrefabDomValue(prefabDom, PrefabDomUtils::SourceName);
if (!findSourceResult.has_value() || !(findSourceResult->get().IsString()) ||
findSourceResult->get().GetStringLength() == 0)
{
AZ_Assert(
false,
"PrefabDomUtils::GetDependentTemplatePath - Source value of prefab in the provided DOM is not a valid string.");
return;
}
templateSourcePaths.emplace(findSourceResult->get().GetString());
PrefabDomValueConstReference instancesReference = GetInstancesValue(prefabDom);
if (instancesReference.has_value())
{
const PrefabDomValue& instances = instancesReference->get();
for (PrefabDomValue::ConstMemberIterator instanceIterator = instances.MemberBegin();
instanceIterator != instances.MemberEnd(); ++instanceIterator)
{
GetTemplateSourcePaths(instanceIterator->value, templateSourcePaths);
}
}
}
PrefabDomValueConstReference GetInstancesValue(const PrefabDomValue& prefabDom)
{
PrefabDomValueConstReference findInstancesResult = FindPrefabDomValue(prefabDom, PrefabDomUtils::InstancesName);
if (!findInstancesResult.has_value() || !(findInstancesResult->get().IsObject()))
{
return AZStd::nullopt;
}
return findInstancesResult->get();
}
void PrintPrefabDomValue(
[[maybe_unused]] const AZStd::string_view printMessage,
[[maybe_unused]] const PrefabDomValue& prefabDomValue)
@@ -100,6 +100,20 @@ namespace AzToolsFramework
.Append(instanceName);
};
/**
* Gets a set of all the template source paths in the given dom.
* @param prefabDom The DOM to get the template source paths from.
* @param[out] templateSourcePaths The set of template source paths to populate.
*/
void GetTemplateSourcePaths(const PrefabDomValue& prefabDom, AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths);
/**
* Gets the instances DOM value from the given prefab DOM.
*
* @return the instances DOM value or AZStd::nullopt if it instances can't be found.
*/
PrefabDomValueConstReference GetInstancesValue(const PrefabDomValue& prefabDom);
/**
* Prints the contents of the given prefab DOM value to the debug output console in a readable format.
* @param printMessage The message that will be printed before printing the PrefabDomValue
@@ -234,18 +234,24 @@ namespace AzToolsFramework
auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
// If the template isn't currently loaded, there's no way for it to be in the hierarchy so we just skip the check.
if (templateId != Prefab::InvalidTemplateId && IsPrefabInInstanceAncestorHierarchy(templateId, instanceToParentUnder->get()))
if (templateId == InvalidTemplateId)
{
return AZ::Failure(
AZStd::string::format(
"Instantiate Prefab operation aborted - Cyclical dependency detected\n(%s depends on %s).",
relativePath.Native().c_str(),
instanceToParentUnder->get().GetTemplateSourcePath().Native().c_str()
)
);
// Load the template from the file
templateId = m_prefabLoaderInterface->LoadTemplateFromFile(filePath);
AZ_Assert(templateId != InvalidTemplateId, "Template with source path %s couldn't be loaded correctly.", filePath);
}
const PrefabDom& templateDom = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
AZStd::unordered_set<AZ::IO::Path> templatePaths;
PrefabDomUtils::GetTemplateSourcePaths(templateDom, templatePaths);
if (IsCyclicalDependencyFound(instanceToParentUnder->get(), templatePaths))
{
return AZ::Failure(AZStd::string::format(
"Instantiate Prefab operation aborted - Cyclical dependency detected\n(%s depends on %s).",
relativePath.Native().c_str(), instanceToParentUnder->get().GetTemplateSourcePath().Native().c_str()));
}
{
// Initialize Undo Batch object
ScopedUndoBatch undoBatch("Instantiate Prefab");
@@ -319,17 +325,17 @@ namespace AzToolsFramework
return AZ::Success();
}
bool PrefabPublicHandler::IsPrefabInInstanceAncestorHierarchy(TemplateId prefabTemplateId, InstanceOptionalConstReference instance)
bool PrefabPublicHandler::IsCyclicalDependencyFound(
InstanceOptionalConstReference instance, const AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths)
{
InstanceOptionalConstReference currentInstance = instance;
while (currentInstance.has_value())
{
if (currentInstance->get().GetTemplateId() == prefabTemplateId)
if (templateSourcePaths.contains(currentInstance->get().GetTemplateSourcePath()))
{
return true;
}
currentInstance = currentInstance->get().GetParentInstance();
}
@@ -999,5 +1005,5 @@ namespace AzToolsFramework
return true;
}
}
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -12,8 +12,8 @@
#pragma once
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
@@ -106,13 +106,15 @@ namespace AzToolsFramework
const AZStd::vector<AZ::EntityId>& entityIds, EntityList& inputEntityList, EntityList& topLevelEntities,
AZ::EntityId& commonRootEntityId, InstanceOptionalReference& commonRootEntityOwningInstance);
/* Detects whether an instance of prefabTemplateId is present in the hierarchy of ancestors of instance.
/* Checks whether the template source path of any of the ancestors in the instance hierarchy matches with one of the
* paths provided in a set.
*
* \param prefabTemplateId The template id to test for
* \param instance The instance whose ancestor hierarchy prefabTemplateId will be tested against.
* \return true if an instance of the template of id prefabTemplateId could be found in the ancestor hierarchy of instance, false otherwise.
* \param instance The instance whose ancestor hierarchy the provided set of template source paths will be tested against.
* \param templateSourcePaths The template source paths provided to be checked against the instance ancestor hierarchy.
* \return true if any of the template source paths could be found in the ancestor hierarchy of instance, false otherwise.
*/
bool IsPrefabInInstanceAncestorHierarchy(TemplateId prefabTemplateId, InstanceOptionalConstReference instance);
bool IsCyclicalDependencyFound(
InstanceOptionalConstReference instance, const AZStd::unordered_set<AZ::IO::Path>& templateSourcePaths);
static Instance* GetParentInstance(Instance* instance);
static Instance* GetAncestorOfInstanceThatIsChildOfRoot(const Instance* ancestor, Instance* descendant);
@@ -128,5 +130,5 @@ namespace AzToolsFramework
uint64_t m_newEntityCounter = 1;
};
}
}
} // namespace Prefab
} // namespace AzToolsFramework
@@ -1,20 +1,20 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
#include <AzCore/Math/ToString.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/ToString.h>
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
namespace AzToolsFramework
{
@@ -32,12 +32,13 @@ namespace AzToolsFramework
serializeContext->Class<EditorNonUniformScaleComponent, EditorComponentBase>()
->Version(1)
->Field("NonUniformScale", &EditorNonUniformScaleComponent::m_scale)
;
->Field("ComponentMode", &EditorNonUniformScaleComponent::m_componentModeDelegate);
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<EditorNonUniformScaleComponent>("Non-uniform Scale",
"Non-uniform scale for this entity only (does not propagate through hierarchy)")
editContext
->Class<EditorNonUniformScaleComponent>(
"Non-uniform Scale", "Non-uniform scale for this entity only (does not propagate through hierarchy)")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::FixedComponentListIndex, 1)
->Attribute(AZ::Edit::Attributes::RemoveableByUser, true)
@@ -50,7 +51,10 @@ namespace AzToolsFramework
->Attribute(AZ::Edit::Attributes::Max, AZ::MaxTransformScale)
->Attribute(AZ::Edit::Attributes::Step, 0.1f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorNonUniformScaleComponent::OnScaleChanged)
;
->DataElement(
AZ::Edit::UIHandlers::Default, &EditorNonUniformScaleComponent::m_componentModeDelegate, "Component Mode",
"Non-uniform Scale Component Mode")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly);
}
}
}
@@ -74,10 +78,16 @@ namespace AzToolsFramework
void EditorNonUniformScaleComponent::Activate()
{
AZ::NonUniformScaleRequestBus::Handler::BusConnect(GetEntityId());
// ComponentMode
m_componentModeDelegate.ConnectWithSingleComponentMode<EditorNonUniformScaleComponent, NonUniformScaleComponentMode>(
AZ::EntityComponentIdPair(GetEntityId(), GetId()), nullptr);
}
void EditorNonUniformScaleComponent::Deactivate()
{
m_componentModeDelegate.Disconnect();
AZ::NonUniformScaleRequestBus::Handler::BusDisconnect();
}
@@ -96,7 +106,8 @@ namespace AzToolsFramework
else
{
AZ::Vector3 clampedScale = scale.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale));
AZ_Warning("Editor Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s",
AZ_Warning(
"Editor Non-uniform Scale Component", false, "SetScale value was clamped from %s to %s for entity %s",
AZ::ToString(scale).c_str(), AZ::ToString(clampedScale).c_str(), GetEntity()->GetName().c_str());
m_scale = clampedScale;
}
@@ -13,6 +13,9 @@
#pragma once
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.h>
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzCore/Component/NonUniformScaleBus.h>
namespace AzToolsFramework
@@ -52,6 +55,9 @@ namespace AzToolsFramework
AZ::Vector3 m_scale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleChangedEvent m_scaleChangedEvent;
//! Responsible for detecting ComponentMode activation and creating a concrete ComponentMode.
AzToolsFramework::ComponentModeFramework::ComponentModeDelegate m_componentModeDelegate;
};
} // namespace Components
} // namespace AzToolsFramework
@@ -0,0 +1,92 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/Component/NonUniformScaleBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzFramework/Viewport/ViewportColors.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponentMode.h>
namespace AzToolsFramework
{
namespace Components
{
NonUniformScaleComponentMode::NonUniformScaleComponentMode(
const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType)
: EditorBaseComponentMode(entityComponentIdPair, componentType)
{
m_entityComponentIdPair = entityComponentIdPair;
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(worldFromLocal, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
worldFromLocal.ExtractScale();
m_manipulators = AZStd::make_unique<ScaleManipulators>(worldFromLocal);
m_manipulators->Register(g_mainManipulatorManagerId);
m_manipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
const float axisLength = 2.0f;
m_manipulators->ConfigureView(
axisLength, AzFramework::ViewportColors::XAxisColor, AzFramework::ViewportColors::YAxisColor,
AzFramework::ViewportColors::ZAxisColor);
auto mouseDownCallback = [this](const LinearManipulator::Action& action) {
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(
nonUniformScale, m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
m_initialScale = nonUniformScale + action.m_start.m_scaleSnapOffset;
AZ::NonUniformScaleRequestBus::Event(
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale, m_initialScale);
};
m_manipulators->InstallAxisLeftMouseDownCallback(mouseDownCallback);
m_manipulators->InstallAxisMouseMoveCallback([this](const LinearManipulator::Action& action) {
const AZ::Vector3 scaleMultiplier =
(AZ::Vector3::CreateOne() + ((action.LocalScaleOffset() * action.m_start.m_sign) / m_initialScale));
AZ::NonUniformScaleRequestBus::Event(
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale,
(scaleMultiplier * m_initialScale).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)));
});
m_manipulators->InstallUniformLeftMouseDownCallback(mouseDownCallback);
m_manipulators->InstallUniformMouseMoveCallback([this](const LinearManipulator::Action& action) {
const auto sumVectorElements = [](const AZ::Vector3& vec) { return vec.GetX() + vec.GetY() + vec.GetZ(); };
const float minScaleMultiplier = AZ::MinTransformScale / m_initialScale.GetMinElement();
const float maxScaleMultiplier = AZ::MaxTransformScale / m_initialScale.GetMaxElement();
const float scaleMultiplier = AZ::GetClamp(
1.0f + sumVectorElements(action.m_start.m_sign * action.LocalScaleOffset() / m_initialScale), minScaleMultiplier,
maxScaleMultiplier);
AZ::NonUniformScaleRequestBus::Event(
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale, scaleMultiplier * m_initialScale);
});
}
NonUniformScaleComponentMode::~NonUniformScaleComponentMode()
{
if (m_manipulators)
{
m_manipulators->Unregister();
}
m_manipulators.reset();
}
void NonUniformScaleComponentMode::Refresh()
{
}
} // namespace Components
} // namespace AzToolsFramework
@@ -0,0 +1,43 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzToolsFramework/ComponentMode/EditorBaseComponentMode.h>
#include <AzToolsFramework/Manipulators/ScaleManipulators.h>
namespace AzToolsFramework
{
namespace Components
{
class NonUniformScaleComponentMode : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode
{
public:
AZ_CLASS_ALLOCATOR(NonUniformScaleComponentMode, AZ::SystemAllocator, 0)
NonUniformScaleComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType);
NonUniformScaleComponentMode(const NonUniformScaleComponentMode&) = delete;
NonUniformScaleComponentMode& operator=(const NonUniformScaleComponentMode&) = delete;
NonUniformScaleComponentMode(NonUniformScaleComponentMode&&) = delete;
NonUniformScaleComponentMode& operator=(NonUniformScaleComponentMode&&) = delete;
~NonUniformScaleComponentMode();
// EditorBaseComponentMode overrides ...
void Refresh() override;
private:
AZ::EntityComponentIdPair m_entityComponentIdPair;
AZStd::unique_ptr<ScaleManipulators> m_manipulators;
AZ::Vector3 m_initialScale;
};
} // namespace Components
} // namespace AzToolsFramework
@@ -254,7 +254,7 @@ namespace AzToolsFramework
m_localTransformDirty = true;
m_worldTransformDirty = true;
if (GetEntity())
if (const AZ::Entity* entity = GetEntity())
{
SetDirty();
@@ -273,6 +273,22 @@ namespace AzToolsFramework
{
boundsUnion->OnTransformUpdated(GetEntity());
}
// Fire a property changed notification for this component
if (const AZ::Component* component = entity->FindComponent<Components::TransformComponent>())
{
PropertyEditorEntityChangeNotificationBus::Event(
GetEntityId(), &PropertyEditorEntityChangeNotifications::OnEntityComponentPropertyChanged, component->GetId());
}
// Refresh the property editor if we're selected
bool selected = false;
ToolsApplicationRequestBus::BroadcastResult(
selected, &AzToolsFramework::ToolsApplicationRequests::IsSelected, GetEntityId());
if (selected)
{
ToolsApplicationEvents::Bus::Broadcast(
&ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values);
}
}
}
@@ -303,6 +303,8 @@ set(FILES
ToolsComponents/AzToolsFrameworkConfigurationSystemComponent.cpp
ToolsComponents/EditorNonUniformScaleComponent.h
ToolsComponents/EditorNonUniformScaleComponent.cpp
ToolsComponents/EditorNonUniformScaleComponentMode.h
ToolsComponents/EditorNonUniformScaleComponentMode.cpp
ToolsMessaging/EntityHighlightBus.h
UI/Docking/DockWidgetUtils.cpp
UI/Docking/DockWidgetUtils.h
@@ -237,4 +237,23 @@ namespace UnitTest
EXPECT_THAT(cameraTransform, IsClose(cameraTransformFromView));
EXPECT_THAT(cameraView, IsClose(cameraViewFromTransform));
}
TEST(ViewportScreen, FovCanBeRetrievedFromProjectionMatrix)
{
using ::testing::FloatNear;
auto cameraState = AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AZ::Vector2(800.0f, 600.0f));
{
const float fovRadians = AZ::DegToRad(45.0f);
AzFramework::SetCameraClippingVolume(cameraState, 0.1f, 100.0f, fovRadians);
EXPECT_THAT(AzFramework::RetrieveFov(AzFramework::CameraProjection(cameraState)), FloatNear(fovRadians, 0.001f));
}
{
const float fovRadians = AZ::DegToRad(90.0f);
AzFramework::SetCameraClippingVolume(cameraState, 0.1f, 100.0f, fovRadians);
EXPECT_THAT(AzFramework::RetrieveFov(AzFramework::CameraProjection(cameraState)), FloatNear(fovRadians, 0.001f));
}
}
} // namespace UnitTest