Merging latest origin
This commit is contained in:
@@ -197,6 +197,7 @@ namespace AZ
|
||||
AzFramework::InputDeviceKeyboard::Key::EditSpace, // ImGuiKey_Space
|
||||
AzFramework::InputDeviceKeyboard::Key::EditEnter, // ImGuiKey_Enter
|
||||
AzFramework::InputDeviceKeyboard::Key::Escape, // ImGuiKey_Escape
|
||||
AzFramework::InputDeviceKeyboard::Key::NumPadEnter, // ImGuiKey_KeyPadEnter
|
||||
AzFramework::InputDeviceKeyboard::Key::AlphanumericA, // ImGuiKey_A
|
||||
AzFramework::InputDeviceKeyboard::Key::AlphanumericC, // ImGuiKey_C
|
||||
AzFramework::InputDeviceKeyboard::Key::AlphanumericV, // ImGuiKey_V
|
||||
|
||||
@@ -118,6 +118,7 @@ namespace AZ
|
||||
|
||||
// set initial transform
|
||||
mesh.m_transform = m_transformServiceFeatureProcessor->GetTransformForId(objectId);
|
||||
mesh.m_nonUniformScale = m_transformServiceFeatureProcessor->GetNonUniformScaleForId(objectId);
|
||||
|
||||
m_revision++;
|
||||
m_subMeshCount += aznumeric_cast<uint32_t>(subMeshes.size());
|
||||
|
||||
@@ -34,6 +34,7 @@ namespace AZ
|
||||
constexpr uint32_t StreamCountMax = 12;
|
||||
constexpr uint32_t StreamChannelCountMax = 16;
|
||||
constexpr uint32_t DrawListTagCountMax = 64;
|
||||
constexpr uint32_t DrawFilterTagCountMax = 32;
|
||||
constexpr uint32_t MultiSampleCustomLocationsCountMax = 16;
|
||||
constexpr uint32_t MultiSampleCustomLocationGridSize = 16;
|
||||
constexpr uint32_t SubpassCountMax = 10;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 <Atom/RHI/DrawItem.h>
|
||||
#include <Atom/RHI/TagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
using DrawFilterTagRegistry = TagRegistry<DrawFilterTag, Limits::Pipeline::DrawFilterTagCountMax>;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI.Reflect/Handle.h>
|
||||
#include <Atom/RHI.Reflect/Limits.h>
|
||||
#include <Atom/RHI/StreamBufferView.h>
|
||||
#include <Atom/RHI/IndexBufferView.h>
|
||||
@@ -152,36 +153,53 @@ namespace AZ
|
||||
};
|
||||
|
||||
using DrawItemSortKey = int64_t;
|
||||
|
||||
struct DrawItemKeyPair
|
||||
|
||||
// A filter associate to a DrawItem which can be used to filter the DrawItem when submitting to command list
|
||||
using DrawFilterTag = Handle<uint8_t>;
|
||||
using DrawFilterMask = uint32_t; // AZStd::bitset's impelmentation is too expensive.
|
||||
constexpr uint32_t DrawFilterMaskDefaultValue = uint32_t(-1); // Default all bit to 1.
|
||||
static_assert(sizeof(DrawFilterMask) * 8 >= Limits::Pipeline::DrawFilterTagCountMax, "DrawFilterMask doesn't have enough bits for maximum tag count");
|
||||
|
||||
struct DrawItemProperties
|
||||
{
|
||||
DrawItemKeyPair() = default;
|
||||
DrawItemProperties() = default;
|
||||
|
||||
DrawItemKeyPair(const DrawItem* item, DrawItemSortKey sortKey)
|
||||
DrawItemProperties(const DrawItem* item, DrawItemSortKey sortKey = 0, DrawFilterMask filterMask = DrawFilterMaskDefaultValue)
|
||||
: m_item{item}
|
||||
, m_sortKey{sortKey}
|
||||
{}
|
||||
, m_drawFilterMask{filterMask}
|
||||
{
|
||||
}
|
||||
|
||||
bool operator == (const DrawItemKeyPair& rhs) const
|
||||
bool operator==(const DrawItemProperties& rhs) const
|
||||
{
|
||||
return m_item == rhs.m_item &&
|
||||
m_sortKey == rhs.m_sortKey &&
|
||||
m_depth == rhs.m_depth;
|
||||
m_depth == rhs.m_depth &&
|
||||
m_drawFilterMask == rhs.m_drawFilterMask
|
||||
;
|
||||
}
|
||||
|
||||
bool operator != (const DrawItemKeyPair& rhs) const
|
||||
bool operator!=(const DrawItemProperties& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool operator < (const DrawItemKeyPair& rhs) const
|
||||
bool operator<(const DrawItemProperties& rhs) const
|
||||
{
|
||||
return m_sortKey < rhs.m_sortKey;
|
||||
}
|
||||
|
||||
//! A pointer to the draw item
|
||||
const DrawItem* m_item = nullptr;
|
||||
//! A sorting key of this draw item which is used for sorting draw items in DrawList
|
||||
// Check RHI::SortDrawList() function for detail
|
||||
DrawItemSortKey m_sortKey = 0;
|
||||
//! A depth value this draw item which is used for sorting draw items in DrawList
|
||||
//! Check RHI::SortDrawList() function for detail
|
||||
float m_depth = 0.0f;
|
||||
//! A filter mask which helps decide whether to submit this draw item to a Scope's command list or not
|
||||
DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace AZ
|
||||
using DrawListTag = Handle<uint8_t>;
|
||||
using DrawListMask = AZStd::bitset<RHI::Limits::Pipeline::DrawListTagCountMax>;
|
||||
|
||||
using DrawList = AZStd::vector<RHI::DrawItemKeyPair>;
|
||||
using DrawListView = AZStd::array_view<RHI::DrawItemKeyPair>;
|
||||
using DrawList = AZStd::vector<RHI::DrawItemProperties>;
|
||||
using DrawListView = AZStd::array_view<RHI::DrawItemProperties>;
|
||||
|
||||
/// Contains a table of draw lists, indexed by the tag.
|
||||
using DrawListsByTag = AZStd::array<DrawList, RHI::Limits::Pipeline::DrawListTagCountMax>;
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace AZ
|
||||
|
||||
/// Adds an individual draw item to the draw list associated with the provided tag. This will
|
||||
/// no-op if the tag is not present in the internal draw list mask.
|
||||
void AddDrawItem(DrawListTag drawListTag, DrawItemKeyPair drawItemKeyPair);
|
||||
void AddDrawItem(DrawListTag drawListTag, DrawItemProperties drawItemProperties);
|
||||
|
||||
/// Coalesces the draw lists in preparation for access via GetList. This should
|
||||
/// be called from a single thread as a sync point between the append / consume phases.
|
||||
|
||||
@@ -12,83 +12,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Atom/RHI/DrawList.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
#include <Atom/RHI/TagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
/**
|
||||
* Allocates and registers draw list tags by name, allowing the user to acquire and find tags from names.
|
||||
* The class is designed to map user-friendly tag names defined through content or higher level code to
|
||||
* low-level tags, which are simple handles.
|
||||
*
|
||||
* Some notes about usage and design:
|
||||
* - DrawListTag values represent indexes into a bitmask, which allows for fast comparison when filtering
|
||||
* draw items into draw lists (see View::HasDrawListTag()).
|
||||
* - Tags are reference counted, which means multiple calls to 'Acquire' with the same name will increment
|
||||
* the internal reference count on the tag. This allows shared ownership between systems, if necessary.
|
||||
* - FindTag is provided to search for a tag reference without taking ownership.
|
||||
* - Names are case sensitive.
|
||||
*/
|
||||
class DrawListTagRegistry final
|
||||
: public AZStd::intrusive_base
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(DrawListTagRegistry, AZ::SystemAllocator, 0);
|
||||
AZ_DISABLE_COPY_MOVE(DrawListTagRegistry);
|
||||
|
||||
static Ptr<DrawListTagRegistry> Create();
|
||||
|
||||
/**
|
||||
* Resets the registry back to an empty state. All references are released.
|
||||
*/
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* Acquires a draw list tag from the provided name (case sensitive). If the tag already existed, it is ref-counted.
|
||||
* Returns a valid tag on success; returns a null tag if the registry is at full capacity. You must
|
||||
* call ReleaseTag() if successful.
|
||||
*/
|
||||
DrawListTag AcquireTag(const Name& drawListName);
|
||||
|
||||
/**
|
||||
* Releases a reference to a tag. Tags are ref-counted, so it's necessary to maintain ownership of the
|
||||
* tag and release when its no longer needed.
|
||||
*/
|
||||
void ReleaseTag(DrawListTag drawListTag);
|
||||
|
||||
/**
|
||||
* Finds the tag associated with the provided name (case sensitive). If a tag exists with that name, the tag
|
||||
* is returned. The reference count is NOT incremented on success; ownership is not passed to the user. If
|
||||
* the tag does not exist, a null tag is returned.
|
||||
*/
|
||||
DrawListTag FindTag(const Name& drawListName) const;
|
||||
|
||||
/**
|
||||
* Returns the name of the given DrawListTag, or empty string if the tag is not registered.
|
||||
*/
|
||||
Name GetName(DrawListTag tag) const;
|
||||
|
||||
/**
|
||||
* Returns the number of allocated tags in the registry.
|
||||
*/
|
||||
size_t GetAllocatedTagCount() const;
|
||||
|
||||
private:
|
||||
DrawListTagRegistry() = default;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Name m_name;
|
||||
size_t m_refCount = 0;
|
||||
};
|
||||
|
||||
mutable AZStd::shared_mutex m_mutex;
|
||||
AZStd::array<Entry, Limits::Pipeline::DrawListTagCountMax> m_entriesByTag;
|
||||
size_t m_allocatedTagCount = 0;
|
||||
};
|
||||
using DrawListTagRegistry = TagRegistry<DrawListTag, Limits::Pipeline::DrawListTagCountMax>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,45 +21,48 @@ namespace AZ
|
||||
|
||||
namespace RHI
|
||||
{
|
||||
/**
|
||||
* DrawPacket is a packed data structure (one contiguous allocation) containing a collection of
|
||||
* DrawItems and their associated array data. Each draw item in the packet is associated
|
||||
* with a DrawListTag. All draw items in the packet share the same set of shader resource
|
||||
* groups, index buffer, and draw arguments.
|
||||
*
|
||||
* Some notes about design and usage:
|
||||
* - Draw packets should be used to 'broadcast' variations of the same 'object' to multiple passes.
|
||||
* For example: 'Shadow', 'Depth', 'Forward'.
|
||||
*
|
||||
* - Draw packets can be re-used between different views, scenes, or passes. The embedded shader resource groups
|
||||
* should represent only the local data necessary to describe the 'object', not the full context including
|
||||
* scene / view / pass specific state. They serve as a 'template'.
|
||||
*
|
||||
* - The packet is self-contained and does not reference external memory. Use DrawPacketBuilder to construct
|
||||
* an instance and either store in an RHI::Ptr or call 'delete' to release.
|
||||
*/
|
||||
//!
|
||||
//! DrawPacket is a packed data structure (one contiguous allocation) containing a collection of
|
||||
//! DrawItems and their associated array data. Each draw item in the packet is associated
|
||||
//! with a DrawListTag. All draw items in the packet share the same set of shader resource
|
||||
//! groups, index buffer, one DrawFilterMask, and draw arguments.
|
||||
//!
|
||||
//! Some notes about design and usage:
|
||||
//! - Draw packets should be used to 'broadcast' variations of the same 'object' to multiple passes.
|
||||
//! For example: 'Shadow', 'Depth', 'Forward'.
|
||||
//!
|
||||
//! - Draw packets can be re-used between different views, scenes, or passes. The embedded shader resource groups
|
||||
//! should represent only the local data necessary to describe the 'object', not the full context including
|
||||
//! scene / view / pass specific state. They serve as a 'template'.
|
||||
//!
|
||||
//! - The packet is self-contained and does not reference external memory. Use DrawPacketBuilder to construct
|
||||
//! an instance and either store in an RHI::Ptr or call 'delete' to release.
|
||||
//!
|
||||
class DrawPacket final : public AZStd::intrusive_base
|
||||
{
|
||||
friend class DrawPacketBuilder;
|
||||
public:
|
||||
using DrawItemVisitor = AZStd::function<void(DrawListTag, DrawItemKeyPair)>;
|
||||
using DrawItemVisitor = AZStd::function<void(DrawListTag, DrawItemProperties)>;
|
||||
|
||||
/// Draw packets cannot be move constructed or copied, as they contain an additional memory payload.
|
||||
//! Draw packets cannot be move constructed or copied, as they contain an additional memory payload.
|
||||
AZ_DISABLE_COPY_MOVE(DrawPacket);
|
||||
|
||||
/// Returns the mask representing all the draw lists affected by the packet.
|
||||
//! Returns the mask representing all the draw lists affected by the packet.
|
||||
DrawListMask GetDrawListMask() const;
|
||||
|
||||
/// Returns the number of draw items stored in the packet.
|
||||
//! Returns the number of draw items stored in the packet.
|
||||
size_t GetDrawItemCount() const;
|
||||
|
||||
/// Returns the draw item / sort key associated with the provided index.
|
||||
DrawItemKeyPair GetDrawItem(size_t index) const;
|
||||
//! Returns the draw item and its properties associated with the provided index.
|
||||
DrawItemProperties GetDrawItem(size_t index) const;
|
||||
|
||||
/// Returns the draw list tag associated with the provided index.
|
||||
//! Returns the draw list tag associated with the provided index.
|
||||
DrawListTag GetDrawListTag(size_t index) const;
|
||||
|
||||
/// Overloaded operator delete for freeing a draw packet.
|
||||
//! Returns the draw filter mask which applied to all the draw items.
|
||||
DrawFilterMask GetDrawFilterMask() const;
|
||||
|
||||
//! Overloaded operator delete for freeing a draw packet.
|
||||
void operator delete(void* p, size_t size);
|
||||
|
||||
private:
|
||||
@@ -72,6 +75,9 @@ namespace AZ
|
||||
// The bit-mask of all active filter tags.
|
||||
DrawListMask m_drawListMask = 0;
|
||||
|
||||
// The draw filter applies to each draw item
|
||||
DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue;
|
||||
|
||||
// The index buffer view used when the draw call is indexed.
|
||||
IndexBufferView m_indexBufferView;
|
||||
|
||||
|
||||
@@ -29,23 +29,26 @@ namespace AZ
|
||||
{
|
||||
DrawRequest() = default;
|
||||
|
||||
/// The filter tag used to direct the draw item.
|
||||
//! The filter tag used to direct the draw item.
|
||||
DrawListTag m_listTag;
|
||||
|
||||
/// The stencil ref value used for this draw item.
|
||||
//! The stencil ref value used for this draw item.
|
||||
uint8_t m_stencilRef = 0;
|
||||
|
||||
/// The array of stream buffers to bind for this draw item.
|
||||
//! The array of stream buffers to bind for this draw item.
|
||||
AZStd::array_view<StreamBufferView> m_streamBufferViews;
|
||||
|
||||
/// Shader resource group unique for this draw request
|
||||
//! Shader resource group unique for this draw request
|
||||
const ShaderResourceGroup* m_uniqueShaderResourceGroup = nullptr;
|
||||
|
||||
/// The pipeline state assigned to this draw item.
|
||||
//! The pipeline state assigned to this draw item.
|
||||
const PipelineState* m_pipelineState = nullptr;
|
||||
|
||||
/// The sort key assigned to this draw item.
|
||||
//! The sort key assigned to this draw item.
|
||||
DrawItemSortKey m_sortKey = 0;
|
||||
|
||||
//! The filter associated to this draw item.
|
||||
DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue;
|
||||
};
|
||||
|
||||
// NOTE: This is configurable; just used to control the amount of memory held by the builder.
|
||||
@@ -69,6 +72,8 @@ namespace AZ
|
||||
|
||||
void AddShaderResourceGroup(const ShaderResourceGroup* shaderResourceGroup);
|
||||
|
||||
void SetDrawFilterMask(DrawFilterMask filterMask);
|
||||
|
||||
void AddDrawItem(const DrawRequest& request);
|
||||
|
||||
const DrawPacket* End();
|
||||
@@ -79,6 +84,7 @@ namespace AZ
|
||||
IAllocatorAllocate* m_allocator = nullptr;
|
||||
DrawArguments m_drawArguments;
|
||||
DrawListMask m_drawListMask = 0;
|
||||
DrawFilterMask m_drawFilterMask = DrawFilterMaskDefaultValue;
|
||||
size_t m_streamBufferViewCount = 0;
|
||||
IndexBufferView m_indexBufferView;
|
||||
AZStd::fixed_vector<DrawRequest, DrawItemCountMax> m_drawRequests;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
class Device;
|
||||
class DrawListTagRegistry;
|
||||
class FrameGraphBuilder;
|
||||
class PipelineState;
|
||||
class PipelineStateCache;
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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/Name/Name.h>
|
||||
#include <AzCore/std/smart_ptr/intrusive_base.h>
|
||||
#include <AzCore/std/parallel/shared_mutex.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
//!
|
||||
//! Allocates and registers tags by name, allowing the user to acquire and find tags from names.
|
||||
//! The class is designed to map user-friendly tag names defined through content or higher level code to
|
||||
//! low-level tags, which are simple handles.
|
||||
//!
|
||||
//! Some notes about usage and design:
|
||||
//! - TagType need to be a Handle<Integer> type.
|
||||
//! - Tags are reference counted, which means multiple calls to 'Acquire' with the same name will increment
|
||||
//! the internal reference count on the tag. This allows shared ownership between systems, if necessary.
|
||||
//! - FindTag is provided to search for a tag reference without taking ownership.
|
||||
//! - Names are case sensitive.
|
||||
//!
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
class TagRegistry final
|
||||
: public AZStd::intrusive_base
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(TagRegistry, AZ::SystemAllocator, 0);
|
||||
AZ_DISABLE_COPY_MOVE(TagRegistry);
|
||||
|
||||
static Ptr<TagRegistry> Create();
|
||||
|
||||
//! Resets the registry back to an empty state. All references are released.
|
||||
void Reset();
|
||||
|
||||
//! Acquires a tag from the provided name (case sensitive). If the tag already existed, it is ref-counted.
|
||||
//! Returns a valid tag on success; returns a null tag if the registry is at full capacity. You must
|
||||
//! call ReleaseTag() if successful.
|
||||
TagType AcquireTag(const Name& tagName);
|
||||
|
||||
//! Releases a reference to a tag. Tags are ref-counted, so it's necessary to maintain ownership of the
|
||||
//! tag and release when its no longer needed.
|
||||
void ReleaseTag(TagType tagName);
|
||||
|
||||
//! Finds the tag associated with the provided name (case sensitive). If a tag exists with that name, the tag
|
||||
//! is returned. The reference count is NOT incremented on success; ownership is not passed to the user. If
|
||||
//! the tag does not exist, a null tag is returned.
|
||||
TagType FindTag(const Name& tagName) const;
|
||||
|
||||
//! Returns the name of the given tag, or empty string if the tag is not registered.
|
||||
Name GetName(TagType tag) const;
|
||||
|
||||
//! Returns the number of allocated tags in the registry.
|
||||
size_t GetAllocatedTagCount() const;
|
||||
|
||||
private:
|
||||
TagRegistry() = default;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
Name m_name;
|
||||
size_t m_refCount = 0;
|
||||
};
|
||||
|
||||
mutable AZStd::shared_mutex m_mutex;
|
||||
AZStd::array<Entry, MaxTagCount> m_entriesByTag;
|
||||
size_t m_allocatedTagCount = 0;
|
||||
};
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
Ptr<TagRegistry<TagType, MaxTagCount>> TagRegistry<TagType, MaxTagCount>::Create()
|
||||
{
|
||||
return aznew TagRegistry<TagType, MaxTagCount>();
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
void TagRegistry<TagType, MaxTagCount>::Reset()
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
m_entriesByTag.fill({});
|
||||
m_allocatedTagCount = 0;
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
TagType TagRegistry<TagType, MaxTagCount>::AcquireTag(const Name& tagName)
|
||||
{
|
||||
if (tagName.IsEmpty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
TagType tag;
|
||||
Entry* foundEmptyEntry = nullptr;
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
for (size_t i = 0; i < m_entriesByTag.size(); ++i)
|
||||
{
|
||||
Entry& entry = m_entriesByTag[i];
|
||||
|
||||
// Found an empty entry. Cache off the tag and pointer, but keep searching to find if
|
||||
// another entry holds the same name.
|
||||
if (entry.m_refCount == 0 && !foundEmptyEntry)
|
||||
{
|
||||
foundEmptyEntry = &entry;
|
||||
tag = TagType(i);
|
||||
}
|
||||
else if (entry.m_name == tagName)
|
||||
{
|
||||
entry.m_refCount++;
|
||||
return TagType(i);
|
||||
}
|
||||
}
|
||||
|
||||
// No other entry holds the name, so allocate the empty entry.
|
||||
if (foundEmptyEntry)
|
||||
{
|
||||
foundEmptyEntry->m_refCount = 1;
|
||||
foundEmptyEntry->m_name = tagName;
|
||||
++m_allocatedTagCount;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
void TagRegistry<TagType, MaxTagCount>::ReleaseTag(TagType tag)
|
||||
{
|
||||
if (tag.IsValid())
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
Entry& entry = m_entriesByTag[tag.GetIndex()];
|
||||
const size_t refCount = --entry.m_refCount;
|
||||
AZ_Assert(
|
||||
refCount != static_cast<size_t>(-1), "Attempted to forfeit a tag that is not valid. Tag{%d},Name{'%s'}", tag,
|
||||
entry.m_name.GetCStr());
|
||||
if (refCount == 0)
|
||||
{
|
||||
entry.m_name = Name();
|
||||
--m_allocatedTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
TagType TagRegistry<TagType, MaxTagCount>::FindTag(const Name& tagName) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
for (size_t i = 0; i < m_entriesByTag.size(); ++i)
|
||||
{
|
||||
if (m_entriesByTag[i].m_name == tagName)
|
||||
{
|
||||
return TagType(i);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
Name TagRegistry<TagType, MaxTagCount>::GetName(TagType tag) const
|
||||
{
|
||||
if (tag.GetIndex() < m_entriesByTag.size())
|
||||
{
|
||||
return m_entriesByTag[tag.GetIndex()].m_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Name();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TagType, size_t MaxTagCount>
|
||||
size_t TagRegistry<TagType, MaxTagCount>::GetAllocatedTagCount() const
|
||||
{
|
||||
return m_allocatedTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,7 @@ namespace AZ
|
||||
switch (sortType)
|
||||
{
|
||||
case DrawListSortType::KeyThenDepth:
|
||||
AZStd::sort(drawList.begin(), drawList.end(),
|
||||
[](const DrawItemKeyPair& a, const DrawItemKeyPair& b)
|
||||
AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b)
|
||||
{
|
||||
if (a.m_sortKey != b.m_sortKey)
|
||||
{
|
||||
@@ -48,8 +47,7 @@ namespace AZ
|
||||
break;
|
||||
|
||||
case DrawListSortType::KeyThenReverseDepth:
|
||||
AZStd::sort(drawList.begin(), drawList.end(),
|
||||
[](const DrawItemKeyPair& a, const DrawItemKeyPair& b)
|
||||
AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b)
|
||||
{
|
||||
if (a.m_sortKey != b.m_sortKey)
|
||||
{
|
||||
@@ -61,8 +59,7 @@ namespace AZ
|
||||
break;
|
||||
|
||||
case DrawListSortType::DepthThenKey:
|
||||
AZStd::sort(drawList.begin(), drawList.end(),
|
||||
[](const DrawItemKeyPair& a, const DrawItemKeyPair& b)
|
||||
AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b)
|
||||
{
|
||||
if (a.m_depth != b.m_depth)
|
||||
{
|
||||
@@ -74,8 +71,7 @@ namespace AZ
|
||||
break;
|
||||
|
||||
case DrawListSortType::ReverseDepthThenKey:
|
||||
AZStd::sort(drawList.begin(), drawList.end(),
|
||||
[](const DrawItemKeyPair& a, const DrawItemKeyPair& b)
|
||||
AZStd::sort(drawList.begin(), drawList.end(), [](const DrawItemProperties& a, const DrawItemProperties& b)
|
||||
{
|
||||
if (a.m_depth != b.m_depth)
|
||||
{
|
||||
|
||||
@@ -63,14 +63,14 @@ namespace AZ
|
||||
|
||||
if (m_drawListMask[drawListTag.GetIndex()])
|
||||
{
|
||||
DrawItemKeyPair drawItem = drawPacket->GetDrawItem(i);
|
||||
DrawItemProperties drawItem = drawPacket->GetDrawItem(i);
|
||||
drawItem.m_depth = depth;
|
||||
threadListsByTag[drawListTag.GetIndex()].push_back(drawItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawListContext::AddDrawItem(DrawListTag drawListTag, DrawItemKeyPair drawItemKeyPair)
|
||||
void DrawListContext::AddDrawItem(DrawListTag drawListTag, DrawItemProperties drawItemProperties)
|
||||
{
|
||||
if (Validation::IsEnabled())
|
||||
{
|
||||
@@ -84,7 +84,7 @@ namespace AZ
|
||||
if (m_drawListMask[drawListTag.GetIndex()])
|
||||
{
|
||||
DrawListsByTag& drawListsByTag = m_threadListsByTag.GetStorage();
|
||||
drawListsByTag[drawListTag.GetIndex()].push_back(drawItemKeyPair);
|
||||
drawListsByTag[drawListTag.GetIndex()].push_back(drawItemProperties);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,117 +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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Atom/RHI/DrawListTagRegistry.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RHI
|
||||
{
|
||||
Ptr<DrawListTagRegistry> DrawListTagRegistry::Create()
|
||||
{
|
||||
return aznew DrawListTagRegistry;
|
||||
}
|
||||
|
||||
void DrawListTagRegistry::Reset()
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
m_entriesByTag.fill({});
|
||||
m_allocatedTagCount = 0;
|
||||
}
|
||||
|
||||
DrawListTag DrawListTagRegistry::AcquireTag(const Name& drawListName)
|
||||
{
|
||||
if (drawListName.IsEmpty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
DrawListTag drawListTag;
|
||||
Entry* foundEmptyEntry = nullptr;
|
||||
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
for (size_t i = 0; i < m_entriesByTag.size(); ++i)
|
||||
{
|
||||
Entry& entry = m_entriesByTag[i];
|
||||
|
||||
// Found an empty entry. Cache off the tag and pointer, but keep searching to find if
|
||||
// another entry holds the same name.
|
||||
if (entry.m_refCount == 0 && !foundEmptyEntry)
|
||||
{
|
||||
foundEmptyEntry = &entry;
|
||||
drawListTag = DrawListTag(i);
|
||||
}
|
||||
else if (entry.m_name == drawListName)
|
||||
{
|
||||
entry.m_refCount++;
|
||||
return DrawListTag(i);
|
||||
}
|
||||
}
|
||||
|
||||
// No other entry holds the name, so allocate the empty entry.
|
||||
if (foundEmptyEntry)
|
||||
{
|
||||
foundEmptyEntry->m_refCount = 1;
|
||||
foundEmptyEntry->m_name = drawListName;
|
||||
++m_allocatedTagCount;
|
||||
}
|
||||
|
||||
return drawListTag;
|
||||
}
|
||||
|
||||
void DrawListTagRegistry::ReleaseTag(DrawListTag drawListTag)
|
||||
{
|
||||
if (drawListTag.IsValid())
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
Entry& entry = m_entriesByTag[drawListTag.GetIndex()];
|
||||
const size_t refCount = --entry.m_refCount;
|
||||
AZ_Assert(refCount != static_cast<size_t>(-1), "Attempted to forfeit a tag that is not valid. Tag{%d},Name{'%s'}", drawListTag, entry.m_name.GetCStr());
|
||||
if (refCount == 0)
|
||||
{
|
||||
entry.m_name = Name();
|
||||
--m_allocatedTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawListTag DrawListTagRegistry::FindTag(const Name& drawListName) const
|
||||
{
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_mutex);
|
||||
for (size_t i = 0; i < m_entriesByTag.size(); ++i)
|
||||
{
|
||||
if (m_entriesByTag[i].m_name == drawListName)
|
||||
{
|
||||
return DrawListTag(i);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Name DrawListTagRegistry::GetName(DrawListTag tag) const
|
||||
{
|
||||
if (tag.GetIndex() < m_entriesByTag.size())
|
||||
{
|
||||
return m_entriesByTag[tag.GetIndex()].m_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Name();
|
||||
}
|
||||
}
|
||||
|
||||
size_t DrawListTagRegistry::GetAllocatedTagCount() const
|
||||
{
|
||||
return m_allocatedTagCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@ namespace AZ
|
||||
return m_drawItemCount;
|
||||
}
|
||||
|
||||
DrawItemKeyPair DrawPacket::GetDrawItem(size_t index) const
|
||||
DrawItemProperties DrawPacket::GetDrawItem(size_t index) const
|
||||
{
|
||||
AZ_Assert(index < GetDrawItemCount(), "Out of bounds array access!");
|
||||
return DrawItemKeyPair(&m_drawItems[index], m_drawItemSortKeys[index]);
|
||||
return DrawItemProperties(&m_drawItems[index], m_drawItemSortKeys[index], m_drawFilterMask);
|
||||
}
|
||||
|
||||
DrawListTag DrawPacket::GetDrawListTag(size_t index) const
|
||||
@@ -36,6 +36,11 @@ namespace AZ
|
||||
return m_drawListTags[index];
|
||||
}
|
||||
|
||||
DrawFilterMask DrawPacket::GetDrawFilterMask() const
|
||||
{
|
||||
return m_drawFilterMask;
|
||||
}
|
||||
|
||||
DrawListMask DrawPacket::GetDrawListMask() const
|
||||
{
|
||||
return m_drawListMask;
|
||||
|
||||
@@ -82,6 +82,11 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void DrawPacketBuilder::SetDrawFilterMask(DrawFilterMask filterMask)
|
||||
{
|
||||
m_drawFilterMask = filterMask;
|
||||
}
|
||||
|
||||
void DrawPacketBuilder::AddDrawItem(const DrawRequest& request)
|
||||
{
|
||||
if (request.m_listTag.IsValid())
|
||||
@@ -165,6 +170,7 @@ namespace AZ
|
||||
drawPacket->m_allocator = m_allocator;
|
||||
drawPacket->m_indexBufferView = m_indexBufferView;
|
||||
drawPacket->m_drawListMask = m_drawListMask;
|
||||
drawPacket->m_drawFilterMask = m_drawFilterMask;
|
||||
|
||||
if (shaderResourceGroupsOffset.IsValid())
|
||||
{
|
||||
@@ -288,6 +294,7 @@ namespace AZ
|
||||
m_rootConstants = {};
|
||||
m_scissors.clear();
|
||||
m_viewports.clear();
|
||||
m_drawFilterMask = DrawFilterMaskDefaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace AZ
|
||||
AZ_Assert(false, "RHISystem", "Unable to initialize RHI! \n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_drawListTagRegistry = RHI::DrawListTagRegistry::Create();
|
||||
m_pipelineStateCache = RHI::PipelineStateCache::Create(*m_device);
|
||||
|
||||
@@ -199,7 +199,6 @@ namespace AZ
|
||||
m_frameScheduler.Shutdown();
|
||||
|
||||
m_platformLimitsDescriptor = nullptr;
|
||||
m_drawListTagRegistry = nullptr;
|
||||
m_pipelineStateCache = nullptr;
|
||||
m_device->PreShutdown();
|
||||
AZ_Assert(m_device->use_count()==1, "The ref count for Device is %i but it should be 1 here to ensure all the resources are released", m_device->use_count());
|
||||
|
||||
@@ -80,11 +80,11 @@ namespace UnitTest
|
||||
m_indexBufferView = RHI::IndexBufferView(*m_bufferEmpty, random.GetRandom(), random.GetRandom(), RHI::IndexFormat::Uint16);
|
||||
}
|
||||
|
||||
void ValidateDrawItem(const DrawItemData& drawItemData, RHI::DrawItemKeyPair itemKeyPair) const
|
||||
void ValidateDrawItem(const DrawItemData& drawItemData, RHI::DrawItemProperties itemProperties) const
|
||||
{
|
||||
const RHI::DrawItem* drawItem = itemKeyPair.m_item;
|
||||
const RHI::DrawItem* drawItem = itemProperties.m_item;
|
||||
|
||||
EXPECT_EQ(itemKeyPair.m_sortKey, drawItemData.m_sortKey);
|
||||
EXPECT_EQ(itemProperties.m_sortKey, drawItemData.m_sortKey);
|
||||
EXPECT_EQ(drawItem->m_stencilRef, drawItemData.m_stencilRef);
|
||||
EXPECT_EQ(drawItem->m_pipelineState, drawItemData.m_pipelineState);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ set(FILES
|
||||
Include/Atom/RHI/CopyItem.h
|
||||
Include/Atom/RHI/ConstantsData.h
|
||||
Include/Atom/RHI/DispatchItem.h
|
||||
Include/Atom/RHI/DrawFilterTagRegistry.h
|
||||
Include/Atom/RHI/DrawItem.h
|
||||
Include/Atom/RHI/DrawList.h
|
||||
Include/Atom/RHI/DrawListTagRegistry.h
|
||||
@@ -48,7 +49,6 @@ set(FILES
|
||||
Source/RHI/ConstantsData.cpp
|
||||
Source/RHI/DrawList.cpp
|
||||
Source/RHI/DrawListContext.cpp
|
||||
Source/RHI/DrawListTagRegistry.cpp
|
||||
Source/RHI/DrawPacket.cpp
|
||||
Source/RHI/DrawPacketBuilder.cpp
|
||||
Include/Atom/RHI/Device.h
|
||||
@@ -201,4 +201,5 @@ set(FILES
|
||||
Include/Atom/RHI/CpuProfiler.h
|
||||
Include/Atom/RHI/CpuProfilerImpl.h
|
||||
Source/RHI/CpuProfilerImpl.cpp
|
||||
Include/Atom/RHI/TagRegistry.h
|
||||
)
|
||||
|
||||
@@ -214,6 +214,10 @@ namespace AZ
|
||||
Scene* m_scene = nullptr;
|
||||
RHI::DrawListTag m_drawListTag;
|
||||
|
||||
// All draw items use this filter when submit them to views
|
||||
// It's set to RenderPipeline's draw filter mask if the DynamicDrawContext was created for a render pipeline.
|
||||
RHI::DrawFilterMask m_drawFilter = RHI::DrawFilterMaskDefaultValue;
|
||||
|
||||
// Cached draw data
|
||||
AZStd::vector<RHI::StreamBufferView> m_cachedStreamBufferViews;
|
||||
AZStd::vector<RHI::IndexBufferView> m_cachedIndexBufferViews;
|
||||
|
||||
@@ -56,9 +56,11 @@ namespace AZ
|
||||
//! Draw calls which are made to this DynamicDrawContext will only be submitted for this scene.
|
||||
//! The created DynamicDrawContext is managed by dynamic draw system.
|
||||
virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) = 0;
|
||||
|
||||
//! Create a DynamicDrawContext for specified pass
|
||||
virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Pass* pass = nullptr) = 0;
|
||||
|
||||
//! Create a DynamicDrawContext for specified render pipeline
|
||||
//! Draw calls submitted through the context created by this function are only submitted
|
||||
//! to the supplied render pipeline (viewport)
|
||||
virtual RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) = 0;
|
||||
|
||||
//! Get a DynamicBuffer from DynamicDrawSystem.
|
||||
//! The returned buffer will be invalidated every time the RPISystem's RenderTick is called
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AZ
|
||||
|
||||
// DynamicDrawInterface overrides...
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Scene* scene) override;
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(Pass* pass) override;
|
||||
RHI::Ptr<DynamicDrawContext> CreateDynamicDrawContext(RenderPipeline* pipeline) override;
|
||||
RHI::Ptr<DynamicBuffer> GetDynamicBuffer(uint32_t size, uint32_t alignment = 1) override;
|
||||
void DrawGeometry(Data::Instance<Material> material, const GeometryData& geometry, ScenePtr scene) override;
|
||||
void AddDrawPacket(Scene* scene, AZStd::unique_ptr<const RHI::DrawPacket> drawPacket) override;
|
||||
|
||||
@@ -184,6 +184,12 @@ namespace AZ
|
||||
//! Get current render mode
|
||||
RenderMode GetRenderMode() const;
|
||||
|
||||
//! Get draw filter tag
|
||||
RHI::DrawFilterTag GetDrawFilterTag() const;
|
||||
|
||||
//! Get draw filter mask
|
||||
RHI::DrawFilterMask GetDrawFilterMask() const;
|
||||
|
||||
private:
|
||||
RenderPipeline() = default;
|
||||
|
||||
@@ -211,6 +217,8 @@ namespace AZ
|
||||
// if the view already exists in map, its DrawListMask will be combined to the existing one's
|
||||
void CollectPersistentViews(AZStd::map<ViewPtr, RHI::DrawListMask>& outViewMasks) const;
|
||||
|
||||
void SetDrawFilterTag(RHI::DrawFilterTag);
|
||||
|
||||
// End of functions accessed by Scene class
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
@@ -250,6 +258,13 @@ namespace AZ
|
||||
|
||||
// Original settings from RenderPipelineDescriptor, used to revert active render settings to original settings from RenderPipelineDescriptor
|
||||
PipelineRenderSettings m_originalRenderSettings;
|
||||
|
||||
// A tag to filter draw items submitted by passes of this render pipeline.
|
||||
// This tag is allocated when it's added to a scene. It's set to invalid when it's removed to the scene.
|
||||
RHI::DrawFilterTag m_drawFilterTag;
|
||||
// A mask to filter draw items submitted by passes of this render pipeline.
|
||||
// This mask is created from the value of m_drawFilterTag.
|
||||
RHI::DrawFilterMask m_drawFilterMask = 0;
|
||||
};
|
||||
|
||||
} // namespace RPI
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <Atom/RHI/DrawList.h>
|
||||
#include <Atom/RHI/PipelineStateDescriptor.h>
|
||||
#include <Atom/RHI/DrawFilterTagRegistry.h>
|
||||
#include <Atom/RHI.Reflect/FrameSchedulerEnums.h>
|
||||
#include <Atom/RHI.Reflect/ShaderResourceGroupLayoutDescriptor.h>
|
||||
#include <Atom/RPI.Reflect/System/SceneDescriptor.h>
|
||||
@@ -234,6 +235,9 @@ namespace AZ
|
||||
|
||||
// reference of dynamic draw system (from RPISystem)
|
||||
DynamicDrawSystem* m_dynamicDrawSystem = nullptr;
|
||||
|
||||
// Registry which allocates draw filter tag for RenderPipeline
|
||||
RHI::Ptr<RHI::DrawFilterTagRegistry> m_drawFilterTagRegistry;
|
||||
};
|
||||
|
||||
// --- Template functions ---
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace AZ
|
||||
void AddDrawPacket(const RHI::DrawPacket* drawPacket, Vector3 worldPosition);
|
||||
|
||||
//! Add a draw item to this view with its associated draw list tag
|
||||
void AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemKeyPair& drawItemKeyPair);
|
||||
void AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemProperties& drawItemProperties);
|
||||
|
||||
//! Sets the worldToView matrix and recalculates the other matrices.
|
||||
void SetWorldToViewMatrix(const AZ::Matrix4x4& worldToView);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicBuffer.h>
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawContext.h>
|
||||
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawInterface.h>
|
||||
#include <Atom/RPI.Public/RenderPipeline.h>
|
||||
|
||||
#include <Atom/RPI.Public/View.h>
|
||||
|
||||
@@ -601,10 +602,11 @@ namespace AZ
|
||||
drawItemInfo.m_drawItem.m_streamBufferViews = &m_cachedStreamBufferViews[drawItemInfo.m_vertexBufferViewIndex];
|
||||
}
|
||||
|
||||
RHI::DrawItemKeyPair drawItemKeyPair;
|
||||
drawItemKeyPair.m_sortKey = sortKey;
|
||||
drawItemKeyPair.m_item = &drawItemInfo.m_drawItem;
|
||||
view->AddDrawItem(m_drawListTag, drawItemKeyPair);
|
||||
RHI::DrawItemProperties drawItemProperties;
|
||||
drawItemProperties.m_sortKey = sortKey;
|
||||
drawItemProperties.m_item = &drawItemInfo.m_drawItem;
|
||||
drawItemProperties.m_drawFilterMask = m_drawFilter;
|
||||
view->AddDrawItem(m_drawListTag, drawItemProperties);
|
||||
sortKey++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,11 @@ namespace AZ
|
||||
|
||||
RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext(Scene* scene)
|
||||
{
|
||||
if (!scene)
|
||||
{
|
||||
AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input scene is invalid");
|
||||
return nullptr;
|
||||
}
|
||||
RHI::Ptr<DynamicDrawContext> drawContext = aznew DynamicDrawContext();
|
||||
drawContext->m_scene = scene;
|
||||
|
||||
@@ -67,11 +72,17 @@ namespace AZ
|
||||
return drawContext;
|
||||
}
|
||||
|
||||
// [GFX TODO][ATOM-13185] Add support for creating DynamicDrawContext for Pass
|
||||
RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext([[maybe_unused]] Pass* pass)
|
||||
RHI::Ptr<DynamicDrawContext> DynamicDrawSystem::CreateDynamicDrawContext(RenderPipeline* pipeline)
|
||||
{
|
||||
AZ_Error("RPI", false, "Unimplemented function");
|
||||
return nullptr;
|
||||
if (!pipeline || !pipeline->GetScene())
|
||||
{
|
||||
AZ_Error("RPI", false, "Failed to create a DynamicDrawContext: the input RenderPipeline is invalid or wasn't added to a Scene");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto context = CreateDynamicDrawContext(pipeline->GetScene());
|
||||
context->m_drawFilter = pipeline->GetDrawFilterMask();
|
||||
return context;
|
||||
}
|
||||
|
||||
// [GFX TODO][ATOM-13184] Add support of draw geometry with material for DynamicDrawSystemInterface
|
||||
|
||||
@@ -195,9 +195,12 @@ namespace AZ
|
||||
SetSrgsForDraw(commandList);
|
||||
}
|
||||
|
||||
for (const RHI::DrawItemKeyPair& drawItemKeyPair : drawListViewPartition)
|
||||
for (const RHI::DrawItemProperties& drawItemProperties : drawListViewPartition)
|
||||
{
|
||||
commandList->Submit(*drawItemKeyPair.m_item);
|
||||
if (drawItemProperties.m_drawFilterMask & m_pipeline->GetDrawFilterMask())
|
||||
{
|
||||
commandList->Submit(*drawItemProperties.m_item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -300,6 +300,9 @@ namespace AZ
|
||||
m_scene = nullptr;
|
||||
m_rootPass->SetEnabled(false);
|
||||
m_rootPass->QueueForRemoval();
|
||||
|
||||
m_drawFilterTag.Reset();
|
||||
m_drawFilterMask = 0;
|
||||
}
|
||||
|
||||
void RenderPipeline::OnPassModified()
|
||||
@@ -506,5 +509,28 @@ namespace AZ
|
||||
{
|
||||
return m_renderMode != RenderMode::NoRender;
|
||||
}
|
||||
|
||||
RHI::DrawFilterTag RenderPipeline::GetDrawFilterTag() const
|
||||
{
|
||||
return m_drawFilterTag;
|
||||
}
|
||||
|
||||
RHI::DrawFilterMask RenderPipeline::GetDrawFilterMask() const
|
||||
{
|
||||
return m_drawFilterMask;
|
||||
}
|
||||
|
||||
void RenderPipeline::SetDrawFilterTag(RHI::DrawFilterTag tag)
|
||||
{
|
||||
m_drawFilterTag = tag;
|
||||
if (m_drawFilterTag.IsValid())
|
||||
{
|
||||
m_drawFilterMask = 1 << tag.GetIndex();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_drawFilterMask = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ namespace AZ
|
||||
m_id = Uuid::CreateRandom();
|
||||
m_cullingScene = aznew CullingScene();
|
||||
SceneRequestBus::Handler::BusConnect(m_id);
|
||||
m_drawFilterTagRegistry = RHI::DrawFilterTagRegistry::Create();
|
||||
}
|
||||
|
||||
Scene::~Scene()
|
||||
@@ -269,6 +270,8 @@ namespace AZ
|
||||
return;
|
||||
}
|
||||
|
||||
pipeline->SetDrawFilterTag(m_drawFilterTagRegistry->AcquireTag(pipelineId));
|
||||
|
||||
m_pipelines.push_back(pipeline);
|
||||
|
||||
// Set this pipeline as default if the default pipeline was empty. This pipeline should be the first pipeline be added to the scene
|
||||
@@ -303,6 +306,8 @@ namespace AZ
|
||||
m_defaultPipeline = nullptr;
|
||||
}
|
||||
|
||||
m_drawFilterTagRegistry->ReleaseTag(pipelineToRemove->GetDrawFilterTag());
|
||||
|
||||
pipelineToRemove->OnRemovedFromScene(this);
|
||||
m_pipelines.erase(it);
|
||||
|
||||
|
||||
@@ -90,9 +90,9 @@ namespace AZ
|
||||
AddDrawPacket(drawPacket, depth);
|
||||
}
|
||||
|
||||
void View::AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemKeyPair& drawItemKeyPair)
|
||||
void View::AddDrawItem(RHI::DrawListTag drawListTag, const RHI::DrawItemProperties& drawItemProperties)
|
||||
{
|
||||
m_drawListContext.AddDrawItem(drawListTag, drawItemKeyPair);
|
||||
m_drawListContext.AddDrawItem(drawListTag, drawItemProperties);
|
||||
}
|
||||
|
||||
void View::SetWorldToViewMatrix(const AZ::Matrix4x4& worldToView)
|
||||
|
||||
+3
@@ -49,6 +49,7 @@ namespace AtomToolsFramework
|
||||
AZ::Name m_id;
|
||||
AZStd::string m_nameId;
|
||||
AZStd::string m_displayName;
|
||||
AZStd::string m_groupName;
|
||||
AZStd::string m_description;
|
||||
AZStd::any m_defaultValue;
|
||||
AZStd::any m_parentValue;
|
||||
@@ -108,6 +109,8 @@ namespace AtomToolsFramework
|
||||
private:
|
||||
// Functions used to configure edit data attributes.
|
||||
AZStd::string GetDisplayName() const;
|
||||
AZStd::string GetGroupName() const;
|
||||
AZStd::string GetAssetPickerTitle() const;
|
||||
AZStd::string GetDescription() const;
|
||||
AZStd::vector<AZ::Edit::EnumConstant<uint32_t>> GetEnumValues() const;
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ namespace AtomToolsFramework
|
||||
m_editData.m_elementId = AZ::Edit::UIHandlers::Default;
|
||||
|
||||
AddEditDataAttributeMemberFunction(AZ::Edit::Attributes::NameLabelOverride, &DynamicProperty::GetDisplayName);
|
||||
AddEditDataAttributeMemberFunction(AZ::Edit::Attributes::AssetPickerTitle, &DynamicProperty::GetAssetPickerTitle);
|
||||
AddEditDataAttributeMemberFunction(AZ::Edit::Attributes::DescriptionTextOverride, &DynamicProperty::GetDescription);
|
||||
AddEditDataAttributeMemberFunction(AZ::Edit::Attributes::ReadOnly, &DynamicProperty::IsReadOnly);
|
||||
AddEditDataAttributeMemberFunction(AZ::Edit::Attributes::EnumValues, &DynamicProperty::GetEnumValues);
|
||||
@@ -197,6 +198,16 @@ namespace AtomToolsFramework
|
||||
return !m_config.m_displayName.empty() ? m_config.m_displayName : m_config.m_nameId;
|
||||
}
|
||||
|
||||
AZStd::string DynamicProperty::GetGroupName() const
|
||||
{
|
||||
return m_config.m_groupName;
|
||||
}
|
||||
|
||||
AZStd::string DynamicProperty::GetAssetPickerTitle() const
|
||||
{
|
||||
return GetGroupName().empty() ? GetDisplayName() : GetGroupName() + " " + GetDisplayName();
|
||||
}
|
||||
|
||||
AZStd::string DynamicProperty::GetDescription() const
|
||||
{
|
||||
return AZStd::string::format("%s%s(Script Name = '%s')",
|
||||
|
||||
@@ -773,6 +773,7 @@ namespace MaterialEditor
|
||||
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
|
||||
propertyConfig.m_originalValue = AtomToolsFramework::ConvertToEditableType(m_materialAsset->GetPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(parentPropertyValues[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_groupName = m_materialTypeSourceData.FindGroup(groupNameId)->m_displayName;
|
||||
m_properties[propertyConfig.m_id] = AtomToolsFramework::DynamicProperty(propertyConfig);
|
||||
}
|
||||
return true;
|
||||
@@ -789,6 +790,7 @@ namespace MaterialEditor
|
||||
propertyConfig.m_id = "details.materialType";
|
||||
propertyConfig.m_nameId = "materialType";
|
||||
propertyConfig.m_displayName = "Material Type";
|
||||
propertyConfig.m_groupName = "Details";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
propertyConfig.m_defaultValue = AZStd::any(materialTypeAsset);
|
||||
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
|
||||
@@ -802,6 +804,7 @@ namespace MaterialEditor
|
||||
propertyConfig.m_id = "details.parentMaterial";
|
||||
propertyConfig.m_nameId = "parentMaterial";
|
||||
propertyConfig.m_displayName = "Parent Material";
|
||||
propertyConfig.m_groupName = "Details";
|
||||
propertyConfig.m_description = propertyConfig.m_displayName;
|
||||
propertyConfig.m_defaultValue = AZStd::any(parentMaterialAsset);
|
||||
propertyConfig.m_originalValue = propertyConfig.m_defaultValue;
|
||||
@@ -822,6 +825,7 @@ namespace MaterialEditor
|
||||
propertyConfig.m_id = MaterialPropertyId(UvGroupName, shaderInput).GetCStr();
|
||||
propertyConfig.m_nameId = shaderInput;
|
||||
propertyConfig.m_displayName = shaderInput;
|
||||
propertyConfig.m_groupName = "UV Names";
|
||||
propertyConfig.m_description = shaderInput;
|
||||
propertyConfig.m_defaultValue = uvName;
|
||||
propertyConfig.m_originalValue = uvName;
|
||||
|
||||
+2
@@ -203,6 +203,7 @@ namespace AZ
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, shaderInputStr).GetCStr();
|
||||
propertyConfig.m_nameId = shaderInputStr;
|
||||
propertyConfig.m_displayName = shaderInputStr;
|
||||
propertyConfig.m_groupName = groupDisplayName;
|
||||
propertyConfig.m_description = shaderInputStr;
|
||||
propertyConfig.m_defaultValue = uvName;
|
||||
propertyConfig.m_originalValue = uvName;
|
||||
@@ -247,6 +248,7 @@ namespace AZ
|
||||
AtomToolsFramework::ConvertToPropertyConfig(propertyConfig, propertyDefinition);
|
||||
|
||||
propertyConfig.m_id = AZ::RPI::MaterialPropertyId(groupNameId, propertyDefinition.m_nameId).GetFullName();
|
||||
propertyConfig.m_groupName = groupDisplayName;
|
||||
const auto& propertyIndex = m_editData.m_materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(propertyConfig.m_id);
|
||||
propertyConfig.m_defaultValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
propertyConfig.m_parentValue = AtomToolsFramework::ConvertToEditableType(m_editData.m_materialTypeAsset->GetDefaultPropertyValues()[propertyIndex.GetIndex()]);
|
||||
|
||||
@@ -95,14 +95,14 @@ namespace AZ
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
InitializeViewportSizeIfNeeded();
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::Render);
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::Render);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ImguiAtomSystemComponent::OnViewportSizeChanged(AzFramework::WindowSize size)
|
||||
{
|
||||
#if defined(IMGUI_ENABLED)
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast([this, size](ImGui::ImGuiManagerListenerBus::Events* imgui)
|
||||
ImGui::ImGuiManagerBus::Broadcast([this, size](ImGui::ImGuiManagerBus::Events* imgui)
|
||||
{
|
||||
imgui->OverrideRenderWindowSize(size.m_width, size.m_height);
|
||||
// ImGuiManagerListenerBus may not have been connected when this system component is activated
|
||||
|
||||
@@ -57,7 +57,6 @@ namespace AZ
|
||||
void OnRenderTick() override;
|
||||
void OnViewportSizeChanged(AzFramework::WindowSize size) override;
|
||||
|
||||
DebugConsole m_debugConsole;
|
||||
bool m_initialized = false;
|
||||
};
|
||||
} // namespace LYIntegration
|
||||
|
||||
@@ -26,7 +26,7 @@ ly_add_target(
|
||||
PRIVATE
|
||||
Source
|
||||
INTERFACE
|
||||
../External/ImGui/v1.70
|
||||
../External/ImGui/v1.82
|
||||
PUBLIC
|
||||
Include
|
||||
COMPILE_DEFINITIONS
|
||||
|
||||
@@ -45,7 +45,7 @@ ImGuiViewportWidget::ImGuiViewportWidget(QWidget* parent)
|
||||
ImGuiViewportWidget::~ImGuiViewportWidget()
|
||||
{
|
||||
DestroyRenderContext();
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetEditorWindowState,
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetEditorWindowState,
|
||||
DisplayState::Hidden);
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ bool ImGuiViewportWidget::CreateRenderContext()
|
||||
editor->GetEnv()->pRenderer->CreateContext(window);
|
||||
RestorePreviousContext();
|
||||
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetEditorWindowState,
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetEditorWindowState,
|
||||
DisplayState::Visible);
|
||||
|
||||
m_creatingRenderContext = false;
|
||||
@@ -154,8 +154,8 @@ void ImGuiViewportWidget::Render()
|
||||
ColorF stateMessageColor(Col_Gray);
|
||||
AZStd::string stateMessage = "No State";
|
||||
DisplayState visibilityState = DisplayState::Hidden;
|
||||
ImGuiManagerListenerBus::BroadcastResult(visibilityState,
|
||||
&IImGuiManagerListener::GetEditorWindowState);
|
||||
ImGuiManagerBus::BroadcastResult(visibilityState,
|
||||
&IImGuiManager::GetEditorWindowState);
|
||||
switch (visibilityState)
|
||||
{
|
||||
case ImGui::DisplayState::Hidden:
|
||||
|
||||
@@ -68,13 +68,12 @@ namespace ImGui
|
||||
typedef AZ::EBus<IImGuiUpdateListener> ImGuiUpdateListenerBus;
|
||||
|
||||
// Bus for sending events and getting state from the ImGui manager
|
||||
class IImGuiManagerListener : public AZ::EBusTraits
|
||||
class IImGuiManager
|
||||
{
|
||||
public:
|
||||
static const char* GetUniqueName() { return "IImGuiManagerListener"; }
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using Bus = AZ::EBus<IImGuiManagerListener>;
|
||||
AZ_RTTI(IImGuiManager, "{F5A0F08B-F2DA-43B7-8CD2-C6FC71E1A712}");
|
||||
|
||||
static const char* GetUniqueName() { return "IImGuiManager"; }
|
||||
|
||||
virtual DisplayState GetEditorWindowState() const = 0;
|
||||
virtual void SetEditorWindowState(DisplayState state) = 0;
|
||||
@@ -94,7 +93,16 @@ namespace ImGui
|
||||
virtual void RestoreRenderWindowSizeToDefault() = 0;
|
||||
virtual void Render() = 0;
|
||||
};
|
||||
typedef AZ::EBus<IImGuiManagerListener> ImGuiManagerListenerBus;
|
||||
|
||||
class IImGuiManagerRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
using Bus = AZ::EBus<IImGuiManager>;
|
||||
};
|
||||
using ImGuiManagerBus = AZ::EBus<IImGuiManager, IImGuiManagerRequests>;
|
||||
|
||||
// Bus for getting notifications from the IMGUI Entity Outliner
|
||||
class IImGuiEntityOutlinerNotifcations : public AZ::EBusTraits
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace
|
||||
void ImGuiManager::Initialize()
|
||||
{
|
||||
// Register for Buses
|
||||
ImGuiManagerListenerBus::Handler::BusConnect();
|
||||
ImGuiManagerBus::Handler::BusConnect();
|
||||
|
||||
// Register for Input Notifications
|
||||
InputChannelEventListener::Connect();
|
||||
@@ -236,10 +236,14 @@ void ImGuiManager::Initialize()
|
||||
// Future work here could include responding to the mouse being connected and disconnected at run-time, but this is fine for now.
|
||||
const AzFramework::InputDevice* mouseDevice = AzFramework::InputDeviceRequests::FindInputDevice(AzFramework::InputDeviceMouse::Id);
|
||||
m_hardwardeMouseConnected = mouseDevice && mouseDevice->IsConnected();
|
||||
|
||||
AZ::Interface<ImGui::IImGuiManager>::Register(this);
|
||||
}
|
||||
|
||||
void ImGuiManager::Shutdown()
|
||||
{
|
||||
AZ::Interface<ImGui::IImGuiManager>::Unregister(this);
|
||||
|
||||
if (!gEnv)
|
||||
{
|
||||
AZ_Warning("ImGuiManager", false, "%s %s", __func__, "gEnv Invalid -- Skipping ImGui Shutdown.");
|
||||
@@ -253,7 +257,7 @@ void ImGuiManager::Shutdown()
|
||||
#endif
|
||||
|
||||
// Unregister from Buses
|
||||
ImGuiManagerListenerBus::Handler::BusDisconnect();
|
||||
ImGuiManagerBus::Handler::BusDisconnect();
|
||||
InputChannelEventListener::Disconnect();
|
||||
InputTextEventListener::Disconnect();
|
||||
AzFramework::WindowNotificationBus::Handler::BusDisconnect();
|
||||
@@ -332,7 +336,7 @@ void ImGuiManager::Render()
|
||||
}
|
||||
|
||||
// If no item and no window is focused, we should artificially add focus to the Main Menu Bar, to save 1 step when navigating with a controller.
|
||||
if (!ImGui::IsAnyItemFocused() && !ImGui::IsAnyWindowFocused())
|
||||
if (!ImGui::IsAnyItemFocused() && !ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow))
|
||||
{
|
||||
ImGuiWindow* mainMenuWin = ImGui::FindWindowByName("##MainMenuBar");
|
||||
if (mainMenuWin)
|
||||
@@ -829,27 +833,27 @@ void OnEnableCameraMonitorCBFunc(ICVar* pArgs)
|
||||
|
||||
void OnShowImGuiCBFunc(ICVar* pArgs)
|
||||
{
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::SetClientMenuBarState, pArgs->GetIVal() != 0 ? ImGui::DisplayState::Visible : ImGui::DisplayState::Hidden);
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetClientMenuBarState, pArgs->GetIVal() != 0 ? ImGui::DisplayState::Visible : ImGui::DisplayState::Hidden);
|
||||
}
|
||||
|
||||
void OnDiscreteInputModeCBFunc(ICVar* pArgs)
|
||||
{
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::SetEnableDiscreteInputMode, pArgs->GetIVal() != 0 );
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetEnableDiscreteInputMode, pArgs->GetIVal() != 0 );
|
||||
}
|
||||
|
||||
void OnEnableControllerCBFunc(ICVar* pArgs)
|
||||
{
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::EnableControllerSupportMode, ImGuiControllerModeFlags::Contextual, (pArgs->GetIVal() != 0));
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Contextual, (pArgs->GetIVal() != 0));
|
||||
}
|
||||
|
||||
void OnEnableControllerMouseCBFunc(ICVar* pArgs)
|
||||
{
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::EnableControllerSupportMode, ImGuiControllerModeFlags::Mouse, (pArgs->GetIVal() != 0));
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Mouse, (pArgs->GetIVal() != 0));
|
||||
}
|
||||
|
||||
void OnControllerMouseSensitivityCBFunc(ICVar* pArgs)
|
||||
{
|
||||
ImGui::ImGuiManagerListenerBus::Broadcast(&ImGui::IImGuiManagerListener::SetControllerMouseSensitivity, pArgs->GetFVal());
|
||||
ImGui::ImGuiManagerBus::Broadcast(&ImGui::IImGuiManager::SetControllerMouseSensitivity, pArgs->GetFVal());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace ImGui
|
||||
class ImGuiManager
|
||||
: public AzFramework::InputChannelEventListener
|
||||
, public AzFramework::InputTextEventListener
|
||||
, public ImGuiManagerListenerBus::Handler
|
||||
, public ImGuiManagerBus::Handler
|
||||
, public AzFramework::WindowNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
@@ -45,7 +45,7 @@ namespace ImGui
|
||||
protected:
|
||||
void RenderImGuiBuffers(const ImVec2& scaleRects);
|
||||
|
||||
// -- ImGuiManagerListenerBus Interface -------------------------------------------------------------------
|
||||
// -- ImGuiManagerBus Interface -------------------------------------------------------------------
|
||||
DisplayState GetEditorWindowState() const override { return m_editorWindowState; }
|
||||
void SetEditorWindowState(DisplayState state) override { m_editorWindowState = state; }
|
||||
DisplayState GetClientMenuBarState() const override { return m_clientMenuBarState; }
|
||||
@@ -63,7 +63,7 @@ namespace ImGui
|
||||
void OverrideRenderWindowSize(uint32_t width, uint32_t height) override;
|
||||
void RestoreRenderWindowSizeToDefault() override;
|
||||
void Render() override;
|
||||
// -- ImGuiManagerListenerBus Interface -------------------------------------------------------------------
|
||||
// -- ImGuiManagerBus Interface -------------------------------------------------------------------
|
||||
|
||||
// -- AzFramework::InputChannelEventListener and AzFramework::InputTextEventListener Interface ------------
|
||||
bool OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel) override;
|
||||
|
||||
@@ -362,7 +362,7 @@ namespace ImGui
|
||||
ImGui::NextColumn();
|
||||
// A Small Legend and Hints section for help using this thing
|
||||
ImGui::BeginChild("MouseHoverLegendChild", ImVec2(250.0f, 30.0f), true);
|
||||
if (ImGui::IsMouseHoveringWindow())
|
||||
if (ImGui::IsWindowHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::TextColored(ImGui::Colors::s_NiceLabelColor, "Legend:");
|
||||
@@ -389,7 +389,7 @@ namespace ImGui
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
ImGui::TextColored(ImGui::IsMouseHoveringWindow() ? ImGui::Colors::s_NiceLabelColor : ImGui::Colors::s_PlainLabelColor, "Mouse Over For Legend and Tips");
|
||||
ImGui::TextColored(ImGui::IsWindowHovered() ? ImGui::Colors::s_NiceLabelColor : ImGui::Colors::s_PlainLabelColor, "Mouse Over For Legend and Tips");
|
||||
ImGui::EndChild(); // MouseHover Child
|
||||
ImGui::NextColumn();
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace ImGui
|
||||
ImGui::TextColored(ImGui::Colors::s_NiceLabelColor, "Previous Cam %d: %s %s", i, camInfo.m_camId.ToString().c_str(), camInfo.m_camName.c_str());
|
||||
ImGui::TextColored(ImGui::Colors::s_NiceLabelColor, " Active Cam frames/time: %d / %.02f", camInfo.m_activeFrames, camInfo.m_activeTime);
|
||||
|
||||
if (ImGui::IsMouseHoveringWindow())
|
||||
if (ImGui::IsWindowHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::BeginChild(AZStd::string::format("cameraInfoTooltip%d", i).c_str(), ImVec2(500.0f, 140.0f), true);
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace ImGui
|
||||
{
|
||||
// Get Discrete Input state now, we will use it both inside the ImGui SubMenu, and along the main task bar ( when it is on )
|
||||
bool discreteInputEnabled = false;
|
||||
ImGuiManagerListenerBus::BroadcastResult(discreteInputEnabled, &IImGuiManagerListener::GetEnableDiscreteInputMode);
|
||||
ImGuiManagerBus::BroadcastResult(discreteInputEnabled, &IImGuiManager::GetEnableDiscreteInputMode);
|
||||
|
||||
// Input Mode Display
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace ImGui
|
||||
{
|
||||
// Discrete Input - Control ImGui and Game independently.
|
||||
ImGui::DisplayState state;
|
||||
ImGui::ImGuiManagerListenerBus::BroadcastResult(state, &ImGui::IImGuiManagerListener::GetClientMenuBarState);
|
||||
ImGui::ImGuiManagerBus::BroadcastResult(state, &ImGui::IImGuiManager::GetClientMenuBarState);
|
||||
if (state == DisplayState::Visible)
|
||||
{
|
||||
inputTitle.append("ImGui");
|
||||
@@ -414,40 +414,40 @@ namespace ImGui
|
||||
// Controller Support - Contextual
|
||||
{
|
||||
bool controllerEnabled = false;
|
||||
ImGuiManagerListenerBus::BroadcastResult(controllerEnabled, &IImGuiManagerListener::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Contextual);
|
||||
ImGuiManagerBus::BroadcastResult(controllerEnabled, &IImGuiManager::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Contextual);
|
||||
|
||||
bool controllerEnabledCheckbox = controllerEnabled;
|
||||
ImGui::Checkbox(AZStd::string::format("Controller Support (Contextual) %s (Click Checkbox to Toggle)", controllerEnabledCheckbox ? "On" : "Off").c_str(), &controllerEnabledCheckbox);
|
||||
if (controllerEnabledCheckbox != controllerEnabled)
|
||||
{
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::EnableControllerSupportMode, ImGuiControllerModeFlags::Contextual, controllerEnabledCheckbox);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Contextual, controllerEnabledCheckbox);
|
||||
}
|
||||
}
|
||||
|
||||
// Controller Support - Mouse
|
||||
{
|
||||
bool controllerMouseEnabled = false;
|
||||
ImGuiManagerListenerBus::BroadcastResult(controllerMouseEnabled, &IImGuiManagerListener::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Mouse);
|
||||
ImGuiManagerBus::BroadcastResult(controllerMouseEnabled, &IImGuiManager::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Mouse);
|
||||
|
||||
bool controllerMouseEnabledCheckbox = controllerMouseEnabled;
|
||||
ImGui::Checkbox(AZStd::string::format("Controller Support (Mouse) %s (Click Checkbox to Toggle)", controllerMouseEnabledCheckbox ? "On" : "Off").c_str(), &controllerMouseEnabledCheckbox);
|
||||
if (controllerMouseEnabledCheckbox != controllerMouseEnabled)
|
||||
{
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::EnableControllerSupportMode, ImGuiControllerModeFlags::Mouse, controllerMouseEnabledCheckbox);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::EnableControllerSupportMode, ImGuiControllerModeFlags::Mouse, controllerMouseEnabledCheckbox);
|
||||
}
|
||||
|
||||
// Only draw Controller Mouse Sensitivity slider if the mouse is enabled
|
||||
if (controllerMouseEnabled)
|
||||
{
|
||||
float controllerMouseSensitivity = 1.0f;
|
||||
ImGuiManagerListenerBus::BroadcastResult(controllerMouseSensitivity, &IImGuiManagerListener::GetControllerMouseSensitivity);
|
||||
ImGuiManagerBus::BroadcastResult(controllerMouseSensitivity, &IImGuiManager::GetControllerMouseSensitivity);
|
||||
|
||||
float controllerMouseSensitivitySlider = controllerMouseSensitivity;
|
||||
ImGui::DragFloat("Controller Mouse Sensitivity", &controllerMouseSensitivitySlider, 0.1f, 0.1f, 50.0f);
|
||||
|
||||
if (controllerMouseSensitivitySlider != controllerMouseSensitivity)
|
||||
{
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetControllerMouseSensitivity, controllerMouseSensitivitySlider);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetControllerMouseSensitivity, controllerMouseSensitivitySlider);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,7 +458,7 @@ namespace ImGui
|
||||
ImGui::Checkbox(AZStd::string::format("Discrete Input %s (Click Checkbox to Toggle)", discreteInputEnabledCheckbox ? "On" : "Off").c_str(), &discreteInputEnabledCheckbox);
|
||||
if (discreteInputEnabledCheckbox != discreteInputEnabled)
|
||||
{
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetEnableDiscreteInputMode, discreteInputEnabledCheckbox);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetEnableDiscreteInputMode, discreteInputEnabledCheckbox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +484,7 @@ namespace ImGui
|
||||
ImGui::TextColored(ImGui::Colors::s_NiceLabelColor, "ImGui Resolution Mode:");
|
||||
|
||||
ImGuiResolutionMode resMode = ImGuiResolutionMode::MatchRenderResolution;
|
||||
ImGuiManagerListenerBus::BroadcastResult(resMode, &IImGuiManagerListener::GetResolutionMode);
|
||||
ImGuiManagerBus::BroadcastResult(resMode, &IImGuiManager::GetResolutionMode);
|
||||
|
||||
int resModeRadioBtn = static_cast<int>(resMode);
|
||||
ImGui::RadioButton("Force Resolution", &resModeRadioBtn, static_cast<int>(ImGuiResolutionMode::LockToResolution));
|
||||
@@ -496,12 +496,12 @@ namespace ImGui
|
||||
ImGuiResolutionMode resModeRadioBtnResult = static_cast<ImGuiResolutionMode>(resModeRadioBtn);
|
||||
if (resModeRadioBtnResult != resMode)
|
||||
{
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetResolutionMode, resModeRadioBtnResult);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetResolutionMode, resModeRadioBtnResult);
|
||||
}
|
||||
|
||||
// Resolutions
|
||||
ImVec2 imGuiRes;
|
||||
ImGuiManagerListenerBus::BroadcastResult(imGuiRes, &IImGuiManagerListener::GetImGuiRenderResolution);
|
||||
ImGuiManagerBus::BroadcastResult(imGuiRes, &IImGuiManager::GetImGuiRenderResolution);
|
||||
|
||||
ImGui::TextColored(ImGui::Colors::s_PlainLabelColor, "Current ImGui Resolution: ");
|
||||
ImGui::SameLine();
|
||||
@@ -518,7 +518,7 @@ namespace ImGui
|
||||
if (ImGui::Button(AZStd::string::format("%d x %d", s_renderResolutionWidths[j], renderHeight).c_str(), ImVec2(400, 0)))
|
||||
{
|
||||
ImVec2 newRenderRes(static_cast<float>(s_renderResolutionWidths[j]), static_cast<float>(renderHeight));
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetImGuiRenderResolution, newRenderRes);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetImGuiRenderResolution, newRenderRes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -577,10 +577,10 @@ namespace ImGui
|
||||
void ImGuiLYCommonMenu::OnImGuiUpdate_DrawControllerLegend()
|
||||
{
|
||||
bool contextualControllerEnabled = false;
|
||||
ImGuiManagerListenerBus::BroadcastResult(contextualControllerEnabled, &IImGuiManagerListener::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Contextual);
|
||||
ImGuiManagerBus::BroadcastResult(contextualControllerEnabled, &IImGuiManager::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Contextual);
|
||||
|
||||
bool controllerMouseEnabled = false;
|
||||
ImGuiManagerListenerBus::BroadcastResult(controllerMouseEnabled, &IImGuiManagerListener::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Mouse);
|
||||
ImGuiManagerBus::BroadcastResult(controllerMouseEnabled, &IImGuiManager::IsControllerSupportModeEnabled, ImGuiControllerModeFlags::Mouse);
|
||||
|
||||
ImGui::TextColored(ImGui::Colors::s_PlainLabelColor, "Contextual Controller Input Legend. Currently Enabled:");
|
||||
ImGui::SameLine();
|
||||
@@ -701,10 +701,10 @@ namespace ImGui
|
||||
AZ::TickBus::Handler::BusConnect();
|
||||
|
||||
// Get the current ImGui Display state to restore it later.
|
||||
ImGuiManagerListenerBus::BroadcastResult(m_telemetryCapturePreCaptureState, &IImGuiManagerListener::GetClientMenuBarState);
|
||||
ImGuiManagerBus::BroadcastResult(m_telemetryCapturePreCaptureState, &IImGuiManager::GetClientMenuBarState);
|
||||
|
||||
// Turn off the ImGui Manager
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetClientMenuBarState, DisplayState::Hidden);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetClientMenuBarState, DisplayState::Hidden);
|
||||
}
|
||||
|
||||
void ImGuiLYCommonMenu::StopTelemetryCapture()
|
||||
@@ -714,7 +714,7 @@ namespace ImGui
|
||||
|
||||
// Restore ImGui State
|
||||
// Turn off the ImGui Manager
|
||||
ImGuiManagerListenerBus::Broadcast(&IImGuiManagerListener::SetClientMenuBarState, m_telemetryCapturePreCaptureState);
|
||||
ImGuiManagerBus::Broadcast(&IImGuiManager::SetClientMenuBarState, m_telemetryCapturePreCaptureState);
|
||||
|
||||
// Reset timer and disconnect tick bus
|
||||
m_telemetryCaptureTimeRemaining = 0.0f;
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace ImGui
|
||||
}
|
||||
|
||||
// Toggle collapsing when double clicking this "window"
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsMouseHoveringWindow())
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsWindowHovered())
|
||||
{
|
||||
m_collapsed = !m_collapsed;
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
../External/ImGui/v1.70/imgui/imconfig.h
|
||||
../External/ImGui/v1.70/imgui/imgui.cpp
|
||||
../External/ImGui/v1.70/imgui/imgui.h
|
||||
../External/ImGui/v1.70/imgui/imgui_draw.cpp
|
||||
../External/ImGui/v1.70/imgui/imgui_internal.h
|
||||
../External/ImGui/v1.70/imgui/imgui_user.h
|
||||
../External/ImGui/v1.70/imgui/imgui_user.inl
|
||||
../External/ImGui/v1.70/imgui/imgui_widgets.cpp
|
||||
../External/ImGui/v1.82/imgui/imconfig.h
|
||||
../External/ImGui/v1.82/imgui/imgui.cpp
|
||||
../External/ImGui/v1.82/imgui/imgui.h
|
||||
../External/ImGui/v1.82/imgui/imgui_draw.cpp
|
||||
../External/ImGui/v1.82/imgui/imgui_internal.h
|
||||
../External/ImGui/v1.82/imgui/imgui_tables.cpp
|
||||
../External/ImGui/v1.82/imgui/imgui_user.h
|
||||
../External/ImGui/v1.82/imgui/imgui_user.inl
|
||||
../External/ImGui/v1.82/imgui/imgui_widgets.cpp
|
||||
)
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# editorconfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings:
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[imstb_*]
|
||||
indent_size = 3
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
@@ -1,34 +0,0 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- if [ $TRAVIS_OS_NAME == linux ]; then
|
||||
sudo apt-get update -qq;
|
||||
sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev;
|
||||
wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip;
|
||||
unzip glfw-3.2.1.zip && cd glfw-3.2.1;
|
||||
cmake -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .;
|
||||
sudo make -j $CPU_NUM install && cd ..;
|
||||
fi
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then
|
||||
brew update;
|
||||
brew install glfw3;
|
||||
brew install sdl2;
|
||||
fi
|
||||
|
||||
script:
|
||||
- make -C examples/example_glfw_opengl2
|
||||
- make -C examples/example_glfw_opengl3
|
||||
- make -C examples/example_sdl_opengl3
|
||||
- if [ $TRAVIS_OS_NAME == osx ]; then
|
||||
xcodebuild -project examples/example_apple_metal/example_apple_metal.xcodeproj -target example_apple_metal_macos;
|
||||
fi
|
||||
@@ -1,81 +0,0 @@
|
||||
// Modifications copyright Amazon.com, Inc. or its affiliates.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h)
|
||||
// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h"
|
||||
// If you do so you need to make sure that configuration settings are defined consistently _everywhere_ dear imgui is used, which include
|
||||
// the imgui*.cpp files but also _any_ of your code that uses imgui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
// Include Platform Def to get mutliplatform AZ_DLL_IMPORT and AZ_DLL_EXPORT to use below
|
||||
#include <AzCore/PlatformDef.h>
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows.
|
||||
#ifdef IMGUI_API_IMPORT
|
||||
#define IMGUI_API AZ_DLL_IMPORT
|
||||
#else
|
||||
#define IMGUI_API AZ_DLL_EXPORT
|
||||
#endif // IMGUI_API_IMPORT
|
||||
|
||||
//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty)
|
||||
//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow.
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function.
|
||||
//#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself if you don't want to link with vsnprintf.
|
||||
//#define IMGUI_DISABLE_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 wrapper so you can implement them yourself. Declare your prototypes in imconfig.h.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of imgui cpp files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, const MyMatrix44& v);
|
||||
}
|
||||
*/
|
||||
-4501
File diff suppressed because it is too large
Load Diff
-1627
File diff suppressed because it is too large
Load Diff
@@ -1,321 +0,0 @@
|
||||
dear imgui, v1.70
|
||||
(Font Readme)
|
||||
|
||||
---------------------------------------
|
||||
|
||||
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer),
|
||||
a 13 pixels high, pixel-perfect font used by default.
|
||||
We embed it font in source code so you can use Dear ImGui without any file system access.
|
||||
|
||||
You may also load external .TTF/.OTF files.
|
||||
The files in this folder are suggested fonts, provided as a convenience.
|
||||
|
||||
Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
|
||||
Also read dear imgui FAQ in imgui.cpp!
|
||||
|
||||
If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum:
|
||||
https://discourse.dearimgui.org/c/getting-started
|
||||
|
||||
|
||||
---------------------------------------
|
||||
INDEX:
|
||||
---------------------------------------
|
||||
|
||||
- Readme First / FAQ
|
||||
- Using Icons
|
||||
- Fonts Loading Instructions
|
||||
- FreeType rasterizer, Small font sizes
|
||||
- Building Custom Glyph Ranges
|
||||
- Embedding Fonts in Source Code
|
||||
- Credits/Licences for fonts included in this folder
|
||||
- Fonts Links
|
||||
|
||||
|
||||
---------------------------------------
|
||||
README FIRST / FAQ
|
||||
---------------------------------------
|
||||
|
||||
- You can use the style editor ImGui::ShowStyleEditor() in the "Fonts" section to browse your fonts
|
||||
and understand what's going on if you have an issue.
|
||||
- Make sure your font ranges data are persistent (available during the call to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build().
|
||||
- Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.:
|
||||
u8"hello"
|
||||
u8"こんにちは" // this will be encoded as UTF-8
|
||||
- If you want to include a backslash \ character in your string literal, you need to double them e.g. "folder\\filename".
|
||||
- Please use the Discourse forum (https://discourse.dearimgui.org) and not the Github issue tracker for basic font loading questions.
|
||||
|
||||
|
||||
---------------------------------------
|
||||
USING ICONS
|
||||
---------------------------------------
|
||||
|
||||
Using an icon font (such as FontAwesome: http://fontawesome.io or OpenFontIcons. https://github.com/traverseda/OpenFontIcons)
|
||||
is an easy and practical way to use icons in your Dear ImGui application.
|
||||
A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without
|
||||
having to change fonts back and forth.
|
||||
|
||||
To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut:
|
||||
https://github.com/juliettef/IconFontCppHeaders
|
||||
|
||||
The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u
|
||||
#define ICON_FA_SEARCH u8"\uf002"
|
||||
The pre-C++11 version has the values directly encoded as utf-8:
|
||||
#define ICON_FA_SEARCH "\xEF\x80\x82"
|
||||
|
||||
Example Setup:
|
||||
|
||||
// Merge icons into default tool font
|
||||
#include "IconsFontAwesome.h"
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced
|
||||
static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges);
|
||||
|
||||
Example Usage:
|
||||
|
||||
// Usage, e.g.
|
||||
ImGui::Text("%s among %d items", ICON_FA_SEARCH, count);
|
||||
ImGui::Button(ICON_FA_SEARCH " Search");
|
||||
// C string _literals_ can be concatenated at compilation time, e.g. "hello" " world"
|
||||
// ICON_FA_SEARCH is defined as a string literal so this is the same as "A" "B" becoming "AB"
|
||||
|
||||
See Links below for other icons fonts and related tools.
|
||||
|
||||
|
||||
---------------------------------------
|
||||
FONTS LOADING INSTRUCTIONS
|
||||
---------------------------------------
|
||||
|
||||
Load default font:
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
Load .TTF/.OTF file with:
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
|
||||
ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels);
|
||||
|
||||
// Select font at runtime
|
||||
ImGui::Text("Hello"); // use the default font (which is the first loaded font)
|
||||
ImGui::PushFont(font2);
|
||||
ImGui::Text("Hello with another font");
|
||||
ImGui::PopFont();
|
||||
|
||||
For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally):
|
||||
|
||||
ImFontConfig config;
|
||||
config.OversampleH = 2;
|
||||
config.OversampleV = 1;
|
||||
config.GlyphExtraSpacing.x = 1.0f;
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config);
|
||||
|
||||
Read about oversampling here:
|
||||
https://github.com/nothings/stb/blob/master/tests/oversample
|
||||
|
||||
If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API.
|
||||
The typical result of failing to upload a texture is if every glyphs appears as white rectangles.
|
||||
In particular, using a large range such as GetGlyphRangesChineseSimplifiedCommon() is not recommended unless you
|
||||
set OversampleH/OversampleV to 1 and use a small font size.
|
||||
Mind the fact that some graphics drivers have texture size limitation.
|
||||
If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours.
|
||||
Some solutions:
|
||||
|
||||
- 1) Reduce glyphs ranges by calculating them from source localization data.
|
||||
You can use ImFontGlyphRangesBuilder for this purpose, this will be the biggest win!
|
||||
- 2) You may reduce oversampling, e.g. config.OversampleH = config.OversampleV = 1, this will largely reduce your texture size.
|
||||
- 3) Set io.Fonts.TexDesiredWidth to specify a texture width to minimize texture height (see comment in ImFontAtlas::Build function).
|
||||
- 4) Set io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight; to disable rounding the texture height to the next power of two.
|
||||
|
||||
Combine two fonts into one:
|
||||
|
||||
// Load a first font
|
||||
ImFont* font = io.Fonts->AddFontDefault();
|
||||
|
||||
// Add character ranges and merge into the previous font
|
||||
// The ranges array is not copied by the AddFont* functions and is used lazily
|
||||
// so ensure it is available at the time of building or calling GetTexDataAsRGBA32().
|
||||
static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // Will not be copied by AddFont* so keep in scope.
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 18.0f, &config, io.Fonts->GetGlyphRangesJapanese());
|
||||
io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 18.0f, &config, icons_ranges);
|
||||
io.Fonts->Build();
|
||||
|
||||
Add a fourth parameter to bake specific font ranges only:
|
||||
|
||||
// Basic Latin, Extended Latin
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault());
|
||||
|
||||
// Default + Selection of 2500 Ideographs used by Simplified Chinese
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon());
|
||||
|
||||
// Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs
|
||||
io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
|
||||
See "BUILDING CUSTOM GLYPH RANGES" section to create your own ranges.
|
||||
Offset font vertically by altering the io.Font->DisplayOffset value:
|
||||
|
||||
ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels);
|
||||
font->DisplayOffset.y = 1; // Render 1 pixel down
|
||||
|
||||
|
||||
---------------------------------------
|
||||
FREETYPE RASTERIZER, SMALL FONT SIZES
|
||||
---------------------------------------
|
||||
|
||||
Dear ImGui uses imstb_truetype.h to rasterize fonts (with optional oversampling).
|
||||
This technique and its implementation are not ideal for fonts rendered at _small sizes_, which may appear a
|
||||
little blurry or hard to read.
|
||||
|
||||
There is an implementation of the ImFontAtlas builder using FreeType that you can use in the misc/freetype/ folder.
|
||||
|
||||
FreeType supports auto-hinting which tends to improve the readability of small fonts.
|
||||
Note that this code currently creates textures that are unoptimally too large (could be fixed with some work).
|
||||
Also note that correct sRGB space blending will have an important effect on your font rendering quality.
|
||||
|
||||
|
||||
---------------------------------------
|
||||
BUILDING CUSTOM GLYPH RANGES
|
||||
---------------------------------------
|
||||
|
||||
You can use the ImFontGlyphRangesBuilder helper to create glyph ranges based on text input.
|
||||
For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs.
|
||||
|
||||
ImVector<ImWchar> ranges;
|
||||
ImFontGlyphRangesBuilder builder;
|
||||
builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters)
|
||||
builder.AddChar(0x7262); // Add a specific character
|
||||
builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges
|
||||
builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted)
|
||||
|
||||
io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data);
|
||||
io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted.
|
||||
|
||||
|
||||
---------------------------------------
|
||||
EMBEDDING FONTS IN SOURCE CODE
|
||||
---------------------------------------
|
||||
|
||||
Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code.
|
||||
See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool.
|
||||
You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README).
|
||||
The tool can optionally output Base85 encoding to reduce the size of _source code_ but the read-only arrays in the
|
||||
actual binary will be about 20% bigger.
|
||||
|
||||
Then load the font with:
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...);
|
||||
or:
|
||||
ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...);
|
||||
|
||||
|
||||
---------------------------------------
|
||||
CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER
|
||||
---------------------------------------
|
||||
|
||||
Roboto-Medium.ttf
|
||||
|
||||
Apache License 2.0
|
||||
by Christian Robertson
|
||||
https://fonts.google.com/specimen/Roboto
|
||||
|
||||
Cousine-Regular.ttf
|
||||
|
||||
by Steve Matteson
|
||||
Digitized data copyright (c) 2010 Google Corporation.
|
||||
Licensed under the SIL Open Font License, Version 1.1
|
||||
https://fonts.google.com/specimen/Cousine
|
||||
|
||||
DroidSans.ttf
|
||||
|
||||
Copyright (c) Steve Matteson
|
||||
Apache License, version 2.0
|
||||
https://www.fontsquirrel.com/fonts/droid-sans
|
||||
|
||||
ProggyClean.ttf
|
||||
|
||||
Copyright (c) 2004, 2005 Tristan Grimmer
|
||||
MIT License
|
||||
recommended loading setting in ImGui: Size = 13.0, DisplayOffset.Y = +1
|
||||
http://www.proggyfonts.net/
|
||||
|
||||
ProggyTiny.ttf
|
||||
Copyright (c) 2004, 2005 Tristan Grimmer
|
||||
MIT License
|
||||
recommended loading setting in ImGui: Size = 10.0, DisplayOffset.Y = +1
|
||||
http://www.proggyfonts.net/
|
||||
|
||||
Karla-Regular.ttf
|
||||
Copyright (c) 2012, Jonathan Pinhorn
|
||||
SIL OPEN FONT LICENSE Version 1.1
|
||||
|
||||
|
||||
---------------------------------------
|
||||
FONTS LINKS
|
||||
---------------------------------------
|
||||
|
||||
ICON FONTS
|
||||
|
||||
C/C++ header for icon fonts (#define with code points to use in source code string literals)
|
||||
https://github.com/juliettef/IconFontCppHeaders
|
||||
|
||||
FontAwesome
|
||||
https://fortawesome.github.io/Font-Awesome
|
||||
|
||||
OpenFontIcons
|
||||
https://github.com/traverseda/OpenFontIcons
|
||||
|
||||
Google Icon Fonts
|
||||
https://design.google.com/icons/
|
||||
|
||||
Kenney Icon Font (Game Controller Icons)
|
||||
https://github.com/nicodinh/kenney-icon-font
|
||||
|
||||
IcoMoon - Custom Icon font builder
|
||||
https://icomoon.io/app
|
||||
|
||||
REGULAR FONTS
|
||||
|
||||
Google Noto Fonts (worldwide languages)
|
||||
https://www.google.com/get/noto/
|
||||
|
||||
Open Sans Fonts
|
||||
https://fonts.google.com/specimen/Open+Sans
|
||||
|
||||
(Japanese) M+ fonts by Coji Morishita are free
|
||||
http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html
|
||||
|
||||
MONOSPACE FONTS
|
||||
|
||||
(Pixel Perfect) Proggy Fonts, by Tristan Grimmer
|
||||
http://www.proggyfonts.net or http://upperbounds.net
|
||||
|
||||
(Pixel Perfect) Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A)
|
||||
https://github.com/kmar/Sweet16Font
|
||||
Also include .inl file to use directly in dear imgui.
|
||||
|
||||
Google Noto Mono Fonts
|
||||
https://www.google.com/get/noto/
|
||||
|
||||
Typefaces for source code beautification
|
||||
https://github.com/chrissimpkins/codeface
|
||||
|
||||
Programmation fonts
|
||||
http://s9w.github.io/font_compare/
|
||||
|
||||
Inconsolata
|
||||
http://www.levien.com/type/myfonts/inconsolata.html
|
||||
|
||||
Adobe Source Code Pro: Monospaced font family for user interface and coding environments
|
||||
https://github.com/adobe-fonts/source-code-pro
|
||||
|
||||
Monospace/Fixed Width Programmer's Fonts
|
||||
http://www.lowing.org/fonts/
|
||||
|
||||
|
||||
Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing).
|
||||
@@ -1,131 +0,0 @@
|
||||
# imgui_freetype
|
||||
|
||||
Build font atlases using FreeType instead of stb_truetype (the default imgui's font rasterizer).
|
||||
<br>by @vuhdo, @mikesart, @ocornut.
|
||||
|
||||
### Usage
|
||||
|
||||
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`).
|
||||
2. Add imgui_freetype.h/cpp alongside your imgui sources.
|
||||
3. Include imgui_freetype.h after imgui.h.
|
||||
4. Call `ImGuiFreeType::BuildFontAtlas()` *BEFORE* calling `ImFontAtlas::GetTexDataAsRGBA32()` or `ImFontAtlas::Build()` (so normal Build() won't be called):
|
||||
|
||||
```cpp
|
||||
// See ImGuiFreeType::RasterizationFlags
|
||||
unsigned int flags = ImGuiFreeType::NoHinting;
|
||||
ImGuiFreeType::BuildFontAtlas(io.Fonts, flags);
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
```
|
||||
|
||||
### Gamma Correct Blending
|
||||
|
||||
FreeType assumes blending in linear space rather than gamma space.
|
||||
See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
|
||||
For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
|
||||
The default imgui styles will be impacted by this change (alpha values will need tweaking).
|
||||
|
||||
### Test code Usage
|
||||
```cpp
|
||||
#include "misc/freetype/imgui_freetype.h"
|
||||
#include "misc/freetype/imgui_freetype.cpp"
|
||||
|
||||
// Load various small fonts
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f);
|
||||
io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f);
|
||||
io.Fonts->AddFontDefault();
|
||||
|
||||
FreeTypeTest freetype_test;
|
||||
|
||||
// Main Loop
|
||||
while (true)
|
||||
{
|
||||
if (freetype_test.UpdateRebuild())
|
||||
{
|
||||
// REUPLOAD FONT TEXTURE TO GPU
|
||||
ImGui_ImplXXX_DestroyDeviceObjects();
|
||||
ImGui_ImplXXX_CreateDeviceObjects();
|
||||
}
|
||||
ImGui::NewFrame();
|
||||
freetype_test.ShowFreetypeOptionsWindow();
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Test code
|
||||
```cpp
|
||||
#include "misc/freetype/imgui_freetype.h"
|
||||
#include "misc/freetype/imgui_freetype.cpp"
|
||||
|
||||
struct FreeTypeTest
|
||||
{
|
||||
enum FontBuildMode
|
||||
{
|
||||
FontBuildMode_FreeType,
|
||||
FontBuildMode_Stb
|
||||
};
|
||||
|
||||
FontBuildMode BuildMode;
|
||||
bool WantRebuild;
|
||||
float FontsMultiply;
|
||||
int FontsPadding;
|
||||
unsigned int FontsFlags;
|
||||
|
||||
FreeTypeTest()
|
||||
{
|
||||
BuildMode = FontBuildMode_FreeType;
|
||||
WantRebuild = true;
|
||||
FontsMultiply = 1.0f;
|
||||
FontsPadding = 1;
|
||||
FontsFlags = 0;
|
||||
}
|
||||
|
||||
// Call _BEFORE_ NewFrame()
|
||||
bool UpdateRebuild()
|
||||
{
|
||||
if (!WantRebuild)
|
||||
return false;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->TexGlyphPadding = FontsPadding;
|
||||
for (int n = 0; n < io.Fonts->ConfigData.Size; n++)
|
||||
{
|
||||
ImFontConfig* font_config = (ImFontConfig*)&io.Fonts->ConfigData[n];
|
||||
font_config->RasterizerMultiply = FontsMultiply;
|
||||
font_config->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00;
|
||||
}
|
||||
if (BuildMode == FontBuildMode_FreeType)
|
||||
ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags);
|
||||
else if (BuildMode == FontBuildMode_Stb)
|
||||
io.Fonts->Build();
|
||||
WantRebuild = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Call to draw interface
|
||||
void ShowFreetypeOptionsWindow()
|
||||
{
|
||||
ImGui::Begin("FreeType Options");
|
||||
ImGui::ShowFontSelector("Fonts");
|
||||
WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType);
|
||||
ImGui::SameLine();
|
||||
WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb);
|
||||
WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f);
|
||||
WantRebuild |= ImGui::DragInt("Padding", &FontsPadding, 0.1f, 0, 16);
|
||||
if (BuildMode == FontBuildMode_FreeType)
|
||||
{
|
||||
WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting);
|
||||
WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint);
|
||||
WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint);
|
||||
WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting);
|
||||
WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting);
|
||||
WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold);
|
||||
WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Known issues
|
||||
- `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer).
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// Wrapper to use FreeType (instead of stb_truetype) for Dear ImGui
|
||||
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
|
||||
// Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "imgui.h" // IMGUI_API, ImFontAtlas
|
||||
|
||||
namespace ImGuiFreeType
|
||||
{
|
||||
// Hinting greatly impacts visuals (and glyph sizes).
|
||||
// When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output.
|
||||
// The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
|
||||
// The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
|
||||
|
||||
// You can set those flags on a per font basis in ImFontConfig::RasterizerFlags.
|
||||
// Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts.
|
||||
enum RasterizerFlags
|
||||
{
|
||||
// By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
|
||||
NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
||||
NoAutoHint = 1 << 1, // Disable auto-hinter.
|
||||
ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
||||
LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
||||
MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
||||
Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
||||
Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style?
|
||||
};
|
||||
|
||||
IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);
|
||||
|
||||
// By default ImGuiFreeType will use IM_ALLOC()/IM_FREE().
|
||||
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired:
|
||||
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
|
||||
Natvis file to describe dear imgui types in the Visual Studio debugger.
|
||||
With this, types like ImVector<> will be displayed nicely in the debugger.
|
||||
You can include this file a Visual Studio project file, or install it in Visual Studio folder.
|
||||
@@ -0,0 +1,24 @@
|
||||
# See http://editorconfig.org to read about the EditorConfig format.
|
||||
# - In theory automatically supported by VS2017+ and most common IDE or text editors.
|
||||
# - In practice VS2019 stills gets trailing whitespaces wrong :(
|
||||
# - Suggest install to trim whitespaces: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.TrailingWhitespaceVisualizer
|
||||
# - Alternative for older VS2010 to VS2015: https://marketplace.visualstudio.com/items?itemName=EditorConfigTeam.EditorConfig
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings:
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[imstb_*]
|
||||
indent_size = 3
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2019 Omar Cornut
|
||||
Copyright (c) 2014-2021 Omar Cornut
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// COMPILE-TIME OPTIONS FOR DEAR IMGUI
|
||||
// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure.
|
||||
// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it)
|
||||
// B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template.
|
||||
//-----------------------------------------------------------------------------
|
||||
// You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp
|
||||
// files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures.
|
||||
// Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts.
|
||||
// Call IMGUI_CHECKVERSION() from your .cpp files to verify that the data structures your files are using are matching the ones imgui.cpp is using.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
// Include Platform Def to get mutliplatform AZ_DLL_IMPORT and AZ_DLL_EXPORT to use below
|
||||
#include <AzCore/PlatformDef.h>
|
||||
|
||||
//---- Define assertion handler. Defaults to calling assert().
|
||||
// If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement.
|
||||
//#define IM_ASSERT(_EXPR) MyAssert(_EXPR)
|
||||
//#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts
|
||||
|
||||
//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
|
||||
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
|
||||
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
|
||||
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
|
||||
//#define IMGUI_API __declspec( dllexport )
|
||||
//#define IMGUI_API __declspec( dllimport )
|
||||
#ifdef IMGUI_API_IMPORT
|
||||
# define IMGUI_API AZ_DLL_IMPORT
|
||||
#else
|
||||
# define IMGUI_API AZ_DLL_EXPORT
|
||||
#endif // IMGUI_API_IMPORT
|
||||
|
||||
//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names.
|
||||
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
|
||||
//---- Disable all of Dear ImGui or don't implement standard windows.
|
||||
// It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp.
|
||||
//#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty.
|
||||
//#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. Not recommended.
|
||||
//#define IMGUI_DISABLE_METRICS_WINDOW // Disable metrics/debugger window: ShowMetricsWindow() will be empty.
|
||||
|
||||
//---- Don't implement some functions to reduce linkage requirements.
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] Don't implement default IME handler. Won't use and link with ImmGetContext/ImmSetCompositionWindow. (imm32.lib/.a)
|
||||
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, ime).
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
//#define IMGUI_INCLUDE_IMGUI_USER_H
|
||||
|
||||
//---- Pack colors to BGRA8 instead of RGBA8 (to avoid converting from one to another)
|
||||
//#define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h"
|
||||
//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h"
|
||||
//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
|
||||
//---- Use stb_printf's faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined)
|
||||
// Requires 'stb_sprintf.h' to be available in the include path. Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by STB sprintf.
|
||||
// #define IMGUI_USE_STB_SPRINTF
|
||||
|
||||
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
|
||||
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
|
||||
// On Windows you may use vcpkg with 'vcpkg install freetype' + 'vcpkg integrate install'.
|
||||
//#define IMGUI_ENABLE_FREETYPE
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
// The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend.
|
||||
//#define IMGUI_ENABLE_STB_TRUETYPE
|
||||
|
||||
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
|
||||
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
|
||||
/*
|
||||
#define IM_VEC2_CLASS_EXTRA \
|
||||
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
|
||||
operator MyVec2() const { return MyVec2(x,y); }
|
||||
|
||||
#define IM_VEC4_CLASS_EXTRA \
|
||||
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
|
||||
operator MyVec4() const { return MyVec4(x,y,z,w); }
|
||||
*/
|
||||
|
||||
//---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices.
|
||||
// Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices).
|
||||
// Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer.
|
||||
// Read about ImGuiBackendFlags_RendererHasVtxOffset for details.
|
||||
//#define ImDrawIdx unsigned int
|
||||
|
||||
//---- Override ImDrawCallback signature (will need to modify renderer backends accordingly)
|
||||
//struct ImDrawList;
|
||||
//struct ImDrawCmd;
|
||||
//typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data);
|
||||
//#define ImDrawCallback MyImDrawCallback
|
||||
|
||||
//---- Debug Tools: Macro to break in Debugger
|
||||
// (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.)
|
||||
//#define IM_DEBUG_BREAK IM_ASSERT(0)
|
||||
//#define IM_DEBUG_BREAK __debugbreak()
|
||||
|
||||
//---- Debug Tools: Have the Item Picker break in the ItemAdd() function instead of ItemHoverable(),
|
||||
// (which comes earlier in the code, will catch a few extra items, allow picking items other than Hovered one.)
|
||||
// This adds a small runtime cost which is why it is not enabled by default.
|
||||
//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX
|
||||
|
||||
//---- Debug Tools: Enable slower asserts
|
||||
//#define IMGUI_DEBUG_PARANOID
|
||||
|
||||
//---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files.
|
||||
/*
|
||||
namespace ImGui
|
||||
{
|
||||
void MyFunction(const char* name, const MyMatrix44& v);
|
||||
}
|
||||
*/
|
||||
Vendored
+5300
-3675
File diff suppressed because it is too large
Load Diff
Vendored
+1250
-616
File diff suppressed because it is too large
Load Diff
+7663
File diff suppressed because it is too large
Load Diff
+1476
-654
File diff suppressed because it is too large
Load Diff
+2597
File diff suppressed because it is too large
Load Diff
+3953
File diff suppressed because it is too large
Load Diff
+2324
-1372
File diff suppressed because it is too large
Load Diff
+13
-4
@@ -1,10 +1,10 @@
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 0.99.
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_rect_pack.h 1.00.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Added STBRP__CDECL
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
|
||||
// stb_rect_pack.h - v0.99 - public domain - rectangle packing
|
||||
// stb_rect_pack.h - v1.00 - public domain - rectangle packing
|
||||
// Sean Barrett 2014
|
||||
//
|
||||
// Useful for e.g. packing rectangular textures into an atlas.
|
||||
@@ -37,9 +37,11 @@
|
||||
//
|
||||
// Bugfixes / warning fixes
|
||||
// Jeremy Jaussaud
|
||||
// Fabian Giesen
|
||||
//
|
||||
// Version history:
|
||||
//
|
||||
// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles
|
||||
// 0.99 (2019-02-07) warning fixes
|
||||
// 0.11 (2017-03-03) return packing success/fail result
|
||||
// 0.10 (2016-10-25) remove cast-away-const to avoid warnings
|
||||
@@ -357,6 +359,13 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||
width -= width % c->align;
|
||||
STBRP_ASSERT(width % c->align == 0);
|
||||
|
||||
// if it can't possibly fit, bail immediately
|
||||
if (width > c->width || height > c->height) {
|
||||
fr.prev_link = NULL;
|
||||
fr.x = fr.y = 0;
|
||||
return fr;
|
||||
}
|
||||
|
||||
node = c->active_head;
|
||||
prev = &c->active_head;
|
||||
while (node->x + width <= c->width) {
|
||||
@@ -420,7 +429,7 @@ static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int widt
|
||||
}
|
||||
STBRP_ASSERT(node->next->x > xpos && node->x <= xpos);
|
||||
y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste);
|
||||
if (y + height < c->height) {
|
||||
if (y + height <= c->height) {
|
||||
if (y <= best_y) {
|
||||
if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
|
||||
best_x = xpos;
|
||||
+56
-26
@@ -1,4 +1,4 @@
|
||||
// [DEAR IMGUI]
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_textedit.h 1.13.
|
||||
// Those changes would need to be pushed into nothings/stb:
|
||||
// - Fix in stb_textedit_discard_redo (see https://github.com/nothings/stb/issues/321)
|
||||
@@ -148,6 +148,8 @@
|
||||
// STB_TEXTEDIT_K_RIGHT keyboard input to move cursor right
|
||||
// STB_TEXTEDIT_K_UP keyboard input to move cursor up
|
||||
// STB_TEXTEDIT_K_DOWN keyboard input to move cursor down
|
||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
||||
// STB_TEXTEDIT_K_LINESTART keyboard input to move cursor to start of line // e.g. HOME
|
||||
// STB_TEXTEDIT_K_LINEEND keyboard input to move cursor to end of line // e.g. END
|
||||
// STB_TEXTEDIT_K_TEXTSTART keyboard input to move cursor to start of text // e.g. ctrl-HOME
|
||||
@@ -170,14 +172,10 @@
|
||||
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
|
||||
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
|
||||
//
|
||||
// Todo:
|
||||
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN keyboard input to move cursor down a page
|
||||
//
|
||||
// Keyboard input must be encoded as a single integer value; e.g. a character code
|
||||
// and some bitflags that represent shift states. to simplify the interface, SHIFT must
|
||||
// be a bitflag, so we can test the shifted state of cursor movements to allow selection,
|
||||
// i.e. (STB_TEXTED_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
||||
// i.e. (STB_TEXTEDIT_K_RIGHT|STB_TEXTEDIT_K_SHIFT) should be shifted right-arrow.
|
||||
//
|
||||
// You can encode other things, such as CONTROL or ALT, in additional bits, and
|
||||
// then test for their presence in e.g. STB_TEXTEDIT_K_WORDLEFT. For example,
|
||||
@@ -337,6 +335,10 @@ typedef struct
|
||||
// each textfield keeps its own insert mode state. to keep an app-wide
|
||||
// insert mode, copy this value in/out of the app state
|
||||
|
||||
int row_count_per_page;
|
||||
// page size in number of row.
|
||||
// this value MUST be set to >0 for pageup or pagedown in multilines documents.
|
||||
|
||||
/////////////////////
|
||||
//
|
||||
// private data
|
||||
@@ -855,12 +857,16 @@ retry:
|
||||
break;
|
||||
|
||||
case STB_TEXTEDIT_K_DOWN:
|
||||
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT: {
|
||||
case STB_TEXTEDIT_K_DOWN | STB_TEXTEDIT_K_SHIFT:
|
||||
case STB_TEXTEDIT_K_PGDOWN:
|
||||
case STB_TEXTEDIT_K_PGDOWN | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
StbTexteditRow row;
|
||||
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int i, j, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGDOWN;
|
||||
int row_count = is_page ? state->row_count_per_page : 1;
|
||||
|
||||
if (state->single_line) {
|
||||
if (!is_page && state->single_line) {
|
||||
// on windows, up&down in single-line behave like left&right
|
||||
key = STB_TEXTEDIT_K_RIGHT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||
goto retry;
|
||||
@@ -869,17 +875,25 @@ retry:
|
||||
if (sel)
|
||||
stb_textedit_prep_selection_at_cursor(state);
|
||||
else if (STB_TEXT_HAS_SELECTION(state))
|
||||
stb_textedit_move_to_last(str,state);
|
||||
stb_textedit_move_to_last(str, state);
|
||||
|
||||
// compute current position of cursor point
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
|
||||
// now find character position down a row
|
||||
if (find.length) {
|
||||
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
float x;
|
||||
for (j = 0; j < row_count; ++j) {
|
||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
int start = find.first_char + find.length;
|
||||
|
||||
if (find.length == 0)
|
||||
break;
|
||||
|
||||
// [DEAR IMGUI]
|
||||
// going down while being on the last line shouldn't bring us to that line end
|
||||
if (STB_TEXTEDIT_GETCHAR(str, find.first_char + find.length - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
break;
|
||||
|
||||
// now find character position down a row
|
||||
state->cursor = start;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
@@ -901,17 +915,25 @@ retry:
|
||||
|
||||
if (sel)
|
||||
state->select_end = state->cursor;
|
||||
|
||||
// go to next line
|
||||
find.first_char = find.first_char + find.length;
|
||||
find.length = row.num_chars;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case STB_TEXTEDIT_K_UP:
|
||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT: {
|
||||
case STB_TEXTEDIT_K_UP | STB_TEXTEDIT_K_SHIFT:
|
||||
case STB_TEXTEDIT_K_PGUP:
|
||||
case STB_TEXTEDIT_K_PGUP | STB_TEXTEDIT_K_SHIFT: {
|
||||
StbFindState find;
|
||||
StbTexteditRow row;
|
||||
int i, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int i, j, prev_scan, sel = (key & STB_TEXTEDIT_K_SHIFT) != 0;
|
||||
int is_page = (key & ~STB_TEXTEDIT_K_SHIFT) == STB_TEXTEDIT_K_PGUP;
|
||||
int row_count = is_page ? state->row_count_per_page : 1;
|
||||
|
||||
if (state->single_line) {
|
||||
if (!is_page && state->single_line) {
|
||||
// on windows, up&down become left&right
|
||||
key = STB_TEXTEDIT_K_LEFT | (key & STB_TEXTEDIT_K_SHIFT);
|
||||
goto retry;
|
||||
@@ -926,11 +948,14 @@ retry:
|
||||
stb_textedit_clamp(str, state);
|
||||
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
|
||||
|
||||
// can only go up if there's a previous row
|
||||
if (find.prev_first != find.first_char) {
|
||||
for (j = 0; j < row_count; ++j) {
|
||||
float x, goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
|
||||
// can only go up if there's a previous row
|
||||
if (find.prev_first == find.first_char)
|
||||
break;
|
||||
|
||||
// now find character position up a row
|
||||
float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
|
||||
float x;
|
||||
state->cursor = find.prev_first;
|
||||
STB_TEXTEDIT_LAYOUTROW(&row, str, state->cursor);
|
||||
x = row.x0;
|
||||
@@ -952,6 +977,14 @@ retry:
|
||||
|
||||
if (sel)
|
||||
state->select_end = state->cursor;
|
||||
|
||||
// go to previous line
|
||||
// (we need to scan previous line the hard way. maybe we could expose this as a new API function?)
|
||||
prev_scan = find.prev_first > 0 ? find.prev_first - 1 : 0;
|
||||
while (prev_scan > 0 && STB_TEXTEDIT_GETCHAR(str, prev_scan - 1) != STB_TEXTEDIT_NEWLINE)
|
||||
--prev_scan;
|
||||
find.first_char = find.prev_first;
|
||||
find.prev_first = prev_scan;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1075,10 +1108,6 @@ retry:
|
||||
state->has_preferred_x = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// @TODO:
|
||||
// STB_TEXTEDIT_K_PGUP - move cursor up a page
|
||||
// STB_TEXTEDIT_K_PGDOWN - move cursor down a page
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1134,7 +1163,7 @@ static void stb_textedit_discard_redo(StbUndoState *state)
|
||||
state->undo_rec[i].char_storage += n;
|
||||
}
|
||||
// now move all the redo records towards the end of the buffer; the first one is at 'redo_point'
|
||||
// {DEAR IMGUI]
|
||||
// [DEAR IMGUI]
|
||||
size_t move_size = (size_t)((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point - 1) * sizeof(state->undo_rec[0]));
|
||||
const char* buf_begin = (char*)state->undo_rec; (void)buf_begin;
|
||||
const char* buf_end = (char*)state->undo_rec + sizeof(state->undo_rec); (void)buf_end;
|
||||
@@ -1350,6 +1379,7 @@ static void stb_textedit_clear_state(STB_TexteditState *state, int is_single_lin
|
||||
state->initialized = 1;
|
||||
state->single_line = (unsigned char) is_single_line;
|
||||
state->insert_mode = 0;
|
||||
state->row_count_per_page = 0;
|
||||
}
|
||||
|
||||
// API initialize
|
||||
+25
-25
@@ -1,4 +1,4 @@
|
||||
// [DEAR IMGUI]
|
||||
// [DEAR IMGUI]
|
||||
// This is a slightly modified version of stb_truetype.h 1.20.
|
||||
// Mostly fixing for compiler and static analyzer warnings.
|
||||
// Grep for [DEAR IMGUI] to find the changes.
|
||||
@@ -2538,11 +2538,11 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i
|
||||
// There are no other cases.
|
||||
STBTT_assert(0);
|
||||
break;
|
||||
};
|
||||
} // [DEAR IMGUI] removed ;
|
||||
}
|
||||
}
|
||||
break;
|
||||
};
|
||||
} // [DEAR IMGUI] removed ;
|
||||
|
||||
default:
|
||||
// TODO: Implement other stuff.
|
||||
@@ -4132,7 +4132,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect
|
||||
STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges)
|
||||
{
|
||||
stbtt_fontinfo info;
|
||||
int i,j,n, return_value = 1;
|
||||
int i,j,n, return_value; // [DEAR IMGUI] removed = 1
|
||||
//stbrp_context *context = (stbrp_context *) spc->pack_info;
|
||||
stbrp_rect *rects;
|
||||
|
||||
@@ -4302,7 +4302,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex
|
||||
int winding = 0;
|
||||
|
||||
orig[0] = x;
|
||||
//orig[1] = y; // [DEAR IMGUI] commmented double assignment
|
||||
//orig[1] = y; // [DEAR IMGUI] commented double assignment
|
||||
|
||||
// make sure y never passes through a vertex of the shape
|
||||
y_frac = (float) STBTT_fmod(y, 1.0f);
|
||||
@@ -4374,32 +4374,32 @@ static float stbtt__cuberoot( float x )
|
||||
// x^3 + c*x^2 + b*x + a = 0
|
||||
static int stbtt__solve_cubic(float a, float b, float c, float* r)
|
||||
{
|
||||
float s = -a / 3;
|
||||
float p = b - a*a / 3;
|
||||
float q = a * (2*a*a - 9*b) / 27 + c;
|
||||
float s = -a / 3;
|
||||
float p = b - a*a / 3;
|
||||
float q = a * (2*a*a - 9*b) / 27 + c;
|
||||
float p3 = p*p*p;
|
||||
float d = q*q + 4*p3 / 27;
|
||||
if (d >= 0) {
|
||||
float z = (float) STBTT_sqrt(d);
|
||||
float u = (-q + z) / 2;
|
||||
float v = (-q - z) / 2;
|
||||
u = stbtt__cuberoot(u);
|
||||
v = stbtt__cuberoot(v);
|
||||
r[0] = s + u + v;
|
||||
return 1;
|
||||
} else {
|
||||
float u = (float) STBTT_sqrt(-p/3);
|
||||
float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
|
||||
float m = (float) STBTT_cos(v);
|
||||
float d = q*q + 4*p3 / 27;
|
||||
if (d >= 0) {
|
||||
float z = (float) STBTT_sqrt(d);
|
||||
float u = (-q + z) / 2;
|
||||
float v = (-q - z) / 2;
|
||||
u = stbtt__cuberoot(u);
|
||||
v = stbtt__cuberoot(v);
|
||||
r[0] = s + u + v;
|
||||
return 1;
|
||||
} else {
|
||||
float u = (float) STBTT_sqrt(-p/3);
|
||||
float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative
|
||||
float m = (float) STBTT_cos(v);
|
||||
float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f;
|
||||
r[0] = s + u * 2 * m;
|
||||
r[1] = s - u * (m + n);
|
||||
r[2] = s - u * (m - n);
|
||||
r[0] = s + u * 2 * m;
|
||||
r[1] = s - u * (m + n);
|
||||
r[2] = s - u * (m - n);
|
||||
|
||||
//STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe?
|
||||
//STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f);
|
||||
//STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f);
|
||||
return 3;
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -3,6 +3,10 @@ misc/cpp/
|
||||
InputText() wrappers for C++ standard library (STL) type: std::string.
|
||||
This is also an example of how you may wrap your own similar types.
|
||||
|
||||
misc/debuggers/
|
||||
Helper files for popular debuggers.
|
||||
With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger.
|
||||
|
||||
misc/fonts/
|
||||
Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts).
|
||||
Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code.
|
||||
@@ -12,7 +16,8 @@ misc/freetype/
|
||||
Font atlas builder/rasterizer using FreeType instead of stb_truetype.
|
||||
Benefit from better FreeType rasterization, in particular for small fonts.
|
||||
|
||||
misc/natvis/
|
||||
Natvis file to describe dear imgui types in the Visual Studio debugger.
|
||||
With this, types like ImVector<> will be displayed nicely in the debugger.
|
||||
You can include this file a Visual Studio project file, or install it in Visual Studio folder.
|
||||
misc/single_file/
|
||||
Single-file header stub.
|
||||
We use this to validate compiling all *.cpp files in a same compilation unit.
|
||||
Users of that technique (also called "Unity builds") can generally provide this themselves,
|
||||
so we don't really recommend you use this in your projects.
|
||||
+1
-1
@@ -5,6 +5,6 @@ imgui_stdlib.h + imgui_stdlib.cpp
|
||||
|
||||
imgui_scoped.h
|
||||
[Experimental, not currently in main repository]
|
||||
Additional header file with some RAII-style wrappers for common ImGui functions.
|
||||
Additional header file with some RAII-style wrappers for common Dear ImGui functions.
|
||||
Try by merging: https://github.com/ocornut/imgui/pull/2197
|
||||
Discuss at: https://github.com/ocornut/imgui/issues/2096
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// imgui_stdlib.cpp
|
||||
// Wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Compatibility:
|
||||
+1
-2
@@ -1,5 +1,4 @@
|
||||
// imgui_stdlib.h
|
||||
// Wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
|
||||
// This is also an example of how you may wrap your own similar types.
|
||||
|
||||
// Compatibility:
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
HELPER FILES FOR POPULAR DEBUGGERS
|
||||
|
||||
imgui.gdb
|
||||
GDB: disable stepping into trivial functions.
|
||||
(read comments inside file for details)
|
||||
|
||||
imgui.natstepfilter
|
||||
Visual Studio Debugger: disable stepping into trivial functions.
|
||||
(read comments inside file for details)
|
||||
|
||||
imgui.natvis
|
||||
Visual Studio Debugger: describe Dear ImGui types for better display.
|
||||
With this, types like ImVector<> will be displayed nicely in the debugger.
|
||||
(read comments inside file for details)
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
# GDB configuration to aid debugging experience
|
||||
|
||||
# To enable these customizations edit $HOME/.gdbinit (or ./.gdbinit if local gdbinit is enabled) and add:
|
||||
# add-auto-load-safe-path /path/to/imgui.gdb
|
||||
# source /path/to/imgui.gdb
|
||||
#
|
||||
# More Information at:
|
||||
# * https://sourceware.org/gdb/current/onlinedocs/gdb/gdbinit-man.html
|
||||
# * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory
|
||||
|
||||
# Disable stepping into trivial functions
|
||||
skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
.natstepfilter file for Visual Studio debugger.
|
||||
Purpose: instruct debugger to skip some functions when using StepInto (F11)
|
||||
|
||||
To enable:
|
||||
* copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
|
||||
* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
|
||||
If you have multiple VS version installed, the version that matters is the one you are using the IDE/debugger of (not the compiling toolset).
|
||||
This is supported since Visual Studio 2012.
|
||||
|
||||
Unfortunately, unlike .natvis files, it isn't yet possible to include this file in your project :(
|
||||
You may upvote this: https://developercommunity.visualstudio.com/t/allow-natstepfilter-and-natjmc-to-be-included-as-p/561718
|
||||
|
||||
More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2019#BKMK_C___Just_My_Code
|
||||
-->
|
||||
|
||||
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
|
||||
|
||||
<!-- Disable stepping into trivial functions -->
|
||||
<Function>
|
||||
<Name>(ImVec2|ImVec4|ImStrv)::.+</Name>
|
||||
<Action>NoStepInto</Action>
|
||||
</Function>
|
||||
<Function>
|
||||
<Name>(ImVector|ImSpan).*::operator.+</Name>
|
||||
<Action>NoStepInto</Action>
|
||||
</Function>
|
||||
|
||||
</StepFilter>
|
||||
+22
-3
@@ -1,6 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
.natvis file for Visual Studio debugger.
|
||||
Purpose: provide nicer views on data types used by Dear ImGui.
|
||||
|
||||
<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) -->
|
||||
To enable:
|
||||
* include file in your VS project (most recommended: not intrusive and always kept up to date!)
|
||||
* or copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
|
||||
* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
|
||||
|
||||
More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019
|
||||
-->
|
||||
|
||||
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
|
||||
|
||||
@@ -14,6 +23,16 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="ImSpan<*>">
|
||||
<DisplayString>{{Size={DataEnd-Data} }}</DisplayString>
|
||||
<Expand>
|
||||
<ArrayItems>
|
||||
<Size>DataEnd-Data</Size>
|
||||
<ValuePointer>Data</ValuePointer>
|
||||
</ArrayItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="ImVec2">
|
||||
<DisplayString>{{x={x,g} y={y,g}}}</DisplayString>
|
||||
</Type>
|
||||
@@ -35,5 +54,5 @@
|
||||
<Type Name="ImGuiWindow">
|
||||
<DisplayString>{{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}}</DisplayString>
|
||||
</Type>
|
||||
|
||||
</AutoVisualizer>
|
||||
|
||||
</AutoVisualizer>
|
||||
+19
-14
@@ -1,15 +1,17 @@
|
||||
// ImGui - binary_to_compressed_c.cpp
|
||||
// dear imgui
|
||||
// (binary_to_compressed_c.cpp)
|
||||
// Helper tool to turn a file into a C array, if you want to embed font data in your source code.
|
||||
|
||||
// The data is first compressed with stb_compress() to reduce source code size,
|
||||
// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
|
||||
// (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
|
||||
// (If we used 32-bit constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
|
||||
// Note that even with compression, the output array is likely to be bigger than the binary file..
|
||||
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
|
||||
|
||||
// Build with, e.g:
|
||||
// # cl.exe binary_to_compressed_c.cpp
|
||||
// # gcc binary_to_compressed_c.cpp
|
||||
// # g++ binary_to_compressed_c.cpp
|
||||
// # clang++ binary_to_compressed_c.cpp
|
||||
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
|
||||
|
||||
// Usage:
|
||||
@@ -27,7 +29,7 @@
|
||||
// stb_compress* from stb.h - declaration
|
||||
typedef unsigned int stb_uint;
|
||||
typedef unsigned char stb_uchar;
|
||||
stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len);
|
||||
stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len);
|
||||
|
||||
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression);
|
||||
|
||||
@@ -48,18 +50,21 @@ int main(int argc, char** argv)
|
||||
else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
|
||||
else
|
||||
{
|
||||
printf("Unknown argument: '%s'\n", argv[argn]);
|
||||
fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression) ? 0 : 1;
|
||||
bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression);
|
||||
if (!ret)
|
||||
fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
|
||||
return ret ? 0 : 1;
|
||||
}
|
||||
|
||||
char Encode85Byte(unsigned int x)
|
||||
{
|
||||
x = (x % 85) + 35;
|
||||
return (x>='\\') ? x+1 : x;
|
||||
return (x >= '\\') ? x + 1 : x;
|
||||
}
|
||||
|
||||
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression)
|
||||
@@ -69,7 +74,7 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
if (!f) return false;
|
||||
int data_sz;
|
||||
if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; }
|
||||
char* data = new char[data_sz+4];
|
||||
char* data = new char[data_sz + 4];
|
||||
if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; }
|
||||
memset((void*)(((char*)data) + data_sz), 0, 4);
|
||||
fclose(f);
|
||||
@@ -79,16 +84,16 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
char* compressed = use_compression ? new char[maxlen] : data;
|
||||
int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz;
|
||||
if (use_compression)
|
||||
memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
|
||||
memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
|
||||
|
||||
// Output as Base85 encoded
|
||||
FILE* out = stdout;
|
||||
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
|
||||
fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
|
||||
const char* compressed_str = use_compression ? "compressed_" : "";
|
||||
const char* compressed_str = use_compression ? "compressed_" : "";
|
||||
if (use_base85_encoding)
|
||||
{
|
||||
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz+3)/4)*5);
|
||||
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
|
||||
char prev_c = 0;
|
||||
for (int src_i = 0; src_i < compressed_sz; src_i += 4)
|
||||
{
|
||||
@@ -100,7 +105,7 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c);
|
||||
prev_c = c;
|
||||
}
|
||||
if ((src_i % 112) == 112-4)
|
||||
if ((src_i % 112) == 112 - 4)
|
||||
fprintf(out, "\"\n \"");
|
||||
}
|
||||
fprintf(out, "\";\n\n");
|
||||
@@ -108,7 +113,7 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
else
|
||||
{
|
||||
fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz);
|
||||
fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz+3)/4)*4);
|
||||
fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
|
||||
int column = 0;
|
||||
for (int i = 0; i < compressed_sz; i += 4)
|
||||
{
|
||||
@@ -124,7 +129,7 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
|
||||
// Cleanup
|
||||
delete[] data;
|
||||
if (use_compression)
|
||||
delete[] compressed;
|
||||
delete[] compressed;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# imgui_freetype
|
||||
|
||||
Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer).
|
||||
<br>by @vuhdo, @mikesart, @ocornut.
|
||||
|
||||
### Usage
|
||||
|
||||
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`, `vcpkg integrate install`).
|
||||
2. Add imgui_freetype.h/cpp alongside your project files.
|
||||
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file
|
||||
|
||||
### About Gamma Correct Blending
|
||||
|
||||
FreeType assumes blending in linear space rather than gamma space.
|
||||
See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
|
||||
For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
|
||||
The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking).
|
||||
|
||||
### Testbed for toying with settings (for developers)
|
||||
|
||||
See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad
|
||||
|
||||
### Known issues
|
||||
|
||||
- Oversampling settins are ignored but also not so much necessary with the higher quality rendering.
|
||||
|
||||
### Comparaison
|
||||
|
||||
Small, thin anti-aliased fonts are typically benefiting a lots from Freetype's hinting:
|
||||

|
||||
+239
-110
@@ -1,23 +1,33 @@
|
||||
// Wrapper to use FreeType (instead of stb_truetype) for Dear ImGui
|
||||
// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
|
||||
// (code)
|
||||
|
||||
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
|
||||
// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained and v0.60+ by @ocornut.
|
||||
// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut.
|
||||
|
||||
// Changelog:
|
||||
// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks.
|
||||
// - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply.
|
||||
// - v0.52: (2017/09/26) fixes for imgui internal changes.
|
||||
// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement).
|
||||
// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member.
|
||||
// - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club)
|
||||
// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
|
||||
// - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
|
||||
// - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
|
||||
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
|
||||
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
|
||||
// 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'.
|
||||
// renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas().
|
||||
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
|
||||
// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
|
||||
// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
|
||||
// 2019/01/10: re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
|
||||
// 2018/06/08: added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
|
||||
// 2018/02/04: moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club)
|
||||
// 2018/01/22: fix for addition of ImFontAtlas::TexUvscale member.
|
||||
// 2017/10/22: minor inconsequential change to match change in master (removed an unnecessary statement).
|
||||
// 2017/09/26: fixes for imgui internal changes.
|
||||
// 2017/08/26: cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply.
|
||||
// 2017/08/16: imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks.
|
||||
|
||||
// Gamma Correct Blending:
|
||||
// FreeType assumes blending in linear space rather than gamma space.
|
||||
// See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph
|
||||
// For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
|
||||
// The default imgui styles will be impacted by this change (alpha values will need tweaking).
|
||||
// About Gamma Correct Blending:
|
||||
// - FreeType assumes blending in linear space rather than gamma space.
|
||||
// - See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph
|
||||
// - For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
|
||||
// - The default dear imgui styles will be impacted by this change (alpha values will need tweaking).
|
||||
|
||||
// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
|
||||
|
||||
@@ -35,9 +45,27 @@
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
|
||||
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Data
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// Default memory allocators
|
||||
static void* ImGuiFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
|
||||
static void ImGuiFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
|
||||
|
||||
// Current memory allocators
|
||||
static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFreeTypeDefaultAllocFunc;
|
||||
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
|
||||
static void* GImGuiFreeTypeAllocatorUserData = NULL;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Code
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
// Glyph metrics:
|
||||
@@ -71,7 +99,7 @@ namespace
|
||||
// | |
|
||||
// |------------- advanceX ----------->|
|
||||
|
||||
/// A structure that describe a glyph.
|
||||
// A structure that describe a glyph.
|
||||
struct GlyphInfo
|
||||
{
|
||||
int Width; // Glyph's width in pixels.
|
||||
@@ -79,6 +107,7 @@ namespace
|
||||
FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph.
|
||||
FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0.
|
||||
float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
|
||||
bool IsColored; // The glyph is colored
|
||||
};
|
||||
|
||||
// Font parameters and metrics.
|
||||
@@ -101,7 +130,7 @@ namespace
|
||||
void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size
|
||||
const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
|
||||
const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
|
||||
void BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
|
||||
void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
|
||||
~FreeTypeFont() { CloseFont(); }
|
||||
|
||||
// [Internals]
|
||||
@@ -109,12 +138,13 @@ namespace
|
||||
FT_Face Face;
|
||||
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
|
||||
FT_Int32 LoadFlags;
|
||||
FT_Render_Mode RenderMode;
|
||||
};
|
||||
|
||||
// From SDL_ttf: Handy routines for converting from fixed point
|
||||
#define FT_CEIL(X) (((X + 63) & -64) / 64)
|
||||
|
||||
bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags)
|
||||
bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags)
|
||||
{
|
||||
FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face);
|
||||
if (error != 0)
|
||||
@@ -123,25 +153,37 @@ namespace
|
||||
if (error != 0)
|
||||
return false;
|
||||
|
||||
memset(&Info, 0, sizeof(Info));
|
||||
SetPixelHeight((uint32_t)cfg.SizePixels);
|
||||
|
||||
// Convert to FreeType flags (NB: Bold and Oblique are processed separately)
|
||||
UserFlags = cfg.RasterizerFlags | extra_user_flags;
|
||||
LoadFlags = FT_LOAD_NO_BITMAP;
|
||||
if (UserFlags & ImGuiFreeType::NoHinting)
|
||||
UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags;
|
||||
|
||||
LoadFlags = 0;
|
||||
if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0)
|
||||
LoadFlags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting)
|
||||
LoadFlags |= FT_LOAD_NO_HINTING;
|
||||
if (UserFlags & ImGuiFreeType::NoAutoHint)
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint)
|
||||
LoadFlags |= FT_LOAD_NO_AUTOHINT;
|
||||
if (UserFlags & ImGuiFreeType::ForceAutoHint)
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint)
|
||||
LoadFlags |= FT_LOAD_FORCE_AUTOHINT;
|
||||
if (UserFlags & ImGuiFreeType::LightHinting)
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_LightHinting)
|
||||
LoadFlags |= FT_LOAD_TARGET_LIGHT;
|
||||
else if (UserFlags & ImGuiFreeType::MonoHinting)
|
||||
else if (UserFlags & ImGuiFreeTypeBuilderFlags_MonoHinting)
|
||||
LoadFlags |= FT_LOAD_TARGET_MONO;
|
||||
else
|
||||
LoadFlags |= FT_LOAD_TARGET_NORMAL;
|
||||
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_Monochrome)
|
||||
RenderMode = FT_RENDER_MODE_MONO;
|
||||
else
|
||||
RenderMode = FT_RENDER_MODE_NORMAL;
|
||||
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
|
||||
LoadFlags |= FT_LOAD_COLOR;
|
||||
|
||||
memset(&Info, 0, sizeof(Info));
|
||||
SetPixelHeight((uint32_t)cfg.SizePixels);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -160,7 +202,7 @@ namespace
|
||||
// is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
|
||||
// NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result.
|
||||
FT_Size_RequestRec req;
|
||||
req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
||||
req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
|
||||
req.width = 0;
|
||||
req.height = (uint32_t)pixel_height * 64;
|
||||
req.horiResolution = 0;
|
||||
@@ -188,12 +230,12 @@ namespace
|
||||
|
||||
// Need an outline for this to work
|
||||
FT_GlyphSlot slot = Face->glyph;
|
||||
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE);
|
||||
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
|
||||
|
||||
// Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
|
||||
if (UserFlags & ImGuiFreeType::Bold)
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
|
||||
FT_GlyphSlot_Embolden(slot);
|
||||
if (UserFlags & ImGuiFreeType::Oblique)
|
||||
if (UserFlags & ImGuiFreeTypeBuilderFlags_Oblique)
|
||||
{
|
||||
FT_GlyphSlot_Oblique(slot);
|
||||
//FT_BBox bbox;
|
||||
@@ -208,7 +250,7 @@ namespace
|
||||
const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
|
||||
{
|
||||
FT_GlyphSlot slot = Face->glyph;
|
||||
FT_Error error = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
|
||||
FT_Error error = FT_Render_Glyph(slot, RenderMode);
|
||||
if (error != 0)
|
||||
return NULL;
|
||||
|
||||
@@ -218,11 +260,12 @@ namespace
|
||||
out_glyph_info->OffsetX = Face->glyph->bitmap_left;
|
||||
out_glyph_info->OffsetY = -Face->glyph->bitmap_top;
|
||||
out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x);
|
||||
out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA);
|
||||
|
||||
return ft_bitmap;
|
||||
}
|
||||
|
||||
void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
|
||||
void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
|
||||
{
|
||||
IM_ASSERT(ft_bitmap != NULL);
|
||||
const uint32_t w = ft_bitmap->width;
|
||||
@@ -230,32 +273,94 @@ namespace
|
||||
const uint8_t* src = ft_bitmap->buffer;
|
||||
const uint32_t src_pitch = ft_bitmap->pitch;
|
||||
|
||||
if (multiply_table == NULL)
|
||||
switch (ft_bitmap->pixel_mode)
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
memcpy(dst, src, w);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
dst[x] = multiply_table[src[x]];
|
||||
case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
|
||||
{
|
||||
if (multiply_table == NULL)
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
dst[x] = IM_COL32(255, 255, 255, src[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
|
||||
{
|
||||
uint8_t color0 = multiply_table ? multiply_table[0] : 0;
|
||||
uint8_t color1 = multiply_table ? multiply_table[255] : 255;
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
{
|
||||
uint8_t bits = 0;
|
||||
const uint8_t* bits_ptr = src;
|
||||
for (uint32_t x = 0; x < w; x++, bits <<= 1)
|
||||
{
|
||||
if ((x & 7) == 0)
|
||||
bits = *bits_ptr++;
|
||||
dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FT_PIXEL_MODE_BGRA:
|
||||
{
|
||||
// FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good.
|
||||
#define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
|
||||
if (multiply_table == NULL)
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
{
|
||||
uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
|
||||
dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
|
||||
{
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
{
|
||||
uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3];
|
||||
dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DE_MULTIPLY
|
||||
break;
|
||||
}
|
||||
default:
|
||||
IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
|
||||
#define STBRP_ASSERT(x) IM_ASSERT(x)
|
||||
#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
|
||||
#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
|
||||
#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0)
|
||||
#define STBRP_STATIC
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#endif
|
||||
#ifdef IMGUI_STB_RECT_PACK_FILENAME
|
||||
#include IMGUI_STB_RECT_PACK_FILENAME
|
||||
#else
|
||||
#include "imstb_rectpack.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct ImFontBuildSrcGlyphFT
|
||||
{
|
||||
GlyphInfo Info;
|
||||
uint32_t Codepoint;
|
||||
unsigned char* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
|
||||
unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
|
||||
|
||||
ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
struct ImFontBuildSrcDataFT
|
||||
@@ -266,7 +371,7 @@ struct ImFontBuildSrcDataFT
|
||||
int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[]
|
||||
int GlyphsHighest; // Highest requested codepoint
|
||||
int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font)
|
||||
ImBoolVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB)
|
||||
ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB)
|
||||
ImVector<ImFontBuildSrcGlyphFT> GlyphsList;
|
||||
};
|
||||
|
||||
@@ -276,14 +381,14 @@ struct ImFontBuildDstDataFT
|
||||
int SrcCount; // Number of source fonts targeting this destination font.
|
||||
int GlyphsHighest;
|
||||
int GlyphsCount;
|
||||
ImBoolVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font.
|
||||
ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font.
|
||||
};
|
||||
|
||||
bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags)
|
||||
bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags)
|
||||
{
|
||||
IM_ASSERT(atlas->ConfigData.Size > 0);
|
||||
|
||||
ImFontAtlasBuildRegisterDefaultCustomRects(atlas);
|
||||
ImFontAtlasBuildInit(atlas);
|
||||
|
||||
// Clear atlas
|
||||
atlas->TexID = (ImTextureID)NULL;
|
||||
@@ -293,12 +398,13 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
atlas->ClearTexData();
|
||||
|
||||
// Temporary storage for building
|
||||
bool src_load_color = false;
|
||||
ImVector<ImFontBuildSrcDataFT> src_tmp_array;
|
||||
ImVector<ImFontBuildDstDataFT> dst_tmp_array;
|
||||
src_tmp_array.resize(atlas->ConfigData.Size);
|
||||
dst_tmp_array.resize(atlas->Fonts.Size);
|
||||
memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
|
||||
memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
|
||||
memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
|
||||
memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
|
||||
|
||||
// 1. Initialize font loading structure, check font data validity
|
||||
for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
|
||||
@@ -322,6 +428,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
return false;
|
||||
|
||||
// Measure highest codepoints
|
||||
src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0;
|
||||
ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
|
||||
src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
|
||||
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
|
||||
@@ -336,14 +443,14 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
{
|
||||
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
|
||||
ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
|
||||
src_tmp.GlyphsSet.Resize(src_tmp.GlyphsHighest + 1);
|
||||
src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1);
|
||||
if (dst_tmp.GlyphsSet.Storage.empty())
|
||||
dst_tmp.GlyphsSet.Resize(dst_tmp.GlyphsHighest + 1);
|
||||
dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1);
|
||||
|
||||
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
|
||||
for (int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
|
||||
for (int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++)
|
||||
{
|
||||
if (dst_tmp.GlyphsSet.GetBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
|
||||
if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
|
||||
continue;
|
||||
uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..)
|
||||
if (glyph_index == 0)
|
||||
@@ -352,8 +459,8 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
// Add to avail set/counters
|
||||
src_tmp.GlyphsCount++;
|
||||
dst_tmp.GlyphsCount++;
|
||||
src_tmp.GlyphsSet.SetBit(codepoint, true);
|
||||
dst_tmp.GlyphsSet.SetBit(codepoint, true);
|
||||
src_tmp.GlyphsSet.SetBit(codepoint);
|
||||
dst_tmp.GlyphsSet.SetBit(codepoint);
|
||||
total_glyphs_count++;
|
||||
}
|
||||
}
|
||||
@@ -364,16 +471,15 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
|
||||
src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount);
|
||||
|
||||
IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(int));
|
||||
const int* it_begin = src_tmp.GlyphsSet.Storage.begin();
|
||||
const int* it_end = src_tmp.GlyphsSet.Storage.end();
|
||||
for (const int* it = it_begin; it < it_end; it++)
|
||||
if (int entries_32 = *it)
|
||||
for (int bit_n = 0; bit_n < 32; bit_n++)
|
||||
if (entries_32 & (1 << bit_n))
|
||||
IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32));
|
||||
const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin();
|
||||
const ImU32* it_end = src_tmp.GlyphsSet.Storage.end();
|
||||
for (const ImU32* it = it_begin; it < it_end; it++)
|
||||
if (ImU32 entries_32 = *it)
|
||||
for (ImU32 bit_n = 0; bit_n < 32; bit_n++)
|
||||
if (entries_32 & ((ImU32)1 << bit_n))
|
||||
{
|
||||
ImFontBuildSrcGlyphFT src_glyph;
|
||||
memset(&src_glyph, 0, sizeof(src_glyph));
|
||||
src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n);
|
||||
//src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
|
||||
src_tmp.GlyphsList.push_back(src_glyph);
|
||||
@@ -427,7 +533,6 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
|
||||
|
||||
const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint);
|
||||
IM_ASSERT(metrics != NULL);
|
||||
if (metrics == NULL)
|
||||
continue;
|
||||
|
||||
@@ -436,7 +541,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
IM_ASSERT(ft_bitmap);
|
||||
|
||||
// Allocate new temporary chunk if needed
|
||||
const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height;
|
||||
const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4;
|
||||
if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
|
||||
{
|
||||
buf_bitmap_current_used_bytes = 0;
|
||||
@@ -444,9 +549,9 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
}
|
||||
|
||||
// Blit rasterized pixels to our temporary buffer and keep a pointer to it.
|
||||
src_glyph.BitmapData = buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes;
|
||||
src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes);
|
||||
buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
|
||||
src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width * 1, multiply_enabled ? multiply_table : NULL);
|
||||
src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : NULL);
|
||||
|
||||
src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
|
||||
src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
|
||||
@@ -462,7 +567,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
if (atlas->TexDesiredWidth > 0)
|
||||
atlas->TexWidth = atlas->TexDesiredWidth;
|
||||
else
|
||||
atlas->TexWidth = (surface_sqrt >= 4096*0.7f) ? 4096 : (surface_sqrt >= 2048*0.7f) ? 2048 : (surface_sqrt >= 1024*0.7f) ? 1024 : 512;
|
||||
atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
|
||||
|
||||
// 5. Start packing
|
||||
// Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
|
||||
@@ -493,25 +598,37 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
// 7. Allocate texture
|
||||
atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
|
||||
atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
|
||||
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
|
||||
if (src_load_color)
|
||||
{
|
||||
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight * 4);
|
||||
memset(atlas->TexPixelsRGBA32, 0, atlas->TexWidth * atlas->TexHeight * 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
|
||||
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
|
||||
}
|
||||
|
||||
// 8. Copy rasterized font characters back into the main texture
|
||||
// 9. Setup ImFont and glyphs for runtime
|
||||
bool tex_use_colors = false;
|
||||
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
|
||||
{
|
||||
ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
|
||||
if (src_tmp.GlyphsCount == 0)
|
||||
continue;
|
||||
|
||||
// When merging fonts with MergeMode=true:
|
||||
// - We can have multiple input fonts writing into a same destination font.
|
||||
// - dst_font->ConfigData is != from cfg which is our source configuration.
|
||||
ImFontConfig& cfg = atlas->ConfigData[src_i];
|
||||
ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)
|
||||
ImFont* dst_font = cfg.DstFont;
|
||||
|
||||
const float ascent = src_tmp.Font.Info.Ascender;
|
||||
const float descent = src_tmp.Font.Info.Descender;
|
||||
ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
|
||||
const float font_off_x = cfg.GlyphOffset.x;
|
||||
const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);
|
||||
const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
|
||||
|
||||
const int padding = atlas->TexGlyphPadding;
|
||||
for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
|
||||
@@ -519,6 +636,8 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
|
||||
stbrp_rect& pack_rect = src_tmp.Rects[glyph_i];
|
||||
IM_ASSERT(pack_rect.was_packed);
|
||||
if (pack_rect.w == 0 && pack_rect.h == 0)
|
||||
continue;
|
||||
|
||||
GlyphInfo& info = src_glyph.Info;
|
||||
IM_ASSERT(info.Width + padding <= pack_rect.w);
|
||||
@@ -529,19 +648,24 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
// Blit from temporary buffer to final texture
|
||||
size_t blit_src_stride = (size_t)src_glyph.Info.Width;
|
||||
size_t blit_dst_stride = (size_t)atlas->TexWidth;
|
||||
unsigned char* blit_src = src_glyph.BitmapData;
|
||||
unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
|
||||
for (int y = info.Height; y > 0; y--, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
|
||||
memcpy(blit_dst, blit_src, blit_src_stride);
|
||||
|
||||
float char_advance_x_org = info.AdvanceX;
|
||||
float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
|
||||
float char_off_x = font_off_x;
|
||||
if (char_advance_x_org != char_advance_x_mod)
|
||||
char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
|
||||
unsigned int* blit_src = src_glyph.BitmapData;
|
||||
if (atlas->TexPixelsAlpha8 != NULL)
|
||||
{
|
||||
unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
|
||||
for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
|
||||
for (int x = 0; x < info.Width; x++)
|
||||
blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx;
|
||||
for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
|
||||
for (int x = 0; x < info.Width; x++)
|
||||
blit_dst[x] = blit_src[x];
|
||||
}
|
||||
|
||||
// Register glyph
|
||||
float x0 = info.OffsetX + char_off_x;
|
||||
float x0 = info.OffsetX + font_off_x;
|
||||
float y0 = info.OffsetY + font_off_y;
|
||||
float x1 = x0 + info.Width;
|
||||
float y1 = y0 + info.Height;
|
||||
@@ -549,11 +673,17 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
float v0 = (ty) / (float)atlas->TexHeight;
|
||||
float u1 = (tx + info.Width) / (float)atlas->TexWidth;
|
||||
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
|
||||
dst_font->AddGlyph((ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, char_advance_x_mod);
|
||||
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
|
||||
|
||||
ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
|
||||
IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
|
||||
if (src_glyph.Info.IsColored)
|
||||
dst_glyph->Colored = tex_use_colors = true;
|
||||
}
|
||||
|
||||
src_tmp.Rects = NULL;
|
||||
}
|
||||
atlas->TexPixelsUseColors = tex_use_colors;
|
||||
|
||||
// Cleanup
|
||||
for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
|
||||
@@ -566,53 +696,45 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
return true;
|
||||
}
|
||||
|
||||
// Default memory allocators
|
||||
static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
|
||||
static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
|
||||
|
||||
// Current memory allocators
|
||||
static void* (*GImFreeTypeAllocFunc)(size_t size, void* user_data) = ImFreeTypeDefaultAllocFunc;
|
||||
static void (*GImFreeTypeFreeFunc)(void* ptr, void* user_data) = ImFreeTypeDefaultFreeFunc;
|
||||
static void* GImFreeTypeAllocatorUserData = NULL;
|
||||
|
||||
// FreeType memory allocation callbacks
|
||||
static void* FreeType_Alloc(FT_Memory /*memory*/, long size)
|
||||
{
|
||||
return GImFreeTypeAllocFunc((size_t)size, GImFreeTypeAllocatorUserData);
|
||||
return GImGuiFreeTypeAllocFunc((size_t)size, GImGuiFreeTypeAllocatorUserData);
|
||||
}
|
||||
|
||||
static void FreeType_Free(FT_Memory /*memory*/, void* block)
|
||||
{
|
||||
GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData);
|
||||
GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
|
||||
}
|
||||
|
||||
static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block)
|
||||
{
|
||||
// Implement realloc() as we don't ask user to provide it.
|
||||
if (block == NULL)
|
||||
return GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData);
|
||||
return GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData);
|
||||
|
||||
if (new_size == 0)
|
||||
{
|
||||
GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData);
|
||||
GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (new_size > cur_size)
|
||||
{
|
||||
void* new_block = GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData);
|
||||
void* new_block = GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData);
|
||||
memcpy(new_block, block, (size_t)cur_size);
|
||||
GImFreeTypeFreeFunc(block, GImFreeTypeAllocatorUserData);
|
||||
GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
|
||||
return new_block;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
|
||||
static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
|
||||
{
|
||||
// FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
|
||||
FT_MemoryRec_ memory_rec = { 0 };
|
||||
FT_MemoryRec_ memory_rec = {};
|
||||
memory_rec.user = NULL;
|
||||
memory_rec.alloc = &FreeType_Alloc;
|
||||
memory_rec.free = &FreeType_Free;
|
||||
memory_rec.realloc = &FreeType_Realloc;
|
||||
@@ -626,15 +748,22 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
|
||||
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
|
||||
FT_Add_Default_Modules(ft_library);
|
||||
|
||||
bool ret = ImFontAtlasBuildWithFreeType(ft_library, atlas, extra_flags);
|
||||
bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
|
||||
FT_Done_Library(ft_library);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ImFontBuilderIO* ImGuiFreeType::GetBuilderForFreeType()
|
||||
{
|
||||
static ImFontBuilderIO io;
|
||||
io.FontBuilder_Build = ImFontAtlasBuildWithFreeType;
|
||||
return &io;
|
||||
}
|
||||
|
||||
void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
|
||||
{
|
||||
GImFreeTypeAllocFunc = alloc_func;
|
||||
GImFreeTypeFreeFunc = free_func;
|
||||
GImFreeTypeAllocatorUserData = user_data;
|
||||
GImGuiFreeTypeAllocFunc = alloc_func;
|
||||
GImGuiFreeTypeFreeFunc = free_func;
|
||||
GImGuiFreeTypeAllocatorUserData = user_data;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
|
||||
// (headers)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "imgui.h" // IMGUI_API
|
||||
|
||||
// Forward declarations
|
||||
struct ImFontAtlas;
|
||||
struct ImFontBuilderIO;
|
||||
|
||||
// Hinting greatly impacts visuals (and glyph sizes).
|
||||
// - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
|
||||
// - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h
|
||||
// - The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
|
||||
// - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
|
||||
// You can set those flags globaly in ImFontAtlas::FontBuilderFlags
|
||||
// You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags
|
||||
enum ImGuiFreeTypeBuilderFlags
|
||||
{
|
||||
ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
|
||||
ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter.
|
||||
ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
|
||||
ImGuiFreeTypeBuilderFlags_LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.
|
||||
ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
|
||||
ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font?
|
||||
ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
|
||||
ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results!
|
||||
ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs
|
||||
ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs
|
||||
};
|
||||
|
||||
namespace ImGuiFreeType
|
||||
{
|
||||
// This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'.
|
||||
// If you need to dynamically select between multiple builders:
|
||||
// - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()'
|
||||
// - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data.
|
||||
IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType();
|
||||
|
||||
// Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
|
||||
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
|
||||
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
|
||||
|
||||
// Obsolete names (will be removed soon)
|
||||
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// dear imgui: single-file wrapper include
|
||||
// We use this to validate compiling all *.cpp files in a same compilation unit.
|
||||
// Users of that technique (also called "Unity builds") can generally provide this themselves,
|
||||
// so we don't really recommend you use this in your projects.
|
||||
|
||||
// Do this:
|
||||
// #define IMGUI_IMPLEMENTATION
|
||||
// Before you include this file in *one* C++ file to create the implementation.
|
||||
// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit.
|
||||
#include "../../imgui.h"
|
||||
|
||||
#ifdef IMGUI_IMPLEMENTATION
|
||||
#include "../../imgui.cpp"
|
||||
#include "../../imgui_demo.cpp"
|
||||
#include "../../imgui_draw.cpp"
|
||||
#include "../../imgui_tables.cpp"
|
||||
#include "../../imgui_widgets.cpp"
|
||||
#endif
|
||||
@@ -100,49 +100,10 @@ namespace LmbrCentral
|
||||
|
||||
void DecalComponent::Activate()
|
||||
{
|
||||
AZ::Transform transform = AZ::Transform::CreateIdentity();
|
||||
EBUS_EVENT_ID_RESULT(transform, GetEntityId(), AZ::TransformBus, GetWorldTM);
|
||||
|
||||
SDecalProperties decalProperties = m_configuration.GetDecalProperties(transform);
|
||||
|
||||
m_decalRenderNode = static_cast<IDecalRenderNode*>(gEnv->p3DEngine->CreateRenderNode(eERType_Decal));
|
||||
if (m_decalRenderNode)
|
||||
{
|
||||
m_decalRenderNode->SetRndFlags(m_decalRenderNode->GetRndFlags() | ERF_COMPONENT_ENTITY);
|
||||
m_decalRenderNode->SetDecalProperties(decalProperties);
|
||||
m_decalRenderNode->SetMinSpec(static_cast<int>(decalProperties.m_minSpec));
|
||||
m_decalRenderNode->SetMatrix(AZTransformToLYTransform(transform));
|
||||
m_decalRenderNode->SetViewDistanceMultiplier(m_configuration.m_viewDistanceMultiplier);
|
||||
|
||||
const int configSpec = gEnv->pSystem->GetConfigSpec(true);
|
||||
if (!m_configuration.m_visible || static_cast<AZ::u32>(configSpec) < static_cast<AZ::u32>(m_configuration.m_minSpec))
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
m_materialBusHandler->Activate(m_decalRenderNode, m_entity->GetId());
|
||||
|
||||
DecalComponentRequestBus::Handler::BusConnect(GetEntityId());
|
||||
RenderNodeRequestBus::Handler::BusConnect(GetEntityId());
|
||||
AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId());
|
||||
MaterialOwnerRequestBus::Handler::BusConnect(GetEntityId());
|
||||
}
|
||||
|
||||
void DecalComponent::Deactivate()
|
||||
{
|
||||
DecalComponentRequestBus::Handler::BusDisconnect();
|
||||
RenderNodeRequestBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
||||
MaterialOwnerRequestBus::Handler::BusDisconnect();
|
||||
|
||||
m_materialBusHandler->Deactivate();
|
||||
|
||||
if (m_decalRenderNode)
|
||||
{
|
||||
gEnv->p3DEngine->DeleteRenderNode(m_decalRenderNode);
|
||||
m_decalRenderNode = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DecalComponent::OnTransformChanged([[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
|
||||
|
||||
@@ -190,50 +190,10 @@ namespace LmbrCentral
|
||||
void EditorDecalComponent::Activate()
|
||||
{
|
||||
Base::Activate();
|
||||
|
||||
AZ::EntityId entityId = GetEntityId();
|
||||
|
||||
IEditor* editor = nullptr;
|
||||
EBUS_EVENT_RESULT(editor, AzToolsFramework::EditorRequests::Bus, GetEditor);
|
||||
|
||||
m_configuration.m_editorEntityId = entityId;
|
||||
m_decalRenderNode = static_cast<IDecalRenderNode*>(editor->Get3DEngine()->CreateRenderNode(eERType_Decal));
|
||||
RefreshDecal();
|
||||
|
||||
MaterialOwnerRequestBus::Handler::BusConnect(entityId);
|
||||
AZ::TransformNotificationBus::Handler::BusConnect(entityId);
|
||||
DecalComponentEditorRequests::Bus::Handler::BusConnect(entityId);
|
||||
RenderNodeRequestBus::Handler::BusConnect(entityId);
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(entityId);
|
||||
AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusConnect(entityId);
|
||||
AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(entityId);
|
||||
AzFramework::BoundsRequestBus::Handler::BusConnect(entityId);
|
||||
}
|
||||
|
||||
void EditorDecalComponent::Deactivate()
|
||||
{
|
||||
MaterialOwnerRequestBus::Handler::BusDisconnect();
|
||||
DecalComponentEditorRequests::Bus::Handler::BusDisconnect();
|
||||
RenderNodeRequestBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorVisibilityNotificationBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
|
||||
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
|
||||
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
|
||||
|
||||
m_configuration.m_editorEntityId.SetInvalid();
|
||||
|
||||
if (m_decalRenderNode)
|
||||
{
|
||||
IEditor* editor = nullptr;
|
||||
EBUS_EVENT_RESULT(editor, AzToolsFramework::EditorRequests::Bus, GetEditor);
|
||||
editor->Get3DEngine()->DeleteRenderNode(m_decalRenderNode);
|
||||
|
||||
m_decalRenderNode = nullptr;
|
||||
}
|
||||
|
||||
Base::Deactivate();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <AzCore/RTTI/RTTI.h>
|
||||
#include <AzNetworking/ConnectionLayer/IConnection.h>
|
||||
#include <AzNetworking/DataStructures/ByteBuffer.h>
|
||||
#include <Include/MultiplayerStats.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
@@ -23,21 +24,6 @@ namespace AzNetworking
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
struct MultiplayerStats
|
||||
{
|
||||
uint64_t m_entityCount = 0;
|
||||
uint64_t m_clientConnectionCount = 0;
|
||||
uint64_t m_serverConnectionCount = 0;
|
||||
uint64_t m_propertyUpdatesSent = 0;
|
||||
uint64_t m_propertyUpdatesSentBytes = 0;
|
||||
uint64_t m_propertyUpdatesRecv = 0;
|
||||
uint64_t m_propertyUpdatesRecvBytes = 0;
|
||||
uint64_t m_rpcsSent = 0;
|
||||
uint64_t m_rpcsSentBytes = 0;
|
||||
uint64_t m_rpcsRecv = 0;
|
||||
uint64_t m_rpcsRecvBytes = 0;
|
||||
};
|
||||
|
||||
//! Collection of types of Multiplayer Connections
|
||||
enum class MultiplayerAgentType
|
||||
{
|
||||
@@ -88,14 +74,36 @@ namespace Multiplayer
|
||||
//! @param handler The SessionShutdownEvent handler to add
|
||||
virtual void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) = 0;
|
||||
|
||||
//! Retrieve the stats object bound to this multiplayer instance.
|
||||
//! @return the stats object bound to this multiplayer instance
|
||||
MultiplayerStats& GetStats() { return m_stats; }
|
||||
|
||||
//! Sends a packet telling if entity update messages can be sent
|
||||
//! @param readyForEntityUpdates Ready for entity updates or not
|
||||
virtual void SendReadyForEntityUpdates(bool readyForEntityUpdates) = 0;
|
||||
|
||||
//! Returns the gem name associated with the provided component index.
|
||||
//! @param netComponentId the componentId to return the gem name of
|
||||
//! @return the name of the gem that contains the requested component
|
||||
virtual const char* GetComponentGemName(NetComponentId netComponentId) const = 0;
|
||||
|
||||
//! Returns the component name associated with the provided component index.
|
||||
//! @param netComponentId the componentId to return the component name of
|
||||
//! @return the name of the component
|
||||
virtual const char* GetComponentName(NetComponentId netComponentId) const = 0;
|
||||
|
||||
//! Returns the property name associated with the provided component index and property index.
|
||||
//! @param netComponentId the component index to return the property name of
|
||||
//! @param propertyIndex the index of the network property to return the property name of
|
||||
//! @return the name of the network property
|
||||
virtual const char* GetComponentPropertyName(NetComponentId netComponentId, PropertyIndex propertyIndex) const = 0;
|
||||
|
||||
//! Returns the Rpc name associated with the provided component index and rpc index.
|
||||
//! @param netComponentId the componentId to return the property name of
|
||||
//! @param rpcIndex the index of the rpc to return the rpc name of
|
||||
//! @return the name of the requested rpc
|
||||
virtual const char* GetComponentRpcName(NetComponentId netComponentId, RpcIndex rpcIndex) const = 0;
|
||||
|
||||
//! Retrieve the stats object bound to this multiplayer instance.
|
||||
//! @return the stats object bound to this multiplayer instance
|
||||
MultiplayerStats& GetStats() { return m_stats; }
|
||||
|
||||
private:
|
||||
MultiplayerStats m_stats;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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 <Include/MultiplayerStats.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
void MultiplayerStats::ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
if (m_componentStats.size() <= netComponentIndex)
|
||||
{
|
||||
m_componentStats.resize(netComponentIndex + 1);
|
||||
}
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent.resize(propertyCount);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv.resize(propertyCount);
|
||||
m_componentStats[netComponentIndex].m_rpcsSent.resize(rpcCount);
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv.resize(rpcCount);
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(propertyId);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesSent[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t propertyIndex = aznumeric_cast<uint16_t>(propertyId);
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_propertyUpdatesRecv[propertyIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(rpcId);
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_rpcsSent[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes)
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
const uint16_t rpcIndex = aznumeric_cast<uint16_t>(rpcId);
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalCalls++;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_totalBytes += totalBytes;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_callHistory[m_recordMetricIndex]++;
|
||||
m_componentStats[netComponentIndex].m_rpcsRecv[rpcIndex].m_byteHistory[m_recordMetricIndex] += totalBytes;
|
||||
}
|
||||
|
||||
void MultiplayerStats::TickStats(AZ::TimeMs metricFrameTimeMs)
|
||||
{
|
||||
m_totalHistoryTimeMs = metricFrameTimeMs * static_cast<AZ::TimeMs>(RingbufferSamples);
|
||||
m_recordMetricIndex = ++m_recordMetricIndex % RingbufferSamples;
|
||||
}
|
||||
|
||||
static void CombineMetrics(MultiplayerStats::Metric& outArg1, const MultiplayerStats::Metric& arg2)
|
||||
{
|
||||
outArg1.m_totalCalls += arg2.m_totalCalls;
|
||||
outArg1.m_totalBytes += arg2.m_totalBytes;
|
||||
for (uint32_t index = 0; index < MultiplayerStats::RingbufferSamples; ++index)
|
||||
{
|
||||
outArg1.m_callHistory[index] += arg2.m_callHistory[index];
|
||||
outArg1.m_byteHistory[index] += arg2.m_byteHistory[index];
|
||||
}
|
||||
}
|
||||
|
||||
static MultiplayerStats::Metric SumMetricVector(const AZStd::vector<MultiplayerStats::Metric>& metricVector)
|
||||
{
|
||||
MultiplayerStats::Metric result;
|
||||
for (AZStd::size_t index = 0; index < metricVector.size(); ++index)
|
||||
{
|
||||
CombineMetrics(result, metricVector[index]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateSentMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentPropertyUpdateRecvMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_propertyUpdatesRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsSentMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsSent);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateComponentRpcsRecvMetrics(NetComponentId netComponentId) const
|
||||
{
|
||||
const uint16_t netComponentIndex = aznumeric_cast<uint16_t>(netComponentId);
|
||||
return SumMetricVector(m_componentStats[netComponentIndex].m_rpcsRecv);
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateSentMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalPropertyUpdateRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentPropertyUpdateRecvMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsSentMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentRpcsSentMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MultiplayerStats::Metric MultiplayerStats::CalculateTotalRpcsRecvMetrics() const
|
||||
{
|
||||
Metric result;
|
||||
for (AZStd::size_t index = 0; index < m_componentStats.size(); ++index)
|
||||
{
|
||||
const NetComponentId netComponentId = aznumeric_cast<NetComponentId>(index);
|
||||
CombineMetrics(result, CalculateComponentRpcsRecvMetrics(netComponentId));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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/Time/ITime.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <Include/MultiplayerTypes.h>
|
||||
|
||||
namespace AzNetworking
|
||||
{
|
||||
class INetworkInterface;
|
||||
}
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
struct MultiplayerStats
|
||||
{
|
||||
uint64_t m_entityCount = 0;
|
||||
uint64_t m_clientConnectionCount = 0;
|
||||
uint64_t m_serverConnectionCount = 0;
|
||||
|
||||
uint64_t m_recordMetricIndex = 0;
|
||||
AZ::TimeMs m_totalHistoryTimeMs = AZ::TimeMs{ 0 };
|
||||
|
||||
static const uint32_t RingbufferSamples = 32;
|
||||
using MetricRingbuffer = AZStd::array<uint64_t, RingbufferSamples>;
|
||||
struct Metric
|
||||
{
|
||||
uint64_t m_totalCalls = 0;
|
||||
uint64_t m_totalBytes = 0;
|
||||
MetricRingbuffer m_callHistory;
|
||||
MetricRingbuffer m_byteHistory;
|
||||
};
|
||||
|
||||
struct ComponentStats
|
||||
{
|
||||
AZStd::vector<Metric> m_propertyUpdatesSent;
|
||||
AZStd::vector<Metric> m_propertyUpdatesRecv;
|
||||
AZStd::vector<Metric> m_rpcsSent;
|
||||
AZStd::vector<Metric> m_rpcsRecv;
|
||||
};
|
||||
AZStd::vector<ComponentStats> m_componentStats;
|
||||
|
||||
void ReserveComponentStats(NetComponentId netComponentId, uint16_t propertyCount, uint16_t rpcCount);
|
||||
void RecordPropertySent(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes);
|
||||
void RecordPropertyReceived(NetComponentId netComponentId, PropertyIndex propertyId, uint32_t totalBytes);
|
||||
void RecordRpcSent(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes);
|
||||
void RecordRpcReceived(NetComponentId netComponentId, RpcIndex rpcId, uint32_t totalBytes);
|
||||
void TickStats(AZ::TimeMs metricFrameTimeMs);
|
||||
|
||||
Metric CalculateComponentPropertyUpdateSentMetrics(NetComponentId netComponentId) const;
|
||||
Metric CalculateComponentPropertyUpdateRecvMetrics(NetComponentId netComponentId) const;
|
||||
Metric CalculateComponentRpcsSentMetrics(NetComponentId netComponentId) const;
|
||||
Metric CalculateComponentRpcsRecvMetrics(NetComponentId netComponentId) const;
|
||||
Metric CalculateTotalPropertyUpdateSentMetrics() const;
|
||||
Metric CalculateTotalPropertyUpdateRecvMetrics() const;
|
||||
Metric CalculateTotalRpcsSentMetrics() const;
|
||||
Metric CalculateTotalRpcsRecvMetrics() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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/Event.h>
|
||||
#include <AzCore/Name/Name.h>
|
||||
#include <AzCore/RTTI/TypeSafeIntegral.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
#include <AzNetworking/Serialization/ISerializer.h>
|
||||
#include <AzNetworking/ConnectionLayer/ConnectionEnums.h>
|
||||
|
||||
namespace Multiplayer
|
||||
{
|
||||
//! The default number of rewindable samples for us to store.
|
||||
static constexpr uint32_t RewindHistorySize = 128;
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL(HostId, uint32_t);
|
||||
static constexpr HostId InvalidHostId = static_cast<HostId>(-1);
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL(NetEntityId, uint32_t);
|
||||
static constexpr NetEntityId InvalidNetEntityId = static_cast<NetEntityId>(-1);
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL(NetComponentId, uint16_t);
|
||||
static constexpr NetComponentId InvalidNetComponentId = static_cast<NetComponentId>(-1);
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL(PropertyIndex, uint16_t);
|
||||
AZ_TYPE_SAFE_INTEGRAL(RpcIndex, uint16_t);
|
||||
|
||||
using LongNetworkString = AZ::CVarFixedString;
|
||||
using ReliabilityType = AzNetworking::ReliabilityType;
|
||||
|
||||
class NetworkEntityRpcMessage;
|
||||
using RpcSendEvent = AZ::Event<NetworkEntityRpcMessage&>;
|
||||
|
||||
// Note that we explicitly set storage classes so that sizeof() is accurate for serialized size
|
||||
enum class RpcDeliveryType : uint8_t
|
||||
{
|
||||
None,
|
||||
AuthorityToClient, // Invoked from Authority, handled on Client
|
||||
AuthorityToAutonomous, // Invoked from Authority, handled on Autonomous
|
||||
AutonomousToAuthority, // Invoked from Autonomous, handled on Authority
|
||||
ServerToAuthority // Invoked from Server, handled on Authority
|
||||
};
|
||||
|
||||
enum class NetEntityRole : uint8_t
|
||||
{
|
||||
InvalidRole, // No role
|
||||
Client, // A simulated proxy on a client
|
||||
Autonomous, // An autonomous proxy on a client (can execute local prediction)
|
||||
Server, // A simulated proxy on a server
|
||||
Authority // An authoritative proxy on a server (full authority)
|
||||
};
|
||||
|
||||
enum class ComponentSerializationType : uint8_t
|
||||
{
|
||||
Properties,
|
||||
Correction
|
||||
};
|
||||
|
||||
enum class EntityIsMigrating : uint8_t
|
||||
{
|
||||
False,
|
||||
True
|
||||
};
|
||||
|
||||
// This is just a placeholder
|
||||
// The level/prefab cooking will devise the actual solution for identifying a dynamically spawnable entity within a prefab
|
||||
struct PrefabEntityId
|
||||
{
|
||||
AZ_TYPE_INFO(PrefabEntityId, "{EFD37465-CCAC-4E87-A825-41B4010A2C75}");
|
||||
|
||||
static constexpr uint32_t AllIndices = AZStd::numeric_limits<uint32_t>::max();
|
||||
|
||||
AZ::Name m_prefabName;
|
||||
uint32_t m_entityOffset = AllIndices;
|
||||
|
||||
PrefabEntityId() = default;
|
||||
|
||||
explicit PrefabEntityId(AZ::Name name, uint32_t entityOffset = AllIndices)
|
||||
: m_prefabName(name)
|
||||
, m_entityOffset(entityOffset)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const PrefabEntityId& rhs) const
|
||||
{
|
||||
return m_prefabName == rhs.m_prefabName && m_entityOffset == rhs.m_entityOffset;
|
||||
}
|
||||
|
||||
bool operator!=(const PrefabEntityId& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
bool Serialize(AzNetworking::ISerializer& serializer)
|
||||
{
|
||||
serializer.Serialize(m_prefabName, "prefabName");
|
||||
serializer.Serialize(m_entityOffset, "entityOffset");
|
||||
return serializer.IsValid();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::HostId);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetEntityId);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::NetComponentId);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::PropertyIndex);
|
||||
AZ_TYPE_SAFE_INTEGRAL_SERIALIZEBINDING(Multiplayer::RpcIndex);
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/std/containers/list.h>
|
||||
#include <Source/MultiplayerTypes.h>
|
||||
#include <Include/MultiplayerTypes.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -12,15 +12,8 @@ namespace AZ
|
||||
{% set Namespace = dataFiles[0].attrib['Namespace'] %}
|
||||
namespace {{ Namespace }}
|
||||
{
|
||||
enum class ComponentTypes
|
||||
{
|
||||
{% for Component in dataFiles %}
|
||||
{% set ComponentName = Component.attrib['Name'] %}
|
||||
{{ ComponentName }},
|
||||
{% endfor %}
|
||||
Count
|
||||
};
|
||||
static_assert(ComponentTypes::Count < static_cast<ComponentTypes>(Multiplayer::InvalidNetComponentId), "ComponentId overflow");
|
||||
//! Registers all multiplayer components contained within this gem with the MultiplayerComponentRegistry.
|
||||
void RegisterMultiplayerComponents();
|
||||
|
||||
//! For reflecting multiplayer components into the serialize, edit, and behaviour contexts.
|
||||
void CreateComponentDescriptors(AZStd::list<AZ::ComponentDescriptor*>& descriptors);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <Source/Components/MultiplayerComponentRegistry.h>
|
||||
#include <Source/NetworkEntity/INetworkEntityManager.h>
|
||||
{% for Component in dataFiles %}
|
||||
{% set ComponentDerived = Component.attrib['OverrideComponent']|booleanTrue %}
|
||||
{% set ControllerDerived = Component.attrib['OverrideController']|booleanTrue %}
|
||||
@@ -10,8 +12,38 @@
|
||||
{% endfor %}
|
||||
|
||||
{% set Namespace = dataFiles[0].attrib['Namespace'] %}
|
||||
{% for Component in dataFiles %}
|
||||
{% if Component.attrib['Namespace'] != Namespace %}
|
||||
#error "mismatched component namespaces detected in declared multiplayer components, expected {{ Namespace }} but found {{ Component.attrib['Namespace'] }}"
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
namespace {{ Namespace }}
|
||||
{
|
||||
void RegisterMultiplayerComponents()
|
||||
{
|
||||
Multiplayer::MultiplayerComponentRegistry* multiplayerComponentRegistry = GetMultiplayerComponentRegistry();
|
||||
Multiplayer::MultiplayerStats& stats = AZ::Interface<Multiplayer::IMultiplayer>::Get()->GetStats();
|
||||
{% for Component in dataFiles %}
|
||||
{% set ComponentName = Component.attrib['Name'] %}
|
||||
{% set ComponentBaseName = ComponentName %}
|
||||
{% if Component.attrib['OverrideComponent']|booleanTrue %}
|
||||
{% set ComponentBaseName = ComponentName + "Base" %}
|
||||
{% endif %}
|
||||
{% set NetworkInputCount = Component.findall('NetworkInput') | len %}
|
||||
{% set NetworkPropertyCount = Component.findall('NetworkProperty') | len %}
|
||||
{% set RpcCount = Component.findall('RemoteProcedure') | len %}
|
||||
{
|
||||
Multiplayer::MultiplayerComponentRegistry::ComponentData componentData;
|
||||
componentData.m_gemName = AZ::Name("{{ Namespace }}");
|
||||
componentData.m_componentName = AZ::Name("{{ Component.attrib['Name'] }}");
|
||||
componentData.m_componentPropertyNameLookupFunction = {{ ComponentBaseName }}::GetNetworkPropertyName;
|
||||
componentData.m_componentRpcNameLookupFunction = {{ ComponentBaseName }}::GetRpcName;
|
||||
{{ ComponentBaseName }}::s_netComponentId = multiplayerComponentRegistry->RegisterMultiplayerComponent(componentData);
|
||||
stats.ReserveComponentStats({{ ComponentBaseName }}::s_netComponentId, static_cast<uint16_t>({{ NetworkPropertyCount }}), static_cast<uint16_t>({{ RpcCount }}));
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
void CreateComponentDescriptors(AZStd::list<AZ::ComponentDescriptor*>& descriptors)
|
||||
{
|
||||
descriptors.insert(descriptors.end(), {
|
||||
|
||||
@@ -227,7 +227,7 @@ AZStd::fixed_vector<{{ Property.attrib['Type'] }}, {{ Property.attrib['Count'] }
|
||||
#include <Source/Components/MultiplayerController.h>
|
||||
#include <Source/NetworkInput/IMultiplayerComponentInput.h>
|
||||
#include <Source/NetworkTime/RewindableObject.h>
|
||||
#include <Source/MultiplayerTypes.h>
|
||||
#include <Include/MultiplayerTypes.h>
|
||||
{% call(Include) AutoComponentMacros.ParseIncludes(Component) %}
|
||||
#include <{{ Include.attrib['File'] }}>
|
||||
{% endcall %}
|
||||
@@ -251,9 +251,6 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
class {{ ComponentName }};
|
||||
class {{ ControllerName }};
|
||||
|
||||
//! Returns a human readable name for the provided remoteProcedureId.
|
||||
const char* GetRemoteProcedureName(uint16_t remoteProcedureId);
|
||||
|
||||
{% set RecordName = ComponentName + "Record" %}
|
||||
//! @class {{RecordName }}
|
||||
//! @brief A record of the changed bits in the NetworkProperties for component {{ ComponentName }}.
|
||||
@@ -329,7 +326,6 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
: public Multiplayer::IMultiplayerComponentInput
|
||||
{
|
||||
public:
|
||||
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
|
||||
Multiplayer::NetComponentId GetComponentId() const override;
|
||||
INetworkInput& operator=(const INetworkInput& rhs) override;
|
||||
bool Serialize(AzNetworking::ISerializer& serializer);
|
||||
@@ -412,8 +408,6 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
AZ_MULTIPLAYER_COMPONENT({{ Component.attrib['Namespace'] }}::{{ ComponentBaseName }}, s_{{ LowerFirst(ComponentName) }}ConcreteUuid, Multiplayer::MultiplayerComponent);
|
||||
{% endif %}
|
||||
|
||||
static const Multiplayer::NetComponentId s_componentId = static_cast<Multiplayer::NetComponentId>({{ Component.attrib['Namespace'] }}::ComponentTypes::{{ Component.attrib['Name'] }});
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
static void ReflectToEditContext(AZ::ReflectContext* context);
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
|
||||
@@ -489,6 +483,10 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
bool SerializeAutonomousToAuthorityProperties({{ RecordName }}& replicationRecord, AzNetworking::ISerializer& serializer);
|
||||
void NotifyChangesAutonomousToAuthorityProperties(const {{ RecordName }}& replicationRecord) const;
|
||||
|
||||
//! Debug name helpers
|
||||
static const char* GetNetworkPropertyName(PropertyIndex propertyIndex);
|
||||
static const char* GetRpcName(RpcIndex rpcIndex);
|
||||
|
||||
AZStd::unique_ptr<{{ RecordName }}> m_currentRecord;
|
||||
AZStd::unique_ptr<{{ ControllerName }}> m_controller;
|
||||
|
||||
@@ -518,6 +516,9 @@ namespace {{ Component.attrib['Namespace'] }}
|
||||
{% call(Type, Name) AutoComponentMacros.ParseComponentServiceTypeAndName(Component) %}
|
||||
{{ Type }}* {{ Name }} = nullptr;
|
||||
{% endcall %}
|
||||
|
||||
static NetComponentId s_netComponentId;
|
||||
friend void RegisterMultiplayerComponents();
|
||||
};
|
||||
}
|
||||
{% endfor %}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user