Integrating github/staging through commit b0dd7ed

This commit is contained in:
alexpete
2021-04-09 12:03:26 -07:00
parent 1044dc3da1
commit c5b955d281
180 changed files with 6416 additions and 1850 deletions
+4
View File
@@ -71,10 +71,14 @@ COMPILE_TIME_ASSERT(sizeof(uint32) == 4);
COMPILE_TIME_ASSERT(sizeof(sint32) == 4);
typedef slonglong int64;
#ifndef O3DE_INT64_DEFINED
#define O3DE_INT64_DEFINED
typedef slonglong sint64;
typedef ulonglong uint64;
COMPILE_TIME_ASSERT(sizeof(uint64) == 8);
COMPILE_TIME_ASSERT(sizeof(sint64) == 8);
#endif
typedef float f32;
+1 -1
View File
@@ -19,6 +19,6 @@ ly_add_target(
.
BUILD_DEPENDENCIES
PRIVATE
3rdParty::FreeType2
3rdParty::freetype
Legacy::CryCommon
)
+1 -1
View File
@@ -22,7 +22,7 @@
#endif
#if !(defined(ANDROID) || defined(IOS) || defined(LINUX)) && AZ_LEGACY_CRYSYSTEM_TRAIT_IMAGEHANDLER_TIFFIO // Rally US1050 - Compile libtiff for Android and IOS
#include <libtiff/tiffio.h>
#include <tiffio.h>
static_assert(sizeof(thandle_t) >= sizeof(AZ::IO::HandleType), "Platform defines thandle_t to be smaller than required");
#endif
@@ -43,6 +43,9 @@ namespace AZ
{
const static AZ::Crc32 RuntimeEBusAttribute = AZ_CRC("RuntimeEBus", 0x466b899b); ///< Signals that this reflected ebus should only be available at runtime, helps tools filter out data driven ebuses
constexpr const char* k_PropertyNameGetterSuffix = "::Getter";
constexpr const char* k_PropertyNameSetterSuffix = "::Setter";
/// Typedef for class unwrapping callback (i.e. used for things like smart_ptr<T> to unwrap for T)
using BehaviorClassUnwrapperFunction = void(*)(void* /*classPtr*/, void*& /*unwrappedClass*/, AZ::Uuid& /*unwrappedClassTypeId*/, void* /*userData*/);
@@ -2525,7 +2528,7 @@ namespace AZ
getterPropertyName += "::";
}
getterPropertyName += m_name;
getterPropertyName += "::Getter";
getterPropertyName += k_PropertyNameGetterSuffix;
m_getter = aznew GetterType(getter, context, getterPropertyName);
if (AZStd::is_class<typename GetterType::ClassType>::value)
@@ -2603,7 +2606,7 @@ namespace AZ
setterPropertyName += "::";
}
setterPropertyName += m_name;
setterPropertyName += "::Setter";
setterPropertyName += k_PropertyNameSetterSuffix;
m_setter = aznew SetterType(setter, context, setterPropertyName);
if (AZStd::is_class<typename SetterType::ClassType>::value)
{
@@ -243,6 +243,28 @@ namespace AZ
return variance;
}
void RemovePropertyGetterNameArtifacts(AZStd::string& name)
{
if (name.ends_with(k_PropertyNameGetterSuffix))
{
AZ::StringFunc::Replace(name, k_PropertyNameGetterSuffix, "");
}
}
void RemovePropertySetterNameArtifacts(AZStd::string& name)
{
if (name.ends_with(k_PropertyNameSetterSuffix))
{
AZ::StringFunc::Replace(name, k_PropertyNameSetterSuffix, "");
}
}
void RemovePropertyNameArtifacts(AZStd::string& name)
{
RemovePropertyGetterNameArtifacts(name);
RemovePropertySetterNameArtifacts(name);
}
AZStd::string ReplaceCppArtifacts(AZStd::string_view sourceName)
{
using namespace AZ::StringFunc;
@@ -68,6 +68,12 @@ namespace AZ
AZStd::vector<AZStd::pair<const BehaviorMethod*, const BehaviorClass*>> OverloadsToVector(const BehaviorMethod&, const BehaviorClass*);
void RemovePropertyGetterNameArtifacts(AZStd::string& name);
void RemovePropertySetterNameArtifacts(AZStd::string& name);
void RemovePropertyNameArtifacts(AZStd::string& name);
AZStd::string ReplaceCppArtifacts(AZStd::string_view sourceName);
void StripQualifiers(AZStd::string& name);
@@ -0,0 +1,531 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "CameraInput.h"
#include <AzCore/Math/MathUtils.h>
#include <AzCore/Math/Plane.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Windowing/WindowBus.h>
namespace AzFramework
{
void CameraSystem::HandleEvents(const InputEvent& event)
{
if (const auto& cursor_motion = AZStd::get_if<CursorMotionEvent>(&event))
{
m_currentCursorPosition = cursor_motion->m_position;
}
else if (const auto& scroll = AZStd::get_if<ScrollEvent>(&event))
{
m_scrollDelta = scroll->m_delta;
}
m_cameras.HandleEvents(event);
}
Camera CameraSystem::StepCamera(const Camera& targetCamera, float deltaTime)
{
const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value()
? m_currentCursorPosition.value() - m_lastCursorPosition.value()
: ScreenVector(0, 0);
if (m_currentCursorPosition.has_value())
{
m_lastCursorPosition = m_currentCursorPosition;
}
const auto nextCamera = m_cameras.StepCamera(targetCamera, cursorDelta, m_scrollDelta, deltaTime);
m_scrollDelta = 0.0f;
return nextCamera;
}
void Cameras::AddCamera(AZStd::shared_ptr<CameraInput> camera_input)
{
m_idleCameraInputs.push_back(AZStd::move(camera_input));
}
void Cameras::HandleEvents(const InputEvent& event)
{
for (auto& camera_input : m_activeCameraInputs)
{
camera_input->HandleEvents(event);
}
for (auto& camera_input : m_idleCameraInputs)
{
camera_input->HandleEvents(event);
}
}
Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime)
{
for (int i = 0; i < m_idleCameraInputs.size();)
{
auto& camera_input = m_idleCameraInputs[i];
const bool can_begin = camera_input->Beginning() &&
std::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(),
[](const auto& input) { return !input->Exclusive(); }) &&
(!camera_input->Exclusive() || (camera_input->Exclusive() && m_activeCameraInputs.empty()));
if (can_begin)
{
m_activeCameraInputs.push_back(camera_input);
using AZStd::swap;
swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]);
m_idleCameraInputs.pop_back();
}
else
{
i++;
}
}
// accumulate
Camera nextCamera = targetCamera;
for (auto& camera_input : m_activeCameraInputs)
{
nextCamera = camera_input->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
}
for (int i = 0; i < m_activeCameraInputs.size();)
{
auto& camera_input = m_activeCameraInputs[i];
if (camera_input->Ending())
{
camera_input->ClearActivation();
m_idleCameraInputs.push_back(camera_input);
using AZStd::swap;
swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
m_activeCameraInputs.pop_back();
}
else
{
camera_input->ContinueActivation();
i++;
}
}
return nextCamera;
}
void Cameras::Reset()
{
for (int i = 0; i < m_activeCameraInputs.size();)
{
m_activeCameraInputs[i]->Reset();
m_idleCameraInputs.push_back(m_activeCameraInputs[i]);
m_activeCameraInputs[i] = m_activeCameraInputs[m_activeCameraInputs.size() - 1];
m_activeCameraInputs.pop_back();
}
}
void RotateCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == m_channelId)
{
if (input->m_state == InputChannel::State::Began)
{
BeginActivation();
}
else if (input->m_state == InputChannel::State::Ended)
{
EndActivation();
}
}
}
}
Camera RotateCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
nextCamera.m_pitch += float(cursorDelta.m_y) * m_props.m_rotateSpeed;
nextCamera.m_yaw += float(cursorDelta.m_x) * m_props.m_rotateSpeed;
auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoOverPi, AZ::Constants::TwoOverPi); };
nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw);
// clamp pitch to be +-90 degrees
nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::Pi * 0.5f, AZ::Constants::Pi * 0.5f);
return nextCamera;
}
void PanCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == InputDeviceMouse::Button::Middle)
{
if (input->m_state == InputChannel::State::Began)
{
BeginActivation();
}
else if (input->m_state == InputChannel::State::Ended)
{
EndActivation();
}
}
}
}
Camera PanCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
const auto pan_axes = m_panAxesFn(nextCamera);
const auto delta_pan_x = float(cursorDelta.m_x) * pan_axes.m_horizontalAxis * m_props.m_panSpeed;
const auto delta_pan_y = float(cursorDelta.m_y) * pan_axes.m_verticalAxis * m_props.m_panSpeed;
const auto inv = [](const bool invert) {
constexpr float Dir[] = {1.0f, -1.0f};
return Dir[static_cast<int>(invert)];
};
nextCamera.m_lookAt += delta_pan_x * inv(m_props.m_panInvertX);
nextCamera.m_lookAt += delta_pan_y * -inv(m_props.m_panInvertY);
return nextCamera;
}
TranslateCameraInput::TranslationType TranslateCameraInput::translationFromKey(InputChannelId channelId)
{
// note: remove hard-coded InputDevice keys
if (channelId == InputDeviceKeyboard::Key::AlphanumericW)
{
return TranslationType::Forward;
}
if (channelId == InputDeviceKeyboard::Key::AlphanumericS)
{
return TranslationType::Backward;
}
if (channelId == InputDeviceKeyboard::Key::AlphanumericA)
{
return TranslationType::Left;
}
if (channelId == InputDeviceKeyboard::Key::AlphanumericD)
{
return TranslationType::Right;
}
if (channelId == InputDeviceKeyboard::Key::AlphanumericQ)
{
return TranslationType::Down;
}
if (channelId == InputDeviceKeyboard::Key::AlphanumericE)
{
return TranslationType::Up;
}
return TranslationType::Nil;
}
void TranslateCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_state == InputChannel::State::Began)
{
if (input->m_state == InputChannel::State::Updated)
{
return;
}
m_translation |= translationFromKey(input->m_channelId);
if (m_translation != TranslationType::Nil)
{
BeginActivation();
}
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
{
m_boost = true;
}
}
else if (input->m_state == InputChannel::State::Ended)
{
m_translation ^= translationFromKey(input->m_channelId);
if (m_translation == TranslationType::Nil)
{
EndActivation();
}
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
{
m_boost = false;
}
}
}
}
Camera TranslateCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
const float deltaTime)
{
Camera nextCamera = targetCamera;
const auto translation_basis = m_translationAxesFn(nextCamera);
const auto axisX = translation_basis.GetBasisX();
const auto axisY = translation_basis.GetBasisY();
const auto axisZ = translation_basis.GetBasisZ();
const float speed = [boost = m_boost, props = m_props]() {
return props.m_translateSpeed * (boost ? props.m_boostMultiplier : 1.0f);
}();
if ((m_translation & TranslationType::Forward) == TranslationType::Forward)
{
nextCamera.m_lookAt += axisY * speed * deltaTime;
}
if ((m_translation & TranslationType::Backward) == TranslationType::Backward)
{
nextCamera.m_lookAt -= axisY * speed * deltaTime;
}
if ((m_translation & TranslationType::Left) == TranslationType::Left)
{
nextCamera.m_lookAt -= axisX * speed * deltaTime;
}
if ((m_translation & TranslationType::Right) == TranslationType::Right)
{
nextCamera.m_lookAt += axisX * speed * deltaTime;
}
if ((m_translation & TranslationType::Up) == TranslationType::Up)
{
nextCamera.m_lookAt += axisZ * speed * deltaTime;
}
if ((m_translation & TranslationType::Down) == TranslationType::Down)
{
nextCamera.m_lookAt -= axisZ * speed * deltaTime;
}
if (Ending())
{
m_translation = TranslationType::Nil;
}
return nextCamera;
}
void TranslateCameraInput::ResetImpl()
{
m_translation = TranslationType::Nil;
m_boost = false;
}
void OrbitCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierAltL)
{
if (input->m_state == InputChannel::State::Updated)
{
goto end;
}
if (input->m_state == InputChannel::State::Began)
{
BeginActivation();
}
else if (input->m_state == InputChannel::State::Ended)
{
EndActivation();
}
}
}
end:
if (Active())
{
m_orbitCameras.HandleEvents(event);
}
}
Camera OrbitCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, float deltaTime)
{
Camera nextCamera = targetCamera;
if (Beginning())
{
float hit_distance = 0.0f;
if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateZero())
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY() * m_props.m_maxOrbitDistance, hit_distance))
{
nextCamera.m_lookDist = -hit_distance;
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * hit_distance;
}
else
{
nextCamera.m_lookDist = -m_props.m_defaultOrbitDistance;
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * m_props.m_defaultOrbitDistance;
}
}
if (Active())
{
// todo: need to return nested cameras to idle state when ending
nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
}
if (Ending())
{
m_orbitCameras.Reset();
nextCamera.m_lookAt = nextCamera.Translation();
nextCamera.m_lookDist = 0.0f;
}
return nextCamera;
}
void OrbitDollyScrollCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
{
BeginActivation();
}
}
Camera OrbitDollyScrollCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
[[maybe_unused]] float deltaTime)
{
Camera nextCamera = targetCamera;
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_props.m_dollySpeed, 0.0f);
EndActivation();
return nextCamera;
}
void OrbitDollyCursorMoveCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == InputDeviceMouse::Button::Right)
{
if (input->m_state == InputChannel::State::Began)
{
BeginActivation();
}
else if (input->m_state == InputChannel::State::Ended)
{
EndActivation();
}
}
}
}
Camera OrbitDollyCursorMoveCameraInput::StepCamera(
const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + float(cursorDelta.m_y) * m_props.m_dollySpeed, 0.0f);
return nextCamera;
}
void ScrollTranslationCameraInput::HandleEvents(const InputEvent& event)
{
if (const auto* scroll = AZStd::get_if<ScrollEvent>(&event))
{
BeginActivation();
}
}
Camera ScrollTranslationCameraInput::StepCamera(
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, float scrollDelta,
[[maybe_unused]] const float deltaTime)
{
Camera nextCamera = targetCamera;
const auto translation_basis = LookTranslation(nextCamera);
const auto axisY = translation_basis.GetBasisY();
nextCamera.m_lookAt += axisY * scrollDelta * m_props.m_translateSpeed;
EndActivation();
return nextCamera;
}
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, const float deltaTime)
{
const auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
// keep yaw in 0 - 360 range
float target_yaw = clamp_rotation(targetCamera.m_yaw);
const float current_yaw = clamp_rotation(currentCamera.m_yaw);
auto sign = [](const float value) { return static_cast<float>((0.0f < value) - (value < 0.0f)); };
// ensure smooth transition when moving across 0 - 360 boundary
const float yaw_delta = target_yaw - current_yaw;
if (std::abs(yaw_delta) >= AZ::Constants::Pi)
{
target_yaw -= AZ::Constants::TwoPi * sign(yaw_delta);
}
Camera camera;
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
// article by Scott Lembcke: https://www.gamasutra.com/blogs/ScottLembcke/20180404/316046/Improved_Lerp_Smoothing.php
const float lookRate = std::exp2(props.m_lookSmoothness);
const float lookT = std::exp2(-lookRate * deltaTime);
camera.m_pitch = AZ::Lerp(targetCamera.m_pitch, currentCamera.m_pitch, lookT);
camera.m_yaw = AZ::Lerp(target_yaw, current_yaw, lookT);
const float moveRate = std::exp2(props.m_moveSmoothness);
const float moveT = std::exp2(-moveRate * deltaTime);
camera.m_lookDist = AZ::Lerp(targetCamera.m_lookDist, currentCamera.m_lookDist, moveT);
camera.m_lookAt = targetCamera.m_lookAt.Lerp(currentCamera.m_lookAt, moveT);
return camera;
}
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize)
{
const auto& inputChannelId = inputChannel.GetInputChannelId();
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
if (inputChannelId == InputDeviceMouse::SystemCursorPosition)
{
AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero();
InputSystemCursorRequestBus::EventResult(
systemCursorPositionNormalized, inputDeviceId, &InputSystemCursorRequestBus::Events::GetSystemCursorPositionNormalized);
return CursorMotionEvent{ScreenPoint(
systemCursorPositionNormalized.GetX() * windowSize.m_width, systemCursorPositionNormalized.GetY() * windowSize.m_height)};
}
else if (inputChannelId == InputDeviceMouse::Movement::Z)
{
return ScrollEvent{inputChannel.GetValue()};
}
else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
{
return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
}
return AZStd::monostate{};
}
} // namespace AzFramework
@@ -0,0 +1,420 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Matrix3x3.h>
#include <AzCore/Math/Transform.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/optional.h>
#include <AzFramework/Input/Channels/InputChannel.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
namespace AzFramework
{
struct WindowSize;
struct Camera
{
AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero,
//!< or position of m_lookAt when m_lookDist is greater
//!< than zero.
float m_yaw{0.0};
float m_pitch{0.0};
float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt
//! View camera transform (v in MVP).
AZ::Transform View() const;
//! World camera transform.
AZ::Transform Transform() const;
//! World rotation.
AZ::Matrix3x3 Rotation() const;
//! World translation.
AZ::Vector3 Translation() const;
};
inline AZ::Transform Camera::View() const
{
return Transform().GetInverse();
}
inline AZ::Transform Camera::Transform() const
{
return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationX(m_pitch) *
AZ::Transform::CreateRotationZ(m_yaw) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisZ(m_lookDist));
}
inline AZ::Matrix3x3 Camera::Rotation() const
{
return AZ::Matrix3x3::CreateFromQuaternion(Transform().GetRotation());
}
inline AZ::Vector3 Camera::Translation() const
{
return Transform().GetTranslation();
}
struct CursorMotionEvent
{
ScreenPoint m_position;
};
struct ScrollEvent
{
float m_delta;
};
struct DiscreteInputEvent
{
InputChannelId m_channelId; //!< Channel type. (e.g. Keyboard key, mouse button or other device input).
InputChannel::State m_state; //!< Channel state. (e.g. Begin/update/end event).
};
using InputEvent = AZStd::variant<AZStd::monostate, CursorMotionEvent, ScrollEvent, DiscreteInputEvent>;
class CameraInput
{
public:
enum class Activation
{
Idle,
Begin,
Active,
End
};
virtual ~CameraInput() = default;
bool Beginning() const
{
return m_activation == Activation::Begin;
}
bool Ending() const
{
return m_activation == Activation::End;
}
bool Idle() const
{
return m_activation == Activation::Idle;
}
bool Active() const
{
return m_activation == Activation::Active;
}
void BeginActivation()
{
m_activation = Activation::Begin;
}
void EndActivation()
{
m_activation = Activation::End;
}
void ContinueActivation()
{
m_activation = Activation::Active;
}
void ClearActivation()
{
m_activation = Activation::Idle;
}
void Reset()
{
ClearActivation();
ResetImpl();
}
virtual void HandleEvents(const InputEvent& event) = 0;
virtual Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) = 0;
virtual bool Exclusive() const
{
return false;
}
protected:
virtual void ResetImpl()
{
}
private:
Activation m_activation = Activation::Idle;
};
struct SmoothProps
{
float m_lookSmoothness = 5.0f;
float m_moveSmoothness = 5.0f;
};
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, float deltaTime);
class Cameras
{
public:
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
void HandleEvents(const InputEvent& event);
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
void Reset();
private:
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_activeCameraInputs;
AZStd::vector<AZStd::shared_ptr<CameraInput>> m_idleCameraInputs;
};
class CameraSystem
{
public:
void HandleEvents(const InputEvent& event);
Camera StepCamera(const Camera& targetCamera, float deltaTime);
Cameras m_cameras;
private:
float m_scrollDelta = 0.0f;
AZStd::optional<ScreenPoint> m_lastCursorPosition;
AZStd::optional<ScreenPoint> m_currentCursorPosition;
};
class RotateCameraInput : public CameraInput
{
public:
explicit RotateCameraInput(const InputChannelId channelId)
: m_channelId(channelId)
{
}
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
InputChannelId m_channelId;
struct Props
{
float m_rotateSpeed = 0.005f;
} m_props;
};
struct PanAxes
{
AZ::Vector3 m_horizontalAxis;
AZ::Vector3 m_verticalAxis;
};
using PanAxesFn = AZStd::function<PanAxes(const Camera& camera)>;
inline PanAxes LookPan(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
return {orientation.GetBasisX(), orientation.GetBasisZ()};
}
inline PanAxes OrbitPan(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
const auto basisY = [&orientation] {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
return {basisX, basisY};
}
class PanCameraInput : public CameraInput
{
public:
explicit PanCameraInput(PanAxesFn panAxesFn)
: m_panAxesFn(AZStd::move(panAxesFn))
{
}
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
struct Props
{
float m_panSpeed = 0.01f;
bool m_panInvertX = true;
bool m_panInvertY = true;
} m_props;
private:
PanAxesFn m_panAxesFn;
};
using TranslationAxesFn = AZStd::function<AZ::Matrix3x3(const Camera& camera)>;
inline AZ::Matrix3x3 LookTranslation(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
const auto basisY = orientation.GetBasisY();
const auto basisZ = AZ::Vector3::CreateAxisZ();
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
}
inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera)
{
const AZ::Matrix3x3 orientation = camera.Rotation();
const auto basisX = orientation.GetBasisX();
const auto basisY = [&orientation] {
const auto forward = orientation.GetBasisY();
return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized();
}();
const auto basisZ = AZ::Vector3::CreateAxisZ();
return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ);
}
class TranslateCameraInput : public CameraInput
{
public:
explicit TranslateCameraInput(TranslationAxesFn translationAxesFn)
: m_translationAxesFn(AZStd::move(translationAxesFn))
{
}
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
void ResetImpl() override;
struct Props
{
float m_translateSpeed = 10.0f;
float m_boostMultiplier = 3.0f;
} m_props;
private:
enum class TranslationType
{
// clang-format off
Nil = 0,
Forward = 1 << 0,
Backward = 1 << 1,
Left = 1 << 2,
Right = 1 << 3,
Up = 1 << 4,
Down = 1 << 5,
// clang-format on
};
friend TranslationType operator|(const TranslationType lhs, const TranslationType rhs)
{
return static_cast<TranslationType>(
static_cast<std::underlying_type_t<TranslationType>>(lhs) | static_cast<std::underlying_type_t<TranslationType>>(rhs));
}
friend TranslationType& operator|=(TranslationType& lhs, const TranslationType rhs)
{
lhs = lhs | rhs;
return lhs;
}
friend TranslationType operator^(const TranslationType lhs, const TranslationType rhs)
{
return static_cast<TranslationType>(
static_cast<std::underlying_type_t<TranslationType>>(lhs) ^ static_cast<std::underlying_type_t<TranslationType>>(rhs));
}
friend TranslationType& operator^=(TranslationType& lhs, const TranslationType rhs)
{
lhs = lhs ^ rhs;
return lhs;
}
friend TranslationType operator&(const TranslationType lhs, const TranslationType rhs)
{
return static_cast<TranslationType>(
static_cast<std::underlying_type_t<TranslationType>>(lhs) & static_cast<std::underlying_type_t<TranslationType>>(rhs));
}
friend TranslationType& operator&=(TranslationType& lhs, const TranslationType rhs)
{
lhs = lhs & rhs;
return lhs;
}
static TranslationType translationFromKey(InputChannelId channelId);
TranslationType m_translation = TranslationType::Nil;
TranslationAxesFn m_translationAxesFn;
bool m_boost = false;
};
class OrbitDollyScrollCameraInput : public CameraInput
{
public:
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
struct Props
{
float m_dollySpeed = 0.2f;
} m_props;
};
class OrbitDollyCursorMoveCameraInput : public CameraInput
{
public:
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
struct Props
{
float m_dollySpeed = 0.1f;
} m_props;
};
class ScrollTranslationCameraInput : public CameraInput
{
public:
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
struct Props
{
float m_translateSpeed = 0.2f;
} m_props;
};
class OrbitCameraInput : public CameraInput
{
public:
void HandleEvents(const InputEvent& event) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
bool Exclusive() const override
{
return true;
}
Cameras m_orbitCameras;
struct Props
{
float m_defaultOrbitDistance = 15.0f;
float m_maxOrbitDistance = 100.0f;
} m_props;
};
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize);
} // namespace AzFramework
@@ -13,6 +13,7 @@
#pragma once
#include <AzFramework/Viewport/ViewportId.h>
#include <AzFramework/Windowing/WindowBus.h>
#include <AzCore/std/chrono/chrono.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
@@ -60,17 +61,18 @@ namespace AzFramework
{
//! The viewport ID this event was dispatched to.
ViewportId m_viewportId;
//! The native window handle for the application.
NativeWindowHandle m_windowHandle;
//! The input channel data for this event.
const AzFramework::InputChannel& m_inputChannel;
//! The priority this event was dispatched at.
ViewportControllerPriority m_priority;
ViewportControllerInputEvent(
ViewportId viewportId,
const AzFramework::InputChannel& inputChannel,
ViewportControllerPriority priority = ViewportControllerPriority::DispatchToAllPriorities
)
ViewportId viewportId, NativeWindowHandle windowHandle, const AzFramework::InputChannel& inputChannel,
ViewportControllerPriority priority = ViewportControllerPriority::DispatchToAllPriorities)
: m_viewportId(viewportId)
, m_windowHandle(windowHandle)
, m_inputChannel(inputChannel)
, m_priority(priority)
{
@@ -102,6 +102,8 @@ set(FILES
Viewport/ScreenGeometry.cpp
Viewport/CameraState.h
Viewport/CameraState.cpp
Viewport/CameraInput.h
Viewport/CameraInput.cpp
Viewport/DisplayContextRequestBus.h
Entity/BehaviorEntity.cpp
Entity/BehaviorEntity.h
@@ -43,14 +43,12 @@ namespace AzToolsFramework
const PrefabDom& modifiedState, const LinkId linkId) = 0;
//! Updates the affected template for a given entityId using the providedPatch
virtual bool PatchEntityInTemplate(PrefabDomValue& providedPatch, const AZ::EntityId& entityId) = 0;
virtual bool PatchEntityInTemplate(PrefabDomValue& providedPatch, const EntityAlias& entityAlias, const TemplateId& templateId) = 0;
virtual bool PatchEntityInTemplate(PrefabDom& providedPatch, AZ::EntityId entityId) = 0;
virtual void AppendEntityAliasToPatchPaths(PrefabDom& providedPatch, const AZ::EntityId& entityId) = 0;
//! Updates the template links (updating instances) for the given templateId using the providedPatch
virtual void PatchTemplate(PrefabDomValue& providedPatch, const TemplateId& templateId) = 0;
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId) = 0;
virtual void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) = 0;
@@ -107,7 +107,7 @@ namespace AzToolsFramework
return result.GetProcessing() != AZ::JsonSerializationResult::Processing::Halted;
}
bool InstanceToTemplatePropagator::PatchEntityInTemplate(PrefabDomValue& providedPatch, const AZ::EntityId& entityId)
bool InstanceToTemplatePropagator::PatchEntityInTemplate(PrefabDom& providedPatch, AZ::EntityId entityId)
{
InstanceOptionalReference instanceOptionalReference = m_instanceEntityMapperInterface->FindOwningInstance(entityId);
@@ -119,53 +119,10 @@ namespace AzToolsFramework
return false;
}
//get template space associated with instance
Instance& instance = instanceOptionalReference->get();
TemplateId templateId = instance.GetTemplateId();
//alias entity goes by in template -> get via owning instance map
AZStd::optional<EntityAlias> entityAlias = instance.GetEntityAlias(entityId);
if (!entityAlias)
{
AZ_Error("Prefab", false, "Failed to find an entity alias for the provided entity");
return false;
}
return PatchEntityInTemplate(providedPatch, entityAlias.value(), templateId);
}
bool InstanceToTemplatePropagator::PatchEntityInTemplate(PrefabDomValue& providedPatch, const EntityAlias& entityAlias, const TemplateId& templateId)
{
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
//query into the template dom for the alias
PrefabDomValueReference entityList = PrefabDomUtils::FindPrefabDomValue(templateDomReference, PrefabDomUtils::EntitiesName);
if (!entityList)
{
AZ_Error("Prefab", false, "Cannot patch entity in Template with id [%llu] because entity couldn't be found in the template", templateId);
return false;
}
PrefabDomValueReference entity = PrefabDomUtils::FindPrefabDomValue(entityList->get(), entityAlias.c_str());
if (!entity)
{
AZ_Error("Prefab", false, "Failed to aquire entity value reference");
return false;
}
//apply patch to section
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(entity->get(),
templateDomReference.GetAllocator(), providedPatch, AZ::JsonMergeApproach::JsonPatch);
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success, "Patch was not successfully applied")
//trigger propagation
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId);
return true;
//get template id associated with instance
TemplateId templateId = instanceOptionalReference->get().GetTemplateId();
AppendEntityAliasToPatchPaths(providedPatch, entityId);
return PatchTemplate(providedPatch, templateId);
}
void InstanceToTemplatePropagator::AppendEntityAliasToPatchPaths(PrefabDom& providedPatch, const AZ::EntityId& entityId)
@@ -215,7 +172,7 @@ namespace AzToolsFramework
}
}
void InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, const TemplateId& templateId)
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId)
{
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
@@ -223,14 +180,17 @@ namespace AzToolsFramework
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
templateDomReference.GetAllocator(), providedPatch, AZ::JsonMergeApproach::JsonPatch);
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
"Patch was not successfully applied");
//trigger propagation
if (result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success)
{
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId);
return true;
}
else
{
AZ_Error("Prefab", false, "Patch was not successfully applied");
return false;
}
}
@@ -287,6 +247,8 @@ namespace AzToolsFramework
AddPatchesToLink(patches, linkToApplyPatches);
linkToApplyPatches.UpdateTarget();
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(linkToApplyPatches.GetTargetTemplateId(), true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(linkToApplyPatches.GetTargetTemplateId());
}
@@ -31,21 +31,19 @@ namespace AzToolsFramework
bool GeneratePatch(PrefabDom& generatedPatch, const PrefabDom& initialState, const PrefabDom& modifiedState) override;
bool GeneratePatchForLink(PrefabDom& generatedPatch, const PrefabDom& initialState,
const PrefabDom& modifiedState, LinkId linkId) override;
bool PatchEntityInTemplate(PrefabDomValue& providedPatch, const AZ::EntityId& entityId) override;
bool PatchEntityInTemplate(PrefabDomValue& providedPatch, const EntityAlias& entityAlias, const TemplateId& templateId) override;
bool PatchEntityInTemplate(PrefabDom& providedPatch, AZ::EntityId entityId) override;
void AppendEntityAliasToPatchPaths(PrefabDom& providedPatch, const AZ::EntityId& entityId) override;
InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId);
void PatchTemplate(PrefabDomValue& providedPatch, const AzToolsFramework::Prefab::TemplateId& templateId) override;
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId) override;
void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override;
void AddPatchesToLink(PrefabDom& patches, Link& link);
private:
InstanceEntityMapperInterface* m_instanceEntityMapperInterface;
PrefabSystemComponentInterface* m_prefabSystemComponentInterface;
@@ -127,12 +127,12 @@ namespace AzToolsFramework
InstanceEntityScrubber instanceEntityScrubber(newlyAddedEntities);
settings.m_metadata.Add(&instanceEntityScrubber);
AZ::JsonSerializationResult::ResultCode result =
AZ::JsonSerialization::Load(instance, prefabDom, settings);
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Load(instance, prefabDom, settings);
if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
{
AZ_Error("Prefab", false,
AZ_Error(
"Prefab", false,
"Failed to de-serialize Prefab Instance from Prefab DOM. "
"Unable to proceed.");
@@ -348,8 +348,7 @@ namespace AzToolsFramework
"Prefab", false,
"PrefabLoader::SaveTemplate - Unable to save Prefab Template with id: %llu. "
"Template with that id is invalid",
templateId
);
templateId);
return AZStd::nullopt;
}
@@ -79,13 +79,16 @@ namespace AzToolsFramework
//generate undo/redo patches
m_instanceToTemplateInterface->GeneratePatch(m_redoPatch, initialState, endState);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(m_redoPatch, entityId);
m_instanceToTemplateInterface->GeneratePatch(m_undoPatch, endState, initialState);
m_instanceToTemplateInterface->AppendEntityAliasToPatchPaths(m_undoPatch, entityId);
}
void PrefabUndoEntityUpdate::Undo()
{
[[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchEntityInTemplate(m_undoPatch, m_entityAlias, m_templateId);
m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId);
AZ_Error(
"Prefab", isPatchApplicationSuccessful,
"Applying the undo patch on the entity with alias '%s' in template with id '%llu' was unsuccessful", m_entityAlias.c_str(),
@@ -95,7 +98,8 @@ namespace AzToolsFramework
void PrefabUndoEntityUpdate::Redo()
{
[[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchEntityInTemplate(m_redoPatch, m_entityAlias, m_templateId);
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId);
AZ_Error(
"Prefab", isPatchApplicationSuccessful,
"Applying the redo patch on the entity with alias '%s' in template with id '%llu' was unsuccessful", m_entityAlias.c_str(),
@@ -21,7 +21,12 @@
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h>
class QPoint;
class QPoint; // LYN-2315 in-progress, remove this
namespace AzFramework
{
struct ScreenPoint;
}
namespace AzToolsFramework
{
@@ -235,12 +240,12 @@ namespace AzToolsFramework
/// Restores the cursor and ends locking it in place, allowing it to be moved freely.
virtual void EndCursorCapture() = 0;
/// Gets the most recent recorded cursor position in the viewport in screen space coordinates.
virtual QPoint ViewportCursorScreenPosition() = 0;
virtual AzFramework::ScreenPoint ViewportCursorScreenPosition() = 0;
/// Gets the cursor position recorded prior to the most recent cursor position.
/// Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
/// from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
/// position delta.
virtual AZStd::optional<QPoint> PreviousViewportCursorScreenPosition() = 0;
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
protected:
~ViewportMouseCursorRequests() = default;
@@ -202,12 +202,18 @@ namespace AzToolsFramework
return mouseInteractionEvent.m_wheelDelta;
}
/// Return Qt QPoint from an Viewport ScreenPoint.
/// Return QPoint from AzFramework::ScreenPoint.
inline QPoint QPointFromScreenPoint(const AzFramework::ScreenPoint& screenPoint)
{
return {screenPoint.m_x, screenPoint.m_y};
}
/// Return AzFramework::ScreenPoint from QPoint.
inline AzFramework::ScreenPoint ScreenPointFromQPoint(const QPoint& qpoint)
{
return AzFramework::ScreenPoint{qpoint.x(), qpoint.y()};
}
/// Map from Qt -> Lumberyard buttons.
inline AZ::u32 TranslateMouseButtons(const Qt::MouseButtons buttons)
{
@@ -75,7 +75,7 @@ namespace UnitTest
EntityAlias entityAlias = entityAliasRef.value();
//update template
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityAlias, templateId));
ASSERT_TRUE(m_instanceToTemplateInterface->PatchEntityInTemplate(patch, entityId));
//undo change
instanceEntityUndo.Undo();
@@ -12,5 +12,5 @@
set(LY_BUILD_DEPENDENCIES
PUBLIC
3rdParty::FreeType2
3rdParty::freetype
)
+16 -1
View File
@@ -76,6 +76,7 @@
#include "EditorPreferencesPageGeneral.h"
#include "ViewportManipulatorController.h"
#include "LegacyViewportCameraController.h"
#include "ModernViewportCameraController.h"
#include "ViewPane.h"
#include "CustomResolutionDlg.h"
@@ -92,6 +93,7 @@
// Atom
#include <Atom/RPI.Public/View.h>
#include <Atom/RPI.Public/ViewportContextManager.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/Math/MatrixUtils.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -106,6 +108,10 @@ void StartFixedCursorMode(QObject *viewport);
#define RENDER_MESH_TEST_DISTANCE (0.2f)
#define CURSOR_FONT_HEIGHT 8.0f
AZ_CVAR(
bool, ed_useNewCameraSystem, false, nullptr, AZ::ConsoleFunctorFlags::Null,
"Use the new Editor camera system (the Atom-native Editor viewport (experimental) must also be enabled)");
namespace AZ::ViewportHelpers
{
static const char TextCantCreateCameraNoLevel[] = "Cannot create camera when no level is loaded.";
@@ -1236,7 +1242,16 @@ void EditorViewportWidget::SetViewportId(int id)
viewportContext->ConnectProjectionMatrixChangedHandler(m_cameraProjectionMatrixChangeHandler);
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::ViewportManipulatorController>());
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::LegacyViewportCameraController>());
if (ed_useNewCameraSystem)
{
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::ModernViewportCameraController>());
}
else
{
m_renderViewport->GetControllerList()->Add(AZStd::make_shared<SandboxEditor::LegacyViewportCameraController>());
}
UpdateScene();
}
@@ -11,8 +11,10 @@
*/
#include "LegacyViewportCameraController.h"
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <Atom/RPI.Public/ViewportContext.h>
@@ -73,7 +75,8 @@ AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportC
return viewportContextManager->GetViewportContextById(GetViewportId());
}
bool LegacyViewportCameraControllerInstance::HandleMouseMove(const QPoint& currentMousePos, const QPoint& previousMousePos)
bool LegacyViewportCameraControllerInstance::HandleMouseMove(
const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos)
{
if (previousMousePos == currentMousePos)
{
@@ -100,7 +103,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(const QPoint& curre
Vec3 ydir = m.GetColumn1().GetNormalized();
Vec3 pos = m.GetTranslation();
const float posDelta = 0.2f * (previousMousePos.y() - currentMousePos.y()) * speedScale;
const float posDelta = 0.2f * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
pos = pos - ydir * posDelta;
m_orbitDistance = m_orbitDistance + posDelta;
m_orbitDistance = fabs(m_orbitDistance);
@@ -111,7 +114,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(const QPoint& curre
}
else if (m_inRotateMode)
{
Ang3 angles(-currentMousePos.y() + previousMousePos.y(), 0, -currentMousePos.x() + previousMousePos.x());
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertYRotation)
{
@@ -143,7 +146,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(const QPoint& curre
}
Vec3 pos = m.GetTranslation();
pos += 0.1f * xdir * (currentMousePos.x() - previousMousePos.x()) * speedScale + 0.1f * zdir * (previousMousePos.y() - currentMousePos.y()) * speedScale;
pos += 0.1f * xdir * (currentMousePos.m_x - previousMousePos.m_x) * speedScale + 0.1f * zdir * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
m.SetTranslation(pos);
AZ::Transform transform = viewportContext->GetCameraTransform();
@@ -153,7 +156,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(const QPoint& curre
}
else if (m_inOrbitMode)
{
Ang3 angles(-currentMousePos.y() + previousMousePos.y(), 0, -currentMousePos.x() + previousMousePos.x());
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertPan)
@@ -289,14 +292,13 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
if (id == AzFramework::InputDeviceMouse::SystemCursorPosition)
{
QPoint screenPosition = QPoint();
bool result = false;
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
GetViewportId(),
[this, &result](AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequests* mouseRequests)
{
auto previousMousePosition = mouseRequests->PreviousViewportCursorScreenPosition();
if (previousMousePosition.has_value())
if (auto previousMousePosition = mouseRequests->PreviousViewportCursorScreenPosition();
previousMousePosition.has_value())
{
result = HandleMouseMove(mouseRequests->ViewportCursorScreenPosition(), previousMousePosition.value());
}
@@ -21,6 +21,11 @@
#include <QtCore/qnamespace.h>
#include <QPoint>
namespace AzFramework
{
struct ScreenPoint;
}
namespace SandboxEditor
{
class LegacyViewportCameraControllerInstance final
@@ -45,7 +50,7 @@ namespace SandboxEditor
AZ::RPI::ViewportContextPtr GetViewportContext();
bool HandleMouseMove(const QPoint& currentMousePos, const QPoint& previousMousePos);
bool HandleMouseMove(const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos);
bool HandleMouseWheel(float zDelta);
bool IsKeyDown(Qt::Key key) const;
@@ -0,0 +1,97 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "ModernViewportCameraController.h"
#include <Atom/RPI.Public/ViewportContext.h>
#include <Atom/RPI.Public/ViewportContextBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzFramework/Windowing/WindowBus.h>
namespace SandboxEditor
{
static AZ::RPI::ViewportContextPtr RetrieveViewportContext(const AzFramework::ViewportId viewportId)
{
auto viewportContextManager = AZ::Interface<AZ::RPI::ViewportContextRequestsInterface>::Get();
if (!viewportContextManager)
{
return nullptr;
}
auto viewportContext = viewportContextManager->GetViewportContextById(viewportId);
if (!viewportContext)
{
return nullptr;
}
return viewportContext;
}
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(const AzFramework::ViewportId viewportId)
: MultiViewportControllerInstanceInterface(viewportId)
{
// LYN-2315 TODO - move setup out of constructor, pass cameras in
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Right);
auto firstPersonPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::LookPan);
auto firstPersonTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::LookTranslation);
auto firstPersonWheelCamera = AZStd::make_shared<AzFramework::ScrollTranslationCameraInput>();
auto orbitCamera = AZStd::make_shared<AzFramework::OrbitCameraInput>();
auto orbitRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::InputDeviceMouse::Button::Left);
auto orbitTranslateCamera = AZStd::make_shared<AzFramework::TranslateCameraInput>(AzFramework::OrbitTranslation);
auto orbitDollyWheelCamera = AZStd::make_shared<AzFramework::OrbitDollyScrollCameraInput>();
auto orbitDollyMoveCamera = AZStd::make_shared<AzFramework::OrbitDollyCursorMoveCameraInput>();
auto orbitPanCamera = AZStd::make_shared<AzFramework::PanCameraInput>(AzFramework::OrbitPan);
orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera);
orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera);
orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera);
orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera);
orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera);
m_cameraSystem.m_cameras.AddCamera(firstPersonRotateCamera);
m_cameraSystem.m_cameras.AddCamera(firstPersonPanCamera);
m_cameraSystem.m_cameras.AddCamera(firstPersonTranslateCamera);
m_cameraSystem.m_cameras.AddCamera(firstPersonWheelCamera);
m_cameraSystem.m_cameras.AddCamera(orbitCamera);
if (const auto viewportContext = RetrieveViewportContext(viewportId))
{
// set position but not orientation
m_targetCamera.m_lookAt = viewportContext->GetCameraTransform().GetTranslation();
// LYN-2315 TODO https://www.geometrictools.com/Documentation/EulerAngles.pdf
m_camera = m_targetCamera;
}
}
bool ModernViewportCameraControllerInstance::HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event)
{
AzFramework::WindowSize windowSize;
AzFramework::WindowRequestBus::EventResult(
windowSize, event.m_windowHandle, &AzFramework::WindowRequestBus::Events::GetClientAreaSize);
m_cameraSystem.HandleEvents(AzFramework::BuildInputEvent(event.m_inputChannel, windowSize));
return true; // consume event
}
void ModernViewportCameraControllerInstance::UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event)
{
if (auto viewportContext = RetrieveViewportContext(GetViewportId()))
{
m_targetCamera = m_cameraSystem.StepCamera(m_targetCamera, event.m_deltaTime.count());
m_camera = AzFramework::SmoothCamera(m_camera, m_targetCamera, m_smoothProps, event.m_deltaTime.count());
viewportContext->SetCameraTransform(m_camera.Transform());
}
}
} // namespace SandboxEditor
@@ -0,0 +1,37 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzFramework/Viewport/CameraInput.h>
#include <AzFramework/Viewport/MultiViewportController.h>
namespace SandboxEditor
{
class ModernViewportCameraControllerInstance final : public AzFramework::MultiViewportControllerInstanceInterface
{
public:
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId);
// MultiViewportControllerInstanceInterface overrides ...
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
private:
AzFramework::Camera m_camera;
AzFramework::Camera m_targetCamera;
AzFramework::SmoothProps m_smoothProps;
AzFramework::CameraSystem m_cameraSystem;
};
using ModernViewportCameraController = AzFramework::MultiViewportController<ModernViewportCameraControllerInstance>;
} // namespace SandboxEditor
+1 -1
View File
@@ -16,7 +16,7 @@
#include "ImageTIF.h"
/// libTiff
#include <libtiff/tiffio.h> // TIFF library
#include <tiffio.h> // TIFF library
// Function prototypes
static tsize_t libtiffDummyReadProc (thandle_t fd, tdata_t buf, tsize_t size);
@@ -16,6 +16,7 @@
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzCore/Script/ScriptTimePoint.h>
#include <QApplication>
@@ -99,18 +100,16 @@ bool ViewportManipulatorControllerInstance::HandleInputChannelEvent(const AzFram
// Cache the ray trace results when doing manipulator interaction checks, no need to recalculate after
if (event.m_priority == ManipulatorPriority)
{
QPoint screenPosition = QPoint();
AzFramework::ScreenPoint screenPosition = AzFramework::ScreenPoint(0, 0);
ViewportMouseCursorRequestBus::EventResult(
screenPosition, GetViewportId(),
&ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition
);
m_state.m_mousePick.m_screenCoordinates = AzFramework::ScreenPoint{screenPosition.x(), screenPosition.y()};
screenPosition, GetViewportId(), &ViewportMouseCursorRequestBus::Events::ViewportCursorScreenPosition);
m_state.m_mousePick.m_screenCoordinates = screenPosition;
AZStd::optional<ProjectedViewportRay> ray;
ViewportInteractionRequestBus::EventResult(
ray, GetViewportId(),
&ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay,
screenPosition
);
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay,
QPoint(screenPosition.m_x, screenPosition.m_y));
if (ray.has_value())
{
m_state.m_mousePick.m_rayOrigin = ray.value().origin;
@@ -996,6 +996,8 @@ set(FILES
ViewportManipulatorController.h
LegacyViewportCameraController.cpp
LegacyViewportCameraController.h
ModernViewportCameraController.cpp
ModernViewportCameraController.h
RenderViewport.cpp
RenderViewport.h
TopRendererWnd.cpp
@@ -41,6 +41,65 @@
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
// Class to implement the WindowRequestBus::Handler instead of the QViewport class.
// This is to bypass a link warning that occurs in unity builds if EditorCommon dll
// is linked along with a gem that also implements WindowRequestBus::Handler. The
// issue is that QViewport has a dllexport so it causes duplicate code to be linked
// in and a warning that there will be two of the same symbol in memory
class QViewportRequests
: public AzFramework::WindowRequestBus::Handler
{
public:
QViewportRequests(QViewport& viewport)
: m_viewport(viewport)
{
}
~QViewportRequests() override
{
AzFramework::WindowRequestBus::Handler::BusDisconnect();
}
// WindowRequestBus::Handler...
void SetWindowTitle(const AZStd::string& title) override
{
m_viewport.SetWindowTitle(title);
}
AzFramework::WindowSize GetClientAreaSize() const override
{
return m_viewport.GetClientAreaSize();
}
void ResizeClientArea(AzFramework::WindowSize clientAreaSize) override
{
m_viewport.ResizeClientArea(clientAreaSize);
}
bool GetFullScreenState() const override
{
return m_viewport.GetFullScreenState();
}
void SetFullScreenState(bool fullScreenState) override
{
m_viewport.SetFullScreenState(fullScreenState);
}
bool CanToggleFullScreenState() const override
{
return m_viewport.CanToggleFullScreenState();
}
void ToggleFullScreenState() override
{
m_viewport.ToggleFullScreenState();
}
private:
QViewport& m_viewport;
};
struct QViewport::SPreviousContext
{
CCamera renderCamera;
@@ -188,6 +247,8 @@ QViewport::QViewport(QWidget* parent, StartupMode startupMode)
, m_private(new SPrivate())
, m_cameraControlMode(CameraControlMode::NONE)
{
m_viewportRequests = AZStd::make_unique<QViewportRequests>(*this);
if (startupMode & StartupMode_Immediate)
Startup();
}
@@ -213,6 +274,8 @@ void QViewport::Startup()
QViewport::~QViewport()
{
DestroyRenderContext();
m_viewportRequests.reset();
}
void QViewport::UpdateBackgroundColor()
@@ -316,7 +379,7 @@ bool QViewport::CreateRenderContext()
if (AZ::Interface<AzFramework::AtomActiveInterface>::Get())
{
AzFramework::WindowRequestBus::Handler::BusConnect(windowHandle);
m_viewportRequests.get()->BusConnect(windowHandle);
AzFramework::WindowSystemNotificationBus::Broadcast(&AzFramework::WindowSystemNotificationBus::Handler::OnWindowCreated, windowHandle);
m_lastHwnd = windowHandle;
@@ -346,7 +409,7 @@ void QViewport::DestroyRenderContext()
m_renderContextCreated = false;
AzFramework::WindowNotificationBus::Event(windowHandle, &AzFramework::WindowNotificationBus::Handler::OnWindowClosed);
AzFramework::WindowRequestBus::Handler::BusDisconnect();
m_viewportRequests.get()->BusDisconnect();
m_lastHwnd = 0;
}
}
+10 -9
View File
@@ -41,6 +41,7 @@ struct SMouseEvent;
struct SViewportSettings;
struct SViewportState;
class QElapsedTimer;
class QViewportRequests;
class EDITOR_COMMON_API QViewport;
struct SRenderContext
@@ -66,7 +67,6 @@ AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
class EDITOR_COMMON_API QViewport
: public QWidget
, public AzFramework::WindowRequestBus::Handler
{
Q_OBJECT
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
@@ -107,14 +107,14 @@ public:
void SetSize(const QSize& size);
void GetImageOffscreen(CImageEx& image, const QSize& customSize);
// WindowRequestBus::Handler...
void SetWindowTitle(const AZStd::string& title) override;
AzFramework::WindowSize GetClientAreaSize() const override;
void ResizeClientArea(AzFramework::WindowSize clientAreaSize) override;
bool GetFullScreenState() const override;
void SetFullScreenState(bool fullScreenState) override;
bool CanToggleFullScreenState() const override;
void ToggleFullScreenState() override;
// WindowRequestBus::Handler... (handler moved to cpp to resolve link issues in unity builds)
void SetWindowTitle(const AZStd::string& title);
AzFramework::WindowSize GetClientAreaSize() const;
void ResizeClientArea(AzFramework::WindowSize clientAreaSize);
bool GetFullScreenState() const;
void SetFullScreenState(bool fullScreenState);
bool CanToggleFullScreenState() const;
void ToggleFullScreenState();
public slots:
void Update();
@@ -197,6 +197,7 @@ private:
std::unique_ptr<SViewportSettings> m_settings;
std::unique_ptr<SViewportState> m_state;
std::vector<QViewportConsumer*> m_consumers;
AZStd::unique_ptr<QViewportRequests> m_viewportRequests;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
HWND m_lastHwnd = 0;
bool m_resizeWindowEvent = false;
@@ -170,7 +170,9 @@ bool CCrySimpleJob::ExecuteCommand(const std::string& rCmd, std::string& outErro
threadIdStream << threadId;
// Multiple threads could execute a command, therefore the temporary file has to be unique per thread.
std::string stdErrorTempFilename = SEnviropment::Instance().m_TempPath + "stderr_" + threadIdStream.str() + ".log";
AZ::IO::Path errorTempFilePath = SEnviropment::Instance().m_TempPath / AZStd::string::format("stderr_%s.log", threadIdStream.str().c_str());
std::string stdErrorTempFilename{ errorTempFilePath.c_str(), errorTempFilePath.Native().size() };
CCrySimpleFileGuard FGTmpOutput(stdErrorTempFilename); // Delete file at the end of this function
std::string systemCmd = rCmd;