Merge branch 'main' into ly-as-sdk/LYN-2948
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzFramework/Entity/EntityContextBus.h>
|
||||
#include <AzFramework/Render/GeometryIntersectionStructures.h>
|
||||
|
||||
namespace AzFramework
|
||||
@@ -35,12 +36,12 @@ namespace AzFramework
|
||||
AzFramework::EntityContextId m_contextId;
|
||||
};
|
||||
|
||||
//! Interface for intersection requests, implement this interface for making your component
|
||||
//! render geometry intersectable.
|
||||
//! Interface for intersection requests.
|
||||
//! Implement this interface to make your component 'intersectable'.
|
||||
class IntersectionRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
//! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus
|
||||
//! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus
|
||||
//! so it updates the internal data of the entities
|
||||
template<class Bus>
|
||||
struct IntersectionRequestsConnectionPolicy
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace AzFramework
|
||||
z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
|
||||
}
|
||||
|
||||
return {x, y, z};
|
||||
return { x, y, z };
|
||||
}
|
||||
|
||||
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
|
||||
@@ -179,7 +179,7 @@ namespace AzFramework
|
||||
{
|
||||
const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime);
|
||||
|
||||
m_motionDelta = ScreenVector{0, 0};
|
||||
m_motionDelta = ScreenVector{ 0, 0 };
|
||||
m_scrollDelta = 0.0f;
|
||||
|
||||
return nextCamera;
|
||||
@@ -213,7 +213,10 @@ namespace AzFramework
|
||||
auto& cameraInput = m_idleCameraInputs[i];
|
||||
const bool canBegin = cameraInput->Beginning() &&
|
||||
AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
|
||||
[](const auto& input) { return !input->Exclusive(); }) &&
|
||||
[](const auto& input)
|
||||
{
|
||||
return !input->Exclusive();
|
||||
}) &&
|
||||
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
|
||||
|
||||
if (canBegin)
|
||||
@@ -231,7 +234,8 @@ namespace AzFramework
|
||||
|
||||
const Camera nextCamera = AZStd::accumulate(
|
||||
AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera,
|
||||
[cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) {
|
||||
[cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera)
|
||||
{
|
||||
acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime);
|
||||
return acc;
|
||||
});
|
||||
@@ -284,7 +288,8 @@ namespace AzFramework
|
||||
|
||||
bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
|
||||
{
|
||||
const ClickDetector::ClickEvent clickEvent = [&event, this] {
|
||||
const ClickDetector::ClickEvent clickEvent = [&event, this]
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_rotateChannelId)
|
||||
@@ -330,7 +335,10 @@ namespace AzFramework
|
||||
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
|
||||
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
|
||||
|
||||
const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
const auto clampRotation = [](const float angle)
|
||||
{
|
||||
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
|
||||
};
|
||||
|
||||
nextCamera.m_yaw = clampRotation(nextCamera.m_yaw);
|
||||
// clamp pitch to be +-90 degrees
|
||||
@@ -377,9 +385,10 @@ namespace AzFramework
|
||||
const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed;
|
||||
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed;
|
||||
|
||||
const auto inv = [](const bool invert) {
|
||||
constexpr float Dir[] = {1.0f, -1.0f};
|
||||
return Dir[static_cast<int>(invert)];
|
||||
const auto inv = [](const bool invert)
|
||||
{
|
||||
constexpr float Dir[] = { 1.0f, -1.0f };
|
||||
return Dir[aznumeric_cast<int>(invert)];
|
||||
};
|
||||
|
||||
nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX);
|
||||
@@ -475,7 +484,8 @@ namespace AzFramework
|
||||
const auto axisY = translationBasis.GetBasisY();
|
||||
const auto axisZ = translationBasis.GetBasisZ();
|
||||
|
||||
const float speed = [boost = m_boost]() {
|
||||
const float speed = [boost = m_boost]()
|
||||
{
|
||||
return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f);
|
||||
}();
|
||||
|
||||
@@ -555,10 +565,12 @@ namespace AzFramework
|
||||
|
||||
if (Beginning())
|
||||
{
|
||||
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] {
|
||||
const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn]
|
||||
{
|
||||
if (lookAtFn)
|
||||
{
|
||||
if (const auto lookAt = lookAtFn())
|
||||
// pass through the camera's position and look vector for use in the lookAt function
|
||||
if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY()))
|
||||
{
|
||||
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
|
||||
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
|
||||
@@ -692,14 +704,20 @@ namespace AzFramework
|
||||
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime)
|
||||
{
|
||||
const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
const auto clamp_rotation = [](const float angle)
|
||||
{
|
||||
return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi);
|
||||
};
|
||||
|
||||
// keep yaw in 0 - 360 range
|
||||
float targetYaw = clamp_rotation(targetCamera.m_yaw);
|
||||
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
|
||||
|
||||
// return the sign of the float input (-1, 0, 1)
|
||||
const auto sign = [](const float value) { return aznumeric_cast<float>((0.0f < value) - (value < 0.0f)); };
|
||||
const auto sign = [](const float value)
|
||||
{
|
||||
return aznumeric_cast<float>((0.0f < value) - (value < 0.0f));
|
||||
};
|
||||
|
||||
// ensure smooth transition when moving across 0 - 360 boundary
|
||||
const float yawDelta = targetYaw - currentYaw;
|
||||
@@ -727,26 +745,28 @@ namespace AzFramework
|
||||
const auto& inputChannelId = inputChannel.GetInputChannelId();
|
||||
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
|
||||
|
||||
const bool wasMouseButton =
|
||||
AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) {
|
||||
const bool wasMouseButton = AZStd::any_of(
|
||||
InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(),
|
||||
[inputChannelId](const auto& button)
|
||||
{
|
||||
return button == inputChannelId;
|
||||
});
|
||||
|
||||
if (inputChannelId == InputDeviceMouse::Movement::X)
|
||||
{
|
||||
return HorizontalMotionEvent{(int)inputChannel.GetValue()};
|
||||
return HorizontalMotionEvent{ aznumeric_cast<int>(inputChannel.GetValue()) };
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
return VerticalMotionEvent{(int)inputChannel.GetValue()};
|
||||
return VerticalMotionEvent{ aznumeric_cast<int>(inputChannel.GetValue()) };
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
return ScrollEvent{inputChannel.GetValue()};
|
||||
return ScrollEvent{ inputChannel.GetValue() };
|
||||
}
|
||||
else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
|
||||
return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() };
|
||||
}
|
||||
|
||||
return AZStd::monostate{};
|
||||
|
||||
@@ -34,9 +34,9 @@ namespace AzFramework
|
||||
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
|
||||
//!< or position of m_lookAt when m_lookDist is greater
|
||||
//!< than zero.
|
||||
float m_yaw{0.0};
|
||||
float m_pitch{0.0};
|
||||
float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
|
||||
float m_yaw{ 0.0 };
|
||||
float m_pitch{ 0.0 };
|
||||
float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt
|
||||
|
||||
//! View camera transform (v in MVP).
|
||||
AZ::Transform View() const;
|
||||
@@ -195,7 +195,11 @@ namespace AzFramework
|
||||
inline bool Cameras::Exclusive() const
|
||||
{
|
||||
return AZStd::any_of(
|
||||
m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); });
|
||||
m_activeCameraInputs.begin(), m_activeCameraInputs.end(),
|
||||
[](const auto& cameraInput)
|
||||
{
|
||||
return cameraInput->Exclusive();
|
||||
});
|
||||
}
|
||||
|
||||
//! Responsible for updating a series of cameras given various inputs.
|
||||
@@ -209,7 +213,7 @@ namespace AzFramework
|
||||
|
||||
private:
|
||||
ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional.
|
||||
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
|
||||
float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional.
|
||||
};
|
||||
|
||||
class RotateCameraInput : public CameraInput
|
||||
@@ -237,7 +241,7 @@ namespace AzFramework
|
||||
inline PanAxes LookPan(const Camera& camera)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
return {orientation.GetBasisX(), orientation.GetBasisZ()};
|
||||
return { orientation.GetBasisX(), orientation.GetBasisZ() };
|
||||
}
|
||||
|
||||
inline PanAxes OrbitPan(const Camera& camera)
|
||||
@@ -245,12 +249,13 @@ namespace AzFramework
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
const auto basisX = orientation.GetBasisX();
|
||||
const auto basisY = [&orientation] {
|
||||
const auto basisY = [&orientation]
|
||||
{
|
||||
const auto forward = orientation.GetBasisY();
|
||||
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
|
||||
}();
|
||||
|
||||
return {basisX, basisY};
|
||||
return { basisX, basisY };
|
||||
}
|
||||
|
||||
class PanCameraInput : public CameraInput
|
||||
@@ -285,7 +290,8 @@ namespace AzFramework
|
||||
const AZ::Matrix3x3 orientation = camera.Rotation();
|
||||
|
||||
const auto basisX = orientation.GetBasisX();
|
||||
const auto basisY = [&orientation] {
|
||||
const auto basisY = [&orientation]
|
||||
{
|
||||
const auto forward = orientation.GetBasisY();
|
||||
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
|
||||
}();
|
||||
@@ -398,7 +404,7 @@ namespace AzFramework
|
||||
class OrbitCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>()>;
|
||||
using LookAtFn = AZStd::function<AZStd::optional<AZ::Vector3>(const AZ::Vector3& position, const AZ::Vector3& direction)>;
|
||||
|
||||
// CameraInput overrides ...
|
||||
bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
|
||||
|
||||
+18
-11
@@ -57,7 +57,6 @@ namespace AzToolsFramework
|
||||
"Couldn't get prefab loader interface, it's a requirement for PrefabEntityOwnership system to work");
|
||||
|
||||
m_rootInstance = AZStd::unique_ptr<Prefab::Instance>(m_prefabSystemComponent->CreatePrefab({}, {}, "NewLevel.prefab"));
|
||||
|
||||
m_sliceOwnershipService.BusConnect(m_entityContextId);
|
||||
m_sliceOwnershipService.m_shouldAssertForLegacySlicesUsage = m_shouldAssertForLegacySlicesUsage;
|
||||
m_editorSliceOwnershipService.BusConnect();
|
||||
@@ -91,14 +90,17 @@ namespace AzToolsFramework
|
||||
|
||||
void PrefabEditorEntityOwnershipService::Reset()
|
||||
{
|
||||
Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
|
||||
if (templateId != Prefab::InvalidTemplateId)
|
||||
if (m_rootInstance)
|
||||
{
|
||||
m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
|
||||
m_prefabSystemComponent->RemoveTemplate(templateId);
|
||||
Prefab::TemplateId templateId = m_rootInstance->GetTemplateId();
|
||||
if (templateId != Prefab::InvalidTemplateId)
|
||||
{
|
||||
m_rootInstance->SetTemplateId(Prefab::InvalidTemplateId);
|
||||
m_prefabSystemComponent->RemoveTemplate(templateId);
|
||||
}
|
||||
m_rootInstance->Reset();
|
||||
m_rootInstance->SetContainerEntityName("Level");
|
||||
}
|
||||
m_rootInstance->Reset();
|
||||
m_rootInstance->SetContainerEntityName("Level");
|
||||
|
||||
AzFramework::EntityOwnershipServiceNotificationBus::Event(
|
||||
m_entityContextId, &AzFramework::EntityOwnershipServiceNotificationBus::Events::OnEntityOwnershipServiceReset);
|
||||
@@ -202,7 +204,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
m_rootInstance->SetTemplateId(templateId);
|
||||
m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GetRelativePathToProject(filename));
|
||||
m_rootInstance->SetTemplateSourcePath(m_loaderInterface->GenerateRelativePath(filename));
|
||||
m_rootInstance->SetContainerEntityName("Level");
|
||||
m_prefabSystemComponent->PropagateTemplateChanges(templateId);
|
||||
|
||||
@@ -220,7 +222,7 @@ namespace AzToolsFramework
|
||||
|
||||
bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename)
|
||||
{
|
||||
AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
|
||||
AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
|
||||
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
|
||||
|
||||
m_rootInstance->SetTemplateSourcePath(relativePath);
|
||||
@@ -267,7 +269,7 @@ namespace AzToolsFramework
|
||||
|
||||
void PrefabEditorEntityOwnershipService::CreateNewLevelPrefab(AZStd::string_view filename, const AZStd::string& templateFilename)
|
||||
{
|
||||
AZ::IO::Path relativePath = m_loaderInterface->GetRelativePathToProject(filename);
|
||||
AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
|
||||
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
|
||||
|
||||
m_rootInstance->SetTemplateSourcePath(relativePath);
|
||||
@@ -378,7 +380,12 @@ namespace AzToolsFramework
|
||||
Prefab::InstanceOptionalReference PrefabEditorEntityOwnershipService::GetRootPrefabInstance()
|
||||
{
|
||||
AZ_Assert(m_rootInstance, "A valid root prefab instance couldn't be found in PrefabEditorEntityOwnershipService.");
|
||||
return *m_rootInstance;
|
||||
if (m_rootInstance)
|
||||
{
|
||||
return *m_rootInstance;
|
||||
}
|
||||
|
||||
return AZStd::nullopt;
|
||||
}
|
||||
|
||||
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& PrefabEditorEntityOwnershipService::GetPlayInEditorAssetData()
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ namespace AzToolsFramework
|
||||
"PrefabLoaderInterface could not be found. It is required to load Prefab Instances");
|
||||
|
||||
// Make sure we have a relative path
|
||||
instance->m_templateSourcePath = loaderInterface->GetRelativePathToProject(instance->m_templateSourcePath);
|
||||
instance->m_templateSourcePath = loaderInterface->GenerateRelativePath(instance->m_templateSourcePath);
|
||||
|
||||
TemplateId templateId = prefabSystemComponentInterface->GetTemplateIdFromFilePath(instance->GetTemplateSourcePath());
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzFramework/FileFunc/FileFunc.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
|
||||
@@ -112,7 +114,7 @@ namespace AzToolsFramework
|
||||
return InvalidTemplateId;
|
||||
}
|
||||
|
||||
AZ::IO::Path relativePath = GetRelativePathToProject(originPath);
|
||||
AZ::IO::Path relativePath = GenerateRelativePath(originPath);
|
||||
|
||||
// Cyclical dependency detected if the prefab file is already part of the progressed
|
||||
// file path set.
|
||||
@@ -385,21 +387,100 @@ namespace AzToolsFramework
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path).MakePreferred();
|
||||
if (pathWithOSSeparator.IsAbsolute())
|
||||
{
|
||||
// If an absolute path was passed in, just return it as-is.
|
||||
return path;
|
||||
}
|
||||
|
||||
return AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
|
||||
// A relative path was passed in, so try to turn it back into an absolute path.
|
||||
|
||||
AZ::IO::Path fullPath;
|
||||
|
||||
bool pathFound = false;
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
AZStd::string rootFolder;
|
||||
AZStd::string inputPath(path.Native());
|
||||
|
||||
// Given an input path that's expected to exist, try to look it up.
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath,
|
||||
inputPath.c_str(), assetInfo, rootFolder);
|
||||
|
||||
if (pathFound)
|
||||
{
|
||||
// The asset system provided us with a valid root folder and relative path, so return it.
|
||||
fullPath = AZ::IO::Path(rootFolder) / assetInfo.m_relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
|
||||
|
||||
// Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
|
||||
// the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
|
||||
// a unit test, so just execute the fallback logic without an error.
|
||||
[[maybe_unused]] bool assetProcessorReady = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
|
||||
|
||||
AZ_Error(
|
||||
"Prefab", !assetProcessorReady, "Full source path for '%.*s' could not be determined. Using fallback logic.",
|
||||
AZ_STRING_ARG(path.Native()));
|
||||
|
||||
// If a relative path was passed in, make it relative to the project root.
|
||||
fullPath = AZ::IO::Path(m_projectPathWithOsSeparator).Append(pathWithOSSeparator);
|
||||
}
|
||||
|
||||
return fullPath;
|
||||
}
|
||||
|
||||
AZ::IO::Path PrefabLoader::GetRelativePathToProject(AZ::IO::PathView path)
|
||||
AZ::IO::Path PrefabLoader::GenerateRelativePath(AZ::IO::PathView path)
|
||||
{
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
|
||||
if (!pathWithOSSeparator.IsAbsolute())
|
||||
bool pathFound = false;
|
||||
|
||||
AZStd::string relativePath;
|
||||
AZStd::string rootFolder;
|
||||
AZ::IO::Path finalPath;
|
||||
|
||||
// The asset system allows for paths to be relative to multiple root folders, using a priority system.
|
||||
// This request will make the input path relative to the most appropriate, highest-priority root folder.
|
||||
AzToolsFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
pathFound, &AzToolsFramework::AssetSystemRequestBus::Events::GenerateRelativeSourcePath, path.Native(),
|
||||
relativePath, rootFolder);
|
||||
|
||||
if (pathFound && !relativePath.empty())
|
||||
{
|
||||
return path;
|
||||
// A relative path was generated successfully, so return it.
|
||||
finalPath = relativePath;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If for some reason the Asset system couldn't provide a relative path, provide some fallback logic.
|
||||
|
||||
// Check to see if the AssetProcessor is ready. If it *is* and we didn't get a path, print an error then follow
|
||||
// the fallback logic. If it's *not* ready, we're probably either extremely early in a tool startup flow or inside
|
||||
// a unit test, so just execute the fallback logic without an error.
|
||||
[[maybe_unused]] bool assetProcessorReady = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
assetProcessorReady, &AzFramework::AssetSystemRequestBus::Events::AssetProcessorIsReady);
|
||||
|
||||
AZ_Error("Prefab", !assetProcessorReady,
|
||||
"Relative source path for '%.*s' could not be determined. Using project path as relative root.",
|
||||
AZ_STRING_ARG(path.Native()));
|
||||
|
||||
AZ::IO::Path pathWithOSSeparator = AZ::IO::Path(path.Native()).MakePreferred();
|
||||
|
||||
if (pathWithOSSeparator.IsAbsolute())
|
||||
{
|
||||
// If an absolute path was passed in, make it relative to the project path.
|
||||
finalPath = AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a relative path was passed in, just return it.
|
||||
finalPath = path;
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::IO::Path(path.Native(), '/').MakePreferred().LexicallyRelative(m_projectPathWithSlashSeparator);
|
||||
return finalPath;
|
||||
}
|
||||
|
||||
AZ::IO::Path PrefabLoaderInterface::GeneratePath()
|
||||
|
||||
@@ -91,9 +91,11 @@ namespace AzToolsFramework
|
||||
//! The path will always have the correct separator for the current OS
|
||||
AZ::IO::Path GetFullPath(AZ::IO::PathView path) override;
|
||||
|
||||
//! Converts path into a relative path to the project, this will be the paths in .prefab file.
|
||||
//! The path will always have '/' separator.
|
||||
AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) override;
|
||||
//! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
|
||||
//! with the engine.
|
||||
//! This path will be the path that appears in the .prefab file.
|
||||
//! The path will always use the '/' separator.
|
||||
AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) override;
|
||||
|
||||
//! Returns if the path is a valid path for a prefab
|
||||
static bool IsValidPrefabPath(AZ::IO::PathView path);
|
||||
|
||||
@@ -74,9 +74,11 @@ namespace AzToolsFramework
|
||||
//! The path will always have the correct separator for the current OS
|
||||
virtual AZ::IO::Path GetFullPath(AZ::IO::PathView path) = 0;
|
||||
|
||||
//! Converts path into a relative path to the current project, this will be the paths in .prefab file.
|
||||
//! The path will always have '/' separator.
|
||||
virtual AZ::IO::Path GetRelativePathToProject(AZ::IO::PathView path) = 0;
|
||||
//! Converts path into a path that's relative to the highest-priority containing folder of all the folders registered
|
||||
//! with the engine.
|
||||
//! This path will be the path that appears in the .prefab file.
|
||||
//! The path will always use the '/' separator.
|
||||
virtual AZ::IO::Path GenerateRelativePath(AZ::IO::PathView path) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
//Detect whether this instantiation would produce a cyclical dependency
|
||||
auto relativePath = m_prefabLoaderInterface->GetRelativePathToProject(filePath);
|
||||
auto relativePath = m_prefabLoaderInterface->GenerateRelativePath(filePath);
|
||||
Prefab::TemplateId templateId = m_prefabSystemComponentInterface->GetTemplateIdFromFilePath(relativePath);
|
||||
|
||||
if (templateId == InvalidTemplateId)
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace AzToolsFramework
|
||||
const AZStd::vector<AZ::Entity*>& entities, AZStd::vector<AZStd::unique_ptr<Instance>>&& instancesToConsume,
|
||||
AZ::IO::PathView filePath, AZStd::unique_ptr<AZ::Entity> containerEntity, bool shouldCreateLinks)
|
||||
{
|
||||
AZ::IO::Path relativeFilePath = m_prefabLoader.GetRelativePathToProject(filePath);
|
||||
AZ::IO::Path relativeFilePath = m_prefabLoader.GenerateRelativePath(filePath);
|
||||
if (GetTemplateIdFromFilePath(relativeFilePath) != InvalidTemplateId)
|
||||
{
|
||||
AZ_Error("Prefab", false,
|
||||
|
||||
+2
-1
@@ -333,7 +333,8 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(selectedEntities, s_prefabLoaderInterface->GetRelativePathToProject(prefabFilePath.data()));
|
||||
auto createPrefabOutcome = s_prefabPublicInterface->CreatePrefab(
|
||||
selectedEntities, s_prefabLoaderInterface->GenerateRelativePath(prefabFilePath.data()));
|
||||
|
||||
if (!createPrefabOutcome.IsSuccess())
|
||||
{
|
||||
|
||||
@@ -1221,50 +1221,73 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
AzFramework::ReloadCameraKeyBindings();
|
||||
|
||||
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
|
||||
controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras)
|
||||
{
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
|
||||
auto firstPersonPanCamera =
|
||||
AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::CameraFreePanButton, AzFramework::LookPan);
|
||||
auto firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation);
|
||||
auto firstPersonWheelCamera = AZStd::make_shared<AzFramework::ScrollTranslationCameraInput>();
|
||||
controller->SetCameraListBuilderCallback(
|
||||
[](AzFramework::Cameras& cameras)
|
||||
{
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
|
||||
auto firstPersonPanCamera =
|
||||
AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::CameraFreePanButton, AzFramework::LookPan);
|
||||
auto firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation);
|
||||
auto firstPersonWheelCamera = AZStd::make_shared<AzFramework::ScrollTranslationCameraInput>();
|
||||
|
||||
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
|
||||
orbitCamera->SetLookAtFn([]() -> AZStd::optional<AZ::Vector3> {
|
||||
AZStd::optional<AZ::Transform> manipulatorTransform;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
|
||||
orbitCamera->SetLookAtFn(
|
||||
[](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional<AZ::Vector3>
|
||||
{
|
||||
AZStd::optional<AZ::Transform> manipulatorTransform;
|
||||
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
|
||||
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
|
||||
|
||||
if (manipulatorTransform)
|
||||
{
|
||||
return manipulatorTransform->GetTranslation();
|
||||
}
|
||||
// initially attempt to use manipulator transform if one exists (there is a selection)
|
||||
if (manipulatorTransform)
|
||||
{
|
||||
return manipulatorTransform->GetTranslation();
|
||||
}
|
||||
|
||||
return {};
|
||||
const float RayDistance = 1000.0f;
|
||||
AzFramework::RenderGeometry::RayRequest ray;
|
||||
ray.m_startWorldPosition = position;
|
||||
ray.m_endWorldPosition = position + direction * RayDistance;
|
||||
ray.m_onlyVisible = true;
|
||||
|
||||
AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult;
|
||||
AzFramework::RenderGeometry::IntersectorBus::EventResult(
|
||||
renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(),
|
||||
&AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray);
|
||||
|
||||
// attempt a ray intersection with any visible mesh and return the intersection position if successful
|
||||
if (renderGeometryIntersectionResult)
|
||||
{
|
||||
return renderGeometryIntersectionResult.m_worldPosition;
|
||||
}
|
||||
|
||||
// if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane
|
||||
// intersection)
|
||||
return {};
|
||||
});
|
||||
|
||||
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraOrbitLookButton);
|
||||
auto orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation);
|
||||
auto orbitDollyWheelCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
|
||||
auto orbitDollyMoveCamera =
|
||||
AZStd::make_shared<AzFramework::OrbitDollyCursorMoveCameraInput>(AzFramework::CameraOrbitDollyButton);
|
||||
auto orbitPanCamera =
|
||||
AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
|
||||
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
|
||||
|
||||
cameras.AddCamera(firstPersonRotateCamera);
|
||||
cameras.AddCamera(firstPersonPanCamera);
|
||||
cameras.AddCamera(firstPersonTranslateCamera);
|
||||
cameras.AddCamera(firstPersonWheelCamera);
|
||||
cameras.AddCamera(orbitCamera);
|
||||
});
|
||||
|
||||
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraOrbitLookButton);
|
||||
auto orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation);
|
||||
auto orbitDollyWheelCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
|
||||
auto orbitDollyMoveCamera =
|
||||
AZStd::make_shared<AzFramework::OrbitDollyCursorMoveCameraInput>(AzFramework::CameraOrbitDollyButton);
|
||||
auto orbitPanCamera =
|
||||
AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan);
|
||||
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
|
||||
orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
|
||||
|
||||
cameras.AddCamera(firstPersonRotateCamera);
|
||||
cameras.AddCamera(firstPersonPanCamera);
|
||||
cameras.AddCamera(firstPersonTranslateCamera);
|
||||
cameras.AddCamera(firstPersonWheelCamera);
|
||||
cameras.AddCamera(orbitCamera);
|
||||
});
|
||||
|
||||
m_renderViewport->GetControllerList()->Add(controller);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
return SavePrefab(templateId);
|
||||
return SavePrefab(outputPath, templateId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace AZ
|
||||
nestedPrefabPath.ReplaceExtension("prefab");
|
||||
|
||||
auto prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
nestedPrefabPath = prefabLoaderInterface->GetRelativePathToProject(nestedPrefabPath);
|
||||
nestedPrefabPath = prefabLoaderInterface->GenerateRelativePath(nestedPrefabPath);
|
||||
|
||||
AzToolsFramework::Prefab::TemplateId nestedTemplateId =
|
||||
prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath);
|
||||
@@ -439,17 +439,31 @@ namespace AZ
|
||||
AZ::Debug::Trace::Instance().Output("", "\n");
|
||||
}
|
||||
|
||||
bool SliceConverter::SavePrefab(AzToolsFramework::Prefab::TemplateId templateId)
|
||||
bool SliceConverter::SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId)
|
||||
{
|
||||
auto prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
|
||||
if (!prefabLoaderInterface->SaveTemplate(templateId))
|
||||
AZStd::string out;
|
||||
if (prefabLoaderInterface->SaveTemplateToString(templateId, out))
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n");
|
||||
return false;
|
||||
IO::SystemFile outputFile;
|
||||
if (!outputFile.Open(
|
||||
AZStd::string(outputPath.Native()).c_str(),
|
||||
IO::SystemFile::OpenMode::SF_OPEN_CREATE |
|
||||
IO::SystemFile::OpenMode::SF_OPEN_CREATE_PATH |
|
||||
IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY))
|
||||
{
|
||||
AZ_Error("Convert-Slice", false, " Unable to create output file '%.*s'.", AZ_STRING_ARG(outputPath.Native()));
|
||||
return false;
|
||||
}
|
||||
|
||||
outputFile.Write(out.data(), out.size());
|
||||
outputFile.Close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
AZ_Printf("Convert-Slice", " Could not save prefab - internal error (Json write operation failure).\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SliceConverter::ConnectToAssetProcessor()
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace AZ
|
||||
AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance);
|
||||
static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
static bool SavePrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
static bool SavePrefab(AZ::IO::PathView outputPath, AzToolsFramework::Prefab::TemplateId templateId);
|
||||
};
|
||||
} // namespace SerializeContextTools
|
||||
} // namespace AZ
|
||||
|
||||
Reference in New Issue
Block a user