Merge branch 'main' of https://github.com/aws-lumberyard-dev/o3de into ATOM/tonypeng/ATOM-15266-2
This commit is contained in:
@@ -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.
|
||||
@@ -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
|
||||
)
|
||||
-13
@@ -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
|
||||
|
||||
@@ -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>>>
|
||||
{
|
||||
};
|
||||
}
|
||||
@@ -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 +0,0 @@
|
||||
*.xml
|
||||
@@ -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)
|
||||
|
||||
+6
-2
@@ -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
|
||||
|
||||
-23
@@ -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)
|
||||
|
||||
+29
-9
@@ -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,
|
||||
|
||||
+80
-76
@@ -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();
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#Ignore these directories
|
||||
SDKs
|
||||
|
||||
#ignore these files
|
||||
*.user
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user