Merge branch 'main' of https://github.com/aws-lumberyard-dev/o3de into ATOM/tonypeng/ATOM-15266-2

This commit is contained in:
Peng
2021-05-13 08:39:43 -07:00
387 changed files with 1607 additions and 19974 deletions
-6
View File
@@ -1,6 +0,0 @@
#Ignore these directories
SDKs
#ColinB (8/26)- I know there are depot files that this will ignore... But these files should not be
#here, they should all be in 3rdParty... so we will ignore them until I can move them, it should
#be OK for now because they shouldn't change at all anyway.
-8
View File
@@ -9,23 +9,15 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform)
ly_add_target(
NAME CryCommon STATIC
NAMESPACE Legacy
FILES_CMAKE
crycommon_files.cmake
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
PLATFORM_INCLUDE_FILES
${pal_dir}/crycommon_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
PUBLIC
. # Lots of code without CryCommon/
.. # Dangerous since exports CryEngine's path (client code can do CrySystem/ without depending on that target)
${pal_dir}
${pal_tool_dirs}
BUILD_DEPENDENCIES
PUBLIC
AZ::AzCore
@@ -1,43 +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 <CryMemoryManager.h>
class MemoryManagerMock
: public IMemoryManager
{
public:
MOCK_METHOD1(GetProcessMemInfo,
bool(SProcessMemInfo& minfo));
MOCK_METHOD3(TraceDefineHeap,
HeapHandle(const char* heapName, size_t size, const void* pBase));
MOCK_METHOD6(TraceHeapAlloc,
void(HeapHandle heap, void* mem, size_t size, size_t blockSize, const char* sUsage, const char* sNameHint));
MOCK_METHOD3(TraceHeapFree,
void(HeapHandle heap, void* mem, size_t blockSize));
MOCK_METHOD1(TraceHeapSetColor,
void(uint32 color));
MOCK_METHOD0(TraceHeapGetColor,
uint32());
MOCK_METHOD1(TraceHeapSetLabel,
void(const char* sLabel));
MOCK_METHOD1(CreateCustomMemoryHeapInstance,
ICustomMemoryHeap* const (EAllocPolicy const eAllocPolicy));
MOCK_METHOD3(CreateGeneralExpandingMemoryHeap,
IGeneralMemoryHeap* (size_t upperLimit, size_t reserveSize, const char* sUsage));
MOCK_METHOD3(CreateGeneralMemoryHeap,
IGeneralMemoryHeap* (void* base, size_t sz, const char* sUsage));
MOCK_METHOD2(ReserveAddressRange,
IMemoryAddressRange* (size_t capacity, const char* sName));
MOCK_METHOD2(CreatePageMappingHeap,
IPageMappingHeap* (size_t addressSpace, const char* sName));
};
@@ -1,47 +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
struct NetworkMock : public INetwork
{
NetworkMock() : m_gridMate(nullptr)
{
}
GridMate::IGridMate* m_gridMate;
void Release() override {}
void GetMemoryStatistics([[maybe_unused]] ICrySizer* pSizer) override {}
void GetBandwidthStatistics([[maybe_unused]] SBandwidthStats* const pStats) override {}
void GetPerformanceStatistics([[maybe_unused]] SNetworkPerformance* pSizer) override {}
void GetProfilingStatistics([[maybe_unused]] SNetworkProfilingStats* const pStats) override {}
void SyncWithGame([[maybe_unused]] ENetworkGameSync syncType) override {}
const char* GetHostName() override { return "testhostname"; }
GridMate::IGridMate* GetGridMate() override
{
return m_gridMate;
}
ChannelId GetChannelIdForSessionMember([[maybe_unused]] GridMate::GridMember* member) const override { return ChannelId(); }
ChannelId GetServerChannelId() const override { return ChannelId(); }
ChannelId GetLocalChannelId() const override { return ChannelId(); }
CTimeValue GetSessionTime() override { return CTimeValue(); }
void ChangedAspects([[maybe_unused]] EntityId id, [[maybe_unused]] NetworkAspectType aspectBits) override {}
void SetDelegatableAspectMask([[maybe_unused]] NetworkAspectType aspectBits) override {}
void SetObjectDelegatedAspectMask([[maybe_unused]] EntityId entityId, [[maybe_unused]] NetworkAspectType aspects, [[maybe_unused]] bool set) override {}
void DelegateAuthorityToClient([[maybe_unused]] EntityId entityId, [[maybe_unused]] ChannelId clientChannelId) override {}
void InvokeActorRMI([[maybe_unused]] EntityId entityId, [[maybe_unused]] uint8 actorExtensionId, [[maybe_unused]] ChannelId targetChannelFilter, [[maybe_unused]] IActorRMIRep& rep) override {}
void InvokeScriptRMI([[maybe_unused]] ISerializable* serializable, [[maybe_unused]] bool isServerRMI, [[maybe_unused]] ChannelId toChannelId = kInvalidChannelId, [[maybe_unused]] ChannelId avoidChannelId = kInvalidChannelId) override {}
void RegisterActorRMI([[maybe_unused]] IActorRMIRep* rep) override {}
void UnregisterActorRMI([[maybe_unused]] IActorRMIRep* rep) override {}
EntityId LocalEntityIdToServerEntityId([[maybe_unused]] EntityId localId) const override { return EntityId(); }
EntityId ServerEntityIdToLocalEntityId([[maybe_unused]] EntityId serverId, [[maybe_unused]] bool allowForcedEstablishment = false) const override { return EntityId(); }
};
@@ -1,29 +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 <AzTest/AzTest.h>
#include <CGFContent.h>
class MockIAssetWriter
: public IAssetWriter
{
public:
~MockIAssetWriter() override = default;
MOCK_METHOD1(WriteCGF,
bool(CContentCGF* content));
MOCK_METHOD2(WriteCHR,
bool(CContentCGF* content, IConvertContext* convertContext));
MOCK_METHOD3(WriteSKIN,
bool(CContentCGF* content, IConvertContext* convertContext, bool exportMorphTargets));
};
@@ -1,11 +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.
#
@@ -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.
#
set(FILES
../../WinBase.cpp
)
@@ -1,13 +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
)
@@ -1,11 +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.
#
@@ -1,13 +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
)
@@ -1,11 +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.
#
@@ -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.
#
set(FILES
../../WinBase.cpp
)
@@ -1,11 +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.
#
@@ -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.
#
set(FILES
../../WinBase.cpp
)
@@ -1,11 +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.
#
@@ -1,13 +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
)
@@ -1,13 +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
)
@@ -1,11 +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.
#
@@ -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.
#
set(FILES
../../WinBase.cpp
)
@@ -1,102 +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 <AzCore/Math/Aabb.h>
namespace Terrain
{
class Viewport2D
{
public:
int m_topLeftX = 0;
int m_topLeftY = 0;
int m_width = 0;
int m_height = 0;
Viewport2D() = default;
Viewport2D(const Viewport2D&) = default;
Viewport2D& operator=(const Viewport2D&) = default;
Viewport2D(int topLeftX, int topLeftY, int width, int height)
: m_topLeftX(topLeftX)
, m_topLeftY(topLeftY)
, m_width(width)
, m_height(height)
{
}
};
// External height map data requests
class HeightmapDataRequestInfo
{
public:
HeightmapDataRequestInfo() = default;
HeightmapDataRequestInfo(const HeightmapDataRequestInfo& rhs) = default;
HeightmapDataRequestInfo& operator=(const HeightmapDataRequestInfo& rhs) = default;
HeightmapDataRequestInfo(int viewportTopLeftX, int viewportTopLeftY, int viewportWidth, int viewportHeight, float metersPerPixel, AZ::Vector2 worldMin, AZ::Vector2 worldMax)
: m_viewport(viewportTopLeftX, viewportTopLeftY, viewportWidth, viewportHeight)
, m_metersPerPixel(metersPerPixel)
, m_worldMin(worldMin)
, m_worldMax(worldMax)
{
}
float GetMetersPerPixel() const
{
return m_metersPerPixel;
}
AZ::Vector2 GetWorldMin() const
{
return m_worldMin;
}
AZ::Vector2 GetWorldMax() const
{
return m_worldMax;
}
AZ::Vector2 GetWorldWidth() const
{
return (m_worldMax - m_worldMin);
}
Viewport2D GetViewport() const
{
return m_viewport;
}
private:
Viewport2D m_viewport;
AZ::Vector2 m_worldMin = AZ::Vector2(0.0f, 0.0f);
AZ::Vector2 m_worldMax = AZ::Vector2(0.0f, 0.0f);
float m_metersPerPixel = 1.0f;
};
class HeightmapDataNotifications
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
virtual void OnTerrainHeightDataChanged(const AZ::Aabb& dirtyRegion) = 0;
};
using HeightmapDataNotificationBus = AZ::EBus<HeightmapDataNotifications>;
}
@@ -1,56 +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 <AzCore/std/string/string_view.h>
class CShader;
namespace Terrain
{
class TerrainDataRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
using MutexType = AZStd::recursive_mutex;
//////////////////////////////////////////////////////////////////////////
virtual float GetHeightSynchronous(float x, float y) = 0;
virtual AZ::Vector3 GetNormalSynchronous(float x, float y) = 0;
virtual CShader* GetTerrainHeightGeneratorShader() const = 0;
virtual CShader* GetTerrainMaterialCompositingShader() const = 0;
};
using TerrainDataRequestBus = AZ::EBus<TerrainDataRequests>;
class TerrainShaderRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
using MutexType = AZStd::recursive_mutex;
//////////////////////////////////////////////////////////////////////////
virtual void RefreshShader(const AZStd::string_view name, CShader* shader) = 0;
virtual void ReleaseShader(CShader* shader) const = 0;
};
using TerrainShaderRequestBus = AZ::EBus<TerrainShaderRequests>;
}
@@ -1,82 +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/Vector2.h>
#include <AzCore/std/functional.h>
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzCore/EBus/EBus.h>
#include "HeightmapDataBus.h"
class CShader;
namespace Terrain
{
// This interface defines how the renderer can access the terrain system to set up state and gather information before rendering height maps
class TerrainProviderRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! allows multiple threads to call
using MutexType = AZStd::recursive_mutex;
//////////////////////////////////////////////////////////////////////////
// world properties
virtual AZ::Vector3 GetWorldSize() = 0;
virtual AZ::Vector3 GetRegionSize() = 0;
virtual AZ::Vector3 GetWorldOrigin() = 0;
virtual AZ::Vector2 GetHeightRange() = 0;
// utility
virtual void GetRegionIndex(const AZ::Vector2& worldMin, const AZ::Vector2& worldMax, int& regionIndexX, int& regionIndexY) = 0;
virtual float GetHeightAtIndexedPosition([[maybe_unused]] int ix, [[maybe_unused]] int iy) { return 64.0f; }
virtual float GetHeightAtWorldPosition([[maybe_unused]] float fx, [[maybe_unused]] float fy) { return 64.0f; }
virtual unsigned char GetSurfaceTypeAtIndexedPosition([[maybe_unused]] int ix, [[maybe_unused]] int iy) { return 0; }
};
using TerrainProviderRequestBus = AZ::EBus<TerrainProviderRequests>;
// This class exists for the terrain system to inject data into the renderer for generating the GPU-side terrain height map
struct CRETerrainContext
{
// Tract map
virtual void OnTractVersionUpdate() = 0;
CShader* m_currentShader = nullptr;
};
class TerrainProviderNotifications
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//! allows multiple threads to call
using MutexType = AZStd::recursive_mutex;
//////////////////////////////////////////////////////////////////////////
// interface to be implemented by the game, invoked by the terrain render element
// pull settings from the world cache, so the next accessors are accurate
virtual void SynchronizeSettings(CRETerrainContext* context) = 0;
};
using TerrainProviderNotificationBus = AZ::EBus<TerrainProviderNotifications>;
}
@@ -1,37 +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>
namespace Terrain
{
class TerrainRendererRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
//! allows multiple threads to call
using MutexType = AZStd::recursive_mutex;
// Query state of the terrain renderer
// Returns true once the terrain renderer has fulfilled most data requests and is ready for rendering
virtual bool IsReady() = 0;
};
using TerrainRendererRequestBus = AZ::EBus<TerrainRendererRequests>;
}
@@ -1,122 +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 <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/fixed_vector.h>
struct IMaterial;
class ITexture;
namespace Terrain
{
struct MacroMaterial
{
// Textures
_smart_ptr<ITexture> m_macroColorMap = nullptr;
_smart_ptr<ITexture> m_macroGlossMap = nullptr;
_smart_ptr<ITexture> m_macroNormalMap = nullptr;
// Material Params
AZ::Color m_macroColorMapColor;
float m_macroGlossMapScale = 1.0f;
float m_macroNormalMapScale = 1.0f;
float m_macroSpecReflectance = 0.03f;
void Clear()
{
m_macroColorMap = nullptr;
m_macroGlossMap = nullptr;
m_macroNormalMap = nullptr;
m_macroColorMapColor = AZ::Color(1.0f);
m_macroGlossMapScale = 1.0f;
m_macroNormalMapScale = 1.0f;
m_macroSpecReflectance = 0.03f;
}
};
struct TerrainMaterialLayer
{
_smart_ptr<IMaterial> m_material = nullptr;
_smart_ptr<ITexture> m_splatTexture = nullptr;
TerrainMaterialLayer(_smart_ptr<IMaterial> material, _smart_ptr<ITexture> splatTexture)
: m_material(material)
, m_splatTexture(splatTexture)
{
}
};
struct RegionMaterials
{
MacroMaterial m_macroMaterial;
AZStd::vector<TerrainMaterialLayer> m_materialLayers;
_smart_ptr<IMaterial> m_defaultMaterial = nullptr;
RegionMaterials& operator=(const RegionMaterials& rhs) = default;
void Clear()
{
m_materialLayers.clear();
m_defaultMaterial = nullptr;
m_macroMaterial.Clear();
}
};
const AZ::u32 kMaxRegionsPerTerrainMaterialRequest = 16;
typedef AZStd::pair<int, int> RegionIndex;
typedef AZStd::fixed_vector<RegionIndex, kMaxRegionsPerTerrainMaterialRequest> RegionIndexVector;
typedef AZStd::fixed_vector<RegionMaterials, kMaxRegionsPerTerrainMaterialRequest> RegionMaterialVector;
enum class RequestResult
{
NoAssetsForRegion,
Loading,
Success
};
class WorldMaterialRequests
: public AZ::EBusTraits
{
public:
//////////////////////////////////////////////////////////////////////////
// EBusTraits overrides
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
//////////////////////////////////////////////////////////////////////////
//! allows multiple threads to call
using MutexType = AZStd::recursive_mutex;
virtual void LoadWorld(const AZStd::string& worldName, int regionSize) = 0;
virtual RequestResult RequestRegionMaterials(const RegionIndexVector& regions, RegionMaterialVector& outRegionMaterials) = 0;
// Parameters:
// int tileX, tileY : Region tile indices
// Returns:
// bool : If true, region material data is loaded and exists. outMacroMaterial will be modified with the respective macro material data
// If false, no region material data has been loaded or exists for the given tile (may still have invalid material layers).
virtual RequestResult GetMacroMaterial(int tileX, int tileY, MacroMaterial& outMacroMaterial) = 0;
virtual void GetTerrainPOMParameters(float& pomHeightBias, float& pomDisplacement, float& selfShadowStrength) = 0;
//Get the surface type at a given position. If not loaded yet, returns "loadingMaterial".
virtual AZStd::string_view GetSurfaceTypeAtPosition(AZ::Vector2 position) = 0;
};
using WorldMaterialRequestBus = AZ::EBus<WorldMaterialRequests>;
} // namespace Terrain
+3
View File
@@ -12,6 +12,7 @@
// Original file Copyright Crytek GMBH or its affiliates, used under license.
// Description : Linux/Mac port support for Win32API calls
#if !defined(WIN32)
#include "platform.h" // Note: This should be first to get consistent debugging definitions
@@ -1667,3 +1668,5 @@ __finddata64_t::~__finddata64_t()
}
}
#endif //defined(APPLE) || defined(LINUX)
#endif // !defined(WIN32)
@@ -249,7 +249,6 @@ set(FILES
platform_impl.cpp
Win32specific.h
Win64specific.h
stl/STLAlignedAlloc.h
LyShine/IDraw2d.h
LyShine/ILyShine.h
LyShine/ISprite.h
@@ -341,11 +340,7 @@ set(FILES
Maestro/Types/AssetBlendKey.h
Maestro/Types/AssetBlends.h
Maestro/Types/SequenceType.h
Terrain/Bus/WorldMaterialRequestsBus.h
Terrain/Bus/TerrainBus.h
Terrain/Bus/TerrainRendererBus.h
Terrain/Bus/HeightmapDataBus.h
Terrain/Bus/TerrainProviderBus.h
StaticInstance.h
Pak/CryPakUtils.h
WinBase.cpp
)
@@ -1,13 +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
)
@@ -14,12 +14,10 @@ set(FILES
Mocks/IConsoleMock.h
Mocks/ICryPakMock.h
Mocks/ILogMock.h
Mocks/IMemoryManagerMock.h
Mocks/ISystemMock.h
Mocks/ITimerMock.h
Mocks/ICVarMock.h
Mocks/IRendererMock.h
Mocks/ITextureMock.h
Mocks/IRemoteConsoleMock.h
Mocks/MockCGFContent.h
)
@@ -1,115 +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 : Implements an aligned allocator for STL
// based on the Mallocator (http://blogs.msdn.com/b/vcblog/archive/2008/08/28/the-mallocator.aspx)
#pragma once
#include <stddef.h> // Required for size_t and ptrdiff_t and NULL
#include <AzCore/Memory/AllocatorBase.h>
namespace stl
{
template <size_t Alignment>
class AlignedAllocator
: public AZ::SimpleSchemaAllocator<AZ::ChildAllocatorSchema<AZ::LegacyAllocator>>
{
public:
AZ_TYPE_INFO(AlignedAllocator, "{DF152D8A-36ED-4A2A-9FA6-734F212716C6}");
using Base = AZ::SimpleSchemaAllocator<AZ::ChildAllocatorSchema<AZ::LegacyAllocator>>;
using Descriptor = Base::Descriptor;
using Schema = AZ::ChildAllocatorSchema<AZ::LegacyAllocator>;
AlignedAllocator()
: Base("AlignedAllocator", "Legacy Cry Aligned Allocator")
{
}
pointer_type Allocate(size_type byteSize, size_type /*alignment*/, int flags /* = 0 */, const char* name /* = 0 */, const char* fileName /* = 0 */, int lineNum /* = 0 */, unsigned int suppressStackRecord /* = 0 */) override
{
return Base::Allocate(byteSize, Alignment, flags, name, fileName, lineNum, suppressStackRecord);
}
void DeAllocate(pointer_type ptr, size_type byteSize, [[maybe_unused]] size_type alignment) override
{
return Base::DeAllocate(ptr, byteSize, Alignment);
}
pointer_type ReAllocate(pointer_type ptr, size_type newSize, size_type /*newAlignment*/) override
{
return Base::ReAllocate(ptr, newSize, Alignment);
}
};
template <size_t Alignment>
using aligned_alloc = AZ::AZStdAlloc<AlignedAllocator<Alignment>>;
//////////////////////////////////////////////////////////////////////////
// Defines aligned vector type
//////////////////////////////////////////////////////////////////////////
template <typename T, int AlignSize>
class aligned_vector
: public AZStd::vector<T, aligned_alloc<AlignSize> >
{
public:
typedef aligned_alloc<AlignSize> MyAlloc;
typedef AZStd::vector<T, MyAlloc> MySuperClass;
typedef aligned_vector<T, AlignSize> MySelf;
typedef size_t size_type;
aligned_vector() {}
explicit aligned_vector(const MyAlloc& _Al)
: MySuperClass(_Al) {}
explicit aligned_vector(size_type _Count)
: MySuperClass(_Count) {};
aligned_vector(size_type _Count, const T& _Val)
: MySuperClass(_Count, _Val) {}
aligned_vector(size_type _Count, const T& _Val, const MyAlloc& _Al)
: MySuperClass(_Count, _Val) {}
aligned_vector(const MySelf& _Right)
: MySuperClass(_Right) {};
template<class _Iter>
aligned_vector(_Iter _First, _Iter _Last)
: MySuperClass(_First, _Last) {};
template<class _Iter>
aligned_vector(_Iter _First, _Iter _Last, const MyAlloc& _Al)
: MySuperClass(_First, _Last, _Al) {};
};
template <class Vec>
inline size_t size_of_aligned_vector(const Vec& c)
{
if (!c.empty())
{
// Not really correct as not taking alignment into the account
return c.capacity() * sizeof(typename Vec::value_type);
}
return 0;
}
} // namespace stl
// Specialize for the AlignedAllocator to provide one per module that does not use the
// environment for its storage. Since this allocator just uses LegacyAllocator
// to do the real work, it's fine if there is one of these per cry module
namespace AZ
{
template <size_t Alignment>
class AllocatorInstance<stl::AlignedAllocator<Alignment>> : public Internal::AllocatorInstanceBase<stl::AlignedAllocator<Alignment>, AllocatorStorage::ModuleStoragePolicy<stl::AlignedAllocator<Alignment>>>
{
};
}
+1 -1
View File
@@ -1216,7 +1216,7 @@ bool CSystem::InitShine([[maybe_unused]] const SSystemInitParams& initParams)
if (!m_env.pLyShine)
{
AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "LYShine System did not initialize correctly. Please check that the LyShine gem is enabled for this project in ProjectConfigurator.");
AZ_Error(AZ_TRACE_SYSTEM_WINDOW, false, "LYShine System did not initialize correctly. Please check that the LyShine gem is enabled for this project in *_dependencies.cmake.");
return false;
}
return true;
@@ -12,7 +12,6 @@
#include "CrySystem_precompiled.h"
#include <AzTest/AzTest.h>
#include <AzCore/Memory/AllocatorScope.h>
#include <CryCommon/stl/STLAlignedAlloc.h>
TEST(StringTests, CUT_Strings)
{
@@ -424,21 +423,6 @@ TEST_F(CryPrimitives, CUT_FixedString)
EXPECT_EQ("0123", str5);
}
//////////////////////////////////////////////////////////////////////////
// Unit Testing of aligned_vector
//////////////////////////////////////////////////////////////////////////
TEST_F(CryPrimitives, CUT_AlignedVector)
{
stl::aligned_vector<int, 16> vec;
vec.push_back(1);
vec.push_back(2);
vec.push_back(3);
EXPECT_TRUE(vec.size() == 3);
EXPECT_TRUE(((INT_PTR)(&vec[0]) % 16) == 0);
}
TEST_F(CryPrimitives, CUT_DynArray)
{
LegacyDynArray<int> a;
-1
View File
@@ -1 +0,0 @@
*.xml
-1
View File
@@ -1 +0,0 @@
*.xml
@@ -37,29 +37,6 @@ namespace AzFramework
void NonUniformScaleComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawObbService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXActorService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXSimpleMotionService"));
incompatible.push_back(AZ_CRC_CE("GradientTransformService"));
incompatible.push_back(AZ_CRC_CE("LegacyMeshService"));
incompatible.push_back(AZ_CRC_CE("LookAtService"));
incompatible.push_back(AZ_CRC_CE("SequenceService"));
incompatible.push_back(AZ_CRC_CE("ClothMeshService"));
incompatible.push_back(AZ_CRC_CE("PhysXJointService"));
incompatible.push_back(AZ_CRC_CE("PhysXCharacterControllerService"));
incompatible.push_back(AZ_CRC_CE("PhysXRagdollService"));
incompatible.push_back(AZ_CRC_CE("WhiteBoxService"));
incompatible.push_back(AZ_CRC_CE("NavigationAreaService"));
incompatible.push_back(AZ_CRC_CE("GeometryService"));
incompatible.push_back(AZ_CRC_CE("CapsuleShapeService"));
incompatible.push_back(AZ_CRC_CE("CompoundShapeService"));
incompatible.push_back(AZ_CRC_CE("CylinderShapeService"));
incompatible.push_back(AZ_CRC_CE("DiskShapeService"));
incompatible.push_back(AZ_CRC_CE("SphereShapeService"));
incompatible.push_back(AZ_CRC_CE("SplineService"));
incompatible.push_back(AZ_CRC_CE("TubeShapeService"));
}
void NonUniformScaleComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -99,6 +99,11 @@ namespace AzPhysics
classElement.RemoveElementByName(AZ_CRC_CE("Property Visibility Flags"));
}
if (classElement.GetVersion() <= 4)
{
classElement.RemoveElementByName(AZ_CRC_CE("Simulated"));
}
return true;
}
}
@@ -110,7 +115,7 @@ namespace AzPhysics
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<RigidBodyConfiguration, AzPhysics::SimulatedBodyConfiguration>()
->Version(4, &Internal::RigidBodyVersionConverter)
->Version(5, &Internal::RigidBodyVersionConverter)
->Field("Initial linear velocity", &RigidBodyConfiguration::m_initialLinearVelocity)
->Field("Initial angular velocity", &RigidBodyConfiguration::m_initialAngularVelocity)
->Field("Linear damping", &RigidBodyConfiguration::m_linearDamping)
@@ -119,7 +124,6 @@ namespace AzPhysics
->Field("Start Asleep", &RigidBodyConfiguration::m_startAsleep)
->Field("Interpolate Motion", &RigidBodyConfiguration::m_interpolateMotion)
->Field("Gravity Enabled", &RigidBodyConfiguration::m_gravityEnabled)
->Field("Simulated", &RigidBodyConfiguration::m_simulated)
->Field("Kinematic", &RigidBodyConfiguration::m_kinematic)
->Field("CCD Enabled", &RigidBodyConfiguration::m_ccdEnabled)
->Field("Compute Mass", &RigidBodyConfiguration::m_computeMass)
@@ -57,7 +57,6 @@ namespace AzPhysics
bool m_startAsleep = false;
bool m_interpolateMotion = false;
bool m_gravityEnabled = true;
bool m_simulated = true;
bool m_kinematic = false;
bool m_ccdEnabled = false; //!< Whether continuous collision detection is enabled.
float m_ccdMinAdvanceCoefficient = 0.15f; //!< Coefficient affecting how granularly time is subdivided in CCD.
@@ -88,13 +88,13 @@ namespace AzPhysics
//! Remove a simulated body from the Scene.z
//! @param sceneHandle A handle to the scene to remove the requested simulated body.
//! @param bodyHandle A handle to the simulated body being removed.
virtual void RemoveSimulatedBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
//! @param bodyHandle A handle to the simulated body being removed. This will be set to AzPhysics::InvalidSimulatedBodyHandle as they're no longer valid.
virtual void RemoveSimulatedBody(SceneHandle sceneHandle, SimulatedBodyHandle& bodyHandle) = 0;
//! Remove a list of simulated bodies from the Scene.
//! @param sceneHandle A handle to the scene to remove the simulated bodies from.
//! @param bodyHandles A list of simulated body handles to be removed.
virtual void RemoveSimulatedBodies(SceneHandle sceneHandle, const SimulatedBodyHandleList& bodyHandles) = 0;
//! @param bodyHandles A list of simulated body handles to be removed. All handles will be set to AzPhysics::InvalidSimulatedBodyHandle as they're no longer valid.
virtual void RemoveSimulatedBodies(SceneHandle sceneHandle, SimulatedBodyHandleList& bodyHandles) = 0;
//! Enable / Disable simulation of the requested body. By default all bodies added are enabled.
//! Disabling simulation the body will no longer be affected by any forces, collisions, or found with scene queries.
@@ -286,12 +286,12 @@ namespace AzPhysics
virtual SimulatedBodyList GetSimulatedBodiesFromHandle(const SimulatedBodyHandleList& bodyHandles) = 0;
//! Remove a simulated body from the Scene.
//! @param bodyHandle A handle to the simulated body being removed.
virtual void RemoveSimulatedBody(SimulatedBodyHandle bodyHandle) = 0;
//! @param bodyHandle A handle to the simulated body being removed. This will be set to AzPhysics::InvalidSimulatedBodyHandle as they're no longer valid.
virtual void RemoveSimulatedBody(SimulatedBodyHandle& bodyHandle) = 0;
//! Remove a list of simulated bodies from the Scene.
//! @param bodyHandles A list of simulated body handles to be removed.
virtual void RemoveSimulatedBodies(const SimulatedBodyHandleList& bodyHandles) = 0;
//! @param bodyHandles A list of simulated body handles to be removed. All handles will be set to AzPhysics::InvalidSimulatedBodyHandle as they're no longer valid.
virtual void RemoveSimulatedBodies(SimulatedBodyHandleList& bodyHandles) = 0;
//! Enable / Disable simulation of the requested body. By default all bodies added are enabled.
//! Disabling simulation the body will no longer be affected by any forces, collisions, or found with scene queries.
@@ -62,7 +62,7 @@ namespace AzPhysics
virtual void SetLinearVelocity(const AZ::Vector3& velocity) = 0;
virtual AZ::Vector3 GetAngularVelocity() const = 0;
virtual void SetAngularVelocity(const AZ::Vector3& angularVelocity) = 0;
virtual AZ::Vector3 GetLinearVelocityAtWorldPoint(const AZ::Vector3& worldPoint) = 0;
virtual AZ::Vector3 GetLinearVelocityAtWorldPoint(const AZ::Vector3& worldPoint) const = 0;
virtual void ApplyLinearImpulse(const AZ::Vector3& impulse) = 0;
virtual void ApplyLinearImpulseAtWorldPoint(const AZ::Vector3& impulse, const AZ::Vector3& worldPoint) = 0;
virtual void ApplyAngularImpulse(const AZ::Vector3& angularImpulse) = 0;
@@ -15,6 +15,7 @@
#include <AzCore/Console/IConsole.h>
#include <AzCore/Math/MathUtils.h>
#include <AzCore/Math/Plane.h>
#include <AzCore/std/numeric.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzFramework/Windowing/WindowBus.h>
@@ -156,35 +157,25 @@ namespace AzFramework
camera.m_lookAt = transform.GetTranslation() + (camera.Rotation().GetBasisY() * -camera.m_lookDist);
}
static ScreenVector CursorDelta(const AZStd::optional<ScreenPoint>& currentPosition, const AZStd::optional<ScreenPoint>& lastPosition)
{
return currentPosition.has_value() && lastPosition.has_value() ? currentPosition.value() - lastPosition.value()
: ScreenVector(0, 0);
}
bool CameraSystem::HandleEvents(const InputEvent& event)
{
if (const auto& cursor = AZStd::get_if<CursorEvent>(&event))
{
m_currentCursorPosition = cursor->m_position;
m_cursorState.SetCurrentPosition(cursor->m_position);
}
else if (const auto& scroll = AZStd::get_if<ScrollEvent>(&event))
{
m_scrollDelta = scroll->m_delta;
}
return m_cameras.HandleEvents(event, CursorDelta(m_currentCursorPosition, m_lastCursorPosition), m_scrollDelta);
return m_cameras.HandleEvents(event, m_cursorState.CursorDelta(), m_scrollDelta);
}
Camera CameraSystem::StepCamera(const Camera& targetCamera, const float deltaTime)
{
const auto cursorDelta = CursorDelta(m_currentCursorPosition, m_lastCursorPosition);
if (m_currentCursorPosition.has_value())
{
m_lastCursorPosition = m_currentCursorPosition;
}
const auto nextCamera = m_cameras.StepCamera(targetCamera, m_cursorState.CursorDelta(), m_scrollDelta, deltaTime);
const auto nextCamera = m_cameras.StepCamera(targetCamera, cursorDelta, m_scrollDelta, deltaTime);
m_cursorState.Update();
m_scrollDelta = 0.0f;
@@ -236,12 +227,12 @@ namespace AzFramework
}
}
// accumulate
Camera nextCamera = targetCamera;
for (auto& cameraInput : m_activeCameraInputs)
{
nextCamera = cameraInput->StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime);
}
const Camera nextCamera = AZStd::accumulate(
AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera,
[cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) {
acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime);
return acc;
});
for (int i = 0; i < m_activeCameraInputs.size();)
{
@@ -275,34 +266,42 @@ namespace AzFramework
}
}
RotateCameraInput::RotateCameraInput(const InputChannelId rotateChannelId)
: m_rotateChannelId(rotateChannelId)
{
}
void RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_channelId == m_rotateChannelId)
const ClickDetector::ClickEvent clickEvent = [&event, this] {
if (const auto& input = AZStd::get_if<DiscreteInputEvent>(&event))
{
if (input->m_state == InputChannel::State::Began)
if (input->m_channelId == m_rotateChannelId)
{
m_tryingToBegin = true;
m_moveAccumulator = 0.0f;
}
else if (input->m_state == InputChannel::State::Ended)
{
m_tryingToBegin = false;
EndActivation();
if (input->m_state == InputChannel::State::Began)
{
return ClickDetector::ClickEvent::Down;
}
else if (input->m_state == InputChannel::State::Ended)
{
return ClickDetector::ClickEvent::Up;
}
}
}
}
return ClickDetector::ClickEvent::Nil;
}();
if (m_tryingToBegin)
switch (const auto outcome = m_clickDetector.DetectClick(clickEvent, cursorDelta); outcome)
{
// only allow the action to begin if the mouse has been moved a small amount
m_moveAccumulator += ScreenVectorLength(cursorDelta);
if (m_moveAccumulator > ed_cameraSystemLookDeadzone)
{
BeginActivation();
m_tryingToBegin = false;
}
case ClickDetector::ClickOutcome::Move:
BeginActivation();
break;
case ClickDetector::ClickOutcome::Release:
EndActivation();
break;
default:
// noop
break;
}
}
@@ -324,6 +323,12 @@ namespace AzFramework
return nextCamera;
}
PanCameraInput::PanCameraInput(const InputChannelId panChannelId, PanAxesFn panAxesFn)
: m_panAxesFn(AZStd::move(panAxesFn))
, m_panChannelId(panChannelId)
{
}
void PanCameraInput::HandleEvents(
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
@@ -400,6 +405,11 @@ namespace AzFramework
return TranslationType::Nil;
}
TranslateCameraInput::TranslateCameraInput(TranslationAxesFn translationAxesFn)
: m_translationAxesFn(AZStd::move(translationAxesFn))
{
}
void TranslateCameraInput::HandleEvents(
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
@@ -574,6 +584,11 @@ namespace AzFramework
return nextCamera;
}
OrbitDollyCursorMoveCameraInput::OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId)
: m_dollyChannelId(dollyChannelId)
{
}
void OrbitDollyCursorMoveCameraInput::HandleEvents(
const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta)
{
@@ -17,6 +17,8 @@
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/optional.h>
#include <AzFramework/Input/Channels/InputChannel.h>
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/CursorState.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzFramework/Viewport/ViewportId.h>
@@ -188,26 +190,21 @@ namespace AzFramework
Cameras m_cameras;
private:
CursorState m_cursorState;
float m_scrollDelta = 0.0f;
AZStd::optional<ScreenPoint> m_lastCursorPosition;
AZStd::optional<ScreenPoint> m_currentCursorPosition;
};
class RotateCameraInput : public CameraInput
{
public:
explicit RotateCameraInput(const InputChannelId rotateChannelId)
: m_rotateChannelId(rotateChannelId)
{
}
explicit RotateCameraInput(InputChannelId rotateChannelId);
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
private:
InputChannelId m_rotateChannelId;
float m_moveAccumulator = 0.0f;
bool m_tryingToBegin = false;
ClickDetector m_clickDetector;
};
struct PanAxes
@@ -240,11 +237,8 @@ namespace AzFramework
class PanCameraInput : public CameraInput
{
public:
PanCameraInput(const InputChannelId panChannelId, PanAxesFn panAxesFn)
: m_panAxesFn(AZStd::move(panAxesFn))
, m_panChannelId(panChannelId)
{
}
PanCameraInput(InputChannelId panChannelId, PanAxesFn panAxesFn);
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
@@ -283,10 +277,8 @@ namespace AzFramework
class TranslateCameraInput : public CameraInput
{
public:
explicit TranslateCameraInput(TranslationAxesFn translationAxesFn)
: m_translationAxesFn(AZStd::move(translationAxesFn))
{
}
explicit TranslateCameraInput(TranslationAxesFn translationAxesFn);
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
void ResetImpl() override;
@@ -363,8 +355,7 @@ namespace AzFramework
class OrbitDollyCursorMoveCameraInput : public CameraInput
{
public:
explicit OrbitDollyCursorMoveCameraInput(const InputChannelId dollyChannelId)
: m_dollyChannelId(dollyChannelId) {}
explicit OrbitDollyCursorMoveCameraInput(InputChannelId dollyChannelId);
void HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override;
Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override;
@@ -0,0 +1,68 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
namespace AzFramework
{
ClickDetector::ClickOutcome ClickDetector::DetectClick(const ClickEvent clickEvent, const ScreenVector& cursorDelta)
{
if (clickEvent == ClickEvent::Down)
{
const auto now = std::chrono::steady_clock::now();
if (m_tryBeginTime)
{
const std::chrono::duration<float> diff = now - m_tryBeginTime.value();
if (diff.count() < m_doubleClickInterval)
{
return ClickOutcome::Nil;
}
}
m_detectionState = DetectionState::WaitingForMove;
m_moveAccumulator = 0.0f;
m_tryBeginTime = now;
}
else if (clickEvent == ClickEvent::Up)
{
const auto clickOutcome = [detectionState = m_detectionState] {
if (detectionState == DetectionState::WaitingForMove)
{
return ClickOutcome::Click;
}
if (detectionState == DetectionState::Moved)
{
return ClickOutcome::Release;
}
return ClickOutcome::Nil;
}();
m_detectionState = DetectionState::Nil;
return clickOutcome;
}
if (m_detectionState == DetectionState::WaitingForMove)
{
// only allow the action to begin if the mouse has been moved a small amount
m_moveAccumulator += ScreenVectorLength(cursorDelta);
if (m_moveAccumulator > m_deadZone)
{
m_detectionState = DetectionState::Moved;
return ClickOutcome::Move;
}
}
return ClickOutcome::Nil;
}
} // namespace AzFramework
@@ -0,0 +1,75 @@
/*
* 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/std/optional.h>
#include <chrono>
namespace AzFramework
{
struct ScreenVector;
//! Utility class to help detect different types of mouse click (mouse down and up with
//! no movement), mouse move (down and initial move after some threshold) and mouse release
//! (mouse down with movement and then mouse up).
class ClickDetector
{
//! Alias for recording time of mouse down events
using Time = std::chrono::time_point<std::chrono::steady_clock>;
public:
//! Internal representation of click event (map from external event for this when
//! calling DetectClick).
enum class ClickEvent
{
Nil,
Down,
Up
};
//! The type of mouse click.
enum class ClickOutcome
{
Nil, //!< Not recognized.
Move, //!< Initial move after mouse down.
Click, //!< Mouse down and up with no intermediate movement.
Release //!< Mouse down with movement and then mouse up.
};
//! Called from any type of 'handle event' function.
ClickOutcome DetectClick(ClickEvent clickEvent, const ScreenVector& cursorDelta);
void SetDoubleClickInterval(float doubleClickInterval);
private:
//! Internal state of ClickDetector based on incoming events.
enum class DetectionState
{
Nil, //!< Initial state
WaitingForMove, //! Mouse down has happened but mouse hasn't yet moved.
Moved //! Mouse has moved, no longer will be counted as a click.
};
float m_moveAccumulator = 0.0f; //!< How far the mouse has moved after mouse down.
float m_deadZone = 2.0f; //!< How far to move before a click is cancelled (when Move will fire).
float m_doubleClickInterval = 0.4f; //!< Default double click interval, can be overridden.
DetectionState m_detectionState; //!< Internal state of ClickDetector.
AZStd::optional<Time> m_tryBeginTime; //!< Mouse down time (happens each mouse down, helps with double click handling).
};
inline void ClickDetector::SetDoubleClickInterval(const float doubleClickInterval)
{
m_doubleClickInterval = doubleClickInterval;
}
} // namespace AzFramework
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzFramework/Viewport/ScreenGeometry.h>
#include <AzCore/std/optional.h>
namespace AzFramework
{
//! Utility type to wrap a current and last cursor position.
struct CursorState
{
//! Returns the delta between the current and last cursor position.
[[nodiscard]] ScreenVector CursorDelta() const;
//! Call this in a 'handle event' call to update the most recent cursor position.
void SetCurrentPosition(const ScreenPoint& currentPosition);
//! Call this in an 'update' call to copy the current cursor position to the last
//! cursor position.
void Update();
private:
AZStd::optional<ScreenPoint> m_lastCursorPosition;
AZStd::optional<ScreenPoint> m_currentCursorPosition;
};
inline void CursorState::SetCurrentPosition(const ScreenPoint& currentPosition)
{
m_currentCursorPosition = currentPosition;
}
inline ScreenVector CursorState::CursorDelta() const
{
return m_currentCursorPosition.has_value() && m_lastCursorPosition.has_value()
? m_currentCursorPosition.value() - m_lastCursorPosition.value()
: ScreenVector(0, 0);
}
inline void CursorState::Update()
{
if (m_currentCursorPosition.has_value())
{
m_lastCursorPosition = m_currentCursorPosition;
}
}
} // namespace AzFramework
@@ -103,6 +103,9 @@ set(FILES
Viewport/CameraState.cpp
Viewport/CameraInput.h
Viewport/CameraInput.cpp
Viewport/ClickDetector.h
Viewport/ClickDetector.cpp
Viewport/CursorState.h
Viewport/DisplayContextRequestBus.h
Entity/BehaviorEntity.cpp
Entity/BehaviorEntity.h
@@ -63,29 +63,6 @@ namespace AzToolsFramework
void EditorNonUniformScaleComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawObbService"));
incompatible.push_back(AZ_CRC_CE("DebugDrawService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXActorService"));
incompatible.push_back(AZ_CRC_CE("EMotionFXSimpleMotionService"));
incompatible.push_back(AZ_CRC_CE("GradientTransformService"));
incompatible.push_back(AZ_CRC_CE("LegacyMeshService"));
incompatible.push_back(AZ_CRC_CE("LookAtService"));
incompatible.push_back(AZ_CRC_CE("SequenceService"));
incompatible.push_back(AZ_CRC_CE("ClothMeshService"));
incompatible.push_back(AZ_CRC_CE("PhysXJointService"));
incompatible.push_back(AZ_CRC_CE("PhysXCharacterControllerService"));
incompatible.push_back(AZ_CRC_CE("PhysXRagdollService"));
incompatible.push_back(AZ_CRC_CE("WhiteBoxService"));
incompatible.push_back(AZ_CRC_CE("NavigationAreaService"));
incompatible.push_back(AZ_CRC_CE("GeometryService"));
incompatible.push_back(AZ_CRC_CE("CapsuleShapeService"));
incompatible.push_back(AZ_CRC_CE("CompoundShapeService"));
incompatible.push_back(AZ_CRC_CE("CylinderShapeService"));
incompatible.push_back(AZ_CRC_CE("DiskShapeService"));
incompatible.push_back(AZ_CRC_CE("SphereShapeService"));
incompatible.push_back(AZ_CRC_CE("SplineService"));
incompatible.push_back(AZ_CRC_CE("TubeShapeService"));
}
void EditorNonUniformScaleComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
@@ -237,16 +237,15 @@ namespace AzToolsFramework
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Alt();
}
static bool IndividualSelect(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
static bool IndividualSelect(const AzFramework::ClickDetector::ClickOutcome clickOutcome)
{
return mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down;
return clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click;
}
static bool AdditiveIndividualSelect(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
static bool AdditiveIndividualSelect(
const AzFramework::ClickDetector::ClickOutcome clickOutcome, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
return mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down &&
return clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click &&
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl() &&
!mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Alt();
}
@@ -1783,6 +1782,25 @@ namespace AzToolsFramework
m_cachedEntityIdUnderCursor = m_editorHelpers->HandleMouseInteraction(cameraState, mouseInteraction);
const AzFramework::ClickDetector::ClickEvent selectClickEvent = [&mouseInteraction] {
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
{
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
return AzFramework::ClickDetector::ClickEvent::Down;
}
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
{
return AzFramework::ClickDetector::ClickEvent::Up;
}
}
return AzFramework::ClickDetector::ClickEvent::Nil;
}();
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
const auto clickOutcome = m_clickDetector.DetectClick(selectClickEvent, m_cursorState.CursorDelta());
// for entities selected with no bounds of their own (just TransformComponent)
// check selection against the selection indicator aabb
for (AZ::EntityId entityId : m_selectedEntityIds)
@@ -1841,7 +1859,7 @@ namespace AzToolsFramework
if (!m_selectedEntityIds.empty())
{
// select/deselect (add/remove) entities with ctrl held
if (Input::AdditiveIndividualSelect(mouseInteraction))
if (Input::AdditiveIndividualSelect(clickOutcome, mouseInteraction))
{
if (SelectDeselect(entityIdUnderCursor))
{
@@ -2023,7 +2041,7 @@ namespace AzToolsFramework
}
// standard toggle selection
if (Input::IndividualSelect(mouseInteraction))
if (Input::IndividualSelect(clickOutcome))
{
SelectDeselect(entityIdUnderCursor);
}
@@ -2526,7 +2544,7 @@ namespace AzToolsFramework
// create the cluster for changing transform mode
ViewportUi::ViewportUiRequestBus::EventResult(
m_transformModeClusterId, ViewportUi::DefaultViewportId,
&ViewportUi::ViewportUiRequestBus::Events::CreateCluster);
&ViewportUi::ViewportUiRequestBus::Events::CreateCluster, ViewportUi::Alignment::TopLeft);
// create and register the buttons (strings correspond to icons even if the values appear different)
m_translateButtonId = RegisterClusterButton(m_transformModeClusterId, "Move");
@@ -3267,6 +3285,8 @@ namespace AzToolsFramework
const auto modifiers = ViewportInteraction::KeyboardModifiers(
ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
m_cursorState.Update();
HandleAccents(
!m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor,
modifiers.Ctrl(), m_hoveredEntityId,
@@ -17,6 +17,8 @@
#include <AzCore/std/optional.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzFramework/Components/CameraBus.h>
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/CursorState.h>
#include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/Commands/EntityManipulatorCommand.h>
#include <AzToolsFramework/ComponentMode/EditorComponentModeBus.h>
@@ -35,37 +37,37 @@ namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; ///< Alias for unordered_set of EntityIds.
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; //!< Alias for unordered_set of EntityIds.
/// Entity related data required by manipulators during action.
//! Entity related data required by manipulators during action.
struct EntityIdManipulatorLookup
{
AZ::Transform m_initial; /// Transform of Entity at mouse down on manipulator.
AZ::Transform m_initial; //!< Transform of Entity at mouse down on manipulator.
};
/// Alias for a mapping between EntityIds and Entity related data required by manipulators.
//! Alias for a mapping between EntityIds and Entity related data required by manipulators.
using EntityIdManipulatorLookups = AZStd::unordered_map<AZ::EntityId, EntityIdManipulatorLookup>;
/// Generic wrapper to handle specific manipulators controlling 1-* entities.
//! Generic wrapper to handle specific manipulators controlling 1-* entities.
struct EntityIdManipulators
{
EntityIdManipulatorLookups m_lookups; ///< Mapping between the EntityId and the transform of the Entity at
///< the point a manipulator started adjusting it.
AZStd::unique_ptr<Manipulators> m_manipulators; ///< The aggregate manipulator currently in use.
EntityIdManipulatorLookups m_lookups; //!< Mapping between the EntityId and the transform of the Entity at
//!< the point a manipulator started adjusting it.
AZStd::unique_ptr<Manipulators> m_manipulators; //!< The aggregate manipulator currently in use.
};
/// Store translation and orientation only (no scale).
//! Store translation and orientation only (no scale).
struct Frame
{
AZ::Vector3 m_translation = AZ::Vector3::CreateZero(); ///< Position of frame.
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity(); ///< Orientation of frame.
AZ::Vector3 m_translation = AZ::Vector3::CreateZero(); //!< Position of frame.
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity(); //!< Orientation of frame.
};
/// Temporary manipulator frame used during selection.
//! Temporary manipulator frame used during selection.
struct OptionalFrame
{
/// What part of the transform did we pick (when using ditto on
/// the manipulator). This will depend on the transform mode we're in.
//! What part of the transform did we pick (when using ditto on
//! the manipulator). This will depend on the transform mode we're in.
struct PickType
{
enum : AZ::u8
@@ -83,29 +85,29 @@ namespace AzToolsFramework
bool PickedTranslation() const;
bool PickedOrientation() const;
/// Clear all state associated with the frame.
//! Clear all state associated with the frame.
void Reset();
/// Clear only picked translation state.
//! Clear only picked translation state.
void ResetPickedTranslation();
/// Clear only picked orientation state.
//! Clear only picked orientation state.
void ResetPickedOrientation();
AZ::EntityId m_pickedEntityIdOverride; ///< 'Picked' Entity - frame and parent space relative to this if active.
AZStd::optional<AZ::Vector3> m_translationOverride; ///< Translation override, if set, reset when selection is empty.
AZStd::optional<AZ::Quaternion> m_orientationOverride; ///< Orientation override, if set, reset when selection is empty.
AZ::u8 m_pickTypes = PickType::None; ///< What mode(s) were we in when picking an EntityId override.
AZ::EntityId m_pickedEntityIdOverride; //!< 'Picked' Entity - frame and parent space relative to this if active.
AZStd::optional<AZ::Vector3> m_translationOverride; //!< Translation override, if set, reset when selection is empty.
AZStd::optional<AZ::Quaternion> m_orientationOverride; //!< Orientation override, if set, reset when selection is empty.
AZ::u8 m_pickTypes = PickType::None; //!< What mode(s) were we in when picking an EntityId override.
};
/// What frame/space is the manipulator currently operating in.
//! What frame/space is the manipulator currently operating in.
enum class ReferenceFrame
{
Local, /// The local space of the individual entity.
Parent, /// The parent space of the individual entity (world space if no parent exists).
World, /// World space (space aligned to world axes - identity).
Local, //!< The local space of the individual entity.
Parent, //!< The parent space of the individual entity (world space if no parent exists).
World, //!< World space (space aligned to world axes - identity).
};
/// Entity selection/interaction handling.
/// Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
//! Entity selection/interaction handling.
//! Provide a suite of functionality for manipulating entities, primarily through their TransformComponent.
class EditorTransformComponentSelection
: public ViewportInteraction::ViewportSelectionRequests
, private EditorEventsBus::Handler
@@ -127,15 +129,15 @@ namespace AzToolsFramework
EditorTransformComponentSelection& operator=(const EditorTransformComponentSelection&) = delete;
virtual ~EditorTransformComponentSelection();
/// Register entity manipulators with the ManipulatorManager.
/// After being registered, the entity manipulators will draw and check for input.
//! Register entity manipulators with the ManipulatorManager.
//! After being registered, the entity manipulators will draw and check for input.
void RegisterManipulator();
/// Unregister entity manipulators with the ManipulatorManager.
/// No longer draw or respond to input.
//! Unregister entity manipulators with the ManipulatorManager.
//! No longer draw or respond to input.
void UnregisterManipulator();
/// ViewportInteraction::ViewportSelectionRequests
/// Intercept all viewport mouse events and respond to inputs.
//! ViewportInteraction::ViewportSelectionRequests
//! Intercept all viewport mouse events and respond to inputs.
bool HandleMouseInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
void DisplayViewportSelection(
@@ -145,9 +147,9 @@ namespace AzToolsFramework
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
/// Add an entity to the current selection
//! Add an entity to the current selection
void AddEntityToSelection(AZ::EntityId entityId);
/// Remove an entity from the current selection
//! Remove an entity from the current selection
void RemoveEntityFromSelection(AZ::EntityId entityId);
private:
@@ -161,8 +163,8 @@ namespace AzToolsFramework
void ClearManipulatorTranslationOverride();
void ClearManipulatorOrientationOverride();
/// Handle an event triggered by the user to clear any manipulator overrides.
/// Delegate to either translation or orientation reset/clear depending on the state we're in.
//! Handle an event triggered by the user to clear any manipulator overrides.
//! Delegate to either translation or orientation reset/clear depending on the state we're in.
void DelegateClearManipulatorOverride();
void ToggleCenterPivotSelection();
@@ -251,63 +253,65 @@ namespace AzToolsFramework
void SetEntityLocalScale(AZ::EntityId entityId, const AZ::Vector3& localScale);
void SetEntityLocalRotation(AZ::EntityId entityId, const AZ::Vector3& localRotation);
AZ::EntityId m_hoveredEntityId; ///< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; ///< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; ///< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; ///< Represents the current entities in the selection.
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; //!< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; //!< Represents the current entities in the selection.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; ///< A cache of packed EntityData that can be
///< iterated over efficiently without the need
///< to make individual EBus calls.
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; ///< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; ///< Mapping from a Manipulator to potentially many EntityIds.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< A cache of packed EntityData that can be
//!< iterated over efficiently without the need
//!< to make individual EBus calls.
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.
EditorBoxSelect m_boxSelect; ///< Type responsible for handling box select.
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; ///< Track adjustments to manipulator translation and orientation (during mouse press/move).
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; ///< What actions are tied to this handler.
ViewportInteraction::KeyboardModifiers m_previousModifiers; ///< What modifiers were held last frame.
EditorContextMenu m_contextMenu; ///< Viewport right click context menu.
OptionalFrame m_pivotOverrideFrame; ///< Has a pivot override been set.
Mode m_mode = Mode::Translation; ///< Manipulator mode - default to translation.
Pivot m_pivotMode = Pivot::Object; ///< Entity pivot mode - default to object (authored root).
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; ///< What reference frame is the Manipulator currently operating in.
Frame m_axisPreview; ///< Axes of entity at the time of mouse down to indicate delta of translation.
bool m_triedToRefresh = false; ///< Did a refresh event occur to recalculate the current Manipulator transform.
bool m_didSetSelectedEntities = false; ///< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_selectedEntityIdsAndManipulatorsDirty = false; ///< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
bool m_transformChangedInternally = false; ///< Was an OnTransformChanged event triggered internally or not.
ViewportUi::ClusterId m_transformModeClusterId; ///< Id of the Viewport UI cluster for changing transform mode.
ViewportUi::ButtonId m_translateButtonId; ///< Id of the Viewport UI button for translate mode.
ViewportUi::ButtonId m_rotateButtonId; ///< Id of the Viewport UI button for rotate mode.
ViewportUi::ButtonId m_scaleButtonId; ///< Id of the Viewport UI button for scale mode.
AZ::Event<ViewportUi::ButtonId>::Handler m_transformModeSelectionHandler; ///< Event handler for the Viewport UI cluster.
EditorBoxSelect m_boxSelect; //!< Type responsible for handling box select.
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; //!< Track adjustments to manipulator translation and orientation (during mouse press/move).
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; //!< What actions are tied to this handler.
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< What modifiers were held last frame.
EditorContextMenu m_contextMenu; //!< Viewport right click context menu.
OptionalFrame m_pivotOverrideFrame; //!< Has a pivot override been set.
Mode m_mode = Mode::Translation; //!< Manipulator mode - default to translation.
Pivot m_pivotMode = Pivot::Object; //!< Entity pivot mode - default to object (authored root).
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; //!< What reference frame is the Manipulator currently operating in.
Frame m_axisPreview; //!< Axes of entity at the time of mouse down to indicate delta of translation.
bool m_triedToRefresh = false; //!< Did a refresh event occur to recalculate the current Manipulator transform.
bool m_didSetSelectedEntities = false; //!< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_selectedEntityIdsAndManipulatorsDirty = false; //!< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
bool m_transformChangedInternally = false; //!< Was an OnTransformChanged event triggered internally or not.
ViewportUi::ClusterId m_transformModeClusterId; //!< Id of the Viewport UI cluster for changing transform mode.
ViewportUi::ButtonId m_translateButtonId; //!< Id of the Viewport UI button for translate mode.
ViewportUi::ButtonId m_rotateButtonId; //!< Id of the Viewport UI button for rotate mode.
ViewportUi::ButtonId m_scaleButtonId; //!< Id of the Viewport UI button for scale mode.
AZ::Event<ViewportUi::ButtonId>::Handler m_transformModeSelectionHandler; //!< Event handler for the Viewport UI cluster.
AzFramework::ClickDetector m_clickDetector; //!< Detect different types of mouse click.
AzFramework::CursorState m_cursorState; //!< Track the mouse position and delta movement each frame.
};
/// The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
/// the EditorTransformComponentSelection type. Functions in this namespace are exposed to facilitate testing
/// and should not be used outside of EditorTransformComponentSelection or EditorTransformComponentSelectionTests.
//! The ETCS (EntityTransformComponentSelection) namespace contains functions and data used exclusively by
//! the EditorTransformComponentSelection type. Functions in this namespace are exposed to facilitate testing
//! and should not be used outside of EditorTransformComponentSelection or EditorTransformComponentSelectionTests.
namespace ETCS
{
/// The result from calculating the entity (transform component) orientation.
/// Does the entity have a parent or not, and what orientation should the manipulator have when
/// displayed at the object pivot (determined by the entity hierarchy and what modifiers are held).
//! The result from calculating the entity (transform component) orientation.
//! Does the entity have a parent or not, and what orientation should the manipulator have when
//! displayed at the object pivot (determined by the entity hierarchy and what modifiers are held).
struct PivotOrientationResult
{
AZ::Quaternion m_worldOrientation;
AZ::EntityId m_parentId;
};
/// Calculate the orientation for an individual entity based on the incoming reference frame.
/// Note: If the entity is in a hierarchy the Parent reference frame will return the orientation of the parent.
//! Calculate the orientation for an individual entity based on the incoming reference frame.
//! Note: If the entity is in a hierarchy the Parent reference frame will return the orientation of the parent.
PivotOrientationResult CalculatePivotOrientation(AZ::EntityId entityId, ReferenceFrame referenceFrame);
/// Calculate the orientation for a group of entities based on the incoming reference frame.
//! Calculate the orientation for a group of entities based on the incoming reference frame.
template<typename EntityIdMap>
PivotOrientationResult CalculatePivotOrientationForEntityIds(
const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
/// Calculate the orientation for a group of entities based on the incoming
/// reference frame with possible pivot override.
//! Calculate the orientation for a group of entities based on the incoming
//! reference frame with possible pivot override.
template<typename EntityIdMap>
PivotOrientationResult CalculateSelectionPivotOrientation(
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame,
@@ -41,6 +41,28 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
static Qt::Alignment GetQtAlignment(Alignment align)
{
switch (align)
{
case Alignment::TopRight:
return Qt::AlignTop | Qt::AlignRight;
case Alignment::TopLeft:
return Qt::AlignTop | Qt::AlignLeft;
case Alignment::BottomRight:
return Qt::AlignBottom | Qt::AlignRight;
case Alignment::BottomLeft:
return Qt::AlignBottom | Qt::AlignLeft;
case Alignment::Top:
return Qt::AlignTop;
case Alignment::Bottom:
return Qt::AlignBottom;
}
AZ_Assert(false, "ViewportUI", "Unhandled ViewportUI Alignment %d", static_cast<int>(align));
return Qt::AlignTop;
}
ViewportUiDisplay::ViewportUiDisplay(QWidget* parent, QWidget* renderOverlay)
: m_renderOverlay(renderOverlay)
, m_uiMainWindow(parent)
@@ -56,7 +78,7 @@ namespace AzToolsFramework::ViewportUi::Internal
UnparentWidgets(m_viewportUiElements);
}
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup)
void ViewportUiDisplay::AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
{
if (!buttonGroup.get())
{
@@ -66,7 +88,7 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiCluster = AZStd::make_shared<ViewportUiCluster>(buttonGroup);
auto id = AddViewportUiElement(viewportUiCluster);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, Qt::AlignTop | Qt::AlignLeft);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
}
void ViewportUiDisplay::AddClusterButton(
@@ -94,7 +116,7 @@ namespace AzToolsFramework::ViewportUi::Internal
}
}
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup)
void ViewportUiDisplay::AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, const Alignment align)
{
if (!buttonGroup.get())
{
@@ -104,7 +126,7 @@ namespace AzToolsFramework::ViewportUi::Internal
auto viewportUiSwitcher = AZStd::make_shared<ViewportUiSwitcher>(buttonGroup);
auto id = AddViewportUiElement(viewportUiSwitcher);
buttonGroup->SetViewportUiElementId(id);
PositionViewportUiElementAnchored(id, Qt::AlignTop | Qt::AlignLeft);
PositionViewportUiElementAnchored(id, GetQtAlignment(align));
}
void ViewportUiDisplay::AddSwitcherButton(const ViewportUiElementId clusterId, Button* button)
@@ -56,12 +56,12 @@ namespace AzToolsFramework::ViewportUi::Internal
ViewportUiDisplay(QWidget* parent, QWidget* renderOverlay);
~ViewportUiDisplay();
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup);
void AddCluster(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddClusterButton(ViewportUiElementId clusterId, Button* button);
void RemoveClusterButton(ViewportUiElementId clusterId, ButtonId buttonId);
void UpdateCluster(const ViewportUiElementId clusterId);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup);
void AddSwitcher(AZStd::shared_ptr<ButtonGroup> buttonGroup, Alignment align);
void AddSwitcherButton(ViewportUiElementId switcherId, Button* button);
void RemoveSwitcherButton(ViewportUiElementId switcherId, ButtonId buttonId);
void UpdateSwitcher(ViewportUiElementId switcherId);
@@ -30,18 +30,18 @@ namespace AzToolsFramework::ViewportUi
ViewportUiRequestBus::Handler::BusDisconnect();
}
const ClusterId ViewportUiManager::CreateCluster()
const ClusterId ViewportUiManager::CreateCluster(const Alignment align)
{
auto buttonGroup = AZStd::make_shared<Internal::ButtonGroup>();
m_viewportUi->AddCluster(buttonGroup);
m_viewportUi->AddCluster(buttonGroup, align);
return RegisterNewCluster(buttonGroup);
}
const SwitcherId ViewportUiManager::CreateSwitcher()
const SwitcherId ViewportUiManager::CreateSwitcher(const Alignment align)
{
auto buttonGroup = AZStd::make_shared<Internal::ButtonGroup>();
m_viewportUi->AddSwitcher(buttonGroup);
m_viewportUi->AddSwitcher(buttonGroup, align);
return RegisterNewSwitcher(buttonGroup);
}
@@ -31,8 +31,8 @@ namespace AzToolsFramework::ViewportUi
~ViewportUiManager() = default;
// ViewportUiRequestBus ...
const ClusterId CreateCluster() override;
const SwitcherId CreateSwitcher() override;
const ClusterId CreateCluster(Alignment align) override;
const SwitcherId CreateSwitcher(Alignment align) override;
void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override;
void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override;
const ButtonId CreateClusterButton(ClusterId clusterId, const AZStd::string& icon) override;
@@ -41,15 +41,26 @@ namespace AzToolsFramework::ViewportUi
String
};
//! Used to anchor widgets to a specific side of the viewport.
enum class Alignment
{
TopRight,
TopLeft,
BottomRight,
BottomLeft,
Top,
Bottom
};
//! Viewport requests to interact with the Viewport UI. Viewport UI refers to the entire UI overlay (one per viewport).
//! Each widget on the Viewport UI is referred to as an element.
class ViewportUiRequests
{
public:
//! Creates and registers a cluster with the Viewport UI system.
virtual const ClusterId CreateCluster() = 0;
virtual const ClusterId CreateCluster(Alignment align) = 0;
//! Creates and registers a switcher with the Viewport UI system.
virtual const SwitcherId CreateSwitcher() = 0;
virtual const SwitcherId CreateSwitcher(Alignment align) = 0;
//! Sets the active button of the cluster. This is the button which will display as highlighted.
virtual void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) = 0;
//! Sets the active button of the switcher. This is the button which has a text label.
@@ -72,7 +72,7 @@ namespace UnitTest
TEST_F(ViewportUiDisplayTestFixture, RemoveViewportUiElementRemovesElementFromViewportUi)
{
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto widget = viewportUi.GetViewportUiElement(m_buttonGroup->GetViewportUiElementId());
EXPECT_TRUE(widget.get() != nullptr);
@@ -89,7 +89,7 @@ namespace UnitTest
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
viewportUi.ShowViewportUiElement(m_buttonGroup->GetViewportUiElementId());
@@ -102,7 +102,7 @@ namespace UnitTest
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.HideViewportUiElement(m_buttonGroup->GetViewportUiElementId());
EXPECT_FALSE(viewportUi.IsViewportUiElementVisible(m_buttonGroup->GetViewportUiElementId()));
@@ -112,7 +112,7 @@ namespace UnitTest
{
ViewportUiDisplay viewportUi(m_parentWidget, m_mockRenderOverlay);
viewportUi.InitializeUiOverlay();
viewportUi.AddCluster(m_buttonGroup);
viewportUi.AddCluster(m_buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
auto widget = viewportUi.GetViewportUiElement(m_buttonGroup->GetViewportUiElementId());
@@ -129,7 +129,7 @@ namespace UnitTest
auto buttonGroup = AZStd::make_shared<ButtonGroup>();
buttonGroup->AddButton("");
viewportUi.AddCluster(buttonGroup);
viewportUi.AddCluster(buttonGroup, AzToolsFramework::ViewportUi::Alignment::TopLeft);
viewportUi.Update();
EXPECT_TRUE(viewportUi.GetUiMainWindow()->isVisible());
@@ -101,7 +101,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, CreateClusterAddsNewClusterAndReturnsId)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
EXPECT_TRUE(clusterEntry != m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().end());
@@ -110,7 +110,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, CreateClusterButtonAddsNewButtonAndReturnsId)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -120,7 +120,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, SetClusterActiveButtonSetsButtonStateToActive)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -133,7 +133,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, RegisterClusterEventHandlerConnectsHandlerToClusterEvent)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
// create a handler which will be triggered by the cluster
@@ -159,7 +159,7 @@ namespace UnitTest
TEST_F(ViewportUiManagerTestFixture, RemoveClusterRemovesClusterFromViewportUi)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
m_viewportManagerWrapper.GetViewportManager()->RemoveCluster(clusterId);
auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
@@ -171,7 +171,7 @@ namespace UnitTest
{
m_viewportManagerWrapper.GetMockRenderOverlay()->setVisible(true);
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster();
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
m_viewportManagerWrapper.GetViewportManager()->Update();
+142
View File
@@ -0,0 +1,142 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/ScreenGeometry.h>
namespace AzFramework
{
std::ostream& operator<<(std::ostream& os, const ClickDetector::ClickOutcome clickOutcome)
{
switch (clickOutcome)
{
case ClickDetector::ClickOutcome::Click:
os << "ClickOutcome::Click";
break;
case ClickDetector::ClickOutcome::Move:
os << "ClickOutcome::Move";
break;
case ClickDetector::ClickOutcome::Release:
os << "ClickOutcome::Release";
break;
case ClickDetector::ClickOutcome::Nil:
os << "ClickOutcome::Nil";
break;
}
return os;
}
} // namespace AzFramework
namespace UnitTest
{
using AzFramework::ClickDetector;
using AzFramework::ScreenVector;
class ClickDetectorFixture : public ::testing::Test
{
public:
ClickDetector m_clickDetector;
};
TEST_F(ClickDetectorFixture, ClickIsDetectedWithNoMouseMovementOnMouseUp)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
}
TEST_F(ClickDetectorFixture, MoveIsDetectedWithMouseMovementAfterMouseDown)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome initialMoveOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialMoveOutcome, Eq(ClickDetector::ClickOutcome::Move));
}
TEST_F(ClickDetectorFixture, ReleaseIsDetectedAfterMouseMovementOnMouseUp)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
// move
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Release));
}
TEST_F(ClickDetectorFixture, MoveIsReturnedOnlyAfterFirstMouseMove)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome initialMoveOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
const ClickDetector::ClickOutcome secondaryMoveOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(10, 10));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialMoveOutcome, Eq(ClickDetector::ClickOutcome::Move));
EXPECT_THAT(secondaryMoveOutcome, Eq(ClickDetector::ClickOutcome::Nil));
}
TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterDoubleClick)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondaryDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondaryUpOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
EXPECT_THAT(secondaryDownOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // double click
EXPECT_THAT(secondaryUpOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // click not registered
}
TEST_F(ClickDetectorFixture, ClickIsNotRegisteredAfterIgnoredDoubleClick)
{
using ::testing::Eq;
const ClickDetector::ClickOutcome initialDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Down, ScreenVector(0, 0));
const ClickDetector::ClickOutcome initialUpOutcome = m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondaryDownOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Nil, ScreenVector(0, 0));
const ClickDetector::ClickOutcome secondaryUpOutcome =
m_clickDetector.DetectClick(ClickDetector::ClickEvent::Up, ScreenVector(0, 0));
EXPECT_THAT(initialDownOutcome, Eq(ClickDetector::ClickOutcome::Nil));
EXPECT_THAT(initialUpOutcome, Eq(ClickDetector::ClickOutcome::Click));
EXPECT_THAT(secondaryDownOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // ignored double click
EXPECT_THAT(secondaryUpOutcome, Eq(ClickDetector::ClickOutcome::Nil)); // click not registered
}
} // namespace UnitTest
+54
View File
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Viewport/CursorState.h>
namespace UnitTest
{
using AzFramework::CursorState;
using AzFramework::ScreenVector;
using AzFramework::ScreenPoint;
class CursorStateFixture : public ::testing::Test
{
public:
CursorState m_cursorState;
};
TEST_F(CursorStateFixture, CursorStateHasZeroDeltaInitially)
{
using ::testing::Eq;
EXPECT_THAT(m_cursorState.CursorDelta(), Eq(ScreenVector(0, 0)));
}
TEST_F(CursorStateFixture, CursorStateReturnsZeroDeltaAfterSingleMoveAndUpdate)
{
using ::testing::Eq;
m_cursorState.SetCurrentPosition(ScreenPoint(10, 10));
m_cursorState.Update();
EXPECT_THAT(m_cursorState.CursorDelta(), Eq(ScreenVector(0, 0)));
}
TEST_F(CursorStateFixture, CursorStateReturnsDeltaAfterSecondMoveAndUpdate)
{
using ::testing::Eq;
m_cursorState.SetCurrentPosition(ScreenPoint(10, 10));
m_cursorState.Update();
m_cursorState.SetCurrentPosition(ScreenPoint(15, 22));
EXPECT_THAT(m_cursorState.CursorDelta(), Eq(ScreenVector(5, 12)));
}
} // namespace UnitTest
@@ -17,6 +17,8 @@ set(FILES
BinToTextEncode.cpp
ComponentAddRemove.cpp
ComponentAdapterTests.cpp
ClickDetectorTests.cpp
CursorStateTests.cpp
EntityContext.cpp
EntityTestbed.h
FileFunc.cpp
-5
View File
@@ -1,5 +0,0 @@
#Ignore these directories
SDKs
#ignore these files
*.user
-1
View File
@@ -15,7 +15,6 @@ add_subdirectory(AWSNativeSDKInit)
add_subdirectory(AzTestRunner)
add_subdirectory(CrashHandler)
add_subdirectory(CryCommonTools)
add_subdirectory(CryXML)
add_subdirectory(News)
add_subdirectory(PythonBindingsExample)
add_subdirectory(RemoteConsole)
-26
View File
@@ -13,44 +13,18 @@ if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_add_target(
NAME CryCommonTools STATIC
NAMESPACE Legacy
FILES_CMAKE
crycommontools_files.cmake
${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
${pal_dir}
BUILD_DEPENDENCIES
PRIVATE
3rdParty::lz4
3rdParty::zlib
3rdParty::zstd
AZ::AzCore
PUBLIC
Legacy::CryCommon
AZ::AzFramework
)
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
ly_add_target(
NAME CryCommonTools.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
NAMESPACE Legacy
FILES_CMAKE
crycommontools_tests_files.cmake
INCLUDE_DIRECTORIES
PUBLIC
UnitTests
BUILD_DEPENDENCIES
PRIVATE
Legacy::CryCommonTools
AZ::AzTest
)
ly_add_googletest(
NAME Legacy::CryCommonTools.Tests
)
endif()
-18
View File
@@ -1,18 +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.
*
*/
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
#define CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
#pragma once
static const char* g_LumberyardExportNodeTag = "LumberyardExportNode";
#endif // CRYINCLUDE_CRYCOMMONTOOLS_COLLADASHARED_H
-514
View File
@@ -1,514 +0,0 @@
// Modifications copyright Amazon.com, Inc. or its affiliates.
#include <platform.h>
// Taken from http://tog.acm.org/GraphicsGems/gemsiv/polar_decomp/Decompose.c
/**** Decompose.c ****/
/* Ken Shoemake, 1993 */
#include <math.h>
#include "Decompose.h"
#pragma warning(disable:4244) // conversion from 'double' to 'float', possible loss of data
#pragma warning(disable:4305) // 'initializing' : truncation from 'double' to 'float'
namespace decomp {
/******* Matrix Preliminaries *******/
/** Fill out 3x3 matrix to 4x4 **/
#define mat_pad(A) (A[W][X]=A[X][W]=A[W][Y]=A[Y][W]=A[W][Z]=A[Z][W]=0,A[W][W]=1)
/** Copy nxn matrix A to C using "gets" for assignment **/
#define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
C[i][j] gets (A[i][j]);}
/** Copy transpose of nxn matrix A to C using "gets" for assignment **/
#define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
AT[i][j] gets (A[j][i]);}
/** Assign nxn matrix C the element-wise combination of A and B using "op" **/
#define mat_binop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
C[i][j] gets (A[i][j]) op (B[i][j]);}
/** Multiply the upper left 3x3 parts of A and B to get AB **/
void mat_mult(HMatrix A, HMatrix B, HMatrix AB)
{
int i, j;
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
AB[i][j] = A[i][0] * B[0][j] + A[i][1] * B[1][j] + A[i][2] * B[2][j];
}
/** Return dot product of length 3 vectors va and vb **/
float vdot(float* va, float* vb)
{
return (va[0] * vb[0] + va[1] * vb[1] + va[2] * vb[2]);
}
/** Set v to cross product of length 3 vectors va and vb **/
void vcross(float* va, float* vb, float* v)
{
v[0] = va[1] * vb[2] - va[2] * vb[1];
v[1] = va[2] * vb[0] - va[0] * vb[2];
v[2] = va[0] * vb[1] - va[1] * vb[0];
}
/** Set MadjT to transpose of inverse of M times determinant of M **/
void adjoint_transpose(HMatrix M, HMatrix MadjT)
{
vcross(M[1], M[2], MadjT[0]);
vcross(M[2], M[0], MadjT[1]);
vcross(M[0], M[1], MadjT[2]);
}
/******* Quaternion Preliminaries *******/
/* Construct a (possibly non-unit) quaternion from real components. */
Quat Qt_(float x, float y, float z, float w)
{
Quat qq;
qq.x = x; qq.y = y; qq.z = z; qq.w = w;
return (qq);
}
/* Return conjugate of quaternion. */
Quat Qt_Conj(Quat q)
{
Quat qq;
qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;
return (qq);
}
/* Return quaternion product qL * qR. Note: order is important!
* To combine rotations, use the product Mul(qSecond, qFirst),
* which gives the effect of rotating by qFirst then qSecond. */
Quat Qt_Mul(Quat qL, Quat qR)
{
Quat qq;
qq.w = qL.w * qR.w - qL.x * qR.x - qL.y * qR.y - qL.z * qR.z;
qq.x = qL.w * qR.x + qL.x * qR.w + qL.y * qR.z - qL.z * qR.y;
qq.y = qL.w * qR.y + qL.y * qR.w + qL.z * qR.x - qL.x * qR.z;
qq.z = qL.w * qR.z + qL.z * qR.w + qL.x * qR.y - qL.y * qR.x;
return (qq);
}
/* Return product of quaternion q by scalar w. */
Quat Qt_Scale(Quat q, float w)
{
Quat qq;
qq.w = q.w * w; qq.x = q.x * w; qq.y = q.y * w; qq.z = q.z * w;
return (qq);
}
/* Construct a unit quaternion from rotation matrix. Assumes matrix is
* used to multiply column vector on the left: vnew = mat vold. Works
* correctly for right-handed coordinate system and right-handed rotations.
* Translation and perspective components ignored. */
Quat Qt_FromMatrix(HMatrix mat)
{
/* This algorithm avoids near-zero divides by looking for a large component
* - first w, then x, y, or z. When the trace is greater than zero,
* |w| is greater than 1/2, which is as small as a largest component can be.
* Otherwise, the largest diagonal entry corresponds to the largest of |x|,
* |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */
Quat qu;
double tr, s;
tr = mat[X][X] + mat[Y][Y] + mat[Z][Z];
if (tr >= 0.0) {
s = sqrt(tr + mat[W][W]);
qu.w = s * 0.5;
s = 0.5 / s;
qu.x = (mat[Z][Y] - mat[Y][Z]) * s;
qu.y = (mat[X][Z] - mat[Z][X]) * s;
qu.z = (mat[Y][X] - mat[X][Y]) * s;
} else {
int h = X;
if (mat[Y][Y] > mat[X][X]) h = Y;
if (mat[Z][Z] > mat[h][h]) h = Z;
switch (h) {
#define caseMacro(i,j,k,I,J,K) \
case I:\
s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\
qu.i = s*0.5;\
s = 0.5 / s;\
qu.j = (mat[I][J] + mat[J][I]) * s;\
qu.k = (mat[K][I] + mat[I][K]) * s;\
qu.w = (mat[K][J] - mat[J][K]) * s;\
break
caseMacro(x, y, z, X, Y, Z);
caseMacro(y, z, x, Y, Z, X);
caseMacro(z, x, y, Z, X, Y);
}
}
if (mat[W][W] != 1.0) qu = Qt_Scale(qu, 1 / sqrt(mat[W][W]));
return (qu);
}
/******* Decomp Auxiliaries *******/
static HMatrix mat_id = { {1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1} };
/** Compute either the 1 or infinity norm of M, depending on tpose **/
float mat_norm(HMatrix M, int tpose)
{
int i;
float sum, max;
max = 0.0;
for (i = 0; i < 3; i++) {
if (tpose) sum = fabs(M[0][i]) + fabs(M[1][i]) + fabs(M[2][i]);
else sum = fabs(M[i][0]) + fabs(M[i][1]) + fabs(M[i][2]);
if (max < sum) max = sum;
}
return max;
}
float norm_inf(HMatrix M) { return mat_norm(M, 0); }
float norm_one(HMatrix M) { return mat_norm(M, 1); }
/** Return index of column of M containing maximum abs entry, or -1 if M=0 **/
int find_max_col(HMatrix M)
{
float abs, max;
int i, j, col;
max = 0.0; col = -1;
for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) {
abs = M[i][j]; if (abs < 0.0) abs = -abs;
if (abs > max) { max = abs; col = j; }
}
return col;
}
/** Setup u for Household reflection to zero all v components but first **/
void make_reflector(float* v, float* u)
{
float s = sqrt(vdot(v, v));
u[0] = v[0]; u[1] = v[1];
u[2] = v[2] + ((v[2] < 0.0) ? -s : s);
s = sqrt(2.0 / vdot(u, u));
u[0] = u[0] * s; u[1] = u[1] * s; u[2] = u[2] * s;
}
/** Apply Householder reflection represented by u to column vectors of M **/
void reflect_cols(HMatrix M, float* u)
{
int i, j;
for (i = 0; i < 3; i++) {
float s = u[0] * M[0][i] + u[1] * M[1][i] + u[2] * M[2][i];
for (j = 0; j < 3; j++) M[j][i] -= u[j] * s;
}
}
/** Apply Householder reflection represented by u to row vectors of M **/
void reflect_rows(HMatrix M, float* u)
{
int i, j;
for (i = 0; i < 3; i++) {
float s = vdot(u, M[i]);
for (j = 0; j < 3; j++) M[i][j] -= u[j] * s;
}
}
/** Find orthogonal factor Q of rank 1 (or less) M **/
void do_rank1(HMatrix M, HMatrix Q)
{
float v1[3], v2[3], s;
int col;
mat_copy(Q, =, mat_id, 4);
/* If rank(M) is 1, we should find a non-zero column in M */
col = find_max_col(M);
if (col < 0) return; /* Rank is 0 */
v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
make_reflector(v1, v1); reflect_cols(M, v1);
v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
make_reflector(v2, v2); reflect_rows(M, v2);
s = M[2][2];
if (s < 0.0) Q[2][2] = -1.0;
reflect_cols(Q, v1); reflect_rows(Q, v2);
}
/** Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose **/
void do_rank2(HMatrix M, HMatrix MadjT, HMatrix Q)
{
float v1[3], v2[3];
float w, x, y, z, c, s, d;
int col;
/* If rank(M) is 2, we should find a non-zero column in MadjT */
col = find_max_col(MadjT);
if (col < 0) { do_rank1(M, Q); return; } /* Rank<2 */
v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
make_reflector(v1, v1); reflect_cols(M, v1);
vcross(M[0], M[1], v2);
make_reflector(v2, v2); reflect_rows(M, v2);
w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
if (w * z > x* y) {
c = z + w; s = y - x; d = sqrt(c * c + s * s); c = c / d; s = s / d;
Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
} else {
c = z - w; s = y + x; d = sqrt(c * c + s * s); c = c / d; s = s / d;
Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
}
Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
reflect_cols(Q, v1); reflect_rows(Q, v2);
}
/******* Polar Decomposition *******/
/* Polar Decomposition of 3x3 matrix in 4x4,
* M = QS. See Nicholas Higham and Robert S. Schreiber,
* Fast Polar Decomposition of An Arbitrary Matrix,
* Technical Report 88-942, October 1988,
* Department of Computer Science, Cornell University.
*/
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S)
{
#define TOL 1.0e-6
HMatrix Mk, MadjTk, Ek;
float det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
int i, j;
mat_tpose(Mk, =, M, 3);
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
do {
adjoint_transpose(Mk, MadjTk);
det = vdot(Mk[0], MadjTk[0]);
if (det == 0.0) { do_rank2(Mk, MadjTk, Mk); break; }
MadjT_one = norm_one(MadjTk); MadjT_inf = norm_inf(MadjTk);
gamma = sqrt(sqrt((MadjT_one * MadjT_inf) / (M_one * M_inf)) / fabs(det));
g1 = gamma * 0.5;
g2 = 0.5 / (gamma * det);
mat_copy(Ek, =, Mk, 3);
mat_binop(Mk, =, g1 * Mk, +, g2 * MadjTk, 3);
mat_copy(Ek, -=, Mk, 3);
E_one = norm_one(Ek);
M_one = norm_one(Mk); M_inf = norm_inf(Mk);
} while (E_one > (M_one * TOL));
mat_tpose(Q, =, Mk, 3); mat_pad(Q);
mat_mult(Mk, M, S); mat_pad(S);
for (i = 0; i < 3; i++) for (j = i; j < 3; j++)
S[i][j] = S[j][i] = 0.5 * (S[i][j] + S[j][i]);
return (det);
}
/******* Spectral Decomposition *******/
/* Compute the spectral decomposition of symmetric positive semi-definite S.
* Returns rotation in U and scale factors in result, so that if K is a diagonal
* matrix of the scale factors, then S = U K (U transpose). Uses Jacobi method.
* See Gene H. Golub and Charles F. Van Loan. Matrix Computations. Hopkins 1983.
*/
HVect spect_decomp(HMatrix S, HMatrix U)
{
HVect kv;
double Diag[3], OffD[3]; /* OffD is off-diag (by omitted index) */
double g, h, fabsh, fabsOffDi, t, theta, c, s, tau, ta, OffDq, a, b;
static char nxt[] = { Y,Z,X };
int sweep, i, j;
mat_copy(U, =, mat_id, 4);
Diag[X] = S[X][X]; Diag[Y] = S[Y][Y]; Diag[Z] = S[Z][Z];
OffD[X] = S[Y][Z]; OffD[Y] = S[Z][X]; OffD[Z] = S[X][Y];
for (sweep = 20; sweep > 0; sweep--) {
float sm = fabs(OffD[X]) + fabs(OffD[Y]) + fabs(OffD[Z]);
if (sm == 0.0) break;
for (i = Z; i >= X; i--) {
int p = nxt[i]; int q = nxt[p];
fabsOffDi = fabs(OffD[i]);
g = 100.0 * fabsOffDi;
if (fabsOffDi > 0.0) {
h = Diag[q] - Diag[p];
fabsh = fabs(h);
if (fabsh + g == fabsh) {
t = OffD[i] / h;
} else {
theta = 0.5 * h / OffD[i];
t = 1.0 / (fabs(theta) + sqrt(theta * theta + 1.0));
if (theta < 0.0) t = -t;
}
c = 1.0 / sqrt(t * t + 1.0); s = t * c;
tau = s / (c + 1.0);
ta = t * OffD[i]; OffD[i] = 0.0;
Diag[p] -= ta; Diag[q] += ta;
OffDq = OffD[q];
OffD[q] -= s * (OffD[p] + tau * OffD[q]);
OffD[p] += s * (OffDq - tau * OffD[p]);
for (j = Z; j >= X; j--) {
a = U[j][p]; b = U[j][q];
U[j][p] -= s * (b + tau * a);
U[j][q] += s * (a - tau * b);
}
}
}
}
kv.x = Diag[X]; kv.y = Diag[Y]; kv.z = Diag[Z]; kv.w = 1.0;
return (kv);
}
/******* Spectral Axis Adjustment *******/
/* Given a unit quaternion, q, and a scale vector, k, find a unit quaternion, p,
* which permutes the axes and turns freely in the plane of duplicate scale
* factors, such that q p has the largest possible w component, i.e. the
* smallest possible angle. Permutes k's components to go with q p instead of q.
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
* Proceedings of Graphics Interface 1992. Details on p. 262-263.
*/
Quat snuggle(Quat q, HVect* k)
{
#define SQRTHALF (0.7071067811865475244f)
#define sgn(n,v) ((n)?-(v):(v))
#define swap(a,i,j) {a[3]=a[i]; a[i]=a[j]; a[j]=a[3];}
#define cycle(a,p) if (p) {a[3]=a[0]; a[0]=a[1]; a[1]=a[2]; a[2]=a[3];}\
else {a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; a[0]=a[3];}
Quat p;
float ka[4];
int i, turn = -1;
ka[X] = k->x; ka[Y] = k->y; ka[Z] = k->z;
if (ka[X] == ka[Y]) { if (ka[X] == ka[Z]) turn = W; else turn = Z; }
else { if (ka[X] == ka[Z]) turn = Y; else if (ka[Y] == ka[Z]) turn = X; }
if (turn >= 0) {
Quat qtoz, qp;
unsigned neg[3], win;
double mag[3], t;
static Quat qxtoz = { 0,SQRTHALF,0,SQRTHALF };
static Quat qytoz = { SQRTHALF,0,0,SQRTHALF };
static Quat qppmm = { 0.5, 0.5,-0.5,-0.5 };
static Quat qpppp = { 0.5, 0.5, 0.5, 0.5 };
static Quat qmpmm = { -0.5, 0.5,-0.5,-0.5 };
static Quat qpppm = { 0.5, 0.5, 0.5,-0.5 };
static Quat q0001 = { 0.0, 0.0, 0.0, 1.0 };
static Quat q1000 = { 1.0, 0.0, 0.0, 0.0 };
switch (turn) {
default: return (Qt_Conj(q));
case X: q = Qt_Mul(q, qtoz = qxtoz); swap(ka, X, Z) break;
case Y: q = Qt_Mul(q, qtoz = qytoz); swap(ka, Y, Z) break;
case Z: qtoz = q0001; break;
}
q = Qt_Conj(q);
mag[0] = (double)q.z * q.z + (double)q.w * q.w - 0.5;
mag[1] = (double)q.x * q.z - (double)q.y * q.w;
mag[2] = (double)q.y * q.z + (double)q.x * q.w;
for (i = 0; i < 3; i++) if (neg[i] = (mag[i] < 0.0)) mag[i] = -mag[i];
if (mag[0] > mag[1]) { if (mag[0] > mag[2]) win = 0; else win = 2; }
else { if (mag[1] > mag[2]) win = 1; else win = 2; }
switch (win) {
case 0: if (neg[0]) p = q1000; else p = q0001; break;
case 1: if (neg[1]) p = qppmm; else p = qpppp; cycle(ka, 0) break;
case 2: if (neg[2]) p = qmpmm; else p = qpppm; cycle(ka, 1) break;
}
qp = Qt_Mul(q, p);
t = sqrt(mag[win] + 0.5);
p = Qt_Mul(p, Qt_(0.0, 0.0, -qp.z / t, qp.w / t));
p = Qt_Mul(qtoz, Qt_Conj(p));
} else {
float qa[4], pa[4];
unsigned lo, hi, neg[4], par = 0;
double all, big, two;
qa[0] = q.x; qa[1] = q.y; qa[2] = q.z; qa[3] = q.w;
for (i = 0; i < 4; i++) {
pa[i] = 0.0;
if (neg[i] = (qa[i] < 0.0)) qa[i] = -qa[i];
par ^= neg[i];
}
/* Find two largest components, indices in hi and lo */
if (qa[0] > qa[1]) lo = 0; else lo = 1;
if (qa[2] > qa[3]) hi = 2; else hi = 3;
if (qa[lo] > qa[hi]) {
if (qa[lo ^ 1] > qa[hi]) { hi = lo; lo ^= 1; }
else { hi ^= lo; lo ^= hi; hi ^= lo; }
} else {if (qa[hi^1]>qa[lo]) lo = hi^1;}
all = (qa[0] + qa[1] + qa[2] + qa[3]) * 0.5;
two = (qa[hi] + qa[lo]) * SQRTHALF;
big = qa[hi];
if (all > two) {
if (all > big) {/*all*/
{int i; for (i = 0; i < 4; i++) pa[i] = sgn(neg[i], 0.5); }
cycle(ka, par)
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
} else {
if (two > big) {/*two*/
pa[hi] = sgn(neg[hi], SQRTHALF); pa[lo] = sgn(neg[lo], SQRTHALF);
if (lo > hi) { hi ^= lo; lo ^= hi; hi ^= lo; }
if (hi == W) { hi = "\001\002\000"[lo]; lo = 3 - hi - lo; }
swap(ka, hi, lo)
} else {/*big*/ pa[hi] = sgn(neg[hi],1.0);}
}
p.x = -pa[0]; p.y = -pa[1]; p.z = -pa[2]; p.w = pa[3];
}
k->x = ka[X]; k->y = ka[Y]; k->z = ka[Z];
return (p);
}
/******* Decompose Affine Matrix *******/
/* Decompose 4x4 affine matrix A as TFRUK(U transpose), where t contains the
* translation components, q contains the rotation R, u contains U, k contains
* scale factors, and f contains the sign of the determinant.
* Assumes A transforms column vectors in right-handed coordinates.
* See Ken Shoemake and Tom Duff. Matrix Animation and Polar Decomposition.
* Proceedings of Graphics Interface 1992.
*/
void decomp_affine(HMatrix A, AffineParts* parts)
{
HMatrix Q, S, U;
Quat p;
float det;
parts->t = Qt_(A[X][W], A[Y][W], A[Z][W], 0);
det = polar_decomp(A, Q, S);
if (det < 0.0) {
mat_copy(Q, =, -Q, 3);
parts->f = -1;
} else parts->f = 1;
parts->q = Qt_FromMatrix(Q);
parts->k = spect_decomp(S, U);
parts->u = Qt_FromMatrix(U);
p = snuggle(parts->u, &parts->k);
parts->u = Qt_Mul(parts->u, p);
}
/******* Invert Affine Decomposition *******/
/* Compute inverse of affine decomposition.
*/
void invert_affine(AffineParts* parts, AffineParts* inverse)
{
Quat t, p;
inverse->f = parts->f;
inverse->q = Qt_Conj(parts->q);
inverse->u = Qt_Mul(parts->q, parts->u);
inverse->k.x = (parts->k.x == 0.0) ? 0.0 : 1.0 / parts->k.x;
inverse->k.y = (parts->k.y == 0.0) ? 0.0 : 1.0 / parts->k.y;
inverse->k.z = (parts->k.z == 0.0) ? 0.0 : 1.0 / parts->k.z;
inverse->k.w = parts->k.w;
t = Qt_(-parts->t.x, -parts->t.y, -parts->t.z, 0);
t = Qt_Mul(Qt_Conj(inverse->u), Qt_Mul(t, inverse->u));
t = Qt_(inverse->k.x * t.x, inverse->k.y * t.y, inverse->k.z * t.z, 0);
p = Qt_Mul(inverse->q, inverse->u);
t = Qt_Mul(p, Qt_Mul(t, Qt_Conj(p)));
inverse->t = (inverse->f > 0.0) ? t : Qt_(-t.x, -t.y, -t.z, 0);
}
}
-30
View File
@@ -1,30 +0,0 @@
// Modifications copyright Amazon.com, Inc. or its affiliates.
namespace decomp {
// Taken from http://tog.acm.org/GraphicsGems/gemsiv/polar_decomp/Decompose.h
/**** Decompose.h - Basic declarations ****/
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
#define CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
#pragma once
typedef struct {float x, y, z, w;} Quat; /* Quaternion */
enum QuatPart {X, Y, Z, W};
typedef Quat HVect; /* Homogeneous 3D vector */
typedef float HMatrix[4][4]; /* Right-handed, for column vectors */
typedef struct {
HVect t; /* Translation components */
Quat q; /* Essential rotation */
Quat u; /* Stretch rotation */
HVect k; /* Stretch factors */
float f; /* Sign of determinant */
} AffineParts;
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S);
HVect spect_decomp(HMatrix S, HMatrix U);
Quat snuggle(Quat q, HVect *k);
void decomp_affine(HMatrix A, AffineParts *parts);
void invert_affine(AffineParts *parts, AffineParts *inverse);
#endif // CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
}
-43
View File
@@ -1,43 +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_CRYCOMMONTOOLS_EXCEPTIONS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_EXCEPTIONS_H
#pragma once
#include <stdexcept>
#include <string>
class BaseException
: public std::exception
{
public:
BaseException(const string& msg)
: msg(msg) {}
virtual const char* what() const throw () {return msg.c_str(); }
private:
string msg;
};
template <typename Tag>
class Exception
: public BaseException
{
public:
Exception(const string& msg)
: BaseException(msg) {}
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_EXCEPTIONS_H
-175
View File
@@ -1,175 +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 <platform.h>
#include "FileUtil.h"
#include "PathHelpers.h"
#include "StringHelpers.h"
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/std/functional.h>
//////////////////////////////////////////////////////////////////////////
// returns true if 'dir' is a subdirectory of 'baseDir' or same directory as 'baseDir'
// note: returns false in case of wrong names passed
static bool IsSubdirOrSameDir(const char* dir, const char* baseDir)
{
AZ::IO::LocalFileIO localFileIO;
char szFullPathDir[AZ_MAX_PATH_LEN];
if(!localFileIO.ConvertToAbsolutePath(dir, szFullPathDir, sizeof(szFullPathDir)))
{
return false;
}
char szFullPathBaseDir[2 * 1024];
if(!localFileIO.ConvertToAbsolutePath(baseDir, szFullPathBaseDir, sizeof(szFullPathBaseDir)))
{
return false;
}
const char* p = szFullPathDir;
const char* q = szFullPathBaseDir;
for (;; ++p, ++q)
{
if (tolower(*p) == tolower(*q))
{
if (*p == 0)
{
// dir is exactly same as baseDir
return true;
}
continue;
}
if ((*p == '/' || *p == '\\') && (*q == '/' || *q == '\\'))
{
continue;
}
if (*p == 0)
{
// dir length is shorter than baseDir length. so it's not a subdir
return false;
}
if (*q == 0)
{
// baseDir is shorter than dir. so may be it's a subdir.
const bool isSubdir = (*p == '/' || *p == '\\');
return isSubdir;
}
return false;
}
}
//////////////////////////////////////////////////////////////////////////
// the paths must have trailing slash
static bool ScanDirectoryRecursive(const string& root, const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
{
bool anyFound = false;
if (!dirToIgnore.empty())
{
if (IsSubdirOrSameDir(root.c_str(), dirToIgnore.c_str()))
{
return anyFound;
}
}
AZ::IO::LocalFileIO localFileIO;
localFileIO.FindFiles(root.c_str(), file.c_str(), [&](const char* filePath) -> bool
{
bool isDir = localFileIO.IsDirectory(filePath);
if (!isDir)
{
const string foundFilename(filePath);
if (StringHelpers::MatchesWildcardsIgnoreCase(foundFilename, file))
{
anyFound = true;
files.push_back(PathHelpers::Join(path, PathHelpers::GetFilename(filePath)));
}
}
return true; // Keep iterating
});
if (recursive)
{
localFileIO.FindFiles(root.c_str(), "*", [&](const char* filePath) -> bool
{
bool isDir = localFileIO.IsDirectory(filePath);
// If recursive.
if (isDir && strcmp(filePath, ".") && strcmp(filePath, ".."))
{
if (ScanDirectoryRecursive(filePath, PathHelpers::Join(path, PathHelpers::GetFilename(filePath)), file, files, recursive, dirToIgnore))
{
anyFound = true;
}
}
return true; // Keep iterating
});
}
return anyFound;
}
//////////////////////////////////////////////////////////////////////////
bool FileUtil::ScanDirectory(const string& path, const string& file, std::vector<string>& files, bool recursive, const string& dirToIgnore)
{
return ScanDirectoryRecursive(path, "", file, files, recursive, dirToIgnore);
}
bool FileUtil::EnsureDirectoryExists(const char* szPathIn)
{
if (!szPathIn || !szPathIn[0])
{
return true;
}
if (DirectoryExists(szPathIn))
{
return true;
}
std::vector<char> path(szPathIn, szPathIn + strlen(szPathIn) + 1);
char* p = &path[0];
// Skip '/' and '//' in the beginning
while (*p == '/' || *p == '\\')
{
++p;
}
for (;; )
{
while (*p != '/' && *p != '\\' && *p)
{
++p;
}
const char saved = *p;
*p = 0;
AZ::IO::LocalFileIO().CreatePath(&path[0]);
*p++ = saved;
if (saved == 0)
{
break;
}
}
return DirectoryExists(szPathIn);
}
-311
View File
@@ -1,311 +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_CRYCOMMONTOOLS_FILEUTIL_H
#define CRYINCLUDE_CRYCOMMONTOOLS_FILEUTIL_H
#pragma once
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/PlatformIncl.h>
#if AZ_TRAIT_OS_PLATFORM_APPLE || defined(AZ_PLATFORM_LINUX)
#include <utime.h>
#endif
#if defined(AZ_PLATFORM_LINUX)
#include "Linux64Specific.h"
#endif // defined(AZ_PLATFORM_LINUX)
#include <platform.h>
#include <vector>
namespace FileUtil
{
// Magic number explanation:
// Both epochs are Gregorian. 1970 - 1601 = 369. Assuming a leap
// year every four years, 369 / 4 = 92. However, 1700, 1800, and 1900
// were NOT leap years, so 89 leap years, 280 non-leap years.
// 89 * 366 + 280 * 365 = 134744 days between epochs. Of course
// 60 * 60 * 24 = 86400 seconds per day, so 134744 * 86400 =
// 11644473600 = SECS_BETWEEN_EPOCHS.
//
// This result is also confirmed in the MSDN documentation on how
// to convert a time_t value to a win32 FILETIME.
#define SECS_BETWEEN_EPOCHS 11644473600ll
/* 10^7 */
#define SECS_TO_100NS 10000000ll
// Find all files matching filespec.
bool ScanDirectory(const string& path, const string& filespec, std::vector<string>& files, bool recursive, const string& dirToIgnore);
// Ensures that directory specified by szPathIn exists by creating all needed (sub-)directories.
// Returns false in case of a failure.
// Example: "c:\temp\test" ("c:\temp\test\" also works) - ensures that "c:\temp\test" exists.
bool EnsureDirectoryExists(const char* szPathIn);
// converts the FILETIME to the C Timestamp (compatible with dbghelp.dll)
inline DWORD FiletimeToUnixTime(const FILETIME& ft)
{
return (DWORD)((((int64&)ft) / SECS_TO_100NS) - SECS_BETWEEN_EPOCHS);
}
// converts the FILETIME to 64bit C timestamp
inline AZ::u64 FiletimeTo64BitUnixTime(const FILETIME& fileTime)
{
const AZ::u64 time = static_cast<AZ::u64>(fileTime.dwHighDateTime) << 32 | fileTime.dwLowDateTime;
return ((time / SECS_TO_100NS) - SECS_BETWEEN_EPOCHS);
}
// converts the C Timestamp (compatible with dbghelp.dll) to FILETIME
inline FILETIME UnixTimeToFiletime(DWORD nCTime)
{
const int64 time = (nCTime + SECS_BETWEEN_EPOCHS) * SECS_TO_100NS;
return (FILETIME&)time;
}
//converts the 64 bit C Timestamp to FILETIME
inline void UnixTime64BitToFiletime(AZ::u64 nCTime, FILETIME& fileTime)
{
const AZ::u64 time = (nCTime + SECS_BETWEEN_EPOCHS) * SECS_TO_100NS;
fileTime.dwLowDateTime = static_cast<DWORD>(time);
fileTime.dwHighDateTime = static_cast<DWORD>(time >> 32);
}
inline FILETIME GetInvalidFileTime()
{
FILETIME fileTime;
fileTime.dwLowDateTime = 0;
fileTime.dwHighDateTime = 0;
return fileTime;
}
// returns file time stamps
#if defined(AZ_PLATFORM_WINDOWS)
inline bool GetFileTimes(const char* filename, FILETIME* ftimeCreate = nullptr, FILETIME* ftimeAccess = nullptr, FILETIME* ftimeModify = nullptr)
{
WIN32_FIND_DATAA FindFileData;
const HANDLE hFind = FindFirstFileA(filename, &FindFileData);
if (hFind == INVALID_HANDLE_VALUE)
{
return false;
}
if (ftimeModify == nullptr && ftimeCreate == nullptr && ftimeAccess == nullptr)
{
FindClose(hFind);
return true;
}
FindClose(hFind);
if (ftimeCreate)
{
ftimeCreate->dwLowDateTime = FindFileData.ftCreationTime.dwLowDateTime;
ftimeCreate->dwHighDateTime = FindFileData.ftCreationTime.dwHighDateTime;
}
if (ftimeModify)
{
ftimeModify->dwLowDateTime = FindFileData.ftLastWriteTime.dwLowDateTime;
ftimeModify->dwHighDateTime = FindFileData.ftLastWriteTime.dwHighDateTime;
}
if (ftimeAccess)
{
ftimeAccess->dwLowDateTime = FindFileData.ftLastAccessTime.dwLowDateTime;
ftimeAccess->dwHighDateTime = FindFileData.ftCreationTime.dwHighDateTime;
}
return true;
}
#else
inline bool GetFileTimes(const char* filename, AZ::u64* timeCreate = nullptr, AZ::u64* timeAccess = nullptr, AZ::u64* timeModify = nullptr)
{
struct stat statResult;
if (stat(filename, &statResult) != 0)
{
return false;
}
if (timeCreate)
{
*timeCreate =static_cast<AZ::u64>(statResult.st_ctime);
}
if (timeModify)
{
*timeModify =static_cast<AZ::u64>(statResult.st_mtime);
}
if (timeAccess)
{
*timeAccess =static_cast<AZ::u64>(statResult.st_atime);
}
return true;
}
#endif
inline FILETIME GetLastWriteFileTime(const char* filename)
{
FILETIME timeModify = GetInvalidFileTime();
#if defined(AZ_PLATFORM_WINDOWS)
GetFileTimes(filename, nullptr, nullptr, &timeModify);
#else
AZ::u64 modTime = 0;
GetFileTimes(filename, nullptr, nullptr, &modTime);
if(modTime != 0)
{
UnixTime64BitToFiletime(modTime, timeModify);
}
#endif
return timeModify;
}
inline bool FileTimesAreEqual(const FILETIME& fileTime0, const FILETIME& fileTime1)
{
return
(fileTime0.dwLowDateTime == fileTime1.dwLowDateTime) &&
(fileTime0.dwHighDateTime == fileTime1.dwHighDateTime);
}
inline bool FileTimesAreEqual(const char* const srcfilename, const char* const targetfilename)
{
FILETIME ftSource = FileUtil::GetLastWriteFileTime(srcfilename);
FILETIME ftTarget = FileUtil::GetLastWriteFileTime(targetfilename);
return FileTimesAreEqual(ftSource, ftTarget);
}
inline bool FileTimeIsValid(const FILETIME& fileTime)
{
return !FileTimesAreEqual(GetInvalidFileTime(), fileTime);
}
inline bool SetFileTimes(const char* const filename, const FILETIME& creationFileTime, const FILETIME& accessFileTime, const FILETIME& modifcationFileTime)
{
#if defined(AZ_PLATFORM_WINDOWS)
const HANDLE hf = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hf != INVALID_HANDLE_VALUE)
{
if (SetFileTime(hf, &creationFileTime, &accessFileTime, &modifcationFileTime))
{
if (CloseHandle(hf))
{
return true;
}
}
CloseHandle(hf);
}
#else
AZ::u64 creationTime = FiletimeTo64BitUnixTime(creationFileTime);
AZ::u64 modificationTime = FiletimeTo64BitUnixTime(modifcationFileTime);
struct utimbuf puttime;
puttime.modtime = modificationTime;
puttime.actime = creationTime;
if (utime(filename, &puttime) == 0)
{
return true;
}
#endif
return false;
}
inline bool SetFileTimes(const char* const filename, const FILETIME& fileTime)
{
#if defined(AZ_PLATFORM_WINDOWS)
const HANDLE hf = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hf != INVALID_HANDLE_VALUE)
{
if (SetFileTime(hf, &fileTime, &fileTime, &fileTime))
{
if (CloseHandle(hf))
{
return true;
}
}
CloseHandle(hf);
}
#else
AZ::u64 newTime = FiletimeTo64BitUnixTime(fileTime);
struct utimbuf puttime;
puttime.modtime = newTime;
puttime.actime = newTime;
if (utime(filename, &puttime) == 0)
{
return true;
}
#endif
return false;
}
inline bool SetFileTimes(const char* const srcfilename, const char* const targetfilename)
{
#if defined(AZ_PLATFORM_WINDOWS)
FILETIME creationFileTime, accessFileTime, modifcationFileTime;
if (GetFileTimes(srcfilename, &creationFileTime, &accessFileTime, &modifcationFileTime))
{
const HANDLE hf = CreateFileA(targetfilename, FILE_WRITE_ATTRIBUTES, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
if (hf != INVALID_HANDLE_VALUE)
{
if (SetFileTime(hf, &creationFileTime, &accessFileTime, &modifcationFileTime))
{
if (CloseHandle(hf))
{
return true;
}
}
CloseHandle(hf);
}
}
#else
AZ::u64 creationFileTime, accessFileTime, modifcationFileTime;
if (GetFileTimes(srcfilename, &creationFileTime, &accessFileTime, &modifcationFileTime))
{
struct utimbuf puttime;
puttime.modtime = modifcationFileTime;
puttime.actime = accessFileTime;
if (utime(targetfilename, &puttime) == 0)
{
return true;
}
}
#endif
return false;
}
inline uint64 GetFileSize(const char* const filename)
{
AZ::u64 fileSize = AZ::IO::SystemFile::Length(filename);
return fileSize >= 0? fileSize : -1;
}
inline bool FileExists(const char* szPath)
{
return AZ::IO::LocalFileIO().Exists(szPath);
}
inline bool DirectoryExists(const char* szPath)
{
return AZ::IO::LocalFileIO().IsDirectory(szPath);
}
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_FILEUTIL_H
@@ -1,48 +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_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
#define CRYINCLUDE_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
#pragma once
class FileXmlBufferSource
: public IXmlBufferSource
{
public:
FileXmlBufferSource(const char* path)
{
file = std::fopen(path, "r");
}
~FileXmlBufferSource()
{
if (file)
{
std::fclose(file);
}
}
virtual int Read(void* buffer, int size) const
{
if (!file)
{
return 0;
}
return std::fread(buffer, 1, size, file);
}
private:
mutable std::FILE* file;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_FILEXMLBUFFERSOURCE_H
-53
View File
@@ -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_CRYCOMMONTOOLS_ILOGGER_H
#define CRYINCLUDE_CRYCOMMONTOOLS_ILOGGER_H
#pragma once
#include <stdarg.h>
#include <stdio.h>
class ILogger
{
public:
enum ESeverity
{
eSeverity_Debug,
eSeverity_Info,
eSeverity_Warning,
eSeverity_Error
};
virtual ~ILogger()
{
}
void Log(ESeverity eSeverity, const char* const format, ...)
{
char buffer[2048];
{
va_list args;
va_start(args, format);
_vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, format, args);
va_end(args);
}
LogImpl(eSeverity, buffer);
}
protected:
virtual void LogImpl(ESeverity eSeverity, const char* text) = 0;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ILOGGER_H
-49
View File
@@ -1,49 +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_CRYCOMMONTOOLS_IPAKSYSTEM_H
#define CRYINCLUDE_CRYCOMMONTOOLS_IPAKSYSTEM_H
#pragma once
#include <platform.h>
struct PakSystemFile;
struct PakSystemArchive;
struct IPakSystem
{
virtual PakSystemFile* Open(const char* filename, const char* mode) = 0;
virtual bool ExtractNoOverwrite(const char* filename, const char* extractToFile = 0) = 0;
virtual void Close(PakSystemFile* file) = 0;
virtual int GetLength(PakSystemFile* file) const = 0;
virtual int Read(PakSystemFile* file, void* buffer, int size) = 0;
virtual bool EoF(PakSystemFile* file) = 0;
virtual PakSystemArchive* OpenArchive(const char* path, size_t fileAlignment = 1, bool encrypted = false, const uint32 encryptionKey[4] = 0) = 0;
virtual void CloseArchive(PakSystemArchive* archive) = 0;
// Summary:
// Adds a new file to the pak or update an existing one.
// Adds a directory (creates several nested directories if needed)
// Arguments:
// path - relative path inside archive
// data, size - file content
// modTime - modification timestamp of the file
// compressionLevel - level of compression (correnponds to zlib-levels):
// -1 or [0-9] where -1=default compression, 0=no compression, 9=best compression
virtual void AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel = -1) = 0;
virtual bool DeleteFromArchive(PakSystemArchive* archive, const char* path) = 0;
virtual bool CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime) = 0;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_IPAKSYSTEM_H
-57
View File
@@ -1,57 +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_CRYCOMMONTOOLS_ISETTINGS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_ISETTINGS_H
#pragma once
class ISettings
{
public:
virtual bool GetSettingString(char* buffer, int bufferSizeInBytes, const char* key) = 0;
virtual bool GetSettingInt(int& value, const char* key) = 0;
};
inline bool GetSettingByRef(ISettings* settings, const string& key, string& value)
{
char buffer[1024];
bool success = false;
if (settings)
{
success = settings->GetSettingString(buffer, sizeof(buffer), key.c_str());
}
if (success)
{
value = buffer;
}
return success;
}
inline bool GetSettingByRef(ISettings* settings, const string& key, int& value)
{
return settings->GetSettingInt(value, key.c_str());
}
template <typename T>
inline T GetSetting(ISettings* settings, const string& key, const T& dflt)
{
T value;
if (!GetSettingByRef(settings, key, value))
{
value = dflt;
}
return value;
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_ISETTINGS_H
@@ -1,27 +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 <platform.h>
#include "LocaleChanger.h"
#include <locale.h>
LocaleChanger::LocaleChanger(int category, const char* newLocale)
{
m_category = category;
m_oldLocale = setlocale(category, newLocale);
}
LocaleChanger::~LocaleChanger()
{
setlocale(m_category, m_oldLocale.c_str());
}
-30
View File
@@ -1,30 +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_CRYCOMMONTOOLS_LOCALECHANGER_H
#define CRYINCLUDE_CRYCOMMONTOOLS_LOCALECHANGER_H
#pragma once
class LocaleChanger
{
public:
LocaleChanger(int category, const char* newLocale);
~LocaleChanger();
private:
int m_category;
string m_oldLocale;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_LOCALECHANGER_H
-79
View File
@@ -1,79 +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 <platform.h>
#include "LogFile.h"
LogFile::LogFile(const char* const filename)
: m_file(0)
, m_hasWarnings(false)
, m_hasErrors(false)
{
m_file = std::fopen(filename, "w");
}
LogFile::~LogFile()
{
if (m_file)
{
fclose(m_file);
}
}
bool LogFile::IsOpen() const
{
return m_file != 0;
}
bool LogFile::HasWarningsOrErrors() const
{
return m_hasWarnings || m_hasErrors;
}
void LogFile::LogImpl(ESeverity eSeverity, const char* const text)
{
const char* severityMessage = 0;
switch (eSeverity)
{
case eSeverity_Debug:
severityMessage = " ";
break;
case eSeverity_Info:
severityMessage = " ";
break;
case eSeverity_Warning:
severityMessage = "W: ";
break;
case eSeverity_Error:
severityMessage = "E: ";
break;
default:
severityMessage = "?: ";
break;
}
if (eSeverity == eSeverity_Warning)
{
m_hasWarnings = true;
}
if (eSeverity == eSeverity_Error)
{
m_hasErrors = true;
}
if (m_file)
{
fprintf(m_file, "%s%s\n", severityMessage, text);
fflush(m_file);
}
}
-40
View File
@@ -1,40 +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_CRYCOMMONTOOLS_LOGFILE_H
#define CRYINCLUDE_CRYCOMMONTOOLS_LOGFILE_H
#pragma once
#include "ILogger.h"
class LogFile
: public ILogger
{
public:
LogFile(const char* filename);
~LogFile();
bool IsOpen() const;
bool HasWarningsOrErrors() const;
// ILogger
virtual void LogImpl(ESeverity eSeverity, const char* message);
private:
std::FILE* m_file;
bool m_hasWarnings;
bool m_hasErrors;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_LOGFILE_H
-72
View File
@@ -1,72 +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_CRYCOMMONTOOLS_MATHHELPERS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_MATHHELPERS_H
#pragma once
#include <float.h>
#if (_M_IX86_FP > 0)
#include <intrin.h>
#endif
namespace MathHelpers
{
#if (_M_IX86_FP > 0)
inline int FastRoundFloatTowardZero(float f)
{
return _mm_cvtt_ss2si(_mm_set_ss(f));
}
#else
inline int FastRoundFloatTowardZero(float f)
{
return int(f);
}
#endif
#if defined(AZ_PLATFORM_WINDOWS)
inline unsigned int EnableFloatingPointExceptions(unsigned int mask)
{
_clearfp();
unsigned int oldMask;
_controlfp_s(&oldMask, 0, 0);
unsigned int newMask;
_controlfp_s(&newMask, ~mask, _MCW_EM);
return ~oldMask;
}
class AutoFloatingPointExceptions
{
public:
AutoFloatingPointExceptions(const unsigned int mask)
: m_mask(EnableFloatingPointExceptions(mask))
{
}
~AutoFloatingPointExceptions()
{
EnableFloatingPointExceptions(m_mask);
}
private:
unsigned int m_mask;
};
#endif //AZ_PLATFORM_WINDOWS
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_MATHHELPERS_H
@@ -1,44 +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 <platform.h>
#include "ModuleHelpers.h"
HMODULE ModuleHelpers::GetCurrentModule(CurrentModuleSpecifier moduleSpecifier)
{
switch (moduleSpecifier)
{
case CurrentModuleSpecifier_Executable:
return GetModuleHandle(0);
case CurrentModuleSpecifier_Library:
MEMORY_BASIC_INFORMATION mbi;
static int dummy;
VirtualQuery(&dummy, &mbi, sizeof(mbi));
HMODULE instance = reinterpret_cast<HMODULE>(mbi.AllocationBase);
return instance;
}
return 0;
}
std::basic_string<TCHAR> ModuleHelpers::GetCurrentModulePath(CurrentModuleSpecifier moduleSpecifier)
{
// Here's a trick that will get you the handle of the module
// you're running in without any a-priori knowledge:
// http://www.dotnet247.com/247reference/msgs/13/65259.aspx
HMODULE instance = GetCurrentModule(moduleSpecifier);
TCHAR moduleNameBuffer[MAX_PATH];
GetModuleFileName(instance, moduleNameBuffer, sizeof(moduleNameBuffer) / sizeof(moduleNameBuffer[0]));
return moduleNameBuffer;
}
-31
View File
@@ -1,31 +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_CRYCOMMONTOOLS_MODULEHELPERS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_MODULEHELPERS_H
#pragma once
namespace ModuleHelpers
{
enum CurrentModuleSpecifier
{
CurrentModuleSpecifier_Executable,
CurrentModuleSpecifier_Library
};
HMODULE GetCurrentModule(CurrentModuleSpecifier moduleSpecifier);
std::basic_string<TCHAR> GetCurrentModulePath(CurrentModuleSpecifier moduleSpecifier);
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_MODULEHELPERS_H
-380
View File
@@ -1,380 +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 <platform.h>
#include "PakSystem.h"
#include "PathHelpers.h"
#include "StringHelpers.h"
#include "ZipDir/ZipDir.h"
#include <zlib.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/std/functional.h>
PakSystemFile::PakSystemFile()
{
type = PakSystemFileType_Unknown;
file = NULL;
zip = NULL;
fileEntry = NULL;
data = NULL;
dataPosition = 0;
}
PakSystem::PakSystem()
{
}
PakSystemFile* PakSystem::Open(const char* a_path, const char* a_mode)
{
string normalPath = a_path;
string const zipExt = ".zip";
bool bZip = StringHelpers::EndsWithIgnoreCase(normalPath, zipExt);
if (bZip)
{
// If it's a .zip file, then we'll try to look for a file without .zip extension inside of the .zip file
normalPath.erase(normalPath.length() - zipExt.length(), zipExt.length());
}
string zipPath = normalPath + zipExt;
string filename = PathHelpers::GetFilename(normalPath);
if (!normalPath.empty() && normalPath[0] == '@')
{
// File is inside pak file.
int splitter = normalPath.find_first_of("|;,");
if (splitter >= 0)
{
zipPath = normalPath.substr(1, splitter - 1);
filename = StringHelpers::MakeLowerCase(normalPath.substr(splitter + 1));
bZip = true;
}
else
{
return 0;
}
}
if (!bZip)
{
// Try to open the file.
FILE* f = nullptr;
azfopen(&f, normalPath.c_str(), a_mode);
if (f)
{
std::unique_ptr<PakSystemFile> file(new PakSystemFile());
file->type = PakSystemFileType_File;
file->file = f;
return file.release();
}
}
// if it's simple and read-only, it's assumed it's read-only
unsigned const nFactoryFlags = ZipDir::CacheFactory::FLAGS_DONT_COMPACT | ZipDir::CacheFactory::FLAGS_READ_ONLY;
bool bFileExists = false;
const uint32* decryptionKey = 0; // use default one
if (bZip)
{
// a caller asked to open a .zip file. check if the .zip file on disk exist
FILE* f = nullptr;
azfopen(&f, zipPath.c_str(), "rb");
if (f)
{
fclose(f);
bFileExists = true;
}
}
else
{
// a caller specified normal file. we already failed to find it on disk,
// so the file could be within a .pak file. let's find all 'potential'
// pak files and look within these for a matching file
std::vector<string> foundFileCountainer; // pak files found
for (string dirToSearch = normalPath;; )
{
dirToSearch = PathHelpers::GetDirectory(dirToSearch);
AZ::IO::LocalFileIO localFileIO;
localFileIO.FindFiles(dirToSearch.c_str(), "*.pak", [&](const char* filePath) -> bool
{
const string foundFilename(filePath);
if (StringHelpers::EqualsIgnoreCase(PathHelpers::FindExtension(foundFilename), "pak"))
{
foundFileCountainer.push_back(foundFilename);
}
return true; // continue iterating
});
if (PathHelpers::GetFilename(dirToSearch).empty())
{
// We've reached the top of the path
break;
}
}
// iterate through found containers and look for relevant files within them
for (int iFile = 0; iFile < foundFileCountainer.size(); ++iFile)
{
zipPath = foundFileCountainer[ iFile ];
string pathToZip = PathHelpers::GetDirectory(zipPath);
// construct filename by removing path to zip from path to filename
string pathToFile = PathHelpers::GetDirectory(string(normalPath));
string pureFileName = PathHelpers::GetFilename(string(normalPath));
if (pathToFile.length() != pathToZip.length() && pathToZip.length() > 0)
{
pathToFile = pathToFile.substr(pathToZip.length() + 1);
}
filename = pathToFile.empty()
? pureFileName
: pathToFile + "\\" + pureFileName;
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
ZipDir::CachePtr testZip = factory.New(zipPath.c_str(), decryptionKey);
ZipDir::FileEntry* testFileEntry = (testZip ? testZip->FindFile(filename.c_str()) : 0);
// break out if we have a testFileEntry, as we've found our first (and best) candidate.
if (testFileEntry)
{
bFileExists = true;
break;
}
}
}
{
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
ZipDir::CachePtr zip = (bFileExists ? factory.New(zipPath.c_str(), decryptionKey) : 0);
ZipDir::FileEntry* fileEntry = (zip ? zip->FindFile(filename.c_str()) : 0);
if (fileEntry)
{
std::unique_ptr<PakSystemFile> file(new PakSystemFile());
file->type = PakSystemFileType_PakFile;
file->zip = zip;
file->fileEntry = fileEntry;
file->data = zip->AllocAndReadFile(file->fileEntry);
file->dataPosition = 0;
return file.release();
}
}
return 0;
}
//Extracts archived file to disk without overwriting any files
//returns true on success, false on failure (due to potential overwrite or no file
//in archive
bool PakSystem::ExtractNoOverwrite(const char* fileToExtract, const char* extractToFile)
{
if (0 == extractToFile)
{
extractToFile = fileToExtract;
}
//open file using pak system
PakSystemFile* fileZip = Open(fileToExtract, "r");
if (!fileZip)
{
return false;
}
// Try to open a writable file
FILE* fFileOnDisk = nullptr;
azfopen(&fFileOnDisk, extractToFile, "wb");
if (!fFileOnDisk)
{
Close(fileZip);
return false;
}
fwrite(fileZip->data, fileZip->fileEntry->desc.lSizeUncompressed, 1, fFileOnDisk);
fclose(fFileOnDisk);
Close(fileZip);
return true;
}
void PakSystem::Close(PakSystemFile* file)
{
if (file)
{
switch (file->type)
{
case PakSystemFileType_File:
fclose(file->file);
break;
case PakSystemFileType_PakFile:
file->zip->Free(file->data);
break;
}
delete file;
}
}
int PakSystem::GetLength(PakSystemFile* file) const
{
if (file)
{
switch (file->type)
{
case PakSystemFileType_File:
{
if (file->file)
{
long pos = ftell(file->file);
fseek(file->file, 0, SEEK_END);
int result = ftell(file->file);
fseek(file->file, pos, SEEK_SET);
return result;
}
break;
}
case PakSystemFileType_PakFile:
{
if (file->fileEntry)
{
return file->fileEntry->desc.lSizeUncompressed;
}
break;
}
default:
{
break;
}
}
}
return 0;
}
int PakSystem::Read(PakSystemFile* file, void* buffer, int size)
{
int readBytes = 0;
if (file)
{
switch (file->type)
{
case PakSystemFileType_File:
{
readBytes = fread(buffer, 1, size, file->file);
}
break;
case PakSystemFileType_PakFile:
{
int fileSize = file->fileEntry->desc.lSizeUncompressed;
readBytes = (fileSize - file->dataPosition > size ? size : fileSize - file->dataPosition);
memcpy(buffer, static_cast<char*>(file->data) + file->dataPosition, readBytes);
file->dataPosition += readBytes;
}
break;
}
}
return readBytes;
}
bool PakSystem::EoF(PakSystemFile* file)
{
bool EoF = true;
if (file)
{
switch (file->type)
{
case PakSystemFileType_File:
{
EoF = (0 != feof(file->file));
}
break;
case PakSystemFileType_PakFile:
{
int fileSize = file->fileEntry->desc.lSizeUncompressed;
EoF = (file->dataPosition >= fileSize);
}
break;
}
}
return EoF;
}
PakSystemArchive* PakSystem::OpenArchive(const char* path, size_t fileAlignment, bool encrypted, const uint32 encryptionKey[4])
{
//unsigned nFactoryFlags = ZipDir::CacheFactory::FLAGS_DONT_COMPACT | ZipDir::CacheFactory::FLAGS_CREATE_NEW;
unsigned nFactoryFlags = 0;
ZipDir::CacheFactory factory(ZipDir::ZD_INIT_FAST, nFactoryFlags);
ZipDir::CacheRWPtr cache = factory.NewRW(path, fileAlignment, encrypted, encryptionKey);
PakSystemArchive* archive = (cache ? new PakSystemArchive() : 0);
if (archive)
{
archive->zip = cache;
}
return archive;
}
void PakSystem::CloseArchive(PakSystemArchive* archive)
{
if (archive)
{
archive->zip->Close();
delete archive;
}
}
void PakSystem::AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel)
{
int compressionMethod = ZipFile::METHOD_DEFLATE;
if (compressionLevel == 0)
{
compressionMethod = ZipFile::METHOD_STORE;
}
archive->zip->UpdateFile(path, data, size, compressionMethod, compressionLevel, modTime);
}
//////////////////////////////////////////////////////////////////////////
bool PakSystem::CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime)
{
assert(archive);
ZipDir::FileEntry* pFileEntry = archive->zip->FindFile(path);
if (pFileEntry)
{
return pFileEntry->CompareFileTimeNTFS(modTime);
}
return false;
}
//////////////////////////////////////////////////////////////////////////
bool PakSystem::DeleteFromArchive(PakSystemArchive* archive, const char* path)
{
ZipDir::ErrorEnum err = archive->zip->RemoveFile(path);
return ZipDir::ZD_ERROR_SUCCESS == err;
}
-69
View File
@@ -1,69 +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_CRYCOMMONTOOLS_PAKSYSTEM_H
#define CRYINCLUDE_CRYCOMMONTOOLS_PAKSYSTEM_H
#pragma once
#include "IPakSystem.h"
#include "ZipDir/ZipDir.h" // TODO: get rid of thid include
enum PakSystemFileType
{
PakSystemFileType_Unknown,
PakSystemFileType_File,
PakSystemFileType_PakFile
};
struct PakSystemFile
{
PakSystemFile();
PakSystemFileType type;
// PakSystemFileType_File
FILE* file;
// PakSystemFileType_PakFile
ZipDir::CachePtr zip;
ZipDir::FileEntry* fileEntry;
void* data;
int dataPosition;
};
struct PakSystemArchive
{
ZipDir::CacheRWPtr zip;
};
class PakSystem
: public IPakSystem
{
public:
PakSystem();
// IPakSystem
virtual PakSystemFile* Open(const char* filename, const char* mode);
virtual bool ExtractNoOverwrite(const char* filename, const char* extractToFile = 0);
virtual void Close(PakSystemFile* file);
virtual int GetLength(PakSystemFile* file) const;
virtual int Read(PakSystemFile* file, void* buffer, int size);
virtual bool EoF(PakSystemFile* file);
virtual PakSystemArchive* OpenArchive(const char* path, size_t fileAlignment, bool encrypted, const uint32 encryptionKey[4]);
virtual void CloseArchive(PakSystemArchive* archive);
virtual void AddToArchive(PakSystemArchive* archive, const char* path, void* data, int size, int64 modTime, int compressionLevel);
virtual bool DeleteFromArchive(PakSystemArchive* archive, const char* path);
virtual bool CheckIfFileExist(PakSystemArchive* archive, const char* path, int64 modTime);
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PAKSYSTEM_H
@@ -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.
#ifndef CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
#define CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
#pragma once
#include "../CryXML/IXMLSerializer.h"
#include "IPakSystem.h"
class PakXmlFileBufferSource
: public IXmlBufferSource
{
public:
PakXmlFileBufferSource(IPakSystem* pakSystem, const char* path)
: pakSystem(pakSystem)
{
file = pakSystem->Open(path, "r");
}
~PakXmlFileBufferSource()
{
if (file)
{
pakSystem->Close(file);
}
}
virtual int Read(void* buffer, int size) const
{
return pakSystem->Read(file, buffer, size);
};
IPakSystem* pakSystem;
PakSystemFile* file;
};
class PakXmlBufferSource
: public IXmlBufferSource
{
public:
PakXmlBufferSource(const char* buffer, size_t length)
: position(buffer)
, end(buffer + length)
{
}
virtual int Read(void* output, int size) const
{
size_t bytesLeft = end - position;
size_t bytesToCopy = size < bytesLeft ? size : bytesLeft;
if (bytesToCopy > 0)
{
memcpy(output, position, bytesToCopy);
position += bytesToCopy;
}
return bytesToCopy;
};
mutable const char* position;
const char* end;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PAKXMLFILEBUFFERSOURCE_H
-621
View File
@@ -1,621 +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 <platform.h>
#include "PathHelpers.h"
#include "StringHelpers.h"
#include "Util.h"
#include <AzCore/std/string/conversions.h>
#include <AzFramework/IO/LocalFileIO.h>
#include <AzCore/IO/SystemFile.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzCore/PlatformIncl.h>
// Returns position of last extension in last name (string::npos if not found)
// note: returns string::npos for names starting from '.' and having no
// '.' later (for example 'aaa/.ccc', 'a:.abc', '.rc')
template <class TS>
static inline size_t findExtensionPosition_Tpl(const TS& path)
{
const size_t dotPos = path.rfind('.');
if (dotPos == TS::npos)
{
return TS::npos;
}
static const typename TS::value_type separators[] = { '\\', '/', ':', 0 };
const size_t separatorPos = path.find_last_of(separators);
if (separatorPos != TS::npos)
{
if (separatorPos + 1 >= dotPos)
{
return TS::npos;
}
}
else if (dotPos == 0)
{
return TS::npos;
}
return dotPos + 1;
}
static size_t findExtensionPosition(const string& path)
{
return findExtensionPosition_Tpl(path);
}
static size_t findExtensionPosition(const wstring& path)
{
return findExtensionPosition_Tpl(path);
}
string PathHelpers::FindExtension(const string& path)
{
const size_t extPos = findExtensionPosition(path);
return (extPos == string::npos) ? string() : path.substr(extPos, string::npos);
}
wstring PathHelpers::FindExtension(const wstring& path)
{
const size_t extPos = findExtensionPosition(path);
return (extPos == wstring::npos) ? wstring() : path.substr(extPos, wstring::npos);
}
template <class TS>
static inline TS ReplaceExtension_Tpl(const TS& path, const TS& newExtension)
{
if (path.empty())
{
return TS();
}
if (newExtension.empty())
{
return PathHelpers::RemoveExtension(path);
}
const typename TS::value_type last = path[path.length() - 1];
if ((last == '\\') || (last == '/') || (last == ':') || (last == '.'))
{
return path;
}
const size_t extPos = findExtensionPosition(path);
static const typename TS::value_type dot[] = { '.', 0 };
return ((extPos == TS::npos) ? path + dot : path.substr(0, extPos)) + newExtension;
}
string PathHelpers::ReplaceExtension(const string& path, const string& newExtension)
{
return ReplaceExtension_Tpl(path, newExtension);
}
wstring PathHelpers::ReplaceExtension(const wstring& path, const wstring& newExtension)
{
return ReplaceExtension_Tpl(path, newExtension);
}
string PathHelpers::RemoveExtension(const string& path)
{
const size_t extPos = findExtensionPosition(path);
return (extPos == string::npos) ? path : path.substr(0, extPos - 1);
}
wstring PathHelpers::RemoveExtension(const wstring& path)
{
const size_t extPos = findExtensionPosition(path);
return (extPos == wstring::npos) ? path : path.substr(0, extPos - 1);
}
template <class TS>
static inline TS GetDirectory_Tpl(const TS& path)
{
static const typename TS::value_type separators[] = { '/', '\\', ':', 0 };
const size_t pos = path.find_last_of(separators);
if (pos == TS::npos)
{
return TS();
}
if (path[pos] == ':' || pos == 0 || path[pos - 1] == ':')
{
return path.substr(0, pos + 1);
}
// Handle paths like "\\machine"
if (pos == 1 && (path[0] == '/' || path[0] == '\\'))
{
return path;
}
return path.substr(0, pos);
}
string PathHelpers::GetDirectory(const string& path)
{
return GetDirectory_Tpl(path);
}
wstring PathHelpers::GetDirectory(const wstring& path)
{
return GetDirectory_Tpl(path);
}
template <class TS>
static inline TS GetFilename_Tpl(const TS& path)
{
static const typename TS::value_type separators[] = { '/', '\\', ':', 0 };
const size_t pos = path.find_last_of(separators);
if (pos == TS::npos)
{
return path;
}
// Handle paths like "\\machine"
if (pos == 1 && (path[0] == '/' || path[0] == '\\'))
{
return TS();
}
return path.substr(pos + 1, TS::npos);
}
string PathHelpers::GetFilename(const string& path)
{
return GetFilename_Tpl(path);
}
wstring PathHelpers::GetFilename(const wstring& path)
{
return GetFilename_Tpl(path);
}
template <class TS>
static inline TS AddSeparator_Tpl(const TS& path)
{
if (path.empty())
{
return TS();
}
const typename TS::value_type last = path[path.length() - 1];
if (last == '/' || last == '\\' || last == ':')
{
return path;
}
#if defined(AZ_PLATFORM_WINDOWS)
static const typename TS::value_type separator[] = { '\\', 0 };
#else
static const typename TS::value_type separator[] = { '/', 0 };
#endif
return path + separator;
}
string PathHelpers::AddSeparator(const string& path)
{
return AddSeparator_Tpl(path);
}
wstring PathHelpers::AddSeparator(const wstring& path)
{
return AddSeparator_Tpl(path);
}
template <class TS>
static inline TS RemoveSeparator_Tpl(const TS& path)
{
if (path.empty())
{
return TS();
}
const typename TS::value_type last = path[path.length() - 1];
if ((last == '/' || last == '\\') && path.length() > 1 && path[path.length() - 2] != ':')
{
return path.substr(0, path.length() - 1);
}
return path;
}
string PathHelpers::RemoveSeparator(const string& path)
{
return RemoveSeparator_Tpl(path);
}
wstring PathHelpers::RemoveSeparator(const wstring& path)
{
return RemoveSeparator_Tpl(path);
}
template <class TS>
static inline TS RemoveDuplicateSeparators_Tpl(const TS& path)
{
if (path.length() <= 1)
{
return path;
}
TS ret;
ret.reserve(path.length());
const typename TS::value_type* p = path.c_str();
// We start from the second char just to avoid damaging UNC paths with double backslash at the beginning (e.g. "\\Server04\file.txt")
ret += *p++;
while (*p)
{
ret += *p++;
if (p[-1] == '\\' || p[-1] == '/')
{
while (*p == '\\' || *p == '/')
{
++p;
}
}
}
return ret;
}
string PathHelpers::RemoveDuplicateSeparators(const string& path)
{
return RemoveDuplicateSeparators_Tpl(path);
}
wstring PathHelpers::RemoveDuplicateSeparators(const wstring& path)
{
return RemoveDuplicateSeparators_Tpl(path);
}
template <class TS>
static inline TS Join_Tpl(const TS& path1, const TS& path2)
{
if (path1.empty())
{
return path2;
}
if (path2.empty())
{
return path1;
}
if (!PathHelpers::IsRelative(path2))
{
assert(0 && "Join(): path2 is not relative");
return TS();
}
const typename TS::value_type last = path1[path1.length() - 1];
if (last == '/' || last == '\\' || last == ':')
{
return path1 + path2;
}
#if defined(AZ_PLATFORM_WINDOWS)
static const typename TS::value_type separator[] = { '\\', 0 };
#else
static const typename TS::value_type separator[] = { '/', 0 };
#endif
return path1 + separator + path2;
}
string PathHelpers::Join(const string& path1, const string& path2)
{
return Join_Tpl(path1, path2);
}
wstring PathHelpers::Join(const wstring& path1, const wstring& path2)
{
return Join_Tpl(path1, path2);
}
template <class TS>
static inline bool IsRelative_Tpl(const TS& path)
{
if (path.empty())
{
return true;
}
return path[0] != '/' && path[0] != '\\' && path.find(':') == TS::npos;
}
bool PathHelpers::IsRelative(const string& path)
{
return IsRelative_Tpl(path);
}
bool PathHelpers::IsRelative(const wstring& path)
{
return IsRelative_Tpl(path);
}
string PathHelpers::ToUnixPath(const string& path)
{
return StringHelpers::Replace(path, '\\', '/');
}
wstring PathHelpers::ToUnixPath(const wstring& path)
{
wstring s(path);
std::replace(s.begin(), s.end(), L'\\', L'/');
return s;
}
string PathHelpers::ToDosPath(const string& path)
{
return StringHelpers::Replace(path, '/', '\\');
}
wstring PathHelpers::ToDosPath(const wstring& path)
{
wstring s(path);
std::replace(s.begin(), s.end(), L'/', L'\\');
return s;
}
string PathHelpers::ToPlatformPath(const string& path)
{
#if defined(AZ_PLATFORM_WINDOWS)
return ToDosPath(path);
#else
return ToUnixPath(path);
#endif
}
wstring PathHelpers::ToPlatformPath(const wstring& path)
{
#if defined(AZ_PLATFORM_WINDOWS)
return ToDosPath(path);
#else
return ToUnixPath(path);
#endif
}
string PathHelpers::GetAsciiPath(const char* pPath)
{
AZStd::wstring wstr;
AZStd::to_wstring(wstr, pPath);
return GetAsciiPath(wstr.c_str());
}
string PathHelpers::GetAsciiPath(const wchar_t* pPath)
{
if (!pPath[0])
{
return string();
}
wstring w = ToPlatformPath(RemoveSeparator(wstring(pPath)));
if (StringHelpers::Utf16ContainsAsciiOnly(w.c_str()))
{
return StringHelpers::ConvertAsciiUtf16ToAscii(w.c_str());
}
// The path is non-ASCII, so let's resort to using short
// filenames where needed (short names are always ASCII-only)
// Long names components
std::vector<wstring> p0;
StringHelpers::Split(w, wstring(L"\\"), true, p0);
// find last component that is not in ASCII char set
int lastNonAscii;
for (lastNonAscii = (int)p0.size() - 1; lastNonAscii >= 0; --lastNonAscii)
{
if (!StringHelpers::Utf16ContainsAsciiOnly(p0[lastNonAscii].c_str()))
{
break;
}
}
assert(lastNonAscii >= 0);
string res;
res.reserve(w.length());
w.clear();
for (int i = 0; i <= lastNonAscii; ++i)
{
w.append(p0[i]);
if (i < lastNonAscii)
{
w.push_back('\\');
}
}
enum
{
kBufferLen = AZ_MAX_PATH_LEN
};
wchar_t bufferWchars[kBufferLen];
#if defined(AZ_PLATFORM_WINDOWS)
const int charCount = GetShortPathNameW(w.c_str(), bufferWchars, kBufferLen);
#else
const int charCount = w.length();
wcsncpy(bufferWchars, w.c_str(), kBufferLen);
#endif
if (charCount <= 0 || charCount >= kBufferLen)
{
return string();
}
#if defined(AZ_PLATFORM_WINDOWS)
// Paranoid
if (!StringHelpers::Utf16ContainsAsciiOnly(bufferWchars))
{
assert(0);
return string();
}
#endif
// Short names components
std::vector<wstring> p1;
StringHelpers::Split(wstring(bufferWchars), wstring(L"\\"), true, p1);
for (size_t i = 0; i < (int)p0.size(); ++i)
{
if (!p0[i].empty())
{
const wstring& p =
(i > lastNonAscii || StringHelpers::Utf16ContainsAsciiOnly(p0[i].c_str()))
? p0[i]
: p1[i];
res.append(StringHelpers::ConvertAsciiUtf16ToAscii(p.c_str()));
}
if (i + 1 < (int)p0.size())
{
res.push_back('\\');
}
}
return res;
}
string PathHelpers::GetAbsoluteAsciiPath(const char* pPath)
{
char fullPath[AZ_MAX_PATH_LEN];
AZ::IO::LocalFileIO localFileIO;
AZStd::string normalizedPath(pPath);
AzFramework::StringFunc::Path::Normalize(normalizedPath);
localFileIO.ConvertToAbsolutePath(normalizedPath.c_str(), fullPath, AZ_MAX_PATH_LEN);
fullPath[sizeof(fullPath) - 1] = '\0';
AZStd::wstring wstr;
AZStd::to_wstring(wstr, fullPath);
return GetAsciiPath(wstr.c_str());
}
string PathHelpers::GetAbsoluteAsciiPath(const wchar_t* pPath)
{
AZStd::string str;
AZStd::to_string(str, pPath);
AzFramework::StringFunc::Path::Normalize(str);
char fullPath[AZ_MAX_PATH_LEN];
AZ::IO::LocalFileIO localFileIO;
localFileIO.ConvertToAbsolutePath(str.c_str(), fullPath, AZ_MAX_PATH_LEN);
fullPath[sizeof(fullPath) - 1] = '\0';
AZStd::wstring wstr;
AZStd::to_wstring(wstr, fullPath);
return GetAsciiPath(wstr.c_str());
}
string PathHelpers::GetShortestRelativeAsciiPath(const string& baseFolder, const string& dependentPath)
{
const string d = GetAbsoluteAsciiPath(dependentPath.c_str());
if (d.empty())
{
return PathHelpers::CanonicalizePath(dependentPath);
}
const string b = GetAbsoluteAsciiPath(baseFolder.c_str());
if (b.empty())
{
return PathHelpers::CanonicalizePath(dependentPath);
}
const string b2 = AddSeparator(b);
if (StringHelpers::StartsWithIgnoreCase(d, b2))
{
const size_t len = d.length() - b2.length();
// note: len == 0 is possible in case of "C:\" and "C:\".
return (len == 0) ? string(".") : d.substr(b2.length(), len);
}
std::vector<string> p0;
StringHelpers::Split(b2, string("\\"), true, p0);
std::vector<string> p1;
StringHelpers::Split(d, string("\\"), true, p1);
if (!StringHelpers::EqualsIgnoreCase(p0[0], p1[0]))
{
// got different drive letters
return PathHelpers::CanonicalizePath(dependentPath);
}
if (StringHelpers::EqualsIgnoreCase(d, b))
{
// exactly same path
return string(".");
}
// Search for first non-matching component
for (int i = 1; i < (int)p0.size(); ++i)
{
if (StringHelpers::EqualsIgnoreCase(p0[i], p1[i]))
{
continue;
}
string s;
s.reserve(Util::getMax(d.length(), b.length()));
for (int j = i; j < (int)p0.size(); ++j)
{
if (!p0[j].empty())
{
s.append("..\\");
}
}
for (int j = i; j < (int)p1.size(); ++j)
{
s.append(p1[j]);
if (j + 1 < (int)p1.size())
{
s.push_back('\\');
}
}
return s;
}
assert(0);
return string();
}
string PathHelpers::CanonicalizePath(const string& path)
{
string result = RemoveSeparator(path);
// remove .\ or ./ at the path beginning.
if (result.length() > 2)
{
if (result[0] == '.' && (result[1] == '\\' || result[1] == '/'))
{
result = result.substr(2);
}
}
return result;
}
-110
View File
@@ -1,110 +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_CRYCOMMONTOOLS_PATHHELPERS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_PATHHELPERS_H
#pragma once
#include <CryString.h>
namespace PathHelpers
{
// checks to see what the extension is in a string path
// returns the extension if found or an empty string if not found
string FindExtension(const string& path);
wstring FindExtension(const wstring& path);
// replace an extension of a string path with a new specified extension
// returns a string with the replaced extension or the original string if unable to replace the extension
string ReplaceExtension(const string& path, const string& newExtension);
wstring ReplaceExtension(const wstring& path, const wstring& newExtension);
// removes the extension of a specified string path
// returns a string with the extension removed or the original string if no extension was found
string RemoveExtension(const string& path);
wstring RemoveExtension(const wstring& path);
// "abc/def/ghi" -> "abc/def"
// "abc/def/ghi/" -> "abc/def/ghi"
// "/" -> "/"
// gets the directory path out of a specified string path
// returns a string of the directory path
string GetDirectory(const string& path);
wstring GetDirectory(const wstring& path);
// gets the file name out of a specified string path
// returns a string of the file name
string GetFilename(const string& path);
wstring GetFilename(const wstring& path);
// add a backslash to a specified path if it doesn't already have a separator
// returns a path with the appended backslash unless there was already a separator
string AddSeparator(const string& path);
wstring AddSeparator(const wstring& path);
// removes a forward slash or backslash from the end of a specified string path if found
// returns a string with the separator removed
string RemoveSeparator(const string& path);
wstring RemoveSeparator(const wstring& path);
// removes extra forward slashes and backslashes if they're contained within the string path
// returns a string with the extra forward slashes and backslashes removed
string RemoveDuplicateSeparators(const string& path);
wstring RemoveDuplicateSeparators(const wstring& path);
// It's not allowed to pass an absolute path in path2.
// Join(GetDirectory(fname), GetFilename(fname)) returns fname.
// merges two string paths together into one
// returns the merged string paths
string Join(const string& path1, const string& path2);
wstring Join(const wstring& path1, const wstring& path2);
// checks to see if the path is a relative path
// returns true if it is or false if it is not
bool IsRelative(const string& path);
bool IsRelative(const wstring& path);
// converts a string path to a unix path format
// returns the path in unix format
string ToUnixPath(const string& path);
wstring ToUnixPath(const wstring& path);
// converts a string path to a dos path format
// returns the path in dos format
string ToDosPath(const string& path);
wstring ToDosPath(const wstring& path);
// converts a string to the platform's path format.
// returns the path in the platform's path format.
string ToPlatformPath(const string& path);
wstring ToPlatformPath(const wstring& path);
// char* pPath: in ASCII or UTF-8 encoding
// wchar_t* pPath: in UTF-16 encoding
// Non-ASCII components of pPath (everything from &pPath[0] to last non-ASCII
// part, inclusively) should exist on disk, otherwise an empty string is returned.
string GetAsciiPath(const char* pPath);
string GetAsciiPath(const wchar_t* pPath);
// pPath passed should be in ASCII or UTF-8 encoding
string GetAbsoluteAsciiPath(const char* pPath);
// pPath passed should be in UTF-16 encoding
string GetAbsoluteAsciiPath(const wchar_t* pPath);
// baseFolder and dependentPath passed should be in ASCII or UTF-8 encoding
string GetShortestRelativeAsciiPath(const string& baseFolder, const string& dependentPath);
string CanonicalizePath(const string& path);
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PATHHELPERS_H
@@ -1,15 +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
#define AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(file, offset, s) fseek(file, offset, s)
#define AZ_TRAIT_CRYCOMMONTOOLS_FTELL(file) ftell(file)
@@ -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.
*
*/
#pragma once
#include <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 0
@@ -1,15 +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 <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
#include <ZipDir/ZipDir_Traits_Linux.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.
#
set(FILES
ZipDir/ZipDir_Traits_Platform.h
ZipDir/ZipDir_Traits_Linux.h
../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.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.
*
*/
#pragma once
#include <../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h>
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 1
@@ -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.
#
set(FILES
ZipDir/ZipDir_Traits_Platform.h
ZipDir/ZipDir_Traits_Mac.h
../Common/UnixLike/ZipDir/ZipDir_Traits_UnixLike.h
)
@@ -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.
*
*/
#pragma once
#include <ZipDir/ZipDir_Traits_Windows.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.
*
*/
#pragma once
#define AZ_TRAIT_CRYCOMMONTOOLS_FSEEK(file, offset, s) _fseeki64(file, (__int64)offset, s)
#define AZ_TRAIT_CRYCOMMONTOOLS_FTELL(file) (size_t)_ftelli64(file)
#define AZ_TRAIT_CRYCOMMONTOOLS_PACK_1 1
@@ -1,15 +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
ZipDir/ZipDir_Traits_Platform.h
ZipDir/ZipDir_Traits_Windows.h
)
-89
View File
@@ -1,89 +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_CRYCOMMONTOOLS_PROGRESSRANGE_H
#define CRYINCLUDE_CRYCOMMONTOOLS_PROGRESSRANGE_H
#pragma once
class ProgressRange
{
public:
template <typename T>
ProgressRange(T* object, void (T::* setter)(float progress))
: m_target(new MethodTarget<T>(object, setter))
, m_progress(0.0f)
, m_start(0.0f)
, m_scale(1.0f)
{
m_target->Set(m_start);
}
ProgressRange(ProgressRange& parent, float scale)
: m_target(new ParentRangeTarget(parent))
, m_progress(0.0f)
, m_start(parent.m_progress)
, m_scale(scale)
{
m_target->Set(m_start);
}
~ProgressRange()
{
m_target->Set(m_start + m_scale);
delete m_target;
}
void SetProgress(float progress)
{
assert(progress > -0.01f && progress < 1.1f);
m_progress = progress;
m_target->Set(m_start + m_scale * progress);
}
private:
struct ITarget
{
virtual ~ITarget() {}
virtual void Set(float progress) = 0;
};
struct ParentRangeTarget
: public ITarget
{
ParentRangeTarget(ProgressRange& range)
: range(range) {}
virtual void Set(float progress) {range.SetProgress(progress); }
ProgressRange& range;
};
template <typename T>
struct MethodTarget
: public ITarget
{
typedef void (T::* Setter)(float progress);
MethodTarget(T* object, Setter setter)
: object(object)
, setter(setter) {}
virtual void Set(float progress) {(object->*setter)(progress); }
T* object;
Setter setter;
};
ITarget* m_target;
float m_progress;
float m_start;
float m_scale;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PROGRESSRANGE_H
@@ -1,125 +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 <platform.h>
#include "PropertyHelpers.h"
#include "StringHelpers.h"
bool PropertyHelpers::GetPropertyValue(const string& a_propertiesString, const char* a_propertyName, string& a_value)
{
if ((a_propertyName == 0) || (a_propertyName[0] == 0))
{
return false;
}
const char* lineStart = a_propertiesString.c_str();
while (*lineStart)
{
string key;
string value;
const size_t lineEndPosition = strcspn(lineStart, "\n");
const size_t equalPosition = strcspn(lineStart, "=");
if (equalPosition < lineEndPosition)
{
key = string(lineStart, equalPosition);
value = string(lineStart + equalPosition + 1, lineEndPosition - equalPosition - 1);
}
else
{
key = string(lineStart, lineEndPosition);
value = "";
}
key = StringHelpers::Trim(key);
if (_stricmp(key.c_str(), a_propertyName) == 0)
{
a_value = StringHelpers::Trim(value);
return true;
}
lineStart += lineEndPosition;
if (*lineStart)
{
++lineStart;
}
}
return false;
}
void PropertyHelpers::SetPropertyValue(string& a_propertiesString, const char* a_propertyName, const char* a_value)
{
if ((a_propertyName == 0) || (a_propertyName[0] == 0))
{
return;
}
const string newValue = StringHelpers::Trim(string(a_value));
const char* lineStart = a_propertiesString.c_str();
while (*lineStart)
{
const size_t lineEndPosition = strcspn(lineStart, "\n");
const size_t equalPosition = strcspn(lineStart, "=");
const string key = StringHelpers::Trim(string(lineStart, ((equalPosition < lineEndPosition) ? equalPosition : lineEndPosition)));
if (_stricmp(key.c_str(), a_propertyName) == 0)
{
const size_t prefixSz = lineStart - a_propertiesString.c_str();
const size_t expressionSz = lineEndPosition;
if (newValue.empty())
{
a_propertiesString = a_propertiesString.substr(0, prefixSz) + string(a_propertyName) + a_propertiesString.substr(prefixSz + expressionSz, string::npos);
}
else
{
a_propertiesString = a_propertiesString.substr(0, prefixSz) + string(a_propertyName) + string("=") + newValue + a_propertiesString.substr(prefixSz + expressionSz, string::npos);
}
return;
}
lineStart += lineEndPosition;
if (*lineStart)
{
++lineStart;
}
}
if (a_propertiesString.empty() || (a_propertiesString[a_propertiesString.size() - 1] != '\n'))
{
a_propertiesString += string("\r\n");
}
if (newValue.empty())
{
a_propertiesString += string(a_propertyName);
}
else
{
a_propertiesString += string(a_propertyName) + string("=") + newValue;
}
}
bool PropertyHelpers::HasProperty(const string& a_propertiesString, const char* a_propertyName)
{
string value;
return PropertyHelpers::GetPropertyValue(a_propertiesString, a_propertyName, value);
}
@@ -1,28 +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_CRYCOMMONTOOLS_PROPERTYHELPERS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_PROPERTYHELPERS_H
#pragma once
namespace PropertyHelpers
{
bool GetPropertyValue(const string& propertiesString, const char* propertyName, string& value);
void SetPropertyValue(string& a_propertiesString, const char* propertyName, const char* value);
bool HasProperty(const string& propertiesString, const char* propertyName);
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_PROPERTYHELPERS_H
-14
View File
@@ -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 <platform.h>
-54
View File
@@ -1,54 +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_CRYCOMMONTOOLS_STLHELPERS_H
#define CRYINCLUDE_CRYCOMMONTOOLS_STLHELPERS_H
#pragma once
#include <functional>
namespace STLHelpers
{
template <class Type>
inline const char* constchar_cast(const Type& type)
{
return type;
}
template <>
inline const char* constchar_cast(const std::string& type)
{
return type.c_str();
}
template <class Type>
struct less_strcmp
{
bool operator()(const Type& left, const Type& right) const
{
return strcmp(constchar_cast(left), constchar_cast(right)) < 0;
}
};
template <class Type>
struct less_stricmp
{
bool operator()(const Type& left, const Type& right) const
{
return _stricmp(constchar_cast(left), constchar_cast(right)) < 0;
}
};
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_STLHELPERS_H
-508
View File
@@ -1,508 +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_CRYCOMMONTOOLS_SIMPLEBITMAP_H
#define CRYINCLUDE_CRYCOMMONTOOLS_SIMPLEBITMAP_H
#include <assert.h>
#include <vector> // STL vector
#include "platform.h" // uint32
#include "Cry_Math.h" // uint32
#include "Util.h" // getMin()
enum EImageFilteringMode
{
eifm2DBorder = 0,
eifmCubemapFilter = 1,
};
namespace
{
enum ECubeFace
{
ecfPosX = 0,
ecfNegX = 1,
ecfPosY = 2,
ecfNegY = 3,
ecfPosZ = 4,
ecfNegZ = 5,
ecfUnknown = -1,
};
struct JumpEntry
{
ECubeFace face;
int rot;
};
static const JumpEntry XJmpTable[] =
{
{ecfNegZ, 0}, {ecfPosZ, 2}, // ecfPosXa
{ecfPosZ, 0}, {ecfNegZ, 2}, // ecfNegXa
{ecfPosX, 1}, {ecfNegX, 3}, // ecfPosYa
{ecfPosX, 3}, {ecfNegX, 1}, // ecfNegYa
{ecfPosX, 0}, {ecfNegX, 0}, // ecfPosZa
{ecfPosX, 2}, {ecfNegX, 2} // ecfNegZa
};
static const JumpEntry YJmpTable[] =
{
{ecfPosY, 3}, {ecfNegY, 1}, // ecfPosXa
{ecfPosY, 1}, {ecfNegY, 3}, // ecfNegXa
{ecfNegZ, 2}, {ecfPosZ, 0}, // ecfPosYa
{ecfPosZ, 0}, {ecfNegZ, 2}, // ecfNegYa
{ecfNegY, 0}, {ecfPosY, 2}, // ecfPosZa
{ecfNegY, 2}, {ecfPosY, 0} // ecfNegZa
};
}
//! memory block used as bitmap
//! if you might need mipmaps please consider using ImageObject instead
template <class RasterElement>
class CSimpleBitmap
{
public:
CSimpleBitmap()
: m_dwWidth(0)
, m_dwHeight(0)
{
}
~CSimpleBitmap()
{
}
// copy constructor
CSimpleBitmap(const CSimpleBitmap<RasterElement>& rhs)
: m_dwWidth(0)
, m_dwHeight(0)
{
*this = rhs; // call assignment operator
}
// assignment operator
CSimpleBitmap<RasterElement>& operator=(const CSimpleBitmap<RasterElement>& rhs)
{
if (&rhs != this)
{
m_data = rhs.m_data;
m_dwWidth = rhs.m_dwWidth;
m_dwHeight = rhs.m_dwHeight;
}
return *this;
}
//! free all the memory resources
void FreeData()
{
m_data = std::vector<RasterElement>();
m_dwWidth = 0;
m_dwHeight = 0;
}
//! /return true=success, false=failed because of low memory
bool SetSize(const uint32 indwWidth, const uint32 indwHeight)
{
if (m_dwWidth * m_dwHeight != indwWidth * indwHeight)
{
FreeData();
m_data.resize(indwWidth * indwHeight);
m_dwWidth = indwWidth;
m_dwHeight = indwHeight;
}
return true;
}
private:
ECubeFace JumpX(const ECubeFace srcFace, const bool isdXPos, int* rotCoords) const
{
int index = (int)srcFace * 2 + (isdXPos ? 0 : 1);
assert(index < sizeof(XJmpTable));
const JumpEntry& jmp = XJmpTable[index];
(*rotCoords) += jmp.rot;
return jmp.face;
}
ECubeFace JumpY(const ECubeFace srcFace, const bool isdYPos, int* rotCoords) const
{
int index = (int)srcFace * 2 + (isdYPos ? 0 : 1);
assert(index < sizeof(YJmpTable));
const JumpEntry& jmp = YJmpTable[index];
(*rotCoords) += jmp.rot;
return jmp.face;
}
// table that shows to which face we jump
ECubeFace JumpTable(const ECubeFace srcFace, int isdXPos, int isdYPos, int* rotCoords) const
{
if (isdXPos != 0) // recursive jump until dx==0
{
int newSwap = 0;
ECubeFace newFace = JumpX(srcFace, isdXPos > 0, &newSwap);
(*rotCoords) += newSwap;
isdXPos -= ((isdXPos > 0) ? 1 : -1);
RotateCoord(&isdXPos, &isdYPos, newSwap);
return JumpTable(newFace, isdXPos, isdYPos, rotCoords);
}
if (isdYPos != 0) // recursive jump until dy==0
{
int newSwap = 0;
ECubeFace newFace = JumpY(srcFace, isdYPos > 0, &newSwap);
(*rotCoords) += newSwap;
isdYPos -= ((isdYPos > 0) ? 1 : -1);
RotateCoord(&isdXPos, &isdYPos, newSwap);
return JumpTable(newFace, isdXPos, isdYPos, rotCoords);
}
assert(isdXPos == 0 && isdYPos == 0);
return srcFace;
}
void RotateCoord(int* x, int* y, int mode) const
{
if (mode != 0)
{
if (mode == 2) // 180 degrees
{
(*x) = -(*x);
(*y) = -(*y);
}
else
{
if (mode == 1) // 90 dergees
{
int tmp = (*y);
(*y) = (*x);
(*x) = -tmp;
}
else // 270 degrees
{
assert(mode == 3);
int tmp = (*y);
(*y) = -(*x);
(*x) = tmp;
}
}
}
}
public:
//! works only within the Bitmap for filter kernels
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
//! /param outValue
//! /return pointer to the raster element value if position was in the bitmap, NULL otherwise
const RasterElement* GetForFiltering_2D(const int inX, const int inY) const
{
return Get(inX, inY);
}
//! works only within the Bitmap for filter kernels
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
//! /param outValue
//! /return pointer to the raster element value if position was in the bitmap, NULL otherwise
const RasterElement* GetForFiltering_Cubemap(const int inX, const int inY, const int srcX, const int srcY) const
{
if (m_data.empty())
{
return false;
}
assert(m_dwWidth == m_dwHeight * 6);
assert(srcX >= 0 && srcX < m_dwWidth);
assert(srcY >= 0 && srcY < m_dwHeight);
const int sideSize = m_dwHeight;
ECubeFace srcFace = (ECubeFace)(srcX / sideSize);
if (inX >= 0 && inX < m_dwWidth && inY >= 0 && inY < m_dwHeight) // if we're inside the cubemap
{
ECubeFace destFace = (ECubeFace)(inX / sideSize);
if (destFace == srcFace) // we have the same face as src texel
{
return &m_data[inY * m_dwWidth + inX];
}
}
const int halfSideSize = Util::getMax(1, sideSize / 2);
// ternary logic
const int isdXPositive = int(floorf((float)inX / sideSize) - floorf((float)srcX / sideSize));
const int isdYPositive = int(floorf((float)inY / sideSize) - floorf((float)srcY / sideSize));
//if(isdXPositive==0&&isdYPositive<0&&srcFace==ecfPosY)
//{
// int tmp = 0;
//}
assert(isdXPositive != 0 || isdYPositive != 0);
int rotCoords = 0; // quadrants to rotate coords
ECubeFace destFace = JumpTable(srcFace, isdXPositive, isdYPositive, &rotCoords);
rotCoords = ((rotCoords % 4) + 4) % 4;
int destX = inX - srcFace * sideSize;
int destY = inY;
// rotate coords
destX -= halfSideSize; // center coords
destY -= halfSideSize;
RotateCoord(&destX, &destY, rotCoords);
destX += halfSideSize; // shift back
destY += halfSideSize;
destX = ((destX + sideSize) % sideSize + sideSize) % sideSize; // tile in the face
destY = ((destY + sideSize) % sideSize + sideSize) % sideSize;
destX = Util::getMin(destX, sideSize - 1);
destY = Util::getMin(destY, sideSize - 1);
destX += sideSize * destFace;
assert(destX < m_dwWidth);
assert((ECubeFace)(destX / sideSize) == destFace);
return &m_data[destY * m_dwWidth + destX];
}
const RasterElement* GetForFiltering(const Vec3& inDir) const
{
Vec3 vcAbsDir(fabsf(inDir.x), fabsf(inDir.y), fabsf(inDir.z));
ECubeFace face;
int rotQuadrant = 0;
Vec2 texCoord;
if (vcAbsDir.x > vcAbsDir.y && vcAbsDir.x > vcAbsDir.z)
{
if (inDir.x > 0)
{
rotQuadrant = 3;
face = ecfPosX;
}
else
{
rotQuadrant = 1;
face = ecfNegX;
}
texCoord = Vec2(inDir.y, inDir.z) / vcAbsDir.x;
}
else if (vcAbsDir.y > vcAbsDir.x && vcAbsDir.y > vcAbsDir.z)
{
if (inDir.y > 0)
{
rotQuadrant = 2;
face = ecfPosY;
}
else
{
rotQuadrant = 0;
face = ecfNegY;
}
texCoord = Vec2(inDir.x, inDir.z) / vcAbsDir.y;
}
else
{
assert(vcAbsDir.z >= vcAbsDir.x && vcAbsDir.z >= vcAbsDir.y);
if (inDir.z > 0)
{
rotQuadrant = 1;
face = ecfPosZ;
}
else
{
rotQuadrant = 3;
face = ecfNegZ;
}
texCoord = Vec2(inDir.x, inDir.y) / vcAbsDir.z;
}
texCoord = texCoord * .5f + Vec2(.5f, .5f);
assert(texCoord.x <= 1.f && texCoord.x >= 0);
assert(texCoord.y <= 1.f && texCoord.y >= 0);
Vec2i texelPos(texCoord.x * (m_dwHeight - 1), texCoord.y * (m_dwHeight - 1));
texelPos.x += face * m_dwHeight; // plus face
return &m_data[texelPos.y * m_dwWidth + texelPos.x];
}
//! works only within the Bitmap
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
//! /param outValue
//! /return pointer to raster element value if position was in the bitmap, NULL otherwise
const RasterElement* Get(const uint32 inX, const uint32 inY) const
{
if (m_data.empty())
{
return 0;
}
if (inX >= m_dwWidth || inY >= m_dwHeight)
{
return 0;
}
return &m_data[inY * m_dwWidth + inX];
}
//! bilinear, works only well within 0..1
bool GetFiltered(const float infX, const float infY, RasterElement& outValue) const
{
float fIX = floorf(infX), fIY = floorf(infY);
float fFX = infX - fIX, fFY = infY - fIY;
int iXa = (int)fIX, iYa = (int)fIY;
int iXb = iXa + 1, iYb = iYa + 1;
if (iXb == m_dwWidth)
{
iXb = 0;
}
if (iYb == m_dwHeight)
{
iYb = 0;
}
const RasterElement* p[4];
if ((p[0] = Get(iXa, iYa)) && (p[1] = Get(iXb, iYa)) && (p[2] = Get(iXa, iYb)) && (p[3] = Get(iXb, iYb)))
{
outValue =
(*p[0]) * ((1.0f - fFX) * (1.0f - fFY)) + // left top
(*p[1]) * ((fFX) * (1.0f - fFY)) + // right top
(*p[2]) * ((1.0f - fFX) * (fFY)) + // left bottom
(*p[3]) * ((fFX) * (fFY)); // right bottom
return true;
}
return false;
}
//! works only within the Bitmap
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
const RasterElement& GetRef(const uint32 inX, const uint32 inY) const
{
assert(!m_data.empty());
assert(inX < m_dwWidth && inY < m_dwHeight);
return m_data[inY * m_dwWidth + inX];
}
//! works only within the Bitmap
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
RasterElement& GetRef(const uint32 inX, const uint32 inY)
{
assert(!m_data.empty());
assert(inX < m_dwWidth && inY < m_dwHeight);
return m_data[inY * m_dwWidth + inX];
}
//! works even outside of the Bitmap (tiled)
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
RasterElement& GetTiledRef(const uint32 inX, const uint32 inY)
{
assert(!m_data.empty());
const uint32 x = inX % m_dwWidth;
const uint32 y = inY % m_dwHeight;
return m_data[y * m_dwWidth + x];
}
//! works only within the Bitmap
//! /param inX 0..m_dwWidth-1 or the method returns false
//! /param inY 0..m_dwHeight-1 or the method returns false
//! /param inValue
bool Set(const uint32 inX, const uint32 inY, const RasterElement& inValue)
{
if (m_data.empty())
{
assert(!m_data.empty());
return false;
}
if (inX >= m_dwWidth || inY >= m_dwHeight)
{
return false;
}
m_data[inY * m_dwWidth + inX] = inValue;
return true;
}
uint32 GetWidth() const
{
return m_dwWidth;
}
uint32 GetHeight() const
{
return m_dwHeight;
}
// Returns size of one line in bytes
size_t GetPitch() const
{
return m_dwWidth * sizeof(RasterElement);
}
uint32 GetBitmapSizeInBytes() const
{
return m_dwWidth * m_dwHeight * sizeof(RasterElement);
}
//! /return could be 0 if the pixel is outside the bitmap
const RasterElement* GetPointer(const uint32 inX = 0, const uint32 inY = 0) const
{
if (inX >= m_dwWidth || inY >= m_dwHeight)
{
return 0;
}
return &m_data[inY * m_dwWidth + inX];
}
//! /return could be 0 if the pixel is outside the bitmap
RasterElement* GetPointer(const uint32 inX = 0, const uint32 inY = 0)
{
if (inX >= m_dwWidth || inY >= m_dwHeight)
{
return 0;
}
return &m_data[inY * m_dwWidth + inX];
}
void Fill(const RasterElement& inValue)
{
const uint32 n = m_dwHeight * m_dwWidth;
for (uint32 i = 0; i < n; ++i)
{
m_data[i] = inValue;
}
}
bool IsValid() const
{
return !m_data.empty();
}
protected: // ------------------------------------------------------
std::vector<RasterElement> m_data; //!< [m_dwWidth * m_dwHeight]
uint32 m_dwWidth;
uint32 m_dwHeight;
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SIMPLEBITMAP_H
@@ -1,249 +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_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
#define CRYINCLUDE_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
#pragma once
#include <algorithm>
/////////////////////////////////////////////////////////////////////
// String pool implementation.
// Inspired by expat implementation.
/////////////////////////////////////////////////////////////////////
class CSimpleStringPool
{
public:
enum
{
STD_BLOCK_SIZE = 4096
};
struct BLOCK
{
BLOCK* next;
int size;
char s[1];
};
unsigned int m_blockSize;
BLOCK* m_blocks;
BLOCK* m_free_blocks;
const char* m_end;
char* m_ptr;
char* m_start;
int nUsedSpace;
int nUsedBlocks;
CSimpleStringPool()
{
m_blockSize = STD_BLOCK_SIZE;
m_blocks = 0;
m_start = 0;
m_ptr = 0;
m_end = 0;
nUsedSpace = 0;
nUsedBlocks = 0;
m_free_blocks = 0;
}
~CSimpleStringPool()
{
BLOCK* pBlock = m_blocks;
while (pBlock)
{
BLOCK* temp = pBlock->next;
//nFree++;
free(pBlock);
pBlock = temp;
}
pBlock = m_free_blocks;
while (pBlock)
{
BLOCK* temp = pBlock->next;
//nFree++;
free(pBlock);
pBlock = temp;
}
m_blocks = 0;
m_ptr = 0;
m_start = 0;
m_end = 0;
}
void SetBlockSize(unsigned int nBlockSize)
{
if (nBlockSize > 1024 * 1024)
{
nBlockSize = 1024 * 1024;
}
unsigned int size = 512;
while (size < nBlockSize)
{
size *= 2;
}
m_blockSize = size - offsetof(BLOCK, s);
}
void Clear()
{
if (m_free_blocks)
{
BLOCK* pLast = m_blocks;
while (pLast)
{
BLOCK* temp = pLast->next;
if (!temp)
{
break;
}
pLast = temp;
}
if (pLast)
{
pLast->next = m_free_blocks;
}
}
m_free_blocks = m_blocks;
m_blocks = 0;
m_start = 0;
m_ptr = 0;
m_end = 0;
nUsedSpace = 0;
}
char* Append(const char* ptr, int nStrLen)
{
char* ret = m_ptr;
if (m_ptr && nStrLen + 1 < (m_end - m_ptr))
{
memcpy(m_ptr, ptr, nStrLen);
m_ptr = m_ptr + nStrLen;
*m_ptr++ = 0; // add null termination.
}
else
{
int nNewBlockSize = (std::max)(nStrLen + 1, (int)m_blockSize);
AllocBlock(nNewBlockSize, nStrLen + 1);
memcpy(m_ptr, ptr, nStrLen);
m_ptr = m_ptr + nStrLen;
*m_ptr++ = 0; // add null termination.
ret = m_start;
}
nUsedSpace += nStrLen;
return ret;
}
char* ReplaceString(const char* str1, const char* str2)
{
int nStrLen1 = check_cast<int>(strlen(str1));
int nStrLen2 = check_cast<int>(strlen(str2));
// undo ptr1 add.
if (m_ptr != m_start)
{
m_ptr = m_ptr - nStrLen1 - 1;
}
assert(m_ptr == str1);
int nStrLen = nStrLen1 + nStrLen2;
char* ret = m_ptr;
if (m_ptr && nStrLen + 1 < (m_end - m_ptr))
{
memcpy(m_ptr, str1, nStrLen1);
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
m_ptr = m_ptr + nStrLen;
*m_ptr++ = 0; // add null termination.
}
else
{
int nNewBlockSize = (std::max)(nStrLen + 1, check_cast<int>(m_blockSize));
if (m_ptr == m_start)
{
ReallocBlock(nNewBlockSize * 2); // Reallocate current block.
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
}
else
{
AllocBlock(nNewBlockSize, nStrLen + 1);
memcpy(m_ptr, str1, nStrLen1);
memcpy(m_ptr + nStrLen1, str2, nStrLen2);
}
m_ptr = m_ptr + nStrLen;
*m_ptr++ = 0; // add null termination.
ret = m_start;
}
nUsedSpace += nStrLen;
return ret;
}
private:
void AllocBlock(int blockSize, int nMinBlockSize)
{
if (m_free_blocks)
{
BLOCK* pBlock = m_free_blocks;
BLOCK* pPrev = 0;
while (pBlock)
{
if (pBlock->size >= nMinBlockSize)
{
// Reuse free block
if (pPrev)
{
pPrev->next = pBlock->next;
}
else
{
m_free_blocks = pBlock->next;
}
pBlock->next = m_blocks;
m_blocks = pBlock;
m_ptr = pBlock->s;
m_start = pBlock->s;
m_end = pBlock->s + pBlock->size;
return;
}
pPrev = pBlock;
pBlock = pBlock->next;
}
}
size_t nMallocSize = offsetof(BLOCK, s) + blockSize * sizeof(char);
//nMallocs++;
BLOCK* pBlock = (BLOCK*)malloc(nMallocSize);
pBlock->size = blockSize;
pBlock->next = m_blocks;
m_blocks = pBlock;
m_ptr = pBlock->s;
m_start = pBlock->s;
m_end = pBlock->s + blockSize;
nUsedBlocks++;
}
void ReallocBlock(int blockSize)
{
BLOCK* pThisBlock = m_blocks;
BLOCK* pPrevBlock = m_blocks->next;
m_blocks = pPrevBlock;
size_t nMallocSize = offsetof(BLOCK, s) + blockSize * sizeof(char);
//nMallocs++;
BLOCK* pBlock = (BLOCK*)realloc(pThisBlock, nMallocSize);
pBlock->size = blockSize;
pBlock->next = m_blocks;
m_blocks = pBlock;
m_ptr = pBlock->s;
m_start = pBlock->s;
m_end = pBlock->s + blockSize;
}
};
#endif // CRYINCLUDE_CRYCOMMONTOOLS_SIMPLESTRINGPOOL_H
@@ -1,580 +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 <platform.h>
#include "StealingThreadPool.h"
#include "ThreadUtils.h"
#include <AzCore/std/bind/bind.h>
#include <AzCore/std/parallel/thread.h>
#include <Cry_Math.h>
namespace ThreadUtils {
class StealingWorker
{
public:
StealingWorker(StealingThreadPool* pool, int index, bool trace, AZStd::condition_variable& jobsCV)
: m_pool(pool)
, m_index(index)
, m_tracingEnabled(trace)
, m_lastStartTime(0)
, m_exitFlag(0)
, m_jobsCV(jobsCV)
{
}
static unsigned int __stdcall ThreadFunc(void* param)
{
StealingWorker* self = (StealingWorker*)(param);
self->Work();
return 0;
}
void Start(int startTime)
{
m_lastStartTime = startTime;
string threadName;
threadName.Format("StealingWorker %d", m_index);
AZStd::thread_desc threadDesc;
threadDesc.m_name = threadName.c_str();
m_thread = AZStd::thread(AZStd::bind(StealingWorker::ThreadFunc, (void*)this), &threadDesc);
}
bool GetJobLockless(Job& job)
{
if (m_jobs.empty())
{
return false;
}
job = m_jobs.front();
m_jobs.pop_front();
return true;
}
bool GetJob(Job& job)
{
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
return GetJobLockless(job);
}
void ExecuteJob(Job& job)
{
--m_pool->m_numJobsWaitingForExecution;
job.Run();
if (m_tracingEnabled)
{
int time = (int)GetTickCount();
JobTrace trace;
trace.m_job = job;
trace.m_duration = time - m_lastStartTime;
m_traces.push_back(trace);
m_lastStartTime = time;
}
--m_pool->m_numJobs;
m_pool->m_jobFinishedCV.notify_all();
}
bool TryToStealJob(Job& job)
{
while (true)
{
StealingWorker* victim = m_pool->FindBestVictim(m_index);
if (!victim)
{
return false;
}
if (StealJobs(job, victim))
{
return true;
}
}
}
void Work()
{
Job job;
while (true)
{
AZStd::mutex loadMutex;
AZStd::unique_lock<AZStd::mutex> loadLock(loadMutex, AZStd::defer_lock_t());
while (m_pool->m_numJobsWaitingForExecution == 0)
{
m_jobsCV.wait(loadLock);
if (m_exitFlag == 1)
{
return;
}
}
if (GetJob(job))
{
ExecuteJob(job);
}
else if (TryToStealJob(job))
{
ExecuteJob(job);
}
}
}
// Called from different worker thread
bool StealJobs(Job& job, StealingWorker* victim)
{
if (victim == this)
{
assert(0 && "Trying to steal own jobs");
return false;
}
bool order = m_index < victim->m_index;
AZStd::lock_guard<AZStd::mutex> lock1(order ? m_lockJobs : victim->m_lockJobs);
AZStd::lock_guard<AZStd::mutex> lock2(order ? victim->m_lockJobs : m_lockJobs);
if (victim->m_jobs.empty())
{
return false;
}
int numJobs = (int)victim->m_jobs.size();
size_t stealUntil = numJobs - numJobs / 2;
Jobs::iterator begin = victim->m_jobs.begin();
Jobs::iterator end = victim->m_jobs.begin() + stealUntil;
m_jobs.insert(m_jobs.end(), begin, end);
victim->m_jobs.erase(begin, end);
return GetJobLockless(job);
}
// Called from any thread
void Submit(const Job& job)
{
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
m_jobs.push_back(job);
m_jobs.back().m_debugInitialThread = m_index;
m_jobsCV.notify_one();
}
// Called from any thread
void Submit(const Jobs& jobs)
{
const size_t numJobs = jobs.size();
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
m_jobs.insert(m_jobs.begin(), jobs.begin(), jobs.end());
for (size_t i = 0; i < numJobs; ++i)
{
m_jobs[i].m_debugInitialThread = m_index;
}
m_jobsCV.notify_one();
}
long NumJobsPending() const
{
AZStd::lock_guard<AZStd::mutex> lock(m_lockJobs);
return m_jobs.size();
}
// Called from main thread
void SignalExit()
{
CryInterlockedCompareExchange(&m_exitFlag, 1, 0);
}
void GetTraces(JobTraces& traces)
{
if (m_tracingEnabled)
{
m_traces.swap(traces);
}
}
private:
StealingThreadPool* m_pool;
AZStd::thread m_thread;
int m_index;
bool m_tracingEnabled;
int m_lastStartTime;
JobTraces m_traces;
Jobs m_jobs;
mutable AZStd::mutex m_lockJobs;
AZStd::condition_variable& m_jobsCV;
LONG m_exitFlag;
friend class StealingThreadPool;
};
// ---------------------------------------------------------------------------
StealingThreadPool::StealingThreadPool(int numThreads, bool enableTracing)
: m_numThreads(numThreads)
, m_numJobs(0)
, m_numJobsWaitingForExecution(0)
, m_enableTracing(enableTracing)
{
m_workers.resize(numThreads);
for (int i = 0; i < numThreads; ++i)
{
m_workers[i] = new StealingWorker(this, i, m_enableTracing, m_jobsCV);
}
}
StealingThreadPool::~StealingThreadPool()
{
WaitAllJobs();
size_t numThreads = m_workers.size();
for (size_t i = 0; i < numThreads; ++i)
{
m_workers[i]->SignalExit();
}
m_jobsCV.notify_all();
m_threadTraces.resize(numThreads);
for (size_t i = 0; i < numThreads; ++i)
{
m_workers[i]->GetTraces(m_threadTraces[i]);
}
}
void StealingThreadPool::Start()
{
int startTime = (int)GetTickCount();
size_t numThreads = m_workers.size();
for (int i = 0; i < numThreads; ++i)
{
m_workers[i]->Start(startTime);
}
}
void StealingThreadPool::WaitAllJobs()
{
AZStd::mutex loadMutex;
AZStd::unique_lock<AZStd::mutex> loadLock(loadMutex, AZStd::defer_lock_t());
while (m_numJobs > 0)
{
m_jobsCV.wait(loadLock);
}
}
// Called from any thread
void StealingThreadPool::Submit(const Job& job)
{
++m_numJobs;
++m_numJobsWaitingForExecution;
if (StealingWorker* worker = FindWorstWorker())
{
worker->Submit(job);
}
}
// Called from any thread
void StealingThreadPool::Submit(const Jobs& jobs)
{
m_numJobs += jobs.size();
m_numJobsWaitingForExecution += jobs.size();
if (StealingWorker* worker = FindWorstWorker())
{
worker->Submit(jobs);
}
}
JobGroup* StealingThreadPool::CreateJobGroup(JobFunc func, void* data)
{
return new JobGroup(this, func, data);
}
StealingWorker* StealingThreadPool::FindBestVictim(int exceptFor) const
{
int maxJobs = 0;
StealingWorker* bestVictim = 0;
for (size_t i = 0; i < m_workers.size(); ++i)
{
if (i == exceptFor)
{
continue;
}
StealingWorker* worker = m_workers[i];
long numJobs = worker->NumJobsPending();
if (numJobs > maxJobs)
{
maxJobs = numJobs;
bestVictim = worker;
}
}
return bestVictim;
}
StealingWorker* StealingThreadPool::FindWorstWorker() const
{
if (m_workers.empty())
{
return 0;
}
int minJobs = INT_MAX;
StealingWorker* worstWorker = m_workers[0];
for (size_t i = 0; i < m_workers.size(); ++i)
{
StealingWorker* worker = m_workers[i];
long numJobs = worker->NumJobsPending();
if (numJobs < minJobs)
{
minJobs = numJobs;
worstWorker = worker;
}
}
return worstWorker;
}
static bool WriteString(FILE* f, const char* str)
{
return fwrite(str, strlen(str), 1, f) == 1;
}
static int Interpolate(int a, int b, float phase)
{
return int(float(a) + float(b - a) * phase);
}
static int InterpolateColor(int c1, int c2, float phase)
{
const int r1 = (c1 & 0x0000ff);
const int g1 = (c1 & 0x00ff00) >> 8;
const int b1 = (c1 & 0xff0000) >> 16;
const int r2 = (c2 & 0x0000ff);
const int g2 = (c2 & 0x00ff00) >> 8;
const int b2 = (c2 & 0xff0000) >> 16;
const int r = min(255, max(0, Interpolate(r1, r2, phase)));
const int g = min(255, max(0, Interpolate(g1, g2, phase)));
const int b = min(255, max(0, Interpolate(b1, b2, phase)));
return r + (g << 8) + (b << 16);
}
static const int g_animColors[] = {
0xff0000, 0x0000ff, 0x00ff00,
0xffff00, 0xff00ff, 0x00ffff,
0xff8080, 0x8080ff, 0x80ff80,
0xffff80, 0xff80ff, 0x80ffff
};
static int ColorizeJobTrace(const ThreadUtils::JobTrace& trace)
{
const int numColors = sizeof(g_animColors) / sizeof(g_animColors[0]);
const int initialThread = trace.m_job.m_debugInitialThread;
const int index = initialThread % numColors;
const float brightness = aznumeric_cast<float>(pow(0.5f, initialThread / numColors));
return InterpolateColor(0, InterpolateColor(g_animColors[index], 0xffffff, 0.5f), brightness);
}
bool StealingThreadPool::SaveTracesGraph(const char* filename)
{
if (!m_enableTracing)
{
return false;
}
const float screenWidth = 1240.0f;
float duration = 0;
for (size_t t = 0; t < m_threadTraces.size(); ++t)
{
float threadDuration = 0;
const JobTraces& traces = m_threadTraces[t];
for (int i = 0; i < traces.size(); ++i)
{
threadDuration += traces[i].m_duration;
}
duration = max(threadDuration, duration);
}
const float padding = 10.0f;
const float rowHeight = 60.0f;
const float xScale = fabsf(duration) > FLT_EPSILON ? (screenWidth - padding * 2.0f) / duration : 1.0f;
const float width = screenWidth;
const float height = (m_threadTraces.size() + 0.5f) * rowHeight;
FILE* f = nullptr;
azfopen(&f, filename, "wt");
if (!f)
{
return false;
}
char buf[4096];
azsnprintf(buf, sizeof(buf),
"<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n"
"<svg\n"
" xmlns:dc='http://purl.org/dc/elements/1.1/'\n"
" xmlns:cc='http://creativecommons.org/ns#'\n"
" xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'\n"
" xmlns:svg='http://www.w3.org/2000/svg'\n"
" xmlns='http://www.w3.org/2000/svg'\n"
" xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd'\n"
" xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape'\n"
" width='%f'\n"
" height='%f'\n"
" id='svg2'\n"
" version='1.1'\n"
" >\n",
width, height
);
if (!WriteString(f, buf))
{
return false;
}
for (size_t t = 0; t < m_threadTraces.size(); ++t)
{
float x = padding;
float y = rowHeight * 0.5f + rowHeight * t;
azsnprintf(buf, sizeof(buf),
" <text\n"
" xml:space='preserve'\n"
" style='font-size:40px;font-style:normal;font-weight:normal;line-height:125%%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans'\n"
" x='%f'\n"
" y='%f'\n"
" sodipodi:linespacing='125%%'><tspan sodipodi:role='line' x='%f' y='%f' style='font-size:12px;fill:#000000'>Thread %i</tspan></text>\n",
x, y, x, y, static_cast<int>(t + 1));
if (!WriteString(f, buf))
{
return false;
}
y += padding;
const ThreadUtils::JobTraces& traces = m_threadTraces[t];
for (int i = 0; i < traces.size(); ++i)
{
const float width2 = traces[i].m_duration * xScale;
const float height2 = rowHeight * 0.5f;
const int color = ColorizeJobTrace(traces[i]);
const int strokeColor = 0;
azsnprintf(buf, sizeof(buf),
" <rect\n"
" style='fill:#%06x;fill-rule:evenodd;stroke:#%06x;stroke-width:0.25px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1'\n"
" width='%f'\n"
" height='%f'\n"
" x='%f'\n"
" y='%f' />\n",
color, strokeColor, width2, height2, x, y);
if (!WriteString(f, buf))
{
return false;
}
x += width2;
}
y += rowHeight;
}
if (!WriteString(f, "\n</svg>\n"))
{
return false;
}
fclose(f);
return true;
}
// ---------------------------------------------------------------------------
void JobGroup::Process(JobGroup::GroupInfo* info)
{
info->m_job.Run();
long jobsLeft = --info->m_group->m_numJobsRunning;
assert(jobsLeft >= 0);
if (jobsLeft == 0)
{
info->m_group->m_finishJob.Run();
delete info->m_group;
}
}
JobGroup::JobGroup(StealingThreadPool* pool, JobFunc func, void* data)
: m_pool(pool)
, m_numJobsRunning(0)
, m_finishJob(func, data)
, m_submited(false)
{
}
void JobGroup::Submit()
{
if (m_submited)
{
assert(0);
return;
}
if (m_numJobsRunning == 0)
{
m_pool->Submit(m_finishJob);
return;
}
Jobs jobs;
jobs.resize(m_infos.size());
for (size_t i = 0; i < m_infos.size(); ++i)
{
jobs[i] = Job((JobFunc) & JobGroup::Process, &m_infos[i]);
}
m_pool->Submit(jobs);
}
void JobGroup::Add(JobFunc func, void* data)
{
if (m_submited)
{
assert(0);
return;
}
GroupInfo info;
info.m_job = Job(func, data);
info.m_group = this;
m_infos.push_back(info);
++m_numJobsRunning;
}
}
@@ -1,123 +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_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H
#define CRYINCLUDE_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H
#pragma once
#include "ThreadUtils.h"
#include <AzCore/std/parallel/condition_variable.h>
#include <AzCore/std/parallel/atomic.h>
#include <BaseTypes.h>
#include <AzCore/Casting/numeric_cast.h>
#if AZ_TRAIT_OS_PLATFORM_APPLE
#include "AppleSpecific.h"
#endif
namespace ThreadUtils {
class StealingWorker;
class JobGroup;
// Simple stealing thread pool
class StealingThreadPool
{
public:
explicit StealingThreadPool(int numThreads, bool enableTracing = false);
~StealingThreadPool();
void Start();
void WaitAllJobs();
const std::vector<JobTraces>& Traces() const{ return m_threadTraces; }
bool SaveTracesGraph(const char* filename);
// Submits single independent job
template<class T>
void Submit(void(* jobFunc)(T*), T* data)
{
Submit(Job((JobFunc)jobFunc, data));
}
// Create a group of jobs. A group of jobs can be followed by one "finishing" job.
// It is a way to express dependencies between jobs.
template<class T>
JobGroup* CreateJobGroup(void(* jobFunc)(T*), T* data)
{
return CreateJobGroup((JobFunc)jobFunc, (void*)data);
}
uint GetNumThreads() const { return aznumeric_cast<uint>(m_numThreads); }
private:
StealingWorker* FindBestVictim(int exceptFor) const;
StealingWorker* FindWorstWorker() const;
void Submit(const Job& job);
void Submit(const Jobs& jobs);
JobGroup* CreateJobGroup(JobFunc, void* data);
size_t m_numThreads;
typedef std::vector<class StealingWorker*> ThreadWorkers;
ThreadWorkers m_workers;
bool m_enableTracing;
std::vector<JobTraces> m_threadTraces;
AZStd::atomic_long m_numJobsWaitingForExecution;
AZStd::atomic_long m_numJobs;
AZStd::condition_variable m_jobsCV;
AZStd::condition_variable m_jobFinishedCV;
friend class JobGroup;
friend class StealingWorker;
};
// JobGroup represents a group of jobs that can be followed by one "finishing"
// job. This is a way to express dependencies between jobs.
class JobGroup
{
public:
template<class T>
void Add(void(* jobFunc)(T*), T* data)
{
Add((JobFunc)jobFunc, data);
}
// Submits group to thread pool
void Submit();
private:
struct GroupInfo
{
Job m_job;
JobGroup* m_group;
};
typedef std::vector<GroupInfo> GroupInfos;
JobGroup(StealingThreadPool* pool, JobFunc func, void* data);
static void Process(JobGroup::GroupInfo* job);
void Add(JobFunc func, void* data);
volatile LONG m_numJobsRunning;
StealingThreadPool* m_pool;
GroupInfos m_infos;
Job m_finishJob;
bool m_submited;
friend class StealingThreadPool;
};
}
#endif // CRYINCLUDE_CRYCOMMONTOOLS_STEALINGTHREADPOOL_H

Some files were not shown because too many files have changed in this diff Show More