Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,143 @@
/*
* 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 "TextureAtlas_precompiled.h"
#include "TextureAtlasImpl.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/API/ApplicationAPI.h>
namespace TextureAtlasNamespace
{
const static char* s_CoordinatePairsName = "Coordinate Pairs";
TextureAtlasImpl::TextureAtlasImpl()
{
m_image = nullptr;
}
TextureAtlasImpl::~TextureAtlasImpl() {}
TextureAtlasImpl::TextureAtlasImpl(AtlasCoordinateSets handles)
{
for (int i = 0; i < handles.size(); ++i)
{
this->m_data[handles[i].first] = handles[i].second;
}
m_image = nullptr;
}
bool TextureAtlasImpl::TextureAtlasVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement)
{
if (rootElement.GetVersion() < 2)
{
AZStd::unordered_map<AZStd::string, AtlasCoordinates> oldData;
if (!rootElement.GetChildData(AZ_CRC(s_CoordinatePairsName), oldData))
{
AZ_Error("TextureAtlas", false, "Failed to find old %s unordered_map element on version %u", s_CoordinatePairsName, rootElement.GetVersion());
return false;
}
AZStd::unordered_map<AZStd::string, AtlasCoordinates, hash_case_insensitive, equal_to_case_insensitive> newData{ oldData.begin(), oldData.end() };
rootElement.RemoveElementByName(AZ_CRC(s_CoordinatePairsName));
rootElement.AddElementWithData(context, s_CoordinatePairsName, newData);
}
return true;
}
// Reflect The coordinates and the coordinate format
void TextureAtlasImpl::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->ClassDeprecate("SimpleAssetReference_TextureAtlasAsset", "{6F612FE6-A054-4E49-830C-0288F3C79A52}",
[](AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement)
{
AZStd::vector<AZ::SerializeContext::DataElementNode> childNodeElements;
for (int index = 0; index < rootElement.GetNumSubElements(); ++index)
{
childNodeElements.push_back(rootElement.GetSubElement(index));
}
// Convert the rootElement now, the existing child DataElmentNodes are now removed
rootElement.Convert<AzFramework::SimpleAssetReference<TextureAtlasAsset>>(context);
for (AZ::SerializeContext::DataElementNode& childNodeElement : childNodeElements)
{
rootElement.AddElement(AZStd::move(childNodeElement));
}
return true;
});
// Need to serialize the old AZStd::unordered_map<AZStd::string, AtlasCoordinates> type
serialize->RegisterGenericType<AZStd::unordered_map<AZStd::string, AtlasCoordinates>>();
serialize->Class<TextureAtlasImpl>()->Version(2, &TextureAtlasVersionConverter)
->Field(s_CoordinatePairsName, &TextureAtlasImpl::m_data)
->Field("Width", &TextureAtlasImpl::m_width)
->Field("Height", &TextureAtlasImpl::m_height);
AzFramework::SimpleAssetReference<TextureAtlasAsset>::Register(*serialize);
}
AtlasCoordinates::Reflect(context);
}
// Coordinates reflect their internal properties
void AtlasCoordinates::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<AtlasCoordinates>()
->Version(1)
->Field("Left", &AtlasCoordinates::m_left)
->Field("Top", &AtlasCoordinates::m_top)
->Field("Width", &AtlasCoordinates::m_width)
->Field("Height", &AtlasCoordinates::m_height);
}
}
// Retrieves the value that corresponds to a given handle in the atlas
AtlasCoordinates TextureAtlasImpl::GetAtlasCoordinates(const AZStd::string& handle) const
{
AZStd::string path = handle;
path = path.substr(0, path.find_last_of('.'));
// Use an iterator to check if the key is being used in the hash table
auto iterator = m_data.find(path);
if (iterator != m_data.end())
{
return iterator->second;
}
else
{
return AtlasCoordinates(-1, -1, -1, -1);
}
}
// Links this atlas to an image pointer
void TextureAtlasImpl::SetTexture(ITexture* image)
{
// We don't need to delete the old value because the pointer is handled elsewhere
m_image = image;
}
// Returns the image linked to this atlas
ITexture* TextureAtlasImpl::GetTexture() const
{
return m_image;
}
// Internal to gem function for overwriting parameters
void TextureAtlasImpl::OverwriteMappings(TextureAtlasImpl* source)
{
m_data.clear();
m_data = source->m_data;
m_width = source->m_width;
m_height = source->m_height;
}
}
@@ -0,0 +1,88 @@
/*
* 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/Component/Component.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include "TextureAtlas/TextureAtlas.h"
#include "TextureAtlas/TextureAtlasBus.h"
#include <ITexture.h>
namespace TextureAtlasNamespace
{
struct equal_to_case_insensitive
{
AZ_TYPE_INFO(equal_to_case_insensitive, "{92DE03B1-B84F-4DEB-905D-CBE41DD6939D}");
bool operator()(const AZStd::string& left, const AZStd::string& right) const
{
return AzFramework::StringFunc::Equal(left.data(), right.data());
}
};
struct hash_case_insensitive : public AZStd::hash<AZStd::string>
{
AZ_TYPE_INFO(hash_case_insensitive, "{FE0F4349-D80D-4286-8874-733966A32B29}");
inline result_type operator()(const AZStd::string& value) const
{
AZStd::string lowerStr = value;
AZStd::to_lower(lowerStr.begin(), lowerStr.end());
return hash::operator()(lowerStr);
}
};
class TextureAtlasImpl: public TextureAtlas
{
public:
AZ_CLASS_ALLOCATOR(TextureAtlasImpl, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(TextureAtlasImpl, "{2CA51C61-1B5F-4480-A257-F28D8944AA35}");
TextureAtlasImpl();
TextureAtlasImpl(AtlasCoordinateSets handles);
~TextureAtlasImpl();
static bool TextureAtlasVersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& rootElement);
static void Reflect(AZ::ReflectContext* context);
//! Retrieve a coordinate set from the Atlas by its handle
AtlasCoordinates GetAtlasCoordinates(const AZStd::string& handle) const override;
//! Links this atlas to an image pointer
void SetTexture(ITexture* image) override;
//! Returns the image linked to this atlas
ITexture* GetTexture() const override;
//! Replaces the mappings of this Texture Atlas Object, with the source's mappings
void OverwriteMappings(TextureAtlasImpl* source);
//! Returns the width of the atlas
int GetWidth() const override { return m_width; }
//! Sets the width of the atlas
void SetWidth(int value) { m_width = value; }
//! Returns the height of the atlas
int GetHeight() const override { return m_height; }
//! Sets the height of the atlas
void SetHeight(int value) { m_height = value; }
private:
AZStd::unordered_map<AZStd::string, AtlasCoordinates, hash_case_insensitive, equal_to_case_insensitive> m_data;
ITexture* m_image;
int m_width;
int m_height;
};
} // namespace TextureAtlasNamespace
@@ -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 "TextureAtlas_precompiled.h"
#include <AzCore/Memory/SystemAllocator.h>
#include "TextureAtlasSystemComponent.h"
#include <IGem.h>
namespace TextureAtlasNamespace
{
class TextureAtlasModule
: public CryHooksModule
{
public:
AZ_RTTI(TextureAtlasModule, "{D3997F41-8117-4E0F-9BFE-937C4AE7E71F}", CryHooksModule);
AZ_CLASS_ALLOCATOR(TextureAtlasModule, AZ::SystemAllocator, 0);
TextureAtlasModule()
: CryHooksModule()
{
// Push results of [MyComponent]::CreateDescriptor() into m_descriptors here.
m_descriptors.insert(m_descriptors.end(), {
TextureAtlasSystemComponent::CreateDescriptor(),
});
}
/**
* Add required SystemComponents to the SystemEntity.
*/
AZ::ComponentTypeList GetRequiredSystemComponents() const override
{
return AZ::ComponentTypeList{
azrtti_typeid<TextureAtlasSystemComponent>(),
};
}
};
}
// DO NOT MODIFY THIS LINE UNLESS YOU RENAME THE GEM
// The first parameter should be GemName_GemIdLower
// The second should be the fully qualified name of the class above
AZ_DECLARE_MODULE_CLASS(Gem_TextureAtlas, TextureAtlasNamespace::TextureAtlasModule)
@@ -0,0 +1,268 @@
/*
* 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 "TextureAtlas_precompiled.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/IO/FileIO.h>
#include <AzFramework/API/ApplicationAPI.h>
#include "TextureAtlasSystemComponent.h"
#include "TextureAtlasImpl.h"
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <IRenderer.h>
namespace TextureAtlasNamespace
{
void TextureAtlasSystemComponent::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
serialize->Class<TextureAtlasSystemComponent, AZ::Component>()
->Version(0)
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AZ_CRC("AssetBuilder", 0xc739c7d7) }));
;
if (AZ::EditContext* ec = serialize->GetEditContext())
{
ec->Class<TextureAtlasSystemComponent>(
"TextureAtlas", "This component loads and manages TextureAtlases")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("System"))
->Attribute(AZ::Edit::Attributes::AutoExpand, true);
}
}
TextureAtlasImpl::Reflect(context);
}
void TextureAtlasSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
{
provided.push_back(AZ_CRC("TextureAtlasService"));
}
void
TextureAtlasSystemComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
{
incompatible.push_back(AZ_CRC("TextureAtlasService"));
}
void TextureAtlasSystemComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
{
(void)required;
}
void TextureAtlasSystemComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
{
(void)dependent;
}
void TextureAtlasSystemComponent::Init() { }
void TextureAtlasSystemComponent::Activate()
{
TextureAtlasRequestBus::Handler::BusConnect();
AzFramework::AssetCatalogEventBus::Handler::BusConnect();
}
void TextureAtlasSystemComponent::Deactivate()
{
TextureAtlasRequestBus::Handler::BusDisconnect();
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
}
void TextureAtlasSystemComponent::OnCatalogAssetChanged(const AZ::Data::AssetId& assetId)
{
for (auto iterator = m_atlases.begin(); iterator != m_atlases.end(); ++iterator)
{
if (iterator->second.m_atlasAssetId == assetId)
{
TextureAtlasImpl* input = AZ::Utils::LoadObjectFromFile<TextureAtlasImpl>(iterator->second.m_path);
reinterpret_cast<TextureAtlasImpl*>(iterator->second.m_atlas)->OverwriteMappings(input);
delete input;
// We reload the image here to prevent stuttering in the editor
if (iterator->second.m_atlas && iterator->second.m_atlas->GetTexture())
{
SResourceAsync* pInfo = new SResourceAsync();
pInfo->eClassName = eRCN_Texture;
pInfo->pResource = iterator->second.m_atlas->GetTexture();
gEnv->pRenderer->ReleaseResourceAsync(pInfo);
}
// Reload Texture
AZStd::string imagePath = iterator->second.m_path.substr(0, iterator->second.m_path.find_last_of('.'));
imagePath.append(".dds");
uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM);
ITexture* texture = gEnv->pRenderer->EF_LoadTexture(imagePath.c_str(), loadTextureFlags);
if (!texture || !texture->IsTextureLoaded())
{
gEnv->pSystem->Warning(VALIDATOR_MODULE_UNKNOWN,
VALIDATOR_WARNING,
VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE,
imagePath.c_str(),
"No texture file found for texture atlas: %s. "
"NOTE: File must be in current project or a gem.",
imagePath.c_str());
TextureAtlas* temp = iterator->second.m_atlas;
m_atlases.erase(iterator->first);
TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasUnloaded, temp);
return;
}
iterator->second.m_atlas->SetTexture(texture);
TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasReloaded, iterator->second.m_atlas);
break;
}
}
}
void TextureAtlasSystemComponent::SaveAtlasToFile(
const AZStd::string& outputPath,
AtlasCoordinateSets& handles,
int width,
int height)
{
TextureAtlasImpl atlas(handles);
atlas.SetWidth(width);
atlas.SetHeight(height);
AZ::Utils::SaveObjectToFile(outputPath, AZ::DataStream::StreamType::ST_XML, &(atlas));
}
// Attempts to load an atlas from file
TextureAtlas* TextureAtlasSystemComponent::LoadAtlas(const AZStd::string& filePath)
{
// Dont use an empty string as a path
if (filePath.empty())
{
return nullptr;
}
// Normalize the file path
AZStd::string path = filePath;
AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePath, path);
// Check if the atlas is already loaded
AZStd::string assetPath = path;
AzFramework::StringFunc::Path::ReplaceExtension(assetPath, "texatlasidx");
auto iterator = m_atlases.find(assetPath);
if (iterator != m_atlases.end())
{
iterator->second.m_refs++;
return iterator->second.m_atlas;
}
// If it isn't loaded, load it
// Open the file
AZ::IO::FileIOBase* input = AZ::IO::FileIOBase::GetInstance();
AZ::IO::HandleType handle;
input->Open(assetPath.c_str(), AZ::IO::OpenMode::ModeRead, handle);
// Read the file
AZ::u64 size;
input->Size(handle, size);
char* buffer = new char[size + 1];
input->Read(handle, buffer, size);
buffer[size] = 0;
// Close the file
input->Close(handle);
TextureAtlas* loadedAtlas = AZ::Utils::LoadObjectFromBuffer<TextureAtlasImpl>(buffer, size);
delete[] buffer;
if (loadedAtlas)
{
// Get the image path based on the atlas path
AZStd::string imagePath = path;
AzFramework::StringFunc::Path::ReplaceExtension(imagePath, "dds");
// Load the image in
uint32 loadTextureFlags = (FT_USAGE_ALLOWREADSRGB | FT_DONT_STREAM);
ITexture* texture = gEnv->pRenderer->EF_LoadTexture(imagePath.c_str(), loadTextureFlags);
if (!texture || !texture->IsTextureLoaded())
{
gEnv->pSystem->Warning(VALIDATOR_MODULE_UNKNOWN,
VALIDATOR_WARNING,
VALIDATOR_FLAG_FILE | VALIDATOR_FLAG_TEXTURE,
imagePath.c_str(),
"No texture file found for texture atlas: %s. "
"NOTE: File must be in current project or a gem.",
imagePath.c_str());
delete loadedAtlas;
return nullptr;
}
else
{
texture->SetFilter(FILTER_LINEAR);
// Add the atlas to the list
AtlasInfo info(loadedAtlas, assetPath);
++info.m_refs;
loadedAtlas->SetTexture(texture);
AZ::Data::AssetCatalogRequestBus::BroadcastResult(info.m_atlasAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath, assetPath.c_str(),
info.m_atlasAssetId.TYPEINFO_Uuid(), false);
m_atlases[assetPath] = info;
TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasLoaded, loadedAtlas);
}
}
return loadedAtlas;
}
// Lowers the ref count on an atlas. If the ref count it less than one, deletes the atlas
void TextureAtlasSystemComponent::UnloadAtlas(TextureAtlas* atlas)
{
// Check if the atlas is loaded
for (auto iterator = m_atlases.begin(); iterator != m_atlases.end(); ++iterator)
{
if (iterator->second.m_atlas == atlas)
{
--iterator->second.m_refs;
if (iterator->second.m_refs < 1 && iterator->second.m_atlas->GetTexture())
{
AtlasInfo temp = iterator->second;
m_atlases.erase(iterator->first);
TextureAtlasNotificationBus::Broadcast(&TextureAtlasNotifications::OnAtlasUnloaded, temp.m_atlas);
// Tell the renderer to release the texture.
if (temp.m_atlas && temp.m_atlas->GetTexture())
{
SResourceAsync* pInfo = new SResourceAsync();
pInfo->eClassName = eRCN_Texture;
pInfo->pResource = temp.m_atlas->GetTexture();
gEnv->pRenderer->ReleaseResourceAsync(pInfo);
}
// Delete the atlas
SAFE_DELETE(temp.m_atlas);
}
return;
}
}
}
// Searches for an atlas that contains an image
TextureAtlas* TextureAtlasSystemComponent::FindAtlasContainingImage(const AZStd::string& filePath)
{
// Check all atlases
for (auto iterator = m_atlases.begin(); iterator != m_atlases.end(); ++iterator)
{
if (iterator->second.m_atlas->GetAtlasCoordinates(filePath).GetWidth() > 0)
{
// If we we found the image return the pointer to the atlas
return iterator->second.m_atlas;
}
}
return nullptr;
}
}
@@ -0,0 +1,93 @@
/*
* 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/Component/Component.h>
#include <AzCore/IO/SystemFile.h>
#include "TextureAtlas/TextureAtlasBus.h"
#include "TextureAtlas/TextureAtlas.h"
#include "TextureAtlas/TextureAtlasNotificationBus.h"
#include <AzFramework/Asset/AssetCatalogBus.h>
namespace TextureAtlasNamespace
{
class TextureAtlasSystemComponent : public AZ::Component, protected TextureAtlasRequestBus::Handler, public AzFramework::AssetCatalogEventBus::Handler
{
public:
AZ_COMPONENT(TextureAtlasSystemComponent, "{436E8E5A-76CA-458D-8DAD-835C30D8C41B}");
static void Reflect(AZ::ReflectContext* context);
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
protected:
////////////////////////////////////////////////////////////////////////
// TextureAtlasRequestBus interface implementation
//! Saves a texture atlas to file
void SaveAtlasToFile(const AZStd::string& outputPath,
AtlasCoordinateSets& handles, int width, int height) override;
//! Tells the TextureAtlas system to load an Atlas and return a pointer for the atlas
TextureAtlas* LoadAtlas(const AZStd::string& filePath) override;
//! Returns a pointer to the first Atlas that contains the image, or nullptr if no atlas contains it
TextureAtlas* FindAtlasContainingImage(const AZStd::string& filePath) override;
//! Tells the TextureAtlas system to unload an Atlas
void UnloadAtlas(TextureAtlas* atlas) override;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// AZ::Component interface implementation
void Init() override;
void Activate() override;
void Deactivate() override;
////////////////////////////////////////////////////////////////////////
void OnCatalogAssetChanged(const AZ::Data::AssetId& assetId) override;
//! A struct that aids in the management of texture atlases
struct AtlasInfo
{
TextureAtlas* m_atlas;
AZStd::string m_path;
int m_refs;
AZ::Data::AssetId m_atlasAssetId;
//! A simple constructor that generates the AtlasInfo based on its parameters in a one to one fashion.
AtlasInfo(TextureAtlas* atlas, AZStd::string path)
{
m_atlas = atlas;
m_path = path;
m_refs = 0;
}
AtlasInfo()
{
m_atlas = nullptr;
m_path = "";
m_refs = 0;
}
};
private:
AZStd::unordered_map<AZStd::string, AtlasInfo> m_atlases;
};
}
@@ -0,0 +1,13 @@
/*
* 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 "TextureAtlas_precompiled.h"
@@ -0,0 +1,15 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <platform.h> // Many CryCommon files require that this is included first.