/* * 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. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #ifndef CRYINCLUDE_EDITOR_RENDERVIEWPORT_H #define CRYINCLUDE_EDITOR_RENDERVIEWPORT_H #pragma once // RenderViewport.h : header file // #include #include #include "Viewport.h" #include "Objects/DisplayContext.h" #include "Undo/Undo.h" #include "Util/PredefinedAspectRatios.h" #include #include #include #include #include #include #include #include // forward declarations. class CBaseObject; class QMenu; class QKeyEvent; #if ENABLE_CRY_PHYSICS struct IPhysicalEntity; typedef IPhysicalEntity* PIPhysicalEntity; #endif namespace AzToolsFramework { class ManipulatorManager; } // CRenderViewport window AZ_PUSH_DISABLE_DLL_EXPORT_BASECLASS_WARNING class SANDBOX_API CRenderViewport : public QtViewport , public IEditorNotifyListener , public IUndoManagerListener , public Camera::EditorCameraRequestBus::Handler , public AzToolsFramework::EditorEntityContextNotificationBus::Handler , public AzFramework::InputSystemCursorConstraintRequestBus::Handler , public AzToolsFramework::ViewportInteraction::ViewportFreezeRequestBus::Handler , public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler , public AzToolsFramework::ViewportInteraction::MainEditorViewportInteractionRequestBus::Handler , public AzToolsFramework::EditorEvents::Bus::Handler , public AzFramework::WindowRequestBus::Handler { AZ_POP_DISABLE_DLL_EXPORT_BASECLASS_WARNING Q_OBJECT public: struct SResolution { SResolution() : width(0) , height(0) { } SResolution(int w, int h) : width(w) , height(h) { } int width; int height; }; public: CRenderViewport(const QString& name, QWidget* parent = nullptr); static const GUID& GetClassID() { return QtViewport::GetClassID(); } /** Get type of this viewport. */ virtual EViewportType GetType() const { return ET_ViewportCamera; } virtual void SetType(EViewportType type) { assert(type == ET_ViewportCamera); }; // Implementation public: virtual ~CRenderViewport(); Q_INVOKABLE void InjectFakeMouseMove(int deltaX, int deltaY, Qt::MouseButtons buttons); public: virtual void Update(); virtual void ResetContent(); virtual void UpdateContent(int flags); void OnTitleMenu(QMenu* menu) override; void SetCamera(const CCamera& camera); const CCamera& GetCamera() const { return m_Camera; }; virtual void SetViewTM(const Matrix34& tm) { if (m_viewSourceType == ViewSourceType::None) { m_defaultViewTM = tm; } SetViewTM(tm, false); } //! Map world space position to viewport position. virtual QPoint WorldToView(const Vec3& wp) const; virtual QPoint WorldToViewParticleEditor(const Vec3& wp, int width, int height) const; virtual Vec3 WorldToView3D(const Vec3& wp, int nFlags = 0) const; //! Map viewport position to world space position. virtual Vec3 ViewToWorld(const QPoint& vp, bool* collideWithTerrain = nullptr, bool onlyTerrain = false, bool bSkipVegetation = false, bool bTestRenderMesh = false, bool* collideWithObject = nullptr) const override; virtual void ViewToWorldRay(const QPoint& vp, Vec3& raySrc, Vec3& rayDir) const override; virtual Vec3 ViewToWorldNormal(const QPoint& vp, bool onlyTerrain, bool bTestRenderMesh = false) override; virtual float GetScreenScaleFactor(const Vec3& worldPoint) const; virtual float GetScreenScaleFactor(const CCamera& camera, const Vec3& object_position); virtual float GetAspectRatio() const; virtual bool HitTest(const QPoint& point, HitContext& hitInfo); virtual bool IsBoundsVisible(const AABB& box) const; virtual void CenterOnSelection(); virtual void CenterOnAABB(const AABB& aabb); void CenterOnSliceInstance() override; void focusOutEvent(QFocusEvent* event) override; void keyPressEvent(QKeyEvent* event) override; void keyReleaseEvent(QKeyEvent* event) override; void SetFOV(float fov); float GetFOV() const; void SetDefaultCamera(); bool IsDefaultCamera() const; void SetSequenceCamera(); bool IsSequenceCamera() const { return m_viewSourceType == ViewSourceType::SequenceCamera; } void SetSelectedCamera(); bool IsSelectedCamera() const; void SetCameraObject(CBaseObject* cameraObject); void SetComponentCamera(const AZ::EntityId& entityId); void SetEntityAsCamera(const AZ::EntityId& entityId, bool lockCameraMovement = false); void SetFirstComponentCamera(); void SetViewEntity(const AZ::EntityId& cameraEntityId, bool lockCameraMovement = false); void PostCameraSet(); // This switches the active camera to the next one in the list of (default, all custom cams). void CycleCamera(); // Camera::EditorCameraRequestBus void SetViewFromEntityPerspective(const AZ::EntityId& entityId) override; void SetViewAndMovementLockFromEntityPerspective(const AZ::EntityId& entityId, bool lockCameraMovement) override; AZ::EntityId GetCurrentViewEntityId() override { return m_viewEntityId; } bool GetActiveCameraPosition(AZ::Vector3& cameraPos) override; // AzToolsFramework::EditorEntityContextNotificationBus void OnStartPlayInEditor() override; void OnStopPlayInEditor() override; // AzToolsFramework::ViewportInteractionRequestBus AzFramework::CameraState GetCameraState() override; bool GridSnappingEnabled() override; float GridSize() override; bool ShowGrid() override; bool AngleSnappingEnabled() override; float AngleStep() override; QPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) override; // AzToolsFramework::ViewportFreezeRequestBus bool IsViewportInputFrozen() override; void FreezeViewportInput(bool freeze) override; // AzToolsFramework::MainEditorViewportInteractionRequestBus AZ::EntityId PickEntity(const QPoint& point) override; AZ::Vector3 PickTerrain(const QPoint& point) override; float TerrainHeight(const AZ::Vector2& position) override; void FindVisibleEntities(AZStd::vector& visibleEntitiesOut) override; bool ShowingWorldSpace() override; QWidget* GetWidgetForViewportContextMenu() override; void BeginWidgetContext() override; void EndWidgetContext() override; // WindowRequestBus::Handler... void SetWindowTitle(const AZStd::string& title) override; AzFramework::WindowSize GetClientAreaSize() const override; void ConnectViewportInteractionRequestBus(); void DisconnectViewportInteractionRequestBus(); void ActivateWindowAndSetFocus(); void LockCameraMovement(bool bLock) { m_bLockCameraMovement = bLock; } bool IsCameraMovementLocked() const { return m_bLockCameraMovement; } void EnableCameraObjectMove(bool bMove) { m_bMoveCameraObject = bMove; } bool IsCameraObjectMove() const { return m_bMoveCameraObject; } void SetPlayerControl(uint32 i) { m_PlayerControl = i; }; uint32 GetPlayerControl() { return m_PlayerControl; }; const DisplayContext& GetDisplayContext() const { return m_displayContext; } CBaseObject* GetCameraObject() const; QPoint WidgetToViewport(const QPoint& point) const; QPoint ViewportToWidget(const QPoint& point) const; QSize WidgetToViewport(const QSize& size) const; /// Take raw input and create a final mouse interaction. /// @attention Do not map **point** from widget to viewport explicitly, /// this is handled internally by BuildMouseInteraction - just pass directly. AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteraction( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, const QPoint& point); void SetPlayerPos() { Matrix34 m = GetViewTM(); m.SetTranslation(m.GetTranslation() - m_PhysicalLocation.t); SetViewTM(m); m_AverageFrameTime = 0.14f; m_PhysicalLocation.SetIdentity(); m_LocalEntityMat.SetIdentity(); m_PrevLocalEntityMat.SetIdentity(); m_absCameraHigh = 2.0f; m_absCameraPos = Vec3(0, 3, 2); m_absCameraPosVP = Vec3(0, -3, 1.5); m_absCurrentSlope = 0.0f; m_absLookDirectionXY = Vec2(0, 1); m_LookAt = Vec3(ZERO); m_LookAtRate = Vec3(ZERO); m_vCamPos = Vec3(ZERO); m_vCamPosRate = Vec3(ZERO); m_relCameraRotX = 0; m_relCameraRotZ = 0; uint32 numSample6 = m_arrAnimatedCharacterPath.size(); for (uint32 i = 0; i < numSample6; i++) { m_arrAnimatedCharacterPath[i] = Vec3(ZERO); } numSample6 = m_arrSmoothEntityPath.size(); for (uint32 i = 0; i < numSample6; i++) { m_arrSmoothEntityPath[i] = Vec3(ZERO); } uint32 numSample7 = m_arrRunStrafeSmoothing.size(); for (uint32 i = 0; i < numSample7; i++) { m_arrRunStrafeSmoothing[i] = 0; } m_vWorldDesiredBodyDirection = Vec2(0, 1); m_vWorldDesiredBodyDirectionSmooth = Vec2(0, 1); m_vWorldDesiredBodyDirectionSmoothRate = Vec2(0, 1); m_vWorldDesiredBodyDirection2 = Vec2(0, 1); m_vWorldDesiredMoveDirection = Vec2(0, 1); m_vWorldDesiredMoveDirectionSmooth = Vec2(0, 1); m_vWorldDesiredMoveDirectionSmoothRate = Vec2(0, 1); m_vLocalDesiredMoveDirection = Vec2(0, 1); m_vLocalDesiredMoveDirectionSmooth = Vec2(0, 1); m_vLocalDesiredMoveDirectionSmoothRate = Vec2(0, 1); m_vWorldAimBodyDirection = Vec2(0, 1); m_MoveSpeedMSec = 5.0f; m_key_W = 0; m_keyrcr_W = 0; m_key_S = 0; m_keyrcr_S = 0; m_key_A = 0; m_keyrcr_A = 0; m_key_D = 0; m_keyrcr_D = 0; m_key_SPACE = 0; m_keyrcr_SPACE = 0; m_ControllMode = 0; m_State = -1; m_Stance = 1; //combat m_udGround = 0.0f; m_lrGround = 0.0f; AABB aabb = AABB(Vec3(-40.0f, -40.0f, -0.25f), Vec3(+40.0f, +40.0f, +0.0f)); m_GroundOBB = OBB::CreateOBBfromAABB(Matrix33(IDENTITY), aabb); m_GroundOBBPos = Vec3(0, 0, -0.01f); }; static CRenderViewport* GetPrimaryViewport(); AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING CCamera m_Camera; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING protected: struct SScopedCurrentContext; void SetViewTM(const Matrix34& tm, bool bMoveOnly); virtual float GetCameraMoveSpeed() const; virtual float GetCameraRotateSpeed() const; virtual bool GetCameraInvertYRotation() const; virtual float GetCameraInvertPan() const; // Called to render stuff. virtual void OnRender(); virtual void OnEditorNotifyEvent(EEditorNotifyEvent event); //! Get currently active camera object. void ToggleCameraObject(); void RenderConstructionPlane(); void RenderSnapMarker(); void RenderCursorString(); void RenderSnappingGrid(); void ProcessMouse(); void ProcessKeys(); void RenderAll(); void DrawAxis(); void DrawBackground(); void InitDisplayContext(); void ResetCursor(); // We use this to determine when the viewport context menu is being displayed so we can exit move mode void PopulateEditorGlobalContextMenu(QMenu* /*menu*/, const AZ::Vector2& /*point*/, int /*flags*/) override; struct SPreviousContext { CCamera rendererCamera; HWND window; int width; int height; bool mainViewport; }; SPreviousContext m_preWidgetContext; // Create an auto-sized render context that is sized based on the Editor's current // viewport. SPreviousContext SetCurrentContext() const; SPreviousContext SetCurrentContext(int newWidth, int newHeight) const; void RestorePreviousContext(const SPreviousContext& x) const; void PreWidgetRendering() override; void PostWidgetRendering() override; // Update the safe frame, safe action, safe title, and borders rectangles based on // viewport size and target aspect ratio. void UpdateSafeFrame(); // Draw safe frame, safe action, safe title rectangles and borders. void RenderSafeFrame(); // Draw one of the safe frame rectangles with the desired color. void RenderSafeFrame(const QRect& frame, float r, float g, float b, float a); // Draw the selection rectangle. void RenderSelectionRectangle(); // Draw a selected region if it has been selected void RenderSelectedRegion(); virtual bool CreateRenderContext(); virtual void DestroyRenderContext(); void OnMenuCommandChangeAspectRatio(unsigned int commandId); bool AdjustObjectPosition(const ray_hit& hit, Vec3& outNormal, Vec3& outPos) const; bool RayRenderMeshIntersection(IRenderMesh* pRenderMesh, const Vec3& vInPos, const Vec3& vInDir, Vec3& vOutPos, Vec3& vOutNormal) const; bool AddCameraMenuItems(QMenu* menu); void ResizeView(int width, int height); void OnCameraFOVVariableChanged(IVariable* var); void HideCursor(); void ShowCursor(); bool IsKeyDown(Qt::Key key) const; enum class ViewSourceType { None, SequenceCamera, LegacyCamera, CameraComponent, AZ_Entity, ViewSourceTypesCount, }; void ResetToViewSourceType(const ViewSourceType& viewSourType); //! Assigned renderer. IRenderer* m_renderer = nullptr; I3DEngine* m_engine = nullptr; bool m_bRenderContextCreated = false; bool m_bInRotateMode = false; bool m_bInMoveMode = false; bool m_bInOrbitMode = false; bool m_bInZoomMode = false; QPoint m_mousePos = QPoint(0, 0); QPoint m_prevMousePos = QPoint(0, 0); // for tablets, you can't use SetCursorPos and need to remember the prior point and delta with that. float m_moveSpeed = 1; float m_orbitDistance = 10.0f; AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING Vec3 m_orbitTarget; //------------------------------------------- //--- player-control in CharEdit --- //------------------------------------------- f32 m_MoveSpeedMSec; uint32 m_key_W, m_keyrcr_W; uint32 m_key_S, m_keyrcr_S; uint32 m_key_A, m_keyrcr_A; uint32 m_key_D, m_keyrcr_D; uint32 m_key_SPACE, m_keyrcr_SPACE; uint32 m_ControllMode; int32 m_Stance; int32 m_State; f32 m_AverageFrameTime; uint32 m_PlayerControl = 0; f32 m_absCameraHigh; Vec3 m_absCameraPos; Vec3 m_absCameraPosVP; f32 m_absCurrentSlope; //in radiants Vec2 m_absLookDirectionXY; Vec3 m_LookAt; Vec3 m_LookAtRate; Vec3 m_vCamPos; Vec3 m_vCamPosRate; float m_camFOV; f32 m_relCameraRotX; f32 m_relCameraRotZ; QuatTS m_PhysicalLocation; Matrix34 m_AnimatedCharacterMat; Matrix34 m_LocalEntityMat; //this is used for data-driven animations where the character is running on the spot Matrix34 m_PrevLocalEntityMat; std::vector m_arrVerticesHF; std::vector m_arrIndicesHF; std::vector m_arrAnimatedCharacterPath; std::vector m_arrSmoothEntityPath; std::vector m_arrRunStrafeSmoothing; Vec2 m_vWorldDesiredBodyDirection; Vec2 m_vWorldDesiredBodyDirectionSmooth; Vec2 m_vWorldDesiredBodyDirectionSmoothRate; Vec2 m_vWorldDesiredBodyDirection2; Vec2 m_vWorldDesiredMoveDirection; Vec2 m_vWorldDesiredMoveDirectionSmooth; Vec2 m_vWorldDesiredMoveDirectionSmoothRate; Vec2 m_vLocalDesiredMoveDirection; Vec2 m_vLocalDesiredMoveDirectionSmooth; Vec2 m_vLocalDesiredMoveDirectionSmoothRate; Vec2 m_vWorldAimBodyDirection; f32 m_udGround; f32 m_lrGround; OBB m_GroundOBB; Vec3 m_GroundOBBPos; //------------------------------------------- // Render options. bool m_bRenderStats = true; // Index of camera objects. mutable GUID m_cameraObjectId = GUID_NULL; mutable AZ::EntityId m_viewEntityId; mutable ViewSourceType m_viewSourceType = ViewSourceType::None; AZ::EntityId m_viewEntityIdCachedForEditMode; Matrix34 m_preGameModeViewTM; uint m_disableRenderingCount = 0; bool m_bLockCameraMovement; bool m_bUpdateViewport = false; bool m_bMoveCameraObject = true; enum class KeyPressedState { AllUp, PressedThisFrame, PressedInPreviousFrame, }; KeyPressedState m_pressedKeyState = KeyPressedState::AllUp; Matrix34 m_defaultViewTM; const QString m_defaultViewName; DisplayContext m_displayContext; #if ENABLE_CRY_PHYSICS mutable PIPhysicalEntity * m_pSkipEnts = nullptr; mutable int m_numSkipEnts = 0; #endif bool m_isOnPaint = false; static CRenderViewport* m_pPrimaryViewport; QRect m_safeFrame; QRect m_safeAction; QRect m_safeTitle; CPredefinedAspectRatios m_predefinedAspectRatios; IVariable* m_pCameraFOVVariable = nullptr; bool m_bCursorHidden = false; void OnMenuResolutionCustom(); void OnMenuCreateCameraFromCurrentView(); void OnMenuCreateCameraEntityFromCurrentView(); void OnMenuSelectCurrentCamera(); int OnCreate(); void resizeEvent(QResizeEvent* event) override; void paintEvent(QPaintEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void OnLButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnLButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnLButtonDblClk(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnMButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnMButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnRButtonDown(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnRButtonUp(Qt::KeyboardModifiers modifiers, const QPoint& point) override; void OnMouseMove(Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint& point) override; void OnMouseWheel(Qt::KeyboardModifiers modifiers, short zDelta, const QPoint& pt) override; // From a series of input primitives, compose a complete mouse interaction. AzToolsFramework::ViewportInteraction::MouseInteraction BuildMouseInteractionInternal( AzToolsFramework::ViewportInteraction::MouseButtons buttons, AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers, const AzToolsFramework::ViewportInteraction::MousePick& mousePick) const; // Given a point in the viewport, return the pick ray into the scene. // note: The argument passed to parameter **point**, originating // from a Qt event, must first be passed to WidgetToViewport before being // passed to BuildMousePick. AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(const QPoint& point); bool event(QEvent* event) override; void OnDestroy(); bool CheckRespondToInput() const; // AzFramework::InputSystemCursorConstraintRequestBus void* GetSystemCursorConstraintWindow() const override { return renderOverlayHWND(); } void BuildDragDropContext(AzQtComponents::ViewportDragContext& context, const QPoint& pt) override; private: void ProcessKeyRelease(QKeyEvent* event); void PushDisableRendering(); void PopDisableRendering(); bool IsRenderingDisabled() const; AzToolsFramework::ViewportInteraction::MousePick BuildMousePickInternal( const QPoint& point) const; void RestoreViewportAfterGameMode(); double WidgetToViewportFactor() const { #if defined(AZ_PLATFORM_WINDOWS) // Needed for high DPI mode on windows return devicePixelRatioF(); #else return 1.0f; #endif } void BeginUndoTransaction() override; void EndUndoTransaction() override; void UpdateCurrentMousePos(const QPoint& newPosition); SPreviousContext m_previousContext; QSet m_keyDown; bool m_freezeViewportInput = false; size_t m_cameraSetForWidgetRenderingCount = 0; ///< How many calls to PreWidgetRendering happened before ///< subsequent calls to PostWidetRendering. AZStd::shared_ptr m_manipulatorManager; AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING // Used to prevent circular set camera events bool m_ignoreSetViewFromEntityPerspective = false; bool m_windowResizedEvent = false; // Cache hwnd value for teardown to avoid infinite loops in retrieving it from destroyed widgets. HWND m_hwnd; }; #endif // CRYINCLUDE_EDITOR_RENDERVIEWPORT_H