Merge remote-tracking branch 'upstream/main' into nvsickle/ViewportControllerAPI
This commit is contained in:
@@ -10,5 +10,4 @@
|
||||
#
|
||||
|
||||
add_subdirectory(CryCommon)
|
||||
add_subdirectory(CryFont)
|
||||
add_subdirectory(CrySystem)
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
Matrix34 m_matInv;
|
||||
Vec3 m_eyePosInWS;
|
||||
Vec3 m_eyePosInOS;
|
||||
Plane m_volumeTraceStartPlane;
|
||||
Plane_tpl<f32> m_volumeTraceStartPlane;
|
||||
AABB m_renderBoundsOS;
|
||||
bool m_viewerInsideVolume;
|
||||
bool m_nearPlaneIntersectsVolume;
|
||||
|
||||
@@ -25,7 +25,7 @@ public:
|
||||
|
||||
virtual void mfPrepare(bool bCheckOverflow);
|
||||
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
|
||||
virtual void mfGetPlane(Plane& pl);
|
||||
virtual void mfGetPlane(Plane_tpl<f32>& pl);
|
||||
|
||||
virtual void Create(uint32 nVerticesCount, SVF_P3F_C4B_T2F* pVertices, uint32 nIndicesCount, const void* pIndices, uint32 nIndexSizeof);
|
||||
void ReleaseOcean();
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
virtual ~CREWaterVolume();
|
||||
virtual void mfPrepare(bool bCheckOverflow);
|
||||
virtual bool mfDraw(CShader* ef, SShaderPass* sfm);
|
||||
virtual void mfGetPlane(Plane& pl);
|
||||
virtual void mfGetPlane(Plane_tpl<f32>& pl);
|
||||
virtual void mfCenter(Vec3& vCenter, CRenderObject* pObj);
|
||||
|
||||
virtual void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
Vec3 m_center;
|
||||
AABB m_WSBBox;
|
||||
|
||||
Plane m_fogPlane;
|
||||
Plane_tpl<f32> m_fogPlane;
|
||||
float m_fogDensity;
|
||||
Vec3 m_fogColor;
|
||||
bool m_fogColorAffectedBySun;
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : declaration of struct CryEngineDecalInfo.
|
||||
|
||||
// Note:
|
||||
// 3D Engine and Character Animation subsystems (as well as perhaps
|
||||
// some others) transfer data about the decals that need to be spawned
|
||||
// via this structure. This is to avoid passing many parameters through
|
||||
// each function call, and to save on copying these parameters when just
|
||||
// simply passing the structure from one function to another.
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
|
||||
#define CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
|
||||
#pragma once
|
||||
|
||||
#include "Cry_Math.h"
|
||||
|
||||
// Summary:
|
||||
// Structure containing common parameters that describe a decal
|
||||
|
||||
struct SDecalOwnerInfo
|
||||
{
|
||||
SDecalOwnerInfo() { memset(this, 0, sizeof(*this)); nRenderNodeSlotId = nRenderNodeSlotSubObjectId = -1; }
|
||||
struct IStatObj* GetOwner(Matrix34A& objMat);
|
||||
|
||||
struct IRenderNode* pRenderNode; // Owner (decal will be attached to or wrapped around of this object)
|
||||
PodArray<struct SRNInfo>* pDecalReceivers;
|
||||
int nRenderNodeSlotId; // is set internally by 3dengine
|
||||
int nRenderNodeSlotSubObjectId; // is set internally by 3dengine
|
||||
int nMatID;
|
||||
};
|
||||
|
||||
struct CryEngineDecalInfo
|
||||
{
|
||||
SDecalOwnerInfo ownerInfo;
|
||||
Vec3 vPos; // Decal position (world coordinates)
|
||||
Vec3 vNormal; // Decal/face normal
|
||||
float fSize; // Decal size
|
||||
float fLifeTime; // Decal life time (in seconds)
|
||||
float fAngle; // Angle of rotation
|
||||
struct IStatObj* pIStatObj; // Decal geometry
|
||||
Vec3 vHitDirection; // Direction from weapon/player position to decal position (bullet direction)
|
||||
float fGrowTime, fGrowTimeAlpha;// Used for blood pools
|
||||
unsigned int nGroupId; // Used for multi-component decals
|
||||
bool bSkipOverlappingTest; // Always spawn decals even if there are a lot of other decals in same place
|
||||
bool bAssemble; // Assemble to bigger decals if more than 1 decal is on the same place
|
||||
bool bForceEdge; // force the decal to the nearest edge of the owner mesh and project it accordingly
|
||||
bool bForceSingleOwner; // Do not attempt to cast the decal into the environment even if it's large enough
|
||||
bool bDeferred;
|
||||
uint8 sortPrio;
|
||||
char szMaterialName[_MAX_PATH]; // name of material used for rendering the decal (in favor of szTextureName/nTid and the default decal shader)
|
||||
bool preventDecalOnGround; // mainly for decal placement support
|
||||
const Matrix33* pExplicitRightUpFront; // mainly for decal placement support
|
||||
|
||||
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const{}
|
||||
|
||||
// the constructor fills in some non-obligatory fields; the other fields must be filled in by the client
|
||||
CryEngineDecalInfo ()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
ownerInfo.nRenderNodeSlotId = ownerInfo.nRenderNodeSlotSubObjectId = -1;
|
||||
sortPrio = 255;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_CRYENGINEDECALINFO_H
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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/EBus/EBus.h>
|
||||
|
||||
#include <CryCommon/ISystem.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
/*!
|
||||
* Signal LY to create an ICryFont
|
||||
*/
|
||||
class CryFontCreationRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
virtual bool CreateCryFont([[maybe_unused]] SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams) {return false;} //! return false to fall back to default CryFont initialization
|
||||
};
|
||||
using CryFontCreationRequestBus = AZ::EBus<CryFontCreationRequests>;
|
||||
|
||||
}
|
||||
@@ -594,7 +594,7 @@ public:
|
||||
ILINE const Vec3& GetFPVertex(int nId) const; //get far-plane vertices
|
||||
ILINE const Vec3& GetPPVertex(int nId) const; //get projection-plane vertices
|
||||
|
||||
ILINE const Plane* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; }
|
||||
ILINE const Plane_tpl<f32>* GetFrustumPlane(int numplane) const { return &m_fp[numplane]; }
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Z-Buffer ranges.
|
||||
@@ -720,7 +720,7 @@ private:
|
||||
Vec3 m_cltn, m_crtn, m_clbn, m_crbn; //this are the 4 vertices of the near-plane in cam-space
|
||||
Vec3 m_cltf, m_crtf, m_clbf, m_crbf; //this are the 4 vertices of the farclip-plane in cam-space
|
||||
|
||||
Plane m_fp [FRUSTUM_PLANES]; //
|
||||
Plane_tpl<f32> m_fp [FRUSTUM_PLANES]; //
|
||||
uint32 m_idx1[FRUSTUM_PLANES], m_idy1[FRUSTUM_PLANES], m_idz1[FRUSTUM_PLANES]; //
|
||||
uint32 m_idx2[FRUSTUM_PLANES], m_idy2[FRUSTUM_PLANES], m_idz2[FRUSTUM_PLANES]; //
|
||||
|
||||
@@ -742,7 +742,7 @@ public:
|
||||
m_crtp = arrvVerts[2];
|
||||
m_crbp = arrvVerts[3];
|
||||
}
|
||||
inline void SetFrustumPlane(int i, const Plane& plane)
|
||||
inline void SetFrustumPlane(int i, const Plane_tpl<f32>& plane)
|
||||
{
|
||||
m_fp[i] = plane;
|
||||
//do not break strict aliasing rules, use union instead of reinterpret_casts
|
||||
@@ -1180,12 +1180,12 @@ inline void CCamera::UpdateFrustum()
|
||||
//-------------------------------------------------------------------------------
|
||||
//--- calculate the six frustum-planes using the frustum edges in world-space ---
|
||||
//-------------------------------------------------------------------------------
|
||||
m_fp[FR_PLANE_NEAR ] = Plane::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition());
|
||||
m_fp[FR_PLANE_RIGHT ] = Plane::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_LEFT ] = Plane::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_TOP ] = Plane::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_BOTTOM] = Plane::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_FAR ] = Plane::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane
|
||||
m_fp[FR_PLANE_NEAR ] = Plane_tpl<f32>::CreatePlane(m_crtn + GetPosition(), m_cltn + GetPosition(), m_crbn + GetPosition());
|
||||
m_fp[FR_PLANE_RIGHT ] = Plane_tpl<f32>::CreatePlane(m_crbf + GetPosition(), m_crtf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_LEFT ] = Plane_tpl<f32>::CreatePlane(m_cltf + GetPosition(), m_clbf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_TOP ] = Plane_tpl<f32>::CreatePlane(m_crtf + GetPosition(), m_cltf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_BOTTOM] = Plane_tpl<f32>::CreatePlane(m_clbf + GetPosition(), m_crbf + GetPosition(), GetPosition());
|
||||
m_fp[FR_PLANE_FAR ] = Plane_tpl<f32>::CreatePlane(m_crtf + GetPosition(), m_crbf + GetPosition(), m_cltf + GetPosition()); //clip-plane
|
||||
|
||||
uint32 rh = m_Matrix.IsOrthonormalRH();
|
||||
if (rh == 0)
|
||||
|
||||
@@ -1168,17 +1168,6 @@ namespace Distance {
|
||||
return fDist2;
|
||||
}
|
||||
|
||||
// Compute both the min and max distances of a box to a plane, in the sense of the plane normal.
|
||||
inline void AABB_Plane(float* pfDistMin, float* pfDistMax, const AABB& box, const Plane& pl)
|
||||
{
|
||||
float fDist0 = pl.DistFromPlane(box.min),
|
||||
fDistX = (box.max.x - box.min.x) * pl.n.x,
|
||||
fDistY = (box.max.y - box.min.y) * pl.n.y,
|
||||
fDistZ = (box.max.z - box.min.z) * pl.n.z;
|
||||
*pfDistMin = fDist0 + min(fDistX, 0.f) + min(fDistY, 0.f) + min(fDistZ, 0.f);
|
||||
*pfDistMax = fDist0 + max(fDistX, 0.f) + max(fDistY, 0.f) + max(fDistZ, 0.f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Distance: Sphere_Triangle
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <Cry_Geo.h>
|
||||
|
||||
namespace Intersect {
|
||||
inline bool Ray_Plane(const Ray& ray, const Plane& plane, Vec3& output, bool bSingleSidePlane = true)
|
||||
inline bool Ray_Plane(const Ray& ray, const Plane_tpl<f32>& plane, Vec3& output, bool bSingleSidePlane = true)
|
||||
{
|
||||
float cosine = plane.n | ray.direction;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Intersect {
|
||||
return true; //intersection occurred
|
||||
}
|
||||
|
||||
inline bool Line_Plane(const Line& line, const Plane& plane, Vec3& output, bool bSingleSidePlane = true)
|
||||
inline bool Line_Plane(const Line& line, const Plane_tpl<f32>& plane, Vec3& output, bool bSingleSidePlane = true)
|
||||
{
|
||||
float cosine = plane.n | line.direction;
|
||||
|
||||
|
||||
@@ -945,29 +945,6 @@ namespace Overlap {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
* we use the SEPARATING-AXIS-TEST for OBB/Plane overlap.
|
||||
*
|
||||
* Example:
|
||||
* bool result=Overlap::OBB_Plane( pos,obb, plane );
|
||||
*
|
||||
*/
|
||||
inline bool OBB_Plane(const Vec3& pos, const OBB& obb, const Plane& plane)
|
||||
{
|
||||
//the new center-position in world-space
|
||||
Vec3 p = obb.m33 * obb.c + pos;
|
||||
//extract the orientation-vectors from the columns of the 3x3 matrix
|
||||
//and scale them by the half-lengths
|
||||
Vec3 ax = Vec3(obb.m33.m00, obb.m33.m10, obb.m33.m20) * obb.h.x;
|
||||
Vec3 ay = Vec3(obb.m33.m01, obb.m33.m11, obb.m33.m21) * obb.h.y;
|
||||
Vec3 az = Vec3(obb.m33.m02, obb.m33.m12, obb.m33.m22) * obb.h.z;
|
||||
//check OBB against Plane, using the plane-normal as separating axis
|
||||
return fabsf(plane | p) < (fabsf(plane.n | ax) + fabsf(plane.n | ay) + fabsf(plane.n | az));
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
*
|
||||
* we use the SEPARATING AXIS TEST to check if a triangle and AABB overlap.
|
||||
@@ -1214,7 +1191,7 @@ namespace Overlap {
|
||||
|
||||
//test if the box intersects the plane of the triangle
|
||||
//compute plane equation of triangle: normal*x+d=0
|
||||
Plane plane = Plane::CreatePlane((e0 % e1), v0);
|
||||
Plane_tpl<f32> plane = Plane_tpl<f32>::CreatePlane((e0 % e1), v0);
|
||||
|
||||
Vec3 vmin, vmax;
|
||||
if (plane.n.x > 0.0f)
|
||||
@@ -1505,7 +1482,7 @@ namespace Overlap {
|
||||
|
||||
//test if the box overlaps the plane of the triangle
|
||||
//compute plane equation of triangle: normal*x+d=0
|
||||
Plane plane = Plane::CreatePlane((e0 % e1), v0);
|
||||
Plane_tpl<f32> plane = Plane_tpl<f32>::CreatePlane((e0 % e1), v0);
|
||||
|
||||
Vec3 vmin, vmax;
|
||||
if (plane.n.x > 0.0f)
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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 <platform.h>
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#include AZ_RESTRICTED_FILE(Gem_h)
|
||||
#endif
|
||||
|
||||
#if defined(LINUX) || defined(APPLE) || defined(ANDROID)
|
||||
#define OPENGL 1
|
||||
#endif
|
||||
|
||||
#include <Common/RendererDefs.h>
|
||||
|
||||
#include <Cry_Math.h>
|
||||
#include <Cry_XOptimise.h>
|
||||
#include <Cry_Math.h>
|
||||
#include <Cry_Geo.h>
|
||||
#include <CryArray.h>
|
||||
#include <CryHeaders.h>
|
||||
#include <CrySizer.h>
|
||||
#include <CryArray.h>
|
||||
|
||||
#include <IProcess.h>
|
||||
#include <ITimer.h>
|
||||
#include <ISystem.h>
|
||||
#include <ILog.h>
|
||||
#include <IConsole.h>
|
||||
#include <IRenderer.h>
|
||||
#include <IRenderAuxGeom.h>
|
||||
#include <IEntityRenderState.h>
|
||||
#include <I3DEngine.h>
|
||||
#include <IStreamEngine.h>
|
||||
|
||||
#include <CryArray2d.h>
|
||||
#include <PoolAllocator.h>
|
||||
#include <Cry3DEngineBase.h>
|
||||
#include <cvars.h>
|
||||
#include <Material.h>
|
||||
#include <3dEngine.h>
|
||||
#include <ObjMan.h>
|
||||
#include <StlUtils.h>
|
||||
|
||||
#include <Common/CommonRender.h>
|
||||
#include <Common/Shaders/ShaderComponents.h>
|
||||
#include <Common/Shaders/Shader.h>
|
||||
#include <Common/Shaders/CShader.h>
|
||||
#include <Common/RenderMesh.h>
|
||||
#include <Common/RenderPipeline.h>
|
||||
#include <Common/RenderThread.h>
|
||||
#include <Common/Renderer.h>
|
||||
#include <Common/Textures/Texture.h>
|
||||
#include <Common/Shaders/Parser.h>
|
||||
|
||||
#include <RenderDll/Common/OcclQuery.h>
|
||||
#include <RenderDll/Common/DeferredRenderUtils.h>
|
||||
#include <RenderDll/Common/Textures/TextureManager.h>
|
||||
#include <RenderDll/Common/FrameProfiler.h>
|
||||
#include <RenderDll/XRenderD3D9/DeviceManager/DeviceManagerInline.h>
|
||||
#include <RenderDll/XRenderD3D9/DriverD3D.h>
|
||||
#include <RenderDll/XRenderD3D9/DeviceManager/TempDynBuffer.h>
|
||||
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Asset/AssetTypeInfoBus.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Component/ComponentApplicationBus.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Component/TickBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/IO/GenericStreams.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/XML/rapidxml.h>
|
||||
|
||||
#include <AzFramework/Asset/SimpleAsset.h>
|
||||
#include <AzFramework/Asset/AssetCatalogBus.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
|
||||
#include <LmbrCentral/Rendering/RenderNodeBus.h>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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_CRYCOMMON_I3DENGINE_INFO_H
|
||||
#define CRYINCLUDE_CRYCOMMON_I3DENGINE_INFO_H
|
||||
#pragma once
|
||||
|
||||
#include "TypeInfo_impl.h"
|
||||
#include "IShader_info.h"
|
||||
#include <I3DEngine.h> // <> required for Interfuscator
|
||||
|
||||
STRUCT_INFO_BEGIN(SVisAreaManChunkHeader)
|
||||
STRUCT_VAR_INFO(nVersion, TYPE_INFO(int8))
|
||||
STRUCT_VAR_INFO(nDummy, TYPE_INFO(int8))
|
||||
STRUCT_VAR_INFO(nFlags, TYPE_INFO(int8))
|
||||
STRUCT_VAR_INFO(nFlags2, TYPE_INFO(int8))
|
||||
STRUCT_VAR_INFO(nChunkSize, TYPE_INFO(int))
|
||||
STRUCT_VAR_INFO(nVisAreasNum, TYPE_INFO(int))
|
||||
STRUCT_VAR_INFO(nPortalsNum, TYPE_INFO(int))
|
||||
STRUCT_VAR_INFO(nOcclAreasNum, TYPE_INFO(int))
|
||||
STRUCT_INFO_END(SVisAreaManChunkHeader)
|
||||
|
||||
STRUCT_INFO_BEGIN(SOcTreeNodeChunk)
|
||||
STRUCT_VAR_INFO(nChunkVersion, TYPE_INFO(int16))
|
||||
STRUCT_VAR_INFO(ucChildsMask, TYPE_INFO(int16))
|
||||
STRUCT_VAR_INFO(nodeBox, TYPE_INFO(AABB))
|
||||
STRUCT_VAR_INFO(nObjectsBlockSize, TYPE_INFO(int32))
|
||||
STRUCT_INFO_END(SOcTreeNodeChunk)
|
||||
|
||||
STRUCT_INFO_BEGIN(SHotUpdateInfo)
|
||||
STRUCT_VAR_INFO(nHeigtmap, TYPE_INFO(uint32))
|
||||
STRUCT_VAR_INFO(nObjTypeMask, TYPE_INFO(uint32))
|
||||
STRUCT_VAR_INFO(areaBox, TYPE_INFO(AABB))
|
||||
STRUCT_INFO_END(SHotUpdateInfo)
|
||||
|
||||
STRUCT_INFO_BEGIN(SCommonFileHeader)
|
||||
STRUCT_VAR_INFO(signature, TYPE_ARRAY(4, TYPE_INFO(char)))
|
||||
STRUCT_VAR_INFO(file_type, TYPE_INFO(uint8))
|
||||
STRUCT_VAR_INFO(flags, TYPE_INFO(uint8))
|
||||
STRUCT_VAR_INFO(version, TYPE_INFO(uint16))
|
||||
STRUCT_INFO_END(SCommonFileHeader)
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_I3DENGINE_INFO_H
|
||||
@@ -286,7 +286,6 @@ struct IRenderNode
|
||||
// Physicalizes node.
|
||||
virtual void Physicalize([[maybe_unused]] bool bInstant = false) {}
|
||||
|
||||
// Make sure I3DEngine::FreeRenderNodeState(this) is called in destructor of derived class.
|
||||
virtual ~IRenderNode() { assert(!m_pRNTmpData); };
|
||||
|
||||
// Summary:
|
||||
@@ -731,8 +730,8 @@ struct IWaterVolumeRenderNode
|
||||
virtual void SetAuxPhysParams(pe_params_area*) = 0;
|
||||
|
||||
virtual void CreateOcean(uint64 volumeID, /* TBD */ bool keepSerializationParams = false) = 0;
|
||||
virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0;
|
||||
virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0;
|
||||
virtual void CreateArea(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, const Vec2& surfUVScale, const Plane_tpl<f32>& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0;
|
||||
virtual void CreateRiver(uint64 volumeID, const Vec3* pVertices, unsigned int numVertices, float uTexCoordBegin, float uTexCoordEnd, const Vec2& surfUVScale, const Plane_tpl<f32>& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0;
|
||||
virtual void CreateRiver(uint64 volumeID, const AZStd::vector<AZ::Vector3>& verticies, const AZ::Transform& transform, float uTexCoordBegin, float uTexCoordEnd, const AZ::Vector2& surfUVScale, const AZ::Plane& fogPlane, bool keepSerializationParams = false, int nSID = -1) = 0;
|
||||
|
||||
virtual void SetAreaPhysicsArea(const Vec3* pVertices, unsigned int numVertices, bool keepSerializationParams = false) = 0;
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Interface for LocalMemoryUsage
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYCOMMON_ILOCALMEMORYUSAGE_H
|
||||
#define CRYINCLUDE_CRYCOMMON_ILOCALMEMORYUSAGE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
class CCamera;
|
||||
struct IRenderer;
|
||||
|
||||
struct ILocalMemoryUsage
|
||||
{
|
||||
virtual ~ILocalMemoryUsage(){}
|
||||
virtual void OnRender(IRenderer* pRenderer, const CCamera* camera) = 0;
|
||||
virtual void OnUpdate() = 0;
|
||||
virtual void DeleteGlobalData() = 0;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_ILOCALMEMORYUSAGE_H
|
||||
@@ -273,7 +273,7 @@ struct IMaterial
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// material name
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//! Set material name, (Do not use this directly, to change material name use I3DEngine::RenameMatInfo method).
|
||||
//! Set material name, (Do not use this directly
|
||||
virtual void SetName(const char* pName) = 0;
|
||||
//! Returns material name.
|
||||
virtual const char* GetName() const = 0;
|
||||
@@ -404,7 +404,6 @@ struct IMaterial
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Makes this specific material enter sketch mode.
|
||||
// Se also: I3DEngine::LoadCGF, in I3DEngine.h.
|
||||
// Current supported sketch modes:
|
||||
// - 0, no sketch.
|
||||
// - 1, normal sketch mode.
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include <ISplines.h>
|
||||
#include <IRenderer.h>
|
||||
#include <IRenderAuxGeom.h>
|
||||
#include <I3DEngine.h>
|
||||
#include <VectorSet.h>
|
||||
#include <CryName.h>
|
||||
|
||||
|
||||
@@ -202,7 +202,6 @@ struct IObjManager
|
||||
|
||||
// time counters
|
||||
virtual bool IsAfterWater(const Vec3& vPos, const SRenderingPassInfo& passInfo) = 0;
|
||||
virtual void GetObjectsStreamingStatus(I3DEngine::SObjectsStreamingStatus& outStatus) = 0;
|
||||
virtual void FreeNotUsedCGFs() = 0;
|
||||
virtual void MakeUnitCube() = 0;
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ struct SShaderItem;
|
||||
class ITexture;
|
||||
struct IMaterial;
|
||||
struct SParam;
|
||||
class CMaterial;
|
||||
struct SShaderSerializeContext;
|
||||
struct IAnimNode;
|
||||
struct SSkinningData;
|
||||
|
||||
@@ -66,7 +66,6 @@ struct IConsole;
|
||||
struct IRemoteConsole;
|
||||
struct IRenderer;
|
||||
struct IProcess;
|
||||
struct I3DEngine;
|
||||
struct ITimer;
|
||||
struct ICryFont;
|
||||
struct IMovieSystem;
|
||||
@@ -123,8 +122,6 @@ namespace Serialization {
|
||||
struct IArchiveHost;
|
||||
}
|
||||
|
||||
struct ILocalMemoryUsage;
|
||||
|
||||
typedef void* WIN_HWND;
|
||||
|
||||
class CCamera;
|
||||
@@ -793,7 +790,6 @@ struct SSystemUpdateStats
|
||||
// ISystem
|
||||
struct SSystemGlobalEnvironment
|
||||
{
|
||||
I3DEngine* p3DEngine;
|
||||
AZ::IO::IArchive* pCryPak;
|
||||
AZ::IO::FileIOBase* pFileIO;
|
||||
IFileChangeMonitor* pFileChangeMonitor;
|
||||
@@ -801,7 +797,6 @@ struct SSystemGlobalEnvironment
|
||||
IOpticsManager* pOpticsManager;
|
||||
ITimer* pTimer;
|
||||
ICryFont* pCryFont;
|
||||
ILocalMemoryUsage* pLocalMemoryUsage;
|
||||
::IConsole* pConsole;
|
||||
ISystem* pSystem = nullptr;
|
||||
ILog* pLog;
|
||||
@@ -1113,25 +1108,9 @@ struct ISystem
|
||||
virtual void DoWorkDuringOcclusionChecks() = 0;
|
||||
virtual bool NeedDoWorkDuringOcclusionChecks() = 0;
|
||||
|
||||
// Summary:
|
||||
// Renders subsystems.
|
||||
virtual void Render() = 0;
|
||||
// Summary:
|
||||
// Begins rendering frame.
|
||||
virtual void RenderBegin() = 0;
|
||||
// Summary:
|
||||
// Ends rendering frame and swap back buffer.
|
||||
virtual void RenderEnd(bool bRenderStats = true, bool bMainWindow = true) = 0;
|
||||
|
||||
//! Update screen and call some important tick functions during loading.
|
||||
virtual void SynchronousLoadingTick(const char* pFunc, int line) = 0;
|
||||
|
||||
// Description:
|
||||
// Renders the statistics; this is called from RenderEnd, but if the
|
||||
// Host application (Editor) doesn't employ the Render cycle in ISystem,
|
||||
// it may call this method to render the essential statistics.
|
||||
virtual void RenderStatistics() = 0;
|
||||
|
||||
// Summary:
|
||||
// Returns the current used memory.
|
||||
virtual uint32 GetUsedMemory() = 0;
|
||||
@@ -1229,7 +1208,6 @@ struct ISystem
|
||||
virtual ICryFont* GetICryFont() = 0;
|
||||
virtual IMemoryManager* GetIMemoryManager() = 0;
|
||||
virtual IMovieSystem* GetIMovieSystem() = 0;
|
||||
virtual I3DEngine* GetI3DEngine() = 0;
|
||||
virtual ::IConsole* GetIConsole() = 0;
|
||||
virtual IRemoteConsole* GetIRemoteConsole() = 0;
|
||||
// Returns:
|
||||
|
||||
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
#pragma once
|
||||
|
||||
struct SBezierKey;
|
||||
struct ITimeOfDayUpdateCallback;
|
||||
struct ISplineInterpolator;
|
||||
|
||||
|
||||
//! Interface to the Time Of Day functionality.
|
||||
struct ITimeOfDay
|
||||
{
|
||||
enum ETimeOfDayParamID
|
||||
{
|
||||
PARAM_SUN_COLOR,
|
||||
PARAM_SUN_INTENSITY,
|
||||
PARAM_SUN_SPECULAR_MULTIPLIER,
|
||||
|
||||
PARAM_FOG_COLOR,
|
||||
PARAM_FOG_COLOR_MULTIPLIER,
|
||||
PARAM_VOLFOG_HEIGHT,
|
||||
PARAM_VOLFOG_DENSITY,
|
||||
PARAM_FOG_COLOR2,
|
||||
PARAM_FOG_COLOR2_MULTIPLIER,
|
||||
PARAM_VOLFOG_HEIGHT2,
|
||||
PARAM_VOLFOG_DENSITY2,
|
||||
PARAM_VOLFOG_HEIGHT_OFFSET,
|
||||
|
||||
PARAM_FOG_RADIAL_COLOR,
|
||||
PARAM_FOG_RADIAL_COLOR_MULTIPLIER,
|
||||
PARAM_VOLFOG_RADIAL_SIZE,
|
||||
PARAM_VOLFOG_RADIAL_LOBE,
|
||||
|
||||
PARAM_VOLFOG_FINAL_DENSITY_CLAMP,
|
||||
|
||||
PARAM_VOLFOG_GLOBAL_DENSITY,
|
||||
PARAM_VOLFOG_RAMP_START,
|
||||
PARAM_VOLFOG_RAMP_END,
|
||||
PARAM_VOLFOG_RAMP_INFLUENCE,
|
||||
|
||||
PARAM_VOLFOG_SHADOW_DARKENING,
|
||||
PARAM_VOLFOG_SHADOW_DARKENING_SUN,
|
||||
PARAM_VOLFOG_SHADOW_DARKENING_AMBIENT,
|
||||
PARAM_VOLFOG_SHADOW_RANGE,
|
||||
|
||||
PARAM_VOLFOG2_HEIGHT,
|
||||
PARAM_VOLFOG2_DENSITY,
|
||||
PARAM_VOLFOG2_HEIGHT2,
|
||||
PARAM_VOLFOG2_DENSITY2,
|
||||
PARAM_VOLFOG2_GLOBAL_DENSITY,
|
||||
PARAM_VOLFOG2_RAMP_START,
|
||||
PARAM_VOLFOG2_RAMP_END,
|
||||
PARAM_VOLFOG2_COLOR1,
|
||||
PARAM_VOLFOG2_ANISOTROPIC1,
|
||||
PARAM_VOLFOG2_COLOR2,
|
||||
PARAM_VOLFOG2_ANISOTROPIC2,
|
||||
PARAM_VOLFOG2_BLEND_FACTOR,
|
||||
PARAM_VOLFOG2_BLEND_MODE,
|
||||
PARAM_VOLFOG2_COLOR,
|
||||
PARAM_VOLFOG2_ANISOTROPIC,
|
||||
PARAM_VOLFOG2_RANGE,
|
||||
PARAM_VOLFOG2_INSCATTER,
|
||||
PARAM_VOLFOG2_EXTINCTION,
|
||||
PARAM_VOLFOG2_GLOBAL_FOG_VISIBILITY,
|
||||
PARAM_VOLFOG2_FINAL_DENSITY_CLAMP,
|
||||
|
||||
PARAM_SKYLIGHT_SUN_INTENSITY,
|
||||
PARAM_SKYLIGHT_SUN_INTENSITY_MULTIPLIER,
|
||||
|
||||
PARAM_SKYLIGHT_KM,
|
||||
PARAM_SKYLIGHT_KR,
|
||||
PARAM_SKYLIGHT_G,
|
||||
|
||||
PARAM_SKYLIGHT_WAVELENGTH_R,
|
||||
PARAM_SKYLIGHT_WAVELENGTH_G,
|
||||
PARAM_SKYLIGHT_WAVELENGTH_B,
|
||||
|
||||
PARAM_NIGHSKY_HORIZON_COLOR,
|
||||
PARAM_NIGHSKY_HORIZON_COLOR_MULTIPLIER,
|
||||
PARAM_NIGHSKY_ZENITH_COLOR,
|
||||
PARAM_NIGHSKY_ZENITH_COLOR_MULTIPLIER,
|
||||
PARAM_NIGHSKY_ZENITH_SHIFT,
|
||||
|
||||
PARAM_NIGHSKY_START_INTENSITY,
|
||||
|
||||
PARAM_NIGHSKY_MOON_COLOR,
|
||||
PARAM_NIGHSKY_MOON_COLOR_MULTIPLIER,
|
||||
PARAM_NIGHSKY_MOON_INNERCORONA_COLOR,
|
||||
PARAM_NIGHSKY_MOON_INNERCORONA_COLOR_MULTIPLIER,
|
||||
PARAM_NIGHSKY_MOON_INNERCORONA_SCALE,
|
||||
PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR,
|
||||
PARAM_NIGHSKY_MOON_OUTERCORONA_COLOR_MULTIPLIER,
|
||||
PARAM_NIGHSKY_MOON_OUTERCORONA_SCALE,
|
||||
|
||||
PARAM_CLOUDSHADING_SUNLIGHT_MULTIPLIER,
|
||||
PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR,
|
||||
PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR_MULTIPLIER,
|
||||
PARAM_CLOUDSHADING_SUNLIGHT_CUSTOM_COLOR_INFLUENCE,
|
||||
|
||||
PARAM_SUN_SHAFTS_VISIBILITY,
|
||||
PARAM_SUN_RAYS_VISIBILITY,
|
||||
PARAM_SUN_RAYS_ATTENUATION,
|
||||
PARAM_SUN_RAYS_SUNCOLORINFLUENCE,
|
||||
PARAM_SUN_RAYS_CUSTOMCOLOR,
|
||||
|
||||
PARAM_OCEANFOG_COLOR, // Remove when ocean related feature toggle is removed.
|
||||
PARAM_OCEANFOG_COLOR_MULTIPLIER, // Remove when ocean related feature toggle is removed.
|
||||
PARAM_OCEANFOG_DENSITY, // Remove when ocean related feature toggle is removed.
|
||||
|
||||
PARAM_SKYBOX_MULTIPLIER,
|
||||
|
||||
PARAM_HDR_FILMCURVE_SHOULDER_SCALE,
|
||||
PARAM_HDR_FILMCURVE_LINEAR_SCALE,
|
||||
PARAM_HDR_FILMCURVE_TOE_SCALE,
|
||||
PARAM_HDR_FILMCURVE_WHITEPOINT,
|
||||
|
||||
PARAM_HDR_COLORGRADING_COLOR_SATURATION,
|
||||
PARAM_HDR_COLORGRADING_COLOR_BALANCE,
|
||||
|
||||
PARAM_HDR_EYEADAPTATION_SCENEKEY,
|
||||
PARAM_HDR_EYEADAPTATION_MIN_EXPOSURE,
|
||||
PARAM_HDR_EYEADAPTATION_MAX_EXPOSURE,
|
||||
PARAM_HDR_EYEADAPTATION_EV_MIN,
|
||||
PARAM_HDR_EYEADAPTATION_EV_MAX,
|
||||
PARAM_HDR_EYEADAPTATION_EV_AUTO_COMPENSATION,
|
||||
PARAM_HDR_BLOOM_AMOUNT,
|
||||
|
||||
PARAM_COLORGRADING_FILTERS_GRAIN,
|
||||
PARAM_COLORGRADING_FILTERS_PHOTOFILTER_COLOR,
|
||||
PARAM_COLORGRADING_FILTERS_PHOTOFILTER_DENSITY,
|
||||
|
||||
PARAM_COLORGRADING_DOF_FOCUSRANGE,
|
||||
PARAM_COLORGRADING_DOF_BLURAMOUNT,
|
||||
|
||||
PARAM_SHADOWSC0_BIAS,
|
||||
PARAM_SHADOWSC0_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC1_BIAS,
|
||||
PARAM_SHADOWSC1_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC2_BIAS,
|
||||
PARAM_SHADOWSC2_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC3_BIAS,
|
||||
PARAM_SHADOWSC3_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC4_BIAS,
|
||||
PARAM_SHADOWSC4_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC5_BIAS,
|
||||
PARAM_SHADOWSC5_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC6_BIAS,
|
||||
PARAM_SHADOWSC6_SLOPE_BIAS,
|
||||
PARAM_SHADOWSC7_BIAS,
|
||||
PARAM_SHADOWSC7_SLOPE_BIAS,
|
||||
|
||||
PARAM_SHADOW_JITTERING,
|
||||
|
||||
PARAM_HDR_DYNAMIC_POWER_FACTOR,
|
||||
PARAM_TERRAIN_OCCL_MULTIPLIER,
|
||||
PARAM_SUN_COLOR_MULTIPLIER,
|
||||
|
||||
PARAM_TOTAL
|
||||
};
|
||||
|
||||
struct SPresetInfo
|
||||
{
|
||||
const char* m_pName;
|
||||
bool m_bCurrent;
|
||||
};
|
||||
|
||||
enum EVariableType
|
||||
{
|
||||
TYPE_FLOAT,
|
||||
TYPE_COLOR
|
||||
};
|
||||
struct SVariableInfo
|
||||
{
|
||||
const char* name; //!< Variable name.
|
||||
const char* displayName; //!< Variable user readable name.
|
||||
const char* group; //!< Group name.
|
||||
int nParamId;
|
||||
EVariableType type;
|
||||
float fValue[3]; //!< Value of the variable (3 needed for color type).
|
||||
ISplineInterpolator* pInterpolator; //!< Splines that control variable value.
|
||||
};
|
||||
struct SAdvancedInfo
|
||||
{
|
||||
float fStartTime;
|
||||
float fEndTime;
|
||||
float fAnimSpeed;
|
||||
};
|
||||
struct SEnvironmentInfo
|
||||
{
|
||||
SEnvironmentInfo()
|
||||
: bSunLinkedToTOD(true)
|
||||
, sunRotationLatitude(0)
|
||||
, sunRotationLongitude(0){}
|
||||
bool bSunLinkedToTOD;
|
||||
float sunRotationLatitude;
|
||||
float sunRotationLongitude;
|
||||
};
|
||||
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ITimeOfDay(){}
|
||||
|
||||
virtual int GetPresetCount() const = 0;
|
||||
virtual bool GetPresetsInfos(SPresetInfo* resultArray, unsigned int arraySize) const = 0;
|
||||
virtual bool SetCurrentPreset(const char* szPresetName) = 0;
|
||||
virtual bool AddNewPreset(const char* szPresetName) = 0;
|
||||
virtual bool RemovePreset(const char* szPresetName) = 0;
|
||||
virtual bool SavePreset(const char* szPresetName) const = 0;
|
||||
virtual bool LoadPreset(const char* szFilePath) = 0;
|
||||
virtual void ResetPreset(const char* szPresetName) = 0;
|
||||
|
||||
virtual bool ImportPreset(const char* szPresetName, const char* szFilePath) = 0;
|
||||
virtual bool ExportPreset(const char* szPresetName, const char* szFilePath) const = 0;
|
||||
|
||||
//! Access to variables that control time of the day appearance.
|
||||
virtual int GetVariableCount() const = 0;
|
||||
virtual bool GetVariableInfo(int nIndex, SVariableInfo& varInfo) const = 0;
|
||||
virtual void SetVariableValue(int nIndex, float fValue[3]) = 0;
|
||||
|
||||
//! Editor interface.
|
||||
virtual bool InterpolateVarInRange(int nIndex, float fMin, float fMax, unsigned int nCount, Vec3* resultArray) const = 0;
|
||||
virtual uint GetSplineKeysCount(int nIndex, int nSpline) const = 0;
|
||||
virtual bool GetSplineKeysForVar(int nIndex, int nSpline, SBezierKey* keysArray, unsigned int keysArraySize) const = 0;
|
||||
virtual bool SetSplineKeysForVar(int nIndex, int nSpline, const SBezierKey* keysArray, unsigned int keysArraySize) = 0;
|
||||
virtual bool UpdateSplineKeyForVar(int nIndex, int nSpline, float fTime, float newValue) = 0;
|
||||
|
||||
virtual void ResetVariables() = 0;
|
||||
|
||||
//! Sets the time of the day specified in hours.
|
||||
virtual void SetTime(float fHour, bool bForceUpdate = false, bool bForceEnvUpdate = true) = 0;
|
||||
virtual float GetTime() = 0;
|
||||
|
||||
//! Sun position.
|
||||
virtual void SetSunPos(float longitude, float latitude) = 0;
|
||||
virtual float GetSunLatitude() = 0;
|
||||
virtual float GetSunLongitude() = 0;
|
||||
|
||||
//! Updates the current ToD.
|
||||
virtual void Tick() = 0;
|
||||
|
||||
|
||||
virtual void SetPaused(bool paused) = 0;
|
||||
|
||||
virtual void SetAdvancedInfo(const SAdvancedInfo& advInfo) = 0;
|
||||
virtual void GetAdvancedInfo(SAdvancedInfo& advInfo) = 0;
|
||||
|
||||
//! Updates engine parameters after variable values have been changed.
|
||||
virtual void Update(bool bInterpolate = true, bool bForceUpdate = false, bool bForceEnvUpdate = true) = 0;
|
||||
virtual void SetUpdateCallback(ITimeOfDayUpdateCallback* pCallback) = 0;
|
||||
|
||||
virtual void BeginEditMode() = 0;
|
||||
virtual void EndEditMode() = 0;
|
||||
|
||||
virtual void Serialize(XmlNodeRef& node, bool bLoading) = 0;
|
||||
virtual void Serialize(TSerialize ser) = 0;
|
||||
|
||||
virtual void SetTimer(ITimer* pTimer) = 0;
|
||||
virtual void SetEnvironmentSettings(const SEnvironmentInfo& envInfo) = 0;
|
||||
virtual void LerpWith(const ITimeOfDay& other, float lerpValue, ITimeOfDay& output) const = 0;
|
||||
|
||||
//! Multiplayer serialization.
|
||||
static const int NETSER_FORCESET = BIT(0);
|
||||
static const int NETSER_COMPENSATELAG = BIT(1);
|
||||
static const int NETSER_STATICPROPS = BIT(2);
|
||||
virtual void NetSerialize(TSerialize ser, float lag, uint32 flags) = 0;
|
||||
};
|
||||
|
||||
struct ITimeOfDayUpdateCallback
|
||||
{
|
||||
// <interfuscator:shuffle>
|
||||
virtual ~ITimeOfDayUpdateCallback(){}
|
||||
virtual void BeginUpdate() = 0;
|
||||
virtual bool GetCustomValue(ITimeOfDay::ETimeOfDayParamID paramID, int dim, float* pValues, float& blendWeight) = 0;
|
||||
virtual void EndUpdate() = 0;
|
||||
// </interfuscator:shuffle>
|
||||
};
|
||||
|
||||
@@ -1,528 +0,0 @@
|
||||
/*
|
||||
* 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/Aabb.h>
|
||||
|
||||
#include <I3DEngine.h>
|
||||
#include <ISerialize.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
// the following was generated using google's python script to autogenerate mocks.
|
||||
// however, it needed some hand-editing to make it work, so if you add functions to I3DEngine,
|
||||
// it will probably be better to just manually add them here than try to run the script again.
|
||||
|
||||
class I3DEngineMock
|
||||
: public I3DEngine
|
||||
{
|
||||
public:
|
||||
// From IProcess
|
||||
MOCK_METHOD1(SetFlags,
|
||||
void(int));
|
||||
MOCK_METHOD0(GetFlags,
|
||||
int(void));
|
||||
|
||||
// From I3DEngine
|
||||
MOCK_METHOD0(Init,
|
||||
bool());
|
||||
MOCK_METHOD1(SetLevelPath,
|
||||
void(const char* szFolderName));
|
||||
MOCK_METHOD1(CheckMinSpec,
|
||||
bool(uint32 nMinSpec));
|
||||
MOCK_METHOD1(PrepareOcclusion,
|
||||
void(const CCamera& rCamera));
|
||||
MOCK_METHOD0(EndOcclusion,
|
||||
void());
|
||||
MOCK_METHOD2(LoadLevel,
|
||||
bool(const char* szFolderName, const char* szMissionName));
|
||||
MOCK_METHOD2(InitLevelForEditor,
|
||||
bool(const char* szFolderName, const char* szMissionName));
|
||||
MOCK_METHOD0(LevelLoadingInProgress,
|
||||
bool());
|
||||
MOCK_METHOD0(OnFrameStart,
|
||||
void());
|
||||
MOCK_METHOD0(PostLoadLevel,
|
||||
void());
|
||||
MOCK_METHOD0(LoadEmptyLevel,
|
||||
void());
|
||||
MOCK_METHOD0(UnloadLevel,
|
||||
void());
|
||||
MOCK_METHOD0(Update,
|
||||
void());
|
||||
MOCK_CONST_METHOD0(GetRenderingCamera,
|
||||
const CCamera&());
|
||||
MOCK_CONST_METHOD0(GetZoomFactor,
|
||||
float());
|
||||
MOCK_METHOD0(Tick,
|
||||
void());
|
||||
MOCK_METHOD0(UpdateShaderItems,
|
||||
void());
|
||||
MOCK_METHOD0(Release,
|
||||
void());
|
||||
MOCK_METHOD3(RenderWorld,
|
||||
void(int nRenderFlags, const SRenderingPassInfo& passInfo, const char* szDebugName));
|
||||
MOCK_METHOD2(RenderSceneReflection,
|
||||
void(int nRenderFlags, const SRenderingPassInfo& passInfo));
|
||||
MOCK_METHOD1(PreWorldStreamUpdate,
|
||||
void(const CCamera& cam));
|
||||
MOCK_METHOD0(WorldStreamUpdate,
|
||||
void());
|
||||
MOCK_METHOD0(ShutDown,
|
||||
void());
|
||||
MOCK_METHOD7(LoadStatObjUnsafeManualRef,
|
||||
IStatObj*(const char* fileName, const char* geomName, IStatObj::SSubObject** subObject,
|
||||
bool useStreaming, unsigned long loadingFlags, const void* data, int dataSize));
|
||||
MOCK_METHOD7(LoadStatObjAutoRef,
|
||||
_smart_ptr<IStatObj>(const char* fileName, const char* geomName, IStatObj::SSubObject** subObject,
|
||||
bool useStreaming, unsigned long loadingFlags, const void* data, int dataSize));
|
||||
MOCK_METHOD0(ProcessAsyncStaticObjectLoadRequests,
|
||||
void());
|
||||
MOCK_METHOD5(LoadStatObjAsync,
|
||||
void(LoadStaticObjectAsyncResult resultCallback, const char* szFileName, const char* szGeomName, bool bUseStreaming, unsigned long nLoadingFlags));
|
||||
MOCK_METHOD1(FindStatObjectByFilename,
|
||||
IStatObj*(const char* filename));
|
||||
MOCK_METHOD0(GetGSMRange,
|
||||
const float());
|
||||
MOCK_METHOD0(GetGSMRangeStep,
|
||||
const float());
|
||||
MOCK_METHOD0(GetLoadedObjectCount,
|
||||
int());
|
||||
MOCK_METHOD2(GetLoadedStatObjArray,
|
||||
void(IStatObj** pObjectsArray, int& nCount));
|
||||
MOCK_METHOD1(GetObjectsStreamingStatus,
|
||||
void(SObjectsStreamingStatus& outStatus));
|
||||
MOCK_METHOD2(GetStreamingSubsystemData,
|
||||
void(int subsystem, SStremaingBandwidthData& outData));
|
||||
MOCK_METHOD3(RegisterEntity,
|
||||
void(IRenderNode* pEntity, int nSID, int nSIDConsideredSafe));
|
||||
MOCK_METHOD1(SelectEntity,
|
||||
void(IRenderNode* pEntity));
|
||||
MOCK_METHOD0(IsSunShadows,
|
||||
bool());
|
||||
MOCK_METHOD2(MakeSystemMaterialFromShaderHelper
|
||||
, _smart_ptr<IMaterial>(const char* sShaderName, SInputShaderResources* Res));
|
||||
MOCK_METHOD1(CheckMinSpecHelper
|
||||
, bool(uint32 nMinSpec));
|
||||
MOCK_METHOD1(OnCasterDeleted
|
||||
, void(IShadowCaster* pCaster));
|
||||
MOCK_METHOD4(GetStatObjAndMatTables,
|
||||
void(DynArray<IStatObj*>* pStatObjTable, DynArray<_smart_ptr<IMaterial>>* pMatTable, DynArray<IStatInstGroup*>* pStatInstGroupTable, uint32 nObjTypeMask));
|
||||
#ifndef _RELEASE
|
||||
MOCK_METHOD1(AddObjToDebugDrawList,
|
||||
void(SObjectInfoToAddToDebugDrawList& objInfo));
|
||||
MOCK_CONST_METHOD0(IsDebugDrawListEnabled,
|
||||
bool());
|
||||
#endif
|
||||
MOCK_METHOD1(UnRegisterEntityDirect,
|
||||
void(IRenderNode* pEntity));
|
||||
MOCK_METHOD1(UnRegisterEntityAsJob,
|
||||
void(IRenderNode* pEnt));
|
||||
MOCK_CONST_METHOD1(IsUnderWater,
|
||||
bool(const Vec3& vPos));
|
||||
MOCK_METHOD1(SetOceanRenderFlags,
|
||||
void(uint8 nFlags));
|
||||
MOCK_CONST_METHOD0(GetOceanRenderFlags,
|
||||
uint8());
|
||||
MOCK_CONST_METHOD0(GetOceanVisiblePixelsCount,
|
||||
uint32());
|
||||
MOCK_METHOD3(GetBottomLevel,
|
||||
float(const Vec3& referencePos, float maxRelevantDepth, int objtypes));
|
||||
MOCK_METHOD2(GetBottomLevel,
|
||||
float(const Vec3& referencePos, float maxRelevantDepth));
|
||||
MOCK_METHOD2(GetBottomLevel,
|
||||
float(const Vec3& referencePos, int objflags));
|
||||
MOCK_METHOD0(GetWaterLevel,
|
||||
float());
|
||||
MOCK_METHOD3(GetWaterLevel,
|
||||
float(const Vec3* pvPos, IPhysicalEntity* pent, bool bAccurate));
|
||||
MOCK_CONST_METHOD1(GetAccurateOceanHeight,
|
||||
float(const Vec3& pCurrPos));
|
||||
MOCK_CONST_METHOD0(GetCausticsParams,
|
||||
CausticsParams());
|
||||
MOCK_CONST_METHOD0(GetOceanAnimationParams,
|
||||
OceanAnimationData());
|
||||
MOCK_CONST_METHOD1(GetHDRSetupParams,
|
||||
void(Vec4 pParams[5]));
|
||||
MOCK_METHOD0(ResetParticlesAndDecals,
|
||||
void());
|
||||
MOCK_METHOD1(CreateDecal,
|
||||
void(const CryEngineDecalInfo& Decal));
|
||||
MOCK_METHOD2(DeleteDecalsInRange,
|
||||
void(AABB* pAreaBox, IRenderNode* pEntity));
|
||||
MOCK_METHOD1(SetSunColor,
|
||||
void(Vec3 vColor));
|
||||
MOCK_METHOD0(GetSunAnimColor,
|
||||
Vec3());
|
||||
MOCK_METHOD1(SetSunAnimColor,
|
||||
void(const Vec3& color));
|
||||
MOCK_METHOD0(GetSunAnimSpeed,
|
||||
float());
|
||||
MOCK_METHOD1(SetSunAnimSpeed,
|
||||
void(float sunAnimSpeed));
|
||||
MOCK_METHOD0(GetSunAnimPhase,
|
||||
AZ::u8());
|
||||
MOCK_METHOD1(SetSunAnimPhase,
|
||||
void(AZ::u8 sunAnimPhase));
|
||||
MOCK_METHOD0(GetSunAnimIndex,
|
||||
AZ::u8());
|
||||
MOCK_METHOD1(SetSunAnimIndex,
|
||||
void(AZ::u8 sunAnimIndex));
|
||||
MOCK_METHOD1(SetRainParams,
|
||||
void(const SRainParams& rainParams));
|
||||
MOCK_METHOD1(GetRainParams,
|
||||
bool(SRainParams& rainParams));
|
||||
MOCK_METHOD5(SetSnowSurfaceParams,
|
||||
void(const Vec3& vCenter, float fRadius, float fSnowAmount, float fFrostAmount, float fSurfaceFreezing));
|
||||
MOCK_METHOD5(GetSnowSurfaceParams,
|
||||
bool(Vec3& vCenter, float& fRadius, float& fSnowAmount, float& fFrostAmount, float& fSurfaceFreezing));
|
||||
MOCK_METHOD7(SetSnowFallParams,
|
||||
void(int nSnowFlakeCount, float fSnowFlakeSize, float fSnowFallBrightness, float fSnowFallGravityScale, float fSnowFallWindScale, float fSnowFallTurbulence, float fSnowFallTurbulenceFreq));
|
||||
MOCK_METHOD7(GetSnowFallParams,
|
||||
bool(int& nSnowFlakeCount, float& fSnowFlakeSize, float& fSnowFallBrightness, float& fSnowFallGravityScale, float& fSnowFallWindScale, float& fSnowFallTurbulence, float& fSnowFallTurbulenceFreq));
|
||||
MOCK_METHOD1(SetMaxViewDistanceScale,
|
||||
void(float fScale));
|
||||
MOCK_METHOD1(GetMaxViewDistance,
|
||||
float(bool));
|
||||
MOCK_CONST_METHOD0(GetFrameLodInfo,
|
||||
const SFrameLodInfo&());
|
||||
MOCK_METHOD1(SetFrameLodInfo,
|
||||
void(const SFrameLodInfo& frameLodInfo));
|
||||
MOCK_METHOD1(SetFogColor,
|
||||
void(const Vec3& vFogColor));
|
||||
MOCK_METHOD0(GetFogColor,
|
||||
Vec3());
|
||||
MOCK_METHOD6(GetSkyLightParameters,
|
||||
void(Vec3& sunDir, Vec3& sunIntensity, float& Km, float& Kr, float& g, Vec3& rgbWaveLengths));
|
||||
MOCK_METHOD7(SetSkyLightParameters,
|
||||
void(const Vec3& sunDir, const Vec3& sunIntensity, float Km, float Kr, float g, const Vec3& rgbWaveLengths, bool forceImmediateUpdate));
|
||||
MOCK_CONST_METHOD0(GetLightsHDRDynamicPowerFactor,
|
||||
float());
|
||||
MOCK_CONST_METHOD3(IsTessellationAllowed,
|
||||
bool(const CRenderObject* pObj, const SRenderingPassInfo& passInfo, bool bIgnoreShadowPass));
|
||||
MOCK_METHOD3(SetRenderNodeMaterialAtPosition,
|
||||
void(EERType eNodeType, const Vec3& vPos, _smart_ptr<IMaterial> pMat));
|
||||
MOCK_METHOD1(OverrideCameraPrecachePoint,
|
||||
void(const Vec3& vPos));
|
||||
MOCK_METHOD4(AddPrecachePoint,
|
||||
int(const Vec3& vPos, const Vec3& vDir, float fTimeOut, float fImportanceFactor));
|
||||
MOCK_METHOD1(ClearPrecachePoint,
|
||||
void(int id));
|
||||
MOCK_METHOD0(ClearAllPrecachePoints,
|
||||
void());
|
||||
MOCK_METHOD1(GetPrecacheRoundIds,
|
||||
void(int pRoundIds[MAX_STREAM_PREDICTION_ZONES]));
|
||||
MOCK_METHOD5(TraceFogVolumes,
|
||||
void(const Vec3& vPos, const AABB& objBBox, SFogVolumeData& fogVolData, const SRenderingPassInfo& passInfo, bool fogVolumeShadingQuality));
|
||||
|
||||
MOCK_METHOD1(RemoveAllStaticObjects,
|
||||
void(int));
|
||||
MOCK_METHOD3(SetStatInstGroup,
|
||||
bool(int nGroupId, const IStatInstGroup& siGroup, int nSID));
|
||||
MOCK_METHOD3(GetStatInstGroup,
|
||||
bool(int, IStatInstGroup&, int));
|
||||
MOCK_METHOD3(OnExplosion,
|
||||
void(Vec3, float, bool));
|
||||
MOCK_METHOD1(SetPhysMaterialEnumerator,
|
||||
void(IPhysMaterialEnumerator* pPhysMaterialEnumerator));
|
||||
MOCK_METHOD0(GetPhysMaterialEnumerator,
|
||||
IPhysMaterialEnumerator*());
|
||||
MOCK_METHOD0(SetupDistanceFog,
|
||||
void());
|
||||
MOCK_METHOD1(LoadMissionDataFromXMLNode,
|
||||
void(const char* szMissionName));
|
||||
MOCK_METHOD2(LoadEnvironmentSettingsFromXML,
|
||||
void(XmlNodeRef, int));
|
||||
MOCK_METHOD0(LoadCompiledOctreeForEditor,
|
||||
bool());
|
||||
MOCK_CONST_METHOD0(GetSunDir,
|
||||
Vec3());
|
||||
MOCK_CONST_METHOD0(GetSunDirNormalized,
|
||||
Vec3());
|
||||
MOCK_CONST_METHOD0(GetRealtimeSunDirNormalized,
|
||||
Vec3());
|
||||
MOCK_METHOD0(GetDistanceToSectorWithWater,
|
||||
float());
|
||||
MOCK_CONST_METHOD0(GetSunColor,
|
||||
Vec3());
|
||||
MOCK_CONST_METHOD0(GetSSAOAmount,
|
||||
float());
|
||||
MOCK_CONST_METHOD0(GetSSAOContrast,
|
||||
float());
|
||||
MOCK_METHOD1(FreeRenderNodeState,
|
||||
void(IRenderNode* pEntity));
|
||||
MOCK_METHOD1(GetLevelFilePath,
|
||||
const char*(const char* szFileName));
|
||||
MOCK_METHOD4(DisplayInfo,
|
||||
void(float& fTextPosX, float& fTextPosY, float& fTextStepY, bool bEnhanced));
|
||||
MOCK_METHOD0(DisplayMemoryStatistics,
|
||||
void());
|
||||
|
||||
// Can't mock methods with variable parameters so just create empty bodies for them.
|
||||
void DrawTextRightAligned([[maybe_unused]] const float x, [[maybe_unused]] const float y, [[maybe_unused]] const char* format, ...) override {}
|
||||
void DrawTextRightAligned([[maybe_unused]] const float x, [[maybe_unused]] const float y, [[maybe_unused]] const float scale, [[maybe_unused]] const ColorF& color, [[maybe_unused]] const char* format, ...) override {}
|
||||
|
||||
MOCK_METHOD3(DrawBBoxHelper
|
||||
, void (const Vec3& vMin, const Vec3& vMax, ColorB col));
|
||||
MOCK_METHOD2(DrawBBoxHelper
|
||||
, void (const AABB& box, ColorB col));
|
||||
|
||||
MOCK_METHOD3(ActivatePortal,
|
||||
void(const Vec3& vPos, bool bActivate, const char* szEntityName));
|
||||
MOCK_CONST_METHOD1(GetMemoryUsage,
|
||||
void(ICrySizer* pSizer));
|
||||
MOCK_METHOD2(GetResourceMemoryUsage,
|
||||
void(ICrySizer* pSizer, const AABB& cstAABB));
|
||||
MOCK_METHOD1(CreateVisArea,
|
||||
IVisArea*(uint64 visGUID));
|
||||
MOCK_METHOD1(DeleteVisArea,
|
||||
void(IVisArea* pVisArea));
|
||||
MOCK_METHOD6(UpdateVisArea,
|
||||
void(IVisArea* pArea, const Vec3* pPoints, int nCount, const char* szName, const SVisAreaInfo& info, bool bReregisterObjects));
|
||||
MOCK_METHOD4(IsVisAreasConnected,
|
||||
bool(IVisArea* pArea1, IVisArea* pArea2, int nMaxRecursion, bool bSkipDisabledPortals));
|
||||
MOCK_METHOD0(CreateClipVolume,
|
||||
IClipVolume*());
|
||||
MOCK_METHOD1(DeleteClipVolume,
|
||||
void(IClipVolume* pClipVolume));
|
||||
MOCK_METHOD7(UpdateClipVolume,
|
||||
void(IClipVolume* pClipVolume, _smart_ptr<IRenderMesh> pRenderMesh, IBSPTree3D* pBspTree, const Matrix34& worldTM, bool bActive, uint32 flags, const char* szName));
|
||||
MOCK_METHOD1(CreateRenderNode,
|
||||
IRenderNode*(EERType type));
|
||||
MOCK_METHOD1(DeleteRenderNode,
|
||||
void(IRenderNode* pRenderNode));
|
||||
MOCK_METHOD1(SetWind,
|
||||
void(const Vec3& vWind));
|
||||
MOCK_CONST_METHOD2(GetWind,
|
||||
Vec3(const AABB& box, bool bIndoors));
|
||||
MOCK_CONST_METHOD1(GetGlobalWind,
|
||||
Vec3(bool bIndoors));
|
||||
MOCK_CONST_METHOD4(SampleWind,
|
||||
bool(Vec3* pSamples, int nSamples, const AABB& volume, bool bIndoors));
|
||||
MOCK_METHOD1(GetVisAreaFromPos,
|
||||
IVisArea*(const Vec3& vPos));
|
||||
MOCK_METHOD2(IntersectsVisAreas,
|
||||
bool(const AABB& box, void** pNodeCache));
|
||||
MOCK_METHOD4(ClipToVisAreas,
|
||||
bool(IVisArea* pInside, Sphere& sphere, Vec3 const& vNormal, void* pNodeCache));
|
||||
MOCK_METHOD1(EnableOceanRendering,
|
||||
void(bool bOcean));
|
||||
MOCK_METHOD1(AddTextureLoadHandler,
|
||||
void(ITextureLoadHandler* pHandler));
|
||||
MOCK_METHOD1(RemoveTextureLoadHandler,
|
||||
void(ITextureLoadHandler* pHandler));
|
||||
MOCK_METHOD1(GetTextureLoadHandlerForImage,
|
||||
ITextureLoadHandler*(const char* ext));
|
||||
MOCK_METHOD0(CreateLightSource,
|
||||
struct ILightSource*());
|
||||
MOCK_METHOD1(DeleteLightSource,
|
||||
void(ILightSource* pLightSource));
|
||||
MOCK_METHOD0(GetLightEntities,
|
||||
const PodArray<ILightSource*>* ());
|
||||
MOCK_METHOD3(GetLightVolumes,
|
||||
void(threadID nThreadID, SLightVolume*& pLightVols, uint32& nNumVols));
|
||||
MOCK_METHOD4(RegisterVolumeForLighting,
|
||||
uint16(const Vec3& vPos, f32 fRadius, uint8 nClipVolumeRef, const SRenderingPassInfo& passInfo));
|
||||
MOCK_METHOD1(RestoreTerrainFromDisk,
|
||||
bool(int));
|
||||
MOCK_METHOD1(GetFilePath,
|
||||
const char*(const char* szFileName));
|
||||
MOCK_CONST_METHOD0(GetPostEffectGroups,
|
||||
class IPostEffectGroupManager*());
|
||||
MOCK_CONST_METHOD0(GetPostEffectBaseGroup,
|
||||
class IPostEffectGroup*());
|
||||
MOCK_CONST_METHOD3(SetPostEffectParam,
|
||||
void(const char* pParam, float fValue, bool bForceValue));
|
||||
MOCK_CONST_METHOD3(SetPostEffectParamVec4,
|
||||
void(const char* pParam, const Vec4& pValue, bool bForceValue));
|
||||
MOCK_CONST_METHOD2(SetPostEffectParamString,
|
||||
void(const char* pParam, const char* pszArg));
|
||||
MOCK_CONST_METHOD2(GetPostEffectParam,
|
||||
void(const char* pParam, float& fValue));
|
||||
MOCK_CONST_METHOD2(GetPostEffectParamVec4,
|
||||
void(const char* pParam, Vec4& pValue));
|
||||
MOCK_CONST_METHOD2(GetPostEffectParamString,
|
||||
void(const char* pParam, const char*& pszArg));
|
||||
MOCK_METHOD1(GetPostEffectID,
|
||||
int32(const char* pPostEffectName));
|
||||
MOCK_METHOD1(ResetPostEffects,
|
||||
void(bool));
|
||||
MOCK_METHOD0(DisablePostEffects,
|
||||
void());
|
||||
MOCK_METHOD1(SetShadowsGSMCache,
|
||||
void(bool bCache));
|
||||
MOCK_METHOD2(SetCachedShadowBounds,
|
||||
void(const AABB& shadowBounds, float fAdditionalCascadesScale));
|
||||
MOCK_METHOD1(SetRecomputeCachedShadows,
|
||||
void(uint));
|
||||
MOCK_METHOD0(CheckMemoryHeap,
|
||||
void());
|
||||
MOCK_METHOD1(DeleteEntityDecals,
|
||||
void(IRenderNode* pEntity));
|
||||
MOCK_METHOD0(LockCGFResources,
|
||||
void());
|
||||
MOCK_METHOD0(UnlockCGFResources,
|
||||
void());
|
||||
MOCK_METHOD0(FreeUnusedCGFResources,
|
||||
void());
|
||||
MOCK_METHOD0(CreateStatObj,
|
||||
IStatObj*());
|
||||
MOCK_METHOD1(CreateStatObjOptionalIndexedMesh,
|
||||
IStatObj*(bool createIndexedMesh));
|
||||
MOCK_METHOD0(CreateIndexedMesh,
|
||||
IIndexedMesh*());
|
||||
MOCK_METHOD1(SerializeState,
|
||||
void(TSerialize ser));
|
||||
MOCK_METHOD1(PostSerialize,
|
||||
void(bool bReading));
|
||||
MOCK_METHOD0(GetMaterialHelpers,
|
||||
IMaterialHelpers&());
|
||||
MOCK_METHOD0(GetMaterialManager,
|
||||
IMaterialManager*());
|
||||
MOCK_METHOD0(GetObjManager,
|
||||
IObjManager*());
|
||||
MOCK_METHOD1(CreateChunkfileContent,
|
||||
CContentCGF*(const char* filename));
|
||||
MOCK_METHOD1(ReleaseChunkfileContent,
|
||||
void(CContentCGF*));
|
||||
MOCK_METHOD4(LoadChunkFileContent,
|
||||
bool(CContentCGF* pCGF, const char* filename, bool bNoWarningMode, bool bCopyChunkFile));
|
||||
MOCK_METHOD6(LoadChunkFileContentFromMem,
|
||||
bool(CContentCGF* pCGF, const void* pData, size_t nDataLen, uint32 nLoadingFlags, bool bNoWarningMode, bool bCopyChunkFile));
|
||||
MOCK_METHOD1(CreateChunkFile,
|
||||
IChunkFile*(bool));
|
||||
MOCK_CONST_METHOD3(CreateChunkFileWriter,
|
||||
ChunkFile::IChunkFileWriter*(EChunkFileFormat eFormat, AZ::IO::IArchive* pPak, const char* filename));
|
||||
MOCK_CONST_METHOD1(ReleaseChunkFileWriter,
|
||||
void(ChunkFile::IChunkFileWriter* p));
|
||||
MOCK_METHOD2(CreateOcean,
|
||||
bool(_smart_ptr<IMaterial> pTerrainWaterMat, float waterLevel));
|
||||
MOCK_METHOD0(DeleteOcean,
|
||||
void());
|
||||
MOCK_METHOD1(ChangeOceanMaterial,
|
||||
void(_smart_ptr<IMaterial> pMat));
|
||||
MOCK_METHOD1(ChangeOceanWaterLevel,
|
||||
void(float fWaterLevel));
|
||||
MOCK_METHOD1(InitMaterialDefautMappingAxis
|
||||
, void(_smart_ptr<IMaterial> pMat));
|
||||
MOCK_METHOD0(GetIVisAreaManager,
|
||||
IVisAreaManager*());
|
||||
MOCK_METHOD3(PrecacheLevel,
|
||||
void(bool bPrecacheAllVisAreas, Vec3* pPrecachePoints, int nPrecachePointsNum));
|
||||
MOCK_METHOD0(ProposeContentPrecache,
|
||||
void());
|
||||
MOCK_METHOD0(GetTimeOfDay,
|
||||
ITimeOfDay*());
|
||||
MOCK_METHOD1(SetSkyMaterialPath,
|
||||
void(const string& skyMaterialPath));
|
||||
MOCK_METHOD1(SetSkyLowSpecMaterialPath,
|
||||
void(const string& skyMaterialPath));
|
||||
MOCK_METHOD0(LoadSkyMaterial,
|
||||
void());
|
||||
MOCK_METHOD0(GetSkyMaterial,
|
||||
_smart_ptr<IMaterial>());
|
||||
MOCK_METHOD1(SetSkyMaterial,
|
||||
void(_smart_ptr<IMaterial> pSkyMat));
|
||||
MOCK_METHOD2(SetGlobalParameter,
|
||||
void(E3DEngineParameter param, const Vec3& v));
|
||||
MOCK_METHOD2(GetGlobalParameter,
|
||||
void(E3DEngineParameter param, Vec3& v));
|
||||
MOCK_METHOD1(SetShadowMode,
|
||||
void(EShadowMode shadowMode));
|
||||
MOCK_CONST_METHOD0(GetShadowMode,
|
||||
EShadowMode());
|
||||
MOCK_METHOD6(AddPerObjectShadow,
|
||||
void(IShadowCaster* pCaster, float fConstBias, float fSlopeBias, float fJitter, const Vec3& vBBoxScale, uint nTexSize));
|
||||
MOCK_METHOD1(RemovePerObjectShadow,
|
||||
void(IShadowCaster* pCaster));
|
||||
MOCK_METHOD1(GetPerObjectShadow,
|
||||
struct SPerObjectShadow*(IShadowCaster* pCaster));
|
||||
MOCK_METHOD2(GetCustomShadowMapFrustums,
|
||||
void(struct ShadowMapFrustum*& arrFrustums, int& nFrustumCount));
|
||||
MOCK_METHOD2(SaveStatObj,
|
||||
int(IStatObj* pStatObj, TSerialize ser));
|
||||
MOCK_METHOD1(LoadStatObj,
|
||||
IStatObj*(TSerialize ser));
|
||||
MOCK_METHOD2(CheckIntersectClouds,
|
||||
bool(const Vec3& p1, const Vec3& p2));
|
||||
MOCK_METHOD1(OnRenderMeshDeleted,
|
||||
void(IRenderMesh* pRenderMesh));
|
||||
MOCK_METHOD0(DebugDraw_UpdateDebugNode,
|
||||
void());
|
||||
MOCK_METHOD4(RayObjectsIntersection2D,
|
||||
bool(Vec3 vStart, Vec3 vEnd, Vec3& vHitPoint, EERType eERType));
|
||||
MOCK_METHOD3(RenderMeshRayIntersection,
|
||||
bool(IRenderMesh* pRenderMesh, SRayHitInfo& hitInfo, _smart_ptr<IMaterial> pCustomMtl));
|
||||
MOCK_METHOD3(CheckCreateRNTmpData
|
||||
, void(CRNTmpData** ppInfo, IRenderNode* pRNode, const SRenderingPassInfo& passInfo));
|
||||
MOCK_METHOD1(FreeRNTmpData,
|
||||
void(CRNTmpData** ppInfo));
|
||||
MOCK_METHOD0(IsObjectTreeReady
|
||||
, bool());
|
||||
MOCK_METHOD0(GetIObjectTree
|
||||
, IOctreeNode*());
|
||||
MOCK_METHOD2(GetObjectsByType,
|
||||
uint32(EERType, IRenderNode**));
|
||||
MOCK_METHOD4(GetObjectsByTypeInBox,
|
||||
uint32(EERType objType, const AABB& bbox, IRenderNode** pObjects, ObjectTreeQueryFilterCallback filterCallback));
|
||||
MOCK_METHOD2(GetObjectsInBox,
|
||||
uint32(const AABB& bbox, IRenderNode** pObjects));
|
||||
MOCK_METHOD2(GetObjectsByFlags,
|
||||
uint32(uint, IRenderNode**));
|
||||
MOCK_METHOD4(GetObjectsByTypeInBox,
|
||||
void(EERType objType, const AABB& bbox, PodArray<IRenderNode*>* pLstObjects, ObjectTreeQueryFilterCallback filterCallback));
|
||||
MOCK_METHOD2(OnObjectModified,
|
||||
void(IRenderNode* pRenderNode, uint dwFlags));
|
||||
MOCK_METHOD1(FillDebugFPSInfo,
|
||||
void(SDebugFPSInfo&));
|
||||
MOCK_METHOD0(GetLevelFolder,
|
||||
const char*());
|
||||
MOCK_METHOD0(IsAreaActivationInUse,
|
||||
bool());
|
||||
MOCK_METHOD3(RenderRenderNode_ShadowPass,
|
||||
void(IShadowCaster* pRNode, const SRenderingPassInfo& passInfo, AZ::LegacyJobExecutor* pJobExecutor));
|
||||
MOCK_METHOD0(GetOpticsManager,
|
||||
IOpticsManager*());
|
||||
MOCK_METHOD0(SyncProcessStreamingUpdate,
|
||||
void());
|
||||
MOCK_METHOD1(SetScreenshotCallback,
|
||||
void(IScreenshotCallback* pCallback));
|
||||
MOCK_METHOD8(ActivateObjectsLayer,
|
||||
void(uint16 nLayerId, bool bActivate, bool bPhys, bool bObjects, bool bStaticLights, const char* pLayerName, IGeneralMemoryHeap* pHeap, bool bCheckLayerActivation));
|
||||
MOCK_CONST_METHOD4(GetLayerMemoryUsage,
|
||||
void(uint16 nLayerId, ICrySizer* pSizer, int* pNumBrushes, int* pNumDecals));
|
||||
MOCK_METHOD2(SkipLayerLoading,
|
||||
void(uint16 nLayerId, bool bClearList));
|
||||
MOCK_METHOD2(PrecacheRenderNode,
|
||||
void(IRenderNode* pObj, float fEntDistanceReal));
|
||||
MOCK_METHOD0(GetDeferredPhysicsEventManager,
|
||||
IDeferredPhysicsEventManager*());
|
||||
MOCK_METHOD1(SetStreamableListener,
|
||||
void(IStreamedObjectListener* pListener));
|
||||
MOCK_METHOD1(GetRenderingPassCamera,
|
||||
CCamera*(const CCamera& rCamera));
|
||||
MOCK_METHOD3(GetSvoStaticTextures,
|
||||
void(I3DEngine::SSvoStaticTexInfo& svoInfo, PodArray<I3DEngine::SLightTI>* pLightsTI_S, PodArray<I3DEngine::SLightTI>* pLightsTI_D));
|
||||
MOCK_METHOD2(GetSvoBricksForUpdate,
|
||||
void(PodArray<SSvoNodeInfo>& arrNodeInfo, bool getDynamic));
|
||||
#if defined(USE_GEOM_CACHES)
|
||||
MOCK_METHOD1(LoadGeomCache,
|
||||
IGeomCache*(const char* szFileName));
|
||||
MOCK_METHOD1(FindGeomCacheByFilename,
|
||||
IGeomCache*(const char* szFileName));
|
||||
#endif
|
||||
MOCK_METHOD3(LoadDesignerObject,
|
||||
IStatObj*(int nVersion, const char* szBinaryStream, int size));
|
||||
|
||||
MOCK_METHOD0(WaitForCullingJobsCompletion,
|
||||
void());
|
||||
};
|
||||
|
||||
@@ -12,11 +12,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <IRenderer.h>
|
||||
#include <I3DEngine.h> // needed for SRenderingPassInfo definition
|
||||
#include <IVideoRenderer.h>
|
||||
#include <IImage.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
struct SRendItemSorter {};
|
||||
struct SRenderingPassInfo {};
|
||||
struct SClipVolumeBlendInfo {};
|
||||
struct SFogVolumeData {};
|
||||
|
||||
// the following was generated using google's python script to autogenerate mocks.
|
||||
// however, it needed some hand-editing to make it work, so if you add functions to IRenderer,
|
||||
// it will probably be better to just manually add them here than try to run the script again
|
||||
|
||||
@@ -37,12 +37,6 @@ public:
|
||||
void());
|
||||
MOCK_METHOD0(NeedDoWorkDuringOcclusionChecks,
|
||||
bool());
|
||||
MOCK_METHOD0(Render,
|
||||
void());
|
||||
MOCK_METHOD0(RenderBegin,
|
||||
void());
|
||||
MOCK_METHOD2(RenderEnd,
|
||||
void(bool, bool));
|
||||
MOCK_METHOD2(SynchronousLoadingTick,
|
||||
void(const char* pFunc, int line));
|
||||
MOCK_METHOD0(RenderStatistics,
|
||||
@@ -124,8 +118,6 @@ public:
|
||||
IMovieSystem * ());
|
||||
MOCK_METHOD0(GetIAudioSystem,
|
||||
Audio::IAudioSystem * ());
|
||||
MOCK_METHOD0(GetI3DEngine,
|
||||
I3DEngine * ());
|
||||
MOCK_METHOD0(GetIConsole,
|
||||
::IConsole * ());
|
||||
MOCK_METHOD0(GetIRemoteConsole,
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <ITimer.h>
|
||||
|
||||
//! Simple stub timer that exposes a single simple interface for setting the current time.
|
||||
class StubTimer
|
||||
: public ITimer
|
||||
|
||||
@@ -119,7 +119,7 @@ struct IRenderElement
|
||||
virtual void mfCenter(Vec3& centr, CRenderObject* pObj) = 0;
|
||||
virtual void mfGetBBox(Vec3& vMins, Vec3& vMaxs) = 0;
|
||||
virtual void mfReset() = 0;
|
||||
virtual void mfGetPlane(Plane& pl) = 0;
|
||||
virtual void mfGetPlane(Plane_tpl<f32>& pl) = 0;
|
||||
virtual void mfExport(struct SShaderSerializeContext& SC) = 0;
|
||||
virtual void mfImport(struct SShaderSerializeContext& SC, uint32& offset) = 0;
|
||||
virtual void mfPrecache(const SShaderItem& SH) = 0;
|
||||
@@ -265,7 +265,7 @@ public:
|
||||
void mfPrecache([[maybe_unused]] const SShaderItem& SH) override {}
|
||||
void mfExport([[maybe_unused]] struct SShaderSerializeContext& SC) override { CryFatalError("mfExport has not been implemented for this render element type"); }
|
||||
void mfImport([[maybe_unused]] struct SShaderSerializeContext& SC, [[maybe_unused]] uint32& offset) override { CryFatalError("mfImport has not been implemented for this render element type"); }
|
||||
void mfGetPlane(Plane& pl) override;
|
||||
void mfGetPlane(Plane_tpl<f32>& pl) override;
|
||||
void* mfGetPointer([[maybe_unused]] ESrcPointer ePT, [[maybe_unused]] int* Stride, [[maybe_unused]] EParamType Type, [[maybe_unused]] ESrcPointer Dst, [[maybe_unused]] int Flags) override { return nullptr; }
|
||||
|
||||
uint16 mfGetFlags() override { return m_Flags; }
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(WIN32)
|
||||
#include "CryWindows.h"
|
||||
#include "IRenderer.h"
|
||||
#include "IImage.h"
|
||||
#include "smartptr.h"
|
||||
#include "ImageExtensionHelper.h"
|
||||
|
||||
// Types supported by CreateResourceFromTexture
|
||||
enum EResourceType
|
||||
{
|
||||
eResourceType_IconBig,
|
||||
eResourceType_IconSmall,
|
||||
eResourceType_Cursor,
|
||||
};
|
||||
|
||||
// Loads a (DDS) texture resource from the renderer into a Win32 GDI resource.
|
||||
// Returns a HICON that must be closed with DestroyIcon(), or NULL on failure.
|
||||
static HICON CreateResourceFromTexture(IRenderer* pRenderer, const char* path, EResourceType type)
|
||||
{
|
||||
if (!pRenderer || !path || !*path)
|
||||
{
|
||||
// Invalid parameter passed
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find the target dimensions of the GDI resource
|
||||
const int nRequestedWidth = GetSystemMetrics(type == eResourceType_IconBig ? SM_CXICON : type == eResourceType_IconSmall ? SM_CXSMICON : SM_CXCURSOR);
|
||||
const int nRequestedHeight = GetSystemMetrics(type == eResourceType_IconBig ? SM_CYICON : type == eResourceType_IconSmall ? SM_CYSMICON : SM_CYCURSOR);
|
||||
if (nRequestedWidth != nRequestedHeight || nRequestedHeight <= 0 || nRequestedWidth <= 0)
|
||||
{
|
||||
// Don't support non-squares icons or cursors
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Load texture.
|
||||
// in this case, we want to fall back on a null, not substiture the missing texture.
|
||||
_smart_ptr<IImageFile> pImage = pRenderer->EF_LoadImage(path, FIM_NOFALLBACKS);
|
||||
if (!pImage || pImage->mfGet_depth() != 1 || pImage->mfGet_NumSides() != 1 || pImage->mfGetTileMode() != eTM_None)
|
||||
{
|
||||
// Can't load texture, or texture is a cube-map or volume texture, or uses tiling of some kind
|
||||
return NULL;
|
||||
}
|
||||
byte* pImgRaw = pImage->mfGet_image(0);
|
||||
const ETEX_Format texFormat = pImage->mfGetFormat();
|
||||
|
||||
// Pick first mip level smaller than the GDI resource
|
||||
int nMip = 0;
|
||||
size_t offset = 0;
|
||||
int nMipWidth = pImage->mfGet_width();
|
||||
int nMipHeight = pImage->mfGet_height();
|
||||
while (nMipWidth > nRequestedWidth)
|
||||
{
|
||||
++nMip;
|
||||
offset += pRenderer->GetTextureFormatDataSize(nMipWidth, nMipHeight, 1, 1, texFormat);
|
||||
nMipWidth = max(nMipWidth / 2, 1);
|
||||
nMipHeight = max(nMipHeight / 2, 1);
|
||||
}
|
||||
pImgRaw += offset;
|
||||
if (nMip >= pImage->mfGet_numMips())
|
||||
{
|
||||
// No appropriate mip in the texture
|
||||
// Note: Consider creating a full mip-chain on the texture so this can't happen
|
||||
return NULL;
|
||||
}
|
||||
const size_t nRawSize = pRenderer->GetTextureFormatDataSize(nMipWidth, nMipHeight, 1, 1, texFormat);
|
||||
|
||||
#if 0
|
||||
// Check that DDS indexing is correct here
|
||||
offset += nRawSize;
|
||||
for (int nIdx = nMip + 1; nIdx < pImage->mfGet_numMips(); ++nIdx)
|
||||
{
|
||||
const int w = max(nMipWidth >> (nIdx - nMip), 1);
|
||||
const int h = max(nMipHeight >> (nIdx - nMip), 1);
|
||||
offset += pRenderer->GetTextureFormatDataSize(w, h, 1, 1, texFormat);
|
||||
}
|
||||
assert(offset == pImage->mfGet_ImageSize());
|
||||
#endif
|
||||
|
||||
// Type of bitmap to create
|
||||
BITMAPV5HEADER bi = { 0 };
|
||||
bi.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi.bV5Width = nRequestedWidth;
|
||||
bi.bV5Height = -nRequestedHeight;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_BITFIELDS;
|
||||
// The following mask specification specifies a supported 32 BPP alpha format for Windows XP+
|
||||
bi.bV5AlphaMask = 0xFF000000;
|
||||
bi.bV5RedMask = 0x00FF0000;
|
||||
bi.bV5GreenMask = 0x0000FF00;
|
||||
bi.bV5BlueMask = 0x000000FF;
|
||||
|
||||
// Create the DIB section with an alpha channel
|
||||
const HDC hdc = GetDC(NULL);
|
||||
void* lpBits;
|
||||
const HBITMAP hBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bi, DIB_RGB_COLORS, &lpBits, NULL, 0);
|
||||
ReleaseDC(NULL, hdc);
|
||||
if (!hBitmap || !lpBits)
|
||||
{
|
||||
// Can't allocate OS bitmap
|
||||
return NULL;
|
||||
}
|
||||
GdiFlush();
|
||||
|
||||
// Decompress texture
|
||||
const bool bTryDecompress = texFormat != eTF_R8G8B8A8 && texFormat != eTF_B8G8R8A8 && texFormat != eTF_B8G8R8X8;
|
||||
byte* const pImgDecomp = bTryDecompress ? new byte[nMipWidth * nMipHeight * sizeof(int32)] : pImgRaw;
|
||||
const bool bImgDecompressed = bTryDecompress && pRenderer->DXTDecompress(pImgRaw, nRawSize, pImgDecomp, nMipWidth, nMipHeight, 1, texFormat, false, sizeof(int32));
|
||||
|
||||
// Check which conversions need to be performed
|
||||
const bool bSRGB = (pImage->mfGet_Flags() & CImageExtensionHelper::EIF_SRGBRead) != 0;
|
||||
const bool bSwap = (texFormat == eTF_R8G8B8A8) || bTryDecompress;
|
||||
|
||||
HICON result = NULL;
|
||||
if (!bTryDecompress || bImgDecompressed)
|
||||
{
|
||||
// Assign texture data with mismatching sizes
|
||||
// Note: Any pixels not in the selected mip will become 100% transparent black, no resizing is performed
|
||||
const size_t sourceRowStride = nMipWidth;
|
||||
const size_t targetRowStride = nRequestedWidth;
|
||||
const uint32* pSourceRow = (uint32*)pImgDecomp;
|
||||
uint32* pTargetRow = (uint32*)lpBits;
|
||||
|
||||
assert(sourceRowStride <= targetRowStride);
|
||||
assert(nMipHeight <= nRequestedHeight);
|
||||
assert(pSourceRow != pTargetRow);
|
||||
assert(pSourceRow && pTargetRow);
|
||||
|
||||
uint8 gammaTable[256];
|
||||
if (!bSRGB)
|
||||
{
|
||||
// Linear to sRGB table
|
||||
const float gamma = 1.0f / 2.2f;
|
||||
const float gammaMultiplier = 255.0f / powf(255.0f, gamma);
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
gammaTable[i] = uint8(powf(float(i), gamma) * gammaMultiplier);
|
||||
}
|
||||
}
|
||||
else if (bSwap)
|
||||
{
|
||||
// sRGB to sRGB table (no change)
|
||||
for (int i = 0; i < 256; ++i)
|
||||
{
|
||||
gammaTable[i] = uint8(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int y = 0; y < nMipHeight; ++y, pSourceRow += sourceRowStride, pTargetRow += targetRowStride)
|
||||
{
|
||||
if (!bSwap && bSRGB)
|
||||
{
|
||||
memcpy(pTargetRow, pSourceRow, sourceRowStride * sizeof(uint32));
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32* pSourceTexel = pSourceRow;
|
||||
uint32* pTargetTexel = pTargetRow;
|
||||
for (int x = 0; x < nMipWidth; ++x, ++pSourceTexel, ++pTargetTexel)
|
||||
{
|
||||
const uint8 red = gammaTable[uint8(*pSourceTexel >> 0)];
|
||||
const uint8 green = gammaTable[uint8(*pSourceTexel >> 8)];
|
||||
const uint8 blue = gammaTable[uint8(*pSourceTexel >> 16)];
|
||||
const uint32 alpha = *pSourceTexel & 0xFF000000;
|
||||
*pTargetTexel = (red << (bSwap ? 16 : 0)) | (green << 8) | (blue << (bSwap ? 0 : 16)) | alpha;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill remaining columns with zeros
|
||||
memset(pTargetRow + sourceRowStride, 0, (targetRowStride - sourceRowStride) * sizeof(uint32));
|
||||
}
|
||||
|
||||
// Fill remaining rows with zeros
|
||||
for (int y = nMipHeight; y < nRequestedHeight; ++y)
|
||||
{
|
||||
memset(pTargetRow, 0, targetRowStride * sizeof(uint32));
|
||||
pTargetRow += targetRowStride;
|
||||
}
|
||||
|
||||
// Convert to GDI icon
|
||||
ICONINFO iconinfo = {0};
|
||||
iconinfo.fIcon = type == eResourceType_Cursor ? FALSE : TRUE;
|
||||
iconinfo.hbmMask = ::CreateBitmap(nRequestedWidth, nRequestedHeight, 1, 1, NULL);
|
||||
iconinfo.hbmColor = hBitmap;
|
||||
result = ::CreateIconIndirect(&iconinfo);
|
||||
DeleteObject(iconinfo.hbmMask);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
DeleteObject(hBitmap);
|
||||
if (bTryDecompress)
|
||||
{
|
||||
delete[] pImgDecomp;
|
||||
}
|
||||
pImage.reset();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -14,9 +14,6 @@ set(FILES
|
||||
CryCommon.cpp
|
||||
Allocator.h
|
||||
FinalizingSpline.h
|
||||
Gem.h
|
||||
I3DEngine.h
|
||||
I3DEngine_info.h
|
||||
IAudioInterfacesCommonData.h
|
||||
IAudioSystem.h
|
||||
IChunkFile.h
|
||||
@@ -86,7 +83,6 @@ set(FILES
|
||||
ITexture.h
|
||||
IThreadManager.h
|
||||
IThreadTask.h
|
||||
ITimeOfDay.h
|
||||
ITimer.h
|
||||
IValidator.h
|
||||
IVideoRenderer.h
|
||||
@@ -143,7 +139,6 @@ set(FILES
|
||||
CryAssert.h
|
||||
CryCrc32.h
|
||||
CryCustomTypes.h
|
||||
CryEngineDecalInfo.h
|
||||
CryFile.h
|
||||
CryFixedArray.h
|
||||
CryFixedString.h
|
||||
@@ -292,7 +287,6 @@ set(FILES
|
||||
platform_impl.cpp
|
||||
Win32specific.h
|
||||
Win64specific.h
|
||||
WindowsUtils.h
|
||||
CryExtension/CryCreateClassInstance.h
|
||||
CryExtension/CryGUID.h
|
||||
CryExtension/CryTypeID.h
|
||||
@@ -317,7 +311,6 @@ set(FILES
|
||||
CryPool/STLWrapper.h
|
||||
CryPool/ThreadSafe.h
|
||||
stl/STLAlignedAlloc.h
|
||||
ILocalMemoryUsage.h
|
||||
Serialization/Assert.h
|
||||
Serialization/BitVector.h
|
||||
Serialization/BitVectorImpl.h
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Mocks/I3DEngineMock.h
|
||||
Mocks/IAudioSystemMock.h
|
||||
Mocks/IConsoleMock.h
|
||||
Mocks/ICryPakMock.h
|
||||
|
||||
@@ -1,845 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : CCryFont class.
|
||||
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "CryFont.h"
|
||||
#include "CryPath.h"
|
||||
#include "FFont.h"
|
||||
#include "FontTexture.h"
|
||||
#include "FontRenderer.h"
|
||||
#include "ILocalizationManager.h"
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
|
||||
// Static member definitions
|
||||
const Vec2i CCryFont::defaultGlyphSize = Vec2i(ICryFont::defaultGlyphSizeX, ICryFont::defaultGlyphSizeY);
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
static void DumpFontTexture(IConsoleCmdArgs* pArgs)
|
||||
{
|
||||
if (pArgs->GetArgCount() != 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char* pFontName = pArgs->GetArg(1);
|
||||
|
||||
if (pFontName && *pFontName && *pFontName != '0')
|
||||
{
|
||||
string fontFile("@devroot@/");
|
||||
fontFile += pFontName;
|
||||
fontFile += ".bmp";
|
||||
|
||||
CFFont* pFont = (CFFont*) gEnv->pCryFont->GetFont(pFontName);
|
||||
if (pFont)
|
||||
{
|
||||
pFont->GetFontTexture()->WriteToFile(fontFile.c_str());
|
||||
gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Dumped \"%s\" texture to \"%s\"!", pFontName, fontFile.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpFontNames([[maybe_unused]] IConsoleCmdArgs* pArgs)
|
||||
{
|
||||
string names = gEnv->pCryFont->GetLoadedFontNames();
|
||||
gEnv->pLog->LogWithType(IMiniLog::eInputResponse, "Currently loaded fonts: %s", names.c_str());
|
||||
}
|
||||
|
||||
static void ReloadFonts([[maybe_unused]] IConsoleCmdArgs* pArgs)
|
||||
{
|
||||
gEnv->pCryFont->ReloadAllFonts();
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Stores paths to styled font assets for a given set of languages
|
||||
//! This struct stores the XML data contained within the <font> tag of
|
||||
//! an enclosing <fontfamily> definition:
|
||||
//!
|
||||
//! <fontfamily name="FontFamilyName">
|
||||
//! <font lang="Language1, Language2">
|
||||
//! <file path="regular.font" />
|
||||
//! <file path="bold.font" tags="b" />
|
||||
//! <file path="italic.font" tags="i" />
|
||||
//! <file path="bolditalic.font" tags="b,i" />
|
||||
//! </font>
|
||||
//! </fontfamily>
|
||||
struct FontTagXml
|
||||
{
|
||||
//! \return True if all font asset paths are non-empty, false otherwise
|
||||
bool IsValid() const
|
||||
{
|
||||
// Note that "lang" can be empty
|
||||
return !m_fontFilename.empty()
|
||||
&& !m_boldFontFilename.empty()
|
||||
&& !m_italicFontFilename.empty()
|
||||
&& !m_boldItalicFontFilename.empty();
|
||||
}
|
||||
|
||||
string m_lang; //!< Stores a comma-separated list of languages this collection of fonts applies to.
|
||||
//!< If this is an empty string, it implies that these set of fonts will be applied
|
||||
//!< by default (when a language is being used but no fonts in the font family are
|
||||
//!< mapped to that language).
|
||||
|
||||
string m_fontFilename; //!< Font used when no styling is applied.
|
||||
string m_boldFontFilename; //!< Bold-styled font
|
||||
string m_italicFontFilename; //!< Italic-styled font
|
||||
string m_boldItalicFontFilename; //!< Bold-italic-styled font
|
||||
};
|
||||
|
||||
//! Stores parsed font family XML data.
|
||||
//! This struct contains the name of the font family and a list of font
|
||||
//! file XML data for all the language-specific mappings of this
|
||||
//! font family.
|
||||
//!
|
||||
//! Example XML:
|
||||
//!
|
||||
//! <fontfamily name="FontFamilyName">
|
||||
//! <font>
|
||||
//! <file path="regular.font" />
|
||||
//! <file path="bold.font" tags="b" />
|
||||
//! <file path="italic.font" tags="i" />
|
||||
//! <file path="bolditalic.font" tags="b,i" />
|
||||
//! </font>
|
||||
//! <font lang="korean">
|
||||
//! <file path="../korean/korean-regular.font" />
|
||||
//! <file path="../korean/korean-italic.font" tags="b" />
|
||||
//! <file path="../korean/korean-bold.font" tags="i" />
|
||||
//! <file path="../korean/korean-bolditalic.font" tags="b,i" />
|
||||
//! </font>
|
||||
//! <font lang="chinesesimplified">
|
||||
//! <file path="../chinesesimplified/chinesesimplified-regular.font" />
|
||||
//! <file path="../chinesesimplified/chinesesimplified-bold.font" tags="b" />
|
||||
//! <file path="../chinesesimplified/chinesesimplified-italic.font" tags="i" />
|
||||
//! <file path="../chinesesimplified/chinesesimplified-bolditalic.font" tags="b,i" />
|
||||
//! </font>
|
||||
//! </fontfamily>
|
||||
struct FontFamilyTagXml
|
||||
{
|
||||
//! Returns true if all font file fields were parsed, false otherwise.
|
||||
bool IsValid() const
|
||||
{
|
||||
for (const FontTagXml& fontTagXml : m_fontTagsXml)
|
||||
{
|
||||
if (!fontTagXml.IsValid())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Every font family must have a name
|
||||
return !m_fontFamilyName.empty();
|
||||
}
|
||||
|
||||
string m_fontFamilyName; //!< Value of the "name" font-family tag attribute
|
||||
AZStd::list<FontTagXml> m_fontTagsXml; //!< List of child <font> tag data.
|
||||
};
|
||||
|
||||
//! Returns true if the XML tree was traversed successfully, false otherwise.
|
||||
//!
|
||||
//! Note that, if this function returns true, it simply means that there were
|
||||
//! no unexpected structure issues with the given XML tree, it doesn't
|
||||
//! necessarily mean that all the required fields were parsed.
|
||||
bool ParseFontFamilyXml(const XmlNodeRef& node, FontFamilyTagXml& xmlData)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// <fontfamily>
|
||||
if (AZStd::string(node->getTag()) == "fontfamily")
|
||||
{
|
||||
const int numAttributes = node->getNumAttributes();
|
||||
|
||||
if (numAttributes <= 0)
|
||||
{
|
||||
// Expecting at least one attribute
|
||||
return false;
|
||||
}
|
||||
|
||||
string name;
|
||||
|
||||
for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
|
||||
{
|
||||
const char* key = "";
|
||||
const char* value = "";
|
||||
if (node->getAttributeByIndex(i, &key, &value))
|
||||
{
|
||||
if (string(key) == "name")
|
||||
{
|
||||
name = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unexpected font tag attribute
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
name.Trim();
|
||||
if (!name.empty())
|
||||
{
|
||||
xmlData.m_fontFamilyName = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Font family must have a name
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// <font>
|
||||
if (AZStd::string(node->getTag()) == "font")
|
||||
{
|
||||
xmlData.m_fontTagsXml.push_back(FontTagXml());
|
||||
|
||||
string lang;
|
||||
for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
|
||||
{
|
||||
const char* key = "";
|
||||
const char* value = "";
|
||||
if (node->getAttributeByIndex(i, &key, &value))
|
||||
{
|
||||
if (string(key) == "lang")
|
||||
{
|
||||
lang = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unexpected font tag attribute
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lang.Trim();
|
||||
if (!lang.empty())
|
||||
{
|
||||
xmlData.m_fontTagsXml.back().m_lang = lang;
|
||||
}
|
||||
}
|
||||
|
||||
// <file>
|
||||
else if (AZStd::string(node->getTag()) == "file")
|
||||
{
|
||||
const int numAttributes = node->getNumAttributes();
|
||||
|
||||
if (numAttributes <= 0)
|
||||
{
|
||||
// Expecting at least one attribute
|
||||
return false;
|
||||
}
|
||||
|
||||
string path;
|
||||
string tags;
|
||||
|
||||
for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
|
||||
{
|
||||
const char* key = "";
|
||||
const char* value = "";
|
||||
if (node->getAttributeByIndex(i, &key, &value))
|
||||
{
|
||||
if (string(key) == "path")
|
||||
{
|
||||
path = value;
|
||||
}
|
||||
else if (string(key) == "tags")
|
||||
{
|
||||
tags = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unexpected font tag attribute
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tags.Trim();
|
||||
if (tags.empty())
|
||||
{
|
||||
xmlData.m_fontTagsXml.back().m_fontFilename = path;
|
||||
}
|
||||
else if (tags == "b")
|
||||
{
|
||||
xmlData.m_fontTagsXml.back().m_boldFontFilename = path;
|
||||
}
|
||||
else if (tags == "i")
|
||||
{
|
||||
xmlData.m_fontTagsXml.back().m_italicFontFilename = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We'll just assume any other tag indicates bold italic
|
||||
xmlData.m_fontTagsXml.back().m_boldItalicFontFilename = path;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, count = node->getChildCount(); i < count; ++i)
|
||||
{
|
||||
XmlNodeRef child = node->getChild(i);
|
||||
if (!ParseFontFamilyXml(child, xmlData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//! Only attempt XML file load if file exists.
|
||||
//! There are use-cases where the XML path is not fully known (such as
|
||||
//! when referencing font family names from font family XML files), and
|
||||
//! attempting to load the XML files directly via ISystem() methods can
|
||||
//! produce a lot of warning noise.
|
||||
XmlNodeRef SafeLoadXmlFromFile(const string& xmlPath)
|
||||
{
|
||||
if (gEnv->pCryPak->IsFileExist(xmlPath.c_str()))
|
||||
{
|
||||
return GetISystem()->LoadXmlFromFile(xmlPath.c_str());
|
||||
}
|
||||
|
||||
return XmlNodeRef();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CCryFont::CCryFont(ISystem* pSystem)
|
||||
: m_pSystem(pSystem)
|
||||
, m_fonts()
|
||||
, m_rndPropIsRGBA(false)
|
||||
, m_rndPropHalfTexelOffset(0.5f)
|
||||
{
|
||||
assert(m_pSystem);
|
||||
|
||||
CryLogAlways("Using FreeType %d.%d.%d", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH);
|
||||
|
||||
// Persist fonts for application lifetime to prevent unnecessary work
|
||||
REGISTER_CVAR(r_persistFontFamilies, r_persistFontFamilies, VF_NULL, "Persist loaded font families for lifetime of application.");
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
REGISTER_COMMAND("r_DumpFontTexture", DumpFontTexture, 0,
|
||||
"Dumps the specified font's texture to a bitmap file\n"
|
||||
"Use r_DumpFontTexture to get the loaded font names\n"
|
||||
"Usage: r_DumpFontTexture <fontname>");
|
||||
REGISTER_COMMAND("r_DumpFontNames", DumpFontNames, 0,
|
||||
"Logs a list of fonts currently loaded");
|
||||
REGISTER_COMMAND("r_ReloadFonts", ReloadFonts, VF_NULL,
|
||||
"Reload all fonts");
|
||||
#endif
|
||||
}
|
||||
|
||||
CCryFont::~CCryFont()
|
||||
{
|
||||
// Persist fonts for application lifetime to prevent unnecessary work
|
||||
m_persistedFontFamilies.clear();
|
||||
|
||||
for (FontMapItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; )
|
||||
{
|
||||
CFFont* pFont = it->second;
|
||||
++it; // iterate as Release() below will remove font from the map
|
||||
SAFE_RELEASE(pFont);
|
||||
}
|
||||
}
|
||||
|
||||
void CCryFont::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
IFFont* CCryFont::NewFont(const char* pFontName)
|
||||
{
|
||||
string name = pFontName;
|
||||
name.MakeLower();
|
||||
|
||||
FontMapItor it = m_fonts.find(CONST_TEMP_STRING(name.c_str()));
|
||||
if (it != m_fonts.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
CFFont* pFont = new CFFont(m_pSystem, this, name.c_str());
|
||||
m_fonts.insert(FontMapItor::value_type(name, pFont));
|
||||
return pFont;
|
||||
}
|
||||
|
||||
IFFont* CCryFont::GetFont(const char* pFontName) const
|
||||
{
|
||||
FontMapConstItor it = m_fonts.find(CONST_TEMP_STRING(string(pFontName).MakeLower()));
|
||||
return it != m_fonts.end() ? it->second : 0;
|
||||
}
|
||||
|
||||
FontFamilyPtr CCryFont::LoadFontFamily(const char* pFontFamilyName)
|
||||
{
|
||||
FontFamilyPtr fontFamily(nullptr);
|
||||
string fontFamilyPath;
|
||||
string fontFamilyFullPath;
|
||||
|
||||
XmlNodeRef root = LoadFontFamilyXml(pFontFamilyName, fontFamilyPath, fontFamilyFullPath);
|
||||
|
||||
if (root)
|
||||
{
|
||||
FontFamilyTagXml xmlData;
|
||||
const bool parseSuccess = ParseFontFamilyXml(root, xmlData);
|
||||
if (parseSuccess && xmlData.IsValid())
|
||||
{
|
||||
const char* currentLanguage = gEnv->pSystem->GetLocalizationManager()->GetLanguage();
|
||||
FontTagXml* defaultFont = nullptr;
|
||||
FontTagXml* langSpecificFont = nullptr;
|
||||
|
||||
// Note that we don't break out of this for-loop early because we
|
||||
// want to find both the default font family and the
|
||||
// language-specific font family. We prefer the lang-specific
|
||||
// family but will fall back on the default if it doesn't exist.
|
||||
for (FontTagXml& fontTagXml : xmlData.m_fontTagsXml)
|
||||
{
|
||||
if (fontTagXml.m_lang.empty())
|
||||
{
|
||||
defaultFont = &fontTagXml;
|
||||
}
|
||||
else
|
||||
{
|
||||
int searchPos = 0;
|
||||
string langToken;
|
||||
|
||||
// "lang" font-tag attribute could be comma-separated
|
||||
while (!(langToken = fontTagXml.m_lang.Tokenize(",", searchPos)).empty())
|
||||
{
|
||||
if (langToken.Trim() == currentLanguage)
|
||||
{
|
||||
langSpecificFont = &fontTagXml;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (langSpecificFont || defaultFont)
|
||||
{
|
||||
// Prefer lang-specific font-family over default, if it exists
|
||||
FontTagXml* fontTagXml = langSpecificFont ? langSpecificFont : defaultFont;
|
||||
|
||||
// Pre-pend font family's path to make font family XML paths
|
||||
// relative to font family file
|
||||
fontTagXml->m_fontFilename = fontFamilyPath + fontTagXml->m_fontFilename;
|
||||
fontTagXml->m_boldFontFilename = fontFamilyPath + fontTagXml->m_boldFontFilename;
|
||||
fontTagXml->m_italicFontFilename = fontFamilyPath + fontTagXml->m_italicFontFilename;
|
||||
fontTagXml->m_boldItalicFontFilename = fontFamilyPath + fontTagXml->m_boldItalicFontFilename;
|
||||
|
||||
IFFont* normal = LoadFont(fontTagXml->m_fontFilename.c_str());
|
||||
IFFont* bold = LoadFont(fontTagXml->m_boldFontFilename.c_str());
|
||||
IFFont* italic = LoadFont(fontTagXml->m_italicFontFilename.c_str());
|
||||
IFFont* boldItalic = LoadFont(fontTagXml->m_boldItalicFontFilename.c_str());
|
||||
|
||||
// Only continue if all fonts were created successfully
|
||||
if (normal && bold && italic && boldItalic)
|
||||
{
|
||||
fontFamily.reset(new FontFamily(),
|
||||
[this](FontFamily* pFontFamily)
|
||||
{
|
||||
ReleaseFontFamily(pFontFamily);
|
||||
});
|
||||
|
||||
// Map the font family name both by path and by name defined
|
||||
// within the Font Family XML itself. This allows font
|
||||
// families to also be referenced simply by name.
|
||||
if (!AddFontFamilyToMaps(fontFamilyFullPath, xmlData.m_fontFamilyName, fontFamily))
|
||||
{
|
||||
SAFE_RELEASE(normal);
|
||||
SAFE_RELEASE(bold);
|
||||
SAFE_RELEASE(italic);
|
||||
SAFE_RELEASE(boldItalic);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
fontFamily->familyName = xmlData.m_fontFamilyName;
|
||||
fontFamily->normal = normal;
|
||||
fontFamily->bold = bold;
|
||||
fontFamily->italic = italic;
|
||||
fontFamily->boldItalic = boldItalic;
|
||||
}
|
||||
else
|
||||
{
|
||||
SAFE_RELEASE(normal);
|
||||
SAFE_RELEASE(bold);
|
||||
SAFE_RELEASE(italic);
|
||||
SAFE_RELEASE(boldItalic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fontFamily)
|
||||
{
|
||||
// Unable to load font family XML, so load font normally and associate
|
||||
// it with a font family
|
||||
IFFont* pFont = LoadFont(pFontFamilyName);
|
||||
|
||||
if (pFont)
|
||||
{
|
||||
// Create a font family from a single font by assigning all the
|
||||
// font family stylings to the same font
|
||||
fontFamily.reset(new FontFamily(),
|
||||
[this](FontFamily* pFontFamily)
|
||||
{
|
||||
ReleaseFontFamily(pFontFamily);
|
||||
});
|
||||
|
||||
// Use filepath as familyName so font loading/unloading doesn't break with duplicate file names
|
||||
fontFamily->familyName = pFontFamilyName;
|
||||
|
||||
if (!AddFontFamilyToMaps(pFontFamilyName, fontFamily->familyName, fontFamily))
|
||||
{
|
||||
SAFE_RELEASE(pFont);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Assign all stylings to the same font
|
||||
fontFamily->normal = pFont;
|
||||
fontFamily->bold = pFont;
|
||||
fontFamily->italic = pFont;
|
||||
fontFamily->boldItalic = pFont;
|
||||
|
||||
// The other three stylings need to have their ref count
|
||||
// incremented (even though in this particular case its all the
|
||||
// same font) because when ReleaseFontFamily executes all fonts
|
||||
// in the family will be (corresondingly) Release'd.
|
||||
fontFamily->bold->AddRef();
|
||||
fontFamily->italic->AddRef();
|
||||
fontFamily->boldItalic->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
// Persist fonts for application lifetime to prevent unnecessary work
|
||||
if (r_persistFontFamilies > 0)
|
||||
{
|
||||
m_persistedFontFamilies.emplace_back(FontFamilyPtr(fontFamily));
|
||||
}
|
||||
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
FontFamilyPtr CCryFont::GetFontFamily(const char* pFontFamilyName)
|
||||
{
|
||||
FontFamilyPtr fontFamily = nullptr;
|
||||
|
||||
// The given string could either be: a font family name (defined in font
|
||||
// family XML), a file path (for regular fonts mapped as font families),
|
||||
// or just the filename of a font itself. Fonts are mapped by font family
|
||||
// name or by filepath, so attempt lookup using the map first since it's
|
||||
// the fastest.
|
||||
string loweredName = string(pFontFamilyName).Trim().MakeLower();
|
||||
auto it = m_fontFamilies.find(PathUtil::MakeGamePath(loweredName).c_str());
|
||||
if (it != m_fontFamilies.end())
|
||||
{
|
||||
fontFamily = FontFamilyPtr(it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Iterate through all fonts, returning the first match where simply
|
||||
// the filename of a font could be a match. This case will likely be
|
||||
// hit when text markup references a font that doesn't belong to a
|
||||
// font family.
|
||||
for (const auto& fontFamilyIter : m_fontFamilies)
|
||||
{
|
||||
const AZStd::string& mappedFontFamilyName = fontFamilyIter.first;
|
||||
string mappedFilenameNoExtension = PathUtil::GetFileName(mappedFontFamilyName.c_str());
|
||||
|
||||
string searchStringFilenameNoExtension = PathUtil::GetFileName(loweredName);
|
||||
|
||||
if (mappedFilenameNoExtension == searchStringFilenameNoExtension)
|
||||
{
|
||||
fontFamily = FontFamilyPtr(fontFamilyIter.second);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fontFamily;
|
||||
}
|
||||
|
||||
void CCryFont::AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX, int glyphSizeY)
|
||||
{
|
||||
pFontFamily->normal->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY);
|
||||
pFontFamily->bold->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY);
|
||||
pFontFamily->italic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY);
|
||||
pFontFamily->boldItalic->AddCharsToFontTexture(pChars, glyphSizeX, glyphSizeY);
|
||||
}
|
||||
|
||||
void CCryFont::SetRendererProperties(IRenderer* pRenderer)
|
||||
{
|
||||
if (pRenderer)
|
||||
{
|
||||
m_rndPropIsRGBA = (pRenderer->GetFeatures() & RFT_RGBA) != 0;
|
||||
m_rndPropHalfTexelOffset = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void CCryFont::GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
if (!pSizer->Add(*this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pSizer->AddObject(m_fonts);
|
||||
}
|
||||
|
||||
string CCryFont::GetLoadedFontNames() const
|
||||
{
|
||||
string ret;
|
||||
for (FontMapConstItor it = m_fonts.begin(), itEnd = m_fonts.end(); it != itEnd; ++it)
|
||||
{
|
||||
CFFont* pFont = it->second;
|
||||
if (pFont)
|
||||
{
|
||||
if (!ret.empty())
|
||||
{
|
||||
ret += ",";
|
||||
}
|
||||
ret += pFont->GetName();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CCryFont::OnLanguageChanged()
|
||||
{
|
||||
ReloadAllFonts();
|
||||
|
||||
EBUS_EVENT(LanguageChangeNotificationBus, LanguageChanged);
|
||||
}
|
||||
|
||||
void CCryFont::ReloadAllFonts()
|
||||
{
|
||||
// Persist fonts for application lifetime to prevent unnecessary work
|
||||
m_persistedFontFamilies.clear();
|
||||
|
||||
AZStd::list<AZStd::string> fontFamilyFilenames;
|
||||
AZStd::list<FontFamily*> fontFamilyWeakPtrs;
|
||||
|
||||
// Iterate through all currently loaded font families
|
||||
for (auto it : m_fontFamilyReverseLookup)
|
||||
{
|
||||
fontFamilyWeakPtrs.push_back(it.first);
|
||||
fontFamilyFilenames.push_back(it.second->first);
|
||||
}
|
||||
|
||||
// Release font-family resources and unmap them
|
||||
for (auto fontFamily : fontFamilyWeakPtrs)
|
||||
{
|
||||
ReleaseFontFamily(fontFamily);
|
||||
}
|
||||
|
||||
// Reload the font families
|
||||
for (auto familyFilename : fontFamilyFilenames)
|
||||
{
|
||||
LoadFontFamily(familyFilename.c_str());
|
||||
}
|
||||
|
||||
// All UI text components need to reload their font assets (both in-game
|
||||
// and in-editor).
|
||||
EBUS_EVENT(FontNotificationBus, OnFontsReloaded);
|
||||
}
|
||||
|
||||
void CCryFont::UnregisterFont(const char* pFontName)
|
||||
{
|
||||
FontMapItor it = m_fonts.find(CONST_TEMP_STRING(pFontName));
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
IFFont* fontPtr = it->second;
|
||||
#endif
|
||||
|
||||
if (it != m_fonts.end())
|
||||
{
|
||||
m_fonts.erase(it);
|
||||
}
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
// Make sure the font being released isn't currently in use by a font family.
|
||||
// If it is, the FontFamily will have a dangling pointer and will cause a
|
||||
// crash when the FontFamily eventually gets released.
|
||||
for (auto reverseMapEntry : m_fontFamilyReverseLookup)
|
||||
{
|
||||
FontFamily* fontFamily = reverseMapEntry.first;
|
||||
AZ_Assert(fontFamily->normal != fontPtr,
|
||||
"The following font is being freed but still in use by a FontFamily: %s",
|
||||
pFontName);
|
||||
AZ_Assert(fontFamily->italic != fontPtr,
|
||||
"The following font is being freed but still in use by a FontFamily: %s",
|
||||
pFontName);
|
||||
AZ_Assert(fontFamily->bold != fontPtr,
|
||||
"The following font is being freed but still in use by a FontFamily: %s",
|
||||
pFontName);
|
||||
AZ_Assert(fontFamily->boldItalic != fontPtr,
|
||||
"The following font is being freed but still in use by a FontFamily: %s",
|
||||
pFontName);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IFFont* CCryFont::LoadFont(const char* pFontName)
|
||||
{
|
||||
string fontName = pFontName;
|
||||
fontName.MakeLower();
|
||||
|
||||
IFFont* font = GetFont(fontName);
|
||||
if (font)
|
||||
{
|
||||
font->AddRef(); // use existing loaded font
|
||||
}
|
||||
else
|
||||
{
|
||||
// attempt to create and load a new font, use the font pathname as the font name
|
||||
font = NewFont(fontName);
|
||||
if (!font)
|
||||
{
|
||||
string errorMsg = "Error creating a new font named ";
|
||||
errorMsg += fontName;
|
||||
errorMsg += ".";
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// creating font adds one to its refcount so no need for AddRef here
|
||||
if (!font->Load(fontName))
|
||||
{
|
||||
string errorMsg = "Error loading a font from ";
|
||||
errorMsg += fontName;
|
||||
errorMsg += ".";
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_ERROR, errorMsg);
|
||||
font->Release();
|
||||
font = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
void CCryFont::ReleaseFontFamily(FontFamily* pFontFamily)
|
||||
{
|
||||
// Ensure that Font Family was mapped prior to destruction
|
||||
const bool isMapped = m_fontFamilyReverseLookup.find(pFontFamily) != m_fontFamilyReverseLookup.end();
|
||||
if (!isMapped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that the FontFamily is mapped both by filename and by "family name"
|
||||
auto it = m_fontFamilyReverseLookup[pFontFamily];
|
||||
m_fontFamilies.erase(it);
|
||||
string familyName(pFontFamily->familyName);
|
||||
m_fontFamilies.erase(familyName.MakeLower().c_str());
|
||||
|
||||
// Reverse lookup is used to avoid needing to store filename path with
|
||||
// the font family, so we need to remove that entry also.
|
||||
m_fontFamilyReverseLookup.erase(pFontFamily);
|
||||
|
||||
SAFE_RELEASE(pFontFamily->normal);
|
||||
SAFE_RELEASE(pFontFamily->bold);
|
||||
SAFE_RELEASE(pFontFamily->italic);
|
||||
SAFE_RELEASE(pFontFamily->boldItalic);
|
||||
}
|
||||
|
||||
bool CCryFont::AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily)
|
||||
{
|
||||
if (!pFontFamilyFilename || !pFontFamilyName || !fontFamily.get())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We don't support "updating" mapped values.
|
||||
AZStd::string loweredFilename(PathUtil::MakeGamePath(string(pFontFamilyFilename)).c_str());
|
||||
AZStd::to_lower<AZStd::string::iterator>(loweredFilename.begin(), loweredFilename.end());
|
||||
if (m_fontFamilies.find(loweredFilename) != m_fontFamilies.end())
|
||||
{
|
||||
string warnMsg;
|
||||
warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyFilename);
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Similarly, we don't support Font Family XMLs that have the same font
|
||||
// family name (we assume all Font Family names are unique).
|
||||
AZStd::string loweredFontFamilyName(pFontFamilyName);
|
||||
AZStd::to_lower<AZStd::string::iterator>(loweredFontFamilyName.begin(), loweredFontFamilyName.end());
|
||||
if (m_fontFamilies.find(loweredFontFamilyName) != m_fontFamilies.end())
|
||||
{
|
||||
string warnMsg;
|
||||
warnMsg.Format("Couldn't load Font Family '%s': already loaded", pFontFamilyName);
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, insert by filename
|
||||
AZStd::pair<AZStd::string, AZStd::weak_ptr<FontFamily>> insertPair(loweredFilename, fontFamily);
|
||||
auto iterPosition = m_fontFamilies.insert(insertPair).first;
|
||||
m_fontFamilyReverseLookup[fontFamily.get()] = iterPosition;
|
||||
|
||||
// Then, by Font Family name
|
||||
AZStd::pair<AZStd::string, AZStd::weak_ptr<FontFamily>> nameInsertPair(loweredFontFamilyName, fontFamily);
|
||||
m_fontFamilies.insert(nameInsertPair);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XmlNodeRef CCryFont::LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath)
|
||||
{
|
||||
outputFullPath = pFontFamilyName;
|
||||
outputDirectory = PathUtil::GetPath(pFontFamilyName);
|
||||
XmlNodeRef root = SafeLoadXmlFromFile(outputFullPath);
|
||||
|
||||
// When parsing a <font> tag in markup, only the font name is given and
|
||||
// not a path, so we try to build a "best guess" path from the name.
|
||||
if (!root)
|
||||
{
|
||||
string fileNoExtension(PathUtil::GetFileName(pFontFamilyName));
|
||||
string fileExtension(PathUtil::GetExt(pFontFamilyName));
|
||||
|
||||
if (fileExtension.empty())
|
||||
{
|
||||
fileExtension = ".fontfamily";
|
||||
}
|
||||
|
||||
// Try: "fonts/fontName.fontfamily"
|
||||
outputDirectory = string("fonts/");
|
||||
outputFullPath = outputDirectory + fileNoExtension + fileExtension;
|
||||
root = SafeLoadXmlFromFile(outputFullPath);
|
||||
|
||||
// Finally, try: "fonts/fontName/fontName.fontfamily"
|
||||
if (!root)
|
||||
{
|
||||
outputDirectory = string("fonts/") + fileNoExtension + "/";
|
||||
outputFullPath = outputDirectory + fileNoExtension + fileExtension;
|
||||
root = SafeLoadXmlFromFile(outputFullPath);
|
||||
}
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
EXPORTS
|
||||
ModuleInitISystem @2
|
||||
CryModuleGetMemoryInfo @8
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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_CRYFONT_CRYFONT_H
|
||||
#define CRYINCLUDE_CRYFONT_CRYFONT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include <IXml.h>
|
||||
#include <AzCore/std/containers/map.h>
|
||||
#include <AzCore/std/smart_ptr/weak_ptr.h>
|
||||
#include <map>
|
||||
|
||||
class CFFont;
|
||||
|
||||
|
||||
class CCryFont
|
||||
: public ICryFont
|
||||
{
|
||||
friend class CFFont;
|
||||
|
||||
public:
|
||||
|
||||
static const Vec2i defaultGlyphSize; //!< Default glyph size indicates that glyphs in the font texture
|
||||
//!< should be rendered at the maximum resolution supported by
|
||||
//!< the font texture's glyph cell/slot configuration (configured
|
||||
//!< via font XML).
|
||||
|
||||
public:
|
||||
CCryFont(ISystem* pSystem);
|
||||
virtual ~CCryFont();
|
||||
|
||||
virtual void Release();
|
||||
virtual IFFont* NewFont(const char* pFontName);
|
||||
virtual IFFont* GetFont(const char* pFontName) const;
|
||||
virtual FontFamilyPtr LoadFontFamily(const char* pFontFamilyName) override;
|
||||
virtual FontFamilyPtr GetFontFamily(const char* pFontFamilyName) override;
|
||||
virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override;
|
||||
virtual void SetRendererProperties(IRenderer* pRenderer);
|
||||
virtual void GetMemoryUsage(ICrySizer* pSizer) const;
|
||||
virtual string GetLoadedFontNames() const;
|
||||
virtual void OnLanguageChanged() override;
|
||||
virtual void ReloadAllFonts() override;
|
||||
|
||||
public:
|
||||
void UnregisterFont(const char* pFontName);
|
||||
bool RndPropIsRGBA() const { return m_rndPropIsRGBA; }
|
||||
float RndPropHalfTexelOffset() const { return m_rndPropHalfTexelOffset; }
|
||||
|
||||
private:
|
||||
typedef std::map<string, CFFont*> FontMap;
|
||||
typedef FontMap::iterator FontMapItor;
|
||||
typedef FontMap::const_iterator FontMapConstItor;
|
||||
|
||||
typedef AZStd::map<AZStd::string, AZStd::weak_ptr<FontFamily>> FontFamilyMap;
|
||||
typedef AZStd::map<FontFamily*, FontFamilyMap::iterator> FontFamilyReverseLookupMap;
|
||||
|
||||
private:
|
||||
//! Convenience method for loading fonts
|
||||
IFFont* LoadFont(const char* fontName);
|
||||
|
||||
//! Called when final FontFamily shared_ptr is destroyed; do not call directly.
|
||||
void ReleaseFontFamily(FontFamily* pFontFamily);
|
||||
|
||||
//! Adds new entries into both font family maps for the given font family
|
||||
//!
|
||||
//! Note that it's not possible to update Font Family mappings with this
|
||||
//! method. The only way to do that would be to release the font family
|
||||
//! and re-load it with the new values.
|
||||
//!
|
||||
//! \return True only if the Font Family was added to the maps, false for all other cases (such as
|
||||
//! when the font family is already mapped).
|
||||
bool AddFontFamilyToMaps(const char* pFontFamilyFilename, const char* pFontFamilyName, FontFamilyPtr fontFamily);
|
||||
|
||||
//! Internal method that (possibly) makes several attempts at locating and loading a given font family XML.
|
||||
//! \param pFontFamilyName The name of the font family, or path to a font family file.
|
||||
//! \param outputDirectory Path to loaded font family (no filename), may need resolving with PathUtil::MakeGamePath.
|
||||
//! \param outputFullPath Full path to loaded font family, may need resolving with PathUtil::MakeGamePath.
|
||||
XmlNodeRef LoadFontFamilyXml(const char* pFontFamilyName, string& outputDirectory, string& outputFullPath);
|
||||
|
||||
private:
|
||||
FontMap m_fonts;
|
||||
FontFamilyMap m_fontFamilies; //!< Map font family names to weak ptrs so we can construct shared_ptrs but not keep a ref ourselves.
|
||||
FontFamilyReverseLookupMap m_fontFamilyReverseLookup; //<! FontFamily pointer reverse-lookup for quick removal
|
||||
ISystem* m_pSystem;
|
||||
bool m_rndPropIsRGBA;
|
||||
float m_rndPropHalfTexelOffset;
|
||||
|
||||
int r_persistFontFamilies = 1; //!< Persist fonts for application lifetime to prevent unnecessary work; enabled by default.
|
||||
AZStd::vector<FontFamilyPtr> m_persistedFontFamilies; //!< Stores persisted fonts (if "persist font families" is enabled)
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_CRYFONT_H
|
||||
@@ -1,111 +0,0 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Russian resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
|
||||
#pragma code_page(1251)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // Russian resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// German (Germany) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_DEU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,1
|
||||
PRODUCTVERSION 1,0,0,1
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x2L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "Amazon.com, Inc."
|
||||
VALUE "FileVersion", "1, 0, 0, 1"
|
||||
VALUE "LegalCopyright", "Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates."
|
||||
VALUE "ProductName", "Lumberyard"
|
||||
VALUE "ProductVersion", "1, 0, 0, 1"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x9, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // German (Germany) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define CRYFONT_EXPORTS
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include <IFont.h>
|
||||
|
||||
#include <ILog.h>
|
||||
#include <IConsole.h>
|
||||
#include <IRenderer.h>
|
||||
#include <CrySizer.h>
|
||||
|
||||
#define USE_NULLFONT
|
||||
|
||||
#if defined(DEDICATED_SERVER)
|
||||
#define USE_NULLFONT_ALWAYS 1
|
||||
#endif
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#pragma once
|
||||
#ifndef CRYINCLUDE_CRYFONT_FBITMAP_H
|
||||
#define CRYINCLUDE_CRYFONT_FBITMAP_H
|
||||
|
||||
|
||||
class CFBitmap
|
||||
{
|
||||
public:
|
||||
CFBitmap();
|
||||
~CFBitmap();
|
||||
|
||||
int Blur(int iIterations);
|
||||
int Scale(float fScaleX, float fScaleY);
|
||||
|
||||
int BlitFrom(CFBitmap* pSrc, int iSX, int iSY, int iDX, int iDY, int iW, int iH);
|
||||
int BlitTo(CFBitmap* pDst, int iDX, int iDY, int iSX, int iSY, int iW, int iH);
|
||||
|
||||
int Create(int iWidth, int iHeight);
|
||||
int Release();
|
||||
|
||||
int SaveBitmap(const string& szFileName);
|
||||
int Get32Bpp(unsigned int** pBuffer)
|
||||
{
|
||||
(*pBuffer) = new unsigned int[m_iWidth * m_iHeight];
|
||||
|
||||
if (!(*pBuffer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iDataSize = m_iWidth * m_iHeight;
|
||||
|
||||
for (int i = 0; i < iDataSize; i++)
|
||||
{
|
||||
(*pBuffer)[i] = (m_pData[i] << 24) | (m_pData[i] << 16) | (m_pData[i] << 8) | (m_pData[i]);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GetWidth() { return m_iWidth; }
|
||||
int GetHeight() { return m_iHeight; }
|
||||
|
||||
void SetRenderData(void* pRenderData) { m_pIRenderData = pRenderData; };
|
||||
void* GetRenderData() { return m_pIRenderData; };
|
||||
|
||||
void GetMemoryUsage (class ICrySizer* pSizer);
|
||||
|
||||
unsigned char* GetData() { return m_pData; }
|
||||
|
||||
public:
|
||||
|
||||
int m_iWidth;
|
||||
int m_iHeight;
|
||||
|
||||
unsigned char* m_pData;
|
||||
void* m_pIRenderData;
|
||||
};
|
||||
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_FBITMAP_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Font class.
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYFONT_FFONT_H
|
||||
#define CRYINCLUDE_CRYFONT_FFONT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include <vector>
|
||||
#include <Cry_Math.h>
|
||||
#include <Cry_Color.h>
|
||||
#include <CryString.h>
|
||||
#include "CryFont.h"
|
||||
|
||||
#include <AzCore/std/parallel/mutex.h>
|
||||
|
||||
struct ISystem;
|
||||
class CFontTexture;
|
||||
|
||||
|
||||
class CFFont
|
||||
: public IFFont
|
||||
, public IFFont_RenderProxy
|
||||
{
|
||||
public:
|
||||
//! Determines how characters of different sizes should be handled during render.
|
||||
enum class SizeBehavior
|
||||
{
|
||||
Scale, //!< Default behavior; glyphs rendered at different sizes are rendered on scaled geometry
|
||||
Rerender //!< Similar to Scale, but the glyph in the font texture is re-rendered to match the target
|
||||
//!< size, as long as the size isn't greater than the maximum glyph/slot resolution as
|
||||
//!< configured for the font texture in the font XML.
|
||||
};
|
||||
|
||||
//! The hinting visual algorithm to be used (when hinting is enabled)
|
||||
enum class HintStyle
|
||||
{
|
||||
Normal, //!< Default hinting behavior provided by font renderer
|
||||
Light //!< Produces fuzzier glyphs but more accurately tracks glyph shape
|
||||
};
|
||||
|
||||
//! Chooses whether hinting info should be obtained from the font, turned off entirely, or automatically generated
|
||||
enum class HintBehavior
|
||||
{
|
||||
Default, //!< Obtain hinting data from font itself
|
||||
AutoHint, //!< Procedurally derive hinting information from glyph
|
||||
NoHinting, //!< Disable hinting entirely
|
||||
};
|
||||
|
||||
//! Simple struct used to communicate font hinting parameters to font renderer.
|
||||
struct FontHintParams
|
||||
{
|
||||
FontHintParams() : hintStyle(HintStyle::Normal), hintBehavior(HintBehavior::Default) { }
|
||||
|
||||
HintStyle hintStyle;
|
||||
HintBehavior hintBehavior;
|
||||
};
|
||||
|
||||
struct SRenderingPass
|
||||
{
|
||||
ColorB m_color;
|
||||
Vec2 m_posOffset;
|
||||
int m_blendSrc;
|
||||
int m_blendDest;
|
||||
|
||||
SRenderingPass()
|
||||
: m_color(255, 255, 255, 255)
|
||||
, m_posOffset(0, 0)
|
||||
, m_blendSrc(GS_BLSRC_SRCALPHA)
|
||||
, m_blendDest(GS_BLDST_ONEMINUSSRCALPHA)
|
||||
{
|
||||
}
|
||||
|
||||
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
||||
};
|
||||
|
||||
struct SEffect
|
||||
{
|
||||
string m_name;
|
||||
std::vector<SRenderingPass> m_passes;
|
||||
|
||||
SEffect(const char* name)
|
||||
: m_name(name)
|
||||
{
|
||||
assert(name);
|
||||
}
|
||||
|
||||
SRenderingPass* AddPass()
|
||||
{
|
||||
m_passes.push_back(SRenderingPass());
|
||||
return &m_passes[m_passes.size() - 1];
|
||||
}
|
||||
|
||||
void ClearPasses()
|
||||
{
|
||||
m_passes.resize(0);
|
||||
}
|
||||
|
||||
void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
pSizer->AddObject(m_name);
|
||||
pSizer->AddObject(m_passes);
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<SEffect> Effects;
|
||||
typedef Effects::iterator EffectsIt;
|
||||
|
||||
public:
|
||||
virtual int32 AddRef() override;
|
||||
virtual int32 Release() override;
|
||||
virtual bool Load(const char* pFontFilePath, unsigned int width, unsigned int height, unsigned int widthNumSlots, unsigned int heightNumSlots, unsigned int flags, float sizeRatio);
|
||||
virtual bool Load(const char* pXMLFile);
|
||||
virtual void Free();
|
||||
virtual void DrawString(float x, float y, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
virtual void DrawString(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
virtual Vec2 GetTextSize(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
virtual size_t GetTextLength(const char* pStr, const bool asciiMultiLine) const;
|
||||
virtual void WrapText(string& result, float maxWidth, const char* pStr, const STextDrawContext& ctx);
|
||||
virtual void GetMemoryUsage(ICrySizer* pSizer) const;
|
||||
virtual void GetGradientTextureCoord(float& minU, float& minV, float& maxU, float& maxV) const;
|
||||
virtual unsigned int GetEffectId(const char* pEffectName) const;
|
||||
virtual unsigned int GetNumEffects() const;
|
||||
virtual const char* GetEffectName(unsigned int effectId) const;
|
||||
virtual Vec2 GetMaxEffectOffset(unsigned int effectId) const;
|
||||
virtual bool DoesEffectHaveTransparency(unsigned int effectId) const;
|
||||
virtual void AddCharsToFontTexture(const char* pChars, int glyphSizeX = ICryFont::defaultGlyphSizeX, int glyphSizeY = ICryFont::defaultGlyphSizeY) override;
|
||||
virtual Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph, const STextDrawContext& ctx) const override;
|
||||
virtual float GetAscender(const STextDrawContext& ctx) const override;
|
||||
virtual float GetBaseline(const STextDrawContext& ctx) const override;
|
||||
|
||||
virtual uint32 GetNumQuadsForText(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
virtual uint32 WriteTextQuadsToBuffers(SVF_P2F_C4B_T2F_F4B* verts, uint16* indices, uint32 maxQuads, float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
virtual int GetFontTextureId();
|
||||
virtual uint32 GetFontTextureVersion();
|
||||
|
||||
virtual float GetSizeRatio() const override { return m_sizeRatio; }
|
||||
|
||||
public:
|
||||
virtual void RenderCallback(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
|
||||
public:
|
||||
CFFont(ISystem* pSystem, CCryFont* pCryFont, const char* pFontName);
|
||||
|
||||
bool InitTexture();
|
||||
bool InitCache();
|
||||
|
||||
CFontTexture* GetFontTexture() const { return m_pFontTexture; }
|
||||
const string& GetName() const { return m_name; }
|
||||
|
||||
SEffect* AddEffect(const char* pEffectName);
|
||||
SEffect* GetDefaultEffect();
|
||||
|
||||
private:
|
||||
virtual ~CFFont();
|
||||
|
||||
void Prepare(const char* pStr, bool updateTexture, const Vec2i& glyphSize = CCryFont::defaultGlyphSize);
|
||||
void DrawStringUInternal(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
Vec2 GetTextSizeUInternal(const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx);
|
||||
|
||||
using AddFunction = AZStd::function<void(const Vec3&, const Vec3&, const Vec3&, const Vec3&, const Vec2&, const Vec2&, const Vec2&, const Vec2&, uint32)>;
|
||||
using BeginPassFunction = AZStd::function<void(const SRenderingPass* pPass)>;
|
||||
|
||||
//! This function is used by both RenderCallback and WriteTextQuadsToBuffers
|
||||
//! To do this is takes two function pointers that implement the appropriate AddQuad and BeginPass behavior
|
||||
void CreateQuadsForText(float x, float y, float z, const char* pStr, const bool asciiMultiLine, const STextDrawContext& ctx,
|
||||
AddFunction AddQuad, BeginPassFunction BeginPass);
|
||||
|
||||
struct TextScaleInfoInternal
|
||||
{
|
||||
TextScaleInfoInternal(const Vec2& _scale, float _rcpCellWidth)
|
||||
: scale(_scale), rcpCellWidth(_rcpCellWidth) { }
|
||||
|
||||
Vec2 scale;
|
||||
float rcpCellWidth;
|
||||
};
|
||||
|
||||
TextScaleInfoInternal CalculateScaleInternal(const STextDrawContext& ctx) const;
|
||||
|
||||
Vec2 GetRestoredFontSize(const STextDrawContext& ctx) const;
|
||||
|
||||
private:
|
||||
string m_name;
|
||||
string m_curPath;
|
||||
|
||||
CFontTexture* m_pFontTexture;
|
||||
|
||||
size_t m_fontBufferSize;
|
||||
unsigned char* m_pFontBuffer;
|
||||
|
||||
int m_texID;
|
||||
uint32 m_textureVersion;
|
||||
|
||||
ISystem* m_pSystem;
|
||||
|
||||
AZStd::recursive_mutex m_fontMutex; //!< Controls access between main and render threads. It's common for one thread
|
||||
//!< to add un-cached glyphs to the font texture while another is accessing the
|
||||
//!< font texture.
|
||||
|
||||
CCryFont* m_pCryFont;
|
||||
|
||||
bool m_fontTexDirty;
|
||||
|
||||
Effects m_effects;
|
||||
|
||||
SVF_P3F_C4B_T2F* m_pDrawVB;
|
||||
|
||||
volatile int32 m_nRefCount;
|
||||
|
||||
bool m_monospacedFont; //!< True if this font is fixed/monospaced, false otherwise (obtained from FreeType)
|
||||
|
||||
float m_sizeRatio = IFFontConstants::defaultSizeRatio;
|
||||
SizeBehavior m_sizeBehavior = SizeBehavior::Scale; //!< Changes how glyphs rendered at different sizes are rendered.
|
||||
FontHintParams m_fontHintParams; //!< How the font should be hinted when its loaded and rendered to the font texture
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_FFONT_H
|
||||
@@ -1,448 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : XML parsing to load a font.
|
||||
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "FFont.h"
|
||||
#include "FontTexture.h"
|
||||
#include <Cry_Math.h>
|
||||
#include <CryPath.h>
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
# include <shlobj.h>
|
||||
# include <StringUtils.h>
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Xml parser implementation
|
||||
|
||||
enum
|
||||
{
|
||||
|
||||
ELEMENT_UNKNOWN = 0,
|
||||
ELEMENT_FONT = 1,
|
||||
ELEMENT_EFFECT = 2,
|
||||
ELEMENT_EFFECTFILE = 3,
|
||||
ELEMENT_PASS = 4,
|
||||
ELEMENT_PASS_COLOR = 5,
|
||||
ELEMENT_PASS_POSOFFSET = 12,
|
||||
ELEMENT_PASS_BLEND = 14
|
||||
};
|
||||
|
||||
static inline int GetBlendModeFromString(const string& str, bool dst)
|
||||
{
|
||||
int blend = GS_BLSRC_ONE;
|
||||
|
||||
if (str == "zero")
|
||||
{
|
||||
blend = dst ? GS_BLDST_ZERO : GS_BLSRC_ZERO;
|
||||
}
|
||||
else if (str == "one")
|
||||
{
|
||||
blend = dst ? GS_BLDST_ONE : GS_BLSRC_ONE;
|
||||
}
|
||||
else if (str == "srcalpha" ||
|
||||
str == "src_alpha")
|
||||
{
|
||||
blend = dst ? GS_BLDST_SRCALPHA : GS_BLSRC_SRCALPHA;
|
||||
}
|
||||
else if (str == "invsrcalpha" ||
|
||||
str == "inv_src_alpha")
|
||||
{
|
||||
blend = dst ? GS_BLDST_ONEMINUSSRCALPHA : GS_BLSRC_ONEMINUSSRCALPHA;
|
||||
}
|
||||
else if (str == "dstalpha" ||
|
||||
str == "dst_alpha")
|
||||
{
|
||||
blend = dst ? GS_BLDST_DSTALPHA : GS_BLSRC_DSTALPHA;
|
||||
}
|
||||
else if (str == "invdstalpha" ||
|
||||
str == "inv_dst_alpha")
|
||||
{
|
||||
blend = dst ? GS_BLDST_ONEMINUSDSTALPHA : GS_BLSRC_ONEMINUSDSTALPHA;
|
||||
}
|
||||
else if (str == "dstcolor" ||
|
||||
str == "dst_color")
|
||||
{
|
||||
blend = GS_BLSRC_DSTCOL;
|
||||
}
|
||||
else if (str == "srccolor" ||
|
||||
str == "src_color")
|
||||
{
|
||||
blend = GS_BLDST_SRCCOL;
|
||||
}
|
||||
else if (str == "invdstcolor" ||
|
||||
str == "inv_dst_color")
|
||||
{
|
||||
blend = GS_BLSRC_ONEMINUSDSTCOL;
|
||||
}
|
||||
else if (str == "invsrccolor" ||
|
||||
str == "inv_src_color")
|
||||
{
|
||||
blend = GS_BLDST_ONEMINUSSRCCOL;
|
||||
}
|
||||
|
||||
return blend;
|
||||
}
|
||||
|
||||
class CXmlFontShader
|
||||
{
|
||||
public:
|
||||
CXmlFontShader(CFFont* pFont)
|
||||
{
|
||||
m_pFont = pFont;
|
||||
m_nElement = ELEMENT_UNKNOWN;
|
||||
m_pEffect = NULL;
|
||||
m_pPass = NULL;
|
||||
m_FontTexSize.set(0, 0);
|
||||
|
||||
static const int defaultSlotWidthSize = 16;
|
||||
static const int defaultSlotHeightSize = 8;
|
||||
m_SlotSizes.set(defaultSlotWidthSize, defaultSlotHeightSize);
|
||||
|
||||
m_FontSmoothAmount = 0;
|
||||
m_FontSmoothMethod = FONT_SMOOTH_NONE;
|
||||
}
|
||||
|
||||
~CXmlFontShader()
|
||||
{
|
||||
}
|
||||
|
||||
void ScanXmlNodesRecursively(XmlNodeRef node)
|
||||
{
|
||||
if (!node)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
FoundElement(node->getTag());
|
||||
|
||||
for (int i = 0, count = node->getNumAttributes(); i < count; ++i)
|
||||
{
|
||||
const char* key = "";
|
||||
const char* value = "";
|
||||
if (node->getAttributeByIndex(i, &key, &value))
|
||||
{
|
||||
FoundAttribute(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, count = node->getChildCount(); i < count; ++i)
|
||||
{
|
||||
XmlNodeRef child = node->getChild(i);
|
||||
ScanXmlNodesRecursively(child);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// notify methods
|
||||
void FoundElement(const string& name)
|
||||
{
|
||||
//MessageBox(NULL, string("[" + name + "]").c_str(), "FoundElement", MB_OK);
|
||||
// process the previous element
|
||||
switch (m_nElement)
|
||||
{
|
||||
case ELEMENT_FONT:
|
||||
{
|
||||
if (!m_FontTexSize.x || !m_FontTexSize.y)
|
||||
{
|
||||
m_FontTexSize.set(512, 512);
|
||||
}
|
||||
|
||||
bool fontLoaded = m_pFont->Load(m_strFontPath.c_str(), m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio);
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
if (!fontLoaded)
|
||||
{
|
||||
TCHAR sysFontPath[MAX_PATH];
|
||||
if (SUCCEEDED(SHGetFolderPath(0, CSIDL_FONTS, 0, SHGFP_TYPE_DEFAULT, sysFontPath)))
|
||||
{
|
||||
const char* pFontPath = m_strFontPath.c_str();
|
||||
const char* pFontName = CryStringUtils::FindFileNameInPath(pFontPath);
|
||||
|
||||
string newFontPath(sysFontPath);
|
||||
newFontPath += "/";
|
||||
newFontPath += pFontName;
|
||||
m_pFont->Load(newFontPath, m_FontTexSize.x, m_FontTexSize.y, m_SlotSizes.x, m_SlotSizes.y, TTFFLAG_CREATE(m_FontSmoothMethod, m_FontSmoothAmount), m_SizeRatio);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Translate the m_nElement name to a define
|
||||
if (name == "font")
|
||||
{
|
||||
m_nElement = ELEMENT_FONT;
|
||||
}
|
||||
else if (name == "effect")
|
||||
{
|
||||
m_nElement = ELEMENT_EFFECT;
|
||||
}
|
||||
else if (name == "effectfile")
|
||||
{
|
||||
m_nElement = ELEMENT_EFFECTFILE;
|
||||
}
|
||||
else if (name == "pass")
|
||||
{
|
||||
m_pPass = NULL;
|
||||
m_nElement = ELEMENT_PASS;
|
||||
if (m_pEffect)
|
||||
{
|
||||
m_pPass = m_pEffect->AddPass();
|
||||
}
|
||||
}
|
||||
else if (name == "color")
|
||||
{
|
||||
m_nElement = ELEMENT_PASS_COLOR;
|
||||
}
|
||||
else if (name == "pos" ||
|
||||
name == "offset")
|
||||
{
|
||||
m_nElement = ELEMENT_PASS_POSOFFSET;
|
||||
}
|
||||
else if (name == "blend" ||
|
||||
name == "blending")
|
||||
{
|
||||
m_nElement = ELEMENT_PASS_BLEND;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nElement = ELEMENT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
void FoundAttribute(const string& name, const string& value)
|
||||
{
|
||||
//MessageBox(NULL, string(name + "\n" + value).c_str(), "FoundAttribute", MB_OK);
|
||||
switch (m_nElement)
|
||||
{
|
||||
case ELEMENT_FONT:
|
||||
if (name == "path")
|
||||
{
|
||||
m_strFontPath = value;
|
||||
}
|
||||
else if (name == "w")
|
||||
{
|
||||
m_FontTexSize.x = (long)atof(value.c_str());
|
||||
}
|
||||
else if (name == "h")
|
||||
{
|
||||
m_FontTexSize.y = (long)atof(value.c_str());
|
||||
}
|
||||
else if (name == "widthslots")
|
||||
{
|
||||
m_SlotSizes.x = (int)atoi(value.c_str());
|
||||
}
|
||||
else if (name == "heightslots")
|
||||
{
|
||||
m_SlotSizes.y = (int)atoi(value.c_str());
|
||||
}
|
||||
else if (name == "sizeratio")
|
||||
{
|
||||
m_SizeRatio = static_cast<float>(atof(value.c_str()));
|
||||
}
|
||||
else if (name == "smooth")
|
||||
{
|
||||
if (value == "blur")
|
||||
{
|
||||
m_FontSmoothMethod = FONT_SMOOTH_BLUR;
|
||||
}
|
||||
else if (value == "supersample")
|
||||
{
|
||||
m_FontSmoothMethod = FONT_SMOOTH_SUPERSAMPLE;
|
||||
}
|
||||
else if (value == "none")
|
||||
{
|
||||
m_FontSmoothMethod = FONT_SMOOTH_NONE;
|
||||
}
|
||||
}
|
||||
else if (name == "smooth_amount")
|
||||
{
|
||||
m_FontSmoothAmount = (long)atof(value.c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case ELEMENT_EFFECT:
|
||||
if (name == "name")
|
||||
{
|
||||
if (value == "default")
|
||||
{
|
||||
m_pEffect = m_pFont->GetDefaultEffect();
|
||||
m_pEffect->ClearPasses();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pEffect = m_pFont->AddEffect(value.c_str());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ELEMENT_EFFECTFILE:
|
||||
if (name == "path")
|
||||
{
|
||||
m_strFontEffectPath = value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ELEMENT_PASS_COLOR:
|
||||
if (!m_pPass)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (name == "r")
|
||||
{
|
||||
m_pPass->m_color.r = (uint8)((float)atof(value.c_str()) * 255.0f);
|
||||
}
|
||||
else if (name == "g")
|
||||
{
|
||||
m_pPass->m_color.g = (uint8)((float)atof(value.c_str()) * 255.0f);
|
||||
}
|
||||
else if (name == "b")
|
||||
{
|
||||
m_pPass->m_color.b = (uint8)((float)atof(value.c_str()) * 255.0f);
|
||||
}
|
||||
else if (name == "a")
|
||||
{
|
||||
m_pPass->m_color.a = (uint8)((float)atof(value.c_str()) * 255.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case ELEMENT_PASS_POSOFFSET:
|
||||
if (!m_pPass)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (name == "x")
|
||||
{
|
||||
m_pPass->m_posOffset.x = (float)atoi(value.c_str());
|
||||
}
|
||||
else if (name == "y")
|
||||
{
|
||||
m_pPass->m_posOffset.y = (float)atoi(value.c_str());
|
||||
}
|
||||
break;
|
||||
|
||||
case ELEMENT_PASS_BLEND:
|
||||
if (!m_pPass)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (name == "src")
|
||||
{
|
||||
m_pPass->m_blendSrc = GetBlendModeFromString(value, false);
|
||||
}
|
||||
else if (name == "dst")
|
||||
{
|
||||
m_pPass->m_blendDest = GetBlendModeFromString(value, true);
|
||||
}
|
||||
else if (name == "type")
|
||||
{
|
||||
if (value == "modulate")
|
||||
{
|
||||
m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA;
|
||||
m_pPass->m_blendDest = GS_BLDST_ONEMINUSSRCALPHA;
|
||||
}
|
||||
else if (value == "additive")
|
||||
{
|
||||
m_pPass->m_blendSrc = GS_BLSRC_SRCALPHA;
|
||||
m_pPass->m_blendDest = GS_BLDST_ONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case ELEMENT_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
CFFont* m_pFont;
|
||||
|
||||
unsigned long m_nElement;
|
||||
|
||||
CFFont::SEffect* m_pEffect;
|
||||
CFFont::SRenderingPass* m_pPass;
|
||||
|
||||
string m_strFontPath;
|
||||
string m_strFontEffectPath;
|
||||
vector2l m_FontTexSize;
|
||||
Vec2i m_SlotSizes;
|
||||
float m_SizeRatio = IFFontConstants::defaultSizeRatio;
|
||||
|
||||
int m_FontSmoothMethod;
|
||||
int m_FontSmoothAmount;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Main loading function
|
||||
bool CFFont::Load(const char* pXMLFile)
|
||||
{
|
||||
m_curPath = "";
|
||||
if (pXMLFile)
|
||||
{
|
||||
m_curPath = PathUtil::GetPath(pXMLFile);
|
||||
}
|
||||
|
||||
XmlNodeRef root = GetISystem()->LoadXmlFromFile(pXMLFile);
|
||||
if (!root)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
CXmlFontShader xmlfs(this);
|
||||
xmlfs.ScanXmlNodesRecursively(root);
|
||||
|
||||
// if this was not a valid font XML file then return false
|
||||
if (!m_pFontTexture || !m_pFontBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// if there was a font effect file then parse that for effects
|
||||
if (!xmlfs.m_strFontEffectPath.empty())
|
||||
{
|
||||
XmlNodeRef fontEffectRoot = GetISystem()->LoadXmlFromFile(xmlfs.m_strFontEffectPath.c_str());
|
||||
if (!fontEffectRoot)
|
||||
{
|
||||
AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' pathname %s could not be found.",
|
||||
pXMLFile, xmlfs.m_strFontEffectPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_effects.size() > 1 || (m_effects.size() == 1 && (m_effects[0].m_name != "default" || m_effects[0].m_passes.size() > 1)))
|
||||
{
|
||||
AZ_Warning("Font", false, "Error parsing font file %s, 'effectfile' and 'effect' cannot both be used in the same font file.",
|
||||
pXMLFile);
|
||||
m_effects.clear();
|
||||
}
|
||||
|
||||
// parse the font effects file, adding to this font object
|
||||
CXmlFontShader xmlfsEffect(this);
|
||||
xmlfsEffect.ScanXmlNodesRecursively(fontEffectRoot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,398 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// - Render a glyph outline into a bitmap using FreeType 2
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "FontRenderer.h"
|
||||
|
||||
#include <freetype/ftoutln.h>
|
||||
#include <freetype/ftglyph.h>
|
||||
#include <freetype/ftimage.h>
|
||||
|
||||
#include <AzCore/Casting/lossy_cast.h>
|
||||
|
||||
// Sizes are defined in in 26.6 fixed float format (TT_F26Dot6), where
|
||||
// 1 unit is 1/64 of a pixel.
|
||||
static const int fractionalPixelUnits = 64;
|
||||
|
||||
namespace
|
||||
{
|
||||
FT_Int32 GetLoadFlags(CFFont::HintBehavior hintBehavior)
|
||||
{
|
||||
switch (hintBehavior)
|
||||
{
|
||||
case CFFont::HintBehavior::NoHinting:
|
||||
{
|
||||
return FT_LOAD_NO_HINTING;
|
||||
break;
|
||||
}
|
||||
case CFFont::HintBehavior::AutoHint:
|
||||
{
|
||||
return FT_LOAD_FORCE_AUTOHINT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FT_LOAD_DEFAULT;
|
||||
}
|
||||
|
||||
FT_Int32 GetLoadTarget(CFFont::HintStyle hintStyle)
|
||||
{
|
||||
if (hintStyle == CFFont::HintStyle::Light)
|
||||
{
|
||||
return FT_LOAD_TARGET_LIGHT;
|
||||
}
|
||||
|
||||
return FT_LOAD_TARGET_NORMAL;
|
||||
}
|
||||
|
||||
FT_Render_Mode GetRenderMode(CFFont::HintStyle hintStyle)
|
||||
{
|
||||
// We use the hint style to drive the render mode also. These should
|
||||
// usually be correlated with each other for best results, even though
|
||||
// they could technically be different.
|
||||
if (hintStyle == CFFont::HintStyle::Light)
|
||||
{
|
||||
return FT_RENDER_MODE_LIGHT;
|
||||
}
|
||||
|
||||
return FT_RENDER_MODE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CFontRenderer::CFontRenderer()
|
||||
: m_pLibrary(0)
|
||||
, m_pFace(0)
|
||||
, m_pGlyph(0)
|
||||
, m_fSizeRatio(IFFontConstants::defaultSizeRatio)
|
||||
, m_pEncoding(FONT_ENCODING_UNICODE)
|
||||
, m_iGlyphBitmapWidth(0)
|
||||
, m_iGlyphBitmapHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CFontRenderer::~CFontRenderer()
|
||||
{
|
||||
FT_Done_Face(m_pFace);
|
||||
;
|
||||
FT_Done_FreeType(m_pLibrary);
|
||||
m_pFace = NULL;
|
||||
m_pLibrary = NULL;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::LoadFromFile(const string& szFileName)
|
||||
{
|
||||
int iError = FT_Init_FreeType(&m_pLibrary);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_pFace)
|
||||
{
|
||||
FT_Done_Face(m_pFace);
|
||||
m_pFace = 0;
|
||||
}
|
||||
|
||||
iError = FT_New_Face(m_pLibrary, szFileName.c_str(), 0, &m_pFace);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetEncoding(FONT_ENCODING_UNICODE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::LoadFromMemory(unsigned char* pBuffer, int iBufferSize)
|
||||
{
|
||||
int iError = FT_Init_FreeType(&m_pLibrary);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m_pFace)
|
||||
{
|
||||
FT_Done_Face(m_pFace);
|
||||
m_pFace = 0;
|
||||
}
|
||||
iError = FT_New_Memory_Face(m_pLibrary, pBuffer, iBufferSize, 0, &m_pFace);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SetEncoding(FONT_ENCODING_UNICODE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::Release()
|
||||
{
|
||||
FT_Done_Face(m_pFace);
|
||||
;
|
||||
FT_Done_FreeType(m_pLibrary);
|
||||
m_pFace = NULL;
|
||||
m_pLibrary = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio)
|
||||
{
|
||||
m_iGlyphBitmapWidth = iWidth;
|
||||
m_iGlyphBitmapHeight = iHeight;
|
||||
|
||||
// Assign the given scale for texture slots as long as its positive
|
||||
m_fSizeRatio = sizeRatio > 0.0f ? sizeRatio : m_fSizeRatio;
|
||||
|
||||
FT_Set_Pixel_Sizes(m_pFace, (int)(m_iGlyphBitmapWidth * m_fSizeRatio), (int)(m_iGlyphBitmapHeight * m_fSizeRatio));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::GetGlyphBitmapSize(int* pWidth, int* pHeight)
|
||||
{
|
||||
if (pWidth)
|
||||
{
|
||||
*pWidth = m_iGlyphBitmapWidth;
|
||||
}
|
||||
|
||||
if (pHeight)
|
||||
{
|
||||
*pHeight = m_iGlyphBitmapHeight;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::SetEncoding(FT_Encoding pEncoding)
|
||||
{
|
||||
if (FT_Select_Charmap(m_pFace, pEncoding))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontRenderer::GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& fontHintParams)
|
||||
{
|
||||
FT_Int32 loadFlags = GetLoadFlags(fontHintParams.hintBehavior);
|
||||
loadFlags |= GetLoadTarget(fontHintParams.hintStyle);
|
||||
|
||||
int iError = FT_Load_Char(m_pFace, iCharCode, loadFlags);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
FT_Render_Mode renderMode = GetRenderMode(fontHintParams.hintStyle);
|
||||
|
||||
m_pGlyph = m_pFace->glyph;
|
||||
|
||||
iError = FT_Render_Glyph(m_pGlyph, renderMode);
|
||||
|
||||
if (iError)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iHoriAdvance)
|
||||
{
|
||||
*iHoriAdvance = m_pGlyph->metrics.horiAdvance / fractionalPixelUnits;
|
||||
}
|
||||
|
||||
if (iGlyphWidth)
|
||||
{
|
||||
*iGlyphWidth = m_pGlyph->bitmap.width;
|
||||
}
|
||||
|
||||
if (iGlyphHeight)
|
||||
{
|
||||
*iGlyphHeight = m_pGlyph->bitmap.rows;
|
||||
}
|
||||
|
||||
unsigned char* pBuffer = pGlyphBitmap->GetBuffer();
|
||||
AZ_Assert(pBuffer, "CGlyphBitmap: bad buffer");
|
||||
|
||||
uint32 dwGlyphWidth = pGlyphBitmap->GetWidth();
|
||||
iCharOffsetX = m_pGlyph->bitmap_left;
|
||||
iCharOffsetY = (static_cast<AZ::s32>(round(m_iGlyphBitmapHeight * m_fSizeRatio)) - m_pGlyph->bitmap_top);
|
||||
|
||||
const int textureSlotBufferWidth = pGlyphBitmap->GetWidth();
|
||||
const int textureSlotBufferHeight = pGlyphBitmap->GetHeight();
|
||||
|
||||
// might happen if font characters are too big or cache dimenstions in font.xml is too small "<font path="VeraMono.ttf" w="320" h="368"/>"
|
||||
const bool charWidthFits = iX + m_pGlyph->bitmap.width <= textureSlotBufferWidth;
|
||||
const bool charHeightFits = iY + m_pGlyph->bitmap.rows <= textureSlotBufferHeight;
|
||||
const bool charFitsInSlot = charWidthFits && charHeightFits;
|
||||
AZ_Error("Font", charFitsInSlot, "Character code %d doesn't fit in font texture; check 'sizeRatio' attribute in font XML or adjust this character's sizing in the font.", iCharCode);
|
||||
|
||||
// Since we might be re-rendering/overwriting a glyph that already exists
|
||||
// in the font texture, clear the contents of this particular slot so no
|
||||
// artifacts of the previous glyph remain.
|
||||
pGlyphBitmap->Clear();
|
||||
|
||||
// Restrict iteration to smallest of either the texture slot or glyph
|
||||
// bitmap buffer ranges
|
||||
const int bufferMaxIterWidth = AZStd::GetMin<int>(textureSlotBufferWidth, m_pGlyph->bitmap.width);
|
||||
const int bufferMaxIterHeight = AZStd::GetMin<int>(textureSlotBufferHeight, m_pGlyph->bitmap.rows);
|
||||
|
||||
for (int i = 0; i < bufferMaxIterHeight; i++)
|
||||
{
|
||||
int iNewY = i + iY;
|
||||
|
||||
for (int j = 0; j < bufferMaxIterWidth; j++)
|
||||
{
|
||||
unsigned char cColor = m_pGlyph->bitmap.buffer[(i * m_pGlyph->bitmap.width) + j];
|
||||
int iOffset = iNewY * dwGlyphWidth + iX + j;
|
||||
|
||||
if (iOffset >= (int)dwGlyphWidth * m_iGlyphBitmapHeight)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
pBuffer[iOffset] = cColor;
|
||||
// pBuffer[iOffset] = cColor/2+32; // debug - visualize character in a block
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CFontRenderer::GetGlyphScaled([[maybe_unused]] CGlyphBitmap* pGlyphBitmap, [[maybe_unused]] int* iGlyphWidth, [[maybe_unused]] int* iGlyphHeight, [[maybe_unused]] int iX, [[maybe_unused]] int iY, [[maybe_unused]] float fScaleX, [[maybe_unused]] float fScaleY, [[maybe_unused]] int iCharCode)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vec2 CFontRenderer::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph)
|
||||
{
|
||||
FT_Vector kerningOffsets;
|
||||
kerningOffsets.x = kerningOffsets.y = 0;
|
||||
|
||||
if (FT_HAS_KERNING(m_pFace))
|
||||
{
|
||||
const FT_UInt leftGlyphIndex = FT_Get_Char_Index(m_pFace, leftGlyph);
|
||||
const FT_UInt rightGlyphIndex = FT_Get_Char_Index(m_pFace, rightGlyph);
|
||||
|
||||
[[maybe_unused]] FT_Error ftError = FT_Get_Kerning(m_pFace, leftGlyphIndex, rightGlyphIndex, FT_KERNING_DEFAULT, &kerningOffsets);
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
if (0 != ftError)
|
||||
{
|
||||
string warnMsg;
|
||||
warnMsg.Format("FT_Get_Kerning returned %d", ftError);
|
||||
CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, warnMsg.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return Vec2(azlossy_cast<float>(kerningOffsets.x / fractionalPixelUnits), azlossy_cast<float>(kerningOffsets.y / fractionalPixelUnits));
|
||||
}
|
||||
|
||||
float CFontRenderer::GetAscenderToHeightRatio()
|
||||
{
|
||||
return (static_cast<float>(m_pFace->ascender) / static_cast<float>(m_pFace->height));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
int CFontRenderer::FT_GetIndex(int iCharCode)
|
||||
{
|
||||
if (iCharCode < 256)
|
||||
{
|
||||
int iIndex = 0;
|
||||
int iUnicode;
|
||||
|
||||
// try unicode
|
||||
for (int i = 0; i < m_pFace->num_charmaps; i++)
|
||||
{
|
||||
if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1))
|
||||
{
|
||||
iUnicode = i;
|
||||
|
||||
FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]);
|
||||
|
||||
iIndex = FT_Get_Char_Index(m_pFace, iCharCode);
|
||||
|
||||
// not unicode, try ascii
|
||||
if (iIndex == 0)
|
||||
{
|
||||
for (int i = 0; i < m_pFace->num_charmaps; i++)
|
||||
{
|
||||
if ((m_pFace->charmaps[i]->platform_id == 0) && (m_pFace->charmaps[i]->encoding_id == 0))
|
||||
{
|
||||
FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]);
|
||||
|
||||
iIndex = FT_Get_Char_Index(m_pFace, iCharCode);
|
||||
|
||||
// not ascii either, reuse unicode default "missing char"
|
||||
if (iIndex == 0)
|
||||
{
|
||||
FT_Set_Charmap(m_pFace, m_pFace->charmaps[iUnicode]);
|
||||
|
||||
return FT_Get_Char_Index(m_pFace, iCharCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return iIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < m_pFace->num_charmaps; i++)
|
||||
{
|
||||
if ((m_pFace->charmaps[i]->platform_id == 3) && (m_pFace->charmaps[i]->encoding_id == 1))
|
||||
{
|
||||
FT_Set_Charmap(m_pFace, m_pFace->charmaps[i]);
|
||||
|
||||
return FT_Get_Char_Index(m_pFace, iCharCode);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Render a glyph outline into a bitmap using FreeType 2
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#ifndef CRYINCLUDE_CRYFONT_FONTRENDERER_H
|
||||
#define CRYINCLUDE_CRYFONT_FONTRENDERER_H
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
#include "GlyphBitmap.h"
|
||||
#include "FFont.h"
|
||||
#include <ft2build.h>
|
||||
#pragma push_macro("generic")
|
||||
#define generic GenericFromFreeTypeLibrary
|
||||
#include <freetype/freetype.h>
|
||||
#undef generic
|
||||
#pragma pop_macro("generic")
|
||||
|
||||
|
||||
// Corresponds to the Unicode character set. This value covers all versions of the Unicode repertoire,
|
||||
// including ASCII and Latin-1. Most fonts include a Unicode charmap, but not all of them.
|
||||
#define FONT_ENCODING_UNICODE (FT_ENCODING_UNICODE)
|
||||
|
||||
// Corresponds to the Microsoft Symbol encoding, used to encode mathematical symbols in the 32..255 character code range.
|
||||
// For more information, see `http://www.ceviz.net/symbol.htm'.
|
||||
#define FONT_ENCODING_SYMBOL (FT_ENCODING_MS_SYMBOL)
|
||||
|
||||
// Corresponds to Microsoft's Japanese SJIS encoding.
|
||||
// More info at `http://langsupport.japanreference.com/encoding.shtml'. See note on multi-byte encodings below.
|
||||
#define FONT_ENCODING_SJIS (FT_ENCODING_MS_SJIS)
|
||||
|
||||
// Corresponds to the encoding system for Simplified Chinese, as used in China. Only found in some TrueType fonts.
|
||||
#define FONT_ENCODING_GB2312 (FT_ENCODING_MS_GB2312)
|
||||
|
||||
// Corresponds to the encoding system for Traditional Chinese, as used in Taiwan and Hong Kong. Only found in some TrueType fonts.
|
||||
#define FONT_ENCODING_BIG5 (FT_ENCODING_MS_BIG5)
|
||||
|
||||
// Corresponds to the Korean encoding system known as Wansung.
|
||||
// This is a Microsoft encoding that is only found in some TrueType fonts.
|
||||
// For more information, see `http://www.microsoft.com/typography/unicode/949.txt'.
|
||||
#define FONT_ENCODING_WANSUNG (FT_ENCODING_MS_WANSUNG)
|
||||
|
||||
// The Korean standard character set (KS C-5601-1992), which corresponds to Windows code page 1361.
|
||||
// This character set includes all possible Hangeul character combinations. Only found on some rare TrueType fonts.
|
||||
#define FONT_ENCODING_JOHAB (FT_ENCODING_MS_JOHAB)
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------
|
||||
class CFontRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CFontRenderer();
|
||||
~CFontRenderer();
|
||||
|
||||
int LoadFromFile(const string& szFileName);
|
||||
int LoadFromMemory(unsigned char* pBuffer, int iBufferSize);
|
||||
int Release();
|
||||
|
||||
int SetGlyphBitmapSize(int iWidth, int iHeight, float sizeRatio);
|
||||
int GetGlyphBitmapSize(int* pWidth, int* pHeight);
|
||||
|
||||
int SetSizeRatio(float fSizeRatio) { m_fSizeRatio = fSizeRatio; return 1; };
|
||||
float GetSizeRatio() { return m_fSizeRatio; };
|
||||
|
||||
int SetEncoding(FT_Encoding pEncoding);
|
||||
FT_Encoding GetEncoding() { return m_pEncoding; };
|
||||
|
||||
//! Populates the given pGlyphBitmap's buffer from the FreeType bitmap buffer
|
||||
//! \param iCharCode Used as a character index to retrieve the FreeType glyph and it's associated bitmap buffer for the character
|
||||
//! \param pGlyphBitmap The FreeType glyph buffer is essentially copied into this CGlyphBitmap buffer
|
||||
int GetGlyph(CGlyphBitmap* pGlyphBitmap, int* iHoriAdvance, uint8* iGlyphWidth, uint8* iGlyphHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, int iX, int iY, int iCharCode, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams());
|
||||
int GetGlyphScaled(CGlyphBitmap* pGlyphBitmap, int* iGlyphWidth, int* iGlyphHeight, int iX, int iY, float fScaleX, float fScaleY, int iCharCode);
|
||||
|
||||
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
||||
|
||||
bool GetMonospaced() const { return FT_IS_FIXED_WIDTH(m_pFace) != 0; }
|
||||
|
||||
Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph);
|
||||
|
||||
float GetAscenderToHeightRatio();
|
||||
|
||||
private:
|
||||
|
||||
FT_Library m_pLibrary;
|
||||
FT_Face m_pFace;
|
||||
FT_GlyphSlot m_pGlyph;
|
||||
float m_fSizeRatio;
|
||||
|
||||
FT_Encoding m_pEncoding;
|
||||
|
||||
int m_iGlyphBitmapWidth;
|
||||
int m_iGlyphBitmapHeight;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_FONTRENDERER_H
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
@@ -1,633 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Purpose:
|
||||
// - Create and update a texture with the most recently used glyphs
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "FontTexture.h"
|
||||
#include "UnicodeIterator.h"
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef GetCharWidth
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CFontTexture::CFontTexture()
|
||||
: m_wSlotUsage(1)
|
||||
, m_iWidth(0)
|
||||
, m_iHeight(0)
|
||||
, m_fInvWidth(0.0f)
|
||||
, m_fInvHeight(0.0f)
|
||||
, m_iCellWidth(0)
|
||||
, m_iCellHeight(0)
|
||||
, m_fTextureCellWidth(0)
|
||||
, m_fTextureCellHeight(0)
|
||||
, m_iWidthCellCount(0)
|
||||
, m_iHeightCellCount(0)
|
||||
, m_nTextureSlotCount(0)
|
||||
, m_pBuffer(0)
|
||||
, m_iSmoothMethod(FONT_SMOOTH_NONE)
|
||||
, m_iSmoothAmount(FONT_SMOOTH_AMOUNT_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CFontTexture::~CFontTexture()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount)
|
||||
{
|
||||
if (!m_pGlyphCache.LoadFontFromFile(szFileName))
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio)
|
||||
{
|
||||
if (!m_pGlyphCache.LoadFontFromMemory(pFileData, iDataSize))
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!Create(iWidth, iHeight, iSmoothMethod, iSmoothAmount, iWidthCellCount, iHeightCellCount, sizeRatio))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCellCount, int iHeightCellCount, float sizeRatio)
|
||||
{
|
||||
m_pBuffer = new FONT_TEXTURE_TYPE[iWidth * iHeight];
|
||||
if (!m_pBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(m_pBuffer, 0, iWidth * iHeight * sizeof(FONT_TEXTURE_TYPE));
|
||||
|
||||
if (!(iWidthCellCount * iHeightCellCount))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_iWidth = iWidth;
|
||||
m_iHeight = iHeight;
|
||||
m_fInvWidth = 1.0f / (float)iWidth;
|
||||
m_fInvHeight = 1.0f / (float)iHeight;
|
||||
|
||||
m_iWidthCellCount = iWidthCellCount;
|
||||
m_iHeightCellCount = iHeightCellCount;
|
||||
m_nTextureSlotCount = m_iWidthCellCount * m_iHeightCellCount;
|
||||
|
||||
m_iSmoothMethod = iSmoothMethod;
|
||||
m_iSmoothAmount = iSmoothAmount;
|
||||
|
||||
m_iCellWidth = m_iWidth / m_iWidthCellCount;
|
||||
m_iCellHeight = m_iHeight / m_iHeightCellCount;
|
||||
|
||||
m_fTextureCellWidth = m_iCellWidth * m_fInvWidth;
|
||||
m_fTextureCellHeight = m_iCellHeight * m_fInvHeight;
|
||||
|
||||
if (!m_pGlyphCache.Create(FONT_GLYPH_CACHE_SIZE, m_iCellWidth, m_iCellHeight, iSmoothMethod, iSmoothAmount, sizeRatio))
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CreateSlotList(m_nTextureSlotCount))
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::Release()
|
||||
{
|
||||
delete[] m_pBuffer;
|
||||
m_pBuffer = 0;
|
||||
|
||||
ReleaseSlotList();
|
||||
|
||||
m_pSlotTable.clear();
|
||||
|
||||
m_pGlyphCache.Release();
|
||||
|
||||
m_iWidthCellCount = 0;
|
||||
m_iHeightCellCount = 0;
|
||||
m_nTextureSlotCount = 0;
|
||||
|
||||
m_iWidth = 0;
|
||||
m_iHeight = 0;
|
||||
m_fInvWidth = 0.0f;
|
||||
m_fInvHeight = 0.0f;
|
||||
|
||||
m_iCellWidth = 0;
|
||||
m_iCellHeight = 0;
|
||||
|
||||
m_iSmoothMethod = 0;
|
||||
m_iSmoothAmount = 0;
|
||||
|
||||
m_fTextureCellWidth = 0.0f;
|
||||
m_fTextureCellHeight = 0.0f;
|
||||
|
||||
m_wSlotUsage = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
uint32 CFontTexture::GetSlotChar(int iSlot) const
|
||||
{
|
||||
return m_pSlotList[iSlot]->cCurrentChar;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CTextureSlot* CFontTexture::GetCharSlot(uint32 cChar, const Vec2i& glyphSize)
|
||||
{
|
||||
CryFont::FontTexture::CTextureSlotKey slotKey = GetTextureSlotKey(cChar, glyphSize);
|
||||
CTextureSlotTableItor pItor = m_pSlotTable.find(slotKey);
|
||||
|
||||
if (pItor != m_pSlotTable.end())
|
||||
{
|
||||
return pItor->second;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CTextureSlot* CFontTexture::GetLRUSlot()
|
||||
{
|
||||
uint16 wMaxSlotAge = 0;
|
||||
CTextureSlot* pLRUSlot = 0;
|
||||
CTextureSlot* pSlot;
|
||||
|
||||
CTextureSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
pSlot = *pItor;
|
||||
|
||||
if (pSlot->wSlotUsage == 0)
|
||||
{
|
||||
return pSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage;
|
||||
if (slotAge > wMaxSlotAge)
|
||||
{
|
||||
pLRUSlot = pSlot;
|
||||
wMaxSlotAge = slotAge;
|
||||
}
|
||||
}
|
||||
|
||||
++pItor;
|
||||
}
|
||||
|
||||
return pLRUSlot;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CTextureSlot* CFontTexture::GetMRUSlot()
|
||||
{
|
||||
uint16 wMinSlotAge = 0xFFFF;
|
||||
CTextureSlot* pMRUSlot = 0;
|
||||
CTextureSlot* pSlot;
|
||||
|
||||
CTextureSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
pSlot = *pItor;
|
||||
|
||||
if (pSlot->wSlotUsage != 0)
|
||||
{
|
||||
uint16 slotAge = m_wSlotUsage - pSlot->wSlotUsage;
|
||||
if (slotAge > wMinSlotAge)
|
||||
{
|
||||
pMRUSlot = pSlot;
|
||||
wMinSlotAge = slotAge;
|
||||
}
|
||||
}
|
||||
|
||||
++pItor;
|
||||
}
|
||||
|
||||
return pMRUSlot;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::PreCacheString(const char* szString, int* pUpdated, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams)
|
||||
{
|
||||
Vec2i clampedGlyphSize = ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight);
|
||||
|
||||
uint16 wSlotUsage = m_wSlotUsage++;
|
||||
int iUpdated = 0;
|
||||
|
||||
uint32 cChar;
|
||||
for (Unicode::CIterator<const char*, false> it(szString); *it; ++it)
|
||||
{
|
||||
cChar = *it;
|
||||
CTextureSlot* pSlot = GetCharSlot(cChar, clampedGlyphSize);
|
||||
|
||||
if (!pSlot)
|
||||
{
|
||||
pSlot = GetLRUSlot();
|
||||
|
||||
if (!pSlot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!UpdateSlot(pSlot->iTextureSlot, wSlotUsage, cChar, sizeRatio, clampedGlyphSize, fontHintParams))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
++iUpdated;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSlot->wSlotUsage = wSlotUsage;
|
||||
}
|
||||
}
|
||||
|
||||
if (pUpdated)
|
||||
{
|
||||
*pUpdated = iUpdated;
|
||||
}
|
||||
|
||||
if (iUpdated)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CFontTexture::GetTextureCoord(CTextureSlot* pSlot, float texCoords[4],
|
||||
int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY,
|
||||
const Vec2i& glyphSize) const
|
||||
{
|
||||
if (!pSlot)
|
||||
{
|
||||
return; // expected behavior
|
||||
}
|
||||
|
||||
// Re-rendered glyphs are stored at smaller sizes than glyphs rendered at
|
||||
// the (maximum) font texture slot resolution. We scale the returned width
|
||||
// and height of the (actual) rendered glyph sizes so its transparent to
|
||||
// callers that the glyph is actually smaller (from being re-rendered).
|
||||
const float requestSizeWidthScale = AZ::GetMin<float>(1.0f, GetRequestSizeWidthScale(glyphSize));
|
||||
const float requestSizeHeightScale = AZ::GetMin<float>(1.0f, GetRequestSizeHeightScale(glyphSize));
|
||||
const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale;
|
||||
const float invRequestSizeHeightScale = 1.0f / requestSizeHeightScale;
|
||||
|
||||
// The inverse scale grows as the glyph size decreases. Once the glyph size
|
||||
// reaches the font texture's max slot dimensions, we cap width/height scale
|
||||
// since the text draw context will apply normal (as opposed to re-rendered)
|
||||
// scaling.
|
||||
int iChWidth = static_cast<int>(pSlot->iCharWidth * invRequestSizeWidthScale);
|
||||
int iChHeight = static_cast<int>(pSlot->iCharHeight * invRequestSizeHeightScale);
|
||||
|
||||
float slotCoord0 = pSlot->vTexCoord[0];
|
||||
float slotCoord1 = pSlot->vTexCoord[1];
|
||||
texCoords[0] = slotCoord0 - m_fInvWidth; // extra pixel for nicer bilinear filter
|
||||
texCoords[1] = slotCoord1 - m_fInvHeight; // extra pixel for nicer bilinear filter
|
||||
|
||||
// UV coordinates also must be scaled relative to the re-rendered glyph size
|
||||
// as well. Width scale must be capped at 1.0f since glyph can't grow
|
||||
// beyond the slot's resolution.
|
||||
texCoords[2] = slotCoord0 + (((float)iChWidth * m_fInvWidth) * requestSizeWidthScale);
|
||||
texCoords[3] = slotCoord1 + (((float)iChHeight * m_fInvHeight) * requestSizeHeightScale);
|
||||
|
||||
iCharSizeX = iChWidth + 1; // extra pixel for nicer bilinear filter
|
||||
iCharSizeY = iChHeight + 1; // extra pixel for nicer bilinear filter
|
||||
|
||||
// Offsets are scaled accordingly when the rendered glyph size is smaller
|
||||
// than the glyph/slot dimensions, but otherwise we expect the text draw
|
||||
// context to apply scaling beyond that.
|
||||
iCharOffsetX = static_cast<int>(pSlot->iCharOffsetX * invRequestSizeWidthScale);
|
||||
iCharOffsetY = static_cast<int>(pSlot->iCharOffsetY * invRequestSizeHeightScale);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::GetCharacterWidth(uint32 cChar) const
|
||||
{
|
||||
CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar));
|
||||
|
||||
if (pItor == m_pSlotTable.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CTextureSlot& rSlot = *pItor->second;
|
||||
|
||||
// For proportional fonts, add one pixel of spacing for aesthetic reasons
|
||||
int proportionalOffset = GetMonospaced() ? 0 : 1;
|
||||
|
||||
return rSlot.iCharWidth + proportionalOffset;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize) const
|
||||
{
|
||||
CTextureSlotTableItorConst pItor = m_pSlotTable.find(GetTextureSlotKey(cChar, glyphSize));
|
||||
|
||||
if (pItor == m_pSlotTable.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CTextureSlot& rSlot = *pItor->second;
|
||||
|
||||
// Re-rendered glyphs are stored at smaller sizes than glyphs rendered at
|
||||
// the (maximum) font texture slot resolution. We scale the returned width
|
||||
// and height of the (actual) rendered glyph sizes so its transparent to
|
||||
// callers that the glyph is actually smaller (from being re-rendered).
|
||||
const float requestSizeWidthScale = GetRequestSizeWidthScale(glyphSize);
|
||||
const float invRequestSizeWidthScale = 1.0f / requestSizeWidthScale;
|
||||
|
||||
// Only multiply by 1.0f when glyphsize is greater than cell width because we assume that callers
|
||||
// will use the font draw text context to scale the value appropriately.
|
||||
return static_cast<int>(rSlot.iHoriAdvance * AZ::GetMax<float>(1.0f, invRequestSizeWidthScale));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
/*
|
||||
int CFontTexture::GetCharHeightByChar(wchar_t cChar)
|
||||
{
|
||||
CTextureSlotTableItor pItor = m_pSlotTable.find(cChar);
|
||||
|
||||
if (pItor != m_pSlotTable.end())
|
||||
{
|
||||
return pItor->second->iCharHeight;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::WriteToFile([[maybe_unused]] const string& szFileName)
|
||||
{
|
||||
#ifdef WIN32
|
||||
AZ::IO::FileIOStream outputFile(szFileName.c_str(), AZ::IO::OpenMode::ModeWrite | AZ::IO::OpenMode::ModeBinary);
|
||||
|
||||
if (!outputFile.IsOpen())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
BITMAPFILEHEADER pHeader;
|
||||
BITMAPINFOHEADER pInfoHeader;
|
||||
|
||||
memset(&pHeader, 0, sizeof(BITMAPFILEHEADER));
|
||||
memset(&pInfoHeader, 0, sizeof(BITMAPINFOHEADER));
|
||||
|
||||
pHeader.bfType = 0x4D42;
|
||||
pHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + m_iWidth * m_iHeight * 3;
|
||||
pHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
|
||||
pInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
pInfoHeader.biWidth = m_iWidth;
|
||||
pInfoHeader.biHeight = m_iHeight;
|
||||
pInfoHeader.biPlanes = 1;
|
||||
pInfoHeader.biBitCount = 24;
|
||||
pInfoHeader.biCompression = 0;
|
||||
pInfoHeader.biSizeImage = m_iWidth * m_iHeight * 3;
|
||||
|
||||
outputFile.Write(sizeof(BITMAPFILEHEADER), &pHeader);
|
||||
outputFile.Write(sizeof(BITMAPINFOHEADER), &pInfoHeader);
|
||||
|
||||
unsigned char cRGB[3];
|
||||
|
||||
for (int i = m_iHeight - 1; i >= 0; i--)
|
||||
{
|
||||
for (int j = 0; j < m_iWidth; j++)
|
||||
{
|
||||
cRGB[0] = m_pBuffer[(i * m_iWidth) + j];
|
||||
cRGB[1] = *cRGB;
|
||||
|
||||
cRGB[2] = *cRGB;
|
||||
|
||||
outputFile.Write(3, cRGB);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Vec2 CFontTexture::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph)
|
||||
{
|
||||
return m_pGlyphCache.GetKerning(leftGlyph, rightGlyph);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
float CFontTexture::GetAscenderToHeightRatio()
|
||||
{
|
||||
return m_pGlyphCache.GetAscenderToHeightRatio();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::CreateSlotList(int iListSize)
|
||||
{
|
||||
int y, x;
|
||||
|
||||
for (int i = 0; i < iListSize; i++)
|
||||
{
|
||||
CTextureSlot* pTextureSlot = new CTextureSlot;
|
||||
|
||||
if (!pTextureSlot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pTextureSlot->iTextureSlot = i;
|
||||
pTextureSlot->Reset();
|
||||
|
||||
y = i / m_iWidthCellCount;
|
||||
x = i % m_iWidthCellCount;
|
||||
|
||||
pTextureSlot->vTexCoord[0] = (float)(x * m_fTextureCellWidth) + (0.5f / (float)m_iWidth);
|
||||
pTextureSlot->vTexCoord[1] = (float)(y * m_fTextureCellHeight) + (0.5f / (float)m_iHeight);
|
||||
|
||||
m_pSlotList.push_back(pTextureSlot);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::ReleaseSlotList()
|
||||
{
|
||||
CTextureSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
delete (*pItor);
|
||||
|
||||
pItor = m_pSlotList.erase(pItor);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CFontTexture::UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams)
|
||||
{
|
||||
CTextureSlot* pSlot = m_pSlotList[iSlot];
|
||||
|
||||
if (!pSlot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTextureSlotTableItor pItor = m_pSlotTable.find(GetTextureSlotKey(pSlot->cCurrentChar, pSlot->glyphSize));
|
||||
|
||||
if (pItor != m_pSlotTable.end())
|
||||
{
|
||||
m_pSlotTable.erase(pItor);
|
||||
}
|
||||
m_pSlotTable.insert(AZStd::pair<CryFont::FontTexture::CTextureSlotKey, CTextureSlot*>(GetTextureSlotKey(cChar, glyphSize), pSlot));
|
||||
pSlot->glyphSize = glyphSize;
|
||||
pSlot->wSlotUsage = wSlotUsage;
|
||||
pSlot->cCurrentChar = cChar;
|
||||
|
||||
int iWidth = 0;
|
||||
int iHeight = 0;
|
||||
|
||||
// blit the char glyph into the texture
|
||||
int x = pSlot->iTextureSlot % m_iWidthCellCount;
|
||||
int y = pSlot->iTextureSlot / m_iWidthCellCount;
|
||||
|
||||
CGlyphBitmap* pGlyphBitmap;
|
||||
|
||||
if (glyphSize.x > 0 && glyphSize.y > 0)
|
||||
{
|
||||
m_pGlyphCache.SetGlyphBitmapSize(glyphSize.x, glyphSize.y, sizeRatio);
|
||||
}
|
||||
|
||||
if (!m_pGlyphCache.GetGlyph(&pGlyphBitmap, &pSlot->iHoriAdvance, &iWidth, &iHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, cChar, glyphSize, fontHintParams))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pSlot->iCharWidth = iWidth;
|
||||
pSlot->iCharHeight = iHeight;
|
||||
|
||||
// Add a pixel along width and height to avoid artifacts being rendered
|
||||
// from a previous glyph in this slot due to bilinear filtering. The source
|
||||
// glyph bitmap buffer is presumed to be cleared prior to FreeType rendering
|
||||
// to the bitmap.
|
||||
const int blitWidth = AZ::GetMin<int>(iWidth + 1, m_iCellWidth);
|
||||
const int blitHeight = AZ::GetMin<int>(iHeight + 1, m_iCellHeight);
|
||||
|
||||
pGlyphBitmap->BlitTo8(m_pBuffer, 0, 0,
|
||||
blitWidth, blitHeight, x * m_iCellWidth, y * m_iCellHeight, m_iWidth);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CFontTexture::CreateGradientSlot()
|
||||
{
|
||||
CTextureSlot* pSlot = GetGradientSlot();
|
||||
assert(pSlot->cCurrentChar == (uint32)~0); // 0 needs to be unused spot
|
||||
|
||||
pSlot->Reset();
|
||||
pSlot->iCharWidth = m_iCellWidth - 2;
|
||||
pSlot->iCharHeight = m_iCellHeight - 2;
|
||||
pSlot->SetNotReusable();
|
||||
|
||||
int x = pSlot->iTextureSlot % m_iWidthCellCount;
|
||||
int y = pSlot->iTextureSlot / m_iWidthCellCount;
|
||||
|
||||
assert(sizeof(*m_pBuffer) == sizeof(uint8));
|
||||
uint8* pBuffer = &m_pBuffer[x * m_iCellWidth + y * m_iCellHeight * m_iWidth];
|
||||
|
||||
for (uint32 dwY = 0; dwY < pSlot->iCharHeight; ++dwY)
|
||||
{
|
||||
for (uint32 dwX = 0; dwX < pSlot->iCharWidth; ++dwX)
|
||||
{
|
||||
pBuffer[dwX + dwY * m_iWidth] = dwY * 255 / (pSlot->iCharHeight - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CTextureSlot* CFontTexture::GetGradientSlot()
|
||||
{
|
||||
return m_pSlotList[0];
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CryFont::FontTexture::CTextureSlotKey CFontTexture::GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize) const
|
||||
{
|
||||
const Vec2i clampedGlyphSize(ClampGlyphSize(glyphSize, m_iCellWidth, m_iCellHeight));
|
||||
return CryFont::FontTexture::CTextureSlotKey(clampedGlyphSize, cChar);
|
||||
}
|
||||
|
||||
Vec2i CFontTexture::ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight)
|
||||
{
|
||||
const Vec2i maxCellDimensions(cellWidth, cellHeight);
|
||||
Vec2i clampedGlyphSize(glyphSize);
|
||||
|
||||
const bool hasZeroDimension = glyphSize.x == 0 || glyphSize.y == 0;
|
||||
const bool isDefaultSize = glyphSize == CCryFont::defaultGlyphSize;
|
||||
const bool exceedsDimensions = glyphSize.x > cellWidth || glyphSize.y > cellHeight;
|
||||
const bool useMaxCellDimension = hasZeroDimension || isDefaultSize || exceedsDimensions;
|
||||
if (useMaxCellDimension)
|
||||
{
|
||||
clampedGlyphSize = maxCellDimensions;
|
||||
}
|
||||
|
||||
return clampedGlyphSize;
|
||||
}
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* 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_CRYFONT_FONTTEXTURE_H
|
||||
#define CRYINCLUDE_CRYFONT_FONTTEXTURE_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "GlyphCache.h"
|
||||
#include "GlyphBitmap.h"
|
||||
#include "CryFont.h"
|
||||
#include "FFont.h"
|
||||
|
||||
typedef uint8 FONT_TEXTURE_TYPE;
|
||||
|
||||
// the number of slots in the glyph cache
|
||||
// each slot ocupies ((glyph_bitmap_width * glyph_bitmap_height) + 24) bytes
|
||||
#define FONT_GLYPH_CACHE_SIZE (1)
|
||||
|
||||
// the glyph spacing in font texels between characters in proportional font mode (more correct would be to take the value in the character)
|
||||
#define FONT_GLYPH_PROP_SPACING (1)
|
||||
|
||||
// the size of a rendered space, this value gets multiplied by the default characted width
|
||||
#define FONT_SPACE_SIZE (0.5f)
|
||||
|
||||
// don't draw this char (used to avoid drawing color codes)
|
||||
#define FONT_NOT_DRAWABLE_CHAR (0xffff)
|
||||
|
||||
// smoothing methods
|
||||
#define FONT_SMOOTH_NONE 0
|
||||
#define FONT_SMOOTH_BLUR 1
|
||||
#define FONT_SMOOTH_SUPERSAMPLE 2
|
||||
|
||||
// smoothing amounts
|
||||
#define FONT_SMOOTH_AMOUNT_NONE 0
|
||||
#define FONT_SMOOTH_AMOUNT_2X 1
|
||||
#define FONT_SMOOTH_AMOUNT_4X 2
|
||||
|
||||
//! Stores glyph meta-data read from the font (FreeType).
|
||||
//!
|
||||
//! \sa CCacheSlot
|
||||
typedef struct CTextureSlot
|
||||
{
|
||||
Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< Size of the rendered glyph stored in the font texture
|
||||
uint16 wSlotUsage; //!< For LRU strategy, 0xffff is never released
|
||||
uint32 cCurrentChar; //!< ~0 if not used for characters
|
||||
int iTextureSlot;
|
||||
int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance.
|
||||
float vTexCoord[2]; //!< Character position in the texture (not yet half texel corrected)
|
||||
uint8 iCharWidth; //!< Glyph width (in pixel)
|
||||
uint8 iCharHeight; //!< Glyph height (in pixel)
|
||||
AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left.
|
||||
AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top.
|
||||
|
||||
void Reset()
|
||||
{
|
||||
wSlotUsage = 0;
|
||||
cCurrentChar = ~0;
|
||||
iHoriAdvance = 0;
|
||||
iCharWidth = 0;
|
||||
iCharHeight = 0;
|
||||
iCharOffsetX = 0;
|
||||
iCharOffsetY = 0;
|
||||
}
|
||||
|
||||
void SetNotReusable()
|
||||
{
|
||||
wSlotUsage = 0xffff;
|
||||
}
|
||||
|
||||
void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
||||
} CTextureSlot;
|
||||
|
||||
|
||||
typedef std::vector<CTextureSlot*> CTextureSlotList;
|
||||
typedef std::vector<CTextureSlot*>::iterator CTextureSlotListItor;
|
||||
|
||||
namespace CryFont
|
||||
{
|
||||
namespace FontTexture
|
||||
{
|
||||
//! Height and width pair for glyph size mapping
|
||||
typedef Vec2i CGlyphSizeType;
|
||||
|
||||
//! Pair for mapping a height and width size to a UTF32 character/glyph
|
||||
typedef AZStd::pair<CGlyphSizeType, uint32> CTextureSlotKey;
|
||||
|
||||
//! Hasher for texture slot table keys (glyphsize-char code pair)
|
||||
//!
|
||||
//! Instead of creating our own custom hash, the types are broken down to their
|
||||
//! native types (ints) and passed to existing hashes that handle those types.
|
||||
struct HashTextureSlotTableKey
|
||||
{
|
||||
typedef CTextureSlotKey ArgumentType;
|
||||
typedef AZStd::size_t ResultType;
|
||||
typedef AZStd::pair<int32, int32> Int32Pair;
|
||||
typedef AZStd::pair<Int32Pair, uint32> Int32PairU32Pair;
|
||||
ResultType operator()(const ArgumentType& value) const
|
||||
{
|
||||
// Utiliize existing hash function for pairs of ints
|
||||
AZStd::hash<Int32PairU32Pair> pairHash;
|
||||
return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//! Maps size-speicifc UTF32 glyphs to their corresponding texture slots
|
||||
typedef AZStd::unordered_map<CryFont::FontTexture::CTextureSlotKey, CTextureSlot*, CryFont::FontTexture::HashTextureSlotTableKey> CTextureSlotTable;
|
||||
|
||||
typedef CTextureSlotTable::iterator CTextureSlotTableItor;
|
||||
typedef CTextureSlotTable::const_iterator CTextureSlotTableItorConst;
|
||||
|
||||
#ifdef WIN64
|
||||
#undef GetCharWidth
|
||||
#undef GetCharHeight
|
||||
#endif
|
||||
|
||||
//! Stores the glyphs of a font within a single texture.
|
||||
//!
|
||||
//! The texture resolution is configurable, as is the number of slots within
|
||||
//! the texture.
|
||||
//!
|
||||
//! A texture slot contains a single glyph within the font and are uniform
|
||||
//! size throughout the font texture (each slot occupies the same size
|
||||
//! regardless of the size of a glyph being stored, so a '.' occupies the
|
||||
//! same amount of space as a 'W', for example).
|
||||
//!
|
||||
//! Font glyph buffers are read from FreeType and copied into the texture.
|
||||
//!
|
||||
//! \sa CTextureSlot, CFontRenderer
|
||||
class CFontTexture
|
||||
{
|
||||
public:
|
||||
CFontTexture();
|
||||
~CFontTexture();
|
||||
|
||||
int CreateFromFile(const string& szFileName, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16);
|
||||
|
||||
//! Default texture slot width/height is 16x8 slots, allowing for 128 glyphs to be stored in the font texture. This was
|
||||
//! previously 16x16, allowing 256 glyphs to be stored. For reference, there are 95 printable ASCII characters, so by
|
||||
//! reducing the number of slots, the height of the font texture can be halved (for some nice memory savings). We may
|
||||
//! want to make this configurable in the font XML (especially for languages with a large number of printable chars).
|
||||
int CreateFromMemory(unsigned char* pFileData, int iDataSize, int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount, int iHeightCharCount, float sizeRatio);
|
||||
|
||||
int Create(int iWidth, int iHeight, int iSmoothMethod, int iSmoothAmount, int iWidthCharCount = 16, int iHeightCharCount = 16, float sizeRatio = IFFontConstants::defaultSizeRatio);
|
||||
int Release();
|
||||
|
||||
int SetEncoding(FT_Encoding pEncoding) { return m_pGlyphCache.SetEncoding(pEncoding); }
|
||||
FT_Encoding GetEncoding() { return m_pGlyphCache.GetEncoding(); }
|
||||
|
||||
int GetCellWidth() { return m_iCellWidth; }
|
||||
int GetCellHeight() { return m_iCellHeight; }
|
||||
|
||||
int GetWidth() { return m_iWidth; }
|
||||
int GetHeight() { return m_iHeight; }
|
||||
|
||||
int GetWidthCellCount() { return m_iWidthCellCount; }
|
||||
int GetHeightCellCount() { return m_iHeightCellCount; }
|
||||
|
||||
float GetTextureCellWidth() { return m_fTextureCellWidth; }
|
||||
float GetTextureCellHeight() { return m_fTextureCellHeight; }
|
||||
|
||||
FONT_TEXTURE_TYPE* GetBuffer() { return m_pBuffer; }
|
||||
|
||||
uint32 GetSlotChar(int iSlot) const;
|
||||
CTextureSlot* GetCharSlot(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize);
|
||||
CTextureSlot* GetGradientSlot();
|
||||
|
||||
CTextureSlot* GetLRUSlot();
|
||||
CTextureSlot* GetMRUSlot();
|
||||
|
||||
//! Returns 1 if texture updated, returns 2 if texture not updated, returns 0 on error
|
||||
//! \param szString A string of glyphs (UTF8) to added to the font texture (if they don't already exist in the font texture)
|
||||
//! \param pUpdated is the number of slots updated
|
||||
//! \param sizeRatio A sizing scale that gets applied to all glyphs sizes before they are stored in the font texture.
|
||||
//! \param glyphSize The resolution to render the glyphs in szString at.
|
||||
//! \param glyphFlags Controls hinting behavior for glyphs rendered to the font texture.
|
||||
int PreCacheString(const char* szString, int* pUpdated = 0, float sizeRatio = IFFontConstants::defaultSizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams());
|
||||
// Arguments:
|
||||
// pSlot - function does nothing if this pointer is 0
|
||||
void GetTextureCoord(CTextureSlot * pSlot, float texCoords[4], int& iCharSizeX, int& iCharSizeY, int& iCharOffsetX, int& iCharOffsetY, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const;
|
||||
int GetCharacterWidth(uint32 cChar) const;
|
||||
//! Gets the horizontal advance for the given glyph/char.
|
||||
//! \param cChar The glyph (UTF32) to get the horizontal advance for.
|
||||
//! \param glyphSize The rendered size of the glyph to get the advance for (the same glyph could be stored in the font texture at multiple sizes).
|
||||
int GetHorizontalAdvance(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const;
|
||||
// int GetCharHeightByChar(wchar_t cChar);
|
||||
|
||||
// useful for special feature rendering interleaved with fonts (e.g. box behind the text)
|
||||
void CreateGradientSlot();
|
||||
|
||||
int WriteToFile(const string& szFileName);
|
||||
|
||||
void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
pSizer->AddObject(this, sizeof(*this));
|
||||
pSizer->AddObject(m_pGlyphCache);
|
||||
pSizer->AddObject(m_pSlotList);
|
||||
//pSizer->AddContainer(m_pSlotTable);
|
||||
pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight * sizeof(FONT_TEXTURE_TYPE));
|
||||
}
|
||||
|
||||
bool GetMonospaced() const { return m_pGlyphCache.GetMonospaced(); }
|
||||
|
||||
Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph);
|
||||
|
||||
float GetAscenderToHeightRatio();
|
||||
|
||||
public: // ---------------------------------------------------------------
|
||||
|
||||
//! Clamps the given glyph size to the given max cell width and height dimensions.
|
||||
static Vec2i ClampGlyphSize(const Vec2i& glyphSize, int cellWidth, int cellHeight);
|
||||
|
||||
private: // ---------------------------------------------------------------
|
||||
|
||||
int CreateSlotList(int iListSize);
|
||||
int ReleaseSlotList();
|
||||
|
||||
//! Updates the given font texture slot with the given glyph (UTF8) with the given parameters. If the glyph doesn't
|
||||
//! exist in the font texture at the given size, then the glyph will be rendered to the font texture with the given
|
||||
//! parameters.
|
||||
//! \param iSlot Index of the texture slot to update within the slot list.
|
||||
//! \param wSlotUsage Used for LRU strategy to determine how many times a glyph is referenced for retention within the font texture (before eviction).
|
||||
//! \param cChar UTF32 glyph to store within the slot.
|
||||
//! \param sizeRatio A sizing scale that should be applied to the glyph before being stored within the font texture.
|
||||
//! \param glyphSize The size of the glyph to be rendered at within the font texture.
|
||||
//! \param glyphFlags Specifies hinting behavior that should be applied to the glyph when rendered to the font texture.
|
||||
int UpdateSlot(int iSlot, uint16 wSlotUsage, uint32 cChar, float sizeRatio, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams());
|
||||
|
||||
CryFont::FontTexture::CTextureSlotKey GetTextureSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const;
|
||||
|
||||
//! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution.
|
||||
//!
|
||||
//! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale
|
||||
//! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard
|
||||
//! to whether the glyphs have been re-rendered or not.
|
||||
float GetRequestSizeWidthScale(const Vec2i& glyphSize) const
|
||||
{
|
||||
const int cellWidth = m_iCellWidth == 0 ? 1 : m_iCellWidth;
|
||||
const float invCellWidth = 1.0f / cellWidth;
|
||||
return glyphSize.x > 0 ? glyphSize.x * invCellWidth : 1.0f;
|
||||
}
|
||||
|
||||
//! Calculates scaling info that should be applied when the rendered glyph size doesn't match the maximum glyph slot resolution.
|
||||
//!
|
||||
//! Glyphs can be re-rendered to glyph slots at smaller resolutions for pixel-perfect resolution (rather than applying a scale
|
||||
//! to glyphs rendered at larger sizes). These scaling values allow clients of the font texture to use the glyphs without regard
|
||||
//! to whether the glyphs have been re-rendered or not.
|
||||
float GetRequestSizeHeightScale(const Vec2i& glyphSize) const
|
||||
{
|
||||
const int cellHeight = m_iCellHeight == 0 ? 1 : m_iCellHeight;
|
||||
const float invCellHeight = 1.0f / cellHeight;
|
||||
return glyphSize.y > 0 ? glyphSize.y * invCellHeight : 1.0f;
|
||||
}
|
||||
|
||||
// --------------------------------
|
||||
|
||||
int m_iWidth; // whole texture cache width
|
||||
int m_iHeight; // whole texture cache height
|
||||
|
||||
float m_fInvWidth;
|
||||
float m_fInvHeight;
|
||||
|
||||
int m_iCellWidth;
|
||||
int m_iCellHeight;
|
||||
|
||||
float m_fTextureCellWidth;
|
||||
float m_fTextureCellHeight;
|
||||
|
||||
int m_iWidthCellCount;
|
||||
int m_iHeightCellCount;
|
||||
|
||||
int m_nTextureSlotCount;
|
||||
|
||||
int m_iSmoothMethod;
|
||||
int m_iSmoothAmount;
|
||||
|
||||
CGlyphCache m_pGlyphCache;
|
||||
CTextureSlotList m_pSlotList;
|
||||
CTextureSlotTable m_pSlotTable;
|
||||
|
||||
FONT_TEXTURE_TYPE* m_pBuffer; // [y*iWidth * x] x=0..iWidth-1, y=0..iHeight-1
|
||||
|
||||
uint16 m_wSlotUsage;
|
||||
};
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_FONTTEXTURE_H
|
||||
@@ -1,396 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Purpose:
|
||||
// - Hold a glyph bitmap and blit it to the main texture
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
#include "GlyphBitmap.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CGlyphBitmap::CGlyphBitmap()
|
||||
: m_iWidth(0)
|
||||
, m_iHeight(0)
|
||||
, m_pBuffer(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CGlyphBitmap::~CGlyphBitmap()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::Create(int iWidth, int iHeight)
|
||||
{
|
||||
Release();
|
||||
|
||||
m_pBuffer = new unsigned char[iWidth * iHeight];
|
||||
|
||||
if (!m_pBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_iWidth = iWidth;
|
||||
m_iHeight = iHeight;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::Release()
|
||||
{
|
||||
if (m_pBuffer)
|
||||
{
|
||||
delete[] m_pBuffer;
|
||||
}
|
||||
m_pBuffer = 0;
|
||||
m_iWidth = m_iHeight = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::Blur(int iIterations)
|
||||
{
|
||||
int cSum;
|
||||
int yOffset;
|
||||
int yupOffset;
|
||||
int ydownOffset;
|
||||
|
||||
for (int i = 0; i < iIterations; i++)
|
||||
{
|
||||
for (int y = 0; y < m_iHeight; y++)
|
||||
{
|
||||
yOffset = y * m_iWidth;
|
||||
|
||||
if (y - 1 >= 0)
|
||||
{
|
||||
yupOffset = (y - 1) * m_iWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
yupOffset = (y) * m_iWidth;
|
||||
}
|
||||
|
||||
if (y + 1 < m_iHeight)
|
||||
{
|
||||
ydownOffset = (y + 1) * m_iWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
ydownOffset = (y) * m_iWidth;
|
||||
}
|
||||
|
||||
for (int x = 0; x < m_iWidth; x++)
|
||||
{
|
||||
cSum = m_pBuffer[yupOffset + x] + m_pBuffer[ydownOffset + x];
|
||||
|
||||
if (x - 1 >= 0)
|
||||
{
|
||||
cSum += m_pBuffer[yOffset + x - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cSum += m_pBuffer[yOffset + x];
|
||||
}
|
||||
|
||||
if (x + 1 < m_iWidth)
|
||||
{
|
||||
cSum += m_pBuffer[yOffset + x + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
cSum += m_pBuffer[yOffset + x];
|
||||
}
|
||||
|
||||
m_pBuffer[yOffset + x] = cSum >> 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::Scale(float fScaleX, float fScaleY)
|
||||
{
|
||||
int iNewWidth = (int)(m_iWidth * fScaleX);
|
||||
int iNewHeight = (int)(m_iHeight * fScaleY);
|
||||
|
||||
unsigned char* pNewBuffer = new unsigned char[iNewWidth * iNewHeight];
|
||||
|
||||
if (!pNewBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float xFactor = m_iWidth / (float)iNewWidth;
|
||||
float yFactor = m_iHeight / (float)iNewHeight;
|
||||
|
||||
float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1;
|
||||
int xCeil, yCeil, xFloor, yFloor, yNewOffset;
|
||||
|
||||
unsigned char c0, c1, c2, c3;
|
||||
|
||||
for (int y = 0; y < iNewHeight; ++y)
|
||||
{
|
||||
yFractioned = y * yFactor;
|
||||
yFloor = (int)floor_tpl(yFractioned);
|
||||
yCeil = yFloor + 1;
|
||||
|
||||
if (yCeil >= m_iHeight)
|
||||
{
|
||||
yCeil = yFloor;
|
||||
}
|
||||
|
||||
yFraction = yFractioned - yFloor;
|
||||
oneMinusY = 1.0f - yFraction;
|
||||
|
||||
yNewOffset = y * iNewWidth;
|
||||
|
||||
for (int x = 0; x < iNewWidth; ++x)
|
||||
{
|
||||
xFractioned = x * xFactor;
|
||||
xFloor = (int)floor_tpl(xFractioned);
|
||||
xCeil = xFloor + 1;
|
||||
|
||||
if (xCeil >= m_iWidth)
|
||||
{
|
||||
xCeil = xFloor;
|
||||
}
|
||||
|
||||
xFraction = xFractioned - xFloor;
|
||||
oneMinusX = 1.0f - xFraction;
|
||||
|
||||
c0 = m_pBuffer[yFloor * m_iWidth + xFloor];
|
||||
c1 = m_pBuffer[yFloor * m_iWidth + xCeil];
|
||||
c2 = m_pBuffer[yCeil * m_iWidth + xFloor];
|
||||
c3 = m_pBuffer[yCeil * m_iWidth + xCeil];
|
||||
|
||||
fR0 = (oneMinusX * c0 + xFraction * c1);
|
||||
fR1 = (oneMinusX * c2 + xFraction * c3);
|
||||
|
||||
pNewBuffer[yNewOffset + x] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1));
|
||||
}
|
||||
}
|
||||
|
||||
m_iWidth = iNewWidth;
|
||||
m_iHeight = iNewHeight;
|
||||
|
||||
delete[] m_pBuffer;
|
||||
m_pBuffer = pNewBuffer;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::Clear()
|
||||
{
|
||||
memset(m_pBuffer, 0, m_iWidth * m_iHeight);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth)
|
||||
{
|
||||
int ySrcOffset, yDestOffset;
|
||||
|
||||
for (int y = 0; y < iSrcHeight; y++)
|
||||
{
|
||||
ySrcOffset = (iSrcY + y) * m_iWidth;
|
||||
yDestOffset = (iDestY + y) * iDestWidth;
|
||||
|
||||
for (int x = 0; x < iSrcWidth; x++)
|
||||
{
|
||||
pBuffer[yDestOffset + iDestX + x] = m_pBuffer[ySrcOffset + iSrcX + x];
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth)
|
||||
{
|
||||
int ySrcOffset, yDestOffset;
|
||||
char cColor;
|
||||
|
||||
for (int y = 0; y < iSrcHeight; y++)
|
||||
{
|
||||
ySrcOffset = (iSrcY + y) * m_iWidth;
|
||||
yDestOffset = (iDestY + y) * iDestWidth;
|
||||
|
||||
for (int x = 0; x < iSrcWidth; x++)
|
||||
{
|
||||
cColor = m_pBuffer[ySrcOffset + iSrcX + x];
|
||||
|
||||
pBuffer[yDestOffset + iDestX + x] = (cColor << 24) | (255 << 16) | (255 << 8) | 255;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::BlitScaledTo8(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth)
|
||||
{
|
||||
int iNewWidth = (int)iDestWidth;
|
||||
int iNewHeight = (int)iDestHeight;
|
||||
|
||||
unsigned char* pNewBuffer = pBuffer;
|
||||
|
||||
float xFactor = iSrcWidth / (float)iNewWidth;
|
||||
float yFactor = iSrcHeight / (float)iNewHeight;
|
||||
|
||||
float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1;
|
||||
int xCeil, yCeil, xFloor, yFloor, yNewOffset;
|
||||
|
||||
unsigned char c0, c1, c2, c3;
|
||||
|
||||
for (int y = 0; y < iNewHeight; ++y)
|
||||
{
|
||||
yFractioned = y * yFactor;
|
||||
yFloor = (int)floor_tpl(yFractioned);
|
||||
yCeil = yFloor + 1;
|
||||
|
||||
yFraction = yFractioned - yFloor;
|
||||
oneMinusY = 1.0f - yFraction;
|
||||
|
||||
yNewOffset = y * iDestBufferWidth;
|
||||
|
||||
yFloor += iSrcY;
|
||||
yCeil += iSrcY;
|
||||
|
||||
if (yCeil >= m_iHeight)
|
||||
{
|
||||
yCeil = yFloor;
|
||||
}
|
||||
|
||||
for (int x = 0; x < iNewWidth; ++x)
|
||||
{
|
||||
xFractioned = x * xFactor;
|
||||
xFloor = (int)floor_tpl(xFractioned);
|
||||
xCeil = xFloor + 1;
|
||||
|
||||
xFraction = xFractioned - xFloor;
|
||||
oneMinusX = 1.0f - xFraction;
|
||||
|
||||
xFloor += iSrcY;
|
||||
xCeil += iSrcY;
|
||||
|
||||
if (xCeil >= m_iWidth)
|
||||
{
|
||||
xCeil = xFloor;
|
||||
}
|
||||
|
||||
c0 = m_pBuffer[yFloor * m_iWidth + xFloor];
|
||||
c1 = m_pBuffer[yFloor * m_iWidth + xCeil];
|
||||
c2 = m_pBuffer[yCeil * m_iWidth + xFloor];
|
||||
c3 = m_pBuffer[yCeil * m_iWidth + xCeil];
|
||||
|
||||
fR0 = (oneMinusX * c0 + xFraction * c1);
|
||||
fR1 = (oneMinusX * c2 + xFraction * c3);
|
||||
|
||||
pNewBuffer[yNewOffset + x + iDestX] = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1));
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7
|
||||
#pragma GCC diagnostic ignored "-Woverflow"
|
||||
#endif
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphBitmap::BlitScaledTo32(unsigned char* pBuffer, [[maybe_unused]] int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, [[maybe_unused]] int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth)
|
||||
{
|
||||
int iNewWidth = (int)iDestWidth;
|
||||
int iNewHeight = (int)iDestHeight;
|
||||
|
||||
unsigned char* pNewBuffer = pBuffer;
|
||||
|
||||
float xFactor = iSrcWidth / (float)iNewWidth;
|
||||
float yFactor = iSrcHeight / (float)iNewHeight;
|
||||
|
||||
float xFractioned, yFractioned, xFraction, yFraction, oneMinusX, oneMinusY, fR0, fR1;
|
||||
int xCeil, yCeil, xFloor, yFloor, yNewOffset;
|
||||
|
||||
unsigned char c0, c1, c2, c3, cColor;
|
||||
|
||||
for (int y = 0; y < iNewHeight; ++y)
|
||||
{
|
||||
yFractioned = y * yFactor;
|
||||
yFloor = (int)floor_tpl(yFractioned);
|
||||
yCeil = yFloor + 1;
|
||||
|
||||
yFraction = yFractioned - yFloor;
|
||||
oneMinusY = 1.0f - yFraction;
|
||||
|
||||
yNewOffset = y * iDestBufferWidth;
|
||||
|
||||
yFloor += iSrcY;
|
||||
yCeil += iSrcY;
|
||||
|
||||
if (yCeil >= m_iHeight)
|
||||
{
|
||||
yCeil = yFloor;
|
||||
}
|
||||
|
||||
for (int x = 0; x < iNewWidth; ++x)
|
||||
{
|
||||
xFractioned = x * xFactor;
|
||||
xFloor = (int)floor_tpl(xFractioned);
|
||||
xCeil = xFloor + 1;
|
||||
|
||||
xFraction = xFractioned - xFloor;
|
||||
oneMinusX = 1.0f - xFraction;
|
||||
|
||||
xFloor += iSrcY;
|
||||
xCeil += iSrcY;
|
||||
|
||||
if (xCeil >= m_iWidth)
|
||||
{
|
||||
xCeil = xFloor;
|
||||
}
|
||||
|
||||
c0 = m_pBuffer[yFloor * m_iWidth + xFloor];
|
||||
c1 = m_pBuffer[yFloor * m_iWidth + xCeil];
|
||||
c2 = m_pBuffer[yCeil * m_iWidth + xFloor];
|
||||
c3 = m_pBuffer[yCeil * m_iWidth + xCeil];
|
||||
|
||||
fR0 = (oneMinusX * c0 + xFraction * c1);
|
||||
fR1 = (oneMinusX * c2 + xFraction * c3);
|
||||
|
||||
cColor = (unsigned char)((oneMinusY * fR0) + (yFraction * fR1));
|
||||
|
||||
pNewBuffer[yNewOffset + x + iDestX] = 0xffffff | (cColor << 24);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#if defined(__GNUC__)
|
||||
#if __GNUC__ >= 4 && __GNUC__MINOR__ < 7
|
||||
#pragma GCC diagnostic error "-Woverflow"
|
||||
#endif
|
||||
#endif
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Purpose : Hold a glyph bitmap and blit it to the main texture
|
||||
|
||||
#ifndef CRYINCLUDE_CRYFONT_GLYPHBITMAP_H
|
||||
#define CRYINCLUDE_CRYFONT_GLYPHBITMAP_H
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
class CGlyphBitmap
|
||||
{
|
||||
public:
|
||||
CGlyphBitmap();
|
||||
~CGlyphBitmap();
|
||||
|
||||
int Create(int iWidth, int iHeight);
|
||||
int Release();
|
||||
|
||||
unsigned char* GetBuffer() { return m_pBuffer; };
|
||||
|
||||
int Blur(int iIterations);
|
||||
int Scale(float fScaleX, float fScaleY);
|
||||
|
||||
int Clear();
|
||||
|
||||
int BlitTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth);
|
||||
int BlitTo32(unsigned int* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth);
|
||||
|
||||
int BlitScaledTo8(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth);
|
||||
int BlitScaledTo32(unsigned char* pBuffer, int iSrcX, int iSrcY, int iSrcWidth, int iSrcHeight, int iDestX, int iDestY, int iDestWidth, int iDestHeight, int iDestBufferWidth);
|
||||
|
||||
int GetWidth() { return m_iWidth; }
|
||||
int GetHeight() { return m_iHeight; }
|
||||
|
||||
void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
pSizer->AddObject(m_pBuffer, m_iWidth * m_iHeight);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
unsigned char* m_pBuffer;
|
||||
int m_iWidth;
|
||||
int m_iHeight;
|
||||
};
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_GLYPHBITMAP_H
|
||||
@@ -1,433 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Purpose:
|
||||
// - Manage and cache glyphs, retrieving them from the renderer as needed
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include "GlyphCache.h"
|
||||
#include "FontTexture.h"
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CGlyphCache::CGlyphCache()
|
||||
: m_dwUsage(1)
|
||||
, m_iGlyphBitmapWidth(0)
|
||||
, m_iGlyphBitmapHeight(0)
|
||||
, m_pScaleBitmap(0)
|
||||
{
|
||||
m_pCacheTable.clear();
|
||||
m_pSlotList.clear();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CGlyphCache::~CGlyphCache()
|
||||
{
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio)
|
||||
{
|
||||
m_iSmoothMethod = iSmoothMethod;
|
||||
m_iSmoothAmount = iSmoothAmount;
|
||||
|
||||
m_iGlyphBitmapWidth = iGlyphBitmapWidth;
|
||||
m_iGlyphBitmapHeight = iGlyphBitmapHeight;
|
||||
|
||||
|
||||
if (!CreateSlotList(iCacheSize))
|
||||
{
|
||||
ReleaseSlotList();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iScaledGlyphWidth = 0;
|
||||
int iScaledGlyphHeight = 0;
|
||||
|
||||
switch (m_iSmoothMethod)
|
||||
{
|
||||
case FONT_SMOOTH_SUPERSAMPLE:
|
||||
{
|
||||
switch (m_iSmoothAmount)
|
||||
{
|
||||
case FONT_SMOOTH_AMOUNT_2X:
|
||||
iScaledGlyphWidth = m_iGlyphBitmapWidth << 1;
|
||||
iScaledGlyphHeight = m_iGlyphBitmapHeight << 1;
|
||||
break;
|
||||
case FONT_SMOOTH_AMOUNT_4X:
|
||||
iScaledGlyphWidth = m_iGlyphBitmapWidth << 2;
|
||||
iScaledGlyphHeight = m_iGlyphBitmapHeight << 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (iScaledGlyphWidth)
|
||||
{
|
||||
m_pScaleBitmap = new CGlyphBitmap;
|
||||
|
||||
if (!m_pScaleBitmap)
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!m_pScaleBitmap->Create(iScaledGlyphWidth, iScaledGlyphHeight))
|
||||
{
|
||||
Release();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_pFontRenderer.SetGlyphBitmapSize(iScaledGlyphWidth, iScaledGlyphHeight, sizeRatio);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pFontRenderer.SetGlyphBitmapSize(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight, sizeRatio);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::Release()
|
||||
{
|
||||
ReleaseSlotList();
|
||||
|
||||
m_pCacheTable.clear();
|
||||
|
||||
if (m_pScaleBitmap)
|
||||
{
|
||||
m_pScaleBitmap->Release();
|
||||
|
||||
delete m_pScaleBitmap;
|
||||
|
||||
m_pScaleBitmap = 0;
|
||||
}
|
||||
|
||||
m_iGlyphBitmapWidth = 0;
|
||||
m_iGlyphBitmapHeight = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::LoadFontFromFile(const string& szFileName)
|
||||
{
|
||||
return m_pFontRenderer.LoadFromFile(szFileName);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize)
|
||||
{
|
||||
return m_pFontRenderer.LoadFromMemory(pFileBuffer, iDataSize);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::ReleaseFont()
|
||||
{
|
||||
m_pFontRenderer.Release();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::GetGlyphBitmapSize(int* pWidth, int* pHeight)
|
||||
{
|
||||
if (pWidth)
|
||||
{
|
||||
*pWidth = m_iGlyphBitmapWidth;
|
||||
}
|
||||
|
||||
if (pHeight)
|
||||
{
|
||||
*pHeight = m_iGlyphBitmapWidth;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
void CGlyphCache::SetGlyphBitmapSize(int width, int height, float sizeRatio)
|
||||
{
|
||||
m_pFontRenderer.SetGlyphBitmapSize(width, height, sizeRatio);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams)
|
||||
{
|
||||
CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize));
|
||||
|
||||
if (pItor != m_pCacheTable.end())
|
||||
{
|
||||
pItor->second->dwUsage = m_dwUsage;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
CCacheSlot* pSlot = GetLRUSlot();
|
||||
|
||||
if (!pSlot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pSlot->dwUsage > 0)
|
||||
{
|
||||
UnCacheGlyph(pSlot->cCurrentChar, pSlot->glyphSize);
|
||||
}
|
||||
|
||||
if (m_pScaleBitmap)
|
||||
{
|
||||
int iOffsetMult = 1;
|
||||
|
||||
switch (m_iSmoothAmount)
|
||||
{
|
||||
case FONT_SMOOTH_AMOUNT_2X:
|
||||
iOffsetMult = 2;
|
||||
break;
|
||||
case FONT_SMOOTH_AMOUNT_4X:
|
||||
iOffsetMult = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
m_pScaleBitmap->Clear();
|
||||
|
||||
if (!m_pFontRenderer.GetGlyph(m_pScaleBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pSlot->iCharWidth >>= iOffsetMult >> 1;
|
||||
pSlot->iCharHeight >>= iOffsetMult >> 1;
|
||||
|
||||
m_pScaleBitmap->BlitScaledTo8(pSlot->pGlyphBitmap.GetBuffer(), 0, 0, m_pScaleBitmap->GetWidth(), m_pScaleBitmap->GetHeight(), 0, 0, pSlot->pGlyphBitmap.GetWidth(), pSlot->pGlyphBitmap.GetHeight(), pSlot->pGlyphBitmap.GetWidth());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_pFontRenderer.GetGlyph(&pSlot->pGlyphBitmap, &pSlot->iHoriAdvance, &pSlot->iCharWidth, &pSlot->iCharHeight, pSlot->iCharOffsetX, pSlot->iCharOffsetY, 0, 0, cChar, fontHintParams))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_iSmoothMethod == FONT_SMOOTH_BLUR)
|
||||
{
|
||||
pSlot->pGlyphBitmap.Blur(m_iSmoothAmount);
|
||||
}
|
||||
|
||||
pSlot->dwUsage = m_dwUsage;
|
||||
pSlot->cCurrentChar = cChar;
|
||||
pSlot->glyphSize = glyphSize;
|
||||
|
||||
m_pCacheTable.insert(AZStd::pair<CryFont::GlyphCache::CCacheTableKey, CCacheSlot*>(GetCacheSlotKey(cChar, glyphSize), pSlot));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CGlyphCache::UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize)
|
||||
{
|
||||
CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize));
|
||||
|
||||
if (pItor != m_pCacheTable.end())
|
||||
{
|
||||
CCacheSlot* pSlot = pItor->second;
|
||||
|
||||
pSlot->Reset();
|
||||
|
||||
m_pCacheTable.erase(pItor);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::GlyphCached(uint32 cChar, const Vec2i& glyphSize)
|
||||
{
|
||||
return (m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize)) != m_pCacheTable.end());
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CCacheSlot* CGlyphCache::GetLRUSlot()
|
||||
{
|
||||
unsigned int dwMinUsage = 0xffffffff;
|
||||
CCacheSlot* pLRUSlot = 0;
|
||||
CCacheSlot* pSlot;
|
||||
|
||||
CCacheSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
pSlot = *pItor;
|
||||
|
||||
if (pSlot->dwUsage == 0)
|
||||
{
|
||||
return pSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pSlot->dwUsage < dwMinUsage)
|
||||
{
|
||||
pLRUSlot = pSlot;
|
||||
dwMinUsage = pSlot->dwUsage;
|
||||
}
|
||||
}
|
||||
|
||||
pItor++;
|
||||
}
|
||||
|
||||
return pLRUSlot;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CCacheSlot* CGlyphCache::GetMRUSlot()
|
||||
{
|
||||
unsigned int dwMaxUsage = 0;
|
||||
CCacheSlot* pMRUSlot = 0;
|
||||
CCacheSlot* pSlot;
|
||||
|
||||
CCacheSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
pSlot = *pItor;
|
||||
|
||||
if (pSlot->dwUsage != 0)
|
||||
{
|
||||
if (pSlot->dwUsage > dwMaxUsage)
|
||||
{
|
||||
pMRUSlot = pSlot;
|
||||
dwMaxUsage = pSlot->dwUsage;
|
||||
}
|
||||
}
|
||||
|
||||
pItor++;
|
||||
}
|
||||
|
||||
return pMRUSlot;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize, const CFFont::FontHintParams& fontHintParams)
|
||||
{
|
||||
CCacheTable::iterator pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize));
|
||||
|
||||
if (pItor == m_pCacheTable.end())
|
||||
{
|
||||
if (!PreCacheGlyph(cChar, glyphSize, fontHintParams))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
pItor = m_pCacheTable.find(GetCacheSlotKey(cChar, glyphSize));
|
||||
|
||||
pItor->second->dwUsage = m_dwUsage++;
|
||||
(*pGlyph) = &pItor->second->pGlyphBitmap;
|
||||
|
||||
if (piHoriAdvance)
|
||||
{
|
||||
*piHoriAdvance = pItor->second->iHoriAdvance;
|
||||
}
|
||||
|
||||
if (piWidth)
|
||||
{
|
||||
*piWidth = pItor->second->iCharWidth;
|
||||
}
|
||||
|
||||
if (piHeight)
|
||||
{
|
||||
*piHeight = pItor->second->iCharHeight;
|
||||
}
|
||||
|
||||
iCharOffsetX = pItor->second->iCharOffsetX;
|
||||
iCharOffsetY = pItor->second->iCharOffsetY;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
Vec2 CGlyphCache::GetKerning(uint32_t leftGlyph, uint32_t rightGlyph)
|
||||
{
|
||||
return m_pFontRenderer.GetKerning(leftGlyph, rightGlyph);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
float CGlyphCache::GetAscenderToHeightRatio()
|
||||
{
|
||||
return m_pFontRenderer.GetAscenderToHeightRatio();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::CreateSlotList(int iListSize)
|
||||
{
|
||||
for (int i = 0; i < iListSize; i++)
|
||||
{
|
||||
CCacheSlot* pCacheSlot = new CCacheSlot;
|
||||
|
||||
if (!pCacheSlot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!pCacheSlot->pGlyphBitmap.Create(m_iGlyphBitmapWidth, m_iGlyphBitmapHeight))
|
||||
{
|
||||
delete pCacheSlot;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCacheSlot->Reset();
|
||||
|
||||
pCacheSlot->iCacheSlot = i;
|
||||
|
||||
m_pSlotList.push_back(pCacheSlot);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
int CGlyphCache::ReleaseSlotList()
|
||||
{
|
||||
CCacheSlotListItor pItor = m_pSlotList.begin();
|
||||
|
||||
while (pItor != m_pSlotList.end())
|
||||
{
|
||||
(*pItor)->pGlyphBitmap.Release();
|
||||
|
||||
delete (*pItor);
|
||||
|
||||
pItor = m_pSlotList.erase(pItor);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------
|
||||
CryFont::GlyphCache::CCacheTableKey CGlyphCache::GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize) const
|
||||
{
|
||||
const Vec2i clampedGlyphSize = CFontTexture::ClampGlyphSize(glyphSize, m_iGlyphBitmapWidth, m_iGlyphBitmapHeight);
|
||||
return CryFont::GlyphCache::CCacheTableKey(clampedGlyphSize, cChar);
|
||||
}
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
@@ -1,200 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
// Purpose:
|
||||
// - Manage and cache glyphs, retrieving them from the renderer as needed
|
||||
|
||||
#ifndef CRYINCLUDE_CRYFONT_GLYPHCACHE_H
|
||||
#define CRYINCLUDE_CRYFONT_GLYPHCACHE_H
|
||||
#pragma once
|
||||
|
||||
#if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#include <vector>
|
||||
#include "GlyphBitmap.h"
|
||||
#include "FontRenderer.h"
|
||||
#include "CryFont.h"
|
||||
#include <StlUtils.h>
|
||||
|
||||
//! Glyph cache slots store the bitmap buffer and glyph metadata from FreeType.
|
||||
//!
|
||||
//! This bitmap buffer is eventually copied to a CFontTexture texture buffer.
|
||||
//! A glyph cache slot bitmap buffer only holds a single glyph, whereas the
|
||||
//! CFontTexture stores multiple glyphs in a grid (row/col) format.
|
||||
typedef struct CCacheSlot
|
||||
{
|
||||
Vec2i glyphSize = CCryFont::defaultGlyphSize; //!< The render resolution of the glyph in the glyph bitmap
|
||||
unsigned int dwUsage;
|
||||
int iCacheSlot;
|
||||
int iHoriAdvance; //!< Advance width. See FT_Glyph_Metrics::horiAdvance.
|
||||
uint32 cCurrentChar;
|
||||
|
||||
uint8 iCharWidth; //!< Glyph width (in pixel)
|
||||
uint8 iCharHeight; //!< Glyph height (in pixel)
|
||||
AZ::s32 iCharOffsetX; //!< Glyph's left-side bearing (in pixels). See FT_GlyphSlotRec::bitmap_left.
|
||||
AZ::s32 iCharOffsetY; //!< Glyph's top bearing (in pixels). See FT_GlyphSlotRec::bitmap_top.
|
||||
|
||||
CGlyphBitmap pGlyphBitmap; //!< Contains a buffer storing a copy of the glyph from FreeType
|
||||
|
||||
void Reset()
|
||||
{
|
||||
dwUsage = 0;
|
||||
cCurrentChar = ~0;
|
||||
|
||||
iCharWidth = 0;
|
||||
iCharHeight = 0;
|
||||
iCharOffsetX = 0;
|
||||
iCharOffsetY = 0;
|
||||
|
||||
pGlyphBitmap.Clear();
|
||||
}
|
||||
|
||||
void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
pSizer->AddObject(this, sizeof(*this));
|
||||
pSizer->AddObject(pGlyphBitmap);
|
||||
}
|
||||
} CCacheSlot;
|
||||
|
||||
namespace CryFont
|
||||
{
|
||||
namespace GlyphCache
|
||||
{
|
||||
//! Height and width pair for glyph size mapping
|
||||
typedef Vec2i CCacheTableGlyphSizeType;
|
||||
|
||||
//! Pair for mapping a height and width size to a UTF32 character/glyph
|
||||
typedef AZStd::pair<CCacheTableGlyphSizeType, uint32> CCacheTableKey;
|
||||
|
||||
//! Hasher for glyph cache table keys (glyphsize-char code pair)
|
||||
//!
|
||||
//! Instead of creating our own custom hash, the types are broken down to their
|
||||
//! native types (ints) and passed to existing hashes that handle those types.
|
||||
struct HashGlyphCacheTableKey
|
||||
{
|
||||
typedef CCacheTableKey ArgumentType;
|
||||
typedef AZStd::size_t ResultType;
|
||||
typedef AZStd::pair<int32, int32> Int32Pair;
|
||||
typedef AZStd::pair<Int32Pair, uint32> Int32PairU32Pair;
|
||||
ResultType operator()(const ArgumentType& value) const
|
||||
{
|
||||
AZStd::hash<Int32PairU32Pair> pairHash;
|
||||
return pairHash(Int32PairU32Pair(Int32Pair(value.first.x, value.first.y), value.second));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//! Maps size-speicifc UTF32 glyphs to their corresponding cache slots
|
||||
typedef AZStd::unordered_map<CryFont::GlyphCache::CCacheTableKey, CCacheSlot*, CryFont::GlyphCache::HashGlyphCacheTableKey> CCacheTable;
|
||||
|
||||
typedef std::vector<CCacheSlot*> CCacheSlotList;
|
||||
typedef std::vector<CCacheSlot*>::iterator CCacheSlotListItor;
|
||||
|
||||
|
||||
#ifdef WIN64
|
||||
#undef GetCharWidth
|
||||
#undef GetCharHeight
|
||||
#endif
|
||||
|
||||
//! The glyph cache maps UTF32 codepoints to their corresponding FreeType data.
|
||||
//!
|
||||
//! This cache is used to associate font glyph info (read from FreeType) with
|
||||
//! UTF32 codepoints. Ultimately the glyph info will be read into a font texture
|
||||
//! (CFontTexture) to avoid future FreeType lookups.
|
||||
//!
|
||||
//! If a CFontTexture is missing a glyph that is currently stored in the glyph
|
||||
//! cache, the cached data can be returned instead of having to be rendered from
|
||||
//! FreeType again.
|
||||
//!
|
||||
//! \sa CFontTexture
|
||||
class CGlyphCache
|
||||
{
|
||||
public:
|
||||
CGlyphCache();
|
||||
~CGlyphCache();
|
||||
|
||||
int Create(int iCacheSize, int iGlyphBitmapWidth, int iGlyphBitmapHeight, int iSmoothMethod, int iSmoothAmount, float sizeRatio);
|
||||
int Release();
|
||||
|
||||
int LoadFontFromFile(const string& szFileName);
|
||||
int LoadFontFromMemory(unsigned char* pFileBuffer, int iDataSize);
|
||||
int ReleaseFont();
|
||||
|
||||
int SetEncoding(FT_Encoding pEncoding) { return m_pFontRenderer.SetEncoding(pEncoding); };
|
||||
FT_Encoding GetEncoding() { return m_pFontRenderer.GetEncoding(); };
|
||||
|
||||
int GetGlyphBitmapSize(int* pWidth, int* pHeight);
|
||||
void SetGlyphBitmapSize(int width, int height, float sizeRatio);
|
||||
|
||||
int PreCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams());
|
||||
int UnCacheGlyph(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize);
|
||||
int GlyphCached(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize);
|
||||
|
||||
CCacheSlot* GetLRUSlot();
|
||||
CCacheSlot* GetMRUSlot();
|
||||
|
||||
//! Obtains glyph information for the given UTF32 codepoint.
|
||||
//! This information is obtained from a CCacheSlot that corresponds to
|
||||
//! the given codepoint. If the codepoint doesn't exist within the cache
|
||||
//! table (m_pCacheTable), then the information is obtain from FreeType
|
||||
//! directly via CFontRenderer.
|
||||
//!
|
||||
//! Ultimately the glyph bitmap is copied into a font texture
|
||||
//! (CFontTexture). Once the glyph is copied into the font texture then
|
||||
//! the font texture is referenced directly rather than relying on the
|
||||
//! glyph cache or FreeType.
|
||||
//!
|
||||
//! \sa CFontRenderer::GetGlyph, CFontTexture::UpdateSlot
|
||||
int GetGlyph(CGlyphBitmap** pGlyph, int* piHoriAdvance, int* piWidth, int* piHeight, AZ::s32& iCharOffsetX, AZ::s32& iCharOffsetY, uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize, const CFFont::FontHintParams& glyphFlags = CFFont::FontHintParams());
|
||||
|
||||
void GetMemoryUsage(ICrySizer* pSizer) const
|
||||
{
|
||||
pSizer->AddObject(m_pSlotList);
|
||||
//pSizer->AddContainer(m_pCacheTable);
|
||||
pSizer->AddObject(m_pScaleBitmap);
|
||||
pSizer->AddObject(m_pFontRenderer);
|
||||
}
|
||||
|
||||
bool GetMonospaced() const { return m_pFontRenderer.GetMonospaced(); }
|
||||
|
||||
Vec2 GetKerning(uint32_t leftGlyph, uint32_t rightGlyph);
|
||||
|
||||
float GetAscenderToHeightRatio();
|
||||
|
||||
private:
|
||||
|
||||
//! Returns a key for the cache table where the given char is mapped at the given size.
|
||||
CryFont::GlyphCache::CCacheTableKey GetCacheSlotKey(uint32 cChar, const Vec2i& glyphSize = CCryFont::defaultGlyphSize) const;
|
||||
|
||||
int CreateSlotList(int iListSize);
|
||||
int ReleaseSlotList();
|
||||
|
||||
CCacheSlotList m_pSlotList;
|
||||
CCacheTable m_pCacheTable;
|
||||
|
||||
int m_iGlyphBitmapWidth;
|
||||
int m_iGlyphBitmapHeight;
|
||||
|
||||
int m_iSmoothMethod;
|
||||
int m_iSmoothAmount;
|
||||
|
||||
CGlyphBitmap* m_pScaleBitmap;
|
||||
|
||||
CFontRenderer m_pFontRenderer;
|
||||
|
||||
unsigned int m_dwUsage;
|
||||
};
|
||||
|
||||
#endif // #if !defined(USE_NULLFONT_ALWAYS)
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_GLYPHCACHE_H
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Create the font interface.
|
||||
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#include <IEngineModule.h>
|
||||
#include <CryExtension/ICryFactory.h>
|
||||
#include <CryExtension/Impl/ClassWeaver.h>
|
||||
|
||||
#include "CryFont.h"
|
||||
#if defined(USE_NULLFONT)
|
||||
#include "NullFont.h"
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
struct CSystemEventListner_Font
|
||||
: public ISystemEventListener
|
||||
{
|
||||
public:
|
||||
virtual void OnSystemEvent(ESystemEvent event, [[maybe_unused]] UINT_PTR wparam, [[maybe_unused]] UINT_PTR lparam)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case ESYSTEM_EVENT_LEVEL_POST_UNLOAD:
|
||||
{
|
||||
STLALLOCATOR_CLEANUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
static CSystemEventListner_Font g_system_event_listener_font;
|
||||
|
||||
///////////////////////////////////////////////
|
||||
extern "C" ICryFont * CreateCryFontInterface(ISystem * pSystem)
|
||||
{
|
||||
ModuleInitISystem(pSystem, "CryFont");
|
||||
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
#if defined(USE_NULLFONT)
|
||||
return new CCryNullFont();
|
||||
#else
|
||||
// The NULL font implementation must be present for all platforms
|
||||
// supporting running as a pure dedicated server.
|
||||
pSystem->GetILog()->LogError("Missing NULL font implementation for dedicated server");
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(USE_NULLFONT) && defined(USE_NULLFONT_ALWAYS)
|
||||
return new CCryNullFont();
|
||||
#else
|
||||
pSystem->GetISystemEventDispatcher()->RegisterListener(&g_system_event_listener_font);
|
||||
return new CCryFont(pSystem);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
class CEngineModule_CryFont
|
||||
: public IEngineModule
|
||||
{
|
||||
CRYINTERFACE_SIMPLE(IEngineModule)
|
||||
CRYGENERATE_SINGLETONCLASS(CEngineModule_CryFont, "EngineModule_CryFont", 0x6758643f43214957, 0x9b920d898d31f434)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual const char* GetName() const {
|
||||
return "CryFont";
|
||||
};
|
||||
virtual const char* GetCategory() const { return "CryEngine"; };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
virtual bool Initialize(SSystemGlobalEnvironment& env, [[maybe_unused]] const SSystemInitParams& initParams)
|
||||
{
|
||||
ISystem* pSystem = env.pSystem;
|
||||
env.pCryFont = CreateCryFontInterface(pSystem);
|
||||
return env.pCryFont != 0;
|
||||
}
|
||||
};
|
||||
|
||||
CRYREGISTER_SINGLETON_CLASS(CEngineModule_CryFont)
|
||||
|
||||
CEngineModule_CryFont::CEngineModule_CryFont()
|
||||
{
|
||||
};
|
||||
|
||||
CEngineModule_CryFont::~CEngineModule_CryFont()
|
||||
{
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Dummy font implementation (dedicated server)
|
||||
|
||||
#include "CryFont_precompiled.h"
|
||||
|
||||
#if defined(USE_NULLFONT)
|
||||
|
||||
#include "NullFont.h"
|
||||
|
||||
CNullFont CCryNullFont::ms_nullFont;
|
||||
|
||||
#endif // USE_NULLFONT
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Dummy font implementation (dedicated server)
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYFONT_NULLFONT_H
|
||||
#define CRYINCLUDE_CRYFONT_NULLFONT_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#if defined(USE_NULLFONT)
|
||||
|
||||
#include <IFont.h>
|
||||
|
||||
class CNullFont
|
||||
: public IFFont
|
||||
{
|
||||
public:
|
||||
CNullFont() {}
|
||||
virtual ~CNullFont() {}
|
||||
|
||||
virtual int32 AddRef() { return 0; };
|
||||
virtual int32 Release() { return 0; };
|
||||
|
||||
virtual bool Load([[maybe_unused]] const char* pFontFilePath, [[maybe_unused]] unsigned int width, [[maybe_unused]] unsigned int height, [[maybe_unused]] unsigned int widthNumSlots, [[maybe_unused]] unsigned int heightNumSlots, [[maybe_unused]] unsigned int flags, [[maybe_unused]] float sizeRatio) { return true; }
|
||||
virtual bool Load([[maybe_unused]] const char* pXMLFile) { return true; }
|
||||
virtual void Free() {}
|
||||
|
||||
virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {}
|
||||
virtual void DrawString([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {}
|
||||
|
||||
virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {}
|
||||
virtual void DrawStringW([[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) {}
|
||||
|
||||
virtual Vec2 GetTextSize([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); }
|
||||
virtual Vec2 GetTextSizeW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return Vec2(0.0f, 0.0f); }
|
||||
|
||||
virtual size_t GetTextLength([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; }
|
||||
virtual size_t GetTextLengthW([[maybe_unused]] const wchar_t* pStr, [[maybe_unused]] const bool asciiMultiLine) const { return 0; }
|
||||
|
||||
virtual void WrapText(string& result, [[maybe_unused]] float maxWidth, const char* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; }
|
||||
virtual void WrapTextW(wstring& result, [[maybe_unused]] float maxWidth, const wchar_t* pStr, [[maybe_unused]] const STextDrawContext& ctx) { result = pStr; }
|
||||
|
||||
virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
||||
|
||||
virtual void GetGradientTextureCoord([[maybe_unused]] float& minU, [[maybe_unused]] float& minV, [[maybe_unused]] float& maxU, [[maybe_unused]] float& maxV) const {}
|
||||
|
||||
virtual unsigned int GetEffectId([[maybe_unused]] const char* pEffectName) const { return 0; }
|
||||
virtual unsigned int GetNumEffects() const { return 0; }
|
||||
virtual const char* GetEffectName([[maybe_unused]] unsigned int effectId) const { return nullptr; }
|
||||
virtual Vec2 GetMaxEffectOffset([[maybe_unused]] unsigned int effectId) const { return Vec2(); }
|
||||
virtual bool DoesEffectHaveTransparency([[maybe_unused]] unsigned int effectId) const { return false; }
|
||||
|
||||
virtual void AddCharsToFontTexture([[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {}
|
||||
virtual Vec2 GetKerning([[maybe_unused]] uint32_t leftGlyph, [[maybe_unused]] uint32_t rightGlyph, [[maybe_unused]] const STextDrawContext& ctx) const override { return Vec2(); }
|
||||
virtual float GetAscender([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; }
|
||||
virtual float GetBaseline([[maybe_unused]] const STextDrawContext& ctx) const override { return 0.0f; }
|
||||
virtual float GetSizeRatio() const override { return IFFontConstants::defaultSizeRatio; }
|
||||
virtual uint32 GetNumQuadsForText([[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; }
|
||||
virtual uint32 WriteTextQuadsToBuffers([[maybe_unused]] SVF_P2F_C4B_T2F_F4B* verts, [[maybe_unused]] uint16* indices, [[maybe_unused]] uint32 maxQuads, [[maybe_unused]] float x, [[maybe_unused]] float y, [[maybe_unused]] float z, [[maybe_unused]] const char* pStr, [[maybe_unused]] const bool asciiMultiLine, [[maybe_unused]] const STextDrawContext& ctx) { return 0; }
|
||||
virtual int GetFontTextureId() { return -1; }
|
||||
virtual uint32 GetFontTextureVersion() { return 0; }
|
||||
};
|
||||
|
||||
class CCryNullFont
|
||||
: public ICryFont
|
||||
{
|
||||
public:
|
||||
virtual void Release() {}
|
||||
virtual IFFont* NewFont([[maybe_unused]] const char* pFontName) { return &ms_nullFont; }
|
||||
virtual IFFont* GetFont([[maybe_unused]] const char* pFontName) const { return &ms_nullFont; }
|
||||
virtual FontFamilyPtr LoadFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; }
|
||||
virtual FontFamilyPtr GetFontFamily([[maybe_unused]] const char* pFontFamilyName) override { CRY_ASSERT(false); return nullptr; }
|
||||
virtual void AddCharsToFontTextures(FontFamilyPtr pFontFamily, [[maybe_unused]] const char* pChars, [[maybe_unused]] int glyphSizeX, [[maybe_unused]] int glyphSizeY) override {};
|
||||
virtual void SetRendererProperties([[maybe_unused]] IRenderer* pRenderer) {}
|
||||
virtual void GetMemoryUsage([[maybe_unused]] ICrySizer* pSizer) const {}
|
||||
virtual string GetLoadedFontNames() const { return ""; }
|
||||
virtual void OnLanguageChanged() override { }
|
||||
virtual void ReloadAllFonts() override { }
|
||||
|
||||
private:
|
||||
static CNullFont ms_nullFont;
|
||||
};
|
||||
|
||||
#endif // USE_NULLFONT
|
||||
|
||||
#endif // CRYINCLUDE_CRYFONT_NULLFONT_H
|
||||
@@ -1,16 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
# Platform specific cmake file for configuring target compiler/link properties
|
||||
# based on the active platform
|
||||
# NOTE: functions in cmake are global, therefore adding functions to this file
|
||||
# is being avoided to prevent overriding functions declared in other targets platfrom
|
||||
# specific cmake files
|
||||
@@ -1,33 +0,0 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
CryFont.cpp
|
||||
FFont.cpp
|
||||
FFontXML.cpp
|
||||
FontRenderer.cpp
|
||||
FontTexture.cpp
|
||||
GlyphBitmap.cpp
|
||||
GlyphCache.cpp
|
||||
ICryFont.cpp
|
||||
NullFont.cpp
|
||||
CryFont.h
|
||||
FBitmap.h
|
||||
FFont.h
|
||||
FontRenderer.h
|
||||
FontTexture.h
|
||||
GlyphBitmap.h
|
||||
GlyphCache.h
|
||||
NullFont.h
|
||||
resource.h
|
||||
CryFont_precompiled.h
|
||||
CryFont_precompiled.cpp
|
||||
)
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
#define VS_VERSION_INFO 1
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -90,8 +90,6 @@ ly_add_target(
|
||||
AZ::AzCore
|
||||
Legacy::CryCommon
|
||||
Legacy::CryCommon.EngineSettings.Static
|
||||
RUNTIME_DEPENDENCIES
|
||||
Legacy::CryFont
|
||||
)
|
||||
|
||||
################################################################################
|
||||
|
||||
@@ -52,11 +52,7 @@
|
||||
# define cpuid(op, eax, ebx, ecx, edx) __asm__("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (op) : "cc");
|
||||
#endif
|
||||
|
||||
#if defined(AZ_MONOLITHIC_BUILD)
|
||||
extern int g_CpuFlags;
|
||||
#else
|
||||
int g_CpuFlags;
|
||||
#endif
|
||||
|
||||
struct SAutoMaxPriority
|
||||
{
|
||||
|
||||
@@ -102,7 +102,6 @@ inline int RoundToClosestMB(size_t memSize)
|
||||
#include <IRenderer.h>
|
||||
#include <CryFile.h>
|
||||
#include <ISystem.h>
|
||||
#include <I3DEngine.h>
|
||||
#include <ITimer.h>
|
||||
#include <IPhysics.h>
|
||||
#include <IXml.h>
|
||||
@@ -127,7 +126,6 @@ namespace AZ::IO
|
||||
struct IArchive;
|
||||
}
|
||||
struct ICryFont;
|
||||
struct I3DEngine;
|
||||
struct IMovieSystem;
|
||||
struct IAudioSystem;
|
||||
struct IPhysicalWorld;
|
||||
|
||||
@@ -193,10 +193,6 @@ static void UnloadMap([[maybe_unused]] IConsoleCmdArgs* args)
|
||||
if (gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
|
||||
{
|
||||
gEnv->pSystem->GetILevelSystem()->UnloadLevel();
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->LoadEmptyLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,18 +670,6 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName)
|
||||
pSpamDelay->Set(0.0f);
|
||||
}
|
||||
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
bool is3DEngineLoaded = gEnv->IsEditor() ? gEnv->p3DEngine->InitLevelForEditor(pLevelInfo->GetPath(), pLevelInfo->m_defaultGameTypeName.c_str())
|
||||
: gEnv->p3DEngine->LoadLevel(pLevelInfo->GetPath(), pLevelInfo->m_defaultGameTypeName.c_str());
|
||||
if (!is3DEngineLoaded)
|
||||
{
|
||||
OnLoadingError(levelName, "3DEngine failed to handle loading the level");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse level specific config data.
|
||||
AZStd::string const sLevelNameOnly(PathUtil::GetFileName(levelName));
|
||||
|
||||
@@ -760,14 +744,6 @@ ILevel* CLevelSystem::LoadLevelInternal(const char* _levelName)
|
||||
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PRECACHE);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Notify 3D engine that loading finished
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->PostLoadLevel();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
gEnv->pConsole->SetScrollMax(600 / 2);
|
||||
@@ -991,18 +967,6 @@ void CLevelSystem::UnloadLevel()
|
||||
|
||||
CTimeValue tBegin = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
I3DEngine* p3DEngine = gEnv->p3DEngine;
|
||||
if (p3DEngine)
|
||||
{
|
||||
IDeferredPhysicsEventManager* pPhysEventManager = p3DEngine->GetDeferredPhysicsEventManager();
|
||||
if (pPhysEventManager)
|
||||
{
|
||||
// clear deferred physics queues before renderer, since we could have jobs running
|
||||
// which access a rendermesh
|
||||
pPhysEventManager->ClearDeferredEvents();
|
||||
}
|
||||
}
|
||||
|
||||
//AM: Flush render thread (Flush is not exposed - using EndFrame())
|
||||
//We are about to delete resources that could be in use
|
||||
if (gEnv->pRenderer)
|
||||
@@ -1076,25 +1040,10 @@ void CLevelSystem::UnloadLevel()
|
||||
|
||||
SAFE_RELEASE(m_pCurrentLevel);
|
||||
|
||||
/*
|
||||
Force Lua garbage collection before p3DEngine->UnloadLevel() and pRenderer->FreeResources(flags) are called.
|
||||
p3DEngine->UnloadLevel() will destroy particle emitters even if they're still referenced by Lua objects that are yet to be collected.
|
||||
(as per comment in 3dEngineLoad.cpp (line 501) - "Force to clean all particles that are left, even if still referenced.").
|
||||
Then, during the next GC cycle, Lua finally cleans up, the particle emitter smart pointers will be pointing to invalid memory).
|
||||
Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event), which is too late
|
||||
(after the render resources have been purged).
|
||||
This extra GC step takes a few ms more level unload time, which is a small price for fixing nasty crashes.
|
||||
If, however, we wanted to claim it back, we could potentially get rid of the GC step that is triggered by ESYSTEM_EVENT_LEVEL_POST_UNLOAD to break even.
|
||||
*/
|
||||
|
||||
// Force Lua garbage collection (may no longer be needed now the legacy renderer has been removed).
|
||||
// Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event).
|
||||
EBUS_EVENT(AZ::ScriptSystemRequestBus, GarbageCollect);
|
||||
|
||||
// Delete engine resources
|
||||
if (p3DEngine)
|
||||
{
|
||||
p3DEngine->UnloadLevel();
|
||||
|
||||
}
|
||||
// Force to clean render resources left after deleting all objects and materials.
|
||||
IRenderer* pRenderer = gEnv->pRenderer;
|
||||
if (pRenderer)
|
||||
|
||||
@@ -55,10 +55,6 @@ namespace LegacyLevelSystem
|
||||
if (gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor())
|
||||
{
|
||||
gEnv->pSystem->GetILevelSystem()->UnloadLevel();
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->LoadEmptyLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,22 +258,6 @@ namespace LegacyLevelSystem
|
||||
pSpamDelay->Set(0.0f);
|
||||
}
|
||||
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
AZ::IO::PathView levelPath(levelName);
|
||||
AZStd::string parentPath(levelPath.ParentPath().Native());
|
||||
|
||||
static constexpr const char* defaultGameTypeName = "Mission0";
|
||||
bool is3DEngineLoaded = gEnv->IsEditor() ? gEnv->p3DEngine->InitLevelForEditor(parentPath.c_str(), defaultGameTypeName)
|
||||
: gEnv->p3DEngine->LoadLevel(parentPath.c_str(), defaultGameTypeName);
|
||||
if (!is3DEngineLoaded)
|
||||
{
|
||||
OnLoadingError(levelName, "3DEngine failed to handle loading the level");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse level specific config data.
|
||||
AZStd::string const sLevelNameOnly(PathUtil::GetFileName(levelName));
|
||||
|
||||
@@ -340,14 +320,6 @@ namespace LegacyLevelSystem
|
||||
|
||||
gEnv->pSystem->SetSystemGlobalState(ESYSTEM_GLOBAL_STATE_LEVEL_LOAD_START_PRECACHE);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Notify 3D engine that loading finished
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->PostLoadLevel();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
gEnv->pConsole->SetScrollMax(600 / 2);
|
||||
@@ -569,18 +541,6 @@ namespace LegacyLevelSystem
|
||||
|
||||
CTimeValue tBegin = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
I3DEngine* p3DEngine = gEnv->p3DEngine;
|
||||
if (p3DEngine)
|
||||
{
|
||||
IDeferredPhysicsEventManager* pPhysEventManager = p3DEngine->GetDeferredPhysicsEventManager();
|
||||
if (pPhysEventManager)
|
||||
{
|
||||
// clear deferred physics queues before renderer, since we could have jobs running
|
||||
// which access a rendermesh
|
||||
pPhysEventManager->ClearDeferredEvents();
|
||||
}
|
||||
}
|
||||
|
||||
// AM: Flush render thread (Flush is not exposed - using EndFrame())
|
||||
// We are about to delete resources that could be in use
|
||||
if (gEnv->pRenderer)
|
||||
@@ -644,25 +604,10 @@ namespace LegacyLevelSystem
|
||||
|
||||
GetISystem()->GetIResourceManager()->UnloadLevel();
|
||||
|
||||
/*
|
||||
Force Lua garbage collection before p3DEngine->UnloadLevel() and pRenderer->FreeResources(flags) are called.
|
||||
p3DEngine->UnloadLevel() will destroy particle emitters even if they're still referenced by Lua objects that are yet to be
|
||||
collected. (as per comment in 3dEngineLoad.cpp (line 501) - "Force to clean all particles that are left, even if still referenced.").
|
||||
Then, during the next GC cycle, Lua finally cleans up, the particle emitter smart pointers will be pointing to invalid memory).
|
||||
Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event), which is too late
|
||||
(after the render resources have been purged).
|
||||
This extra GC step takes a few ms more level unload time, which is a small price for fixing nasty crashes.
|
||||
If, however, we wanted to claim it back, we could potentially get rid of the GC step that is triggered by
|
||||
ESYSTEM_EVENT_LEVEL_POST_UNLOAD to break even.
|
||||
*/
|
||||
|
||||
// Force Lua garbage collection (may no longer be needed now the legacy renderer has been removed).
|
||||
// Normally the GC step is triggered at the end of this method (by the ESYSTEM_EVENT_LEVEL_POST_UNLOAD event).
|
||||
EBUS_EVENT(AZ::ScriptSystemRequestBus, GarbageCollect);
|
||||
|
||||
// Delete engine resources
|
||||
if (p3DEngine)
|
||||
{
|
||||
p3DEngine->UnloadLevel();
|
||||
}
|
||||
// Force to clean render resources left after deleting all objects and materials.
|
||||
IRenderer* pRenderer = gEnv->pRenderer;
|
||||
if (pRenderer)
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include "MiniGUI/MiniMenu.h"
|
||||
#include "MiniGUI/MiniTable.h"
|
||||
#include <IConsole.h>
|
||||
#include <I3DEngine.h>
|
||||
#include <ITimer.h>
|
||||
#include "System.h"
|
||||
|
||||
@@ -853,21 +852,6 @@ void CPerfHUD::SaveStatsCallback([[maybe_unused]] void* data, [[maybe_unused]] b
|
||||
// RENDER CALLBACKS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
void CPerfHUD::DisplayRenderInfoCallback(const Rect& rect)
|
||||
{
|
||||
IMiniGUIPtr pGUI;
|
||||
if (CryCreateClassInstanceForInterface( cryiidof<IMiniGUI>(),pGUI ))
|
||||
{
|
||||
//right aligned display
|
||||
float x = rect.right;
|
||||
float y = rect.top;
|
||||
float step = 13.f;
|
||||
|
||||
gEnv->p3DEngine->DisplayInfo(x, y, step, true);
|
||||
}
|
||||
}*/
|
||||
|
||||
void CPerfHUD::EnableWidget(ICryPerfHUDWidget::EWidgetID id, int mode)
|
||||
{
|
||||
const int nWidgets = m_widgets.size();
|
||||
@@ -1530,26 +1514,6 @@ void CRenderStatsWidget::Update()
|
||||
m_runtimeData.nFwdLights = 0;
|
||||
m_runtimeData.nFwdShadowLights = 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
I3DEngine::SObjectsStreamingStatus objStats;
|
||||
gEnv->p3DEngine->GetObjectsStreamingStatus(objStats);
|
||||
|
||||
float fMeshRequiredMB = (float)(objStats.nMemRequired) / (1024 * 1024);
|
||||
sprintf_s(entryBuffer, "Mesh Required: %.2f (%dMB)", fMeshRequiredMB, azlossy_cast<int>(objStats.nMeshPoolSize));
|
||||
if (fMeshRequiredMB < objStats.nMeshPoolSize)
|
||||
{
|
||||
m_pInfoBox->AddEntry(entryBuffer, CPerfHUD::COL_NORM, CPerfHUD::TEXT_SIZE_NORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pInfoBox->AddEntry(entryBuffer, CPerfHUD::COL_ERROR, CPerfHUD::TEXT_SIZE_NORM);
|
||||
CryPerfHUDWarning(1.f, "Too Many Geometry: %.2fMB", fMeshRequiredMB);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (gEnv->pRenderer)
|
||||
{
|
||||
@@ -1727,25 +1691,6 @@ CStreamingStatsWidget::CStreamingStatsWidget(IMiniCtrl* pParentMenu, ICryPerfHUD
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CStreamingStatsWidget::Update()
|
||||
{
|
||||
char entryBuffer[CMiniInfoBox::MAX_TEXT_LENGTH] = {0};
|
||||
|
||||
//Clear old entries
|
||||
m_pInfoBox->ClearEntries();
|
||||
|
||||
I3DEngine::SObjectsStreamingStatus objStats;
|
||||
gEnv->p3DEngine->GetObjectsStreamingStatus(objStats);
|
||||
|
||||
float fMeshRequiredMB = (float)(objStats.nMemRequired) / (1024 * 1024);
|
||||
sprintf_s(entryBuffer, "Mesh Required: %.2f (%dMB)", fMeshRequiredMB, objStats.nMeshPoolSize);
|
||||
if (fMeshRequiredMB < objStats.nMeshPoolSize)
|
||||
{
|
||||
m_pInfoBox->AddEntry(entryBuffer, CPerfHUD::COL_NORM, CPerfHUD::TEXT_SIZE_NORM);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pInfoBox->AddEntry(entryBuffer, CPerfHUD::COL_ERROR, CPerfHUD::TEXT_SIZE_NORM);
|
||||
CryPerfHUDWarning(1.f, "Too Many Geometry: %.2fMB", fMeshRequiredMB);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
|
||||
// Description : Visual helper for checking a local memory usage on maps
|
||||
|
||||
|
||||
#ifndef CRYINCLUDE_CRYSYSTEM_STATISTICS_LOCALMEMORYUSAGE_H
|
||||
#define CRYINCLUDE_CRYSYSTEM_STATISTICS_LOCALMEMORYUSAGE_H
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "../CryCommon/Cry_Geo.h"
|
||||
#include "ILocalMemoryUsage.h"
|
||||
#include "TimeValue.h"
|
||||
|
||||
#define LOCALMEMORY_SECTOR_SIZE 32.f //Size of one sector
|
||||
#define LOCALMEMORY_SECTOR_NR_X 128 //4096 / LOCALMEMORY_SECTOR_SIZE Sector number of the world (x)
|
||||
#define LOCALMEMORY_SECTOR_NR_Y 128 //4096 / LOCALMEMORY_SECTOR_SIZE Sector number of the world (y)
|
||||
#define LOCALMEMORY_SECTOR_PER_PASS 128 //4096 / 32 Sector nr for one calculation pass. Now it is the whole world;
|
||||
|
||||
//Sector number must be = LOCALMEMORY_SECTOR_PER_PASS * n
|
||||
|
||||
#define LOCALMEMORY_COLOR_OK 0, 255, 0
|
||||
#define LOCALMEMORY_COLOR_WARNING 255, 255, 0
|
||||
#define LOCALMEMORY_COLOR_ERROR 255, 0, 0
|
||||
#define LOCALMEMORY_COLOR_TEXTURE 0, 0, 255
|
||||
#define LOCALMEMORY_COLOR_GEOMETRY 0, 0, 0
|
||||
#define LOCALMEMORY_COLOR_BLACK 0, 0, 0, 192
|
||||
#define LOCALMEMORY_FCOLOR_OK 0, 1, 0
|
||||
#define LOCALMEMORY_FCOLOR_WARNING 1, 1, 0
|
||||
#define LOCALMEMORY_FCOLOR_ERROR 1, 0, 0
|
||||
#define LOCALMEMORY_FCOLOR_OTHER 0, 0, 1
|
||||
|
||||
struct IMaterial;
|
||||
struct IStatObj;
|
||||
struct IRenderMesh;
|
||||
struct IRenderNode;
|
||||
struct CRenderChunk;
|
||||
class CCamera;
|
||||
|
||||
#include <VectorMap.h>
|
||||
|
||||
struct CLocalMemoryUsage
|
||||
: public ILocalMemoryUsage
|
||||
{
|
||||
private:
|
||||
|
||||
struct STextureInfo;
|
||||
struct SMaterialInfo;
|
||||
struct SStatObjInfo;
|
||||
|
||||
typedef std__hash_map<INT_PTR, STextureInfo > TTextureMap; // Type: hash map of textures
|
||||
typedef std__hash_map<INT_PTR, SMaterialInfo> TMaterialMap; // Type: hash map of materials
|
||||
typedef std__hash_map<INT_PTR, SStatObjInfo > TStatObjMap; // Type: hash map of stat objects
|
||||
|
||||
//*******************
|
||||
|
||||
struct SResource
|
||||
{
|
||||
CLocalMemoryUsage* m_pLocalMemoryUsage; // Inner pointer to the singleton (we can use gEnv->pLocalMemoryUsage with type cast instead this)
|
||||
|
||||
float m_arrMipFactor[LOCALMEMORY_SECTOR_PER_PASS * LOCALMEMORY_SECTOR_PER_PASS]; // Mipmap factor based on minimum distance of the resource from the sector (bounding box distance)
|
||||
bool m_arrRowDirty[LOCALMEMORY_SECTOR_PER_PASS]; // Dirty flag for m_arrMipFactor rows
|
||||
bool m_used;
|
||||
|
||||
static int m_arrMemoryUsage[LOCALMEMORY_SECTOR_PER_PASS]; // Memory usage of the resource in sectors (last row)
|
||||
static int m_arrPieces[LOCALMEMORY_SECTOR_PER_PASS]; // Pieces nr of the resource in sectors (last row)
|
||||
|
||||
virtual void StartChecking(); // Called every frame first
|
||||
void CheckOnAllSectorsP1(const AABB& bounding, float maxViewDist, float viewDistMultiplierForLOD, float mipFactor); // Calculates the minimum of sector bounding vs renderobject bounding distances
|
||||
|
||||
SResource();
|
||||
virtual void Init(CLocalMemoryUsage* pLocalMemoryUsage);
|
||||
//If we will needed a destructor, it must be virtual!
|
||||
};
|
||||
|
||||
//*******************
|
||||
|
||||
struct STextureInfo
|
||||
: public SResource
|
||||
{
|
||||
ITexture* m_pTexture; // Texture pointer
|
||||
//int m_size; // For later use - Used memory
|
||||
//int m_xSize; // For later use - Texture x size
|
||||
//int m_ySize; // For later use - Texture y size
|
||||
//int m_numMips; // For later use - Number of mip maps
|
||||
|
||||
void CheckOnAllSectorsP2(); // Calculate memory usage using distances
|
||||
|
||||
STextureInfo();
|
||||
~STextureInfo();
|
||||
};
|
||||
|
||||
//*******************
|
||||
|
||||
struct STextureInfoAndTilingFactor
|
||||
{
|
||||
STextureInfo* m_pTextureInfo;
|
||||
float m_tilingFactor;
|
||||
};
|
||||
|
||||
typedef std::vector<STextureInfoAndTilingFactor> TTextureVector; // Type: vector of textures
|
||||
|
||||
struct SMaterialInfo
|
||||
: public SResource
|
||||
{
|
||||
//_smart_ptr<IMaterial> m_pMaterial; // For later use
|
||||
TTextureVector m_textures; // Used textures
|
||||
|
||||
SMaterialInfo();
|
||||
|
||||
void AddTextureInfo(STextureInfoAndTilingFactor texture);// Add a new texture (unique)
|
||||
void CheckOnAllSectorsP2(); // Forward distance informations to textures
|
||||
};
|
||||
|
||||
//*******************
|
||||
|
||||
struct SStatObjInfo
|
||||
: public SResource
|
||||
{
|
||||
int m_streamableContentMemoryUsage; // Total streamable memory usage
|
||||
//IStatObj *m_pStatObj; //TODO kiszedni
|
||||
string m_filePath; // The original file name and path of the StatObj
|
||||
bool m_bSubObject; // Is the original StatObj a subobject?
|
||||
/*
|
||||
int m_lodNr; // For later use
|
||||
int m_vertices;
|
||||
int m_meshSize;
|
||||
int m_physProxySize;
|
||||
int m_physPrimitives;
|
||||
int m_indices;
|
||||
int m_indicesPerLod[MAX_LODS];
|
||||
*/
|
||||
|
||||
SStatObjInfo();
|
||||
void CheckOnAllSectorsP2(); // Calculate memory usage using distances
|
||||
};
|
||||
|
||||
//*******************
|
||||
|
||||
struct SSector
|
||||
{
|
||||
SSector();
|
||||
|
||||
void StartChecking(); // Called every frame first
|
||||
|
||||
int m_memoryUsage_Textures; // Sum of texture memory usage
|
||||
|
||||
int m_memoryUsage_Geometry; // Sum of geometry memory usage
|
||||
};
|
||||
|
||||
//*******************
|
||||
PREFAST_SUPPRESS_WARNING(6262);
|
||||
TTextureMap m_globalTextures; // Hash map of resources: textures
|
||||
PREFAST_SUPPRESS_WARNING(6262);
|
||||
TMaterialMap m_globalMaterials; // Hash map of resources: materials
|
||||
PREFAST_SUPPRESS_WARNING(6262);
|
||||
TStatObjMap m_globalStatObjs; // Hash map of resources: stat objects
|
||||
|
||||
ICVar* m_pStreamCgfPredicitionDistance; // Config: additional object distance for streaming
|
||||
ICVar* m_pDebugDraw; // Config: debug draw mode
|
||||
|
||||
int sys_LocalMemoryTextureLimit; // Config: texture limit for streaming
|
||||
int sys_LocalMemoryGeometryLimit; // Config: stat object geometry limit for streaming
|
||||
int sys_LocalMemoryTextureStreamingSpeedLimit; // Config: texture streaming speed limit (approx)
|
||||
int sys_LocalMemoryGeometryStreamingSpeedLimit; // Config: stat object geometry streaming speed limit (approx)
|
||||
|
||||
float sys_LocalMemoryWarningRatio; // Config: Warning ratio for streaming
|
||||
float sys_LocalMemoryOuterViewDistance; // Config: View distance for debug draw
|
||||
float sys_LocalMemoryInnerViewDistance; // Config: View distance for detailed debug draw
|
||||
|
||||
float sys_LocalMemoryObjectWidth; // Config: Width of the debug object
|
||||
float sys_LocalMemoryObjectHeight; // Config: Height of the debug object
|
||||
int sys_LocalMemoryObjectAlpha; // Config: Color alpha of the debug object
|
||||
|
||||
float sys_LocalMemoryStreamingSpeedObjectLength; // Config: Length of the streaming speed debug object
|
||||
float sys_LocalMemoryStreamingSpeedObjectWidth; // Config: Width of the streaming speed debug object
|
||||
|
||||
float sys_LocalMemoryDiagramWidth; // Config: Width of the diagram
|
||||
|
||||
float sys_LocalMemoryDiagramRadius; // Config: Radius of the diagram
|
||||
float sys_LocalMemoryDiagramDistance; // Config: Distance of the diagram from the main debug object
|
||||
float sys_LocalMemoryDiagramStreamingSpeedRadius; // Config: Radius of the streaming speed diagram
|
||||
float sys_LocalMemoryDiagramStreamingSpeedDistance; // Config: Distance of the streaming speed diagram from the streaming speed debug line
|
||||
int sys_LocalMemoryDiagramAlpha; // Config: Color alpha of the diagram
|
||||
|
||||
int sys_LocalMemoryDrawText; // Config: If != 0, it will draw the numeric values
|
||||
int sys_LocalMemoryLogText; // Config: If != 0, it will log the numeric values
|
||||
|
||||
int sys_LocalMemoryOptimalMSecPerSec; // Config: Optimal calculation time (MSec) per secundum
|
||||
int sys_LocalMemoryMaxMSecBetweenCalls; // Config: Maximal time difference (MSec) between calls
|
||||
|
||||
RectI m_actProcessedSectors; // Processed sectors (now it is the whole world)
|
||||
RectI m_actDrawedSectors; // Processed sectors (now it is the whole world)
|
||||
|
||||
Vec2i m_sectorNr; // Sector x and y number
|
||||
|
||||
float m_AverageUpdateTime; // Avarage Update() time (MSec)
|
||||
CTimeValue m_LastCallTime; // Last call time of Update()
|
||||
|
||||
SSector m_arrSectors[LOCALMEMORY_SECTOR_NR_X * LOCALMEMORY_SECTOR_NR_Y]; // Sectors
|
||||
|
||||
public:
|
||||
|
||||
CLocalMemoryUsage();
|
||||
~CLocalMemoryUsage();
|
||||
|
||||
virtual void OnRender(IRenderer* pRenderer, const CCamera* camera);
|
||||
virtual void OnUpdate();
|
||||
virtual void DeleteGlobalData(); // Deletes the m_globalXXX hash maps
|
||||
|
||||
private:
|
||||
void DeleteUnusedResources(); // Delete the non-used resources (especially StatObjs)
|
||||
void StartChecking(const RectI& actProcessedSectors); // Called every frame first
|
||||
void CollectGeometryP1(); // Calculates the minimum of sector bounding vs renderobject bounding distances
|
||||
|
||||
// Get / create StatObjInfo then run Pass1
|
||||
SStatObjInfo* CheckStatObjP1(IStatObj* pStatObj, IRenderNode* pRenderNode, AABB bounding, float maxViewDist, float scale);
|
||||
//void CollectStatObjInfo_Recursive( SStatObjInfo* statObjInfo, IStatObj *pStatObj );
|
||||
//void CollectGeometryInfo( SStatObjInfo* statObjInfo, IStatObj *pStatObj );
|
||||
|
||||
// Get / create MaterialInfo then run Pass1
|
||||
void CheckMaterialP1(_smart_ptr<IMaterial> pMaterial, AABB bounding, float maxViewDist, float scale, float mipFactor);
|
||||
void CheckChunkMaterialP1(_smart_ptr<IMaterial> pMaterial, AABB bounding, float maxViewDist, float scale, CRenderChunk* pRenderChunk);
|
||||
void CheckMeshMaterialP1(IRenderMesh* pRenderMesh, _smart_ptr<IMaterial> pMaterial, AABB bounding, float maxViewDist, float scale);
|
||||
void CheckStatObjMaterialP1(IStatObj* pStatObj, _smart_ptr<IMaterial> pMaterial, AABB bounding, float maxViewDist, float scale);
|
||||
// Collects textures used by the material
|
||||
void CollectMaterialInfo_Recursive(SMaterialInfo* materialInfo, _smart_ptr<IMaterial> pMaterial);
|
||||
|
||||
// Get / create TextureInfo
|
||||
STextureInfo* GetTextureInfo(ITexture* pTexture);
|
||||
};
|
||||
|
||||
#undef MAX_LODS
|
||||
#endif // CRYINCLUDE_CRYSYSTEM_STATISTICS_LOCALMEMORYUSAGE_H
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Logging/MissingAssetLogger.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzFramework/API/AtomActiveInterface.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
|
||||
|
||||
@@ -120,8 +119,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include AZ_RESTRICTED_FILE(System_cpp)
|
||||
#endif
|
||||
|
||||
|
||||
#include <I3DEngine.h>
|
||||
#include <IRenderer.h>
|
||||
#include <IMovieSystem.h>
|
||||
#include <ServiceNetwork.h>
|
||||
@@ -132,7 +129,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include <ISoftCodeMgr.h>
|
||||
#include "VisRegTest.h"
|
||||
#include <LyShine/ILyShine.h>
|
||||
#include <ITimeOfDay.h>
|
||||
|
||||
#include <LoadScreenBus.h>
|
||||
|
||||
@@ -155,7 +151,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
#include "Serialization/ArchiveHost.h"
|
||||
#include "SystemEventDispatcher.h"
|
||||
#include "ServerThrottle.h"
|
||||
#include "ILocalMemoryUsage.h"
|
||||
#include "ResourceManager.h"
|
||||
#include "HMDBus.h"
|
||||
#include "OverloadSceneManager/OverloadSceneManager.h"
|
||||
@@ -683,15 +678,6 @@ void CSystem::ShutDown()
|
||||
// Shutdown any running VR devices.
|
||||
EBUS_EVENT(AZ::VR::HMDInitRequestBus, Shutdown);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Clear 3D Engine resources.
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
m_env.p3DEngine->UnloadLevel();
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Shutdown resource manager.
|
||||
m_pResourceManager->Shutdown();
|
||||
|
||||
@@ -707,7 +693,6 @@ void CSystem::ShutDown()
|
||||
SAFE_DELETE(m_env.pServiceNetwork);
|
||||
SAFE_RELEASE(m_env.pLyShine);
|
||||
SAFE_RELEASE(m_env.pCryFont);
|
||||
SAFE_RELEASE(m_env.p3DEngine); // depends on EntitySystem
|
||||
if (m_env.pConsole)
|
||||
{
|
||||
((CXConsole*)m_env.pConsole)->FreeRenderResources();
|
||||
@@ -1162,31 +1147,6 @@ void CSystem::SleepIfInactive()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
if (!AZ::Interface<AzFramework::AtomActiveInterface>::Get())
|
||||
{
|
||||
WIN_HWND hRendWnd = GetIRenderer()->GetHWND();
|
||||
if (!hRendWnd)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZ_TRACE_METHOD();
|
||||
// Loop here waiting for window to be activated.
|
||||
for (int nLoops = 0; nLoops < 5; nLoops++)
|
||||
{
|
||||
WIN_HWND hActiveWnd = ::GetActiveWindow();
|
||||
if (hActiveWnd == hRendWnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::PumpSystemEventLoopUntilEmpty);
|
||||
Sleep(5);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1257,8 +1217,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderBegin();
|
||||
|
||||
#ifndef EXCLUDE_UPDATE_ON_CONSOLE
|
||||
// do the dedicated sleep earlier than the frame profiler to avoid having it counted
|
||||
if (gEnv->IsDedicated())
|
||||
@@ -1321,11 +1279,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
GetIRemoteConsole()->Update();
|
||||
#endif
|
||||
|
||||
if (gEnv->pLocalMemoryUsage != NULL)
|
||||
{
|
||||
gEnv->pLocalMemoryUsage->OnUpdate();
|
||||
}
|
||||
|
||||
if (!gEnv->IsEditor() && gEnv->pRenderer)
|
||||
{
|
||||
// If the dimensions of the render target change,
|
||||
@@ -1516,11 +1469,6 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
//update time subsystem
|
||||
m_Time.UpdateOnFrameStart();
|
||||
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
m_env.p3DEngine->OnFrameStart();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// update rate limiter for dedicated server
|
||||
if (m_pServerThrottle.get())
|
||||
@@ -1677,7 +1625,7 @@ bool CSystem::UpdatePreTickBus(int updateFlags, int nPauseMode)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::UpdatePostTickBus(int updateFlags, int nPauseMode)
|
||||
bool CSystem::UpdatePostTickBus(int updateFlags, int /*nPauseMode*/)
|
||||
{
|
||||
CTimeValue updateStart = gEnv->pTimer->GetAsyncTime();
|
||||
|
||||
@@ -1689,44 +1637,6 @@ bool CSystem::UpdatePostTickBus(int updateFlags, int nPauseMode)
|
||||
UpdateMovieSystem(updateFlags, fMovieFrameTime, false);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//update process (3D engine)
|
||||
if (!(updateFlags & ESYSUPDATE_EDITOR) && !m_bNoUpdate && m_env.p3DEngine)
|
||||
{
|
||||
FRAME_PROFILER("SysUpdate:Update3DEngine", this, PROFILE_SYSTEM);
|
||||
|
||||
if (ITimeOfDay* pTOD = m_env.p3DEngine->GetTimeOfDay())
|
||||
{
|
||||
pTOD->Tick();
|
||||
}
|
||||
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
m_env.p3DEngine->Tick(); // clear per frame temp data
|
||||
}
|
||||
if (m_pProcess && (m_pProcess->GetFlags() & PROC_3DENGINE))
|
||||
{
|
||||
if ((nPauseMode != 1))
|
||||
{
|
||||
if (!IsEquivalent(m_ViewCamera.GetPosition(), Vec3(0, 0, 0), VEC_EPSILON))
|
||||
{
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
// m_env.p3DEngine->SetCamera(m_ViewCamera);
|
||||
m_pProcess->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_pProcess)
|
||||
{
|
||||
m_pProcess->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//update sound system part 2
|
||||
if (!g_cvars.sys_deferAudioUpdateOptim && !m_bNoUpdate)
|
||||
@@ -1774,41 +1684,8 @@ bool CSystem::UpdatePostTickBus(int updateFlags, int nPauseMode)
|
||||
gEnv->pCryPak->DisableRuntimeFileAccess(true);
|
||||
}
|
||||
|
||||
// If it's in editing mode (in editor) the render is done in RenderViewport so we skip rendering here.
|
||||
if (!gEnv->IsEditing() && gEnv->pRenderer && gEnv->p3DEngine)
|
||||
{
|
||||
if (GetIViewSystem())
|
||||
{
|
||||
GetIViewSystem()->Update(min(gEnv->pTimer->GetFrameTime(), 0.1f));
|
||||
}
|
||||
|
||||
// Begin occlusion job after setting the correct camera.
|
||||
gEnv->p3DEngine->PrepareOcclusion(GetViewCamera());
|
||||
|
||||
CrySystemNotificationBus::Broadcast(&CrySystemNotifications::OnPreRender);
|
||||
|
||||
// Also broadcast for anyone else that needs to draw global debug to do so now
|
||||
AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
|
||||
|
||||
Render();
|
||||
|
||||
gEnv->p3DEngine->EndOcclusion();
|
||||
|
||||
CrySystemNotificationBus::Broadcast(&CrySystemNotifications::OnPostRender);
|
||||
|
||||
RenderEnd();
|
||||
|
||||
gEnv->p3DEngine->SyncProcessStreamingUpdate();
|
||||
|
||||
if (NeedDoWorkDuringOcclusionChecks())
|
||||
{
|
||||
DoWorkDuringOcclusionChecks();
|
||||
}
|
||||
|
||||
// Sync the work that must be done in the main thread by the end of frame.
|
||||
gEnv->pRenderer->GetGenerateShadowRendItemJobExecutor()->WaitForCompletion();
|
||||
gEnv->pRenderer->GetGenerateRendItemJobExecutor()->WaitForCompletion();
|
||||
}
|
||||
// Also broadcast for anyone else that needs to draw global debug to do so now
|
||||
AzFramework::DebugDisplayEventBus::Broadcast(&AzFramework::DebugDisplayEvents::DrawGlobalDebugInfo);
|
||||
|
||||
return !IsQuitting();
|
||||
}
|
||||
|
||||
@@ -408,13 +408,6 @@ public:
|
||||
virtual void DoWorkDuringOcclusionChecks();
|
||||
virtual bool NeedDoWorkDuringOcclusionChecks() { return m_bNeedDoWorkDuringOcclusionChecks; }
|
||||
|
||||
//! Begin rendering frame.
|
||||
void RenderBegin();
|
||||
//! Render subsystems.
|
||||
void Render();
|
||||
//! End rendering frame and swap back buffer.
|
||||
void RenderEnd(bool bRenderStats = true, bool bMainWindow = true);
|
||||
|
||||
//Called when the renderer finishes rendering the scene
|
||||
void OnScene3DEnd() override;
|
||||
|
||||
@@ -429,11 +422,6 @@ public:
|
||||
//! Update screen and call some important tick functions during loading.
|
||||
void SynchronousLoadingTick(const char* pFunc, int line);
|
||||
|
||||
//! Renders the statistics; this is called from RenderEnd, but if the
|
||||
//! Host application (Editor) doesn't employ the Render cycle in ISystem,
|
||||
//! it may call this method to render the essential statistics
|
||||
void RenderStatistics() override;
|
||||
|
||||
uint32 GetUsedMemory();
|
||||
|
||||
virtual void DumpMemoryUsageStatistics(bool bUseKB);
|
||||
@@ -469,7 +457,6 @@ public:
|
||||
AZ::IO::IArchive* GetIPak() { return m_env.pCryPak; };
|
||||
IConsole* GetIConsole() { return m_env.pConsole; };
|
||||
IRemoteConsole* GetIRemoteConsole();
|
||||
I3DEngine* GetI3DEngine(){ return m_env.p3DEngine; }
|
||||
IMovieSystem* GetIMovieSystem() { return m_env.pMovieSystem; };
|
||||
IMemoryManager* GetIMemoryManager(){ return m_pMemoryManager; }
|
||||
IThreadManager* GetIThreadManager() override {return m_env.pThreadManager; }
|
||||
@@ -676,17 +663,11 @@ private:
|
||||
//! @name Initialization routines
|
||||
//@{
|
||||
bool InitConsole();
|
||||
bool InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams);
|
||||
|
||||
bool InitFont(const SSystemInitParams& initParams);
|
||||
bool InitFileSystem();
|
||||
bool InitFileSystem_LoadEngineFolders(const SSystemInitParams& initParams);
|
||||
bool InitStreamEngine();
|
||||
bool Init3DEngine(const SSystemInitParams& initParams);
|
||||
bool InitAudioSystem(const SSystemInitParams& initParams);
|
||||
bool InitShine(const SSystemInitParams& initParams);
|
||||
bool OpenRenderLibrary(int type, const SSystemInitParams& initParams);
|
||||
bool OpenRenderLibrary(const char* t_rend, const SSystemInitParams& initParams);
|
||||
|
||||
//@}
|
||||
|
||||
@@ -702,9 +683,6 @@ private:
|
||||
void CreateRendererVars(const SSystemInitParams& startupParams);
|
||||
void CreateSystemVars();
|
||||
void CreateAudioVars();
|
||||
void RenderStats();
|
||||
void RenderOverscanBorders();
|
||||
void RenderMemStats();
|
||||
|
||||
AZStd::unique_ptr<AZ::DynamicModuleHandle> LoadDLL(const char* dllName);
|
||||
|
||||
@@ -738,9 +716,6 @@ private:
|
||||
bool GetWinGameFolder(char* szMyDocumentsPath, int maxPathSize);
|
||||
#endif
|
||||
|
||||
//! \brief Initializes the given IFFont member variable with the given name (internal use only).
|
||||
bool LoadFontInternal(IFFont*& font, const string& fontName);
|
||||
|
||||
public:
|
||||
void EnableFloatExceptions(int type);
|
||||
|
||||
|
||||
@@ -43,8 +43,6 @@
|
||||
#include <StringUtils.h>
|
||||
#include <IThreadManager.h>
|
||||
|
||||
#include "CryFontBus.h"
|
||||
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/IO/LocalFileIO.h>
|
||||
|
||||
@@ -70,7 +68,6 @@
|
||||
#include <LyShine/Bus/UiSystemBus.h>
|
||||
#include <AzFramework/Logging/MissingAssetLogger.h>
|
||||
#include <AzFramework/Platform/PlatformDefaults.h>
|
||||
#include <AzFramework/API/AtomActiveInterface.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
@@ -89,7 +86,6 @@
|
||||
|
||||
#endif //WIN32
|
||||
|
||||
#include <I3DEngine.h>
|
||||
#include <IRenderer.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <IMovieSystem.h>
|
||||
@@ -110,7 +106,6 @@
|
||||
#include "PhysRenderer.h"
|
||||
#include "LocalizedStringManager.h"
|
||||
#include "SystemEventDispatcher.h"
|
||||
#include "Statistics/LocalMemoryUsage.h"
|
||||
#include "ThreadConfigManager.h"
|
||||
#include "Validator.h"
|
||||
#include "ServerThrottle.h"
|
||||
@@ -247,24 +242,6 @@ CUNIXConsole* pUnixConsole;
|
||||
|
||||
#define LOCALIZATION_TRANSLATIONS_LIST_FILE_NAME "Libs/Localization/localization.xml"
|
||||
|
||||
#define LOAD_LEGACY_RENDERER_FOR_EDITOR false // If you set this to true you must also set 'ed_useAtomNativeViewport' to false (see /Code/Sandbox/Editor/ViewManager.cpp)
|
||||
#define LOAD_LEGACY_RENDERER_FOR_LAUNCHER false
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Where possible, these are defaults used to initialize cvars
|
||||
// System.cfg can then be used to override them
|
||||
// This includes the Game DLL, although it is loaded elsewhere
|
||||
|
||||
#define DLL_FONT "CryFont"
|
||||
#define DLL_3DENGINE "Cry3DEngine"
|
||||
#define DLL_RENDERER_DX9 "CryRenderD3D9"
|
||||
#define DLL_RENDERER_DX11 "CryRenderD3D11"
|
||||
#define DLL_RENDERER_DX12 "CryRenderD3D12"
|
||||
#define DLL_RENDERER_METAL "CryRenderMetal"
|
||||
#define DLL_RENDERER_GL "CryRenderGL"
|
||||
#define DLL_RENDERER_NULL "CryRenderNULL"
|
||||
#define DLL_SHINE "LyShine"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
#if defined(WIN32) || defined(LINUX) || defined(APPLE)
|
||||
# define DLL_MODULE_INIT_ISYSTEM "ModuleInitISystem"
|
||||
@@ -789,11 +766,6 @@ static void LoadDetectedSpec(ICVar* pVar)
|
||||
|
||||
GetISystem()->SetConfigSpec(static_cast<ESystemConfigSpec>(spec), platform, false);
|
||||
|
||||
if (gEnv->p3DEngine)
|
||||
{
|
||||
gEnv->p3DEngine->GetMaterialManager()->RefreshMaterialRuntime();
|
||||
}
|
||||
|
||||
no_recursive = false;
|
||||
}
|
||||
|
||||
@@ -1079,58 +1051,6 @@ void CSystem::ShutdownModuleLibraries()
|
||||
#endif // !defined(AZ_MONOLITHIC_BUILD)
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::OpenRenderLibrary([[maybe_unused]] const char* t_rend, const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_6
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
return OpenRenderLibrary(R_NULL_RENDERER, initParams);
|
||||
}
|
||||
|
||||
if (AZ::Interface<AzFramework::AtomActiveInterface>::Get())
|
||||
{
|
||||
return OpenRenderLibrary(R_DX11_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "DX9") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_DX9_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "DX11") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_DX11_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "DX12") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_DX12_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "GL") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_GL_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "METAL") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_METAL_RENDERER, initParams);
|
||||
}
|
||||
else if (azstricmp(t_rend, "NULL") == 0)
|
||||
{
|
||||
return OpenRenderLibrary(R_NULL_RENDERER, initParams);
|
||||
}
|
||||
|
||||
AZ_Assert(false, "Unknown renderer type: %s", t_rend);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1220,126 +1140,6 @@ wstring GetErrorStringUnsupportedGPU(const char* gpuName, unsigned int gpuVendor
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CSystem::OpenRenderLibrary(int type, const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION;
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
if (!gEnv->IsDedicated())
|
||||
{
|
||||
unsigned int gpuVendorId = 0, gpuDeviceId = 0, totVidMem = 0;
|
||||
char gpuName[256];
|
||||
Win32SysInspect::DXFeatureLevel featureLevel = Win32SysInspect::DXFL_Undefined;
|
||||
Win32SysInspect::GetGPUInfo(gpuName, sizeof(gpuName), gpuVendorId, gpuDeviceId, totVidMem, featureLevel);
|
||||
|
||||
if (m_env.IsEditor())
|
||||
{
|
||||
#if defined(EXTERNAL_CRASH_REPORTING)
|
||||
CrashHandler::CrashHandlerBase::AddAnnotation("dx.feature.level", Win32SysInspect::GetFeatureLevelAsString(featureLevel));
|
||||
CrashHandler::CrashHandlerBase::AddAnnotation("gpu.name", gpuName);
|
||||
CrashHandler::CrashHandlerBase::AddAnnotation("gpu.vendorId", std::to_string(gpuVendorId));
|
||||
CrashHandler::CrashHandlerBase::AddAnnotation("gpu.deviceId", std::to_string(gpuDeviceId));
|
||||
CrashHandler::CrashHandlerBase::AddAnnotation("gpu.memory", std::to_string(totVidMem));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
if (featureLevel < Win32SysInspect::DXFL_11_0)
|
||||
{
|
||||
const char logMsgFmt[] ("Unsupported GPU configuration!\n- %s (vendor = 0x%.4x, device = 0x%.4x)\n- Dedicated video memory: %d MB\n- Feature level: %s\n");
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, logMsgFmt, gpuName, gpuVendorId, gpuDeviceId, totVidMem >> 20, GetFeatureLevelAsString(featureLevel));
|
||||
|
||||
#if !defined(_RELEASE)
|
||||
const bool allowPrompts = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "noprompt") == 0;
|
||||
#else
|
||||
const bool allowPrompts = true;
|
||||
#endif // !defined(_RELEASE)
|
||||
if (allowPrompts)
|
||||
{
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Asking user if they wish to continue...");
|
||||
const int mbRes = MessageBoxW(0, GetErrorStringUnsupportedGPU(gpuName, gpuVendorId, gpuDeviceId).c_str(), L"Open 3D Engine", MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2 | MB_DEFAULT_DESKTOP_ONLY);
|
||||
if (mbRes == IDCANCEL)
|
||||
{
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to cancel startup due to unsupported GPU.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if !defined(_RELEASE)
|
||||
const bool obeyGPUCheck = m_env.pSystem->GetICmdLine()->FindArg(eCLAT_Pre, "anygpu") == 0;
|
||||
#else
|
||||
const bool obeyGPUCheck = true;
|
||||
#endif // !defined(_RELEASE)
|
||||
if (obeyGPUCheck)
|
||||
{
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "No prompts allowed and unsupported GPU check active. Treating unsupported GPU as error and exiting.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "User chose to continue despite unsupported GPU!");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_7
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
#endif
|
||||
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
type = R_NULL_RENDERER;
|
||||
}
|
||||
const char* libname = "";
|
||||
if (AZ::Interface<AzFramework::AtomActiveInterface>::Get())
|
||||
{
|
||||
libname = DLL_RENDERER_NULL;
|
||||
}
|
||||
else if (type == R_DX9_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_DX9;
|
||||
}
|
||||
else if (type == R_DX11_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_DX11;
|
||||
}
|
||||
else if (type == R_DX12_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_DX12;
|
||||
}
|
||||
else if (type == R_NULL_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_NULL;
|
||||
}
|
||||
else if (type == R_GL_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_GL;
|
||||
}
|
||||
else if (type == R_METAL_RENDERER)
|
||||
{
|
||||
libname = DLL_RENDERER_METAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Renderer did not initialize correctly; no valid renderer specified.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!InitializeEngineModule(libname, "EngineModule_CryRenderer", initParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_env.pRenderer)
|
||||
{
|
||||
AZ_Assert(false, "Renderer did not initialize correctly; it could not be found in the system environment.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitConsole()
|
||||
@@ -1391,123 +1191,6 @@ ICVar* CSystem::attachVariable (const char* szVarName, int* pContainer, const ch
|
||||
return pVar;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitRenderer(WIN_HINSTANCE hinst, WIN_HWND hwnd, const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
if (m_pUserCallback)
|
||||
{
|
||||
m_pUserCallback->OnInitProgress("Initializing Renderer...");
|
||||
}
|
||||
|
||||
if (m_bEditor)
|
||||
{
|
||||
m_env.pConsole->GetCVar("r_Width");
|
||||
|
||||
// save current screen width/height/bpp, so they can be restored on shutdown
|
||||
m_iWidth = m_env.pConsole->GetCVar("r_Width")->GetIVal();
|
||||
m_iHeight = m_env.pConsole->GetCVar("r_Height")->GetIVal();
|
||||
m_iColorBits = m_env.pConsole->GetCVar("r_ColorBits")->GetIVal();
|
||||
}
|
||||
|
||||
if (!OpenRenderLibrary(m_rDriver->GetString(), initParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID)
|
||||
if (m_rWidthAndHeightAsFractionOfScreenSize->GetFlags() & VF_WASINCONFIG)
|
||||
{
|
||||
int displayWidth = 0;
|
||||
int displayHeight = 0;
|
||||
if (GetPrimaryPhysicalDisplayDimensions(displayWidth, displayHeight))
|
||||
{
|
||||
// Ideally we would probably want to clamp this at the source,
|
||||
// but I don't believe cvars support specifying a valid range.
|
||||
float scaleFactor = 1.0f;
|
||||
|
||||
if(IsTablet())
|
||||
{
|
||||
scaleFactor = AZ::GetClamp(m_rTabletWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
scaleFactor = AZ::GetClamp(m_rWidthAndHeightAsFractionOfScreenSize->GetFVal(), 0.1f, 1.0f);
|
||||
}
|
||||
|
||||
displayWidth *= scaleFactor;
|
||||
displayHeight *= scaleFactor;
|
||||
|
||||
const int maxWidth = m_rMaxWidth->GetIVal();
|
||||
if (maxWidth > 0 && maxWidth < displayWidth)
|
||||
{
|
||||
const float widthScaleFactor = static_cast<float>(maxWidth) / static_cast<float>(displayWidth);
|
||||
displayWidth *= widthScaleFactor;
|
||||
displayHeight *= widthScaleFactor;
|
||||
}
|
||||
|
||||
const int maxHeight = m_rMaxHeight->GetIVal();
|
||||
if (maxHeight > 0 && maxHeight < displayHeight)
|
||||
{
|
||||
const float heightScaleFactor = static_cast<float>(maxHeight) / static_cast<float>(displayHeight);
|
||||
displayWidth *= heightScaleFactor;
|
||||
displayHeight *= heightScaleFactor;
|
||||
}
|
||||
|
||||
m_rWidth->Set(displayWidth);
|
||||
m_rHeight->Set(displayHeight);
|
||||
}
|
||||
}
|
||||
#endif // defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_ANDROID)
|
||||
|
||||
if (m_env.pRenderer)
|
||||
{
|
||||
// This is crucial as textures suffix are hard coded to context and we need to initialize
|
||||
// the texture semantics to look it up.
|
||||
m_env.pRenderer->InitTexturesSemantics();
|
||||
|
||||
#ifdef WIN32
|
||||
SCustomRenderInitArgs args;
|
||||
args.appStartedFromMediaCenter = strstr(initParams.szSystemCmdLine, "ReLaunchMediaCenter") != 0;
|
||||
|
||||
m_hWnd = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, &args, initParams.bShaderCacheGen);
|
||||
//Timur, Not very clean code, we need to push new hwnd value to the system init params, so other modules can used when initializing.
|
||||
(const_cast<SSystemInitParams*>(&initParams))->hWnd = m_hWnd;
|
||||
|
||||
|
||||
bool retVal = (initParams.bShaderCacheGen || m_hWnd != 0);
|
||||
AZ_Assert(retVal, "Renderer failed to initialize correctly.");
|
||||
return retVal;
|
||||
#else // WIN32
|
||||
WIN_HWND h = m_env.pRenderer->Init(0, 0, m_rWidth->GetIVal(), m_rHeight->GetIVal(), m_rColorBits->GetIVal(), m_rDepthBits->GetIVal(), m_rStencilBits->GetIVal(), m_rFullscreen->GetIVal() ? true : false, initParams.bEditor, hinst, hwnd, false, nullptr, initParams.bShaderCacheGen);
|
||||
|
||||
#if (defined(LINUX) && !defined(AZ_PLATFORM_ANDROID))
|
||||
return true;
|
||||
#define AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#elif defined(AZ_RESTRICTED_PLATFORM)
|
||||
#define AZ_RESTRICTED_SECTION SYSTEMINIT_CPP_SECTION_8
|
||||
#include AZ_RESTRICTED_FILE(SystemInit_cpp)
|
||||
#endif
|
||||
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
|
||||
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
|
||||
#else
|
||||
bool retVal = (initParams.bShaderCacheGen || h != 0);
|
||||
if (retVal)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AZ_Assert(false, "Renderer failed to initialize correctly.");
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitFileSystem()
|
||||
{
|
||||
@@ -1662,68 +1345,6 @@ bool CSystem::InitStreamEngine()
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitFont(const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
bool fontInited = false;
|
||||
AZ::CryFontCreationRequestBus::BroadcastResult(fontInited, &AZ::CryFontCreationRequests::CreateCryFont, m_env, initParams);
|
||||
if (!fontInited && !InitializeEngineModule(DLL_FONT, "EngineModule_CryFont", initParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_env.pCryFont)
|
||||
{
|
||||
AZ_Assert(false, "Font System did not initialize correctly; it could not be found in the system environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gEnv->IsDedicated())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!LoadFontInternal(m_pIFont, "default"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LoadFontInternal(m_pIFontUi, "default-ui"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::Init3DEngine(const SSystemInitParams& initParams)
|
||||
{
|
||||
LOADING_TIME_PROFILE_SECTION(GetISystem());
|
||||
|
||||
if (!InitializeEngineModule(DLL_3DENGINE, "EngineModule_Cry3DEngine", initParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_env.p3DEngine)
|
||||
{
|
||||
AZ_Assert(false, "3D Engine did not initialize correctly; it could not be found in the system environment");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_env.p3DEngine->Init())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_pProcess = m_env.p3DEngine;
|
||||
m_pProcess->SetFlags(PROC_3DENGINE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool CSystem::InitAudioSystem(const SSystemInitParams& initParams)
|
||||
{
|
||||
@@ -2785,42 +2406,6 @@ AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
InlineInitializationProcessing("CSystem::Init InitLocalizations");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RENDERER
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const bool loadLegacyRenderer = gEnv->IsEditor() ?
|
||||
LOAD_LEGACY_RENDERER_FOR_EDITOR :
|
||||
LOAD_LEGACY_RENDERER_FOR_LAUNCHER;
|
||||
if (loadLegacyRenderer && !startupParams.bSkipRenderer)
|
||||
{
|
||||
AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid before initializing renderer.");
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Renderer initialization");
|
||||
|
||||
if (!InitRenderer(m_hInst, m_hWnd, startupParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
AZ_Assert(CryMemory::IsHeapValid(), "CryMemory must be valid after initializing renderer.");
|
||||
if (m_env.pRenderer)
|
||||
{
|
||||
bool bMultiGPUEnabled = false;
|
||||
m_env.pRenderer->EF_Query(EFQ_MultiGPUEnabled, bMultiGPUEnabled);
|
||||
if (bMultiGPUEnabled)
|
||||
{
|
||||
LoadConfiguration("mgpu.cfg");
|
||||
}
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init InitRenderer");
|
||||
|
||||
if (m_env.pCryFont)
|
||||
{
|
||||
m_env.pCryFont->SetRendererProperties(m_env.pRenderer);
|
||||
}
|
||||
|
||||
AZ_Assert(m_env.pRenderer || startupParams.bSkipRenderer, "The renderer did not initialize correctly.");
|
||||
}
|
||||
|
||||
#if !defined(AZ_RELEASE_BUILD) && defined(AZ_PLATFORM_ANDROID)
|
||||
m_thermalInfoHandler = AZStd::make_unique<ThermalInfoAndroidHandler>();
|
||||
#endif
|
||||
@@ -2869,21 +2454,6 @@ AZ_POP_DISABLE_WARNING
|
||||
|
||||
m_env.pRenderer->SetViewport(0, 0, screenWidth, screenHeight);
|
||||
|
||||
// Skip splash screen rendering
|
||||
if (!AZ::Interface<AzFramework::AtomActiveInterface>::Get())
|
||||
{
|
||||
// make sure it's rendered in full screen mode when triple buffering is enabled as well
|
||||
for (size_t n = 0; n < 3; n++)
|
||||
{
|
||||
m_env.pRenderer->BeginFrame();
|
||||
m_env.pRenderer->SetCullMode(R_CULL_NONE);
|
||||
m_env.pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
||||
m_env.pRenderer->Draw2dImageStretchMode(true);
|
||||
m_env.pRenderer->Draw2dImage(x * vx, y * vy, w * vx, h * vy, pTex->GetTextureID(), 0.0f, 1.0f, 1.0f, 0.0f);
|
||||
m_env.pRenderer->Draw2dImageStretchMode(false);
|
||||
m_env.pRenderer->EndFrame();
|
||||
}
|
||||
}
|
||||
#if defined(AZ_PLATFORM_IOS) || defined(AZ_PLATFORM_MAC)
|
||||
// Pump system events in order to update the screen
|
||||
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::PumpSystemEventLoopUntilEmpty);
|
||||
@@ -2928,24 +2498,10 @@ AZ_POP_DISABLE_WARNING
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// FONT
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (!startupParams.bSkipFont)
|
||||
{
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Font initialization");
|
||||
if (!InitFont(startupParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init InitFonts");
|
||||
|
||||
// The last update to the loading screen message was 'Initializing CryFont...'
|
||||
// Compiling the default system textures can be the lengthiest portion of
|
||||
// editor initialization, so it is useful to inform users that they are waiting on
|
||||
// the necessary default textures to compile, and that they are not waiting on CryFont.
|
||||
// the necessary default textures to compile.
|
||||
if (m_pUserCallback)
|
||||
{
|
||||
m_pUserCallback->OnInitProgress("First time asset processing - may take a minute...");
|
||||
@@ -3040,28 +2596,6 @@ AZ_POP_DISABLE_WARNING
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Init 3d engine
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
if (loadLegacyRenderer && !startupParams.bSkipRenderer && !startupParams.bShaderCacheGen)
|
||||
{
|
||||
AZ_Printf(AZ_TRACE_SYSTEM_WINDOW, "Initializing 3D Engine");
|
||||
INDENT_LOG_DURING_SCOPE();
|
||||
|
||||
if (!Init3DEngine(startupParams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// try flush to keep renderer busy
|
||||
if (m_env.pRenderer)
|
||||
{
|
||||
m_env.pRenderer->TryFlush();
|
||||
}
|
||||
|
||||
InlineInitializationProcessing("CSystem::Init Init3DEngine");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SERVICE NETWORK
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -3247,12 +2781,6 @@ AZ_POP_DISABLE_WARNING
|
||||
m_env.pRenderer->TryFlush();
|
||||
}
|
||||
|
||||
#if !defined(RELEASE)
|
||||
m_env.pLocalMemoryUsage = new CLocalMemoryUsage();
|
||||
#else
|
||||
m_env.pLocalMemoryUsage = nullptr;
|
||||
#endif
|
||||
|
||||
if (g_cvars.sys_float_exceptions > 0)
|
||||
{
|
||||
if (g_cvars.sys_float_exceptions == 3 && gEnv->IsEditor()) // Turn off float exceptions in editor if sys_float_exceptions = 3
|
||||
@@ -4223,24 +3751,3 @@ void CSystem::SetAssertVisible(bool bAssertVisble)
|
||||
{
|
||||
m_bIsAsserting = bAssertVisble;
|
||||
}
|
||||
|
||||
bool CSystem::LoadFontInternal(IFFont*& font, const string& fontName)
|
||||
{
|
||||
font = m_env.pCryFont->NewFont(fontName);
|
||||
if (!font)
|
||||
{
|
||||
AZ_Assert(false, "Could not instantiate the default font.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
string szFontPath = "Fonts/" + fontName + ".font";
|
||||
|
||||
if (!font->Load(szFontPath.c_str()))
|
||||
{
|
||||
AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "Could not load font: %s. Make sure the program is running from the correct working directory.", szFontPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <IProcess.h>
|
||||
#include "Log.h"
|
||||
#include "XConsole.h"
|
||||
#include <I3DEngine.h>
|
||||
#include <CryLibrary.h>
|
||||
#include "PhysRenderer.h"
|
||||
#include <IMovieSystem.h>
|
||||
@@ -222,92 +221,6 @@ void CSystem::CreateRendererVars(const SSystemInitParams& startupParams)
|
||||
"Usage: r_OverscanBordersDrawDebugView [0=off/1=show]");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::RenderBegin()
|
||||
{
|
||||
FUNCTION_PROFILER_FAST(GetISystem(), PROFILE_SYSTEM, g_bProfilerEnabled);
|
||||
|
||||
if (m_bIgnoreUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool rndAvail = m_env.pRenderer != 0;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//start the rendering pipeline
|
||||
if (rndAvail)
|
||||
{
|
||||
m_env.pRenderer->BeginFrame();
|
||||
}
|
||||
|
||||
gEnv->nMainFrameID = (rndAvail) ? m_env.pRenderer->GetFrameID(false) : 0;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::RenderEnd([[maybe_unused]] bool bRenderStats, bool bMainWindow)
|
||||
{
|
||||
{
|
||||
FUNCTION_PROFILER_FAST(GetISystem(), PROFILE_SYSTEM, g_bProfilerEnabled);
|
||||
|
||||
if (m_bIgnoreUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_env.pRenderer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bMainWindow) // we don't do this in UI Editor window for example
|
||||
{
|
||||
#if !defined (_RELEASE)
|
||||
// Flush render data and swap buffers.
|
||||
m_env.pRenderer->RenderDebug(bRenderStats);
|
||||
#endif
|
||||
|
||||
#if defined(USE_PERFHUD)
|
||||
if (m_pPerfHUD)
|
||||
{
|
||||
m_pPerfHUD->Draw();
|
||||
}
|
||||
if (m_pMiniGUI)
|
||||
{
|
||||
m_pMiniGUI->Draw();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!gEnv->pSystem->GetILevelSystem() || !gEnv->pSystem->GetILevelSystem()->IsLevelLoaded())
|
||||
{
|
||||
IConsole* console = GetIConsole();
|
||||
|
||||
//Same goes for the console. When no level is loaded, it's okay to render it outside of the renderer
|
||||
//so that users can load maps or change settings.
|
||||
if (console != nullptr)
|
||||
{
|
||||
console->Draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_env.pRenderer->ForceGC(); // XXX Rename this
|
||||
m_env.pRenderer->EndFrame();
|
||||
|
||||
|
||||
if (IConsole* pConsole = GetIConsole())
|
||||
{
|
||||
// if we have pending cvar calculation, execute it here
|
||||
// since we know cvars will be correct here after ->EndFrame().
|
||||
if (!pConsole->IsHashCalculated())
|
||||
{
|
||||
pConsole->CalcCheatVarHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSystem::OnScene3DEnd()
|
||||
{
|
||||
//Render Console
|
||||
@@ -391,231 +304,3 @@ void CSystem::DisplayErrorMessage(const char* acMessage,
|
||||
#endif
|
||||
m_ErrorMessages.push_back(message);
|
||||
}
|
||||
|
||||
//! Renders the statistics; this is called from RenderEnd, but if the
|
||||
//! Host application (Editor) doesn't employ the Render cycle in ISystem,
|
||||
//! it may call this method to render the essential statistics
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::RenderStatistics()
|
||||
{
|
||||
RenderStats();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
void CSystem::Render()
|
||||
{
|
||||
if (m_bIgnoreUpdates)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//check what is the current process
|
||||
if (!m_pProcess)
|
||||
{
|
||||
return; //should never happen
|
||||
}
|
||||
//check if the game is in pause or
|
||||
//in menu mode
|
||||
//bool bPause=false;
|
||||
//if (m_pProcess->GetFlags() & PROC_MENU)
|
||||
// bPause=true;
|
||||
|
||||
FUNCTION_PROFILER_FAST(GetISystem(), PROFILE_SYSTEM, g_bProfilerEnabled);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//draw
|
||||
m_env.p3DEngine->PreWorldStreamUpdate(m_ViewCamera);
|
||||
|
||||
if (m_pProcess)
|
||||
{
|
||||
if (m_pProcess->GetFlags() & PROC_3DENGINE)
|
||||
{
|
||||
if (!gEnv->IsEditing()) // Editor calls it's own rendering update
|
||||
{
|
||||
if (m_env.p3DEngine && !m_env.IsFMVPlaying())
|
||||
{
|
||||
if (!IsEquivalent(m_ViewCamera.GetPosition(), Vec3(0, 0, 0), VEC_EPSILON) || // never pass undefined camera to p3DEngine->RenderWorld()
|
||||
gEnv->IsDedicated() || (gEnv->pRenderer && gEnv->pRenderer->IsPost3DRendererEnabled()))
|
||||
{
|
||||
GetIRenderer()->SetViewport(0, 0, GetIRenderer()->GetWidth(), GetIRenderer()->GetHeight());
|
||||
m_env.p3DEngine->RenderWorld(SHDF_ALLOW_WATER | SHDF_ALLOWPOSTPROCESS | SHDF_ALLOWHDR | SHDF_ZPASS | SHDF_ALLOW_AO, SRenderingPassInfo::CreateGeneralPassRenderingInfo(m_ViewCamera), __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gEnv->pRenderer)
|
||||
{
|
||||
// force rendering of black screen to be sure we don't only render the clear color (which is the fog color by default)
|
||||
gEnv->pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
||||
gEnv->pRenderer->Draw2dImage(0, 0, 800, 600, -1, 0.0f, 0.0f, 1.0f, 1.0f, 0.f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f, 0.f);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !defined(_RELEASE)
|
||||
if (m_pVisRegTest)
|
||||
{
|
||||
m_pVisRegTest->AfterRender();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_env.pMovieSystem)
|
||||
{
|
||||
m_env.pMovieSystem->Render();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GetIRenderer()->SetViewport(0, 0, GetIRenderer()->GetWidth(), GetIRenderer()->GetHeight());
|
||||
m_pProcess->RenderWorld(SHDF_ALLOW_WATER | SHDF_ALLOWPOSTPROCESS | SHDF_ALLOWHDR | SHDF_ZPASS | SHDF_ALLOW_AO, SRenderingPassInfo::CreateGeneralPassRenderingInfo(m_ViewCamera), __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
m_env.p3DEngine->WorldStreamUpdate();
|
||||
|
||||
gEnv->pRenderer->SwitchToNativeResolutionBackbuffer();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CSystem::RenderStats()
|
||||
{
|
||||
#if defined(ENABLE_PROFILING_CODE)
|
||||
#ifndef _RELEASE
|
||||
// if we rendered an error message on screen during the last frame, then sleep now
|
||||
// to force hard stall for 3sec
|
||||
if (m_bHasRenderedErrorMessage && !gEnv->IsEditor() && !IsLoading())
|
||||
{
|
||||
// DO NOT REMOVE OR COMMENT THIS OUT!
|
||||
// If you hit this, then you most likely have invalid (synchronous) file accesses
|
||||
// which must be fixed in order to not stall the entire game.
|
||||
Sleep(3000);
|
||||
m_bHasRenderedErrorMessage = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// render info messages on screen
|
||||
float fTextPosX = 5.0f;
|
||||
float fTextPosY = -10;
|
||||
float fTextStepY = 13;
|
||||
|
||||
float fFrameTime = gEnv->pTimer->GetRealFrameTime();
|
||||
TErrorMessages::iterator itnext;
|
||||
for (TErrorMessages::iterator it = m_ErrorMessages.begin(); it != m_ErrorMessages.end(); it = itnext)
|
||||
{
|
||||
itnext = it;
|
||||
++itnext;
|
||||
SErrorMessage& message = *it;
|
||||
|
||||
SDrawTextInfo ti;
|
||||
ti.flags = eDrawText_FixedSize | eDrawText_2D | eDrawText_Monospace;
|
||||
memcpy(ti.color, message.m_Color, 4 * sizeof(float));
|
||||
ti.xscale = ti.yscale = 1.4f;
|
||||
m_env.pRenderer->DrawTextQueued(Vec3(fTextPosX, fTextPosY += fTextStepY, 1.0f), ti, message.m_Message.c_str());
|
||||
|
||||
if (!IsLoading())
|
||||
{
|
||||
message.m_fTimeToShow -= fFrameTime;
|
||||
}
|
||||
|
||||
if (message.m_HardFailure)
|
||||
{
|
||||
m_bHasRenderedErrorMessage = true;
|
||||
}
|
||||
|
||||
if (message.m_fTimeToShow < 0.0f)
|
||||
{
|
||||
m_ErrorMessages.erase(it);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_env.pConsole)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef _RELEASE
|
||||
if (m_rOverscanBordersDrawDebugView)
|
||||
{
|
||||
RenderOverscanBorders();
|
||||
}
|
||||
#endif
|
||||
|
||||
int iDisplayInfo = m_rDisplayInfo->GetIVal();
|
||||
if (iDisplayInfo == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw engine stats
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
// Draw 3dengine stats and get last text cursor position
|
||||
float nTextPosX = 101 - 20, nTextPosY = -2, nTextStepY = 3;
|
||||
m_env.p3DEngine->DisplayInfo(nTextPosX, nTextPosY, nTextStepY, iDisplayInfo != 1);
|
||||
|
||||
// Dump Open 3D Engine CPU and GPU memory statistics to screen
|
||||
m_env.p3DEngine->DisplayMemoryStatistics();
|
||||
|
||||
#if defined(ENABLE_LW_PROFILERS)
|
||||
if (m_rDisplayInfo->GetIVal() == 2)
|
||||
{
|
||||
m_env.pRenderer->TextToScreen(nTextPosX, nTextPosY += nTextStepY, "SysMem %.1f mb",
|
||||
float(DumpMMStats(false)) / 1024.f);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < NUM_POOLS; ++i)
|
||||
{
|
||||
int used = (g_pPakHeap->m_iBigPoolUsed[i] ? (int)g_pPakHeap->m_iBigPoolSize[i] : 0);
|
||||
int size = (int)g_pPakHeap->m_iBigPoolSize[i];
|
||||
float fC1[4] = {1, 1, 0, 1};
|
||||
m_env.pRenderer->Draw2dLabel(10, 100.0f + i * 16, 2.1f, fC1, false, "BigPool %d: %d bytes of %d bytes used", i, used, size);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CSystem::RenderOverscanBorders()
|
||||
{
|
||||
#ifndef _RELEASE
|
||||
|
||||
if (m_env.pRenderer && m_rOverscanBordersDrawDebugView)
|
||||
{
|
||||
int iOverscanBordersDrawDebugView = m_rOverscanBordersDrawDebugView->GetIVal();
|
||||
if (iOverscanBordersDrawDebugView)
|
||||
{
|
||||
const int texId = -1;
|
||||
const float uv = 0.0f;
|
||||
const float rot = 0.0f;
|
||||
const int whiteTextureId = m_env.pRenderer->GetWhiteTextureId();
|
||||
|
||||
const float r = 1.0f;
|
||||
const float g = 1.0f;
|
||||
const float b = 1.0f;
|
||||
const float a = 0.2f;
|
||||
|
||||
Vec2 overscanBorders = Vec2(0.0f, 0.0f);
|
||||
m_env.pRenderer->EF_Query(EFQ_OverscanBorders, overscanBorders);
|
||||
|
||||
const float overscanBorderWidth = overscanBorders.x * VIRTUAL_SCREEN_WIDTH;
|
||||
const float overscanBorderHeight = overscanBorders.y * VIRTUAL_SCREEN_HEIGHT;
|
||||
|
||||
const float xPos = overscanBorderWidth;
|
||||
const float yPos = overscanBorderHeight;
|
||||
const float width = VIRTUAL_SCREEN_WIDTH - (2.0f * overscanBorderWidth);
|
||||
const float height = VIRTUAL_SCREEN_HEIGHT - (2.0f * overscanBorderHeight);
|
||||
|
||||
m_env.pRenderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA | GS_NODEPTHTEST);
|
||||
m_env.pRenderer->Draw2dImage(xPos, yPos,
|
||||
width, height,
|
||||
whiteTextureId,
|
||||
uv, uv, uv, uv,
|
||||
rot,
|
||||
r, g, b, a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "System.h"
|
||||
#include <time.h>
|
||||
|
||||
#include <I3DEngine.h>
|
||||
#include <IRenderer.h>
|
||||
#include <IMovieSystem.h>
|
||||
#include <ILog.h>
|
||||
@@ -302,23 +301,6 @@ void CSystem::CollectMemStats (ICrySizer* pSizer, MemStatsPurposeEnum nPurpose,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_env.p3DEngine)
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "Cry3DEngine");
|
||||
{
|
||||
m_env.p3DEngine->GetMemoryUsage (pSizer);
|
||||
{
|
||||
SIZER_COMPONENT_NAME (pSizer, "$Allocations waste");
|
||||
const SmallModuleInfo* info = FindModuleInfo(stats, "Cry3DEngine.dll");
|
||||
if (info)
|
||||
{
|
||||
pSizer->AddObject(info, info->memInfo.allocated - info->memInfo.requested);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_env.pRenderer)
|
||||
{
|
||||
SIZER_COMPONENT_NAME(pSizer, "CryRenderer");
|
||||
|
||||
@@ -98,7 +98,7 @@ void CView::Update(float frameTime, bool isActive)
|
||||
|
||||
//see if the view have to use a custom near clipping plane
|
||||
const float nearPlane = (m_viewParams.nearplane >= CAMERA_MIN_NEAR) ? (m_viewParams.nearplane) : fNearZ;
|
||||
const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : gEnv->p3DEngine->GetMaxViewDistance();
|
||||
const float farPlane = (m_viewParams.farplane > 0.f) ? m_viewParams.farplane : DEFAULT_FAR;
|
||||
float fov = (m_viewParams.fov < 0.001f) ? DEFAULT_FOV : m_viewParams.fov;
|
||||
|
||||
// [VR] specific
|
||||
|
||||
@@ -533,11 +533,6 @@ void CViewSystem::BeginCutScene(IAnimSequence* pSeq, [[maybe_unused]] unsigned l
|
||||
{
|
||||
m_cutsceneCount++;
|
||||
|
||||
if (m_cutsceneCount == 1)
|
||||
{
|
||||
gEnv->p3DEngine->ResetPostEffects();
|
||||
}
|
||||
|
||||
VS_CALL_LISTENERS(OnBeginCutScene(pSeq, bResetFX));
|
||||
}
|
||||
|
||||
@@ -546,11 +541,6 @@ void CViewSystem::EndCutScene(IAnimSequence* pSeq, [[maybe_unused]] unsigned lon
|
||||
{
|
||||
m_cutsceneCount -= (m_cutsceneCount > 0);
|
||||
|
||||
if (m_cutsceneCount == 0)
|
||||
{
|
||||
gEnv->p3DEngine->ResetPostEffects();
|
||||
}
|
||||
|
||||
ClearCutsceneViews();
|
||||
|
||||
VS_CALL_LISTENERS(OnEndCutScene(pSeq));
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "VisRegTest.h"
|
||||
|
||||
#include "ISystem.h"
|
||||
#include "I3DEngine.h"
|
||||
#include "IRenderer.h"
|
||||
#include "IConsole.h"
|
||||
#include "ITimer.h"
|
||||
|
||||
@@ -57,7 +57,6 @@ set(FILES
|
||||
UnixConsole.h
|
||||
SystemInit.h
|
||||
Serialization/MemoryReader.h
|
||||
Statistics/LocalMemoryUsage.h
|
||||
MemoryFragmentationProfiler.h
|
||||
XML/ReadWriteXMLSink.h
|
||||
Serialization/ArchiveHost.h
|
||||
@@ -151,7 +150,6 @@ set(FILES
|
||||
MiniGUI/MiniInfoBox.h
|
||||
MiniGUI/MiniMenu.h
|
||||
MiniGUI/MiniTable.h
|
||||
Statistics/LocalMemoryUsage.cpp
|
||||
ZLibCompressor.cpp
|
||||
ZLibCompressor.h
|
||||
SoftCode/SoftCodeMgr.cpp
|
||||
|
||||
@@ -239,8 +239,13 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
CheckReady();
|
||||
m_initComplete = true;
|
||||
|
||||
// *After* setting initComplete to true, check to see if the assets are already ready.
|
||||
// This check needs to wait until after setting initComplete because if they *are* ready, we want the final call to
|
||||
// RemoveWaitingAsset to trigger the OnAssetContainerReady/Canceled event. If we call CheckReady() *before* setting
|
||||
// initComplete, if all the assets are ready, the event will never get triggered.
|
||||
CheckReady();
|
||||
}
|
||||
|
||||
bool AssetContainer::IsReady() const
|
||||
|
||||
@@ -1454,32 +1454,48 @@ namespace AZ
|
||||
//=========================================================================
|
||||
void AssetManager::ReloadAssetFromData(const Asset<AssetData>& asset)
|
||||
{
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(m_assets.find(asset.GetId()) != m_assets.end(), "Unable to reload asset %s because its not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(m_assets.find(asset.GetId()) == m_assets.end() || asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
bool shouldAssignAssetData = false;
|
||||
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
AZ_Assert(asset.Get(), "Asset data for reload is missing.");
|
||||
AZStd::scoped_lock<AZStd::recursive_mutex> assetLock(m_assetMutex);
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) != m_assets.end(),
|
||||
"Unable to reload asset %s because it's not in the AssetManager's asset list.", asset.ToString<AZStd::string>().c_str());
|
||||
AZ_Assert(
|
||||
m_assets.find(asset.GetId()) == m_assets.end() ||
|
||||
asset->RTTI_GetType() == m_assets.find(asset.GetId())->second->RTTI_GetType(),
|
||||
"New and old data types are mismatched!");
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
auto found = m_assets.find(asset.GetId());
|
||||
if ((found == m_assets.end()) || (asset->RTTI_GetType() != found->second->RTTI_GetType()))
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
return; // this will just lead to crashes down the line and the above asserts cover this.
|
||||
}
|
||||
|
||||
AssetData* newData = asset.Get();
|
||||
|
||||
if (found->second != newData)
|
||||
{
|
||||
// Notify users that we are about to change asset
|
||||
AssetBus::Event(asset.GetId(), &AssetBus::Events::OnAssetPreReload, asset);
|
||||
|
||||
// Resolve the asset handler and account for the new asset instance.
|
||||
{
|
||||
AssetHandlerMap::iterator handlerIt = m_handlers.find(newData->GetType());
|
||||
AZ_Assert(
|
||||
handlerIt != m_handlers.end(), "No handler was registered for this asset [type:%s id:%s]!",
|
||||
newData->GetType().ToString<AZ::OSString>().c_str(), newData->GetId().ToString<AZ::OSString>().c_str());
|
||||
}
|
||||
|
||||
shouldAssignAssetData = true;
|
||||
}
|
||||
}
|
||||
|
||||
// We specifically perform this outside of the m_assetMutex lock so that the lock isn't held at the point that
|
||||
// OnAssetReload is triggered inside of AssignAssetData. Otherwise, we open up a high potential for deadlocks.
|
||||
if (shouldAssignAssetData)
|
||||
{
|
||||
AssignAssetData(asset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,27 +142,44 @@ namespace AZ
|
||||
void SetBasis(const Vector3& basisX, const Vector3& basisY, const Vector3& basisZ);
|
||||
//! @}
|
||||
|
||||
Matrix3x3 operator*(const Matrix3x3& rhs) const;
|
||||
|
||||
//! Calculates (this->GetTranspose() * rhs).
|
||||
Matrix3x3 TransposedMultiply(const Matrix3x3& rhs) const;
|
||||
|
||||
//! Post-multiplies the matrix by a vector.
|
||||
Vector3 operator*(const Vector3& rhs) const;
|
||||
|
||||
Matrix3x3 operator+(const Matrix3x3& rhs) const;
|
||||
Matrix3x3 operator-(const Matrix3x3& rhs) const;
|
||||
|
||||
Matrix3x3 operator*(float multiplier) const;
|
||||
Matrix3x3 operator/(float divisor) const;
|
||||
|
||||
Matrix3x3 operator-() const;
|
||||
|
||||
Matrix3x3& operator*=(const Matrix3x3& rhs);
|
||||
//! Operator for matrix-matrix addition.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x3 operator+(const Matrix3x3& rhs) const;
|
||||
Matrix3x3& operator+=(const Matrix3x3& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for matrix-matrix substraction.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x3 operator-(const Matrix3x3& rhs) const;
|
||||
Matrix3x3& operator-=(const Matrix3x3& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for matrix-matrix multiplication.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x3 operator*(const Matrix3x3& rhs) const;
|
||||
Matrix3x3& operator*=(const Matrix3x3& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for multiplying all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x3 operator*(float multiplier) const;
|
||||
Matrix3x3& operator*=(float multiplier);
|
||||
//! @}
|
||||
|
||||
//! Operator for dividing all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x3 operator/(float divisor) const;
|
||||
Matrix3x3& operator/=(float divisor);
|
||||
//! @}
|
||||
|
||||
//! Operator for negating all matrix's elements
|
||||
[[nodiscard]] Matrix3x3 operator-() const;
|
||||
|
||||
bool operator==(const Matrix3x3& rhs) const;
|
||||
bool operator!=(const Matrix3x3& rhs) const;
|
||||
@@ -187,7 +204,10 @@ namespace AZ
|
||||
//! @}
|
||||
|
||||
//! Gets the scale part of the transformation, i.e. the length of the scale components.
|
||||
Vector3 RetrieveScale() const;
|
||||
[[nodiscard]] Vector3 RetrieveScale() const;
|
||||
|
||||
//! Gets the squared scale part of the transformation (the squared length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScaleSq() const;
|
||||
|
||||
//! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix.
|
||||
Vector3 ExtractScale();
|
||||
@@ -195,6 +215,9 @@ namespace AZ
|
||||
//! Quick multiplication by a scale matrix, equivalent to m*=Matrix3x3::CreateScale(scale).
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Returns a matrix with the reciprocal scale, keeping the same rotation and translation.
|
||||
[[nodiscard]] Matrix3x3 GetReciprocalScaled() const;
|
||||
|
||||
//! Polar decomposition, M=U*H, U is orthogonal (unitary) and H is symmetric (hermitian).
|
||||
//! This function returns the orthogonal part only
|
||||
Matrix3x3 GetPolarDecomposition() const;
|
||||
@@ -241,7 +264,9 @@ namespace AZ
|
||||
//! Note that this is not the usual multiplication order for transformations.
|
||||
Vector3& operator*=(Vector3& lhs, const Matrix3x3& rhs);
|
||||
|
||||
//! Pre-multiplies the matrix by a scalar.
|
||||
Matrix3x3 operator*(float lhs, const Matrix3x3& rhs);
|
||||
}
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
#include <AzCore/Math/Matrix3x3.inl>
|
||||
|
||||
@@ -392,14 +392,6 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(const Matrix3x3& rhs) const
|
||||
{
|
||||
Matrix3x3 result;
|
||||
Simd::Vec3::Mat3x3Multiply(GetSimdValues(), rhs.GetSimdValues(), result.GetSimdValues());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::TransposedMultiply(const Matrix3x3& rhs) const
|
||||
{
|
||||
Matrix3x3 result;
|
||||
@@ -416,51 +408,12 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator+(const Matrix3x3& rhs) const
|
||||
{
|
||||
return Matrix3x3(Simd::Vec3::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue())
|
||||
, Simd::Vec3::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue())
|
||||
, Simd::Vec3::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-(const Matrix3x3& rhs) const
|
||||
{
|
||||
return Matrix3x3(Simd::Vec3::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue())
|
||||
, Simd::Vec3::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue())
|
||||
, Simd::Vec3::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(float multiplier) const
|
||||
{
|
||||
const Simd::Vec3::FloatType mulVec = Simd::Vec3::Splat(multiplier);
|
||||
return Matrix3x3(Simd::Vec3::Mul(m_rows[0].GetSimdValue(), mulVec)
|
||||
, Simd::Vec3::Mul(m_rows[1].GetSimdValue(), mulVec)
|
||||
, Simd::Vec3::Mul(m_rows[2].GetSimdValue(), mulVec));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator/(float divisor) const
|
||||
{
|
||||
const Simd::Vec3::FloatType divVec = Simd::Vec3::Splat(divisor);
|
||||
return Matrix3x3(Simd::Vec3::Div(m_rows[0].GetSimdValue(), divVec)
|
||||
, Simd::Vec3::Div(m_rows[1].GetSimdValue(), divVec)
|
||||
, Simd::Vec3::Div(m_rows[2].GetSimdValue(), divVec));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-() const
|
||||
{
|
||||
const Simd::Vec3::FloatType zeroVec = Simd::Vec3::ZeroFloat();
|
||||
return Matrix3x3(Simd::Vec3::Sub(zeroVec, m_rows[0].GetSimdValue())
|
||||
, Simd::Vec3::Sub(zeroVec, m_rows[1].GetSimdValue())
|
||||
, Simd::Vec3::Sub(zeroVec, m_rows[2].GetSimdValue()));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(const Matrix3x3& rhs)
|
||||
{
|
||||
*this = *this * rhs;
|
||||
return *this;
|
||||
return Matrix3x3
|
||||
(
|
||||
Simd::Vec3::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec3::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec3::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -471,6 +424,17 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-(const Matrix3x3& rhs) const
|
||||
{
|
||||
return Matrix3x3
|
||||
(
|
||||
Simd::Vec3::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec3::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec3::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator-=(const Matrix3x3& rhs)
|
||||
{
|
||||
*this = *this - rhs;
|
||||
@@ -478,6 +442,33 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(const Matrix3x3& rhs) const
|
||||
{
|
||||
Matrix3x3 result;
|
||||
Simd::Vec3::Mat3x3Multiply(GetSimdValues(), rhs.GetSimdValues(), result.GetSimdValues());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(const Matrix3x3& rhs)
|
||||
{
|
||||
*this = *this * rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator*(float multiplier) const
|
||||
{
|
||||
const Simd::Vec3::FloatType mulVec = Simd::Vec3::Splat(multiplier);
|
||||
return Matrix3x3
|
||||
(
|
||||
Simd::Vec3::Mul(m_rows[0].GetSimdValue(), mulVec),
|
||||
Simd::Vec3::Mul(m_rows[1].GetSimdValue(), mulVec),
|
||||
Simd::Vec3::Mul(m_rows[2].GetSimdValue(), mulVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator*=(float multiplier)
|
||||
{
|
||||
*this = *this * multiplier;
|
||||
@@ -485,6 +476,18 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator/(float divisor) const
|
||||
{
|
||||
const Simd::Vec3::FloatType divVec = Simd::Vec3::Splat(divisor);
|
||||
return Matrix3x3
|
||||
(
|
||||
Simd::Vec3::Div(m_rows[0].GetSimdValue(), divVec),
|
||||
Simd::Vec3::Div(m_rows[1].GetSimdValue(), divVec),
|
||||
Simd::Vec3::Div(m_rows[2].GetSimdValue(), divVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3& Matrix3x3::operator/=(float divisor)
|
||||
{
|
||||
*this = *this / divisor;
|
||||
@@ -492,6 +495,18 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::operator-() const
|
||||
{
|
||||
const Simd::Vec3::FloatType zeroVec = Simd::Vec3::ZeroFloat();
|
||||
return Matrix3x3
|
||||
(
|
||||
Simd::Vec3::Sub(zeroVec, m_rows[0].GetSimdValue()),
|
||||
Simd::Vec3::Sub(zeroVec, m_rows[1].GetSimdValue()),
|
||||
Simd::Vec3::Sub(zeroVec, m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Matrix3x3::operator==(const Matrix3x3& rhs) const
|
||||
{
|
||||
return (Simd::Vec3::CmpAllEq(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue())
|
||||
@@ -552,6 +567,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x3::RetrieveScaleSq() const
|
||||
{
|
||||
return Vector3(GetBasisX().GetLengthSq(), GetBasisY().GetLengthSq(), GetBasisZ().GetLengthSq());
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x3::ExtractScale()
|
||||
{
|
||||
const Vector3 x = GetBasisX();
|
||||
@@ -584,6 +605,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 Matrix3x3::GetReciprocalScaled() const
|
||||
{
|
||||
Matrix3x3 result = *this;
|
||||
result.MultiplyByScale(RetrieveScaleSq().GetReciprocal());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Matrix3x3::GetPolarDecomposition(Matrix3x3* orthogonalOut, Matrix3x3* symmetricOut) const
|
||||
{
|
||||
*orthogonalOut = GetPolarDecomposition();
|
||||
@@ -679,8 +708,6 @@ namespace AZ
|
||||
|
||||
AZ_MATH_INLINE Matrix3x3 operator*(float lhs, const Matrix3x3& rhs)
|
||||
{
|
||||
const Simd::Vec3::FloatType lhsVec = Simd::Vec3::Splat(lhs);
|
||||
const Simd::Vec3::FloatType* rows = rhs.GetSimdValues();
|
||||
return Matrix3x3(Simd::Vec3::Mul(lhsVec, rows[0]), Simd::Vec3::Mul(lhsVec, rows[1]), Simd::Vec3::Mul(lhsVec, rows[2]));
|
||||
return rhs * lhs;
|
||||
}
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -225,11 +225,38 @@ namespace AZ
|
||||
//! Sets the three basis vectors and the translation.
|
||||
void SetBasisAndTranslation(const Vector3& basisX, const Vector3& basisY, const Vector3& basisZ, const Vector3& translation);
|
||||
|
||||
//! Operator for matrix-matrix multiplication.
|
||||
[[nodiscard]] Matrix3x4 operator*(const Matrix3x4& rhs) const;
|
||||
//! Operator for matrix-matrix addition.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x4 operator+(const Matrix3x4& rhs) const;
|
||||
Matrix3x4& operator+=(const Matrix3x4& rhs);
|
||||
//! @}
|
||||
|
||||
//! Compound assignment operator for matrix-matrix multiplication.
|
||||
//! Operator for matrix-matrix substraction.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x4 operator-(const Matrix3x4& rhs) const;
|
||||
Matrix3x4& operator-=(const Matrix3x4& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for matrix-matrix multiplication.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x4 operator*(const Matrix3x4& rhs) const;
|
||||
Matrix3x4& operator*=(const Matrix3x4& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for multiplying all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x4 operator*(float multiplier) const;
|
||||
Matrix3x4& operator*=(float multiplier);
|
||||
//! @}
|
||||
|
||||
//! Operator for dividing all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix3x4 operator/(float divisor) const;
|
||||
Matrix3x4& operator/=(float divisor);
|
||||
//! @}
|
||||
|
||||
//! Operator for negating all matrix's elements
|
||||
[[nodiscard]] Matrix3x4 operator-() const;
|
||||
|
||||
//! Operator for transforming a Vector3.
|
||||
[[nodiscard]] Vector3 operator*(const Vector3& rhs) const;
|
||||
@@ -274,12 +301,18 @@ namespace AZ
|
||||
//! Gets the scale part of the transformation (the length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScale() const;
|
||||
|
||||
//! Gets the squared scale part of the transformation (the squared length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScaleSq() const;
|
||||
|
||||
//! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix.
|
||||
Vector3 ExtractScale();
|
||||
|
||||
//! Multiplies the basis vectors of the matrix by the elements of the scale specified.
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Returns a matrix with the reciprocal scale, keeping the same rotation and translation.
|
||||
[[nodiscard]] Matrix3x4 GetReciprocalScaled() const;
|
||||
|
||||
//! Tests if the 3x3 part of the matrix is orthogonal.
|
||||
bool IsOrthogonal(float tolerance = Constants::Tolerance) const;
|
||||
|
||||
@@ -335,6 +368,10 @@ namespace AZ
|
||||
|
||||
Vector4 m_rows[RowCount];
|
||||
};
|
||||
|
||||
//! Pre-multiplies the matrix by a scalar.
|
||||
Matrix3x4 operator*(float lhs, const Matrix3x4& rhs);
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
#include <AzCore/Math/Matrix3x4.inl>
|
||||
|
||||
@@ -472,6 +472,42 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator+(const Matrix3x4& rhs) const
|
||||
{
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator+=(const Matrix3x4& rhs)
|
||||
{
|
||||
*this = *this + rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator-(const Matrix3x4& rhs) const
|
||||
{
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator-=(const Matrix3x4& rhs)
|
||||
{
|
||||
*this = *this - rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator*(const Matrix3x4& rhs) const
|
||||
{
|
||||
Matrix3x4 result;
|
||||
@@ -487,6 +523,56 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator*(float multiplier) const
|
||||
{
|
||||
const Simd::Vec4::FloatType mulVec = Simd::Vec4::Splat(multiplier);
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Mul(m_rows[0].GetSimdValue(), mulVec),
|
||||
Simd::Vec4::Mul(m_rows[1].GetSimdValue(), mulVec),
|
||||
Simd::Vec4::Mul(m_rows[2].GetSimdValue(), mulVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator*=(float multiplier)
|
||||
{
|
||||
*this = *this * multiplier;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator/(float divisor) const
|
||||
{
|
||||
const Simd::Vec4::FloatType divVec = Simd::Vec4::Splat(divisor);
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Div(m_rows[0].GetSimdValue(), divVec),
|
||||
Simd::Vec4::Div(m_rows[1].GetSimdValue(), divVec),
|
||||
Simd::Vec4::Div(m_rows[2].GetSimdValue(), divVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4& Matrix3x4::operator/=(float divisor)
|
||||
{
|
||||
*this = *this / divisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::operator-() const
|
||||
{
|
||||
const Simd::Vec4::FloatType zeroVec = Simd::Vec4::ZeroFloat();
|
||||
return Matrix3x4
|
||||
(
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[2].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::operator*(const Vector3& rhs) const
|
||||
{
|
||||
return Vector3
|
||||
@@ -583,6 +669,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::RetrieveScaleSq() const
|
||||
{
|
||||
return Vector3(GetColumn(0).GetLengthSq(), GetColumn(1).GetLengthSq(), GetColumn(2).GetLengthSq());
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix3x4::ExtractScale()
|
||||
{
|
||||
const Vector3 scale = RetrieveScale();
|
||||
@@ -600,6 +692,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 Matrix3x4::GetReciprocalScaled() const
|
||||
{
|
||||
Matrix3x4 result = *this;
|
||||
result.MultiplyByScale(RetrieveScaleSq().GetReciprocal());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE void Matrix3x4::Orthogonalize()
|
||||
{
|
||||
*this = GetOrthogonalized();
|
||||
@@ -660,4 +760,10 @@ namespace AZ
|
||||
{
|
||||
return reinterpret_cast<Simd::Vec4::FloatType*>(m_rows);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix3x4 operator*(float lhs, const Matrix3x4& rhs)
|
||||
{
|
||||
return rhs * lhs;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -171,14 +171,38 @@ namespace AZ
|
||||
void SetTranslation(const Vector3& v);
|
||||
//! @}
|
||||
|
||||
Matrix4x4 operator+(const Matrix4x4& rhs) const;
|
||||
//! Operator for matrix-matrix addition.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix4x4 operator+(const Matrix4x4& rhs) const;
|
||||
Matrix4x4& operator+=(const Matrix4x4& rhs);
|
||||
//! @}
|
||||
|
||||
Matrix4x4 operator-(const Matrix4x4& rhs) const;
|
||||
//! Operator for matrix-matrix substraction.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix4x4 operator-(const Matrix4x4& rhs) const;
|
||||
Matrix4x4& operator-=(const Matrix4x4& rhs);
|
||||
//! @}
|
||||
|
||||
Matrix4x4 operator*(const Matrix4x4& rhs) const;
|
||||
//! Operator for matrix-matrix multiplication.
|
||||
//! @{
|
||||
[[nodiscard]] Matrix4x4 operator*(const Matrix4x4& rhs) const;
|
||||
Matrix4x4& operator*=(const Matrix4x4& rhs);
|
||||
//! @}
|
||||
|
||||
//! Operator for multiplying all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix4x4 operator*(float multiplier) const;
|
||||
Matrix4x4& operator*=(float multiplier);
|
||||
//! @}
|
||||
|
||||
//! Operator for dividing all matrix's elements with a scalar
|
||||
//! @{
|
||||
[[nodiscard]] Matrix4x4 operator/(float divisor) const;
|
||||
Matrix4x4& operator/=(float divisor);
|
||||
//! @}
|
||||
|
||||
//! Operator for negating all matrix's elements
|
||||
[[nodiscard]] Matrix4x4 operator-() const;
|
||||
|
||||
//! Post-multiplies the matrix by a vector.
|
||||
//! Assumes that the w-component of the Vector3 is 1.0.
|
||||
@@ -222,7 +246,10 @@ namespace AZ
|
||||
//! @}
|
||||
|
||||
//! Gets the scale part of the transformation, i.e. the length of the scale components.
|
||||
Vector3 RetrieveScale() const;
|
||||
[[nodiscard]] Vector3 RetrieveScale() const;
|
||||
|
||||
//! Gets the squared scale part of the transformation (the squared length of the basis vectors).
|
||||
[[nodiscard]] Vector3 RetrieveScaleSq() const;
|
||||
|
||||
//! Gets the scale part of the transformation as in RetrieveScale, and also removes this scaling from the matrix.
|
||||
Vector3 ExtractScale();
|
||||
@@ -230,6 +257,9 @@ namespace AZ
|
||||
//! Quick multiplication by a scale matrix, equivalent to m*=Matrix4x4::CreateScale(scale).
|
||||
void MultiplyByScale(const Vector3& scale);
|
||||
|
||||
//! Returns a matrix with the reciprocal scale, keeping the same rotation and translation.
|
||||
[[nodiscard]] Matrix4x4 GetReciprocalScaled() const;
|
||||
|
||||
bool IsClose(const Matrix4x4& rhs, float tolerance = Constants::Tolerance) const;
|
||||
|
||||
bool operator==(const Matrix4x4& rhs) const;
|
||||
@@ -270,6 +300,10 @@ namespace AZ
|
||||
//! Pre-multiplies the matrix by a vector in-place.
|
||||
//! Note that this is not the usual multiplication order for transformations.
|
||||
Vector4& operator*=(Vector4& lhs, const Matrix4x4& rhs);
|
||||
}
|
||||
|
||||
//! Pre-multiplies the matrix by a scalar.
|
||||
Matrix4x4 operator*(float lhs, const Matrix4x4& rhs);
|
||||
|
||||
} // namespace AZ
|
||||
|
||||
#include <AzCore/Math/Matrix4x4.inl>
|
||||
|
||||
@@ -480,20 +480,12 @@ namespace AZ
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator+(const Matrix4x4& rhs) const
|
||||
{
|
||||
return Matrix4x4
|
||||
( Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue())
|
||||
, Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue())
|
||||
, Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
, Simd::Vec4::Add(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue()));
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-(const Matrix4x4& rhs) const
|
||||
{
|
||||
return Matrix4x4
|
||||
( Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue())
|
||||
, Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue())
|
||||
, Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue())
|
||||
, Simd::Vec4::Sub(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue()));
|
||||
(
|
||||
Simd::Vec4::Add(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()),
|
||||
Simd::Vec4::Add(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator+=(const Matrix4x4& rhs)
|
||||
@@ -502,6 +494,18 @@ namespace AZ
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-(const Matrix4x4& rhs) const
|
||||
{
|
||||
return Matrix4x4
|
||||
(
|
||||
Simd::Vec4::Sub(m_rows[0].GetSimdValue(), rhs.m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Sub(m_rows[1].GetSimdValue(), rhs.m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Sub(m_rows[2].GetSimdValue(), rhs.m_rows[2].GetSimdValue()),
|
||||
Simd::Vec4::Sub(m_rows[3].GetSimdValue(), rhs.m_rows[3].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator-=(const Matrix4x4& rhs)
|
||||
{
|
||||
*this = *this - rhs;
|
||||
@@ -523,6 +527,59 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator*(float multiplier) const
|
||||
{
|
||||
const Simd::Vec4::FloatType mulVec = Simd::Vec4::Splat(multiplier);
|
||||
return Matrix4x4
|
||||
(
|
||||
Simd::Vec4::Mul(m_rows[0].GetSimdValue(), mulVec),
|
||||
Simd::Vec4::Mul(m_rows[1].GetSimdValue(), mulVec),
|
||||
Simd::Vec4::Mul(m_rows[2].GetSimdValue(), mulVec),
|
||||
Simd::Vec4::Mul(m_rows[3].GetSimdValue(), mulVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator*=(float multiplier)
|
||||
{
|
||||
*this = *this * multiplier;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator/(float divisor) const
|
||||
{
|
||||
const Simd::Vec4::FloatType divVec = Simd::Vec4::Splat(divisor);
|
||||
return Matrix4x4
|
||||
(
|
||||
Simd::Vec4::Div(m_rows[0].GetSimdValue(), divVec),
|
||||
Simd::Vec4::Div(m_rows[1].GetSimdValue(), divVec),
|
||||
Simd::Vec4::Div(m_rows[2].GetSimdValue(), divVec),
|
||||
Simd::Vec4::Div(m_rows[3].GetSimdValue(), divVec)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4& Matrix4x4::operator/=(float divisor)
|
||||
{
|
||||
*this = *this / divisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::operator-() const
|
||||
{
|
||||
const Simd::Vec4::FloatType zeroVec = Simd::Vec4::ZeroFloat();
|
||||
return Matrix4x4
|
||||
(
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[0].GetSimdValue()),
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[1].GetSimdValue()),
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[2].GetSimdValue()),
|
||||
Simd::Vec4::Sub(zeroVec, m_rows[3].GetSimdValue())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix4x4::operator*(const Vector3& rhs) const
|
||||
{
|
||||
return Vector3(Simd::Vec4::Mat4x4TransformPoint3(GetSimdValues(), rhs.GetSimdValue()));
|
||||
@@ -595,6 +652,12 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix4x4::RetrieveScaleSq() const
|
||||
{
|
||||
return Vector3(GetBasisX().GetLengthSq(), GetBasisY().GetLengthSq(), GetBasisZ().GetLengthSq());
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Vector3 Matrix4x4::ExtractScale()
|
||||
{
|
||||
Vector4 x = GetBasisX();
|
||||
@@ -619,6 +682,14 @@ namespace AZ
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 Matrix4x4::GetReciprocalScaled() const
|
||||
{
|
||||
Matrix4x4 result = *this;
|
||||
result.MultiplyByScale(RetrieveScaleSq().GetReciprocal());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE bool Matrix4x4::IsClose(const Matrix4x4& rhs, float tolerance) const
|
||||
{
|
||||
const Simd::Vec4::FloatType vecTolerance = Simd::Vec4::Splat(tolerance);
|
||||
@@ -702,4 +773,10 @@ namespace AZ
|
||||
lhs = lhs * rhs;
|
||||
return lhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AZ_MATH_INLINE Matrix4x4 operator*(float lhs, const Matrix4x4& rhs)
|
||||
{
|
||||
return rhs * lhs;
|
||||
}
|
||||
} // namespace AZ
|
||||
|
||||
@@ -816,7 +816,7 @@ namespace AZ
|
||||
template<size_t Index>
|
||||
static void ReflectUnpackMethodFold(BehaviorContext::ClassBuilder<ContainerType>& builder)
|
||||
{
|
||||
AZStd::string methodName = AZStd::string::format("Get%ld", Index);
|
||||
const AZStd::string methodName = AZStd::string::format("Get%zu", Index);
|
||||
builder->Method(methodName.data(), [](ContainerType& value) { return AZStd::get<Index>(value); })
|
||||
->Attribute(AZ::Script::Attributes::ExcludeFrom, AZ::Script::Attributes::ExcludeFlags::All)
|
||||
->Attribute(AZ::ScriptCanvasAttributes::TupleGetFunctionIndex, Index)
|
||||
|
||||
@@ -97,7 +97,8 @@ namespace AZ
|
||||
return context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
|
||||
AZStd::string::format("Failed to retrieve rtti information for %s.", classData->m_name));
|
||||
}
|
||||
AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch during deserialization of a json file. (%s vs %s)");
|
||||
AZ_Assert(classData->m_azRtti->GetTypeId() == typeId, "Type id mismatch during deserialization of a json file. (%s vs %s)",
|
||||
classData->m_azRtti->GetTypeId().ToString<AZStd::string>().c_str(), typeId.ToString<AZStd::string>().c_str());
|
||||
|
||||
void** objectPtr = reinterpret_cast<void**>(object);
|
||||
bool isNull = *objectPtr == nullptr;
|
||||
@@ -512,27 +513,24 @@ namespace AZ
|
||||
if (*object)
|
||||
{
|
||||
const AZ::Uuid& actualClassId = rtti.GetActualUuid(*object);
|
||||
if (actualClassId != objectType)
|
||||
const SerializeContext::ClassData* actualClassData = context.GetSerializeContext()->FindClassData(actualClassId);
|
||||
if (!actualClassData)
|
||||
{
|
||||
const SerializeContext::ClassData* actualClassData = context.GetSerializeContext()->FindClassData(actualClassId);
|
||||
if (!actualClassData)
|
||||
{
|
||||
status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
|
||||
AZStd::string::format("Unable to find serialization information for type %s.", actualClassId.ToString<AZStd::string>().c_str()));
|
||||
return ResolvePointerResult::FullyProcessed;
|
||||
}
|
||||
status = context.Report(Tasks::RetrieveInfo, Outcomes::Unknown,
|
||||
AZStd::string::format("Unable to find serialization information for type %s.", actualClassId.ToString<AZStd::string>().c_str()));
|
||||
return ResolvePointerResult::FullyProcessed;
|
||||
}
|
||||
|
||||
if (actualClassData->m_factory)
|
||||
{
|
||||
actualClassData->m_factory->Destroy(*object);
|
||||
*object = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = context.Report(Tasks::RetrieveInfo, Outcomes::Catastrophic,
|
||||
"Unable to find the factory needed to clear out the default value.");
|
||||
return ResolvePointerResult::FullyProcessed;
|
||||
}
|
||||
if (actualClassData->m_factory)
|
||||
{
|
||||
actualClassData->m_factory->Destroy(*object);
|
||||
*object = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = context.Report(Tasks::RetrieveInfo, Outcomes::Catastrophic,
|
||||
"Unable to find the factory needed to clear out the default value.");
|
||||
return ResolvePointerResult::FullyProcessed;
|
||||
}
|
||||
}
|
||||
status = ResultCode(Tasks::ReadField, Outcomes::Success);
|
||||
|
||||
@@ -38,6 +38,20 @@ namespace AZ
|
||||
};
|
||||
|
||||
//! Core class to handle serialization to and from json documents.
|
||||
//! The Json Serialization works by taking a default constructed object and then apply the information found in the JSON document
|
||||
//! on top of that object. This allows the Json Serialization to avoid storing default values and helps guarantee that the final
|
||||
//! object is in a valid state even if non-fatal issues are encountered.
|
||||
//! Note on containers: Containers such as vector or map are always considered to be empty even if there's entries in the provided
|
||||
//! default object. During deserialization entries will be appended to any existing values. A flag is provided to automatically
|
||||
//! clear containers during deserialization.
|
||||
//! Note on maps: If the key for map containers such as unordered_map can be interpret as a string the Json Serialization will use
|
||||
//! a JSON Object to store the data in instead of an array with key/value objects.
|
||||
//! Note on pointers: The Json Serialization assumes that are always constructed, so a default JSON value of "{}" is interpret as
|
||||
//! creating a new default instance even if the default value is a null pointer. A JSON Null needs to be explicitly stored in
|
||||
//! the JSON Document in order to default or explicitly set a pointer to null.
|
||||
//! Note on pointer memory: Objects created/destroyed by the Json Serialization for pointers require that the AZ_CLASS_ALLOCATOR is
|
||||
//! declared and the object is created using aznew or memory is allocated using azmalloc. Without these the application may
|
||||
//! crash if the Json Serialization tries to create or destroy an object pointed to by a pointer.
|
||||
class JsonSerialization final
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -23,13 +23,6 @@ namespace AZ
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
if (IsExplicitDefault(inputValue))
|
||||
{
|
||||
// Do nothing if the input is an explicit default.
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::DefaultsUsed,
|
||||
"Default value for smart pointer requested so no change was made.");
|
||||
}
|
||||
|
||||
const SerializeContext::ClassData* containerClass = context.GetSerializeContext()->FindClassData(outputValueTypeId);
|
||||
if (!containerClass)
|
||||
{
|
||||
@@ -153,8 +146,7 @@ namespace AZ
|
||||
|
||||
if (defaultValue)
|
||||
{
|
||||
bool typesMatch = false;
|
||||
auto defaultInputCallback = [&defaultValue, &inputPtrType, &typesMatch]
|
||||
auto defaultInputCallback = [&defaultValue]
|
||||
(void* elementPtr, const Uuid&, const SerializeContext::ClassData*, const SerializeContext::ClassElement*)
|
||||
{
|
||||
defaultValue = elementPtr;
|
||||
@@ -164,11 +156,6 @@ namespace AZ
|
||||
}
|
||||
|
||||
JSR::ResultCode result = ContinueStoring(outputValue, inputValue, defaultValue, inputPtrType, context, Flags::ResolvePointer);
|
||||
if (result.GetOutcome() == JSR::Outcomes::DefaultsUsed)
|
||||
{
|
||||
outputValue = GetExplicitDefault();
|
||||
return context.Report(result, "Smart pointer used all defaults.");
|
||||
}
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted ?
|
||||
"Successfully processed smart pointer." : "A problem occurred while processing a smart pointer.");
|
||||
}
|
||||
|
||||
@@ -330,4 +330,163 @@ namespace UnitTest
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// The AssetManagerStreamerImmediateCompletionTests class adjusts the asset loading to force it to complete immediately,
|
||||
// while still within the callstack for GetAsset(). This can be used to test various conditions in which the load thread
|
||||
// completes more rapidly than expected, and can expose subtle race conditions.
|
||||
// There are a few key things that this class does to make this work:
|
||||
// - The file I/O streamer is mocked
|
||||
// - The asset stream data is mocked to a 0-byte length for the asset so that the stream load will bypass the I/O streamer and
|
||||
// just immediately return completion.
|
||||
// - The number of JobManager threads is set to 0, forcing jobs to execute synchronously inline when they are started.
|
||||
// With these changes, GetAssetInternal() will queue the stream, which will immediately call the callback that creates LoadAssetJob,
|
||||
// which immediately executes in-place to process the asset due to the synchronous JobManager.
|
||||
// Note that if we just created the asset in a Ready state, most of the asset loading code is completely bypassed, and so we
|
||||
// wouldn't be able to test for race conditions in the AssetContainer.
|
||||
//
|
||||
// This class also unregisters the catalog and asset handler before shutting down the asset manager. This is done to catch
|
||||
// any outstanding asset references that exist due to loads not completing and cleaning up successfully.
|
||||
struct AssetManagerStreamerImmediateCompletionTests : public BaseAssetManagerTest,
|
||||
public AZ::Data::AssetCatalogRequestBus::Handler,
|
||||
public AZ::Data::AssetHandler,
|
||||
public AZ::Data::AssetCatalog
|
||||
{
|
||||
static inline const AZ::Uuid TestAssetId{"{E970B177-5F45-44EB-A2C4-9F29D9A0B2A2}"};
|
||||
static inline constexpr AZStd::string_view TestAssetPath = "test";
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
BaseAssetManagerTest::SetUp();
|
||||
AssetManager::Descriptor desc;
|
||||
AssetManager::Create(desc);
|
||||
|
||||
// Register the handler and catalog after creation, because we intend to destroy them before AssetManager destruction.
|
||||
// The specific asset we load is irrelevant, so register EmptyAsset.
|
||||
AZ::Data::AssetManager::Instance().RegisterHandler(this, AZ::AzTypeInfo<EmptyAsset>::Uuid());
|
||||
AZ::Data::AssetManager::Instance().RegisterCatalog(this, AZ::AzTypeInfo<EmptyAsset>::Uuid());
|
||||
|
||||
// Intercept messages for finding assets by name so that we can mock out the asset we're loading.
|
||||
AZ::Data::AssetCatalogRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
// Unregister before destroying AssetManager.
|
||||
// This will catch any assets that got stuck in a loading state without getting cleaned up.
|
||||
AZ::Data::AssetManager::Instance().UnregisterCatalog(this);
|
||||
AZ::Data::AssetManager::Instance().UnregisterHandler(this);
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Handler::BusDisconnect();
|
||||
|
||||
AssetManager::Destroy();
|
||||
BaseAssetManagerTest::TearDown();
|
||||
}
|
||||
|
||||
size_t GetNumJobManagerThreads() const override
|
||||
{
|
||||
// Return 0 threads so that the Job Manager executes jobs synchronously inline. This lets us finish a load while still
|
||||
// in the callstack that initiates the load.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create a mock streamer instead of a real one, since we don't really want to load an asset.
|
||||
IO::IStreamer* CreateStreamer() override
|
||||
{
|
||||
m_mockStreamer = AZStd::make_unique<StreamerWrapper>();
|
||||
return &(m_mockStreamer->m_mockStreamer);
|
||||
}
|
||||
|
||||
void DestroyStreamer([[maybe_unused]] IO::IStreamer* streamer) override
|
||||
{
|
||||
m_mockStreamer = nullptr;
|
||||
}
|
||||
|
||||
// AssetHandler implementation
|
||||
|
||||
// Minimalist mock to create a new EmptyAsset with the desired asset ID.
|
||||
AZ::Data::AssetPtr CreateAsset(const AZ::Data::AssetId& id, [[maybe_unused]] const AZ::Data::AssetType& type) override
|
||||
{
|
||||
return new EmptyAsset(id);
|
||||
}
|
||||
|
||||
void DestroyAsset(AZ::Data::AssetPtr ptr) override
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
// The mocked-out Asset Catalog handles EmptyAsset types.
|
||||
void GetHandledAssetTypes(AZStd::vector<AZ::Data::AssetType>& assetTypes) override
|
||||
{
|
||||
assetTypes.push_back(AZ::AzTypeInfo<EmptyAsset>::Uuid());
|
||||
}
|
||||
|
||||
// This is a mocked-out load, so just immediately return completion without doing anything.
|
||||
AZ::Data::AssetHandler::LoadResult LoadAssetData(
|
||||
[[maybe_unused]] const AZ::Data::Asset<AZ::Data::AssetData>& asset,
|
||||
[[maybe_unused]] AZStd::shared_ptr<AZ::Data::AssetDataStream> stream,
|
||||
[[maybe_unused]] const AZ::Data::AssetFilterCB& assetLoadFilterCB)
|
||||
{
|
||||
return AZ::Data::AssetHandler::LoadResult::LoadComplete;
|
||||
}
|
||||
|
||||
// AssetCatalogRequestBus implementation
|
||||
|
||||
// Minimalist mocks to provide our desired asset path or asset id
|
||||
AZStd::string GetAssetPathById([[maybe_unused]] const AZ::Data::AssetId& id) override
|
||||
{
|
||||
return TestAssetPath;
|
||||
}
|
||||
AZ::Data::AssetId GetAssetIdByPath(
|
||||
[[maybe_unused]] const char* path, [[maybe_unused]] const AZ::Data::AssetType& typeToRegister,
|
||||
[[maybe_unused]] bool autoRegisterIfNotFound) override
|
||||
{
|
||||
return TestAssetId;
|
||||
}
|
||||
|
||||
// Return the mocked-out information for our test asset
|
||||
AZ::Data::AssetInfo GetAssetInfoById([[maybe_unused]] const AZ::Data::AssetId& id) override
|
||||
{
|
||||
AZ::Data::AssetInfo assetInfo;
|
||||
assetInfo.m_assetId = TestAssetId;
|
||||
assetInfo.m_assetType = AZ::AzTypeInfo<EmptyAsset>::Uuid();
|
||||
assetInfo.m_relativePath = TestAssetPath;
|
||||
return assetInfo;
|
||||
}
|
||||
|
||||
// AssetCatalog implementation
|
||||
|
||||
// Set the mocked-out asset load to have a 0-byte length so that the load skips I/O and immediately returns success
|
||||
AZ::Data::AssetStreamInfo GetStreamInfoForLoad(
|
||||
[[maybe_unused]] const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override
|
||||
{
|
||||
EXPECT_TRUE(type == AZ::AzTypeInfo<EmptyAsset>::Uuid());
|
||||
AZ::Data::AssetStreamInfo info;
|
||||
info.m_dataOffset = 0;
|
||||
info.m_streamName = TestAssetPath;
|
||||
info.m_dataLen = 0;
|
||||
info.m_streamFlags = AZ::IO::OpenMode::ModeRead;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<StreamerWrapper> m_mockStreamer;
|
||||
};
|
||||
|
||||
// This test will verify that even if the asset loading stream/job returns immediately, all of the loading
|
||||
// code works successfully. The test here is fairly simple - it just loads the asset and verifies that it
|
||||
// loaded successfully. The bulk of the test is really in the setup class above, where the load is forced
|
||||
// to complete immediately. Also, the true failure condition is caught in the setup class too, which is
|
||||
// the presence of any assets at the point that the asset handler is unregistered. If they're present, then
|
||||
// the immediate load wasn't truly successful, as it left around extra references to the asset that haven't
|
||||
// been cleaned up.
|
||||
TEST_F(AssetManagerStreamerImmediateCompletionTests, LoadAssetWithImmediateJobCompletion_WorksSuccessfully)
|
||||
{
|
||||
AZ::Data::AssetLoadParameters loadParams;
|
||||
|
||||
auto testAsset =
|
||||
AssetManager::Instance().GetAsset<EmptyAsset>(TestAssetId, AZ::Data::AssetLoadBehavior::Default, loadParams);
|
||||
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
EXPECT_TRUE(testAsset.IsReady());
|
||||
}
|
||||
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -24,6 +24,13 @@ namespace UnitTest
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(EmptyAsset, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(EmptyAsset, "{098E3F7F-13AC-414B-9B4E-49B5AD1BD7FE}", AZ::Data::AssetData);
|
||||
|
||||
EmptyAsset(
|
||||
const AZ::Data::AssetId& assetId = AZ::Data::AssetId(),
|
||||
AZ::Data::AssetData::AssetStatus status = AZ::Data::AssetData::AssetStatus::NotLoaded)
|
||||
: AZ::Data::AssetData(assetId, status)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// EmptyAssetWithNoHandler: no data contained within, and no AssetHandler registered for this type
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Math/Transform.h>
|
||||
#include <AzCore/Math/Quaternion.h>
|
||||
#include <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
|
||||
using namespace AZ;
|
||||
|
||||
@@ -251,19 +252,19 @@ namespace UnitTest
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
Matrix3x3 m3 = m1 * m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(66.0f, 72.0f, 78.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(156.0f, 171.0f, 186.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(246.0f, 270.0f, 294.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(66.0f, 72.0f, 78.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(156.0f, 171.0f, 186.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(246.0f, 270.0f, 294.0f)));
|
||||
|
||||
Matrix3x3 m4 = m1;
|
||||
m4 *= m2;
|
||||
AZ_TEST_ASSERT(m4.GetRow(0).IsClose(Vector3(66.0f, 72.0f, 78.0f)));
|
||||
AZ_TEST_ASSERT(m4.GetRow(1).IsClose(Vector3(156.0f, 171.0f, 186.0f)));
|
||||
AZ_TEST_ASSERT(m4.GetRow(2).IsClose(Vector3(246.0f, 270.0f, 294.0f)));
|
||||
EXPECT_THAT(m4.GetRow(0), IsClose(Vector3(66.0f, 72.0f, 78.0f)));
|
||||
EXPECT_THAT(m4.GetRow(1), IsClose(Vector3(156.0f, 171.0f, 186.0f)));
|
||||
EXPECT_THAT(m4.GetRow(2), IsClose(Vector3(246.0f, 270.0f, 294.0f)));
|
||||
m3 = m1.TransposedMultiply(m2);
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(138.0f, 150.0f, 162.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(168.0f, 183.0f, 198.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(198.0f, 216.0f, 234.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(138.0f, 150.0f, 162.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(168.0f, 183.0f, 198.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(198.0f, 216.0f, 234.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestVectorMultiplication)
|
||||
@@ -277,11 +278,11 @@ namespace UnitTest
|
||||
m2.SetRow(1, 10.0f, 11.0f, 12.0f);
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
AZ_TEST_ASSERT((m1 * Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(14.0f, 32.0f, 50.0f)));
|
||||
EXPECT_THAT((m1 * Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(14.0f, 32.0f, 50.0f)));
|
||||
Vector3 v1(1.0f, 2.0f, 3.0f);
|
||||
AZ_TEST_ASSERT((v1 * m1).IsClose(Vector3(30.0f, 36.0f, 42.0f)));
|
||||
EXPECT_THAT((v1 * m1), IsClose(Vector3(30.0f, 36.0f, 42.0f)));
|
||||
v1 *= m1;
|
||||
AZ_TEST_ASSERT(v1.IsClose(Vector3(30.0f, 36.0f, 42.0f)));
|
||||
EXPECT_THAT(v1, IsClose(Vector3(30.0f, 36.0f, 42.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestSum)
|
||||
@@ -296,15 +297,15 @@ namespace UnitTest
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
Matrix3x3 m3 = m1 + m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(20.0f, 22.0f, 24.0f)));
|
||||
|
||||
m3 = m1;
|
||||
m3 += m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(20.0f, 22.0f, 24.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestDifference)
|
||||
@@ -319,14 +320,14 @@ namespace UnitTest
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
Matrix3x3 m3 = m1 - m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
m3 = m1;
|
||||
m3 -= m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(-6.0f, -6.0f, -6.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestScalarMultiplication)
|
||||
@@ -341,18 +342,18 @@ namespace UnitTest
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
Matrix3x3 m3 = m1 * 2.0f;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
m3 = m1;
|
||||
m3 *= 2.0f;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
m3 = 2.0f * m1;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestScalarDivision)
|
||||
@@ -367,18 +368,32 @@ namespace UnitTest
|
||||
m2.SetRow(2, 13.0f, 14.0f, 15.0f);
|
||||
|
||||
Matrix3x3 m3 = m1 / 0.5f;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
m3 = m1;
|
||||
m3 /= 0.5f;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
m3 = -m1;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector3(-1.0f, -2.0f, -3.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector3(-4.0f, -5.0f, -6.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector3(-7.0f, -8.0f, -9.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector3(2.0f, 4.0f, 6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector3(8.0f, 10.0f, 12.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector3(14.0f, 16.0f, 18.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestNegation)
|
||||
{
|
||||
Matrix3x3 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f);
|
||||
m1.SetRow(1, 4.0f, 5.0f, 6.0f);
|
||||
m1.SetRow(2, 7.0f, 8.0f, 9.0f);
|
||||
EXPECT_THAT(-(-m1), IsClose(m1));
|
||||
EXPECT_THAT(-Matrix3x3::CreateZero(), IsClose(Matrix3x3::CreateZero()));
|
||||
|
||||
Matrix3x3 m2 = -m1;
|
||||
EXPECT_THAT(m2.GetRow(0), IsClose(Vector3(-1.0f, -2.0f, -3.0f)));
|
||||
EXPECT_THAT(m2.GetRow(1), IsClose(Vector3(-4.0f, -5.0f, -6.0f)));
|
||||
EXPECT_THAT(m2.GetRow(2), IsClose(Vector3(-7.0f, -8.0f, -9.0f)));
|
||||
|
||||
Matrix3x3 m3 = m1 + (-m1);
|
||||
EXPECT_THAT(m3, IsClose(Matrix3x3::CreateZero()));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestTranspose)
|
||||
@@ -425,11 +440,33 @@ namespace UnitTest
|
||||
TEST(MATH_Matrix3x3, TestScaleAccess)
|
||||
{
|
||||
Matrix3x3 m1 = Matrix3x3::CreateRotationX(DegToRad(40.0f)) * Matrix3x3::CreateScale(Vector3(2.0f, 3.0f, 4.0f));
|
||||
AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
AZ_TEST_ASSERT(m1.ExtractScale().IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3::CreateOne()));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
EXPECT_THAT(m1.ExtractScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3::CreateOne()));
|
||||
m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f));
|
||||
AZ_TEST_ASSERT(m1.RetrieveScale().IsClose(Vector3(3.0f, 4.0f, 5.0f)));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(3.0f, 4.0f, 5.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestScaleSqAccess)
|
||||
{
|
||||
Matrix3x3 m1 = Matrix3x3::CreateRotationX(DegToRad(40.0f)) * Matrix3x3::CreateScale(Vector3(2.0f, 3.0f, 4.0f));
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(4.0f, 9.0f, 16.0f)));
|
||||
m1.ExtractScale();
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3::CreateOne()));
|
||||
m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f));
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(9.0f, 16.0f, 25.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestReciprocalScaled)
|
||||
{
|
||||
Matrix3x3 orthogonalMatrix = Matrix3x3::CreateRotationX(DegToRad(40.0f));
|
||||
EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix));
|
||||
const AZ::Vector3 scale(2.8f, 0.7f, 1.3f);
|
||||
AZ::Matrix3x3 scaledMatrix = orthogonalMatrix;
|
||||
scaledMatrix.MultiplyByScale(scale);
|
||||
AZ::Matrix3x3 reciprocalScaledMatrix = orthogonalMatrix;
|
||||
reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal());
|
||||
EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x3, TestPolarDecomposition)
|
||||
|
||||
@@ -467,21 +467,136 @@ namespace UnitTest
|
||||
EXPECT_THAT(matrix.Multiply3x3(axisDirection), IsClose(forwardDirection));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, MultiplyByMatrix3x4)
|
||||
TEST(MATH_Matrix3x4, TestMatrixMultiplication)
|
||||
{
|
||||
const AZ::Matrix3x4 matrix1 = AZ::Matrix3x4::CreateFromValue(1.2f);
|
||||
const AZ::Matrix3x4 matrix2 = AZ::Matrix3x4::CreateDiagonal(AZ::Vector3(1.3f, 1.5f, 0.4f));
|
||||
const AZ::Matrix3x4 matrix3 = AZ::Matrix3x4::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion(0.42f, 0.46f, -0.66f, 0.42f), AZ::Vector3(2.8f, -3.7f, 1.6f));
|
||||
const AZ::Matrix3x4 matrix4 = AZ::Matrix3x4::CreateRotationX(-0.7f) * AZ::Matrix3x4::CreateScale(AZ::Vector3(0.6f, 1.3f, 0.7f));
|
||||
AZ::Matrix3x4 matrix5 = matrix1;
|
||||
matrix5 *= matrix4;
|
||||
const AZ::Vector3 vector(1.9f, 2.3f, 0.2f);
|
||||
EXPECT_TRUE((matrix1 * (matrix2 * matrix3)).IsClose((matrix1 * matrix2) * matrix3));
|
||||
EXPECT_THAT((matrix3 * matrix4) * vector, IsClose(matrix3 * (matrix4 * vector)));
|
||||
EXPECT_TRUE((matrix2 * AZ::Matrix3x4::Identity()).IsClose(matrix2));
|
||||
EXPECT_TRUE((matrix3 * AZ::Matrix3x4::Identity()).IsClose(AZ::Matrix3x4::Identity() * matrix3));
|
||||
EXPECT_TRUE(matrix5.IsClose(matrix1 * matrix4));
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
AZ::Matrix3x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
AZ::Matrix3x4 m3 = m1 * m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(74.0f, 80.0f, 86.0f, 96.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(206.0f, 224.0f, 242.0f, 268.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(338.0f, 368.0f, 398.0f, 440.0f)));
|
||||
AZ::Matrix3x4 m4 = m1;
|
||||
m4 *= m2;
|
||||
EXPECT_THAT(m4.GetRow(0), IsClose(AZ::Vector4(74.0f, 80.0f, 86.0f, 96.0f)));
|
||||
EXPECT_THAT(m4.GetRow(1), IsClose(AZ::Vector4(206.0f, 224.0f, 242.0f, 268.0f)));
|
||||
EXPECT_THAT(m4.GetRow(2), IsClose(AZ::Vector4(338.0f, 368.0f, 398.0f, 440.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, TestSum)
|
||||
{
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
AZ::Matrix3x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
|
||||
AZ::Matrix3x4 m3 = m1 + m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(8.0f, 10.0f, 12.0f, 14.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(16.0f, 18.0f, 20.0f, 22.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(24.0f, 26.0f, 28.0f, 30.0f)));
|
||||
|
||||
m3 = m1;
|
||||
m3 += m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(8.0f, 10.0f, 12.0f, 14.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(16.0f, 18.0f, 20.0f, 22.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(24.0f, 26.0f, 28.0f, 30.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, TestDifference)
|
||||
{
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
AZ::Matrix3x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
|
||||
AZ::Matrix3x4 m3 = m1 - m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
m3 = m1;
|
||||
m3 -= m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, TestScalarMultiplication)
|
||||
{
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
AZ::Matrix3x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
|
||||
AZ::Matrix3x4 m3 = m1 * 2.0f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
m3 = m1;
|
||||
m3 *= 2.0f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
m3 = 2.0f * m1;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, TestScalarDivision)
|
||||
{
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
AZ::Matrix3x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
|
||||
AZ::Matrix3x4 m3 = m1 / 0.5f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
m3 = m1;
|
||||
m3 /= 0.5f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(AZ::Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(AZ::Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(AZ::Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, TestNegation)
|
||||
{
|
||||
AZ::Matrix3x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
EXPECT_THAT(-(-m1), IsClose(m1));
|
||||
EXPECT_THAT(-AZ::Matrix3x4::CreateZero(), IsClose(AZ::Matrix3x4::CreateZero()));
|
||||
|
||||
AZ::Matrix3x4 m2 = -m1;
|
||||
EXPECT_THAT(m2.GetRow(0), IsClose(AZ::Vector4(-1.0f, -2.0f, -3.0f, -4.0f)));
|
||||
EXPECT_THAT(m2.GetRow(1), IsClose(AZ::Vector4(-5.0f, -6.0f, -7.0f, -8.0f)));
|
||||
EXPECT_THAT(m2.GetRow(2), IsClose(AZ::Vector4(-9.0f, -10.0f, -11.0f, -12.0f)));
|
||||
|
||||
AZ::Matrix3x4 m3 = m1 + (-m1);
|
||||
EXPECT_THAT(m3, IsClose(AZ::Matrix3x4::CreateZero()));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix3x4, MultiplyByVector3)
|
||||
@@ -652,6 +767,34 @@ namespace UnitTest
|
||||
EXPECT_THAT(scaledMatrix.RetrieveScale(), IsClose(AZ::Vector3::CreateOne()));
|
||||
}
|
||||
|
||||
TEST_P(Matrix3x4ScaleFixture, ScaleSq)
|
||||
{
|
||||
const AZ::Matrix3x4 orthogonalMatrix = GetParam();
|
||||
EXPECT_THAT(orthogonalMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne()));
|
||||
AZ::Matrix3x4 unscaledMatrix = orthogonalMatrix;
|
||||
unscaledMatrix.ExtractScale();
|
||||
EXPECT_THAT(unscaledMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne()));
|
||||
const AZ::Vector3 scale(2.8f, 0.7f, 1.3f);
|
||||
AZ::Matrix3x4 scaledMatrix = orthogonalMatrix;
|
||||
scaledMatrix.MultiplyByScale(scale);
|
||||
EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(scale * scale));
|
||||
EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(scaledMatrix.RetrieveScale() * scaledMatrix.RetrieveScale()));
|
||||
scaledMatrix.ExtractScale();
|
||||
EXPECT_THAT(scaledMatrix.RetrieveScaleSq(), IsClose(AZ::Vector3::CreateOne()));
|
||||
}
|
||||
|
||||
TEST_P(Matrix3x4ScaleFixture, GetReciprocalScaled)
|
||||
{
|
||||
const AZ::Matrix3x4 orthogonalMatrix = GetParam();
|
||||
EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix));
|
||||
const AZ::Vector3 scale(2.8f, 0.7f, 1.3f);
|
||||
AZ::Matrix3x4 scaledMatrix = orthogonalMatrix;
|
||||
scaledMatrix.MultiplyByScale(scale);
|
||||
AZ::Matrix3x4 reciprocalScaledMatrix = orthogonalMatrix;
|
||||
reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal());
|
||||
EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(MATH_Matrix3x4, Matrix3x4ScaleFixture, ::testing::ValuesIn(MathTestData::OrthogonalMatrix3x4s));
|
||||
|
||||
TEST(MATH_Matrix3x4, IsOrthogonal)
|
||||
|
||||
@@ -246,16 +246,16 @@ namespace UnitTest
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f);
|
||||
Matrix4x4 m3 = m1 * m2;
|
||||
AZ_TEST_ASSERT(m3.GetRow(0).IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(1).IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(2).IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f)));
|
||||
AZ_TEST_ASSERT(m3.GetRow(3).IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f)));
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f)));
|
||||
Matrix4x4 m4 = m1;
|
||||
m4 *= m2;
|
||||
AZ_TEST_ASSERT(m4.GetRow(0).IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f)));
|
||||
AZ_TEST_ASSERT(m4.GetRow(1).IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f)));
|
||||
AZ_TEST_ASSERT(m4.GetRow(2).IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f)));
|
||||
AZ_TEST_ASSERT(m4.GetRow(3).IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f)));
|
||||
EXPECT_THAT(m4.GetRow(0), IsClose(Vector4(150.0f, 160.0f, 170.0f, 180.0f)));
|
||||
EXPECT_THAT(m4.GetRow(1), IsClose(Vector4(358.0f, 384.0f, 410.0f, 436.0f)));
|
||||
EXPECT_THAT(m4.GetRow(2), IsClose(Vector4(566.0f, 608.0f, 650.0f, 692.0f)));
|
||||
EXPECT_THAT(m4.GetRow(3), IsClose(Vector4(774.0f, 832.0f, 890.0f, 948.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestVectorMultiplication)
|
||||
@@ -265,18 +265,148 @@ namespace UnitTest
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
AZ_TEST_ASSERT((m1 * Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(18.0f, 46.0f, 74.0f)));
|
||||
AZ_TEST_ASSERT((m1 * Vector4(1.0f, 2.0f, 3.0f, 4.0f)).IsClose(Vector4(30.0f, 70.0f, 110.0f, 150.0f)));
|
||||
AZ_TEST_ASSERT(m1.TransposedMultiply3x3(Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(38.0f, 44.0f, 50.0f)));
|
||||
AZ_TEST_ASSERT(m1.Multiply3x3(Vector3(1.0f, 2.0f, 3.0f)).IsClose(Vector3(14.0f, 38.0f, 62.0f)));
|
||||
EXPECT_THAT((m1 * Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(18.0f, 46.0f, 74.0f)));
|
||||
EXPECT_THAT((m1 * Vector4(1.0f, 2.0f, 3.0f, 4.0f)), IsClose(Vector4(30.0f, 70.0f, 110.0f, 150.0f)));
|
||||
EXPECT_THAT(m1.TransposedMultiply3x3(Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(38.0f, 44.0f, 50.0f)));
|
||||
EXPECT_THAT(m1.Multiply3x3(Vector3(1.0f, 2.0f, 3.0f)), IsClose(Vector3(14.0f, 38.0f, 62.0f)));
|
||||
Vector3 v1(1.0f, 2.0f, 3.0f);
|
||||
AZ_TEST_ASSERT((v1 * m1).IsClose(Vector3(51.0f, 58.0f, 65.0f)));
|
||||
EXPECT_THAT((v1 * m1), IsClose(Vector3(51.0f, 58.0f, 65.0f)));
|
||||
v1 *= m1;
|
||||
AZ_TEST_ASSERT(v1.IsClose(Vector3(51.0f, 58.0f, 65.0f)));
|
||||
EXPECT_THAT(v1, IsClose(Vector3(51.0f, 58.0f, 65.0f)));
|
||||
Vector4 v2(1.0f, 2.0f, 3.0f, 4.0f);
|
||||
AZ_TEST_ASSERT((v2 * m1).IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f)));
|
||||
EXPECT_THAT((v2 * m1), IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f)));
|
||||
v2 *= m1;
|
||||
AZ_TEST_ASSERT(v2.IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f)));
|
||||
EXPECT_THAT(v2, IsClose(Vector4(90.0f, 100.0f, 110.0f, 120.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestSum)
|
||||
{
|
||||
Matrix4x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
Matrix4x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f);
|
||||
|
||||
Matrix4x4 m3 = m1 + m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(8.0f, 10.0f, 12.0f, 14.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(16.0f, 18.0f, 20.0f, 22.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(24.0f, 26.0f, 28.0f, 30.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(32.0f, 34.0f, 36.0f, 38.0f)));
|
||||
|
||||
m3 = m1;
|
||||
m3 += m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(8.0f, 10.0f, 12.0f, 14.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(16.0f, 18.0f, 20.0f, 22.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(24.0f, 26.0f, 28.0f, 30.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(32.0f, 34.0f, 36.0f, 38.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestDifference)
|
||||
{
|
||||
Matrix4x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
Matrix4x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f);
|
||||
|
||||
Matrix4x4 m3 = m1 - m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
m3 = m1;
|
||||
m3 -= m2;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(-6.0f, -6.0f, -6.0f, -6.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestScalarMultiplication)
|
||||
{
|
||||
Matrix4x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
Matrix4x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f);
|
||||
|
||||
Matrix4x4 m3 = m1 * 2.0f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f)));
|
||||
m3 = m1;
|
||||
m3 *= 2.0f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f)));
|
||||
m3 = 2.0f * m1;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestScalarDivision)
|
||||
{
|
||||
Matrix4x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
Matrix4x4 m2;
|
||||
m2.SetRow(0, 7.0f, 8.0f, 9.0f, 10.0f);
|
||||
m2.SetRow(1, 11.0f, 12.0f, 13.0f, 14.0f);
|
||||
m2.SetRow(2, 15.0f, 16.0f, 17.0f, 18.0f);
|
||||
m2.SetRow(3, 19.0f, 20.0f, 21.0f, 22.0f);
|
||||
|
||||
Matrix4x4 m3 = m1 / 0.5f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f)));
|
||||
m3 = m1;
|
||||
m3 /= 0.5f;
|
||||
EXPECT_THAT(m3.GetRow(0), IsClose(Vector4(2.0f, 4.0f, 6.0f, 8.0f)));
|
||||
EXPECT_THAT(m3.GetRow(1), IsClose(Vector4(10.0f, 12.0f, 14.0f, 16.0f)));
|
||||
EXPECT_THAT(m3.GetRow(2), IsClose(Vector4(18.0f, 20.0f, 22.0f, 24.0f)));
|
||||
EXPECT_THAT(m3.GetRow(3), IsClose(Vector4(26.0f, 28.0f, 30.0f, 32.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestNegation)
|
||||
{
|
||||
Matrix4x4 m1;
|
||||
m1.SetRow(0, 1.0f, 2.0f, 3.0f, 4.0f);
|
||||
m1.SetRow(1, 5.0f, 6.0f, 7.0f, 8.0f);
|
||||
m1.SetRow(2, 9.0f, 10.0f, 11.0f, 12.0f);
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
EXPECT_THAT(-(-m1), IsClose(m1));
|
||||
EXPECT_THAT(-Matrix4x4::CreateZero(), IsClose(Matrix4x4::CreateZero()));
|
||||
|
||||
Matrix4x4 m2 = -m1;
|
||||
EXPECT_THAT(m2.GetRow(0), IsClose(Vector4(-1.0f, -2.0f, -3.0f, -4.0f)));
|
||||
EXPECT_THAT(m2.GetRow(1), IsClose(Vector4(-5.0f, -6.0f, -7.0f, -8.0f)));
|
||||
EXPECT_THAT(m2.GetRow(2), IsClose(Vector4(-9.0f, -10.0f, -11.0f, -12.0f)));
|
||||
EXPECT_THAT(m2.GetRow(3), IsClose(Vector4(-13.0f, -14.0f, -15.0f, -16.0f)));
|
||||
|
||||
Matrix4x4 m3 = m1 + (-m1);
|
||||
EXPECT_THAT(m3, IsClose(Matrix4x4::CreateZero()));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestTranspose)
|
||||
@@ -368,4 +498,36 @@ namespace UnitTest
|
||||
m1.SetRow(3, 13.0f, 14.0f, 15.0f, 16.0f);
|
||||
AZ_TEST_ASSERT(m1.GetDiagonal() == Vector4(1.0f, 6.0f, 11.0f, 16.0f));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestScaleAccess)
|
||||
{
|
||||
Matrix4x4 m1 = Matrix4x4::CreateRotationX(DegToRad(40.0f)) * Matrix4x4::CreateScale(Vector3(2.0f, 3.0f, 4.0f));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
EXPECT_THAT(m1.ExtractScale(), IsClose(Vector3(2.0f, 3.0f, 4.0f)));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3::CreateOne()));
|
||||
m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f));
|
||||
EXPECT_THAT(m1.RetrieveScale(), IsClose(Vector3(3.0f, 4.0f, 5.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestScaleSqAccess)
|
||||
{
|
||||
Matrix4x4 m1 = Matrix4x4::CreateRotationX(DegToRad(40.0f)) * Matrix4x4::CreateScale(Vector3(2.0f, 3.0f, 4.0f));
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(4.0f, 9.0f, 16.0f)));
|
||||
m1.ExtractScale();
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3::CreateOne()));
|
||||
m1.MultiplyByScale(Vector3(3.0f, 4.0f, 5.0f));
|
||||
EXPECT_THAT(m1.RetrieveScaleSq(), IsClose(Vector3(9.0f, 16.0f, 25.0f)));
|
||||
}
|
||||
|
||||
TEST(MATH_Matrix4x4, TestReciprocalScaled)
|
||||
{
|
||||
Matrix4x4 orthogonalMatrix = Matrix4x4::CreateRotationX(DegToRad(40.0f));
|
||||
EXPECT_THAT(orthogonalMatrix.GetReciprocalScaled(), IsClose(orthogonalMatrix));
|
||||
const AZ::Vector3 scale(2.8f, 0.7f, 1.3f);
|
||||
AZ::Matrix4x4 scaledMatrix = orthogonalMatrix;
|
||||
scaledMatrix.MultiplyByScale(scale);
|
||||
AZ::Matrix4x4 reciprocalScaledMatrix = orthogonalMatrix;
|
||||
reciprocalScaledMatrix.MultiplyByScale(scale.GetReciprocal());
|
||||
EXPECT_THAT(scaledMatrix.GetReciprocalScaled(), IsClose(reciprocalScaledMatrix));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace JsonSerializationTests
|
||||
EXPECT_EQ(42, value);
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueLoading_PointerInstance_ValueLoadedCorrectly)
|
||||
TEST_F(BaseJsonSerializerTests, ContinueLoading_ToPointerInstance_ValueLoadedCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
@@ -126,6 +126,51 @@ namespace JsonSerializationTests
|
||||
EXPECT_EQ(42, value);
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueLoading_ToNullPointer_ValueLoadedCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
rapidjson::Value json;
|
||||
json.Set(42);
|
||||
int* ptrValue = nullptr;
|
||||
|
||||
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
ASSERT_NE(nullptr, ptrValue);
|
||||
EXPECT_EQ(42, *ptrValue);
|
||||
|
||||
azfree(ptrValue, AZ::SystemAllocator, sizeof(int), alignof(int));
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueLoading_DefaultToNullPointer_ValueLoadedCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
rapidjson::Value json(rapidjson::kObjectType);
|
||||
int* ptrValue = nullptr;
|
||||
|
||||
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
ASSERT_NE(nullptr, ptrValue);
|
||||
|
||||
azfree(ptrValue, AZ::SystemAllocator, sizeof(int), alignof(int));
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueLoading_NullDeletesObject_ValueLoadedCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
rapidjson::Value json(rapidjson::kNullType);
|
||||
int* ptrValue = reinterpret_cast<int*>(azmalloc(sizeof(int), alignof(int), AZ::SystemAllocator));
|
||||
|
||||
ResultCode result = ContinueLoading(&ptrValue, azrtti_typeid<int>(), json, *m_jsonDeserializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
ASSERT_EQ(nullptr, ptrValue);
|
||||
}
|
||||
|
||||
//
|
||||
// ContinueStoring
|
||||
//
|
||||
@@ -156,6 +201,64 @@ namespace JsonSerializationTests
|
||||
Expect_DocStrEq("42");
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToFullDefaultedInstance_ValueStoredCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
int value = 42;
|
||||
int* ptrValue = &value;
|
||||
int value2 = 42;
|
||||
int* defaultPtrValue = &value2;
|
||||
|
||||
ResultCode result =
|
||||
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
Expect_DocStrEq("{}");
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptr_ValueStoredCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
int* ptrValue = nullptr;
|
||||
|
||||
ResultCode result = ContinueStoring(
|
||||
*m_jsonDocument, &ptrValue, nullptr, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
Expect_DocStrEq("null");
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithValueDefault_ValueStoredCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
int* ptrValue = nullptr;
|
||||
int value2 = 42;
|
||||
int* defaultPtrValue = &value2;
|
||||
|
||||
ResultCode result =
|
||||
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
Expect_DocStrEq("null");
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueStoring_StorePointerToNullptrWithNullPtrDefault_NullPtrIsStored)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
int* ptrValue = nullptr;
|
||||
int* defaultPtrValue = nullptr;
|
||||
|
||||
ResultCode result =
|
||||
ContinueStoring(*m_jsonDocument, &ptrValue, &defaultPtrValue, azrtti_typeid<int>(), *m_jsonSerializationContext, Flags::ResolvePointer);
|
||||
|
||||
EXPECT_EQ(Processing::Completed, result.GetProcessing());
|
||||
Expect_DocStrEq("null");
|
||||
}
|
||||
|
||||
TEST_F(BaseJsonSerializerTests, ContinueStoring_ReplaceDefault_ValueStoredCorrectly)
|
||||
{
|
||||
using namespace AZ::JsonSerializationResult;
|
||||
|
||||
@@ -32,11 +32,6 @@ namespace JsonSerializationTests
|
||||
return AZStd::make_shared<AZ::JsonSmartPointerSerializer>();
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
|
||||
{
|
||||
return AZStd::make_shared<SmartPointer>();
|
||||
}
|
||||
|
||||
void Reflect(AZStd::unique_ptr<AZ::SerializeContext>& context) override
|
||||
{
|
||||
context->RegisterGenericType<SmartPointer>();
|
||||
@@ -51,6 +46,13 @@ namespace JsonSerializationTests
|
||||
using SmartPointer = T<SimpleClass>;
|
||||
using Base = SmartPointerBaseTestDescription<SmartPointer>;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
|
||||
{
|
||||
auto result = AZStd::make_shared<SmartPointer>();
|
||||
*result = SmartPointer(aznew SimpleClass());
|
||||
return result;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
|
||||
{
|
||||
auto result = AZStd::make_shared<SmartPointer>();
|
||||
@@ -106,21 +108,6 @@ namespace JsonSerializationTests
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename...> class T>
|
||||
class SmartPointerSimpleClassWithInstanceTestDescription :
|
||||
public SmartPointerSimpleClassTestDescription<T>
|
||||
{
|
||||
public:
|
||||
using SmartPointer = typename SmartPointerSimpleClassTestDescription<T>::SmartPointer;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
|
||||
{
|
||||
auto result = AZStd::make_shared<SmartPointer>();
|
||||
*result = SmartPointer(aznew SimpleClass());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template<template<typename...> class T>
|
||||
class SmartPointerSimpleDerivedClassTestDescription :
|
||||
public SmartPointerBaseTestDescription<T<BaseClass>>
|
||||
@@ -129,6 +116,13 @@ namespace JsonSerializationTests
|
||||
using SmartPointer = T<BaseClass>;
|
||||
using Base = SmartPointerBaseTestDescription<SmartPointer>;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
|
||||
{
|
||||
auto result = AZStd::make_shared<SmartPointer>();
|
||||
*result = SmartPointer(aznew BaseClass());
|
||||
return result;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
|
||||
{
|
||||
auto* instance = aznew SimpleInheritence();
|
||||
@@ -272,6 +266,13 @@ namespace JsonSerializationTests
|
||||
using SmartPointer = T<BaseClass2>;
|
||||
using Base = SmartPointerBaseTestDescription<SmartPointer>;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateDefaultInstance() override
|
||||
{
|
||||
auto result = AZStd::make_shared<SmartPointer>();
|
||||
*result = SmartPointer(aznew BaseClass2());
|
||||
return result;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> CreateFullySetInstance() override
|
||||
{
|
||||
auto* instance = aznew MultipleInheritence();
|
||||
@@ -424,9 +425,6 @@ namespace JsonSerializationTests
|
||||
SmartPointerSimpleClassTestDescription<AZStd::unique_ptr>,
|
||||
SmartPointerSimpleClassTestDescription<AZStd::shared_ptr>,
|
||||
SmartPointerSimpleClassTestDescription<AZStd::intrusive_ptr>,
|
||||
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::unique_ptr>,
|
||||
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::shared_ptr>,
|
||||
SmartPointerSimpleClassWithInstanceTestDescription<AZStd::intrusive_ptr>,
|
||||
// Simple derived class, include single inheritance.
|
||||
SmartPointerSimpleDerivedClassTestDescription<AZStd::unique_ptr>,
|
||||
SmartPointerSimpleDerivedClassTestDescription<AZStd::shared_ptr>,
|
||||
@@ -551,6 +549,37 @@ namespace JsonSerializationTests
|
||||
EXPECT_EQ(nullptr, *instance);
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Load_DefaultInstanceToNullptr_ReturnsSuccess)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
SmartPointer instance;
|
||||
AZStd::shared_ptr<SmartPointer> compare = m_description.CreateDefaultInstance();
|
||||
m_jsonDocument->SetObject();
|
||||
|
||||
JSR::ResultCode result =
|
||||
m_serializer.Load(&instance, azrtti_typeid<SmartPointer>(), *m_jsonDocument, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
|
||||
EXPECT_NE(nullptr, instance);
|
||||
EXPECT_TRUE(m_description.AreEqual(instance, *compare));
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Load_DefaultObjectDoesNotUpdateInstance_ReturnsSuccess)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateFullySetInstance();
|
||||
AZStd::shared_ptr<SmartPointer> compare = m_description.CreateFullySetInstance();
|
||||
m_jsonDocument->SetObject();
|
||||
|
||||
JSR::ResultCode result =
|
||||
m_serializer.Load(instance.get(), azrtti_typeid<SmartPointer>(), *m_jsonDocument, *m_jsonDeserializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
|
||||
EXPECT_TRUE(m_description.AreEqual(*instance, *compare));
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Load_InstanceBeingReplacedWithDifferentType_ReturnsSuccess)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
@@ -720,13 +749,66 @@ namespace JsonSerializationTests
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateFullySetInstance();
|
||||
SmartPointer nullPtr;
|
||||
JSR::ResultCode result = m_serializer.Store(*m_jsonDocument, instance.get(), &nullPtr,
|
||||
SmartPointer defaultInstance;
|
||||
JSR::ResultCode result = m_serializer.Store(
|
||||
*m_jsonDocument, instance.get(), &defaultInstance,
|
||||
azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome());
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_ValuePointerIsNullPtr_ReturnsSuccessAndStoresNull)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
SmartPointer instance;
|
||||
AZStd::shared_ptr<SmartPointer> defaultInstance = m_description.CreateFullySetInstance();
|
||||
JSR::ResultCode result = m_serializer.Store(
|
||||
*m_jsonDocument, &instance, defaultInstance.get(), azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Outcomes::Success, result.GetOutcome());
|
||||
EXPECT_TRUE(m_jsonDocument->IsNull());
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreNullPtr_ReturnsSuccessAndStoresNull)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
SmartPointer instance;
|
||||
SmartPointer defaultInstance;
|
||||
JSR::ResultCode result =
|
||||
m_serializer.Store(*m_jsonDocument, &instance, &defaultInstance, azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
|
||||
EXPECT_TRUE(m_jsonDocument->IsNull());
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_ValueAndDefaultPointersAreBothDefault_ReturnsSuccess)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateDefaultInstance();
|
||||
AZStd::shared_ptr<SmartPointer> defaultInstance = m_description.CreateDefaultInstance();
|
||||
JSR::ResultCode result =
|
||||
m_serializer.Store(*m_jsonDocument, instance.get(), defaultInstance.get(), azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
|
||||
Expect_ExplicitDefault(*m_jsonDocument);
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_ValueHasDefaultValuesAndDefaultHasNullPointer_ReturnsSuccess)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
AZStd::shared_ptr<SmartPointer> instance = m_description.CreateDefaultInstance();
|
||||
SmartPointer defaultInstance;
|
||||
JSR::ResultCode result = m_serializer.Store(
|
||||
*m_jsonDocument, instance.get(), &defaultInstance, azrtti_typeid<SmartPointer>(), *m_jsonSerializationContext);
|
||||
|
||||
EXPECT_EQ(JSR::Outcomes::DefaultsUsed, result.GetOutcome());
|
||||
Expect_ExplicitDefault(*m_jsonDocument);
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_DefaultPointerIsOtherClass_CompletesButDoesNotReturnDefaults)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
@@ -749,7 +831,7 @@ namespace JsonSerializationTests
|
||||
EXPECT_EQ(JSR::Processing::Completed, result.GetProcessing());
|
||||
}
|
||||
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_SaveAnClassThatIsNotReflected_ReturnsUnknown)
|
||||
TEST_F(JsonSmartPointerSerializerTests, Store_ClassThatIsNotReflected_ReturnsUnknown)
|
||||
{
|
||||
namespace JSR = AZ::JsonSerializationResult;
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ class ITexture;
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
inline constexpr AZ::s32 g_defaultSceneEntityDebugDisplayId = AZ_CRC_CE("MainViewportEntityDebugDisplayId"); // default id to draw to all viewports in the default scene
|
||||
|
||||
/// DebugDisplayRequests provides a debug draw api to be used by components and viewport features.
|
||||
class DebugDisplayRequests
|
||||
: public AZ::EBusTraits
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace AzFramework::ProjectManager
|
||||
}
|
||||
AZ::IO::FixedMaxPath pythonPath = engineRootPath / "python";
|
||||
pythonPath /= AZ_TRAIT_AZFRAMEWORK_PYTHON_SHELL;
|
||||
auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRId64, pythonPath.Native().c_str(),
|
||||
auto cmdPath = AZ::IO::FixedMaxPathString::format("%s %s%s --executable_path=%s --parent_pid=%" PRIu32, pythonPath.Native().c_str(),
|
||||
debugOption.c_str(), (projectManagerPath / projectsScript).c_str(), executablePath.c_str(), AZ::Platform::GetCurrentProcessId());
|
||||
|
||||
AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo;
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Scene::UnsetSubsystem(const T& system)
|
||||
bool Scene::UnsetSubsystem([[maybe_unused]] const T& system)
|
||||
{
|
||||
const AZ::TypeId& targetType = azrtti_typeid<T>();
|
||||
const size_t systemKeysCount = m_systemKeys.size();
|
||||
|
||||
@@ -148,6 +148,12 @@ namespace AzFramework
|
||||
//! Blocks until all operations made on the provided ticket before the barrier call have completed.
|
||||
virtual void Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback) = 0;
|
||||
|
||||
//! Register a handler for OnSpawned events.
|
||||
virtual void AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) = 0;
|
||||
|
||||
//! Register a handler for OnDespawned events.
|
||||
virtual void AddOnDespawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) = 0;
|
||||
|
||||
protected:
|
||||
[[nodiscard]] virtual void* CreateTicket(AZ::Data::Asset<Spawnable>&& spawnable) = 0;
|
||||
virtual void DestroyTicket(void* ticket) = 0;
|
||||
|
||||
@@ -114,6 +114,16 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_onSpawnedEvent);
|
||||
}
|
||||
|
||||
void SpawnableEntitiesManager::AddOnDespawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler)
|
||||
{
|
||||
handler.Connect(m_onDespawnedEvent);
|
||||
}
|
||||
|
||||
auto SpawnableEntitiesManager::ProcessQueue() -> CommandQueueStatus
|
||||
{
|
||||
AZStd::queue<Requests> pendingRequestQueue;
|
||||
@@ -223,6 +233,8 @@ namespace AzFramework
|
||||
ticket.m_spawnedEntities.begin() + spawnedEntitiesCount, ticket.m_spawnedEntities.end()));
|
||||
}
|
||||
|
||||
m_onSpawnedEvent.Signal(ticket.m_spawnable);
|
||||
|
||||
ticket.m_currentTicketId++;
|
||||
return true;
|
||||
}
|
||||
@@ -257,6 +269,8 @@ namespace AzFramework
|
||||
ticket.m_spawnedEntities.begin() + spawnedEntitiesCount, ticket.m_spawnedEntities.end()));
|
||||
}
|
||||
|
||||
m_onSpawnedEvent.Signal(ticket.m_spawnable);
|
||||
|
||||
ticket.m_currentTicketId++;
|
||||
return true;
|
||||
}
|
||||
@@ -289,6 +303,8 @@ namespace AzFramework
|
||||
request.m_completionCallback(*request.m_ticket);
|
||||
}
|
||||
|
||||
m_onDespawnedEvent.Signal(ticket.m_spawnable);
|
||||
|
||||
ticket.m_currentTicketId++;
|
||||
return true;
|
||||
}
|
||||
@@ -315,6 +331,8 @@ namespace AzFramework
|
||||
&GameEntityContextRequestBus::Events::DestroyGameEntityAndDescendants, entity->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
m_onDespawnedEvent.Signal(ticket.m_spawnable);
|
||||
|
||||
// Rebuild the list of entities.
|
||||
ticket.m_spawnedEntities.clear();
|
||||
@@ -350,6 +368,9 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
ticket.m_currentTicketId++;
|
||||
|
||||
m_onSpawnedEvent.Signal(ticket.m_spawnable);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -60,6 +60,9 @@ namespace AzFramework
|
||||
|
||||
void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback) override;
|
||||
|
||||
void AddOnSpawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) override;
|
||||
void AddOnDespawnedHandler(AZ::Event<AZ::Data::Asset<Spawnable>>::Handler& handler) override;
|
||||
|
||||
//
|
||||
// The following function is thread safe but intended to be run from the main thread.
|
||||
//
|
||||
@@ -156,5 +159,8 @@ namespace AzFramework
|
||||
AZStd::deque<Requests> m_delayedQueue; //!< Requests that were processed before, but couldn't be completed.
|
||||
AZStd::queue<Requests> m_pendingRequestQueue;
|
||||
AZStd::mutex m_pendingRequestQueueMutex;
|
||||
|
||||
AZ::Event<AZ::Data::Asset<Spawnable>> m_onSpawnedEvent;
|
||||
AZ::Event<AZ::Data::Asset<Spawnable>> m_onDespawnedEvent;
|
||||
};
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -12,14 +12,150 @@
|
||||
|
||||
#include "CameraInput.h"
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
#include <AzCore/Math/Plane.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
void CameraSystem::HandleEvents(const InputEvent& event)
|
||||
AZ_CVAR(
|
||||
float, ed_cameraSystemDefaultPlaneHeight, 34.0f, nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"The default height of the ground plane to do intersection tests against when orbiting");
|
||||
AZ_CVAR(float, ed_cameraSystemBoostMultiplier, 3.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemTranslateSpeed, 10.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemOrbitDollyScrollSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemOrbitDollyCursorSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemScrollTranslateSpeed, 0.02f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemDefaultOrbitDistance, 60.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemMaxOrbitDistance, 100.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemLookSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemTranslateSmoothness, 5.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemRotateSpeed, 0.005f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(float, ed_cameraSystemPanSpeed, 0.01f, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(bool, ed_cameraSystemPanInvertX, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(bool, ed_cameraSystemPanInvertY, true, nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateForwardKey, "keyboard_key_alphanumeric_W", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateBackwardKey, "keyboard_key_alphanumeric_S", nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"");
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateLeftKey, "keyboard_key_alphanumeric_A", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateRightKey, "keyboard_key_alphanumeric_D", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemTranslateUpKey, "keyboard_key_alphanumeric_E", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateDownKey, "keyboard_key_alphanumeric_Q", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(
|
||||
AZ::CVarFixedString, ed_cameraSystemTranslateBoostKey, "keyboard_key_modifier_shift_l", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitKey, "keyboard_key_modifier_alt_l", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemFreeLookButton, "mouse_button_right", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemFreePanButton, "mouse_button_middle", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitLookButton, "mouse_button_left", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitDollyButton, "mouse_button_right", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
AZ_CVAR(AZ::CVarFixedString, ed_cameraSystemOrbitPanButton, "mouse_button_middle", nullptr, AZ::ConsoleFunctorFlags::Null, "");
|
||||
|
||||
static InputChannelId CameraTranslateForwardId;
|
||||
static InputChannelId CameraTranslateBackwardId;
|
||||
static InputChannelId CameraTranslateLeftId;
|
||||
static InputChannelId CameraTranslateRightId;
|
||||
static InputChannelId CameraTranslateDownId;
|
||||
static InputChannelId CameraTranslateUpId;
|
||||
static InputChannelId CameraTranslateBoostId;
|
||||
static InputChannelId CameraOrbitId;
|
||||
|
||||
// externed elsewhere
|
||||
InputChannelId CameraFreeLookButton;
|
||||
InputChannelId CameraFreePanButton;
|
||||
InputChannelId CameraOrbitLookButton;
|
||||
InputChannelId CameraOrbitDollyButton;
|
||||
InputChannelId CameraOrbitPanButton;
|
||||
|
||||
void ReloadCameraKeyBindings()
|
||||
{
|
||||
const AZ::CVarFixedString& forward = ed_cameraSystemTranslateForwardKey;
|
||||
CameraTranslateForwardId = InputChannelId(forward.c_str());
|
||||
const AZ::CVarFixedString& backward = ed_cameraSystemTranslateBackwardKey;
|
||||
CameraTranslateBackwardId = InputChannelId(backward.c_str());
|
||||
const AZ::CVarFixedString& left = ed_cameraSystemTranslateLeftKey;
|
||||
CameraTranslateLeftId = InputChannelId(left.c_str());
|
||||
const AZ::CVarFixedString& right = ed_cameraSystemTranslateRightKey;
|
||||
CameraTranslateRightId = InputChannelId(right.c_str());
|
||||
const AZ::CVarFixedString& down = ed_cameraSystemTranslateDownKey;
|
||||
CameraTranslateDownId = InputChannelId(down.c_str());
|
||||
const AZ::CVarFixedString& up = ed_cameraSystemTranslateUpKey;
|
||||
CameraTranslateUpId = InputChannelId(up.c_str());
|
||||
const AZ::CVarFixedString& boost = ed_cameraSystemTranslateBoostKey;
|
||||
CameraTranslateBoostId = InputChannelId(boost.c_str());
|
||||
const AZ::CVarFixedString& orbit = ed_cameraSystemOrbitKey;
|
||||
CameraOrbitId = InputChannelId(orbit.c_str());
|
||||
const AZ::CVarFixedString& freeLook = ed_cameraSystemFreeLookButton;
|
||||
CameraFreeLookButton = InputChannelId(freeLook.c_str());
|
||||
const AZ::CVarFixedString& freePan = ed_cameraSystemFreePanButton;
|
||||
CameraFreePanButton = InputChannelId(freePan.c_str());
|
||||
const AZ::CVarFixedString& orbitLook = ed_cameraSystemOrbitLookButton;
|
||||
CameraOrbitLookButton = InputChannelId(orbitLook.c_str());
|
||||
const AZ::CVarFixedString& orbitDolly = ed_cameraSystemOrbitDollyButton;
|
||||
CameraOrbitDollyButton = InputChannelId(orbitDolly.c_str());
|
||||
const AZ::CVarFixedString& orbitPan = ed_cameraSystemOrbitPanButton;
|
||||
CameraOrbitPanButton = InputChannelId(orbitPan.c_str());
|
||||
}
|
||||
|
||||
static void ReloadCameraKeyBindingsConsole(const AZ::ConsoleCommandContainer&)
|
||||
{
|
||||
ReloadCameraKeyBindings();
|
||||
}
|
||||
|
||||
AZ_CONSOLEFREEFUNC(ReloadCameraKeyBindingsConsole, AZ::ConsoleFunctorFlags::Null, "Reload keybindings for the modern camera system");
|
||||
|
||||
// Based on paper by David Eberly - https://www.geometrictools.com/Documentation/EulerAngles.pdf
|
||||
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation)
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
|
||||
// 2.4 Factor as RzRyRx
|
||||
if (orientation.GetElement(2, 0) < 1.0f)
|
||||
{
|
||||
if (orientation.GetElement(2, 0) > -1.0f)
|
||||
{
|
||||
x = std::atan2(orientation.GetElement(2, 1), orientation.GetElement(2, 2));
|
||||
y = std::asin(-orientation.GetElement(2, 0));
|
||||
z = std::atan2(orientation.GetElement(1, 0), orientation.GetElement(0, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0.0f;
|
||||
y = AZ::Constants::Pi * 0.5f;
|
||||
z = -std::atan2(-orientation.GetElement(2, 1), orientation.GetElement(1, 1));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = 0.0f;
|
||||
y = -AZ::Constants::Pi * 0.5f;
|
||||
z = std::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1));
|
||||
}
|
||||
|
||||
return {x, y, z};
|
||||
}
|
||||
|
||||
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform)
|
||||
{
|
||||
const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromTransform(transform));
|
||||
|
||||
camera.m_lookAt = transform.GetTranslation();
|
||||
camera.m_pitch = eulerAngles.GetX();
|
||||
camera.m_yaw = eulerAngles.GetZ();
|
||||
}
|
||||
|
||||
bool CameraSystem::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
if (const auto& cursor_motion = AZStd::get_if<CursorMotionEvent>(&event))
|
||||
{
|
||||
@@ -30,10 +166,10 @@ namespace AzFramework
|
||||
m_scrollDelta = scroll->m_delta;
|
||||
}
|
||||
|
||||
m_cameras.HandleEvents(event);
|
||||
return m_cameras.HandleEvents(event);
|
||||
}
|
||||
|
||||
Camera CameraSystem::StepCamera(const Camera& targetCamera, float deltaTime)
|
||||
Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime)
|
||||
{
|
||||
const auto cursorDelta = m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value()
|
||||
? m_currentCursorPosition.value() - m_lastCursorPosition.value()
|
||||
@@ -51,36 +187,41 @@ namespace AzFramework
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
void Cameras::AddCamera(AZStd::shared_ptr<CameraInput> camera_input)
|
||||
void Cameras::AddCamera(AZStd::shared_ptr<CameraInput> cameraInput)
|
||||
{
|
||||
m_idleCameraInputs.push_back(AZStd::move(camera_input));
|
||||
m_idleCameraInputs.push_back(AZStd::move(cameraInput));
|
||||
}
|
||||
|
||||
void Cameras::HandleEvents(const InputEvent& event)
|
||||
bool Cameras::HandleEvents(const InputEvent& event)
|
||||
{
|
||||
for (auto& camera_input : m_activeCameraInputs)
|
||||
bool handling = false;
|
||||
for (auto& cameraInput : m_activeCameraInputs)
|
||||
{
|
||||
camera_input->HandleEvents(event);
|
||||
cameraInput->HandleEvents(event);
|
||||
handling = !cameraInput->Idle() || handling;
|
||||
}
|
||||
|
||||
for (auto& camera_input : m_idleCameraInputs)
|
||||
for (auto& cameraInput : m_idleCameraInputs)
|
||||
{
|
||||
camera_input->HandleEvents(event);
|
||||
cameraInput->HandleEvents(event);
|
||||
}
|
||||
|
||||
return handling;
|
||||
}
|
||||
|
||||
Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, const float deltaTime)
|
||||
Camera Cameras::StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, const 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() &&
|
||||
auto& cameraInput = m_idleCameraInputs[i];
|
||||
const bool canBegin = cameraInput->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)
|
||||
(!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty()));
|
||||
|
||||
if (canBegin)
|
||||
{
|
||||
m_activeCameraInputs.push_back(camera_input);
|
||||
m_activeCameraInputs.push_back(cameraInput);
|
||||
using AZStd::swap;
|
||||
swap(m_idleCameraInputs[i], m_idleCameraInputs[m_idleCameraInputs.size() - 1]);
|
||||
m_idleCameraInputs.pop_back();
|
||||
@@ -93,25 +234,25 @@ namespace AzFramework
|
||||
|
||||
// accumulate
|
||||
Camera nextCamera = targetCamera;
|
||||
for (auto& camera_input : m_activeCameraInputs)
|
||||
for (auto& cameraInput : m_activeCameraInputs)
|
||||
{
|
||||
nextCamera = camera_input->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
nextCamera = cameraInput->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_activeCameraInputs.size();)
|
||||
{
|
||||
auto& camera_input = m_activeCameraInputs[i];
|
||||
if (camera_input->Ending())
|
||||
auto& cameraInput = m_activeCameraInputs[i];
|
||||
if (cameraInput->Ending())
|
||||
{
|
||||
camera_input->ClearActivation();
|
||||
m_idleCameraInputs.push_back(camera_input);
|
||||
cameraInput->ClearActivation();
|
||||
m_idleCameraInputs.push_back(cameraInput);
|
||||
using AZStd::swap;
|
||||
swap(m_activeCameraInputs[i], m_activeCameraInputs[m_activeCameraInputs.size() - 1]);
|
||||
m_activeCameraInputs.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
camera_input->ContinueActivation();
|
||||
cameraInput->ContinueActivation();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@@ -134,7 +275,7 @@ namespace AzFramework
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == m_channelId)
|
||||
if (input->m_channelId == m_rotateChannelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
@@ -154,14 +295,14 @@ namespace AzFramework
|
||||
{
|
||||
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;
|
||||
nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed;
|
||||
nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed;
|
||||
|
||||
auto clamp_rotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoOverPi, AZ::Constants::TwoOverPi); };
|
||||
const auto clampRotation = [](const float angle) { return std::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); };
|
||||
|
||||
nextCamera.m_yaw = clamp_rotation(nextCamera.m_yaw);
|
||||
nextCamera.m_yaw = clampRotation(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);
|
||||
nextCamera.m_pitch = AZ::GetClamp(nextCamera.m_pitch, -AZ::Constants::HalfPi, AZ::Constants::HalfPi);
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
@@ -170,7 +311,7 @@ namespace AzFramework
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceMouse::Button::Middle)
|
||||
if (input->m_channelId == m_panChannelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
@@ -190,51 +331,50 @@ namespace AzFramework
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
|
||||
const auto pan_axes = m_panAxesFn(nextCamera);
|
||||
const auto panAxes = 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 deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed;
|
||||
const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed;
|
||||
|
||||
const auto inv = [](const bool invert) {
|
||||
constexpr float Dir[] = {1.0f, -1.0f};
|
||||
return Dir[static_cast<int>(invert)];
|
||||
};
|
||||
|
||||
nextCamera.m_lookAt += delta_pan_x * inv(m_props.m_panInvertX);
|
||||
nextCamera.m_lookAt += delta_pan_y * -inv(m_props.m_panInvertY);
|
||||
nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX);
|
||||
nextCamera.m_lookAt += deltaPanY * -inv(ed_cameraSystemPanInvertY);
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
TranslateCameraInput::TranslationType TranslateCameraInput::translationFromKey(InputChannelId channelId)
|
||||
{
|
||||
// note: remove hard-coded InputDevice keys
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericW)
|
||||
if (channelId == CameraTranslateForwardId)
|
||||
{
|
||||
return TranslationType::Forward;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericS)
|
||||
if (channelId == CameraTranslateBackwardId)
|
||||
{
|
||||
return TranslationType::Backward;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericA)
|
||||
if (channelId == CameraTranslateLeftId)
|
||||
{
|
||||
return TranslationType::Left;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericD)
|
||||
if (channelId == CameraTranslateRightId)
|
||||
{
|
||||
return TranslationType::Right;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericQ)
|
||||
if (channelId == CameraTranslateDownId)
|
||||
{
|
||||
return TranslationType::Down;
|
||||
}
|
||||
|
||||
if (channelId == InputDeviceKeyboard::Key::AlphanumericE)
|
||||
if (channelId == CameraTranslateUpId)
|
||||
{
|
||||
return TranslationType::Up;
|
||||
}
|
||||
@@ -259,19 +399,19 @@ namespace AzFramework
|
||||
BeginActivation();
|
||||
}
|
||||
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
|
||||
if (input->m_channelId == CameraTranslateBoostId)
|
||||
{
|
||||
m_boost = true;
|
||||
}
|
||||
}
|
||||
else if (input->m_state == InputChannel::State::Ended)
|
||||
{
|
||||
m_translation ^= translationFromKey(input->m_channelId);
|
||||
m_translation &= ~(translationFromKey(input->m_channelId));
|
||||
if (m_translation == TranslationType::Nil)
|
||||
{
|
||||
EndActivation();
|
||||
}
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierShiftL)
|
||||
if (input->m_channelId == CameraTranslateBoostId)
|
||||
{
|
||||
m_boost = false;
|
||||
}
|
||||
@@ -285,13 +425,13 @@ namespace AzFramework
|
||||
{
|
||||
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 auto translationBasis = m_translationAxesFn(nextCamera);
|
||||
const auto axisX = translationBasis.GetBasisX();
|
||||
const auto axisY = translationBasis.GetBasisY();
|
||||
const auto axisZ = translationBasis.GetBasisZ();
|
||||
|
||||
const float speed = [boost = m_boost, props = m_props]() {
|
||||
return props.m_translateSpeed * (boost ? props.m_boostMultiplier : 1.0f);
|
||||
const float speed = [boost = m_boost]() {
|
||||
return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f);
|
||||
}();
|
||||
|
||||
if ((m_translation & TranslationType::Forward) == TranslationType::Forward)
|
||||
@@ -342,12 +482,8 @@ namespace AzFramework
|
||||
{
|
||||
if (const auto* input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceKeyboard::Key::ModifierAltL)
|
||||
if (input->m_channelId == CameraOrbitId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Updated)
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
BeginActivation();
|
||||
@@ -358,7 +494,7 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
end:
|
||||
|
||||
if (Active())
|
||||
{
|
||||
m_orbitCameras.HandleEvents(event);
|
||||
@@ -366,29 +502,29 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
Camera OrbitCameraInput::StepCamera(
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, float deltaTime)
|
||||
const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const 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))
|
||||
if (AZ::Plane::CreateFromNormalAndPoint(AZ::Vector3::CreateAxisZ(), AZ::Vector3::CreateAxisZ(ed_cameraSystemDefaultPlaneHeight))
|
||||
.CastRay(targetCamera.Translation(), targetCamera.Rotation().GetBasisY(), hit_distance))
|
||||
{
|
||||
hit_distance = AZStd::min<float>(hit_distance, ed_cameraSystemMaxOrbitDistance);
|
||||
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;
|
||||
nextCamera.m_lookDist = -ed_cameraSystemMaxOrbitDistance;
|
||||
nextCamera.m_lookAt = targetCamera.Translation() + targetCamera.Rotation().GetBasisY() * ed_cameraSystemMaxOrbitDistance;
|
||||
}
|
||||
}
|
||||
|
||||
if (Active())
|
||||
{
|
||||
// todo: need to return nested cameras to idle state when ending
|
||||
nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
|
||||
}
|
||||
|
||||
@@ -413,10 +549,10 @@ namespace AzFramework
|
||||
|
||||
Camera OrbitDollyScrollCameraInput::StepCamera(
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
|
||||
[[maybe_unused]] float deltaTime)
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * m_props.m_dollySpeed, 0.0f);
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + scrollDelta * ed_cameraSystemOrbitDollyScrollSpeed, 0.0f);
|
||||
EndActivation();
|
||||
return nextCamera;
|
||||
}
|
||||
@@ -425,7 +561,7 @@ namespace AzFramework
|
||||
{
|
||||
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
|
||||
{
|
||||
if (input->m_channelId == InputDeviceMouse::Button::Right)
|
||||
if (input->m_channelId == m_dollyChannelId)
|
||||
{
|
||||
if (input->m_state == InputChannel::State::Began)
|
||||
{
|
||||
@@ -444,7 +580,7 @@ namespace AzFramework
|
||||
[[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);
|
||||
nextCamera.m_lookDist = AZ::GetMin(nextCamera.m_lookDist + float(cursorDelta.m_y) * ed_cameraSystemOrbitDollyCursorSpeed, 0.0f);
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
@@ -457,7 +593,7 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
Camera ScrollTranslationCameraInput::StepCamera(
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, float scrollDelta,
|
||||
const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta,
|
||||
[[maybe_unused]] const float deltaTime)
|
||||
{
|
||||
Camera nextCamera = targetCamera;
|
||||
@@ -465,38 +601,39 @@ namespace AzFramework
|
||||
const auto translation_basis = LookTranslation(nextCamera);
|
||||
const auto axisY = translation_basis.GetBasisY();
|
||||
|
||||
nextCamera.m_lookAt += axisY * scrollDelta * m_props.m_translateSpeed;
|
||||
nextCamera.m_lookAt += axisY * scrollDelta * ed_cameraSystemScrollTranslateSpeed;
|
||||
|
||||
EndActivation();
|
||||
|
||||
return nextCamera;
|
||||
}
|
||||
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const SmoothProps& props, const float deltaTime)
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, 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);
|
||||
float targetYaw = clamp_rotation(targetCamera.m_yaw);
|
||||
const float currentYaw = clamp_rotation(currentCamera.m_yaw);
|
||||
|
||||
auto sign = [](const float value) { return static_cast<float>((0.0f < value) - (value < 0.0f)); };
|
||||
// return the sign of the float input (-1, 0, 1)
|
||||
const auto sign = [](const float value) { return aznumeric_cast<float>((0.0f < value) - (value < 0.0f)); };
|
||||
|
||||
// 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)
|
||||
const float yawDelta = targetYaw - currentYaw;
|
||||
if (std::abs(yawDelta) >= AZ::Constants::Pi)
|
||||
{
|
||||
target_yaw -= AZ::Constants::TwoPi * sign(yaw_delta);
|
||||
targetYaw -= AZ::Constants::TwoPi * sign(yawDelta);
|
||||
}
|
||||
|
||||
Camera camera;
|
||||
// note: the math for the lerp smoothing implementation for camera rotation and translation was inspired by this excellent
|
||||
// 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 lookRate = std::exp2(ed_cameraSystemLookSmoothness);
|
||||
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);
|
||||
camera.m_yaw = AZ::Lerp(targetYaw, currentYaw, lookT);
|
||||
const float moveRate = std::exp2(ed_cameraSystemTranslateSmoothness);
|
||||
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);
|
||||
@@ -508,20 +645,24 @@ namespace AzFramework
|
||||
const auto& inputChannelId = inputChannel.GetInputChannelId();
|
||||
const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId();
|
||||
|
||||
if (inputChannelId == InputDeviceMouse::SystemCursorPosition)
|
||||
const bool wasMouseButton =
|
||||
AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) {
|
||||
return button == inputChannelId;
|
||||
});
|
||||
|
||||
if (inputChannelId == InputDeviceMouse::Movement::X || inputChannelId == InputDeviceMouse::Movement::Y)
|
||||
{
|
||||
AZ::Vector2 systemCursorPositionNormalized = AZ::Vector2::CreateZero();
|
||||
InputSystemCursorRequestBus::EventResult(
|
||||
systemCursorPositionNormalized, inputDeviceId, &InputSystemCursorRequestBus::Events::GetSystemCursorPositionNormalized);
|
||||
const auto* position = inputChannel.GetCustomData<AzFramework::InputChannel::PositionData2D>();
|
||||
AZ_Assert(position, "Expected PositionData2D but found nullptr");
|
||||
|
||||
return CursorMotionEvent{ScreenPoint(
|
||||
systemCursorPositionNormalized.GetX() * windowSize.m_width, systemCursorPositionNormalized.GetY() * windowSize.m_height)};
|
||||
position->m_normalizedPosition.GetX() * windowSize.m_width, position->m_normalizedPosition.GetY() * windowSize.m_height)};
|
||||
}
|
||||
else if (inputChannelId == InputDeviceMouse::Movement::Z)
|
||||
{
|
||||
return ScrollEvent{inputChannel.GetValue()};
|
||||
}
|
||||
else if (InputDeviceMouse::IsMouseDevice(inputDeviceId) || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId))
|
||||
{
|
||||
return DiscreteInputEvent{inputChannelId, inputChannel.GetState()};
|
||||
}
|
||||
|
||||
@@ -17,13 +17,16 @@
|
||||
#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>
|
||||
#include <AzFramework/Viewport/ViewportId.h>
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
struct WindowSize;
|
||||
//! Update camera key bindings that can be overridden with AZ console vars (invoke from console to update)
|
||||
void ReloadCameraKeyBindings();
|
||||
|
||||
//! Return Euler angles (pitch, roll, yaw) for the incoming orientation.
|
||||
AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation);
|
||||
|
||||
struct Camera
|
||||
{
|
||||
@@ -51,8 +54,8 @@ namespace AzFramework
|
||||
|
||||
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));
|
||||
return AZ::Transform::CreateTranslation(m_lookAt) * AZ::Transform::CreateRotationZ(m_yaw) *
|
||||
AZ::Transform::CreateRotationX(m_pitch) * AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisY(m_lookDist));
|
||||
}
|
||||
|
||||
inline AZ::Matrix3x3 Camera::Rotation() const
|
||||
@@ -65,6 +68,8 @@ namespace AzFramework
|
||||
return Transform().GetTranslation();
|
||||
}
|
||||
|
||||
void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform);
|
||||
|
||||
struct CursorMotionEvent
|
||||
{
|
||||
ScreenPoint m_position;
|
||||
@@ -159,19 +164,13 @@ namespace AzFramework
|
||||
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);
|
||||
Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, float deltaTime);
|
||||
|
||||
class Cameras
|
||||
{
|
||||
public:
|
||||
void AddCamera(AZStd::shared_ptr<CameraInput> cameraInput);
|
||||
void HandleEvents(const InputEvent& event);
|
||||
bool HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime);
|
||||
void Reset();
|
||||
|
||||
@@ -183,7 +182,7 @@ namespace AzFramework
|
||||
class CameraSystem
|
||||
{
|
||||
public:
|
||||
void HandleEvents(const InputEvent& event);
|
||||
bool HandleEvents(const InputEvent& event);
|
||||
Camera StepCamera(const Camera& targetCamera, float deltaTime);
|
||||
|
||||
Cameras m_cameras;
|
||||
@@ -197,19 +196,16 @@ namespace AzFramework
|
||||
class RotateCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit RotateCameraInput(const InputChannelId channelId)
|
||||
: m_channelId(channelId)
|
||||
explicit RotateCameraInput(const InputChannelId rotateChannelId)
|
||||
: m_rotateChannelId(rotateChannelId)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
private:
|
||||
InputChannelId m_rotateChannelId;
|
||||
};
|
||||
|
||||
struct PanAxes
|
||||
@@ -242,22 +238,17 @@ namespace AzFramework
|
||||
class PanCameraInput : public CameraInput
|
||||
{
|
||||
public:
|
||||
explicit PanCameraInput(PanAxesFn panAxesFn)
|
||||
PanCameraInput(const InputChannelId panChannelId, PanAxesFn panAxesFn)
|
||||
: m_panAxesFn(AZStd::move(panAxesFn))
|
||||
, m_panChannelId(panChannelId)
|
||||
{
|
||||
}
|
||||
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;
|
||||
InputChannelId m_panChannelId;
|
||||
};
|
||||
|
||||
using TranslationAxesFn = AZStd::function<AZ::Matrix3x3(const Camera& camera)>;
|
||||
@@ -298,17 +289,11 @@ namespace AzFramework
|
||||
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,
|
||||
Nil = 0,
|
||||
Forward = 1 << 0,
|
||||
Backward = 1 << 1,
|
||||
Left = 1 << 2,
|
||||
@@ -354,6 +339,11 @@ namespace AzFramework
|
||||
return lhs;
|
||||
}
|
||||
|
||||
friend TranslationType operator~(const TranslationType lhs)
|
||||
{
|
||||
return static_cast<TranslationType>(~static_cast<std::underlying_type_t<TranslationType>>(lhs));
|
||||
}
|
||||
|
||||
static TranslationType translationFromKey(InputChannelId channelId);
|
||||
|
||||
TranslationType m_translation = TranslationType::Nil;
|
||||
@@ -366,23 +356,19 @@ namespace AzFramework
|
||||
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:
|
||||
explicit OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId)
|
||||
: m_dollyChannelId(dollyChannelId) {}
|
||||
|
||||
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;
|
||||
private:
|
||||
InputChannelId m_dollyChannelId;
|
||||
};
|
||||
|
||||
class ScrollTranslationCameraInput : public CameraInput
|
||||
@@ -390,11 +376,6 @@ namespace AzFramework
|
||||
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
|
||||
@@ -408,13 +389,10 @@ namespace AzFramework
|
||||
}
|
||||
|
||||
Cameras m_orbitCameras;
|
||||
|
||||
struct Props
|
||||
{
|
||||
float m_defaultOrbitDistance = 15.0f;
|
||||
float m_maxOrbitDistance = 100.0f;
|
||||
} m_props;
|
||||
};
|
||||
|
||||
struct WindowSize;
|
||||
|
||||
//! Map from a generic InputChannel event to a camera specific InputEvent.
|
||||
InputEvent BuildInputEvent(const InputChannel& inputChannel, const WindowSize& windowSize);
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -14,7 +14,6 @@ set(FILES
|
||||
AzFrameworkModule.h
|
||||
AzFrameworkModule.cpp
|
||||
API/ApplicationAPI.h
|
||||
API/AtomActiveInterface.h
|
||||
Application/Application.cpp
|
||||
Application/Application.h
|
||||
Archive/Archive.cpp
|
||||
|
||||
+4
-3
@@ -38,8 +38,9 @@ namespace AzManipulatorTestFramework
|
||||
void SetGridSize(float size) override;
|
||||
void SetAngularStep(float step) override;
|
||||
int GetViewportId() const override;
|
||||
AZStd::optional<AZ::Vector3> ViewportScreenToWorld(const QPoint& screenPosition, float depth) override;
|
||||
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> ViewportScreenToWorldRay(const QPoint& screenPosition) override;
|
||||
AZStd::optional<AZ::Vector3> ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override;
|
||||
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> ViewportScreenToWorldRay(
|
||||
const AzFramework::ScreenPoint& screenPosition) override;
|
||||
private:
|
||||
// ViewportInteractionRequestBus ...
|
||||
bool GridSnappingEnabled();
|
||||
@@ -47,7 +48,7 @@ namespace AzManipulatorTestFramework
|
||||
bool ShowGrid();
|
||||
bool AngleSnappingEnabled();
|
||||
float AngleStep();
|
||||
QPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition);
|
||||
AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition);
|
||||
private:
|
||||
AZStd::unique_ptr<NullDebugDisplayRequests> m_nullDebugDisplayRequests;
|
||||
const int m_viewportId = 1234; // Arbitrary viewport id for manipulator tests
|
||||
|
||||
@@ -66,10 +66,9 @@ namespace AzManipulatorTestFramework
|
||||
return m_angularStep;
|
||||
}
|
||||
|
||||
QPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
|
||||
AzFramework::ScreenPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
|
||||
{
|
||||
auto pos = AzFramework::WorldToScreen(worldPosition, m_cameraState);
|
||||
return QPoint(pos.m_x, pos.m_y);
|
||||
return AzFramework::WorldToScreen(worldPosition, m_cameraState);
|
||||
}
|
||||
|
||||
void ViewportInteraction::SetCameraState(const AzFramework::CameraState& cameraState)
|
||||
@@ -117,12 +116,14 @@ namespace AzManipulatorTestFramework
|
||||
return m_viewportId;
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Vector3> ViewportInteraction::ViewportScreenToWorld([[maybe_unused]]const QPoint& screenPosition, [[maybe_unused]]float depth)
|
||||
AZStd::optional<AZ::Vector3> ViewportInteraction::ViewportScreenToWorld(
|
||||
[[maybe_unused]] const AzFramework::ScreenPoint& screenPosition, [[maybe_unused]] float depth)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> ViewportInteraction::ViewportScreenToWorldRay([[maybe_unused]]const QPoint& screenPosition)
|
||||
AZStd::optional<AzToolsFramework::ViewportInteraction::ProjectedViewportRay> ViewportInteraction::ViewportScreenToWorldRay(
|
||||
[[maybe_unused]] const AzFramework::ScreenPoint& screenPosition)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user