Merge branch 'development' into Atom/guthadam/atomtools_updating_cmake_config

This commit is contained in:
Guthrie Adams
2021-09-08 17:16:54 -05:00
63 changed files with 1635 additions and 305 deletions
@@ -7,8 +7,10 @@ SPDX-License-Identifier: Apache-2.0 OR MIT
Tests that require a GPU in order to run.
"""
import datetime
import logging
import os
import zipfile
import pytest
@@ -40,6 +42,33 @@ def golden_images_directory():
return golden_images_dir
def create_screenshots_archive(screenshot_path):
"""
Creates a new zip file archive at archive_path containing all files listed within archive_path.
:param screenshot_path: location containing the files to archive, the zip archive file will also be saved here.
:return: None, but creates a new zip file archive inside path containing all of the files inside archive_path.
"""
files_to_archive = []
# Search for .png and .ppm files to add to the zip archive file.
for (folder_name, sub_folders, file_names) in os.walk(screenshot_path):
for file_name in file_names:
if file_name.endswith(".png") or file_name.endswith(".ppm"):
file_path = os.path.join(folder_name, file_name)
files_to_archive.append(file_path)
# Setup variables for naming the zip archive file.
timestamp = datetime.datetime.now().timestamp()
formatted_timestamp = datetime.datetime.utcfromtimestamp(timestamp).strftime("%Y-%m-%d_%H-%M-%S")
screenshots_file = os.path.join(screenshot_path, f'zip_archive_{formatted_timestamp}.zip')
# Write all of the valid .png and .ppm files to the archive file.
with zipfile.ZipFile(screenshots_file, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zip_archive:
for file_path in files_to_archive:
file_name = os.path.basename(file_path)
zip_archive.write(file_path, file_name)
@pytest.mark.parametrize("project", ["AutomatedTesting"])
@pytest.mark.parametrize("launcher_platform", ["windows_editor"])
@pytest.mark.parametrize("level", ["auto_test"])
@@ -53,8 +82,8 @@ class TestAllComponentsIndepthTests(object):
Tests that a basic rendering level setup can be created (lighting, meshes, materials, etc.).
"""
# Clear existing test screenshots before starting test.
test_screenshots = [os.path.join(
workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot_name)]
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
test_screenshots = [os.path.join(screenshot_directory, screenshot_name)]
file_system.delete(test_screenshots, True, True)
golden_images = [os.path.join(golden_images_directory(), screenshot_name)]
@@ -86,6 +115,8 @@ class TestAllComponentsIndepthTests(object):
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
compare_screenshots(test_screenshot, golden_screenshot)
create_screenshots_archive(screenshot_directory)
def test_LightComponent_ScreenshotMatchesGoldenImage(
self, request, editor, workspace, project, launcher_platform, level):
"""
@@ -105,9 +136,10 @@ class TestAllComponentsIndepthTests(object):
"SpotLight_5.ppm",
"SpotLight_6.ppm",
]
screenshot_directory = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH)
test_screenshots = []
for screenshot in screenshot_names:
screenshot_path = os.path.join(workspace.paths.project(), DEFAULT_SUBFOLDER_PATH, screenshot)
screenshot_path = os.path.join(screenshot_directory, screenshot)
test_screenshots.append(screenshot_path)
file_system.delete(test_screenshots, True, True)
@@ -139,6 +171,8 @@ class TestAllComponentsIndepthTests(object):
for test_screenshot, golden_screenshot in zip(test_screenshots, golden_images):
compare_screenshots(test_screenshot, golden_screenshot)
create_screenshots_archive(screenshot_directory)
@pytest.mark.parametrize('rhi', ['dx12', 'vulkan'])
@pytest.mark.parametrize("project", ["AutomatedTesting"])
+2
View File
@@ -1087,6 +1087,7 @@ void EditorViewportWidget::ConnectViewportInteractionRequestBus()
{
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusConnect(GetViewportId());
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(GetViewportId());
m_viewportUi.ConnectViewportUiBus(GetViewportId());
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusConnect();
@@ -1097,6 +1098,7 @@ void EditorViewportWidget::DisconnectViewportInteractionRequestBus()
AzFramework::InputSystemCursorConstraintRequestBus::Handler::BusDisconnect();
m_viewportUi.DisconnectViewportUiBus();
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler::BusDisconnect();
}
+17 -11
View File
@@ -91,6 +91,7 @@ class SANDBOX_API EditorViewportWidget final
, private AzFramework::InputSystemCursorConstraintRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
, private AzFramework::AssetCatalogEventBus::Handler
, private AZ::RPI::SceneNotificationBus::Handler
{
@@ -128,10 +129,12 @@ private:
CameraComponent,
ViewSourceTypesCount,
};
enum class PlayInEditorState
{
Editor, Starting, Started
};
enum class KeyPressedState
{
AllUp,
@@ -142,7 +145,7 @@ private:
////////////////////////////////////////////////////////////////////////
// Method overrides ...
// QWidget
// QWidget overrides ...
void focusOutEvent(QFocusEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
bool event(QEvent* event) override;
@@ -150,7 +153,7 @@ private:
void paintEvent(QPaintEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
// QtViewport/IDisplayViewport/CViewport
// QtViewport/IDisplayViewport/CViewport overrides ...
EViewportType GetType() const override { return ET_ViewportCamera; }
void SetType([[maybe_unused]] EViewportType type) override { assert(type == ET_ViewportCamera); };
AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction(
@@ -176,16 +179,17 @@ private:
void Update() override;
void UpdateContent(int flags) override;
// SceneNotificationBus
// SceneNotificationBus overrides ...
void OnBeginPrepareRender() override;
// Camera::CameraNotificationBus
// Camera::CameraNotificationBus overrides ...
void OnActiveViewChanged(const AZ::EntityId&) override;
// IEditorEventListener
// IEditorEventListener overrides ...
void OnEditorNotifyEvent(EEditorNotifyEvent event) override;
// AzToolsFramework::EditorEntityContextNotificationBus (handler moved to cpp to resolve link issues in unity builds)
// AzToolsFramework::EditorEntityContextNotificationBus overrides ...
// note: handler moved to cpp to resolve link issues in unity builds
void OnStartPlayInEditor();
void OnStopPlayInEditor();
void OnStartPlayInEditorBegin();
@@ -194,10 +198,10 @@ private:
void BeginUndoTransaction() override;
void EndUndoTransaction() override;
// AzFramework::InputSystemCursorConstraintRequestBus
// AzFramework::InputSystemCursorConstraintRequestBus overrides ...
void* GetSystemCursorConstraintWindow() const override;
// AzToolsFramework::ViewportFreezeRequestBus
// AzToolsFramework::ViewportFreezeRequestBus overrides ...
bool IsViewportInputFrozen() override;
void FreezeViewportInput(bool freeze) override;
@@ -205,13 +209,15 @@ private:
AZ::EntityId PickEntity(const AzFramework::ScreenPoint& point) override;
AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) override;
float TerrainHeight(const AZ::Vector2& position) override;
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut) override;
bool ShowingWorldSpace() override;
QWidget* GetWidgetForViewportContextMenu() override;
void BeginWidgetContext() override;
void EndWidgetContext() override;
// Camera::EditorCameraRequestBus
// EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
// Camera::EditorCameraRequestBus overrides ...
void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override;
void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override;
AZ::EntityId GetCurrentViewEntityId() override;
@@ -327,7 +333,7 @@ private:
// Determines also if the current camera for this viewport is default editor camera
ViewSourceType m_viewSourceType = ViewSourceType::None;
// During play game in editor, holds the editor entity ID of the last
// During play game in editor, holds the editor entity ID of the last
AZ::EntityId m_viewEntityIdCachedForEditMode;
// The editor camera TM before switching to game mode
+2 -3
View File
@@ -1092,9 +1092,8 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
const int viewportId = GetViewportId();
AzToolsFramework::EntityIdList visibleEntityIds;
AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
viewportId,
&AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequests::FindVisibleEntities,
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
viewportId, &AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
visibleEntityIds);
// Look through all visible entities to find the closest one to the specified mouse point
@@ -14,6 +14,7 @@
#include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Math/Vector4.h>
#include <AzCore/Math/Matrix3x4.h>
#include <AzCore/Math/Color.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Component/ComponentBus.h>
@@ -100,6 +101,8 @@ namespace AzFramework
virtual AZ::u32 SetState(AZ::u32 state) { (void)state; return 0; }
virtual void PushMatrix(const AZ::Transform& tm) { (void)tm; }
virtual void PopMatrix() {}
virtual void PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) { (void)matrix; }
virtual AZ::Matrix3x4 PopPremultipliedMatrix() { return AZ::Matrix3x4::CreateIdentity(); }
protected:
~DebugDisplayRequests() = default;
@@ -588,6 +588,12 @@ namespace AzFramework
// 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()))
{
// default to internal look at behavior if the look at point matches the camera translation
if (targetCamera.m_lookAt.IsClose(*lookAt))
{
return false;
}
auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt);
nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt);
UpdateCameraFromTransform(nextCamera, transform);
@@ -45,6 +45,7 @@ namespace AzFramework
protected:
~BoundsRequests() = default;
};
using BoundsRequestBus = AZ::EBus<BoundsRequests>;
//! Returns a union of all local Aabbs provided by components implementing the BoundsRequestBus.
@@ -6,6 +6,7 @@
*
*/
#include <AZTestShared/Math/MathTestHelpers.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
@@ -47,18 +48,17 @@ namespace UnitTest
m_firstPersonTranslateCamera =
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation, m_translateCameraInputChannelIds);
auto orbitCamera =
AZStd::make_shared<AzFramework::OrbitCameraInput>(AzFramework::InputChannelId("keyboard_key_modifier_alt_l"));
m_orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>(m_orbitChannelId);
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
auto orbitTranslateCamera =
AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation, m_translateCameraInputChannelIds);
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
m_orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
m_orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
m_cameraSystem->m_cameras.AddCamera(m_firstPersonRotateCamera);
m_cameraSystem->m_cameras.AddCamera(m_firstPersonTranslateCamera);
m_cameraSystem->m_cameras.AddCamera(orbitCamera);
m_cameraSystem->m_cameras.AddCamera(m_orbitCamera);
// these tests rely on using motion delta, not cursor positions (default is true)
AzFramework::ed_cameraSystemUseCursor = false;
@@ -68,6 +68,7 @@ namespace UnitTest
{
AzFramework::ed_cameraSystemUseCursor = true;
m_orbitCamera.reset();
m_firstPersonRotateCamera.reset();
m_firstPersonTranslateCamera.reset();
@@ -77,12 +78,14 @@ namespace UnitTest
AllocatorsTestFixture::TearDown();
}
AzFramework::InputChannelId m_orbitChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l");
AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds;
AZStd::shared_ptr<AzFramework::RotateCameraInput> m_firstPersonRotateCamera;
AZStd::shared_ptr<AzFramework::TranslateCameraInput> m_firstPersonTranslateCamera;
AZStd::shared_ptr<AzFramework::OrbitCameraInput> m_orbitCamera;
};
TEST_F(CameraInputFixture, Begin_and_end_OrbitCameraInput_consumes_correct_events)
TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents)
{
// begin orbit camera
const bool consumed1 = HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceKeyboard::Key::ModifierAltL,
@@ -102,7 +105,7 @@ namespace UnitTest
EXPECT_THAT(allConsumed, ElementsAre(true, false, true, false));
}
TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_for_TranslateCameraInput)
TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnForTranslateCameraInput)
{
bool activationBegan = false;
m_firstPersonTranslateCamera->SetActivationBeganFn(
@@ -111,13 +114,13 @@ namespace UnitTest
activationBegan = true;
});
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
AzFramework::InputChannel::State::Began });
EXPECT_TRUE(activationBegan);
}
TEST_F(CameraInputFixture, Begin_CameraInput_notifies_ActivationBeganFn_after_delta_for_RotateCameraInput)
TEST_F(CameraInputFixture, BeginCameraInputNotifiesActivationBeganFnAfterDeltaForRotateCameraInput)
{
bool activationBegan = false;
m_firstPersonRotateCamera->SetActivationBeganFn(
@@ -133,7 +136,7 @@ namespace UnitTest
EXPECT_TRUE(activationBegan);
}
TEST_F(CameraInputFixture, Begin_CameraInput_does_not_notify_ActivationBeganFn_with_no_delta_for_RotateCameraInput)
TEST_F(CameraInputFixture, BeginCameraInputDoesNotNotifyActivationBeganFnWithNoDeltaForRotateCameraInput)
{
bool activationBegan = false;
m_firstPersonRotateCamera->SetActivationBeganFn(
@@ -148,7 +151,7 @@ namespace UnitTest
EXPECT_FALSE(activationBegan);
}
TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationEndFn_after_delta_for_RotateCameraInput)
TEST_F(CameraInputFixture, EndCameraInputNotifiesActivationEndFnAfterDeltaForRotateCameraInput)
{
bool activationEnded = false;
m_firstPersonRotateCamera->SetActivationEndedFn(
@@ -166,7 +169,7 @@ namespace UnitTest
EXPECT_TRUE(activationEnded);
}
TEST_F(CameraInputFixture, End_CameraInput_does_not_notify_ActivationBeganFn_or_ActivationBeganFn_with_no_delta_for_RotateCameraInput)
TEST_F(CameraInputFixture, EndCameraInputDoesNotNotifyActivationBeganFnOrActivationBeganFnWithNoDeltaForRotateCameraInput)
{
bool activationBegan = false;
m_firstPersonRotateCamera->SetActivationBeganFn(
@@ -191,7 +194,7 @@ namespace UnitTest
EXPECT_FALSE(activationEnded);
}
TEST_F(CameraInputFixture, End_CameraInput_notifies_ActivationBeganFn_or_ActivationEndFn_with_TranslateCamera)
TEST_F(CameraInputFixture, End_CameraInputNotifiesActivationBeganFnOrActivationEndFnWithTranslateCamera)
{
bool activationBegan = false;
m_firstPersonTranslateCamera->SetActivationBeganFn(
@@ -207,16 +210,16 @@ namespace UnitTest
activationEnded = true;
});
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Ended });
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
AzFramework::InputChannel::State::Ended });
EXPECT_TRUE(activationBegan);
EXPECT_TRUE(activationEnded);
}
TEST_F(CameraInputFixture, End_activation_called_for_CameraInput_if_active_when_cameras_are_cleared)
TEST_F(CameraInputFixture, EndActivationCalledForCameraInputIfActiveWhenCamerasAreCleared)
{
bool activationEnded = false;
m_firstPersonTranslateCamera->SetActivationEndedFn(
@@ -225,11 +228,37 @@ namespace UnitTest
activationEnded = true;
});
HandleEventAndUpdate(
AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId, AzFramework::InputChannel::State::Began });
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_translateCameraInputChannelIds.m_forwardChannelId,
AzFramework::InputChannel::State::Began });
m_cameraSystem->m_cameras.Clear();
EXPECT_TRUE(activationEnded);
}
TEST_F(CameraInputFixture, OrbitCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenOrbiting)
{
// create pathological lookAtFn that just returns the same position as the camera
m_orbitCamera->SetLookAtFn(
[](const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction)
{
return position;
});
AzFramework::UpdateCameraFromTransform(
m_targetCamera,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 10.0f, 10.0f)));
m_camera = m_targetCamera;
HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began });
// verify the camera yaw has not changed and the look at point
// does not match that of the camera translation
using ::testing::Eq;
using ::testing::Not;
EXPECT_THAT(m_camera.m_yaw, Eq(AZ::DegToRad(90.0f)));
EXPECT_THAT(m_camera.m_lookAt, Not(IsClose(m_camera.Translation())));
}
} // namespace UnitTest
@@ -45,6 +45,9 @@ namespace AzManipulatorTestFramework
virtual void SetAngularStep(float step) = 0;
//! Get the viewport id.
virtual int GetViewportId() const = 0;
//! Updates the visibility state.
//! Updates which entities are currently visible given the current camera state.
virtual void UpdateVisibility() = 0;
};
//! This interface is used to simulate the manipulator manager while the manipulators are under test.
@@ -12,8 +12,8 @@
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <type_traits>
namespace UnitTest
@@ -21,20 +21,18 @@ namespace UnitTest
//! Fixture to provide the indirect call viewport interaction that is dependent on AzToolsFramework::ToolsApplication.
//! \tparam ToolsApplicationFixtureT The fixture that provides the AzToolsFramework::ToolsApplication functionality.
template<typename ToolsApplicationFixtureT>
class IndirectCallManipulatorViewportInteractionFixtureMixin
: public ToolsApplicationFixtureT
class IndirectCallManipulatorViewportInteractionFixtureMixin : public ToolsApplicationFixtureT
{
using IndirectCallManipulatorViewportInteraction =
AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction;
using IndirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction;
using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher;
void SetUpEditorFixtureImpl() override
{
ToolsApplicationFixtureT::SetUpEditorFixtureImpl();
m_viewportManipulatorInteraction = AZStd::make_unique<IndirectCallManipulatorViewportInteraction>();
m_actionDispatcher = AZStd::make_unique<ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction);
m_cameraState = AzFramework::CreateIdentityDefaultCamera(
AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
m_cameraState =
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
}
void TearDownEditorFixtureImpl() override
@@ -9,8 +9,8 @@
#pragma once
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
namespace AzManipulatorTestFramework
{
@@ -18,13 +18,12 @@ namespace AzManipulatorTestFramework
class IndirectCallManipulatorManager;
//! Implementation of manipulator viewport interaction that manipulates the manager indirectly via bus calls.
class IndirectCallManipulatorViewportInteraction
: public ManipulatorViewportInteraction
class IndirectCallManipulatorViewportInteraction : public ManipulatorViewportInteraction
{
public:
IndirectCallManipulatorViewportInteraction();
~IndirectCallManipulatorViewportInteraction();
// ManipulatorViewportInteractionInterface ...
const ViewportInteractionInterface& GetViewportInteraction() const override;
const ManipulatorManagerInterface& GetManipulatorManager() const override;
@@ -8,6 +8,7 @@
#pragma once
#include <AzFramework/Visibility/EntityVisibilityQuery.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
namespace AzManipulatorTestFramework
@@ -19,6 +20,7 @@ namespace AzManipulatorTestFramework
: public ViewportInteractionInterface
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
{
public:
ViewportInteraction();
@@ -34,6 +36,7 @@ namespace AzManipulatorTestFramework
void SetGridSize(float size) override;
void SetAngularStep(float step) override;
int GetViewportId() const override;
void UpdateVisibility() override;
// ViewportInteractionRequestBus overrides ...
AzFramework::CameraState GetCameraState() override;
@@ -52,7 +55,11 @@ namespace AzManipulatorTestFramework
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
// EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
private:
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
AZStd::unique_ptr<NullDebugDisplayRequests> m_nullDebugDisplayRequests;
const int m_viewportId = 1234; // Arbitrary viewport id for manipulator tests
AzFramework::CameraState m_cameraState;
@@ -91,12 +91,12 @@ namespace AzManipulatorTestFramework
AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(
const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState)
{
const auto screenToWorld = AzFramework::ScreenToWorld(screenPoint, cameraState);
const auto nearPlaneWorldPosition = AzFramework::ScreenToWorld(screenPoint, cameraState);
AzToolsFramework::ViewportInteraction::MousePick mousePick;
mousePick.m_screenCoordinates = screenPoint;
mousePick.m_rayOrigin = screenToWorld;
mousePick.m_rayDirection = (screenToWorld - cameraState.m_position).GetNormalized();
mousePick.m_rayOrigin = cameraState.m_position;
mousePick.m_rayDirection = (nearPlaneWorldPosition - cameraState.m_position).GetNormalized();
return mousePick;
}
@@ -16,8 +16,7 @@ namespace AzManipulatorTestFramework
using MouseInteractionEvent = AzToolsFramework::ViewportInteraction::MouseInteractionEvent;
//! Implementation of the manipulator interface using bus calls to access to the manipulator manager.
class IndirectCallManipulatorManager
: public ManipulatorManagerInterface
class IndirectCallManipulatorManager : public ManipulatorManagerInterface
{
public:
IndirectCallManipulatorManager(ViewportInteractionInterface& viewportInteraction);
@@ -39,11 +38,12 @@ namespace AzManipulatorTestFramework
void IndirectCallManipulatorManager::ConsumeMouseInteractionEvent(const MouseInteractionEvent& event)
{
m_viewportInteraction.UpdateVisibility();
DrawManipulators();
AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions,
event);
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions, event);
DrawManipulators();
}
@@ -26,10 +26,12 @@ namespace AzManipulatorTestFramework
{
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId);
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
}
ViewportInteraction::~ViewportInteraction()
{
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusDisconnect();
}
@@ -74,6 +76,16 @@ namespace AzManipulatorTestFramework
return 0.1f;
}
void ViewportInteraction::FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut)
{
visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End());
}
void ViewportInteraction::UpdateVisibility()
{
m_entityVisibilityQuery.UpdateVisibility(m_cameraState);
}
AzFramework::ScreenPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
{
return AzFramework::WorldToScreen(worldPosition, m_cameraState);
@@ -96,7 +96,7 @@ namespace AzToolsFramework
{
AZ::EBusReduceResult<AZ::Aabb, AzFramework::AabbUnionAggregator> aabbResult(AZ::Aabb::CreateNull());
EditorComponentSelectionRequestsBus::EventResult(
aabbResult, entityId, &EditorComponentSelectionRequests::GetEditorSelectionBoundsViewport, viewportInfo);
aabbResult, entityId, &EditorComponentSelectionRequestsBus::Events::GetEditorSelectionBoundsViewport, viewportInfo);
return aabbResult.value;
}
@@ -10,6 +10,25 @@
namespace AzToolsFramework
{
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
{
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
return AzFramework::ClickDetector::ClickEvent::Down;
}
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
{
return AzFramework::ClickDetector::ClickEvent::Up;
}
}
return AzFramework::ClickDetector::ClickEvent::Nil;
}
float ManipulatorLineBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
{
float lineBoundWidth = 0.0f;
@@ -250,8 +250,6 @@ namespace AzToolsFramework
virtual AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) = 0;
//! Return the terrain height given a world position in 2d (xy plane).
virtual float TerrainHeight(const AZ::Vector2& position) = 0;
//! Given the current view frustum (viewport) return all visible entities.
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
//! Is the user holding a modifier key to move the manipulator space from local to world.
virtual bool ShowingWorldSpace() = 0;
//! Return the widget to use as the parent for the viewport context menu.
@@ -269,7 +267,20 @@ namespace AzToolsFramework
//! Type to inherit to implement MainEditorViewportInteractionRequests.
using MainEditorViewportInteractionRequestBus = AZ::EBus<MainEditorViewportInteractionRequests, ViewportEBusTraits>;
//! Viewport requests for managing the viewport's cursor state.
//! Editor entity requests to be made about the viewport.
class EditorEntityViewportInteractionRequests
{
public:
//! Given the current view frustum (viewport) return all visible entities.
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
protected:
~EditorEntityViewportInteractionRequests() = default;
};
using EditorEntityViewportInteractionRequestBus = AZ::EBus<EditorEntityViewportInteractionRequests, ViewportEBusTraits>;
//! Viewport requests for managing the viewport cursor state.
class ViewportMouseCursorRequests
{
public:
@@ -321,23 +332,8 @@ namespace AzToolsFramework
//! Maps a mouse interaction event to a ClickDetector event.
//! @note Function only cares about up or down events, all other events are mapped to Nil (ignored).
inline AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
{
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
return AzFramework::ClickDetector::ClickEvent::Down;
}
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
{
return AzFramework::ClickDetector::ClickEvent::Up;
}
}
return AzFramework::ClickDetector::ClickEvent::Nil;
}
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
//! Wrap EBus call to retrieve manipulator line bound width.
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
@@ -19,7 +19,7 @@
namespace AzToolsFramework
{
// default ray length for picking in the viewport
static const float s_pickRayLength = 1000.0f;
static const float EditorPickRayLength = 1000.0f;
AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
{
@@ -60,16 +60,27 @@ namespace AzToolsFramework
return screenPosition;
}
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
const AZ::Vector3 rayScaledDir = mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength;
const AZ::Vector3 rayScaledDir = direction * EditorPickRayLength;
AZ::Vector3 startNormal;
float t, end;
return AZ::Intersect::IntersectRayAABB(
mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0;
AZ::Vector3 startNormal;
if (AZ::Intersect::IntersectRayAABB(origin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0)
{
distance = t * EditorPickRayLength;
return true;
}
return false;
}
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
{
float unused;
return AabbIntersectRay(mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection, aabb, unused);
}
bool PickEntity(
@@ -117,8 +128,7 @@ namespace AzToolsFramework
{
float scaling = 1.0f;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
scaling, viewportId,
&ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
scaling, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
return scaling;
}
@@ -46,6 +46,10 @@ namespace AzToolsFramework
//! in screen space intersected an aabb in world space.
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb);
//! Wrapper to perform an intersection between a ray and an aabb.
//! Note: direction should be normalized (it is scaled internally by the editor pick distance).
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance);
//! Return if a mouse interaction (pick ray) did intersect the tested EntityId.
bool PickEntity(
AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction, float& closestDistance, int viewportId);
@@ -161,8 +161,8 @@ namespace AzToolsFramework
// request list of visible entities from authoritative system
EntityIdList nextVisibleEntityIds;
ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
viewportInfo.m_viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities,
ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
viewportInfo.m_viewportId, &ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
nextVisibleEntityIds);
// only bother resorting if we know the lists have changed
@@ -6,8 +6,8 @@
*
*/
#include "ComponentModeTestDoubles.h"
#include "ComponentModeTestFixture.h"
#include "ComponentModeTestDoubles.h"
#include <AzCore/UserSettings/UserSettingsComponent.h>
@@ -15,17 +15,15 @@ namespace UnitTest
{
void ComponentModeTestFixture::SetUpEditorFixtureImpl()
{
using namespace AzToolsFramework;
using namespace AzToolsFramework::ComponentModeFramework;
namespace AztfCmf = AzToolsFramework::ComponentModeFramework;
auto* app = GetApplication();
ASSERT_TRUE(app);
app->RegisterComponentDescriptor(PlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(AnotherPlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(DependentPlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(AztfCmf::PlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(AztfCmf::AnotherPlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(AztfCmf::DependentPlaceholderEditorComponent::CreateDescriptor());
app->RegisterComponentDescriptor(
TestComponentModeComponent<OverrideMouseInteractionComponentMode>::CreateDescriptor());
app->RegisterComponentDescriptor(IncompatiblePlaceholderEditorComponent::CreateDescriptor());
AztfCmf::TestComponentModeComponent<AztfCmf::OverrideMouseInteractionComponentMode>::CreateDescriptor());
app->RegisterComponentDescriptor(AztfCmf::IncompatiblePlaceholderEditorComponent::CreateDescriptor());
}
} // namespace UnitTest
+2 -2
View File
@@ -178,7 +178,7 @@ void CSystem::LogVersion()
strftime(s, 128, "%d %b %y (%H %M %S)", today);
#endif
const SFileVersion& ver = GetFileVersion();
[[maybe_unused]] const SFileVersion& ver = GetFileVersion();
CryLogAlways("BackupNameAttachment=\" Build(%d) %s\" -- used by backup system\n", ver.v[0], s); // read by CreateBackupFile()
@@ -249,7 +249,7 @@ void CSystem::LogVersion()
//////////////////////////////////////////////////////////////////////////
void CSystem::LogBuildInfo()
{
auto projectName = AZ::Utils::GetProjectName();
[[maybe_unused]] auto projectName = AZ::Utils::GetProjectName();
CryLogAlways("GameName: %s", projectName.c_str());
CryLogAlways("BuildTime: " __DATE__ " " __TIME__);
}
@@ -115,10 +115,13 @@ namespace AZ
AZ_Assert(m_shaderResourceGroup, "RayTracingPass [%s]: Failed to create RayTracingGlobalSrg", GetPathName().GetCStr());
RPI::PassUtils::BindDataMappingsToSrg(m_passDescriptor, m_shaderResourceGroup.get());
// check to see if the shader requires the View and RayTracingMaterial Srgs
// check to see if the shader requires the View, Scene, or RayTracingMaterial Srgs
const auto& viewSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::View);
m_requiresViewSrg = (viewSrgLayout != nullptr);
const auto& sceneSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RPI::SrgBindingSlot::Scene);
m_requiresSceneSrg = (sceneSrgLayout != nullptr);
const auto& rayTracingMaterialSrgLayout = m_rayGenerationShader->FindShaderResourceGroupLayout(RayTracingMaterialSrgBindingSlot);
m_requiresRayTracingMaterialSrg = (rayTracingMaterialSrgLayout != nullptr);
@@ -324,6 +327,11 @@ namespace AZ
}
}
if (m_requiresSceneSrg)
{
shaderResourceGroups.push_back(scene->GetShaderResourceGroup()->GetRHIShaderResourceGroup());
}
if (m_requiresRayTracingMaterialSrg)
{
shaderResourceGroups.push_back(rayTracingFeatureProcessor->GetRayTracingMaterialSrg()->GetRHIShaderResourceGroup());
@@ -72,6 +72,7 @@ namespace AZ
RHI::ConstPtr<RHI::PipelineState> m_globalPipelineState;
RHI::Ptr<RHI::RayTracingShaderTable> m_rayTracingShaderTable;
bool m_requiresViewSrg = false;
bool m_requiresSceneSrg = false;
bool m_requiresRayTracingMaterialSrg = false;
};
} // namespace RPI
@@ -73,6 +73,7 @@ namespace AtomToolsFramework
return AZ::Transform::CreateIdentity();
}
void ModularCameraViewportContextImpl::SetCameraTransform(const AZ::Transform& transform)
{
if (auto viewportContext = RetrieveViewportContext(m_viewportId))
@@ -80,6 +81,7 @@ namespace AtomToolsFramework
viewportContext->SetCameraTransform(transform);
}
}
void ModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler)
{
if (auto viewportContext = RetrieveViewportContext(m_viewportId))
@@ -1552,6 +1552,26 @@ namespace AZ::AtomBridge
}
}
void AtomDebugDisplayViewportInterface::PushPremultipliedMatrix(const AZ::Matrix3x4& matrix)
{
AZ_Assert(m_rendState.m_currentTransform < RenderState::TransformStackSize, "Exceeded AtomDebugDisplayViewportInterface matrix stack size");
if (m_rendState.m_currentTransform < RenderState::TransformStackSize)
{
m_rendState.m_currentTransform++;
m_rendState.m_transformStack[m_rendState.m_currentTransform] = matrix;
}
}
AZ::Matrix3x4 AtomDebugDisplayViewportInterface::PopPremultipliedMatrix()
{
AZ_Assert(m_rendState.m_currentTransform > 0, "Underflowed AtomDebugDisplayViewportInterface matrix stack");
if (m_rendState.m_currentTransform > 0)
{
m_rendState.m_currentTransform--;
}
return m_rendState.m_transformStack[m_rendState.m_currentTransform + 1];
}
const AZ::Matrix3x4& AtomDebugDisplayViewportInterface::GetCurrentTransform() const
{
return m_rendState.m_transformStack[m_rendState.m_currentTransform];
@@ -193,6 +193,8 @@ namespace AZ::AtomBridge
AZ::u32 SetState(AZ::u32 state) override;
void PushMatrix(const AZ::Transform& tm) override;
void PopMatrix() override;
void PushPremultipliedMatrix(const AZ::Matrix3x4& matrix) override;
AZ::Matrix3x4 PopPremultipliedMatrix() override;
private:
@@ -11,8 +11,8 @@
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/FileFunc/FileFunc.h>
// For AZ_Printf statements...
#define WWISE_CONFIG_WINDOW "WwiseConfig"
@@ -56,7 +56,7 @@ namespace Audio::Wwise
bool ConfigurationSettings::Load(const AZStd::string& filePath)
{
AZ::IO::Path fileIoPath(filePath);
auto outcome = AzFramework::FileFunc::ReadJsonFile(fileIoPath);
auto outcome = AZ::JsonSerializationUtils::ReadJsonFile(fileIoPath.Native());
if (!outcome)
{
AZ_Printf(WWISE_CONFIG_WINDOW, "ERROR: %s\n", outcome.GetError().c_str());
@@ -92,7 +92,7 @@ namespace Audio::Wwise
return false;
}
auto outcome = AzFramework::FileFunc::WriteJsonFile(jsonDoc, filePath);
auto outcome = AZ::JsonSerializationUtils::WriteJsonFile(jsonDoc, filePath);
if (!outcome)
{
AZ_Printf(WWISE_CONFIG_WINDOW, "ERROR: %s\n", outcome.GetError().c_str());
@@ -19,9 +19,7 @@
#include <AudioEngineWwise_Traits_Platform.h>
#include <cinttypes>
#define MAX_NUMBER_STRING_SIZE (10) // 4G
#define ID_TO_STRING_FORMAT_BANK AKTEXT("%u.bnk")
#define ID_TO_STRING_FORMAT_WEM AKTEXT("%u.wem")
#define MAX_NUMBER_STRING_SIZE (10) // max digits in u32 base-10 number
#define MAX_EXTENSION_SIZE (4) // .xxx
#define MAX_FILETITLE_SIZE (MAX_NUMBER_STRING_SIZE + MAX_EXTENSION_SIZE + 1) // null-terminated
@@ -442,11 +440,16 @@ namespace Audio
}
}
AkOSChar fileName[MAX_FILETITLE_SIZE] = { '\0' };
AkOSChar fileName[MAX_FILETITLE_SIZE] = { 0 };
const AkOSChar* const filenameFormat = (flags->uCodecID == AKCODECID_BANK ? ID_TO_STRING_FORMAT_BANK : ID_TO_STRING_FORMAT_WEM);
AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, filenameFormat, static_cast<int unsigned>(fileID));
if (flags->uCodecID == AKCODECID_BANK)
{
AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, AKTEXT("%u.bnk"), static_cast<unsigned int>(fileID));
}
else
{
AK_OSPRINTF(fileName, MAX_FILETITLE_SIZE, AKTEXT("%u.wem"), static_cast<unsigned int>(fileID));
}
AKPLATFORM::SafeStrCat(finalFilePath, fileName, AK_MAX_PATH);
@@ -72,6 +72,7 @@
// Shape components
#include "Shape/SphereShapeComponent.h"
#include "Shape/DiskShapeComponent.h"
#include "Shape/AxisAlignedBoxShapeComponent.h"
#include "Shape/BoxShapeComponent.h"
#include "Shape/QuadShapeComponent.h"
#include "Shape/CylinderShapeComponent.h"
@@ -202,6 +203,7 @@ namespace LmbrCentral
SphereShapeComponent::CreateDescriptor(),
DiskShapeComponent::CreateDescriptor(),
BoxShapeComponent::CreateDescriptor(),
AxisAlignedBoxShapeComponent::CreateDescriptor(),
QuadShapeComponent::CreateDescriptor(),
CylinderShapeComponent::CreateDescriptor(),
CapsuleShapeComponent::CreateDescriptor(),
@@ -215,6 +217,7 @@ namespace LmbrCentral
SphereShapeDebugDisplayComponent::CreateDescriptor(),
DiskShapeDebugDisplayComponent::CreateDescriptor(),
BoxShapeDebugDisplayComponent::CreateDescriptor(),
AxisAlignedBoxShapeDebugDisplayComponent::CreateDescriptor(),
QuadShapeDebugDisplayComponent::CreateDescriptor(),
CapsuleShapeDebugDisplayComponent::CreateDescriptor(),
CylinderShapeDebugDisplayComponent::CreateDescriptor(),
@@ -24,6 +24,7 @@
#include "Scripting/EditorSpawnerComponent.h"
#include "Scripting/EditorTagComponent.h"
#include "Shape/EditorAxisAlignedBoxShapeComponent.h"
#include "Shape/EditorBoxShapeComponent.h"
#include "Shape/EditorQuadShapeComponent.h"
#include "Shape/EditorSphereShapeComponent.h"
@@ -67,6 +68,7 @@ namespace LmbrCentral
EditorDiskShapeComponent::CreateDescriptor(),
EditorTubeShapeComponent::CreateDescriptor(),
EditorBoxShapeComponent::CreateDescriptor(),
EditorAxisAlignedBoxShapeComponent::CreateDescriptor(),
EditorQuadShapeComponent::CreateDescriptor(),
EditorLookAtComponent::CreateDescriptor(),
EditorCylinderShapeComponent::CreateDescriptor(),
@@ -0,0 +1,59 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "AxisAlignedBoxShape.h"
#include <AzCore/Math/Color.h>
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Random.h>
#include <AzCore/Math/Sfmt.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/containers/array.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <Shape/ShapeDisplay.h>
#include <random>
namespace LmbrCentral
{
AxisAlignedBoxShape::AxisAlignedBoxShape()
: BoxShape()
{
}
void AxisAlignedBoxShape::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AxisAlignedBoxShape, BoxShape>()
->Version(1)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
{
editContext->Class<AxisAlignedBoxShape>("Axis Aligned Box Shape", "Axis Aligned Box shape configuration parameters")
;
}
}
}
void AxisAlignedBoxShape::Activate(AZ::EntityId entityId)
{
BoxShape::Activate(entityId);
m_currentTransform.SetRotation(AZ::Quaternion::CreateIdentity());
}
void AxisAlignedBoxShape::OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world)
{
AZ::Transform worldNoRotation(world.GetTranslation(), AZ::Quaternion::CreateIdentity(), world.GetUniformScale());
BoxShape::OnTransformChanged(local, worldNoRotation);
}
} // namespace LmbrCentral
@@ -0,0 +1,44 @@
/*
* 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/Component/TransformBus.h>
#include <AzCore/Math/Aabb.h>
#include <AzCore/Math/Obb.h>
#include <AzCore/Component/NonUniformScaleBus.h>
#include <LmbrCentral/Shape/ShapeComponentBus.h>
#include <LmbrCentral/Shape/BoxShapeComponentBus.h>
#include "BoxShape.h"
namespace AzFramework
{
class DebugDisplayRequests;
}
namespace LmbrCentral
{
struct ShapeDrawParams;
class AxisAlignedBoxShape
: public BoxShape
{
public:
AZ_CLASS_ALLOCATOR(AxisAlignedBoxShape, AZ::SystemAllocator, 0)
AZ_RTTI(AxisAlignedBoxShape, "{CFDC96C5-287A-4033-8D7D-BA9331C13F25}", BoxShape)
AxisAlignedBoxShape();
static void Reflect(AZ::ReflectContext* context);
void Activate(AZ::EntityId entityId) override;
// AZ::TransformNotificationBus::Handler
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
};
} // namespace LmbrCentral
@@ -0,0 +1,159 @@
/*
* 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 "AxisAlignedBoxShapeComponent.h"
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <Shape/ShapeComponentConverters.h>
#include <Shape/ShapeDisplay.h>
namespace LmbrCentral
{
void AxisAlignedBoxShapeComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC_CE("ShapeService"));
provided.push_back(AZ_CRC_CE("BoxShapeService"));
provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService"));
}
void AxisAlignedBoxShapeComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("ShapeService"));
incompatible.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService"));
}
void AxisAlignedBoxShapeComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
required.push_back(AZ_CRC_CE("TransformService"));
}
void AxisAlignedBoxShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
dependent.push_back(AZ_CRC_CE("NonUniformScaleService"));
}
void AxisAlignedBoxShapeDebugDisplayComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AxisAlignedBoxShapeDebugDisplayComponent, EntityDebugDisplayComponent>()
->Version(1)->Field(
"Configuration", &AxisAlignedBoxShapeDebugDisplayComponent::m_boxShapeConfig)
;
}
}
void AxisAlignedBoxShapeDebugDisplayComponent::Activate()
{
EntityDebugDisplayComponent::Activate();
ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId());
m_nonUniformScale = AZ::Vector3::CreateOne();
AZ::NonUniformScaleRequestBus::EventResult(m_nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
}
void AxisAlignedBoxShapeDebugDisplayComponent::Deactivate()
{
ShapeComponentNotificationsBus::Handler::BusDisconnect();
EntityDebugDisplayComponent::Deactivate();
}
void AxisAlignedBoxShapeDebugDisplayComponent::Draw(AzFramework::DebugDisplayRequests& debugDisplay)
{
AZ::Matrix3x4 saveMatrix;
ShapeDrawParams drawParams = g_defaultShapeDrawParams;
drawParams.m_shapeColor = m_boxShapeConfig.GetDrawColor();
drawParams.m_filled = m_boxShapeConfig.IsFilled();
AZ::Transform transform = GetCurrentTransform();
transform.SetRotation(AZ::Quaternion::CreateIdentity());
saveMatrix = debugDisplay.PopPremultipliedMatrix();
debugDisplay.PushMatrix(transform);
DrawBoxShape(drawParams, m_boxShapeConfig, debugDisplay, m_nonUniformScale);
debugDisplay.PopMatrix();
debugDisplay.PushPremultipliedMatrix(saveMatrix);
}
bool AxisAlignedBoxShapeDebugDisplayComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
{
if (const auto config = azrtti_cast<const BoxShapeConfig*>(baseConfig))
{
m_boxShapeConfig = *config;
return true;
}
return false;
}
bool AxisAlignedBoxShapeDebugDisplayComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
{
if (auto outConfig = azrtti_cast<BoxShapeConfig*>(outBaseConfig))
{
*outConfig = m_boxShapeConfig;
return true;
}
return false;
}
void AxisAlignedBoxShapeDebugDisplayComponent::OnShapeChanged(ShapeChangeReasons changeReason)
{
if (changeReason == ShapeChangeReasons::ShapeChanged)
{
BoxShapeComponentRequestsBus::EventResult(m_boxShapeConfig, GetEntityId(), &BoxShapeComponentRequests::GetBoxConfiguration);
AZ::NonUniformScaleRequestBus::EventResult(m_nonUniformScale, GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
}
}
void AxisAlignedBoxShapeComponent::Reflect(AZ::ReflectContext* context)
{
AxisAlignedBoxShape::Reflect(context);
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AxisAlignedBoxShapeComponent, Component>()
->Version(1)
->Field("AxisAlignedBoxShape", &AxisAlignedBoxShapeComponent::m_aaboxShape)
;
}
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Constant("AxisAlignedBoxShapeComponentTypeId", BehaviorConstant(AxisAlignedBoxShapeComponentTypeId));
}
}
void AxisAlignedBoxShapeComponent::Activate()
{
m_aaboxShape.Activate(GetEntityId());
}
void AxisAlignedBoxShapeComponent::Deactivate()
{
m_aaboxShape.Deactivate();
}
bool AxisAlignedBoxShapeComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
{
if (const auto config = azrtti_cast<const BoxShapeConfig*>(baseConfig))
{
m_aaboxShape.SetBoxConfiguration(*config);
return true;
}
return false;
}
bool AxisAlignedBoxShapeComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
{
if (auto config = azrtti_cast<BoxShapeConfig*>(outBaseConfig))
{
*config = m_aaboxShape.GetBoxConfiguration();
return true;
}
return false;
}
} // namespace LmbrCentral
@@ -0,0 +1,76 @@
/*
* 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/Component/Component.h>
#include "Rendering/EntityDebugDisplayComponent.h"
#include "AxisAlignedBoxShape.h"
namespace LmbrCentral
{
/// Type ID for the AxisAlignedBoxShapeComponent
static const AZ::Uuid AxisAlignedBoxShapeComponentTypeId = "{641D817E-1BC6-406A-BBB2-218541808E45}";
/// Type ID for the EditorAxisAlignedBoxShapeComponent
static const AZ::Uuid EditorAxisAlignedBoxShapeComponentTypeId = "{8C027DF6-E157-4159-9BF8-F1B925466F1F}";
/// Provide a Component interface for AxisAlignedBoxShape functionality.
class AxisAlignedBoxShapeComponent
: public AZ::Component
{
public:
AZ_COMPONENT(AxisAlignedBoxShapeComponent, AxisAlignedBoxShapeComponentTypeId)
static void Reflect(AZ::ReflectContext* context);
// AZ::Component
void Activate() override;
void Deactivate() override;
bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
private:
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
AxisAlignedBoxShape m_aaboxShape; ///< Stores underlying box type for this component.
};
/// Concrete EntityDebugDisplay implementation for BoxShape.
class AxisAlignedBoxShapeDebugDisplayComponent
: public EntityDebugDisplayComponent
, public ShapeComponentNotificationsBus::Handler
{
public:
AZ_COMPONENT(AxisAlignedBoxShapeDebugDisplayComponent, "{BA93F933-1DC9-4E0E-B930-A7E3968D5DD1}", EntityDebugDisplayComponent)
static void Reflect(AZ::ReflectContext* context);
AxisAlignedBoxShapeDebugDisplayComponent() = default;
// AZ::Component
void Activate() override;
void Deactivate() override;
bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
// EntityDebugDisplayComponent
void Draw(AzFramework::DebugDisplayRequests& debugDisplay) override;
private:
AZ_DISABLE_COPY_MOVE(AxisAlignedBoxShapeDebugDisplayComponent)
// ShapeComponentNotificationsBus
void OnShapeChanged(ShapeChangeReasons changeReason) override;
BoxShapeConfig m_boxShapeConfig; ///< Stores configuration data for box shape.
AZ::Vector3 m_nonUniformScale = AZ::Vector3::CreateOne(); ///< Caches non-uniform scale for this entity.
};
} // namespace LmbrCentral
@@ -37,7 +37,7 @@ namespace LmbrCentral
static void Reflect(AZ::ReflectContext* context);
void Activate(AZ::EntityId entityId);
virtual void Activate(AZ::EntityId entityId);
void Deactivate();
void InvalidateCache(InvalidateShapeCacheReason reason);
@@ -67,12 +67,9 @@ namespace LmbrCentral
void SetDrawColor(const AZ::Color& color) { m_boxShapeConfig.SetDrawColor(color); }
protected:
friend class EditorBoxShapeComponent;
BoxShapeConfig& ModifyConfiguration() { return m_boxShapeConfig; }
private:
protected:
/// Runtime data - cache potentially expensive operations.
class BoxIntersectionDataCache
: public IntersectionTestDataCache<BoxShapeConfig>
@@ -82,6 +79,7 @@ namespace LmbrCentral
const AZ::Vector3& currentNonUniformScale = AZ::Vector3::CreateOne()) override;
friend BoxShape;
friend class AxisAlignedBoxShape;
AZ::Aabb m_aabb; ///< Aabb representing this Box (including the effects of scale).
AZ::Obb m_obb; ///< Obb representing this Box (including the effects of scale).
@@ -90,12 +88,12 @@ namespace LmbrCentral
bool m_axisAligned = true; ///< Indicates whether the box is axis or object aligned.
};
BoxShapeConfig m_boxShapeConfig; ///< Underlying box configuration.
BoxIntersectionDataCache m_intersectionDataCache; ///< Caches transient intersection data.
AZ::Transform m_currentTransform; ///< Caches the current transform for the entity on which this component lives.
AZ::EntityId m_entityId; ///< Id of the entity the box shape is attached to.
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; ///< Responds to changes in non-uniform scale.
AZ::Vector3 m_currentNonUniformScale = AZ::Vector3::CreateOne(); ///< Caches the current non-uniform scale.
BoxShapeConfig m_boxShapeConfig; ///< Underlying box configuration.
};
void DrawBoxShape(
@@ -101,23 +101,15 @@ namespace LmbrCentral
}
}
namespace ClassConverters
{
static bool DeprecateBoxColliderConfiguration(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
static bool DeprecateBoxColliderComponent(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
}
void BoxShapeConfig::Reflect(AZ::ReflectContext* context)
{
// Don't reflect again if we're already reflected to the passed in context
if (context->IsTypeReflected(BoxShapeConfigTypeId))
{
return;
}
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
// Deprecate: BoxColliderConfiguration -> BoxShapeConfig
serializeContext->ClassDeprecate(
"BoxColliderConfiguration",
"{282E47CB-9F6D-47AE-A210-4CE879527EFD}",
&ClassConverters::DeprecateBoxColliderConfiguration)
;
serializeContext->Class<BoxShapeConfig, ShapeComponentConfig>()
->Version(2)
->Field("Dimensions", &BoxShapeConfig::m_dimensions)
@@ -151,13 +143,6 @@ namespace LmbrCentral
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
// Deprecate: BoxColliderComponent -> BoxShapeComponent
serializeContext->ClassDeprecate(
"BoxColliderComponent",
"{C215EB2A-1803-4EDC-B032-F7C92C142337}",
&ClassConverters::DeprecateBoxColliderComponent)
;
serializeContext->Class<BoxShapeComponent, Component>()
->Version(2, &ClassConverters::UpgradeBoxShapeComponent)
->Field("BoxShape", &BoxShapeComponent::m_boxShape)
@@ -205,85 +190,4 @@ namespace LmbrCentral
}
return false;
}
namespace ClassConverters
{
static bool DeprecateBoxColliderConfiguration(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
/*
Old:
<Class name="BoxColliderConfiguration" field="Configuration" version="1" type="{282E47CB-9F6D-47AE-A210-4CE879527EFD}">
<Class name="Vector3" field="Size" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
</Class>
New:
<Class name="BoxShapeConfig" field="Configuration" version="1" type="{F034FBA2-AC2F-4E66-8152-14DFB90D6283}">
<Class name="Vector3" field="Dimensions" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
</Class>
*/
// Cache the Dimensions
AZ::Vector3 oldDimensions;
const int oldIndex = classElement.FindElement(AZ_CRC("Size", 0xf7c0246a));
if (oldIndex != -1)
{
classElement.GetSubElement(oldIndex).GetData<AZ::Vector3>(oldDimensions);
}
// Convert to BoxShapeConfig
const bool result = classElement.Convert(context, "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}");
if (result)
{
const int newIndex = classElement.AddElement<AZ::Vector3>(context, "Dimensions");
if (newIndex != -1)
{
classElement.GetSubElement(newIndex).SetData<AZ::Vector3>(context, oldDimensions);
return true;
}
}
return false;
}
static bool DeprecateBoxColliderComponent(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement)
{
/*
Old:
<Class name="BoxColliderComponent" version="1" type="{C215EB2A-1803-4EDC-B032-F7C92C142337}">
<Class name="BoxColliderConfiguration" field="Configuration" version="1" type="{282E47CB-9F6D-47AE-A210-4CE879527EFD}">
<Class name="Vector3" field="Size" value="1.0000000 1.0000000 1.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
</Class>
</Class>
New:
<Class name="BoxShapeComponent" version="1" type="{5EDF4B9E-0D3D-40B8-8C91-5142BCFC30A6}">
<Class name="BoxShapeConfig" field="Configuration" version="1" type="{F034FBA2-AC2F-4E66-8152-14DFB90D6283}">
<Class name="Vector3" field="Dimensions" value="1.0000000 2.0000000 3.0000000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
</Class>
</Class>
*/
// Cache the Configuration
BoxShapeConfig configuration;
int configIndex = classElement.FindElement(AZ_CRC("Configuration", 0xa5e2a5d7));
if (configIndex != -1)
{
classElement.GetSubElement(configIndex).GetData<BoxShapeConfig>(configuration);
}
// Convert to BoxShapeComponent
const bool result = classElement.Convert(context, BoxShapeComponentTypeId);
if (result)
{
configIndex = classElement.AddElement<BoxShapeConfig>(context, "Configuration");
if (configIndex != -1)
{
classElement.GetSubElement(configIndex).SetData<BoxShapeConfig>(context, configuration);
}
return true;
}
return false;
}
} // namespace ClassConverters
} // namespace LmbrCentral
@@ -0,0 +1,168 @@
/*
* 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/Math/Transform.h>
#include <AzCore/RTTI/ReflectContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzToolsFramework/ComponentModes/BoxComponentMode.h>
#include <AzToolsFramework/Maths/TransformUtils.h>
#include "AxisAlignedBoxShapeComponent.h"
#include "EditorAxisAlignedBoxShapeComponent.h"
#include "EditorShapeComponentConverters.h"
#include "ShapeDisplay.h"
namespace LmbrCentral
{
void EditorAxisAlignedBoxShapeComponent::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<EditorAxisAlignedBoxShapeComponent, EditorBaseShapeComponent>()
->Version(1)
->Field("AxisAlignedBoxShape", &EditorAxisAlignedBoxShapeComponent::m_aaboxShape)
->Field("ComponentMode", &EditorAxisAlignedBoxShapeComponent::m_componentModeDelegate)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<EditorAxisAlignedBoxShapeComponent>(
"Axis Aligned Box Shape", "The Axis Aligned Box Shape component creates a box around the associated entity")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Category, "Shape")
->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Box_Shape.svg")
->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Box_Shape.svg")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/shape/axis-aligned-box-shape/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorAxisAlignedBoxShapeComponent::m_aaboxShape, "Axis Aligned Box Shape", "Axis Aligned Box Shape Configuration")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAxisAlignedBoxShapeComponent::ConfigurationChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorAxisAlignedBoxShapeComponent::m_componentModeDelegate, "Component Mode", "Axis Aligned Box Shape Component Mode")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
;
}
}
}
void EditorAxisAlignedBoxShapeComponent::Init()
{
EditorBaseShapeComponent::Init();
SetShapeComponentConfig(&m_aaboxShape.ModifyConfiguration());
}
void EditorAxisAlignedBoxShapeComponent::Activate()
{
EditorBaseShapeComponent::Activate();
m_aaboxShape.Activate(GetEntityId());
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId());
AzToolsFramework::BoxManipulatorRequestBus::Handler::BusConnect(
AZ::EntityComponentIdPair(GetEntityId(), GetId()));
// ComponentMode
m_componentModeDelegate.ConnectWithSingleComponentMode<
EditorAxisAlignedBoxShapeComponent, AzToolsFramework::BoxComponentMode>(
AZ::EntityComponentIdPair(GetEntityId(), GetId()), this);
}
void EditorAxisAlignedBoxShapeComponent::Deactivate()
{
m_componentModeDelegate.Disconnect();
AzToolsFramework::BoxManipulatorRequestBus::Handler::BusDisconnect();
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
m_aaboxShape.Deactivate();
EditorBaseShapeComponent::Deactivate();
}
void EditorAxisAlignedBoxShapeComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
EditorBaseShapeComponent::GetProvidedServices(provided);
provided.push_back(AZ_CRC_CE("BoxShapeService"));
provided.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService"));
}
void EditorAxisAlignedBoxShapeComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
dependent.push_back(AZ_CRC_CE("NonUniformScaleService"));
}
void EditorAxisAlignedBoxShapeComponent::DisplayEntityViewport(
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)
{
DisplayShape(
debugDisplay, [this]() { return CanDraw(); },
[this](AzFramework::DebugDisplayRequests& debugDisplay)
{
DrawBoxShape(
{ m_aaboxShape.GetBoxConfiguration().GetDrawColor(), m_shapeWireColor, m_aaboxShape.GetBoxConfiguration().IsFilled() },
m_aaboxShape.GetBoxConfiguration(), debugDisplay, m_aaboxShape.GetCurrentNonUniformScale());
},
m_aaboxShape.GetCurrentTransform());
}
void EditorAxisAlignedBoxShapeComponent::ConfigurationChanged()
{
m_aaboxShape.InvalidateCache(InvalidateShapeCacheReason::ShapeChange);
ShapeComponentNotificationsBus::Event(GetEntityId(),
&ShapeComponentNotificationsBus::Events::OnShapeChanged,
ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged);
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::Refresh,
AZ::EntityComponentIdPair(GetEntityId(), GetId()));
}
void EditorAxisAlignedBoxShapeComponent::BuildGameEntity(AZ::Entity* gameEntity)
{
if (AxisAlignedBoxShapeComponent* boxShapeComponent = gameEntity->CreateComponent<AxisAlignedBoxShapeComponent>())
{
boxShapeComponent->SetConfiguration(m_aaboxShape.GetBoxConfiguration());
}
if (m_visibleInGameView)
{
if (auto component = gameEntity->CreateComponent<AxisAlignedBoxShapeDebugDisplayComponent>())
{
component->SetConfiguration(m_aaboxShape.GetBoxConfiguration());
}
}
}
void EditorAxisAlignedBoxShapeComponent::OnTransformChanged(
const AZ::Transform& /*local*/, const AZ::Transform& /*world*/)
{
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequests::Refresh,
AZ::EntityComponentIdPair(GetEntityId(), GetId()));
}
AZ::Vector3 EditorAxisAlignedBoxShapeComponent::GetDimensions()
{
return m_aaboxShape.GetBoxDimensions();
}
void EditorAxisAlignedBoxShapeComponent::SetDimensions(const AZ::Vector3& dimensions)
{
return m_aaboxShape.SetBoxDimensions(dimensions);
}
AZ::Transform EditorAxisAlignedBoxShapeComponent::GetCurrentTransform()
{
return AzToolsFramework::TransformNormalizedScale(m_aaboxShape.GetCurrentTransform());
}
AZ::Vector3 EditorAxisAlignedBoxShapeComponent::GetBoxScale()
{
return AZ::Vector3(m_aaboxShape.GetCurrentTransform().GetUniformScale() * m_aaboxShape.GetCurrentNonUniformScale());
}
} // namespace LmbrCentral
@@ -0,0 +1,71 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include "AxisAlignedBoxShape.h"
#include "AxisAlignedBoxShapeComponent.h"
#include "EditorBaseShapeComponent.h"
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/ComponentMode/ComponentModeDelegate.h>
#include <AzToolsFramework/Manipulators/BoxManipulatorRequestBus.h>
namespace LmbrCentral
{
/// Editor representation of Box Shape Component.
class EditorAxisAlignedBoxShapeComponent
: public EditorBaseShapeComponent
, private AzFramework::EntityDebugDisplayEventBus::Handler
, private AzToolsFramework::BoxManipulatorRequestBus::Handler
{
public:
AZ_EDITOR_COMPONENT(EditorAxisAlignedBoxShapeComponent, EditorAxisAlignedBoxShapeComponentTypeId, EditorBaseShapeComponent);
static void Reflect(AZ::ReflectContext* context);
EditorAxisAlignedBoxShapeComponent() = default;
// AZ::Component
void Init() override;
void Activate() override;
void Deactivate() override;
protected:
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
// EditorComponentBase
void BuildGameEntity(AZ::Entity* gameEntity) override;
// AZ::TransformNotificationBus::Handler
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
private:
AZ_DISABLE_COPY_MOVE(EditorAxisAlignedBoxShapeComponent)
// AzFramework::EntityDebugDisplayEventBus
void DisplayEntityViewport(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
// AzToolsFramework::BoxManipulatorRequestBus
AZ::Vector3 GetDimensions() override;
void SetDimensions(const AZ::Vector3& dimensions) override;
AZ::Transform GetCurrentTransform() override;
AZ::Vector3 GetBoxScale() override;
void ConfigurationChanged();
AxisAlignedBoxShape m_aaboxShape; ///< Stores underlying box representation for this component.
using ComponentModeDelegate = AzToolsFramework::ComponentModeFramework::ComponentModeDelegate;
ComponentModeDelegate m_componentModeDelegate; /**< Responsible for detecting ComponentMode activation
* and creating a concrete ComponentMode.*/
};
} // namespace LmbrCentral
@@ -49,7 +49,7 @@ namespace LmbrCentral
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/shape/box-shape/")
->DataElement(AZ::Edit::UIHandlers::Default, &EditorBoxShapeComponent::m_boxShape, "Box Shape", "Box Shape Configuration")
// ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) // disabled - prevents ChangeNotify attribute firing correctly
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorBoxShapeComponent::ConfigurationChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &EditorBoxShapeComponent::m_componentModeDelegate, "Component Mode", "Box Shape Component Mode")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
@@ -0,0 +1,238 @@
/*
* 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 <AzTest/AzTest.h>
#include <AZTestShared/Math/MathTestHelpers.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Random.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Components/NonUniformScaleComponent.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/UnitTest/TestDebugDisplayRequests.h>
#include <Shape/AxisAlignedBoxShapeComponent.h>
namespace UnitTest
{
class AxisAlignedBoxShapeTest : public AllocatorsFixture
{
AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_transformComponentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_axisAlignedBoxShapeComponentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_axisAlignedBoxShapeDebugDisplayComponentDescriptor;
AZStd::unique_ptr<AZ::ComponentDescriptor> m_nonUniformScaleComponentDescriptor;
public:
void SetUp() override
{
AllocatorsFixture::SetUp();
m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
m_transformComponentDescriptor =
AZStd::unique_ptr<AZ::ComponentDescriptor>(AzFramework::TransformComponent::CreateDescriptor());
m_transformComponentDescriptor->Reflect(&(*m_serializeContext));
m_axisAlignedBoxShapeComponentDescriptor =
AZStd::unique_ptr<AZ::ComponentDescriptor>(LmbrCentral::AxisAlignedBoxShapeComponent::CreateDescriptor());
m_axisAlignedBoxShapeComponentDescriptor->Reflect(&(*m_serializeContext));
m_axisAlignedBoxShapeDebugDisplayComponentDescriptor =
AZStd::unique_ptr<AZ::ComponentDescriptor>(LmbrCentral::AxisAlignedBoxShapeDebugDisplayComponent::CreateDescriptor());
m_axisAlignedBoxShapeDebugDisplayComponentDescriptor->Reflect(&(*m_serializeContext));
m_nonUniformScaleComponentDescriptor =
AZStd::unique_ptr<AZ::ComponentDescriptor>(AzFramework::NonUniformScaleComponent::CreateDescriptor());
m_nonUniformScaleComponentDescriptor->Reflect(&(*m_serializeContext));
}
void TearDown() override
{
m_transformComponentDescriptor.reset();
m_axisAlignedBoxShapeComponentDescriptor.reset();
m_axisAlignedBoxShapeDebugDisplayComponentDescriptor.reset();
m_nonUniformScaleComponentDescriptor.reset();
m_serializeContext.reset();
AllocatorsFixture::TearDown();
}
};
void CreateAxisAlignedBox(const AZ::Transform& transform, const AZ::Vector3& dimensions, AZ::Entity& entity)
{
entity.CreateComponent<LmbrCentral::AxisAlignedBoxShapeComponent>();
entity.CreateComponent<LmbrCentral::AxisAlignedBoxShapeDebugDisplayComponent>();
entity.CreateComponent<AzFramework::TransformComponent>();
entity.Init();
entity.Activate();
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
LmbrCentral::BoxShapeComponentRequestsBus::Event(
entity.GetId(), &LmbrCentral::BoxShapeComponentRequestsBus::Events::SetBoxDimensions, dimensions);
}
void CreateAxisAlignedBoxWithNonUniformScale(
const AZ::Transform& transform, const AZ::Vector3& nonUniformScale, const AZ::Vector3& dimensions, AZ::Entity& entity)
{
entity.CreateComponent<LmbrCentral::AxisAlignedBoxShapeComponent>();
entity.CreateComponent<LmbrCentral::AxisAlignedBoxShapeDebugDisplayComponent>();
entity.CreateComponent<AzFramework::TransformComponent>();
entity.CreateComponent<AzFramework::NonUniformScaleComponent>();
entity.Init();
entity.Activate();
AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
LmbrCentral::BoxShapeComponentRequestsBus::Event(
entity.GetId(), &LmbrCentral::BoxShapeComponentRequestsBus::Events::SetBoxDimensions, dimensions);
AZ::NonUniformScaleRequestBus::Event(entity.GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale);
}
void CreateDefaultAxisAlignedBox(const AZ::Transform& transform, AZ::Entity& entity)
{
CreateAxisAlignedBox(transform, AZ::Vector3(10.0f, 10.0f, 10.0f), entity);
}
TEST_F(AxisAlignedBoxShapeTest, EntityTransformIsCorrect)
{
AZ::Entity entity;
CreateAxisAlignedBox(
AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)) * AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi),
AZ::Vector3(1.0f), entity);
AZ::Transform transform;
AZ::TransformBus::EventResult(transform, entity.GetId(), &AZ::TransformBus::Events::GetWorldTM);
EXPECT_EQ(transform, AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi));
}
TEST_F(AxisAlignedBoxShapeTest, BoxWithZRotationHasCorrectRayIntersection)
{
AZ::Entity entity;
CreateAxisAlignedBox(
AZ::Transform::CreateRotationZ(AZ::Constants::QuarterPi),
AZ::Vector3(1.0f), entity);
bool rayHit = false;
float distance;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(5.0f, 0.0f, 0.0f),
AZ::Vector3(-1.0f, 0.0f, 0.0f), distance);
// This test creates a unit box centered on (0, 0, 0) and rotated by 45 degrees. The distance to the box should
// be 4.5 if it isn't rotated but less if there is any rotation.
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 4.5f, 1e-2f);
}
TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationAndRotationsHasCorrectRayIntersection)
{
AZ::Entity entity;
CreateAxisAlignedBox(
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisX(), AZ::Constants::HalfPi) *
AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), AZ::Constants::QuarterPi),
AZ::Vector3(-10.0f, -10.0f, -10.0f)),
AZ::Vector3(4.0f, 4.0f, 2.0f), entity);
bool rayHit = false;
float distance;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(-10.0f, -10.0f, 0.0f),
AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
// This test creates a box of dimensions (4.0, 4.0, 2.0) centered on (-10, -10, 0) and rotated in X and Z. The distance to the box should
// be 9.0 if it isn't rotated but less if there is any rotation.
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 9.00f, 1e-2f);
}
TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationHasCorrectRayIntersection)
{
AZ::Entity entity;
CreateAxisAlignedBox(
AZ::Transform::CreateTranslation(AZ::Vector3(100.0f, 100.0f, 0.0f)),
AZ::Vector3(5.0f, 5.0f, 5.0f), entity);
bool rayHit = false;
float distance;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(100.0f, 100.0f, -100.0f),
AZ::Vector3(0.0f, 0.0f, 1.0f), distance);
// This test creates a box of dimensions (5.0, 5.0, 5.0) centered on (100, 100, 0) and not rotated. The distance to the box
// should be 97.5.
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 97.5f, 1e-2f);
}
TEST_F(AxisAlignedBoxShapeTest, BoxWithTranslationRotationAndScaleHasCorrectRayIntersection)
{
AZ::Entity entity;
CreateAxisAlignedBox(
AZ::Transform(
AZ::Vector3(0.0f, 0.0f, 5.0f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisY(), AZ::Constants::QuarterPi), 3.0f),
AZ::Vector3(2.0f, 4.0f, 1.0f), entity);
bool rayHit = false;
float distance;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.0f, -10.0f, 4.0f),
AZ::Vector3(0.0f, 1.0f, 0.0f), distance);
// This test creates a box of dimensions (2.0, 4.0, 1.0) centered on (0, 0, 5) and rotated about the Y axis by 45 degrees.
// The distance to the box should be 4.0 if not rotated but scaled and less if it is.
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 4.0f, 1e-2f);
}
TEST_F(AxisAlignedBoxShapeTest, RayIntersectWithBoxRotatedNonUniformScale)
{
AZ::Entity entity;
CreateAxisAlignedBoxWithNonUniformScale(
AZ::Transform(
AZ::Vector3(2.0f, -5.0f, 3.0f), AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisY(), AZ::Constants::QuarterPi),
0.5f),
AZ::Vector3(2.2f, 1.8f, 0.4f), AZ::Vector3(0.2f, 2.6f, 1.2f), entity);
// This test creates a box of dimensions (2.2, 1.8, 0.4) centered on (2.0, -5, 3) and rotated about the Y axis by 45 degrees.
// The box is tested for axis-alignment by firing various rays and ensuring they either hit or miss the box. Any failure here
// would show the box has been rotated.
// Ray should just miss the box
bool rayHit = false;
float distance = AZ::Constants::FloatMax;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.8f, -6.2f, 3.0f),
AZ::Vector3(1.0f, 0.0f, 0.0f), distance);
EXPECT_FALSE(rayHit);
// Ray should just hit the box
rayHit = false;
distance = AZ::Constants::FloatMax;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(1.8f, -6.1f, 3.0f),
AZ::Vector3(1.0f, 0.0f, 0.0f), distance);
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 0.09f, 1e-3f);
// Ray should just miss the box
rayHit = false;
distance = AZ::Constants::FloatMax;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(2.2f, -6.2f, 3.0f),
AZ::Vector3(0.0f, 1.0f, 0.0f), distance);
EXPECT_FALSE(rayHit);
// Ray should just hit the box
rayHit = false;
distance = AZ::Constants::FloatMax;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay, AZ::Vector3(2.1f, -6.2f, 3.0f),
AZ::Vector3(0.0f, 1.0f, 0.0f), distance);
EXPECT_TRUE(rayHit);
EXPECT_NEAR(distance, 0.03f, 1e-3f);
}
} // namespace UnitTest
+15 -15
View File
@@ -34,10 +34,10 @@ namespace
0.5f, 1.0f, 2.0f, 4.0f, 8.0f,
};
const uint32_t RayCount = 5;
const uint32_t RayCountDisk = 5;
// Various normalized offset directions from center of disk along disk's surface.
const AZStd::array<AZ::Vector3, RayCount> OffsetsFromCenter =
const AZStd::array<AZ::Vector3, RayCountDisk> OffsetsFromCenterDisk =
{
AZ::Vector3(0.18f, -0.50f, 0.0f).GetNormalized(),
AZ::Vector3(-0.08f, 0.59f, 0.0f).GetNormalized(),
@@ -47,7 +47,7 @@ namespace
};
// Various directions away from a point on the disk's surface
const AZStd::array<AZ::Vector3, RayCount> OffsetsFromSurface =
const AZStd::array<AZ::Vector3, RayCountDisk> OffsetsFromSurfaceDisk =
{
AZ::Vector3(0.69f, 0.38f, 0.09f).GetNormalized(),
AZ::Vector3(-0.98f, -0.68f, -0.28f).GetNormalized(),
@@ -57,7 +57,7 @@ namespace
};
// Various distance away from the surface for the rays
const AZStd::array<float, RayCount> RayDistances =
const AZStd::array<float, RayCountDisk> RayDistancesDisk =
{
0.5f, 1.0f, 2.0f, 4.0f, 8.0f
};
@@ -185,7 +185,7 @@ namespace UnitTest
}
// Offsets from center scaled down from the disk edge so that all the rays should hit
const AZStd::array<float, RayCount> offsetFromCenterScale =
const AZStd::array<float, RayCountDisk> offsetFromCenterScale =
{
0.8f,
0.2f,
@@ -197,20 +197,20 @@ namespace UnitTest
// Construct rays and test against the different disks
for (uint32_t diskIndex = 0; diskIndex < DiskCount; ++diskIndex)
{
for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex)
for (uint32_t rayIndex = 0; rayIndex < RayCountDisk; ++rayIndex)
{
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex];
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterDisk[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex];
AZ::Vector3 positionOnDiskSurface = DiskTransforms[diskIndex].TransformPoint(scaledOffsetFromCenter);
AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex];
AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurfaceDisk[rayIndex] * RayDistancesDisk[rayIndex];
bool rayHit2 = false;
float distance2;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit2, diskEntities[diskIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
rayOrigin, -OffsetsFromSurface[rayIndex], distance2);
rayOrigin, -OffsetsFromSurfaceDisk[rayIndex], distance2);
EXPECT_TRUE(rayHit2);
EXPECT_NEAR(distance2, RayDistances[rayIndex], 1e-4f);
EXPECT_NEAR(distance2, RayDistancesDisk[rayIndex], 1e-4f);
}
}
@@ -241,7 +241,7 @@ namespace UnitTest
}
// Offsets from center scaled up from the disk edge so that all the rays should miss
const AZStd::array<float, RayCount> offsetFromCenterScale =
const AZStd::array<float, RayCountDisk> offsetFromCenterScale =
{
1.8f,
1.2f,
@@ -253,17 +253,17 @@ namespace UnitTest
// Construct rays and test against the different disks
for (uint32_t diskIndex = 0; diskIndex < DiskCount; ++diskIndex)
{
for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex)
for (uint32_t rayIndex = 0; rayIndex < RayCountDisk; ++rayIndex)
{
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex];
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterDisk[rayIndex] * DiskRadii[diskIndex] * offsetFromCenterScale[rayIndex];
AZ::Vector3 positionOnDiskSurface = DiskTransforms[diskIndex].TransformPoint(scaledOffsetFromCenter);
AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex];
AZ::Vector3 rayOrigin = positionOnDiskSurface + OffsetsFromSurfaceDisk[rayIndex] * RayDistancesDisk[rayIndex];
bool rayHit2 = false;
float distance2;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit2, diskEntities[diskIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
rayOrigin, -OffsetsFromSurface[rayIndex], distance2);
rayOrigin, -OffsetsFromSurfaceDisk[rayIndex], distance2);
EXPECT_FALSE(rayHit2);
}
+16 -16
View File
@@ -41,10 +41,10 @@ namespace
LmbrCentral::QuadShapeConfig(1.0f, 0.5f),
};
const uint32_t RayCount = 5;
const uint32_t RayCountQuad = 5;
// Various normalized offset directions from center of quad along quad's surface.
const AZStd::array<AZ::Vector3, RayCount> OffsetsFromCenter =
const AZStd::array<AZ::Vector3, RayCountQuad> OffsetsFromCenterQuad =
{
AZ::Vector3( 0.18f, -0.50f, 0.0f).GetNormalized(),
AZ::Vector3(-0.08f, 0.59f, 0.0f).GetNormalized(),
@@ -54,7 +54,7 @@ namespace
};
// Various directions away from a point on the quad's surface
const AZStd::array<AZ::Vector3, RayCount> OffsetsFromSurface =
const AZStd::array<AZ::Vector3, RayCountQuad> OffsetsFromSurfaceQuad =
{
AZ::Vector3( 0.69f, 0.38f, 0.09f).GetNormalized(),
AZ::Vector3(-0.98f, -0.68f, -0.28f).GetNormalized(),
@@ -64,7 +64,7 @@ namespace
};
// Various distance away from the surface for the rays
const AZStd::array<float, RayCount> RayDistances =
const AZStd::array<float, RayCountQuad> RayDistancesQuad =
{
0.5f, 1.0f, 2.0f, 4.0f, 8.0f
};
@@ -248,23 +248,23 @@ namespace UnitTest
// Construct rays and test against the different quads
for (uint32_t quadIndex = 0; quadIndex < QuadCount; ++quadIndex)
{
for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex)
for (uint32_t rayIndex = 0; rayIndex < RayCountQuad; ++rayIndex)
{
// OffsetsFromCenter are all less than 1, so scale by the dimensions of the quad.
// OffsetsFromCenterQuad are all less than 1, so scale by the dimensions of the quad.
AZ::Vector3 scaledWidthHeight = AZ::Vector3(QuadDims[quadIndex].m_width, QuadDims[quadIndex].m_height, 0.0f);
// Scale the offset and multiply by 0.5 because distance from center is half the width/height
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenter[rayIndex] * scaledWidthHeight * 0.5f;
AZ::Vector3 scaledOffsetFromCenter = OffsetsFromCenterQuad[rayIndex] * scaledWidthHeight * 0.5f;
AZ::Vector3 positionOnQuadSurface = QuadTransforms[quadIndex].TransformPoint(scaledOffsetFromCenter);
AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex];
AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurfaceQuad[rayIndex] * RayDistancesQuad[rayIndex];
bool rayHit2 = false;
float distance2;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit2, quadEntities[quadIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
rayOrigin, -OffsetsFromSurface[rayIndex], distance2);
rayOrigin, -OffsetsFromSurfaceQuad[rayIndex], distance2);
EXPECT_TRUE(rayHit2);
EXPECT_NEAR(distance2, RayDistances[rayIndex], 1e-4f);
EXPECT_NEAR(distance2, RayDistancesQuad[rayIndex], 1e-4f);
}
}
@@ -297,20 +297,20 @@ namespace UnitTest
// Construct rays and test against the different quads
for (uint32_t quadIndex = 0; quadIndex < QuadCount; ++quadIndex)
{
for (uint32_t rayIndex = 0; rayIndex < RayCount; ++rayIndex)
for (uint32_t rayIndex = 0; rayIndex < RayCountQuad; ++rayIndex)
{
// OffsetsFromCenter are all less than 1, so scale by the dimensions of the quad.
// OffsetsFromCenterQuad are all less than 1, so scale by the dimensions of the quad.
AZ::Vector3 scaledWidthHeight = AZ::Vector3(QuadDims[quadIndex].m_width, QuadDims[quadIndex].m_height, 0.0f);
// Scale the offset and add 1.0 to OffsetsFromCenter to ensure the point is outside the quad.
AZ::Vector3 scaledOffsetFromCenter = (AZ::Vector3::CreateOne() + OffsetsFromCenter[rayIndex]) * scaledWidthHeight;
// Scale the offset and add 1.0 to OffsetsFromCenterQuad to ensure the point is outside the quad.
AZ::Vector3 scaledOffsetFromCenter = (AZ::Vector3::CreateOne() + OffsetsFromCenterQuad[rayIndex]) * scaledWidthHeight;
AZ::Vector3 positionOnQuadSurface = QuadTransforms[quadIndex].TransformPoint(scaledOffsetFromCenter);
AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurface[rayIndex] * RayDistances[rayIndex];
AZ::Vector3 rayOrigin = positionOnQuadSurface + OffsetsFromSurfaceQuad[rayIndex] * RayDistancesQuad[rayIndex];
bool rayHit2 = false;
float distance2;
LmbrCentral::ShapeComponentRequestsBus::EventResult(
rayHit2, quadEntities[quadIndex].GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
rayOrigin, -OffsetsFromSurface[rayIndex], distance2);
rayOrigin, -OffsetsFromSurfaceQuad[rayIndex], distance2);
EXPECT_FALSE(rayHit2);
}
@@ -21,13 +21,16 @@ namespace LmbrCentral
/// Type ID for the EditorBoxShapeComponent
static const AZ::Uuid EditorBoxShapeComponentTypeId = "{2ADD9043-48E8-4263-859A-72E0024372BF}";
/// Type ID for the BoxShapeConfig
static const AZ::Uuid BoxShapeConfigTypeId = "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}";
/// Configuration data for BoxShapeComponent
class BoxShapeConfig
: public ShapeComponentConfig
{
public:
AZ_CLASS_ALLOCATOR(BoxShapeConfig, AZ::SystemAllocator, 0)
AZ_RTTI(BoxShapeConfig, "{F034FBA2-AC2F-4E66-8152-14DFB90D6283}", ShapeComponentConfig)
AZ_RTTI(BoxShapeConfig, BoxShapeConfigTypeId, ShapeComponentConfig)
static void Reflect(AZ::ReflectContext* context);
@@ -50,6 +50,8 @@ set(FILES
Source/Shape/EditorDiskShapeComponent.cpp
Source/Shape/EditorBoxShapeComponent.h
Source/Shape/EditorBoxShapeComponent.cpp
Source/Shape/EditorAxisAlignedBoxShapeComponent.h
Source/Shape/EditorAxisAlignedBoxShapeComponent.cpp
Source/Shape/EditorCylinderShapeComponent.h
Source/Shape/EditorCylinderShapeComponent.cpp
Source/Shape/EditorCapsuleShapeComponent.h
@@ -106,6 +106,10 @@ set(FILES
Source/Shape/SphereShape.cpp
Source/Shape/SphereShapeComponent.h
Source/Shape/SphereShapeComponent.cpp
Source/Shape/AxisAlignedBoxShape.h
Source/Shape/AxisAlignedBoxShape.cpp
Source/Shape/AxisAlignedBoxShapeComponent.h
Source/Shape/AxisAlignedBoxShapeComponent.cpp
Source/Shape/BoxShape.h
Source/Shape/BoxShape.cpp
Source/Shape/BoxShapeComponent.h
@@ -8,6 +8,7 @@
set(FILES
Tests/AudioComponentTests.cpp
Tests/AxisAlignedBoxShapeTest.cpp
Tests/BoxShapeTest.cpp
Tests/BundlingSystemComponentTests.cpp
Tests/SphereShapeTest.cpp
@@ -78,6 +78,8 @@ namespace ScriptCanvas
variableIds.insert(scopedVariableId->m_identifier);
}
}
Node::CollectVariableReferences(variableIds);
}
bool EBusEventHandler::ContainsReferencesToVariables(const AZStd::unordered_set< ScriptCanvas::VariableId >& variableIds) const
@@ -90,11 +92,14 @@ namespace ScriptCanvas
if (scopedVariableId)
{
return variableIds.find(scopedVariableId->m_identifier) != variableIds.end();
if(variableIds.find(scopedVariableId->m_identifier) != variableIds.end())
{
return true;
}
}
}
return false;
return Node::ContainsReferencesToVariables(variableIds);
}
size_t EBusEventHandler::GenerateFingerprint() const
@@ -105,17 +105,19 @@ namespace Terrain
AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId());
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId());
TerrainAreaRequestBus::Handler::BusConnect(GetEntityId());
TerrainSpawnerRequestBus::Handler::BusConnect(GetEntityId());
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RegisterArea, GetEntityId());
}
void TerrainLayerSpawnerComponent::Deactivate()
{
TerrainAreaRequestBus::Handler::BusDisconnect();
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::UnregisterArea, GetEntityId());
AZ::TransformNotificationBus::Handler::BusDisconnect();
TerrainSpawnerRequestBus::Handler::BusDisconnect();
TerrainAreaRequestBus::Handler::BusDisconnect();
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect();
AZ::TransformNotificationBus::Handler::BusDisconnect();
}
bool TerrainLayerSpawnerComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
@@ -147,6 +149,17 @@ namespace Terrain
{
RefreshArea();
}
void TerrainLayerSpawnerComponent::GetPriority(AZ::u32& outLayer, AZ::u32& outPriority)
{
outLayer = m_configuration.m_layer;
outPriority = m_configuration.m_priority;
}
bool TerrainLayerSpawnerComponent::GetUseGroundPlane()
{
return m_configuration.m_useGroundPlane;
}
void TerrainLayerSpawnerComponent::RegisterArea()
{
@@ -59,6 +59,7 @@ namespace Terrain
, private AZ::TransformNotificationBus::Handler
, private LmbrCentral::ShapeComponentNotificationsBus::Handler
, private Terrain::TerrainAreaRequestBus::Handler
, private Terrain::TerrainSpawnerRequestBus::Handler
{
public:
template<typename, typename>
@@ -80,7 +81,6 @@ namespace Terrain
bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
//////////////////////////////////////////////////////////////////////////
// AZ::TransformNotificationBus::Handler
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
@@ -88,6 +88,10 @@ namespace Terrain
// ShapeComponentNotificationsBus
void OnShapeChanged(ShapeChangeReasons changeReason) override;
// TerrainSpawnerRequestBus
void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) override;
bool GetUseGroundPlane() override;
void RegisterArea() override;
void RefreshArea() override;
@@ -17,6 +17,33 @@
using namespace Terrain;
bool TerrainLayerPriorityComparator::operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const
{
// Comparator for insertion/keylookup.
// Sorts into layer/priority order, highest priority first.
AZ::u32 priority1, layer1;
Terrain::TerrainSpawnerRequestBus::Event(layer1id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer1, priority1);
AZ::u32 priority2, layer2;
Terrain::TerrainSpawnerRequestBus::Event(layer2id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer2, priority2);
if (layer1 < layer2)
{
return false;
}
else if (layer1 > layer2)
{
return true;
}
if (priority1 != priority2)
{
return priority1 > priority2;
}
return layer1id > layer2id;
}
TerrainSystem::TerrainSystem()
{
Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect();
@@ -78,17 +105,14 @@ float TerrainSystem::GetHeightSynchronous(float x, float y) const
AZStd::shared_lock<AZStd::shared_mutex> lock(m_areaMutex);
if (!m_registeredAreas.empty())
for (auto& [areaId, areaBounds] : m_registeredAreas)
{
for (auto& [areaId, areaBounds] : m_registeredAreas)
inPosition.SetZ(areaBounds.GetMin().GetZ());
if (areaBounds.Contains(inPosition))
{
inPosition.SetZ(areaBounds.GetMin().GetZ());
if (areaBounds.Contains(inPosition))
{
Terrain::TerrainAreaHeightRequestBus::Event(
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition,
Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT);
}
Terrain::TerrainAreaHeightRequestBus::Event(
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition,
Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT);
}
}
@@ -305,26 +329,34 @@ void TerrainSystem::SystemDeactivate()
void TerrainSystem::RegisterArea(AZ::EntityId areaId)
{
{
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
AZ::Aabb aabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas[areaId] = aabb;
}
RefreshArea(areaId);
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
AZ::Aabb aabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas[areaId] = aabb;
m_dirtyRegion.AddAabb(aabb);
m_terrainHeightDirty = true;
}
void TerrainSystem::UnregisterArea(AZ::EntityId areaId)
{
{
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
AZ::Aabb aabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas.erase(areaId);
}
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
RefreshArea(areaId);
// Remove the data for this entity from the registered areas.
// Erase_if is used as erase would use the comparator to lookup the entity id in the map.
// As the comparator will get the new layer/priority data for the entity, the id lookup will fail.
AZStd::erase_if(
m_registeredAreas,
[areaId, this](const auto& item)
{
auto const& [entityId, aabb] = item;
if (areaId == entityId)
{
m_dirtyRegion.AddAabb(aabb);
m_terrainHeightDirty = true;
return true;
}
return false;
});
}
void TerrainSystem::RefreshArea(AZ::EntityId areaId)
@@ -336,7 +368,6 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId)
AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second : AZ::Aabb::CreateNull();
AZ::Aabb newAabb = AZ::Aabb::CreateNull();
LmbrCentral::ShapeComponentRequestsBus::EventResult(newAabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
m_registeredAreas[areaId] = newAabb;
AZ::Aabb expandedAabb = oldAabb;
@@ -400,31 +431,37 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
const uint32_t pixelDataSize = width * height * sizeof(float);
memset(pixels.data(), 0, pixelDataSize);
for (auto& [areaId, areaBounds] : m_registeredAreas)
for (uint32_t y = 0; y < height; y++)
{
for (uint32_t y = 0; y < height; y++)
for (uint32_t x = 0; x < width; x++)
{
for (uint32_t x = 0; x < width; x++)
// Find the first terrain layer that covers this position. This will be the highest priority, so others can be ignored.
for (auto& [areaId, areaBounds] : m_registeredAreas)
{
AZ::Vector3 inPosition(
(x * m_currentSettings.m_heightQueryResolution.GetX()) + m_currentSettings.m_worldBounds.GetMin().GetX(),
(y * m_currentSettings.m_heightQueryResolution.GetY()) + m_currentSettings.m_worldBounds.GetMin().GetY(),
areaBounds.GetMin().GetZ());
if (areaBounds.Contains(inPosition))
if (!areaBounds.Contains(inPosition))
{
AZ::Vector3 outPosition;
const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter =
Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT;
Terrain::TerrainAreaHeightRequestBus::Event(
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter);
pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) /
m_currentSettings.m_worldBounds.GetExtents().GetZ();
continue;
}
AZ::Vector3 outPosition;
const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter = Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT;
Terrain::TerrainAreaHeightRequestBus::Event(
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter);
pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) /
m_currentSettings.m_worldBounds.GetExtents().GetZ();
break;
}
}
}
const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
auto terrainFeatureProcessor = scene->GetFeatureProcessor<TerrainFeatureProcessor>();
@@ -25,6 +25,11 @@
namespace Terrain
{
struct TerrainLayerPriorityComparator
{
bool operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const;
};
class TerrainSystem
: public AzFramework::Terrain::TerrainDataRequestBus::Handler
, private Terrain::TerrainSystemServiceRequestBus::Handler
@@ -112,6 +117,6 @@ namespace Terrain
AZ::Aabb m_dirtyRegion;
mutable AZStd::shared_mutex m_areaMutex;
AZStd::unordered_map<AZ::EntityId, AZ::Aabb> m_registeredAreas;
AZStd::map<AZ::EntityId, AZ::Aabb, TerrainLayerPriorityComparator> m_registeredAreas;
};
} // namespace Terrain
@@ -112,5 +112,26 @@ namespace Terrain
};
using TerrainAreaHeightRequestBus = AZ::EBus<TerrainAreaHeightRequests>;
/**
* A bus for the TerrainSystem to interrogate TerrainLayerSpawners.
*/
class TerrainSpawnerRequests
: public AZ::ComponentBus
{
public:
////////////////////////////////////////////////////////////////////////
// EBusTraits
using MutexType = AZStd::recursive_mutex;
////////////////////////////////////////////////////////////////////////
virtual ~TerrainSpawnerRequests() = default;
virtual void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) = 0;
virtual bool GetUseGroundPlane() = 0;
};
using TerrainSpawnerRequestBus = AZ::EBus<TerrainSpawnerRequests>;
}
@@ -0,0 +1,222 @@
/*
* 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/Component/ComponentApplication.h>
#include <AzCore/Memory/MemoryComponent.h>
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
#include <Components/TerrainLayerSpawnerComponent.h>
#include <LmbrCentral/Shape/BoxShapeComponentBus.h>
#include <AzTest/AzTest.h>
#include <TerrainMocks.h>
class LayerSpawnerComponentTest
: public ::testing::Test
{
protected:
AZ::ComponentApplication m_app;
AZStd::unique_ptr<AZ::Entity> m_entity;
Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent;
UnitTest::MockBoxShapeComponent* m_shapeComponent;
AZStd::unique_ptr<UnitTest::MockTerrainSystem> m_terrainSystem;
void SetUp() override
{
AZ::ComponentApplication::Descriptor appDesc;
appDesc.m_memoryBlocksByteSize = 20 * 1024 * 1024;
appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_NO_RECORDS;
appDesc.m_stackRecordLevels = 20;
m_app.Create(appDesc);
}
void TearDown() override
{
if (m_terrainSystem)
{
m_terrainSystem->Deactivate();
}
m_app.Destroy();
}
void CreateEntity()
{
m_entity = AZStd::make_unique<AZ::Entity>();
m_entity->Init();
ASSERT_TRUE(m_entity);
}
void AddLayerSpawnerAndShapeComponentToEntity()
{
AddLayerSpawnerAndShapeComponentToEntity(Terrain::TerrainLayerSpawnerConfig());
}
void AddLayerSpawnerAndShapeComponentToEntity(const Terrain::TerrainLayerSpawnerConfig& config)
{
m_layerSpawnerComponent = m_entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(config);
m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor());
m_shapeComponent = m_entity->CreateComponent<UnitTest::MockBoxShapeComponent>();
m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor());
ASSERT_TRUE(m_layerSpawnerComponent);
ASSERT_TRUE(m_shapeComponent);
}
void ResetEntity()
{
m_entity->Deactivate();
m_entity->Reset();
}
void CreateMockTerrainSystem()
{
m_terrainSystem = AZStd::make_unique<UnitTest::MockTerrainSystem>();
m_terrainSystem->Activate();
}
};
TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess)
{
CreateEntity();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect)
{
CreateEntity();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
AZ::u32 priority = 999, layer = 999;
Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
EXPECT_EQ(0, priority);
EXPECT_EQ(1, layer);
bool useGroundPlane = false;
Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
EXPECT_TRUE(useGroundPlane);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect)
{
CreateEntity();
constexpr static AZ::u32 testPriority = 15;
constexpr static AZ::u32 testLayer = 0;
Terrain::TerrainLayerSpawnerConfig config;
config.m_layer = testLayer;
config.m_priority = testPriority;
config.m_useGroundPlane = false;
AddLayerSpawnerAndShapeComponentToEntity(config);
m_entity->Activate();
AZ::u32 priority = 999, layer = 999;
Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
EXPECT_EQ(testPriority, priority);
EXPECT_EQ(testLayer, layer);
bool useGroundPlane = true;
Terrain::TerrainSpawnerRequestBus::EventResult(
useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
EXPECT_FALSE(useGroundPlane);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem)
{
CreateEntity();
CreateMockTerrainSystem();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
// The Activate call should have registered the area.
EXPECT_EQ(1, m_terrainSystem->m_registerAreaCalledCount);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem)
{
CreateEntity();
CreateMockTerrainSystem();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
m_layerSpawnerComponent->Deactivate();
// The Deactivate call should have unregistered the area.
EXPECT_EQ(1, m_terrainSystem->m_unregisterAreaCalledCount);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem)
{
CreateEntity();
CreateMockTerrainSystem();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
AZ::TransformNotificationBus::Event(
m_entity->GetId(), &AZ::TransformNotificationBus::Events::OnTransformChanged, AZ::Transform(), AZ::Transform());
EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount);
ResetEntity();
}
TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem)
{
CreateEntity();
CreateMockTerrainSystem();
AddLayerSpawnerAndShapeComponentToEntity();
m_entity->Activate();
LmbrCentral::ShapeComponentNotificationsBus::Event(
m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged,
LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged);
EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount);
ResetEntity();
}
+104
View File
@@ -0,0 +1,104 @@
/*
* 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/Component/ComponentApplication.h>
#include <LmbrCentral/Shape/ShapeComponentBus.h>
namespace UnitTest
{
static const AZ::Uuid BoxShapeComponentTypeId = "{5EDF4B9E-0D3D-40B8-8C91-5142BCFC30A6}";
class MockBoxShapeComponent
: public AZ::Component
{
public:
AZ_COMPONENT(MockBoxShapeComponent, BoxShapeComponentTypeId)
static void Reflect([[maybe_unused]] AZ::ReflectContext* context)
{
}
void Activate() override
{
}
void Deactivate() override
{
}
bool ReadInConfig([[maybe_unused]] const AZ::ComponentConfig* baseConfig) override
{
return true;
}
bool WriteOutConfig([[maybe_unused]] AZ::ComponentConfig* outBaseConfig) const override
{
return true;
}
private:
static void GetProvidedServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe));
provided.push_back(AZ_CRC("BoxShapeService", 0x946a0032));
}
static void GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
}
static void GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
{
}
static void GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
}
};
class MockTerrainSystem : private Terrain::TerrainSystemServiceRequestBus::Handler
{
public:
void Activate() override
{
Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect();
}
void Deactivate() override
{
Terrain::TerrainSystemServiceRequestBus::Handler::BusDisconnect();
}
void SetWorldBounds(const AZ::Aabb& worldBounds) override
{
}
void SetHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override
{
}
void RegisterArea([[maybe_unused]] AZ::EntityId areaId) override
{
m_registerAreaCalledCount++;
}
void UnregisterArea([[maybe_unused]] AZ::EntityId areaId) override
{
m_unregisterAreaCalledCount++;
}
void RefreshArea([[maybe_unused]] AZ::EntityId areaId) override
{
m_refreshAreaCalledCount++;
}
int m_registerAreaCalledCount = 0;
int m_refreshAreaCalledCount = 0;
int m_unregisterAreaCalledCount = 0;
};
}
@@ -7,5 +7,7 @@
#
set(FILES
Tests/TerrainMocks.h
Tests/TerrainTest.cpp
Tests/LayerSpawnerTests.cpp
)
@@ -11,7 +11,6 @@ ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5
ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023)
ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf)
ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-android TARGETS lz4 PACKAGE_HASH da8ec7736640a3e9834f6db1c69e8a0ea61c054fe8b6324509f36928cfc21dc9)
ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418)
ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665)
ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee)
@@ -28,3 +27,5 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-android TARGETS Goo
ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-android TARGETS libsamplerate PACKAGE_HASH bf13662afe65d02bcfa16258a4caa9b875534978227d6f9f36c9cfa92b3fb12b)
ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-android TARGETS OpenSSL PACKAGE_HASH 4036d4019d722f0e1b7a1621bf60b5a17ca6a65c9c78fd8701cee1131eec8480)
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-android TARGETS zlib PACKAGE_HASH 85b730b97176772538cfcacd6b6aaf4655fc2d368d134d6dd55e02f28f183826)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-android TARGETS lz4 PACKAGE_HASH f5b22642d218dbbb442cae61e469e5b241c4740acd258c3e8678e60dec61ea93)
+2 -4
View File
@@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform
ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf)
ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b)
ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-linux TARGETS lz4 PACKAGE_HASH 2e2653ce04a036c38fe28f3971bc3bfb8a4e771335aa8d1b95b0feb3423f1b0a)
ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418)
ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665)
ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4)
@@ -28,7 +27,7 @@ ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform
ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af)
ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-linux TARGETS freetype PACKAGE_HASH 9ad246873067717962c6b780d28a5ce3cef3321b73c9aea746a039c798f52e93)
ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-linux TARGETS tiff PACKAGE_HASH ae92b4d3b189c42ef644abc5cac865d1fb2eb7cb5622ec17e35642b00d1a0a76)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-linux TARGETS AWSNativeSDK PACKAGE_HASH 0101a4052d9fce83a6f5515e00f366e97b308ecb8261ad23a6e4eb4365212ab6)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4)
ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0)
ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-linux TARGETS PhysX PACKAGE_HASH a110249cbef4f266b0002c4ee9a71f59f373040cefbe6b82f1e1510c811edde6)
ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430)
@@ -46,5 +45,4 @@ ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev2-linux
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-linux TARGETS zlib PACKAGE_HASH 16f3b9e11cda525efb62144f354c1cfc30a5def9eff020dbe49cb00ee7d8234f)
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-linux TARGETS squish-ccr PACKAGE_HASH 85fecafbddc6a41a27c5f59ed4a5dfb123a94cb4666782cf26e63c0a4724c530)
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-linux TARGETS ISPCTexComp PACKAGE_HASH 065fd12abe4247dde247330313763cf816c3375c221da030bdec35024947f259)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-linux TARGETS lz4 PACKAGE_HASH 5de3dbd3e2a3537c6555d759b3c5bb98e5456cf85c74ff6d046f809b7087290d)
+2 -2
View File
@@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform
ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf)
ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b)
ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-mac TARGETS lz4 PACKAGE_HASH 3ce6866b43d024452c0412f385ae46aba0e1ae99eb64f7099d3fc539c8460881)
ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418)
ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665)
ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4)
@@ -30,7 +29,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-ma
ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515)
ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-mac-ios TARGETS freetype PACKAGE_HASH 67b4f57aed92082d3fd7c16aa244a7d908d90122c296b0a63f73e0a0b8761977)
ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-mac-ios TARGETS tiff PACKAGE_HASH a23ae1f8991a29f8e5df09d6d5b00d7768a740f90752cef465558c1768343709)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-mac TARGETS AWSNativeSDK PACKAGE_HASH 89e1651cde6b4e6bd80cdb96ed6b624accad9f9688ff38bfca226777f4fcb678)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01)
ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08)
ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e)
ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818)
@@ -44,4 +43,5 @@ ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-mac
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-mac TARGETS zlib PACKAGE_HASH 21714e8a6de4f2523ee92a7f52d51fbee29c5f37ced334e00dc3c029115b472e)
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-mac TARGETS squish-ccr PACKAGE_HASH 155bfbfa17c19a9cd2ef025de14c5db598f4290045d5b0d83ab58cb345089a77)
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-mac TARGETS ISPCTexComp PACKAGE_HASH 8a4e93277b8face6ea2fd57c6d017bdb55643ed3d6387110bc5f6b3b884dd169)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-mac TARGETS lz4 PACKAGE_HASH 891ff630bf34f7ab1d8eaee2ea0a8f1fca89dbdc63fca41ee592703dd488a73b)
@@ -15,7 +15,6 @@ ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform
ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf)
ly_associate_package(PACKAGE_NAME pybind11-2.4.3-rev2-multiplatform TARGETS pybind11 PACKAGE_HASH d8012f907b6c54ac990b899a0788280857e7c93a9595405a28114b48c354eb1b)
ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-windows TARGETS lz4 PACKAGE_HASH 02e6ba2ca1407483bac082fd97803c5e19f48bc576171bfc8cec62412efe639c)
ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418)
ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665)
ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform TARGETS SQLite PACKAGE_HASH dd4d3de6cbb4ce3d15fc504ba0ae0587e515dc89a25228037035fc0aef4831f4)
@@ -31,7 +30,7 @@ ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-wi
ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817)
ly_associate_package(PACKAGE_NAME freetype-2.10.4.14-windows TARGETS freetype PACKAGE_HASH 88dedc86ccb8c92f14c2c033e51ee7d828fa08eafd6475c6aa963938a99f4bf3)
ly_associate_package(PACKAGE_NAME tiff-4.2.0.14-windows TARGETS tiff PACKAGE_HASH ab60d1398e4e1e375ec0f1a00cdb1d812a07c0096d827db575ce52dd6d714207)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev3-windows TARGETS AWSNativeSDK PACKAGE_HASH 929873d4252c464620a9d288e41bd5d47c0bd22750aeb3a1caa68a3da8247c48)
ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c)
ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40)
ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-windows TARGETS PhysX PACKAGE_HASH 0c5ffbd9fa588e5cf7643721a7cfe74d0fe448bf82252d39b3a96d06dfca2298)
ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123)
@@ -51,3 +50,4 @@ ly_associate_package(PACKAGE_NAME Crashpad-0.8.0-rev1-windows
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-windows TARGETS zlib PACKAGE_HASH 9afab1d67641ed8bef2fb38fc53942da47f2ab339d9e77d3d20704a48af2da0b)
ly_associate_package(PACKAGE_NAME squish-ccr-deb557d-rev1-windows TARGETS squish-ccr PACKAGE_HASH 5c3d9fa491e488ccaf802304ad23b932268a2b2846e383f088779962af2bfa84)
ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-windows TARGETS ISPCTexComp PACKAGE_HASH b6fa6ea28a2808a9a5524c72c37789c525925e435770f2d94eb2d387360fa2d0)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-windows TARGETS lz4 PACKAGE_HASH 4ea457b833cd8cfaf8e8e06ed6df601d3e6783b606bdbc44a677f77e19e0db16)
+1 -1
View File
@@ -11,7 +11,6 @@ ly_associate_package(PACKAGE_NAME md5-2.0-multiplatform TARGETS md5
ly_associate_package(PACKAGE_NAME RapidJSON-1.1.0-rev1-multiplatform TARGETS RapidJSON PACKAGE_HASH 2f5e26ecf86c3b7a262753e7da69ac59928e78e9534361f3d00c1ad5879e4023)
ly_associate_package(PACKAGE_NAME RapidXML-1.13-multiplatform TARGETS RapidXML PACKAGE_HASH 510b3c12f8872c54b34733e34f2f69dd21837feafa55bfefa445c98318d96ebf)
ly_associate_package(PACKAGE_NAME cityhash-1.1-multiplatform TARGETS cityhash PACKAGE_HASH 0ace9e6f0b2438c5837510032d2d4109125845c0efd7d807f4561ec905512dd2)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev1-ios TARGETS lz4 PACKAGE_HASH 7a9391daf53e47e529cf811dca3554c83769f62a2ee52488610ec73214961ae1)
ly_associate_package(PACKAGE_NAME expat-2.1.0-multiplatform TARGETS expat PACKAGE_HASH 452256acd1fd699cef24162575b3524fccfb712f5321c83f1df1ce878de5b418)
ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zstd PACKAGE_HASH 45d466c435f1095898578eedde85acf1fd27190e7ea99aeaa9acfd2f09e12665)
ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee)
@@ -29,3 +28,4 @@ ly_associate_package(PACKAGE_NAME googlebenchmark-1.5.0-rev2-ios TARGETS GoogleB
ly_associate_package(PACKAGE_NAME libsamplerate-0.2.1-rev2-ios TARGETS libsamplerate PACKAGE_HASH 7656b961697f490d4f9c35d2e61559f6fc38c32102e542a33c212cd618fc2119)
ly_associate_package(PACKAGE_NAME OpenSSL-1.1.1b-rev1-ios TARGETS OpenSSL PACKAGE_HASH cd0dfce3086a7172777c63dadbaf0ac3695b676119ecb6d0614b5fb1da03462f)
ly_associate_package(PACKAGE_NAME zlib-1.2.11-rev2-ios TARGETS zlib PACKAGE_HASH a59fc0f83a02c616b679799310e9d86fde84514c6d2acefa12c6def0ae4a880c)
ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-ios TARGETS lz4 PACKAGE_HASH 588ea05739caa9231a9a17a1e8cf64c5b9a265e16528bc05420af7e2534e86c1)
+24
View File
@@ -415,6 +415,19 @@ def ExportTestResults(Map options, String platform, String type, String workspac
}
}
def ExportTestScreenshots(Map options, String workspace, String platformName, String jobName, Map params) {
catchError(message: "Error exporting test screenshots (this won't fail the build)", buildResult: 'SUCCESS', stageResult: 'FAILURE') {
def screenshotsFolder = '${workspace}/${ENGINE_REPOSITORY_NAME}/AutomatedTesting/user/PythonTests/Automated/Screenshots'
def s3Uploader = '${workspace}/${ENGINE_REPOSITORY_NAME}/scripts/build/tools/upload_to_s3.py'
def command = '${options.PYTHON_DIR}/python.cmd -u ${s3Uploader} --base_dir ${screenshotsFolder} ' +
'--file_regex "(.*zip$)" --bucket ${env.TEST_SCREENSHOT_BUCKET} ' +
'--search_subdirectories True --key_prefix ${branchName}_${env.BUILD_NUMBER}' +
'--extra-args {"ACL": "bucket-owner-full-control"}'
bat label: "Uploading test screenshots for ${jobName}",
script: command
}
}
def PostBuildCommonSteps(String workspace, boolean mount = true) {
echo 'Starting post-build common steps...'
@@ -470,6 +483,14 @@ def CreateExportTestResultsStage(Map pipelineConfig, String platformName, String
}
}
def CreateExportTestScreenshotsStage(Map pipelineConfig, String platformName, String jobName, Map environmentVars, Map params) {
return {
stage("${jobName}_screenshots") {
ExportTestScreenshots(pipelineConfig, platformName, jobName, environmentVars['WORKSPACE'], params)
}
}
}
def CreateTeardownStage(Map environmentVars) {
return {
stage('Teardown') {
@@ -532,6 +553,9 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar
if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') {
CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call()
}
if (params && params.containsKey('TEST_SCREENSHOTS') && params.TEST_SCREENSHOTS == 'True' && currentResult == 'FAILURE') {
CreateExportTestScreenshotsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call()
}
CreateTeardownStage(envVars).call()
}
}