初始提交: UE5.3项目基础框架
This commit is contained in:
20
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Assert.h
vendored
Normal file
20
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Assert.h
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
//
|
||||
// Define our own assertion, so that users can forcebly turn them on if needed
|
||||
//
|
||||
#if defined CESIUM_FORCE_ASSERTIONS && defined NDEBUG
|
||||
// Asserts are defined in cassert and normally compiled out when NDEBUG is
|
||||
// defined. Redirect to our own assertion that can't be compiled out
|
||||
namespace CesiumUtility {
|
||||
std::int32_t forceAssertFailure();
|
||||
};
|
||||
#define CESIUM_ASSERT(expression) \
|
||||
((expression) ? 0 : CesiumUtility::forceAssertFailure())
|
||||
#else
|
||||
// Let assertions get defined with default behavior
|
||||
#include <cassert>
|
||||
#define CESIUM_ASSERT(expression) assert(expression)
|
||||
#endif
|
||||
82
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/AttributeCompression.h
vendored
Normal file
82
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/AttributeCompression.h
vendored
Normal file
@ -0,0 +1,82 @@
|
||||
#pragma once
|
||||
|
||||
#include "Library.h"
|
||||
#include "Math.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief Functions to handle compressed attributes in different formats
|
||||
*/
|
||||
class CESIUMUTILITY_API AttributeCompression final {
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Decodes a unit-length vector in 'oct' encoding to a normalized
|
||||
* 3-component vector.
|
||||
*
|
||||
* @param x The x component of the oct-encoded unit length vector.
|
||||
* @param y The y component of the oct-encoded unit length vector.
|
||||
* @param rangeMax The maximum value of the SNORM range. The encoded vector is
|
||||
* stored in log2(rangeMax+1) bits.
|
||||
* @returns The decoded and normalized vector.
|
||||
*/
|
||||
template <
|
||||
typename T,
|
||||
class = typename std::enable_if<std::is_unsigned<T>::value>::type>
|
||||
static glm::dvec3 octDecodeInRange(T x, T y, T rangeMax) {
|
||||
glm::dvec3 result;
|
||||
|
||||
result.x = CesiumUtility::Math::fromSNorm(x, rangeMax);
|
||||
result.y = CesiumUtility::Math::fromSNorm(y, rangeMax);
|
||||
result.z = 1.0 - (glm::abs(result.x) + glm::abs(result.y));
|
||||
|
||||
if (result.z < 0.0) {
|
||||
const double oldVX = result.x;
|
||||
result.x =
|
||||
(1.0 - glm::abs(result.y)) * CesiumUtility::Math::signNotZero(oldVX);
|
||||
result.y =
|
||||
(1.0 - glm::abs(oldVX)) * CesiumUtility::Math::signNotZero(result.y);
|
||||
}
|
||||
|
||||
return glm::normalize(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes a unit-length vector in 2 byte 'oct' encoding to a
|
||||
* normalized 3-component vector.
|
||||
*
|
||||
* @param x The x component of the oct-encoded unit length vector.
|
||||
* @param y The y component of the oct-encoded unit length vector.
|
||||
* @returns The decoded and normalized vector.
|
||||
*
|
||||
* @see AttributeCompression::octDecodeInRange
|
||||
*/
|
||||
static glm::dvec3 octDecode(uint8_t x, uint8_t y) {
|
||||
constexpr uint8_t rangeMax = 255;
|
||||
return AttributeCompression::octDecodeInRange(x, y, rangeMax);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes a RGB565-encoded color to a 3-component vector
|
||||
* containing the normalized RGB values.
|
||||
*
|
||||
* @param value The RGB565-encoded value.
|
||||
* @returns The normalized RGB values.
|
||||
*/
|
||||
static glm::dvec3 decodeRGB565(const uint16_t value) {
|
||||
constexpr uint16_t mask5 = (1 << 5) - 1;
|
||||
constexpr uint16_t mask6 = (1 << 6) - 1;
|
||||
constexpr float normalize5 = 1.0f / 31.0f; // normalize [0, 31] to [0, 1]
|
||||
constexpr float normalize6 = 1.0f / 63.0f; // normalize [0, 63] to [0, 1]
|
||||
|
||||
const uint16_t red = static_cast<uint16_t>(value >> 11);
|
||||
const uint16_t green = static_cast<uint16_t>((value >> 5) & mask6);
|
||||
const uint16_t blue = value & mask5;
|
||||
|
||||
return glm::dvec3(red * normalize5, green * normalize6, blue * normalize5);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
114
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/CreditSystem.h
vendored
Normal file
114
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/CreditSystem.h
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
#pragma once
|
||||
|
||||
#include "Library.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Represents an HTML string that should be shown on screen to attribute
|
||||
* third parties for used data, imagery, etc. Acts as a handle into a
|
||||
* {@link CreditSystem} object that actually holds the credit string.
|
||||
*/
|
||||
struct CESIUMUTILITY_API Credit {
|
||||
public:
|
||||
/**
|
||||
* @brief Returns `true` if two credit objects have the same ID.
|
||||
*/
|
||||
bool operator==(const Credit& rhs) const noexcept {
|
||||
return this->id == rhs.id;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t id;
|
||||
|
||||
Credit(size_t id_) noexcept { id = id_; }
|
||||
|
||||
friend class CreditSystem;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Creates and manages {@link Credit} objects. Avoids repetitions and
|
||||
* tracks which credits should be shown and which credits should be removed this
|
||||
* frame.
|
||||
*/
|
||||
class CESIUMUTILITY_API CreditSystem final {
|
||||
public:
|
||||
/**
|
||||
* @brief Inserts a credit string
|
||||
*
|
||||
* @return If this string already exists, returns a Credit handle to the
|
||||
* existing entry. Otherwise returns a Credit handle to a new entry.
|
||||
*/
|
||||
Credit createCredit(std::string&& html, bool showOnScreen = false);
|
||||
|
||||
/**
|
||||
* @brief Inserts a credit string
|
||||
*
|
||||
* @return If this string already exists, returns a Credit handle to the
|
||||
* existing entry. Otherwise returns a Credit handle to a new entry.
|
||||
*/
|
||||
Credit createCredit(const std::string& html, bool showOnScreen = false);
|
||||
|
||||
/**
|
||||
* @brief Gets whether or not the credit should be shown on screen.
|
||||
*/
|
||||
bool shouldBeShownOnScreen(Credit credit) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Sets whether or not the credit should be shown on screen.
|
||||
*/
|
||||
void setShowOnScreen(Credit credit, bool showOnScreen) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the HTML string for this credit
|
||||
*/
|
||||
const std::string& getHtml(Credit credit) const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Adds the Credit to the set of credits to show this frame
|
||||
*/
|
||||
void addCreditToFrame(Credit credit);
|
||||
|
||||
/**
|
||||
* @brief Notifies this CreditSystem to start tracking the credits to show for
|
||||
* the next frame.
|
||||
*/
|
||||
void startNextFrame() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the credits to show this frame.
|
||||
*/
|
||||
const std::vector<Credit>& getCreditsToShowThisFrame() noexcept;
|
||||
|
||||
/**
|
||||
* @brief Get the credits that were shown last frame but should no longer be
|
||||
* shown.
|
||||
*/
|
||||
const std::vector<Credit>&
|
||||
getCreditsToNoLongerShowThisFrame() const noexcept {
|
||||
return _creditsToNoLongerShowThisFrame;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string INVALID_CREDIT_MESSAGE =
|
||||
"Error: Invalid Credit, cannot get HTML string.";
|
||||
|
||||
struct HtmlAndLastFrameNumber {
|
||||
std::string html;
|
||||
bool showOnScreen;
|
||||
int32_t lastFrameNumber;
|
||||
int count;
|
||||
};
|
||||
|
||||
std::vector<HtmlAndLastFrameNumber> _credits;
|
||||
|
||||
int32_t _currentFrameNumber = 0;
|
||||
std::vector<Credit> _creditsToShowThisFrame;
|
||||
std::vector<Credit> _creditsToNoLongerShowThisFrame;
|
||||
};
|
||||
} // namespace CesiumUtility
|
||||
274
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h
vendored
Normal file
274
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/DoublyLinkedList.h
vendored
Normal file
@ -0,0 +1,274 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Contains the previous and next pointers for an element in
|
||||
* a {@link DoublyLinkedList}.
|
||||
*/
|
||||
template <class T> class DoublyLinkedListPointers final {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
DoublyLinkedListPointers() noexcept : pNext(nullptr), pPrevious(nullptr) {}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
*
|
||||
* @param rhs The other instance.
|
||||
*/
|
||||
// Following the example of boost::instrusive::list's list_member_hook, the
|
||||
// copy constructor and assignment operator do nothing.
|
||||
// https://www.boost.org/doc/libs/1_73_0/doc/html/boost/intrusive/list_member_hook.html
|
||||
DoublyLinkedListPointers(
|
||||
[[maybe_unused]] DoublyLinkedListPointers& rhs) noexcept
|
||||
: DoublyLinkedListPointers() {}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
*/
|
||||
DoublyLinkedListPointers&
|
||||
operator=(const DoublyLinkedListPointers& /*rhs*/) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <
|
||||
typename TElement,
|
||||
typename TElementBase,
|
||||
DoublyLinkedListPointers<TElement>(TElementBase::*Pointers)>
|
||||
friend class DoublyLinkedListAdvanced;
|
||||
|
||||
T* pNext;
|
||||
T* pPrevious;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A doubly-linked list.
|
||||
*
|
||||
* In this implementation, the previous and next pointers are embedded directly
|
||||
* in the data object.
|
||||
*
|
||||
* @tparam T The data object type.
|
||||
* @tparam (T::*Pointers) A member pointer to the field that holds the links to
|
||||
* the previous and next nodes.
|
||||
*/
|
||||
template <
|
||||
typename T,
|
||||
typename TPointerBase,
|
||||
DoublyLinkedListPointers<T>(TPointerBase::*Pointers)>
|
||||
class DoublyLinkedListAdvanced final {
|
||||
public:
|
||||
/**
|
||||
* @brief Removes the given node from this list.
|
||||
*/
|
||||
void remove(T& node) noexcept {
|
||||
DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
|
||||
|
||||
if (nodePointers.pPrevious) {
|
||||
DoublyLinkedListPointers<T>& previousPointers =
|
||||
nodePointers.pPrevious->*Pointers;
|
||||
previousPointers.pNext = nodePointers.pNext;
|
||||
--this->_size;
|
||||
} else if (this->_pHead == &node) {
|
||||
this->_pHead = nodePointers.pNext;
|
||||
--this->_size;
|
||||
}
|
||||
|
||||
if (nodePointers.pNext) {
|
||||
DoublyLinkedListPointers<T>& nextPointers = nodePointers.pNext->*Pointers;
|
||||
nextPointers.pPrevious = nodePointers.pPrevious;
|
||||
} else if (this->_pTail == &node) {
|
||||
this->_pTail = nodePointers.pPrevious;
|
||||
}
|
||||
|
||||
nodePointers.pPrevious = nullptr;
|
||||
nodePointers.pNext = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert the given node after the other node.
|
||||
*/
|
||||
void insertAfter(T& after, T& node) noexcept {
|
||||
this->remove(node);
|
||||
|
||||
DoublyLinkedListPointers<T>& afterPointers = after.*Pointers;
|
||||
DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
|
||||
|
||||
nodePointers.pPrevious = &after;
|
||||
nodePointers.pNext = afterPointers.pNext;
|
||||
afterPointers.pNext = &node;
|
||||
|
||||
if (nodePointers.pNext) {
|
||||
DoublyLinkedListPointers<T>& nextPointers = nodePointers.pNext->*Pointers;
|
||||
nextPointers.pPrevious = &node;
|
||||
}
|
||||
|
||||
if (this->_pTail == &after) {
|
||||
this->_pTail = &node;
|
||||
}
|
||||
|
||||
++this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert the given node before the other node.
|
||||
*/
|
||||
void insertBefore(T& before, T& node) noexcept {
|
||||
this->remove(node);
|
||||
|
||||
DoublyLinkedListPointers<T>& beforePointers = before.*Pointers;
|
||||
DoublyLinkedListPointers<T>& nodePointers = node.*Pointers;
|
||||
|
||||
nodePointers.pPrevious = beforePointers.pPrevious;
|
||||
nodePointers.pNext = &before;
|
||||
beforePointers.pPrevious = &node;
|
||||
|
||||
if (nodePointers.pPrevious) {
|
||||
DoublyLinkedListPointers<T>& previousPointers =
|
||||
nodePointers.pPrevious->*Pointers;
|
||||
previousPointers.pNext = &node;
|
||||
}
|
||||
|
||||
if (this->_pHead == &before) {
|
||||
this->_pHead = &node;
|
||||
}
|
||||
|
||||
++this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert the given node as the new head of the list.
|
||||
*/
|
||||
void insertAtHead(T& node) noexcept {
|
||||
this->remove(node);
|
||||
|
||||
if (this->_pHead) {
|
||||
(this->_pHead->*Pointers).pPrevious = &node;
|
||||
(node.*Pointers).pNext = this->_pHead;
|
||||
} else {
|
||||
this->_pTail = &node;
|
||||
}
|
||||
this->_pHead = &node;
|
||||
|
||||
++this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert the given node as the new tail of the list.
|
||||
*/
|
||||
void insertAtTail(T& node) noexcept {
|
||||
this->remove(node);
|
||||
|
||||
if (this->_pTail) {
|
||||
(this->_pTail->*Pointers).pNext = &node;
|
||||
(node.*Pointers).pPrevious = this->_pTail;
|
||||
} else {
|
||||
this->_pHead = &node;
|
||||
}
|
||||
this->_pTail = &node;
|
||||
|
||||
++this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the size of this list.
|
||||
*/
|
||||
size_t size() const noexcept { return this->_size; }
|
||||
|
||||
/**
|
||||
* @brief Returns the head node of this list, or `nullptr` if the list is
|
||||
* empty.
|
||||
*/
|
||||
T* head() noexcept { return this->_pHead; }
|
||||
|
||||
/** @copydoc DoublyLinkedList::head() */
|
||||
const T* head() const noexcept { return this->_pHead; }
|
||||
|
||||
/**
|
||||
* @brief Returns the tail node of this list, or `nullptr` if the list is
|
||||
* empty.
|
||||
*/
|
||||
T* tail() noexcept { return this->_pTail; }
|
||||
|
||||
/** @copydoc DoublyLinkedList::tail() */
|
||||
const T* tail() const noexcept { return this->_pTail; }
|
||||
|
||||
/**
|
||||
* @brief Returns the next node after the given one, or `nullptr` if the given
|
||||
* node is the tail.
|
||||
*/
|
||||
T* next(T& node) noexcept { return (node.*Pointers).pNext; }
|
||||
|
||||
/** @copydoc DoublyLinkedList::next(T&) */
|
||||
const T* next(const T& node) const noexcept { return (node.*Pointers).pNext; }
|
||||
|
||||
/**
|
||||
* @brief Returns the next node after the given one, or the head if the given
|
||||
* node is `nullptr`.
|
||||
*/
|
||||
T* next(T* pNode) noexcept {
|
||||
return pNode ? this->next(*pNode) : this->_pHead;
|
||||
}
|
||||
|
||||
/** @copydoc DoublyLinkedList::next(T*) */
|
||||
const T* next(const T* pNode) const noexcept {
|
||||
return pNode ? this->next(*pNode) : this->_pHead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the previous node before the given one, or `nullptr` if the
|
||||
* given node is the head.
|
||||
*/
|
||||
T* previous(T& node) noexcept { return (node.*Pointers).pPrevious; }
|
||||
|
||||
/** @copydoc DoublyLinkedList::previous(T&) */
|
||||
const T* previous(const T& node) const noexcept {
|
||||
return (node.*Pointers).pPrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the previous node before the given one, or the tail if the
|
||||
* given node is `nullptr`.
|
||||
*/
|
||||
T* previous(T* pNode) {
|
||||
return pNode ? this->previous(*pNode) : this->_pTail;
|
||||
}
|
||||
|
||||
/** @copydoc DoublyLinkedList::previous(T*) */
|
||||
const T* previous(const T* pNode) const noexcept {
|
||||
return pNode ? this->previous(*pNode) : this->_pTail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if this list contains a given node in constant time. In
|
||||
* order to avoid a full list scan, this method assumes that if the node has
|
||||
* any next or previous node, then it is contained in this list. Do not use
|
||||
* this method to determine which of multiple lists contain this node.
|
||||
*
|
||||
* @param node The node to check.
|
||||
* @return True if this node is the head of the list, or if the node has next
|
||||
* or previous nodes. False if the node does not have next or previous nodes
|
||||
* and it is not the head of this list.
|
||||
*/
|
||||
bool contains(const T& node) const {
|
||||
return this->next(node) != nullptr || this->previous(node) != nullptr ||
|
||||
this->_pHead == &node;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _size = 0;
|
||||
T* _pHead = nullptr;
|
||||
T* _pTail = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief An intrusive doubly-linked list.
|
||||
*/
|
||||
template <typename T, DoublyLinkedListPointers<T>(T::*Pointers)>
|
||||
using DoublyLinkedList = DoublyLinkedListAdvanced<T, T, Pointers>;
|
||||
|
||||
} // namespace CesiumUtility
|
||||
127
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ErrorList.h
vendored
Normal file
127
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ErrorList.h
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
#pragma once
|
||||
|
||||
#include "Library.h"
|
||||
#include "joinToString.h"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief The container to store the error and warning list when loading a tile
|
||||
* or glTF content
|
||||
*/
|
||||
struct CESIUMUTILITY_API ErrorList {
|
||||
/**
|
||||
* @brief Creates an {@link ErrorList} containing a single error.
|
||||
*
|
||||
* @param errorMessage The error message.
|
||||
* @return The new list containing the single error.
|
||||
*/
|
||||
static ErrorList error(std::string errorMessage);
|
||||
|
||||
/**
|
||||
* @brief Creates an {@link ErrorList} containing a single warning.
|
||||
*
|
||||
* @param warningMessage The warning message.
|
||||
* @return The new list containing the single warning.
|
||||
*/
|
||||
static ErrorList warning(std::string warningMessage);
|
||||
|
||||
/**
|
||||
* @brief Merge the errors and warnings from other ErrorList together
|
||||
*
|
||||
* @param errorList The other instance of ErrorList that will be merged with
|
||||
* the current instance.
|
||||
*/
|
||||
void merge(const ErrorList& errorList);
|
||||
|
||||
/**
|
||||
* @brief Merge the errors and warnings from other ErrorList together
|
||||
*
|
||||
* @param errorList The other instance of ErrorList that will be merged with
|
||||
* the current instance.
|
||||
*/
|
||||
void merge(ErrorList&& errorList);
|
||||
|
||||
/**
|
||||
* @brief Add an error message
|
||||
*
|
||||
* @param error The error message to be added.
|
||||
*/
|
||||
template <typename ErrorStr> void emplaceError(ErrorStr&& error) {
|
||||
errors.emplace_back(std::forward<ErrorStr>(error));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a warning message
|
||||
*
|
||||
* @param warning The warning message to be added.
|
||||
*/
|
||||
template <typename WarningStr> void emplaceWarning(WarningStr&& warning) {
|
||||
warnings.emplace_back(std::forward<WarningStr>(warning));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if there are any error messages.
|
||||
*/
|
||||
bool hasErrors() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief Log all the error messages.
|
||||
*
|
||||
* @param pLogger The logger to log the messages
|
||||
* @param prompt The message prompt for the error messages.
|
||||
*/
|
||||
template <typename PromptStr>
|
||||
void logError(
|
||||
const std::shared_ptr<spdlog::logger>& pLogger,
|
||||
PromptStr&& prompt) const noexcept {
|
||||
if (!errors.empty()) {
|
||||
SPDLOG_LOGGER_ERROR(
|
||||
pLogger,
|
||||
"{}:\n- {}",
|
||||
std::forward<PromptStr>(prompt),
|
||||
CesiumUtility::joinToString(errors, "\n- "));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Log all the warning messages
|
||||
*
|
||||
* @param pLogger The logger to log the messages
|
||||
* @param prompt The message prompt for the warning messages.
|
||||
*/
|
||||
template <typename PromptStr>
|
||||
void logWarning(
|
||||
const std::shared_ptr<spdlog::logger>& pLogger,
|
||||
PromptStr&& prompt) const noexcept {
|
||||
if (!warnings.empty()) {
|
||||
SPDLOG_LOGGER_WARN(
|
||||
pLogger,
|
||||
"{}:\n- {}",
|
||||
std::forward<PromptStr>(prompt),
|
||||
CesiumUtility::joinToString(warnings, "\n- "));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if there are any error messages.
|
||||
*/
|
||||
explicit operator bool() const noexcept;
|
||||
|
||||
/**
|
||||
* @brief The error messages of this container
|
||||
*/
|
||||
std::vector<std::string> errors;
|
||||
|
||||
/**
|
||||
* @brief The warning messages of this container
|
||||
*/
|
||||
std::vector<std::string> warnings;
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
149
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h
vendored
Normal file
149
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ExtensibleObject.h
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
#pragma once
|
||||
|
||||
#include "JsonValue.h"
|
||||
#include "Library.h"
|
||||
|
||||
#include <any>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief The base class for objects that have extensions and extras.
|
||||
*/
|
||||
struct CESIUMUTILITY_API ExtensibleObject {
|
||||
/**
|
||||
* @brief Checks if an extension exists given its static type.
|
||||
*
|
||||
* @tparam T The type of the extension.
|
||||
* @return A boolean indicating whether the extension exists.
|
||||
*/
|
||||
template <typename T> bool hasExtension() const noexcept {
|
||||
auto it = this->extensions.find(T::ExtensionName);
|
||||
return it != this->extensions.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets an extension given its static type.
|
||||
*
|
||||
* @tparam T The type of the extension.
|
||||
* @return A pointer to the extension, or nullptr if the extension is not
|
||||
* attached to this object.
|
||||
*/
|
||||
template <typename T> const T* getExtension() const noexcept {
|
||||
auto it = this->extensions.find(T::ExtensionName);
|
||||
if (it == this->extensions.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::any_cast<T>(&it->second);
|
||||
}
|
||||
|
||||
/** @copydoc ExtensibleObject::getExtension */
|
||||
template <typename T> T* getExtension() noexcept {
|
||||
return const_cast<T*>(std::as_const(*this).getExtension<T>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a generic extension with the given name as a
|
||||
* {@link CesiumUtility::JsonValue}.
|
||||
*
|
||||
* If the extension exists but has a static type, this method will return
|
||||
* nullptr. Use {@link getExtension} to retrieve a statically-typed extension.
|
||||
*
|
||||
* @param extensionName The name of the extension.
|
||||
* @return The generic extension, or nullptr if the generic extension doesn't
|
||||
* exist.
|
||||
*/
|
||||
const JsonValue*
|
||||
getGenericExtension(const std::string& extensionName) const noexcept;
|
||||
|
||||
/** @copydoc ExtensibleObject::getGenericExtension */
|
||||
JsonValue* getGenericExtension(const std::string& extensionName) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Adds a statically-typed extension to this object.
|
||||
*
|
||||
* If the extension already exists, the existing one is returned.
|
||||
*
|
||||
* @tparam T The type of the extension to add.
|
||||
* @return The added extension.
|
||||
*/
|
||||
template <typename T, typename... ConstructorArgumentTypes>
|
||||
T& addExtension(ConstructorArgumentTypes&&... constructorArguments) {
|
||||
std::any& extension =
|
||||
extensions
|
||||
.try_emplace(
|
||||
T::ExtensionName,
|
||||
std::make_any<T>(std::forward<ConstructorArgumentTypes>(
|
||||
constructorArguments)...))
|
||||
.first->second;
|
||||
return std::any_cast<T&>(extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes a statically-typed extension from this object.
|
||||
*
|
||||
* @tparam T The type of the extension to remove.
|
||||
*/
|
||||
template <typename T> void removeExtension() {
|
||||
extensions.erase(T::ExtensionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The extensions attached to this object.
|
||||
*
|
||||
* Use {@link getExtension} to get the extension with a particular static
|
||||
* type. Use {@link getGenericExtension} to get unknown extensions as a
|
||||
* generic {@link CesiumUtility::JsonValue}.
|
||||
*/
|
||||
std::unordered_map<std::string, std::any> extensions;
|
||||
|
||||
/**
|
||||
* @brief Application-specific data.
|
||||
*
|
||||
* **Implementation Note:** Although extras may have any type, it is common
|
||||
* for applications to store and access custom data as key/value pairs. As
|
||||
* best practice, extras should be an Object rather than a primitive value for
|
||||
* best portability.
|
||||
*/
|
||||
JsonValue::Object extras;
|
||||
|
||||
/**
|
||||
* @brief Unknown properties that exist on this object but do not have any
|
||||
* representation in the statically-typed classes.
|
||||
*
|
||||
* These properties may be invalid, or they may represent deprecated,
|
||||
* experimental, or next-version properties.
|
||||
*/
|
||||
JsonValue::Object unknownProperties;
|
||||
|
||||
/**
|
||||
* @brief Calculates the size in bytes of this ExtensibleObject, including all
|
||||
* of its extras but NOT including its extensions. Calling this method may be
|
||||
* slow as it requires traversing the entire object.
|
||||
*/
|
||||
int64_t getSizeBytes() const {
|
||||
int64_t accum = 0;
|
||||
accum += int64_t(sizeof(ExtensibleObject));
|
||||
|
||||
accum += int64_t(
|
||||
this->extras.size() * (sizeof(std::string) + sizeof(JsonValue)));
|
||||
for (const auto& [k, v] : this->extras) {
|
||||
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
|
||||
accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
|
||||
}
|
||||
|
||||
accum += int64_t(
|
||||
this->unknownProperties.size() *
|
||||
(sizeof(std::string) + sizeof(JsonValue)));
|
||||
for (const auto& [k, v] : this->unknownProperties) {
|
||||
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
|
||||
accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
};
|
||||
} // namespace CesiumUtility
|
||||
44
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Gzip.h
vendored
Normal file
44
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Gzip.h
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Checks whether the data is gzipped.
|
||||
*
|
||||
* @param data The data.
|
||||
*
|
||||
* @returns Whether the data is gzipped
|
||||
*/
|
||||
bool isGzip(const std::span<const std::byte>& data);
|
||||
|
||||
/**
|
||||
* @brief Gzips data.
|
||||
*
|
||||
* If successful, it will return true and the result will be in the
|
||||
* provided vector.
|
||||
*
|
||||
* @param data The data to gzip.
|
||||
* @param out The gzipped data.
|
||||
*
|
||||
* @returns True if successful, false otherwise.
|
||||
*/
|
||||
bool gzip(const std::span<const std::byte>& data, std::vector<std::byte>& out);
|
||||
|
||||
/**
|
||||
* @brief Gunzips data.
|
||||
*
|
||||
* If successful, it will return true and the result will be in the
|
||||
* provided vector.
|
||||
*
|
||||
* @param data The data to gunzip.
|
||||
* @param out The gunzipped data.
|
||||
*
|
||||
* @returns True if successful, false otherwise.
|
||||
*/
|
||||
bool gunzip(
|
||||
const std::span<const std::byte>& data,
|
||||
std::vector<std::byte>& out);
|
||||
|
||||
} // namespace CesiumUtility
|
||||
23
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Hash.h
vendored
Normal file
23
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Hash.h
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Contains functions for working with hashes.
|
||||
*
|
||||
*/
|
||||
struct Hash {
|
||||
/**
|
||||
* @brief Combines two hash values, usually generated using `std::hash`, to
|
||||
* form a single hash value.
|
||||
*
|
||||
* @param first The first hash value.
|
||||
* @param second The second hash value.
|
||||
* @return A new hash value which is a combination of the two.
|
||||
*/
|
||||
static std::size_t combine(std::size_t first, std::size_t second);
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
43
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IDepotOwningAsset.h
vendored
Normal file
43
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IDepotOwningAsset.h
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief An interface representing the depot that owns a {@link SharedAsset}.
|
||||
* This interface is an implementation detail of the shared asset system and
|
||||
* should not be used directly.
|
||||
*
|
||||
* {@link SharedAsset} has a pointer to the asset depot that owns it using this
|
||||
* interface, rather than a complete {@link CesiumAsync::SharedAssetDepot}, in
|
||||
* order to "erase" the type of the asset key. This allows SharedAsset to be
|
||||
* templatized only on the asset type, not on the asset key type.
|
||||
*/
|
||||
template <typename TAssetType> class IDepotOwningAsset {
|
||||
public:
|
||||
virtual ~IDepotOwningAsset() {}
|
||||
|
||||
/**
|
||||
* @brief Marks the given asset as a candidate for deletion.
|
||||
* Should only be called by {@link SharedAsset}. May be called from any thread.
|
||||
*
|
||||
* @param asset The asset to mark for deletion.
|
||||
* @param threadOwnsDepotLock True if the calling thread already owns the
|
||||
* depot lock; otherwise, false.
|
||||
*/
|
||||
virtual void
|
||||
markDeletionCandidate(const TAssetType& asset, bool threadOwnsDepotLock) = 0;
|
||||
|
||||
/**
|
||||
* @brief Unmarks the given asset as a candidate for deletion.
|
||||
* Should only be called by {@link SharedAsset}. May be called from any thread.
|
||||
*
|
||||
* @param asset The asset to unmark for deletion.
|
||||
* @param threadOwnsDepotLock True if the calling thread already owns the
|
||||
* depot lock; otherwise, false.
|
||||
*/
|
||||
virtual void unmarkDeletionCandidate(
|
||||
const TAssetType& asset,
|
||||
bool threadOwnsDepotLock) = 0;
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
241
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h
vendored
Normal file
241
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/IntrusivePointer.h
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
#pragma once
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief A smart pointer that calls `addReference` and `releaseReference` on
|
||||
* the controlled object.
|
||||
*
|
||||
* Please note that the thread-safety of this type is entirely dependent on the
|
||||
* implementation of `addReference` and `releaseReference`. If these methods are
|
||||
* not thread safe on a particular type - which is common for objects that are
|
||||
* not meant to be used from multiple threads simultaneously - then using an
|
||||
* `IntrusivePointer` from multiple threads is also unsafe.
|
||||
*
|
||||
* @tparam T The type of object controlled.
|
||||
*/
|
||||
template <class T> class IntrusivePointer final {
|
||||
public:
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
IntrusivePointer(T* p = nullptr) noexcept : _p(p) { this->addReference(); }
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
*/
|
||||
IntrusivePointer(const IntrusivePointer<T>& rhs) noexcept : _p(rhs._p) {
|
||||
this->addReference();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implicit conversion to a pointer to a base (or otherwise
|
||||
* convertible) type.
|
||||
*
|
||||
* @tparam U The new type, usually a base class.
|
||||
* @param rhs The pointer.
|
||||
*/
|
||||
template <class U>
|
||||
IntrusivePointer(const IntrusivePointer<U>& rhs) noexcept : _p(rhs._p) {
|
||||
this->addReference();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
*/
|
||||
IntrusivePointer(IntrusivePointer<T>&& rhs) noexcept
|
||||
: _p(std::exchange(rhs._p, nullptr)) {
|
||||
// Reference count is unchanged
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implicit conversion of an r-value to a pointer to a base (or
|
||||
* otherwise convertible) type.
|
||||
*
|
||||
* @tparam U The new type, usually a base class.
|
||||
* @param rhs The pointer.
|
||||
*/
|
||||
template <class U>
|
||||
IntrusivePointer(IntrusivePointer<U>&& rhs) noexcept
|
||||
: _p(std::exchange(rhs._p, nullptr)) {
|
||||
// Reference count is unchanged
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default destructor.
|
||||
*/
|
||||
~IntrusivePointer() noexcept { this->releaseReference(); }
|
||||
|
||||
/**
|
||||
* @brief Constructs a new instance and assigns it to this IntrusivePointer.
|
||||
* If this IntrusivePointer already points to another instance,
|
||||
* {@link releaseReference} is called on it.
|
||||
*
|
||||
* @param constructorArguments The arguments to the constructor to create the
|
||||
* new instance.
|
||||
* @return A reference to the newly-created instance.
|
||||
*/
|
||||
template <typename... ConstructorArgumentTypes>
|
||||
T& emplace(ConstructorArgumentTypes&&... constructorArguments) {
|
||||
*this =
|
||||
new T(std::forward<ConstructorArgumentTypes>(constructorArguments)...);
|
||||
return *this->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset this pointer to nullptr.
|
||||
*/
|
||||
void reset() { *this = nullptr; }
|
||||
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
*/
|
||||
IntrusivePointer& operator=(const IntrusivePointer& rhs) noexcept {
|
||||
if (this->_p != rhs._p) {
|
||||
// addReference the new pointer before releaseReference'ing the old.
|
||||
T* pOld = this->_p;
|
||||
this->_p = rhs._p;
|
||||
addReference();
|
||||
|
||||
if (pOld) {
|
||||
pOld->releaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns an \ref IntrusivePointer of another type to this \ref
|
||||
* IntrusivePointer.
|
||||
*/
|
||||
template <class U>
|
||||
IntrusivePointer& operator=(const IntrusivePointer<U>& rhs) noexcept {
|
||||
if (this->_p != rhs._p) {
|
||||
// addReference the new pointer before releaseReference'ing the old.
|
||||
T* pOld = this->_p;
|
||||
this->_p = rhs._p;
|
||||
addReference();
|
||||
|
||||
if (pOld) {
|
||||
pOld->releaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
*/
|
||||
IntrusivePointer& operator=(IntrusivePointer&& rhs) noexcept {
|
||||
if (this->_p != rhs._p) {
|
||||
std::swap(this->_p, rhs._p);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
*/
|
||||
IntrusivePointer& operator=(T* p) noexcept {
|
||||
if (this->_p != p) {
|
||||
// addReference the new pointer before releaseReference'ing the old.
|
||||
T* pOld = this->_p;
|
||||
this->_p = p;
|
||||
addReference();
|
||||
|
||||
if (pOld) {
|
||||
pOld->releaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dereferencing operator.
|
||||
*/
|
||||
T& operator*() const noexcept { return *this->_p; }
|
||||
|
||||
/**
|
||||
* @brief Arrow operator.
|
||||
*/
|
||||
T* operator->() const noexcept { return this->_p; }
|
||||
|
||||
/**
|
||||
* @brief Implicit conversion to `bool`, being `true` iff this is not the
|
||||
* `nullptr`.
|
||||
*/
|
||||
explicit operator bool() const noexcept { return this->_p != nullptr; }
|
||||
|
||||
/**
|
||||
* @brief Returns the internal pointer.
|
||||
*/
|
||||
T* get() const noexcept { return this->_p; }
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if two pointers are equal.
|
||||
*/
|
||||
bool operator==(const IntrusivePointer<T>& rhs) const noexcept {
|
||||
return this->_p == rhs._p;
|
||||
}
|
||||
|
||||
/** @brief Returns `true` if two pointers are equal. */
|
||||
template <class U>
|
||||
bool operator==(const IntrusivePointer<U>& rhs) const noexcept {
|
||||
return this->_p == rhs._p;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if two pointers are *not* equal.
|
||||
*/
|
||||
bool operator!=(const IntrusivePointer<T>& rhs) const noexcept {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if the contents of this pointer is equal to the given
|
||||
* pointer.
|
||||
*/
|
||||
bool operator==(const T* pRhs) const noexcept { return this->_p == pRhs; }
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if the contents of this pointer is *not* equal to the
|
||||
* given pointer.
|
||||
*/
|
||||
bool operator!=(const T* pRhs) const noexcept { return !(*this == pRhs); }
|
||||
|
||||
private:
|
||||
void addReference() noexcept {
|
||||
if (this->_p) {
|
||||
this->_p->addReference();
|
||||
}
|
||||
}
|
||||
|
||||
void releaseReference() noexcept {
|
||||
if (this->_p) {
|
||||
this->_p->releaseReference();
|
||||
}
|
||||
}
|
||||
|
||||
T* _p;
|
||||
template <typename U> friend class IntrusivePointer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Casts a `const` \ref IntrusivePointer to its non-const equivalent.
|
||||
*
|
||||
* @param p The `const` \ref IntrusivePointer.
|
||||
* @returns A non-const \ref IntrusivePointer with the same underlying pointer.
|
||||
*/
|
||||
template <typename T, typename U>
|
||||
IntrusivePointer<T>
|
||||
const_intrusive_cast(const IntrusivePointer<U>& p) noexcept {
|
||||
return IntrusivePointer<T>(const_cast<T*>(p.get()));
|
||||
}
|
||||
|
||||
} // namespace CesiumUtility
|
||||
246
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h
vendored
Normal file
246
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonHelpers.h
vendored
Normal file
@ -0,0 +1,246 @@
|
||||
#pragma once
|
||||
|
||||
#include <glm/fwd.hpp>
|
||||
#include <rapidjson/fwd.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief A collection of helper functions to make reading JSON simpler.
|
||||
*/
|
||||
class JsonHelpers final {
|
||||
public:
|
||||
/**
|
||||
* @brief Attempts to read the value at `key` of `tileJson` as a `double`,
|
||||
* returning std::nullopt if it wasn't found or couldn't be read as a double.
|
||||
*
|
||||
* @param tileJson The JSON object to obtain the scalar property from.
|
||||
* @param key The key of the scalar property to obtain.
|
||||
*/
|
||||
static std::optional<double>
|
||||
getScalarProperty(const rapidjson::Value& tileJson, const std::string& key);
|
||||
/**
|
||||
* @brief Attempts to read the value at `key` of `tileJson` as a
|
||||
* `glm::dmat4x4`, returning std::nullopt if it wasn't found or couldn't be
|
||||
* read as a glm::dmat4x4.
|
||||
*
|
||||
* @param tileJson The JSON object to obtain the transform property from.
|
||||
* @param key The key of the transform property.
|
||||
*/
|
||||
static std::optional<glm::dmat4x4> getTransformProperty(
|
||||
const rapidjson::Value& tileJson,
|
||||
const std::string& key);
|
||||
|
||||
/**
|
||||
* @brief Obtains an array of numbers from the given JSON.
|
||||
*
|
||||
* If the property is not found, or is not an array, or does contain
|
||||
* elements that are not numbers, then `std::nullopt` is returned.
|
||||
*
|
||||
* If the given expected size is not negative, and the actual size of the
|
||||
* array does not match the expected size, then `nullopt` is returned.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param expectedSize The expected size of the array.
|
||||
* @param key The key (property name) of the array.
|
||||
* @return The array, or `nullopt`.
|
||||
*/
|
||||
static std::optional<std::vector<double>> getDoubles(
|
||||
const rapidjson::Value& json,
|
||||
int32_t expectedSize,
|
||||
const std::string& key);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a string from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the string.
|
||||
* @param defaultValue The default value to return if the string property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static std::string getStringOrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
const std::string& defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a string, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a string.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a string.
|
||||
*/
|
||||
static std::string getStringOrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a double from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the double.
|
||||
* @param defaultValue The default value to return if the double property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static double getDoubleOrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
double defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a double, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a double.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a double.
|
||||
*/
|
||||
static double
|
||||
getDoubleOrDefault(const rapidjson::Value& json, double defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a uint32_t from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the uint32_t.
|
||||
* @param defaultValue The default value to return if the uint32_t property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static uint32_t getUint32OrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
uint32_t defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a uint32_t, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a uint32_t.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a uint32_t.
|
||||
*/
|
||||
static uint32_t
|
||||
getUint32OrDefault(const rapidjson::Value& json, uint32_t defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a int32_t from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the int32_t.
|
||||
* @param defaultValue The default value to return if the int32_t property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static int32_t getInt32OrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
int32_t defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a int32_t, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a int32_t.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a int32_t.
|
||||
*/
|
||||
static int32_t
|
||||
getInt32OrDefault(const rapidjson::Value& json, int32_t defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a uint64_t from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the uint64_t.
|
||||
* @param defaultValue The default value to return if the uint64_t property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static uint64_t getUint64OrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
uint64_t defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a uint64_t, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a uint64_t.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a uint64_t.
|
||||
*/
|
||||
static uint64_t
|
||||
getUint64OrDefault(const rapidjson::Value& json, uint64_t defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a int64_t from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the int64_t.
|
||||
* @param defaultValue The default value to return if the int64_t property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static int64_t getInt64OrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
int64_t defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a int64_t, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a int64_t.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a int64_t.
|
||||
*/
|
||||
static int64_t
|
||||
getInt64OrDefault(const rapidjson::Value& json, int64_t defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a bool from the given key on the JSON object,
|
||||
* returning a default value if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the bool.
|
||||
* @param defaultValue The default value to return if the bool property
|
||||
* `key` of `json` couldn't be read.
|
||||
*/
|
||||
static bool getBoolOrDefault(
|
||||
const rapidjson::Value& json,
|
||||
const std::string& key,
|
||||
bool defaultValue);
|
||||
/**
|
||||
* @brief Attempts to read `json` as a bool, returning a default value if
|
||||
* this isn't possible.
|
||||
*
|
||||
* @param json The JSON value that might be a bool.
|
||||
* @param defaultValue The default value to return if `json` couldn't be read
|
||||
* as a bool.
|
||||
*/
|
||||
static bool getBoolOrDefault(const rapidjson::Value& json, bool defaultValue);
|
||||
|
||||
/**
|
||||
* @brief Attempts to read an array of strings from the property `key` of
|
||||
* `json`, returning an empty vector if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the string array.
|
||||
*/
|
||||
static std::vector<std::string>
|
||||
getStrings(const rapidjson::Value& json, const std::string& key);
|
||||
|
||||
/**
|
||||
* @brief Attempts to read an int64_t array from the property `key` of
|
||||
* `json`, returning an empty vector if this isn't possible.
|
||||
*
|
||||
* @param json The JSON object.
|
||||
* @param key The key (property name) of the int64_t array.
|
||||
*/
|
||||
static std::vector<int64_t>
|
||||
getInt64s(const rapidjson::Value& json, const std::string& key);
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
712
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h
vendored
Normal file
712
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/JsonValue.h
vendored
Normal file
@ -0,0 +1,712 @@
|
||||
#pragma once
|
||||
|
||||
#include "Library.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <initializer_list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Attempts a narrowing conversion of `U` into `T` without losing
|
||||
* information. If a lossless conversion can't be performed, `std::nullopt` is
|
||||
* returned.
|
||||
*
|
||||
* @tparam U The type to convert from.
|
||||
* @tparam T The type to convert to.
|
||||
* @param u The value to perform the conversion on.
|
||||
*/
|
||||
template <typename T, typename U>
|
||||
constexpr std::optional<T> losslessNarrow(U u) noexcept {
|
||||
constexpr const bool is_different_signedness =
|
||||
(std::is_signed<T>::value != std::is_signed<U>::value);
|
||||
|
||||
const T t = static_cast<T>(u);
|
||||
|
||||
if (static_cast<U>(t) != u ||
|
||||
(is_different_signedness && ((t < T{}) != (u < U{})))) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attempts a narrowing conversion of `U` into `T` without losing
|
||||
* information. If a lossless conversion can't be performed, `defaultValue` is
|
||||
* returned.
|
||||
*
|
||||
* @tparam U The type to convert from.
|
||||
* @tparam T The type to convert to.
|
||||
* @param u The value to perform the conversion on.
|
||||
* @param defaultValue The value that will be returned if a lossless conversion
|
||||
* can't be performed.
|
||||
*/
|
||||
template <typename T, typename U>
|
||||
constexpr T losslessNarrowOrDefault(U u, T defaultValue) noexcept {
|
||||
constexpr const bool is_different_signedness =
|
||||
(std::is_signed<T>::value != std::is_signed<U>::value);
|
||||
|
||||
const T t = static_cast<T>(u);
|
||||
|
||||
if (static_cast<U>(t) != u ||
|
||||
(is_different_signedness && ((t < T{}) != (u < U{})))) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A generic implementation of a value in a JSON structure.
|
||||
*
|
||||
* Instances of this class are used to represent the common `extras` field
|
||||
* of glTF elements that extend the the {@link ExtensibleObject} class.
|
||||
*/
|
||||
class CESIUMUTILITY_API JsonValue final {
|
||||
public:
|
||||
/**
|
||||
* @brief The type to represent a `null` JSON value.
|
||||
*/
|
||||
using Null = std::nullptr_t;
|
||||
|
||||
/**
|
||||
* @brief The type to represent a `Bool` JSON value.
|
||||
*/
|
||||
using Bool = bool;
|
||||
|
||||
/**
|
||||
* @brief The type to represent a `String` JSON value.
|
||||
*/
|
||||
using String = std::string;
|
||||
|
||||
/**
|
||||
* @brief The type to represent an `Object` JSON value.
|
||||
*/
|
||||
using Object = std::map<std::string, JsonValue>;
|
||||
|
||||
/**
|
||||
* @brief The type to represent an `Array` JSON value.
|
||||
*/
|
||||
using Array = std::vector<JsonValue>;
|
||||
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
*/
|
||||
JsonValue() noexcept : value() {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `null` JSON value.
|
||||
*/
|
||||
JsonValue(std::nullptr_t) noexcept : value(nullptr) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Number` JSON value.
|
||||
*
|
||||
* NaN and ±Infinity are represented as {@link JsonValue::Null}.
|
||||
*/
|
||||
JsonValue(double v) noexcept {
|
||||
if (std::isnan(v) || std::isinf(v)) {
|
||||
value = nullptr;
|
||||
} else {
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::int64_t` JSON value (Widening conversion from
|
||||
* std::int8_t).
|
||||
*/
|
||||
JsonValue(std::int8_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::uint64_t` JSON value (Widening conversion from
|
||||
* std::uint8_t).
|
||||
*/
|
||||
JsonValue(std::uint8_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::int64_t` JSON value (Widening conversion from
|
||||
* std::int16_t).
|
||||
*/
|
||||
JsonValue(std::int16_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::uint64_t` JSON value (Widening conversion from
|
||||
* std::uint16_t).
|
||||
*/
|
||||
JsonValue(std::uint16_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::int64_t` JSON value (Widening conversion from
|
||||
* std::int32_t).
|
||||
*/
|
||||
JsonValue(std::int32_t v) noexcept : value(static_cast<std::int64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::uint64_t` JSON value (Widening conversion from
|
||||
* std::uint32_t).
|
||||
*/
|
||||
JsonValue(std::uint32_t v) noexcept : value(static_cast<std::uint64_t>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::int64_t` JSON value.
|
||||
*/
|
||||
JsonValue(std::int64_t v) noexcept : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `std::uint64_t` JSON value.
|
||||
*/
|
||||
JsonValue(std::uint64_t v) noexcept : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Bool` JSON value.
|
||||
*/
|
||||
JsonValue(bool v) noexcept : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `String` JSON value.
|
||||
*/
|
||||
JsonValue(const std::string& v) : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `String` JSON value.
|
||||
*/
|
||||
JsonValue(std::string&& v) noexcept : value(std::move(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `String` JSON value.
|
||||
*/
|
||||
JsonValue(const char* v) : value(std::string(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an `Object` JSON value with the given properties.
|
||||
*/
|
||||
JsonValue(const std::map<std::string, JsonValue>& v) : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an `Object` JSON value with the given properties.
|
||||
*/
|
||||
JsonValue(std::map<std::string, JsonValue>&& v) : value(std::move(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an `Array` JSON value with the given elements.
|
||||
*/
|
||||
JsonValue(const std::vector<JsonValue>& v) : value(v) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an `Array` JSON value with the given elements.
|
||||
*/
|
||||
JsonValue(std::vector<JsonValue>&& v) noexcept : value(std::move(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an JSON value from the given initializer list.
|
||||
*/
|
||||
JsonValue(std::initializer_list<JsonValue> v)
|
||||
: value(std::vector<JsonValue>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates an JSON value from the given initializer list.
|
||||
*/
|
||||
JsonValue(std::initializer_list<std::pair<const std::string, JsonValue>> v)
|
||||
: value(std::map<std::string, JsonValue>(v)) {}
|
||||
|
||||
/**
|
||||
* @brief Attempts to obtain a pointer to a \ref JsonValue for the given key
|
||||
* on this object.
|
||||
*
|
||||
* @param key The key to lookup.
|
||||
* @returns A pointer to the \ref JsonValue for the provided key, or
|
||||
* `nullptr`.
|
||||
*/
|
||||
[[nodiscard]] const JsonValue*
|
||||
getValuePtrForKey(const std::string& key) const;
|
||||
/** @copydoc getValuePtrForKey */
|
||||
[[nodiscard]] JsonValue* getValuePtrForKey(const std::string& key);
|
||||
|
||||
/**
|
||||
* @brief Gets a typed value corresponding to the given key in the
|
||||
* object represented by this instance.
|
||||
*
|
||||
* If this instance is not a {@link JsonValue::Object}, returns
|
||||
* `nullptr`. If the key does not exist in this object, returns
|
||||
* `nullptr`. If the named value does not have the type T, returns
|
||||
* nullptr.
|
||||
*
|
||||
* @tparam T The expected type of the value.
|
||||
* @param key The key for which to retrieve the value from this object.
|
||||
* @return A pointer to the requested value, or nullptr if the value
|
||||
* cannot be obtained as requested.
|
||||
*/
|
||||
template <typename T>
|
||||
const T* getValuePtrForKey(const std::string& key) const {
|
||||
const JsonValue* pValue = this->getValuePtrForKey(key);
|
||||
if (!pValue) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::get_if<T>(&pValue->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a typed value corresponding to the given key in the
|
||||
* object represented by this instance.
|
||||
*
|
||||
* If this instance is not a {@link JsonValue::Object}, returns
|
||||
* `nullptr`. If the key does not exist in this object, returns
|
||||
* `nullptr`. If the named value does not have the type T, returns
|
||||
* nullptr.
|
||||
*
|
||||
* @tparam T The expected type of the value.
|
||||
* @param key The key for which to retrieve the value from this object.
|
||||
* @return A pointer to the requested value, or nullptr if the value
|
||||
* cannot be obtained as requested.
|
||||
*/
|
||||
template <typename T> T* getValuePtrForKey(const std::string& key) {
|
||||
JsonValue* pValue = this->getValuePtrForKey(key);
|
||||
return std::get_if<T>(&pValue->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts the numerical value corresponding to the given key
|
||||
* to the provided numerical template type.
|
||||
|
||||
* If this instance is not a {@link JsonValue::Object}, the key does not exist
|
||||
* in this object, the named value does not have a numerical type, or if the
|
||||
* named value cannot be converted from `double` / `std::uint64_t` /
|
||||
* `std::int64_t` without precision loss, returns `std::nullopt`.
|
||||
* @tparam To The expected type of the value.
|
||||
* @param key The key for which to retrieve the value from this object.
|
||||
* @return The converted value, or std::nullopt if it cannot be converted for
|
||||
* any of the previously-mentioned reasons.
|
||||
* @remarks Compilation will fail if type 'To' is not an integral / float /
|
||||
* double type.
|
||||
*/
|
||||
template <
|
||||
typename To,
|
||||
typename std::enable_if<
|
||||
std::is_integral<To>::value ||
|
||||
std::is_floating_point<To>::value>::type* = nullptr>
|
||||
[[nodiscard]] std::optional<To>
|
||||
getSafeNumericalValueForKey(const std::string& key) const {
|
||||
const Object& pObject = std::get<Object>(this->value);
|
||||
const auto it = pObject.find(key);
|
||||
if (it == pObject.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return it->second.getSafeNumber<To>();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts the numerical value corresponding to the given key
|
||||
* to the provided numerical template type.
|
||||
*
|
||||
* If this instance is not a {@link JsonValue::Object}, the key does not exist
|
||||
* in this object, or the named value does not have a numerical type that can
|
||||
* be represented as T without precision loss, then the default value is
|
||||
* returned.
|
||||
*
|
||||
* @tparam To The expected type of the value.
|
||||
* @param key The key for which to retrieve the value from this object.
|
||||
* @param defaultValue The value that will be returned if a numerical value
|
||||
* can't be obtained.
|
||||
* @return The converted value.
|
||||
* @throws If unable to convert the converted value for one of the
|
||||
* aforementioned reasons.
|
||||
* @remarks Compilation will fail if type 'To' is not an integral / float /
|
||||
* double type.
|
||||
*/
|
||||
template <
|
||||
typename To,
|
||||
typename std::enable_if<
|
||||
std::is_integral<To>::value ||
|
||||
std::is_floating_point<To>::value>::type* = nullptr>
|
||||
[[nodiscard]] To getSafeNumericalValueOrDefaultForKey(
|
||||
const std::string& key,
|
||||
To defaultValue) const {
|
||||
const Object& pObject = std::get<Object>(this->value);
|
||||
const auto it = pObject.find(key);
|
||||
if (it == pObject.end()) {
|
||||
return defaultValue;
|
||||
}
|
||||
return it->second.getSafeNumberOrDefault<To>(defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if this value is an Object and has the given key.
|
||||
*
|
||||
* @param key The key.
|
||||
* @return true if this value contains the key. false if it is not an object
|
||||
* or does not contain the given key.
|
||||
*/
|
||||
[[nodiscard]] inline bool hasKey(const std::string& key) const {
|
||||
const Object* pObject = std::get_if<Object>(&this->value);
|
||||
if (!pObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pObject->find(key) != pObject->end();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the numerical quantity from the value casted to the `To`
|
||||
* type. This function should be used over `getDouble()` / `getUint64()` /
|
||||
* `getInt64()` if you plan on casting that type into another smaller type or
|
||||
* different type.
|
||||
* @returns The converted type if it is numerical and it can be cast without
|
||||
* precision loss; otherwise, std::nullopt.
|
||||
*/
|
||||
template <
|
||||
typename To,
|
||||
typename std::enable_if<
|
||||
std::is_integral<To>::value ||
|
||||
std::is_floating_point<To>::value>::type* = nullptr>
|
||||
[[nodiscard]] std::optional<To> getSafeNumber() const {
|
||||
const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
|
||||
if (uInt) {
|
||||
return losslessNarrow<To>(*uInt);
|
||||
}
|
||||
|
||||
const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
|
||||
if (sInt) {
|
||||
return losslessNarrow<To>(*sInt);
|
||||
}
|
||||
|
||||
const double* real = std::get_if<double>(&this->value);
|
||||
if (real) {
|
||||
return losslessNarrow<To>(*real);
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the numerical quantity from the value casted to the `To`
|
||||
* type or returns defaultValue if unable to do so.
|
||||
|
||||
* @returns The converted type if it can be cast without precision loss
|
||||
* or `defaultValue` if it cannot be converted safely.
|
||||
*/
|
||||
template <
|
||||
typename To,
|
||||
typename std::enable_if<
|
||||
std::is_integral<To>::value ||
|
||||
std::is_floating_point<To>::value>::type* = nullptr>
|
||||
[[nodiscard]] To getSafeNumberOrDefault(To defaultValue) const noexcept {
|
||||
const std::uint64_t* uInt = std::get_if<std::uint64_t>(&this->value);
|
||||
if (uInt) {
|
||||
return losslessNarrowOrDefault<To>(*uInt, defaultValue);
|
||||
}
|
||||
|
||||
const std::int64_t* sInt = std::get_if<std::int64_t>(&this->value);
|
||||
if (sInt) {
|
||||
return losslessNarrowOrDefault<To>(*sInt, defaultValue);
|
||||
}
|
||||
|
||||
const double* real = std::get_if<double>(&this->value);
|
||||
if (real) {
|
||||
return losslessNarrowOrDefault<To>(*real, defaultValue);
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the object from the value.
|
||||
* @return The object.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* JsonValue::Object
|
||||
*/
|
||||
|
||||
[[nodiscard]] inline const JsonValue::Object& getObject() const {
|
||||
return std::get<JsonValue::Object>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the string from the value.
|
||||
* @return The string.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* JsonValue::String
|
||||
*/
|
||||
[[nodiscard]] inline const JsonValue::String& getString() const {
|
||||
return std::get<String>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the array from the value.
|
||||
* @return The array.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* JsonValue::Array
|
||||
*/
|
||||
[[nodiscard]] inline const JsonValue::Array& getArray() const {
|
||||
return std::get<JsonValue::Array>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets an array of strings from the value.
|
||||
*
|
||||
* @param defaultString The default string to include in the array for an
|
||||
* element that is not a string.
|
||||
* @return The array of strings, or an empty array if this value is not an
|
||||
* array at all.
|
||||
*/
|
||||
[[nodiscard]] std::vector<std::string>
|
||||
getArrayOfStrings(const std::string& defaultString) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the bool from the value.
|
||||
* @return The bool.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* JsonValue::Bool
|
||||
*/
|
||||
[[nodiscard]] inline bool getBool() const {
|
||||
return std::get<bool>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the double from the value.
|
||||
* @return The double.
|
||||
* @throws std::bad_variant_access if the underlying type is not a double
|
||||
*/
|
||||
[[nodiscard]] inline double getDouble() const {
|
||||
return std::get<double>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the std::uint64_t from the value.
|
||||
* @return The std::uint64_t.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* std::uint64_t
|
||||
*/
|
||||
[[nodiscard]] std::uint64_t getUint64() const {
|
||||
return std::get<std::uint64_t>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the std::int64_t from the value.
|
||||
* @return The std::int64_t.
|
||||
* @throws std::bad_variant_access if the underlying type is not a
|
||||
* std::int64_t
|
||||
*/
|
||||
[[nodiscard]] std::int64_t getInt64() const {
|
||||
return std::get<std::int64_t>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the bool from the value or returns defaultValue
|
||||
* @return The bool or defaultValue if this->value is not a bool.
|
||||
*/
|
||||
[[nodiscard]] inline bool getBoolOrDefault(bool defaultValue) const noexcept {
|
||||
const auto* v = std::get_if<bool>(&this->value);
|
||||
if (v) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the string from the value or returns defaultValue
|
||||
* @return The string or defaultValue if this->value is not a string.
|
||||
*/
|
||||
[[nodiscard]] inline const JsonValue::String
|
||||
getStringOrDefault(String defaultValue) const {
|
||||
const auto* v = std::get_if<JsonValue::String>(&this->value);
|
||||
if (v) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the double from the value or returns defaultValue
|
||||
* @return The double or defaultValue if this->value is not a double.
|
||||
*/
|
||||
[[nodiscard]] inline double
|
||||
getDoubleOrDefault(double defaultValue) const noexcept {
|
||||
const auto* v = std::get_if<double>(&this->value);
|
||||
if (v) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the uint64_t from the value or returns defaultValue
|
||||
* @return The uint64_t or defaultValue if this->value is not a uint64_t.
|
||||
*/
|
||||
[[nodiscard]] inline std::uint64_t
|
||||
getUint64OrDefault(std::uint64_t defaultValue) const noexcept {
|
||||
const auto* v = std::get_if<std::uint64_t>(&this->value);
|
||||
if (v) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the int64_t from the value or returns defaultValue
|
||||
* @return The int64_t or defaultValue if this->value is not a int64_t.
|
||||
*/
|
||||
[[nodiscard]] inline std::int64_t
|
||||
getInt64OrDefault(std::int64_t defaultValue) const noexcept {
|
||||
const auto* v = std::get_if<std::int64_t>(&this->value);
|
||||
if (v) {
|
||||
return *v;
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `null` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isNull() const noexcept {
|
||||
return std::holds_alternative<Null>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `double`, `std::uint64_t` or
|
||||
* `std::int64_t`. Use this function in conjunction with `getNumber` for
|
||||
* safely casting to arbitrary types
|
||||
*/
|
||||
[[nodiscard]] inline bool isNumber() const noexcept {
|
||||
return isDouble() || isUint64() || isInt64();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `Bool` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isBool() const noexcept {
|
||||
return std::holds_alternative<Bool>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `String` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isString() const noexcept {
|
||||
return std::holds_alternative<String>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is an `Object` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isObject() const noexcept {
|
||||
return std::holds_alternative<Object>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is an `Array` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isArray() const noexcept {
|
||||
return std::holds_alternative<Array>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `double` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isDouble() const noexcept {
|
||||
return std::holds_alternative<double>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `std::uint64_t` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isUint64() const noexcept {
|
||||
return std::holds_alternative<std::uint64_t>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns whether this value is a `std::int64_t` value.
|
||||
*/
|
||||
[[nodiscard]] inline bool isInt64() const noexcept {
|
||||
return std::holds_alternative<std::int64_t>(this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns `true` if two values are equal.
|
||||
*/
|
||||
inline bool operator==(const JsonValue& rhs) const noexcept {
|
||||
return this->value == rhs.value;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns the size in bytes of this `JsonValue`.
|
||||
*/
|
||||
int64_t getSizeBytes() const noexcept {
|
||||
struct Operation {
|
||||
int64_t operator()([[maybe_unused]] const Null& /*inside*/) { return 0; }
|
||||
int64_t operator()([[maybe_unused]] const double& /*inside*/) {
|
||||
return 0;
|
||||
}
|
||||
int64_t operator()([[maybe_unused]] const std::uint64_t& /*inside*/) {
|
||||
return 0;
|
||||
}
|
||||
int64_t operator()([[maybe_unused]] const std::int64_t& /*inside*/) {
|
||||
return 0;
|
||||
}
|
||||
int64_t operator()([[maybe_unused]] const Bool& /*inside*/) { return 0; }
|
||||
int64_t operator()(const String& inside) {
|
||||
return int64_t(inside.capacity() * sizeof(char));
|
||||
}
|
||||
int64_t operator()(const Object& inside) {
|
||||
int64_t accum = 0;
|
||||
accum +=
|
||||
int64_t(inside.size() * (sizeof(std::string) + sizeof(JsonValue)));
|
||||
for (const auto& [k, v] : inside) {
|
||||
accum += int64_t(k.capacity() * sizeof(char) - sizeof(std::string));
|
||||
accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
|
||||
}
|
||||
|
||||
return accum;
|
||||
}
|
||||
int64_t operator()(const Array& inside) {
|
||||
int64_t accum = 0;
|
||||
accum += int64_t(sizeof(JsonValue) * inside.capacity());
|
||||
for (const JsonValue& v : inside) {
|
||||
accum += v.getSizeBytes() - int64_t(sizeof(JsonValue));
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
};
|
||||
|
||||
return static_cast<int64_t>(sizeof(JsonValue)) +
|
||||
std::visit(Operation{}, this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The actual value.
|
||||
*
|
||||
* The type of the value may be queried with the `isNull`, `isDouble`,
|
||||
* `isBool`, `isString`, `isObject`, `isUint64`, `isInt64`, `isNumber`, and
|
||||
* `isArray` functions.
|
||||
*
|
||||
* The actual value may be obtained with the `getNumber`, `getBool`,
|
||||
* and `getString` functions for the respective types. For
|
||||
* `Object` values, the properties may be accessed with the
|
||||
* `getValueForKey` functions.
|
||||
*/
|
||||
std::variant<
|
||||
Null,
|
||||
double,
|
||||
std::uint64_t,
|
||||
std::int64_t,
|
||||
Bool,
|
||||
String,
|
||||
Object,
|
||||
Array>
|
||||
value;
|
||||
};
|
||||
} // namespace CesiumUtility
|
||||
18
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h
vendored
Normal file
18
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Library.h
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Utility classes for Cesium
|
||||
*
|
||||
* @mermaid-interactive{dependencies/CesiumUtility}
|
||||
*/
|
||||
namespace CesiumUtility {}
|
||||
|
||||
#if defined(_WIN32) && defined(CESIUM_SHARED)
|
||||
#ifdef CESIUMUTILITY_BUILDING
|
||||
#define CESIUMUTILITY_API __declspec(dllexport)
|
||||
#else
|
||||
#define CESIUMUTILITY_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define CESIUMUTILITY_API
|
||||
#endif
|
||||
73
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Log.h
vendored
Normal file
73
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Log.h
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
#include <rapidjson/document.h>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
|
||||
/** @cond Doxygen_Exclude */
|
||||
template <>
|
||||
struct fmt::formatter<rapidjson::ParseErrorCode> : formatter<string_view> {
|
||||
// parse is inherited from formatter<string_view>.
|
||||
|
||||
auto format(rapidjson::ParseErrorCode code, format_context& ctx) const {
|
||||
string_view name = "unknown";
|
||||
switch (code) {
|
||||
case rapidjson::ParseErrorCode::kParseErrorNone:
|
||||
name = "No error.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorDocumentEmpty:
|
||||
name = "The document is empty.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorDocumentRootNotSingular:
|
||||
name = "The document root must not follow by other values.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorValueInvalid:
|
||||
name = "Invalid value.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorObjectMissName:
|
||||
name = "Missing a name for object member.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorObjectMissColon:
|
||||
name = "Missing a colon after a name of object member.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorObjectMissCommaOrCurlyBracket:
|
||||
name = "Missing a comma or '}' after an object member.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorArrayMissCommaOrSquareBracket:
|
||||
name = "Missing a comma or ']' after an array element.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorStringUnicodeEscapeInvalidHex:
|
||||
name = "Incorrect hex digit after \\u escape in string.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorStringUnicodeSurrogateInvalid:
|
||||
name = "The surrogate pair in string is invalid.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorStringEscapeInvalid:
|
||||
name = "Invalid escape character in string.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorStringMissQuotationMark:
|
||||
name = "Missing a closing quotation mark in string.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorStringInvalidEncoding:
|
||||
name = "Invalid encoding in string.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorNumberTooBig:
|
||||
name = "Number too big to be stored in double.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorNumberMissFraction:
|
||||
name = "Miss fraction part in number.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorNumberMissExponent:
|
||||
name = "Miss exponent in number.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorTermination:
|
||||
name = "Parsing was terminated.";
|
||||
break;
|
||||
case rapidjson::ParseErrorCode::kParseErrorUnspecificSyntaxError:
|
||||
name = "Unspecific syntax error.";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return formatter<string_view>::format(name, ctx);
|
||||
}
|
||||
};
|
||||
/** @endcond */
|
||||
503
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h
vendored
Normal file
503
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Math.h
vendored
Normal file
@ -0,0 +1,503 @@
|
||||
#pragma once
|
||||
|
||||
#include "Library.h"
|
||||
|
||||
#include <glm/gtc/epsilon.hpp>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Mathematical constants and functions
|
||||
*/
|
||||
class CESIUMUTILITY_API Math final {
|
||||
public:
|
||||
/** @brief 0.1 */
|
||||
static constexpr double Epsilon1 = 1e-1;
|
||||
|
||||
/** @brief 0.01 */
|
||||
static constexpr double Epsilon2 = 1e-2;
|
||||
|
||||
/** @brief 0.001 */
|
||||
static constexpr double Epsilon3 = 1e-3;
|
||||
|
||||
/** @brief 0.0001 */
|
||||
static constexpr double Epsilon4 = 1e-4;
|
||||
|
||||
/** @brief 0.00001 */
|
||||
static constexpr double Epsilon5 = 1e-5;
|
||||
|
||||
/** @brief 0.000001 */
|
||||
static constexpr double Epsilon6 = 1e-6;
|
||||
|
||||
/** @brief 0.0000001 */
|
||||
static constexpr double Epsilon7 = 1e-7;
|
||||
|
||||
/** @brief 0.00000001 */
|
||||
static constexpr double Epsilon8 = 1e-8;
|
||||
|
||||
/** @brief 0.000000001 */
|
||||
static constexpr double Epsilon9 = 1e-9;
|
||||
|
||||
/** @brief 0.0000000001 */
|
||||
static constexpr double Epsilon10 = 1e-10;
|
||||
|
||||
/** @brief 0.00000000001 */
|
||||
static constexpr double Epsilon11 = 1e-11;
|
||||
|
||||
/** @brief 0.000000000001 */
|
||||
static constexpr double Epsilon12 = 1e-12;
|
||||
|
||||
/** @brief 0.0000000000001 */
|
||||
static constexpr double Epsilon13 = 1e-13;
|
||||
|
||||
/** @brief 0.00000000000001 */
|
||||
static constexpr double Epsilon14 = 1e-14;
|
||||
|
||||
/** @brief 0.000000000000001 */
|
||||
static constexpr double Epsilon15 = 1e-15;
|
||||
|
||||
/** @brief 0.0000000000000001 */
|
||||
static constexpr double Epsilon16 = 1e-16;
|
||||
|
||||
/** @brief 0.00000000000000001 */
|
||||
static constexpr double Epsilon17 = 1e-17;
|
||||
|
||||
/** @brief 0.000000000000000001 */
|
||||
static constexpr double Epsilon18 = 1e-18;
|
||||
|
||||
/** @brief 0.0000000000000000001 */
|
||||
static constexpr double Epsilon19 = 1e-19;
|
||||
|
||||
/** @brief 0.00000000000000000001 */
|
||||
static constexpr double Epsilon20 = 1e-20;
|
||||
|
||||
/** @brief 0.000000000000000000001 */
|
||||
static constexpr double Epsilon21 = 1e-21;
|
||||
|
||||
/**
|
||||
* @brief pi
|
||||
*/
|
||||
static constexpr double OnePi = 3.14159265358979323846;
|
||||
|
||||
/**
|
||||
* @brief two times pi
|
||||
*/
|
||||
static constexpr double TwoPi = OnePi * 2.0;
|
||||
|
||||
/**
|
||||
* @brief pi divded by two
|
||||
*/
|
||||
static constexpr double PiOverTwo = OnePi / 2.0;
|
||||
|
||||
/**
|
||||
* @brief Converts a relative to an absolute epsilon, for the epsilon-equality
|
||||
* check between two values.
|
||||
*
|
||||
* @tparam L The length type.
|
||||
* @tparam T value value type.
|
||||
* @tparam Q The GLM qualifier type.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
* @param relativeEpsilon The relative epsilon.
|
||||
* @return The absolute epsilon.
|
||||
*/
|
||||
template <glm::length_t L, typename T, glm::qualifier Q>
|
||||
static constexpr glm::vec<L, T, Q> relativeEpsilonToAbsolute(
|
||||
const glm::vec<L, T, Q>& a,
|
||||
const glm::vec<L, T, Q>& b,
|
||||
double relativeEpsilon) noexcept {
|
||||
return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a relative to an absolute epsilon, for the epsilon-equality
|
||||
* check between two values.
|
||||
*
|
||||
* @param a The first value.
|
||||
* @param b The second value.
|
||||
* @param relativeEpsilon The relative epsilon.
|
||||
* @return The absolute epsilon.
|
||||
*/
|
||||
static constexpr double relativeEpsilonToAbsolute(
|
||||
double a,
|
||||
double b,
|
||||
double relativeEpsilon) noexcept {
|
||||
return relativeEpsilon * glm::max(glm::abs(a), glm::abs(b));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether two values are equal up to a given relative epsilon.
|
||||
*
|
||||
* @tparam L The length type.
|
||||
* @tparam T value value type.
|
||||
* @tparam Q The GLM qualifier type.
|
||||
*
|
||||
* @param left The first value.
|
||||
* @param right The second value.
|
||||
* @param relativeEpsilon The relative epsilon.
|
||||
* @return Whether the values are epsilon-equal
|
||||
*/
|
||||
template <glm::length_t L, typename T, glm::qualifier Q>
|
||||
static bool constexpr equalsEpsilon(
|
||||
const glm::vec<L, T, Q>& left,
|
||||
const glm::vec<L, T, Q>& right,
|
||||
double relativeEpsilon) noexcept {
|
||||
return Math::equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether two values are equal up to a given relative epsilon.
|
||||
*
|
||||
* @param left The first value.
|
||||
* @param right The second value.
|
||||
* @param relativeEpsilon The relative epsilon.
|
||||
* @return Whether the values are epsilon-equal
|
||||
*/
|
||||
static constexpr bool
|
||||
equalsEpsilon(double left, double right, double relativeEpsilon) noexcept {
|
||||
return equalsEpsilon(left, right, relativeEpsilon, relativeEpsilon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if two values are equal using an absolute or relative
|
||||
* tolerance test.
|
||||
*
|
||||
* This is useful to avoid problems due to roundoff error when comparing
|
||||
* floating-point values directly. The values are first compared using an
|
||||
* absolute tolerance test. If that fails, a relative tolerance test is
|
||||
* performed. Use this test if you are unsure of the magnitudes of left and
|
||||
* right.
|
||||
*
|
||||
* @param left The first value to compare.
|
||||
* @param right The other value to compare.
|
||||
* @param relativeEpsilon The maximum inclusive delta between `left` and
|
||||
* `right` for the relative tolerance test.
|
||||
* @param absoluteEpsilon The maximum inclusive delta between `left` and
|
||||
* `right` for the absolute tolerance test.
|
||||
* @returns `true` if the values are equal within the epsilon; otherwise,
|
||||
* `false`.
|
||||
*
|
||||
* @snippet TestMath.cpp equalsEpsilon
|
||||
*/
|
||||
static constexpr bool equalsEpsilon(
|
||||
double left,
|
||||
double right,
|
||||
double relativeEpsilon,
|
||||
double absoluteEpsilon) noexcept {
|
||||
const double diff = glm::abs(left - right);
|
||||
return diff <= absoluteEpsilon ||
|
||||
diff <= relativeEpsilonToAbsolute(left, right, relativeEpsilon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines if two values are equal using an absolute or relative
|
||||
* tolerance test.
|
||||
*
|
||||
* This is useful to avoid problems due to roundoff error when comparing
|
||||
* floating-point values directly. The values are first compared using an
|
||||
* absolute tolerance test. If that fails, a relative tolerance test is
|
||||
* performed. Use this test if you are unsure of the magnitudes of left and
|
||||
* right.
|
||||
*
|
||||
* @tparam L The length type.
|
||||
* @tparam T value value type.
|
||||
* @tparam Q The GLM qualifier type.
|
||||
*
|
||||
* @param left The first value to compare.
|
||||
* @param right The other value to compare.
|
||||
* @param relativeEpsilon The maximum inclusive delta between `left` and
|
||||
* `right` for the relative tolerance test.
|
||||
* @param absoluteEpsilon The maximum inclusive delta between `left` and
|
||||
* `right` for the absolute tolerance test.
|
||||
* @returns `true` if the values are equal within the epsilon; otherwise,
|
||||
* `false`.
|
||||
*/
|
||||
template <glm::length_t L, typename T, glm::qualifier Q>
|
||||
static constexpr bool equalsEpsilon(
|
||||
const glm::vec<L, T, Q>& left,
|
||||
const glm::vec<L, T, Q>& right,
|
||||
double relativeEpsilon,
|
||||
double absoluteEpsilon) noexcept {
|
||||
const glm::vec<L, T, Q> diff = glm::abs(left - right);
|
||||
return glm::lessThanEqual(diff, glm::vec<L, T, Q>(absoluteEpsilon)) ==
|
||||
glm::vec<L, bool, Q>(true) ||
|
||||
glm::lessThanEqual(
|
||||
diff,
|
||||
relativeEpsilonToAbsolute(left, right, relativeEpsilon)) ==
|
||||
glm::vec<L, bool, Q>(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the sign of the value.
|
||||
*
|
||||
* This is 1 if the value is positive, -1 if the value is
|
||||
* negative, or 0 if the value is 0.
|
||||
*
|
||||
* @param value The value to return the sign of.
|
||||
* @returns The sign of value.
|
||||
*/
|
||||
static constexpr double sign(double value) noexcept {
|
||||
if (value == 0.0 || value != value) {
|
||||
// zero or NaN
|
||||
return value;
|
||||
}
|
||||
return value > 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns 1.0 if the given value is positive or zero, and -1.0 if it
|
||||
* is negative.
|
||||
*
|
||||
* This is similar to {@link Math::sign} except that returns 1.0 instead of
|
||||
* 0.0 when the input value is 0.0.
|
||||
*
|
||||
* @param value The value to return the sign of.
|
||||
* @returns The sign of value.
|
||||
*/
|
||||
static constexpr double signNotZero(double value) noexcept {
|
||||
return value < 0.0 ? -1.0 : 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Produces an angle in the range -Pi <= angle <= Pi which is
|
||||
* equivalent to the provided angle.
|
||||
*
|
||||
* @param angle The angle in radians.
|
||||
* @returns The angle in the range [`-Math::OnePi`, `Math::OnePi`].
|
||||
*/
|
||||
static double negativePiToPi(double angle) noexcept {
|
||||
if (angle >= -Math::OnePi && angle <= Math::OnePi) {
|
||||
// Early exit if the input is already inside the range. This avoids
|
||||
// unnecessary math which could introduce floating point error.
|
||||
return angle;
|
||||
}
|
||||
return Math::zeroToTwoPi(angle + Math::OnePi) - Math::OnePi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Produces an angle in the range 0 <= angle <= 2Pi which is equivalent
|
||||
* to the provided angle.
|
||||
*
|
||||
* @param angle The angle in radians.
|
||||
* @returns The angle in the range [0, `Math::TwoPi`].
|
||||
*/
|
||||
static double zeroToTwoPi(double angle) noexcept {
|
||||
if (angle >= 0 && angle <= Math::TwoPi) {
|
||||
// Early exit if the input is already inside the range. This avoids
|
||||
// unnecessary math which could introduce floating point error.
|
||||
return angle;
|
||||
}
|
||||
const double mod = Math::mod(angle, Math::TwoPi);
|
||||
if (glm::abs(mod) < Math::Epsilon14 && glm::abs(angle) > Math::Epsilon14) {
|
||||
return Math::TwoPi;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The modulo operation that also works for negative dividends.
|
||||
*
|
||||
* @param m The dividend.
|
||||
* @param n The divisor.
|
||||
* @returns The remainder.
|
||||
*/
|
||||
static double mod(double m, double n) noexcept {
|
||||
if (Math::sign(m) == Math::sign(n) && glm::abs(m) < glm::abs(n)) {
|
||||
// Early exit if the input does not need to be modded. This avoids
|
||||
// unnecessary math which could introduce floating point error.
|
||||
return m;
|
||||
}
|
||||
return fmod(fmod(m, n) + n, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts degrees to radians.
|
||||
*
|
||||
* @param angleDegrees The angle to convert in degrees.
|
||||
* @returns The corresponding angle in radians.
|
||||
*/
|
||||
static constexpr double degreesToRadians(double angleDegrees) noexcept {
|
||||
return angleDegrees * Math::OnePi / 180.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts radians to degrees.
|
||||
*
|
||||
* @param angleRadians The angle to convert in radians.
|
||||
* @returns The corresponding angle in degrees.
|
||||
*/
|
||||
static constexpr double radiansToDegrees(double angleRadians) noexcept {
|
||||
return angleRadians * 180.0 / Math::OnePi;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Computes the linear interpolation of two values.
|
||||
*
|
||||
* @param p The start value to interpolate.
|
||||
* @param q The end value to interpolate.
|
||||
* @param time The time of interpolation generally in the range `[0.0, 1.0]`.
|
||||
* @returns The linearly interpolated value.
|
||||
*
|
||||
* @snippet TestMath.cpp lerp
|
||||
*/
|
||||
static double lerp(double p, double q, double time) noexcept {
|
||||
return glm::mix(p, q, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constrain a value to lie between two values.
|
||||
*
|
||||
* @param value The value to constrain.
|
||||
* @param min The minimum value.
|
||||
* @param max The maximum value.
|
||||
* @returns The value clamped so that min <= value <= max.
|
||||
*/
|
||||
static constexpr double clamp(double value, double min, double max) noexcept {
|
||||
return glm::clamp(value, min, max);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the
|
||||
* range [0, rangeMaximum]
|
||||
*
|
||||
* @param value The scalar value in the range [-1.0, 1.0].
|
||||
* @param rangeMaximum The maximum value in the mapped range, 255 by default.
|
||||
* @returns A SNORM value, where 0 maps to -1.0 and rangeMaximum maps to 1.0.
|
||||
*
|
||||
* @see Math::fromSNorm
|
||||
*/
|
||||
static double toSNorm(double value, double rangeMaximum = 255.0) noexcept {
|
||||
return glm::round(
|
||||
(Math::clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum);
|
||||
};
|
||||
/**
|
||||
* @brief Converts a SNORM value in the range [0, rangeMaximum] to a scalar in
|
||||
* the range [-1.0, 1.0].
|
||||
*
|
||||
* @param value SNORM value in the range [0, rangeMaximum].
|
||||
* @param rangeMaximum The maximum value in the SNORM range, 255 by default.
|
||||
* @returns Scalar in the range [-1.0, 1.0].
|
||||
*
|
||||
* @see Math::toSNorm
|
||||
*/
|
||||
static constexpr double
|
||||
fromSNorm(double value, double rangeMaximum = 255.0) noexcept {
|
||||
return (Math::clamp(value, 0.0, rangeMaximum) / rangeMaximum) * 2.0 - 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a longitude value, in radians, to the range [`-Math::OnePi`,
|
||||
* `Math::OnePi`).
|
||||
*
|
||||
* @param angle The longitude value, in radians, to convert to the range
|
||||
* [`-Math::OnePi`, `Math::OnePi`).
|
||||
* @returns The equivalent longitude value in the range [`-Math::OnePi`,
|
||||
* `Math::OnePi`).
|
||||
*
|
||||
* @snippet TestMath.cpp convertLongitudeRange
|
||||
*/
|
||||
static double convertLongitudeRange(double angle) noexcept {
|
||||
constexpr double twoPi = Math::TwoPi;
|
||||
|
||||
const double simplified = angle - glm::floor(angle / twoPi) * twoPi;
|
||||
|
||||
if (simplified < -Math::OnePi) {
|
||||
return simplified + twoPi;
|
||||
}
|
||||
if (simplified >= Math::OnePi) {
|
||||
return simplified - twoPi;
|
||||
}
|
||||
|
||||
return simplified;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Rounds a value up to the nearest integer, like `ceil`, except
|
||||
* that if the value is very close to the lower integer it is rounded down
|
||||
* (like `floor`) instead.
|
||||
*
|
||||
* @param value The value to round.
|
||||
* @param tolerance The tolerance. If the value is closer than this to the
|
||||
* lower integer, it is rounded down instead.
|
||||
* @return The rounded value.
|
||||
*/
|
||||
static double roundUp(double value, double tolerance) noexcept {
|
||||
const double up = glm::ceil(value);
|
||||
const double down = glm::floor(value);
|
||||
if (value - down < tolerance) {
|
||||
return down;
|
||||
} else {
|
||||
return up;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rounds a value down to the nearest integer, like `floor`, except
|
||||
* that if the value is very close to the higher integer it is rounded up
|
||||
* (like `ceil`) instead.
|
||||
*
|
||||
* @param value The value to round.
|
||||
* @param tolerance The tolerance. If the value is closer than this to the
|
||||
* higher integer, it is rounded up instead.
|
||||
* @return The rounded value.
|
||||
*/
|
||||
static double roundDown(double value, double tolerance) noexcept {
|
||||
const double up = glm::ceil(value);
|
||||
const double down = glm::floor(value);
|
||||
if (up - value < tolerance) {
|
||||
return up;
|
||||
} else {
|
||||
return down;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Construct a vector perpendicular to the argument.
|
||||
* @param v The input vector
|
||||
* @return A vector perpendicular to the input vector
|
||||
*/
|
||||
template <typename T, glm::qualifier Q>
|
||||
static glm::vec<3, T, Q> perpVec(const glm::vec<3, T, Q>& v) {
|
||||
// This constructs a vector whose dot product with v will be 0, hence
|
||||
// perpendicular to v. As seen in the "Physically Based Rendering".
|
||||
if (std::abs(v.x) > std::abs(v.y)) {
|
||||
return glm::vec<3, T, Q>(-v.z, 0, v.x) / std::sqrt(v.x * v.x + v.z * v.z);
|
||||
}
|
||||
return glm::vec<3, T, Q>(0, v.z, -v.y) / std::sqrt(v.y * v.y + v.z * v.z);
|
||||
}
|
||||
|
||||
/** @brief Compute the rotation between two unit vectors.
|
||||
* @param vec1 The first vector.
|
||||
* @param vec2 The second vector.
|
||||
* @return A quaternion representing the rotation of vec1 to vec2.
|
||||
*/
|
||||
template <typename T, glm::qualifier Q>
|
||||
static glm::qua<T, Q>
|
||||
rotation(const glm::vec<3, T, Q>& vec1, const glm::vec<3, T, Q>& vec2) {
|
||||
// If we take the dot and cross products of the two vectors and store
|
||||
// them in a quaternion, that quaternion represents twice the required
|
||||
// rotation. We get the correct quaternion by "averaging" with the zero
|
||||
// rotation quaternion, in a way analagous to finding the half vector
|
||||
// between two 3D vectors.
|
||||
auto cosRot = dot(vec1, vec2);
|
||||
auto rotAxis = cross(vec1, vec2);
|
||||
auto rotAxisLen2 = dot(rotAxis, rotAxis);
|
||||
// Not using epsilon for these tests. If abs(cosRot) < 1.0, we can still
|
||||
// create a sensible rotation.
|
||||
if (cosRot >= 1 || (rotAxisLen2 == 0 && cosRot > 0)) {
|
||||
// zero rotation
|
||||
return glm::qua<T, Q>(1, 0, 0, 0);
|
||||
}
|
||||
if (cosRot <= -1 || (rotAxisLen2 == 0 && cosRot < 0)) {
|
||||
auto perpAxis = CesiumUtility::Math::perpVec(vec1);
|
||||
// rotation by pi radians
|
||||
return glm::qua<T, Q>(0, perpAxis);
|
||||
}
|
||||
|
||||
glm::qua<T, Q> sumQuat(cosRot + 1, rotAxis);
|
||||
return normalize(sumQuat);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
136
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCounted.h
vendored
Normal file
136
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ReferenceCounted.h
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
#pragma once
|
||||
|
||||
#include <CesiumUtility/Assert.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/** \cond Doxygen_Suppress */
|
||||
#ifndef NDEBUG
|
||||
template <bool isThreadSafe> class ThreadIdHolder;
|
||||
|
||||
template <> class ThreadIdHolder<false> {
|
||||
ThreadIdHolder() : _threadID(std::this_thread::get_id()) {}
|
||||
|
||||
std::thread::id _threadID;
|
||||
|
||||
template <typename T, bool isThreadSafe> friend class ReferenceCounted;
|
||||
};
|
||||
|
||||
template <> class ThreadIdHolder<true> {};
|
||||
#endif
|
||||
/** \endcond */
|
||||
|
||||
/**
|
||||
* @brief A reference-counted base class, meant to be used with
|
||||
* {@link IntrusivePointer}.
|
||||
*
|
||||
* Consider using {@link ReferenceCountedThreadSafe} or
|
||||
* {@link ReferenceCountedNonThreadSafe} instead of using this class directly.
|
||||
*
|
||||
* @tparam T The type that is _deriving_ from this class. For example, you
|
||||
* should declare your class as
|
||||
* `class MyClass : public ReferenceCounted<MyClass> { ... };`
|
||||
* @tparam isThreadSafe If `true`, the reference count will be thread-safe by
|
||||
* using `std::atomic`, allowing references to safely be added and removed from
|
||||
* any thread at any time. The object will be destroyed in the thread that
|
||||
* releases the last reference. If false, it uses a simple integer for the
|
||||
* reference count, which is not thread safe. In this case, references must be
|
||||
* added and removed (including automatically via `IntrusivePointer`) from only
|
||||
* one thread at a time. However, this mode has a bit less overhead for objects
|
||||
* that are only ever accessed from a single thread.
|
||||
*/
|
||||
template <typename T, bool isThreadSafe = true>
|
||||
class ReferenceCounted
|
||||
#ifndef NDEBUG
|
||||
: public ThreadIdHolder<isThreadSafe>
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
ReferenceCounted() noexcept {}
|
||||
~ReferenceCounted() noexcept { CESIUM_ASSERT(this->_referenceCount == 0); }
|
||||
|
||||
/**
|
||||
* @brief Adds a counted reference to this object. Use
|
||||
* {@link CesiumUtility::IntrusivePointer} instead of calling this method
|
||||
* directly.
|
||||
*/
|
||||
void addReference() const /*noexcept*/ {
|
||||
#ifndef NDEBUG
|
||||
if constexpr (!isThreadSafe) {
|
||||
CESIUM_ASSERT(std::this_thread::get_id() == this->_threadID);
|
||||
}
|
||||
#endif
|
||||
|
||||
++this->_referenceCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Removes a counted reference from this object. When the last
|
||||
* reference is removed, this method will delete this instance. Use
|
||||
* {@link CesiumUtility::IntrusivePointer} instead of calling this method
|
||||
* directly.
|
||||
*/
|
||||
void releaseReference() const /*noexcept*/ {
|
||||
#ifndef NDEBUG
|
||||
if constexpr (!isThreadSafe) {
|
||||
CESIUM_ASSERT(std::this_thread::get_id() == this->_threadID);
|
||||
}
|
||||
#endif
|
||||
|
||||
CESIUM_ASSERT(this->_referenceCount > 0);
|
||||
const int32_t references = --this->_referenceCount;
|
||||
if (references == 0) {
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current reference count of this instance.
|
||||
*/
|
||||
std::int32_t getReferenceCount() const noexcept {
|
||||
return this->_referenceCount;
|
||||
}
|
||||
|
||||
private:
|
||||
using ThreadSafeCounter = std::atomic<std::int32_t>;
|
||||
using NonThreadSafeCounter = std::int32_t;
|
||||
using CounterType =
|
||||
std::conditional_t<isThreadSafe, ThreadSafeCounter, NonThreadSafeCounter>;
|
||||
|
||||
mutable CounterType _referenceCount{0};
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A reference-counted base class, meant to be used with
|
||||
* {@link IntrusivePointer}. The reference count is thread-safe, so references
|
||||
* may be added and removed from any thread at any time. The object will be
|
||||
* destroyed in the thread that releases the last reference.
|
||||
*
|
||||
* @tparam T The type that is _deriving_ from this class. For example, you
|
||||
* should declare your class as
|
||||
* `class MyClass : public ReferenceCountedThreadSafe<MyClass> { ... };`
|
||||
*/
|
||||
template <typename T>
|
||||
using ReferenceCountedThreadSafe = ReferenceCounted<T, true>;
|
||||
|
||||
/**
|
||||
* @brief A reference-counted base class, meant to be used with
|
||||
* {@link IntrusivePointer}. The reference count is not thread-safe, so
|
||||
* references must be added and removed (including automatically via
|
||||
* `IntrusivePointer`) from only one thread at a time.
|
||||
*
|
||||
* @tparam T The type that is _deriving_ from this class. For example, you
|
||||
* should declare your class as
|
||||
* `class MyClass : public ReferenceCountedNonThreadSafe<MyClass> { ... };`
|
||||
*/
|
||||
template <typename T>
|
||||
using ReferenceCountedNonThreadSafe = ReferenceCounted<T, false>;
|
||||
|
||||
} // namespace CesiumUtility
|
||||
124
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Result.h
vendored
Normal file
124
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Result.h
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
#include <CesiumUtility/ErrorList.h>
|
||||
#include <CesiumUtility/IntrusivePointer.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Holds the result of an operation. If the operation succeeds, it will
|
||||
* provide a value. It may also provide errors and warnings.
|
||||
*
|
||||
* @tparam T The type of value included in the result.
|
||||
*/
|
||||
template <typename T> struct Result {
|
||||
/**
|
||||
* @brief Creates a `Result` with the given value and an empty \ref ErrorList.
|
||||
*
|
||||
* @param value_ The value that will be contained in this `Result`.
|
||||
*/
|
||||
Result(T value_) noexcept : value(std::move(value_)), errors() {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Result` with the given value and \ref ErrorList.
|
||||
*
|
||||
* @param value_ The value that will be contained in this `Result`.
|
||||
* @param errors_ The \ref ErrorList containing errors and warnings related to
|
||||
* this `Result`.
|
||||
*/
|
||||
Result(T value_, ErrorList errors_) noexcept
|
||||
: value(std::move(value_)), errors(std::move(errors_)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Result` with an empty value and the given \ref ErrorList.
|
||||
*
|
||||
* @param errors_ The \ref ErrorList containing errors and warnings related to
|
||||
* this `Result`.
|
||||
*/
|
||||
Result(ErrorList errors_) noexcept : value(), errors(std::move(errors_)) {}
|
||||
|
||||
/**
|
||||
* @brief The value, if the operation succeeded to the point where it can
|
||||
* provide one.
|
||||
*
|
||||
* If a value is not provided because the operation failed, then there should
|
||||
* be at least one error in {@link errors} indicating what went wrong.
|
||||
*/
|
||||
std::optional<T> value;
|
||||
|
||||
/**
|
||||
* @brief The errors and warnings that occurred during the operation.
|
||||
*
|
||||
* If a {@link value} is provided, there should not be any errors in this
|
||||
* list, but there may be warnings. If a value is not provided, there should
|
||||
* be at least one error in this list.
|
||||
*/
|
||||
ErrorList errors;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Holds the result of an operation. If the operation succeeds, it will
|
||||
* provide a value. It may also provide errors and warnings.
|
||||
*
|
||||
* @tparam T The type of value included in the result.
|
||||
*/
|
||||
template <typename T> struct Result<CesiumUtility::IntrusivePointer<T>> {
|
||||
/**
|
||||
* @brief Creates a `Result` with the given value and an empty \ref ErrorList.
|
||||
*
|
||||
* @param pValue_ An intrusive pointer to the value that will be contained in
|
||||
* this `Result`.
|
||||
*/
|
||||
Result(CesiumUtility::IntrusivePointer<T> pValue_) noexcept
|
||||
: pValue(std::move(pValue_)), errors() {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Result` with the given value and \ref ErrorList.
|
||||
*
|
||||
* @param pValue_ An intrusive pointer to the value that will be contained in
|
||||
* this `Result`.
|
||||
* @param errors_ The \ref ErrorList containing errors and warnings related to
|
||||
* this `Result`.
|
||||
*/
|
||||
Result(CesiumUtility::IntrusivePointer<T> pValue_, ErrorList errors_) noexcept
|
||||
: pValue(std::move(pValue_)), errors(std::move(errors_)) {}
|
||||
|
||||
/**
|
||||
* @brief Creates a `Result` with an empty value and the given \ref ErrorList.
|
||||
*
|
||||
* @param errors_ The \ref ErrorList containing errors and warnings related to
|
||||
* this `Result`.
|
||||
*/
|
||||
Result(ErrorList errors_) noexcept
|
||||
: pValue(nullptr), errors(std::move(errors_)) {}
|
||||
|
||||
/**
|
||||
* @brief The value, if the operation succeeded to the point where it can
|
||||
* provide one.
|
||||
*
|
||||
* If a value is not provided because the operation failed, then there should
|
||||
* be at least one error in {@link errors} indicating what went wrong.
|
||||
*/
|
||||
CesiumUtility::IntrusivePointer<T> pValue;
|
||||
|
||||
/**
|
||||
* @brief The errors and warnings that occurred during the operation.
|
||||
*
|
||||
* If a {@link pValue} is provided, there should not be any errors in this
|
||||
* list, but there may be warnings. If a pValue is not provided, there should
|
||||
* be at least one error in this list.
|
||||
*/
|
||||
ErrorList errors;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A convenient shortcut for
|
||||
* `CesiumUtility::Result<CesiumUtility::IntrusivePointer<T>>`.
|
||||
*
|
||||
* @tparam T The type of object that the IntrusivePointer points to.
|
||||
*/
|
||||
template <typename T> using ResultPointer = Result<IntrusivePointer<T>>;
|
||||
|
||||
} // namespace CesiumUtility
|
||||
87
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h
vendored
Normal file
87
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/ScopeGuard.h
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief A utility that will automatically call the lambda function when
|
||||
* exiting a scope.
|
||||
*
|
||||
* @tparam ExitFunction The function type to be called when the guard is out of
|
||||
* scope.
|
||||
*/
|
||||
template <typename ExitFunction> class ScopeGuard {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
* @param exitFunc The function type to be called when the guard is out
|
||||
* of scope
|
||||
*/
|
||||
template <
|
||||
typename ExitFunctionArg,
|
||||
typename std::enable_if_t<
|
||||
!std::is_same_v<
|
||||
std::remove_reference_t<std::remove_const_t<ExitFunctionArg>>,
|
||||
ScopeGuard<ExitFunction>>,
|
||||
int> = 0>
|
||||
explicit ScopeGuard(ExitFunctionArg&& exitFunc)
|
||||
: _callExitFuncOnDestruct{true},
|
||||
_exitFunc{std::forward<ExitFunctionArg>(exitFunc)} {}
|
||||
|
||||
ScopeGuard(const ScopeGuard& rhs) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor. The rhs will move its lambda to the lhs, and the
|
||||
* rhs will not call its lambda upon exiting a scope
|
||||
*/
|
||||
ScopeGuard(ScopeGuard&& rhs) noexcept
|
||||
: _callExitFuncOnDestruct{rhs._callExitFuncOnDestruct},
|
||||
_exitFunc{std::move(rhs._exitFunc)} {
|
||||
rhs.release();
|
||||
}
|
||||
|
||||
ScopeGuard& operator=(const ScopeGuard& rhs) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator. The rhs will move its lambda to the lhs,
|
||||
* and the rhs will not call its lambda upon exiting a scope
|
||||
*/
|
||||
ScopeGuard& operator=(ScopeGuard&& rhs) noexcept {
|
||||
if (&rhs != this) {
|
||||
_callExitFuncOnDestruct = rhs._callExitFuncOnDestruct;
|
||||
_exitFunc = std::move(rhs._exitFunc);
|
||||
rhs.release();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor. The guard will execute the lambda function when exiting
|
||||
* a scope if it's not released
|
||||
*/
|
||||
~ScopeGuard() noexcept {
|
||||
if (_callExitFuncOnDestruct) {
|
||||
_exitFunc();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Upon calling ScopeGuard::release(), the guard will not execute the
|
||||
* lambda function when exiting a scope
|
||||
*/
|
||||
void release() noexcept { _callExitFuncOnDestruct = false; }
|
||||
|
||||
private:
|
||||
bool _callExitFuncOnDestruct;
|
||||
ExitFunction _exitFunc;
|
||||
};
|
||||
|
||||
/** @brief Template deduction guide for \ref ScopeGuard to help the compiler
|
||||
* figure out that the type of `ExitFunction` should be the type of the
|
||||
* function passed to the constructor. */
|
||||
template <typename ExitFunction>
|
||||
ScopeGuard(ExitFunction) -> ScopeGuard<ExitFunction>;
|
||||
} // namespace CesiumUtility
|
||||
154
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SharedAsset.h
vendored
Normal file
154
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SharedAsset.h
vendored
Normal file
@ -0,0 +1,154 @@
|
||||
#pragma once
|
||||
|
||||
#include <CesiumUtility/Assert.h>
|
||||
#include <CesiumUtility/ExtensibleObject.h>
|
||||
#include <CesiumUtility/IDepotOwningAsset.h>
|
||||
#include <CesiumUtility/Library.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace CesiumAsync {
|
||||
template <typename TAssetType, typename TAssetKey> class SharedAssetDepot;
|
||||
}
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief An asset that is potentially shared between multiple objects, such as
|
||||
* an image shared between multiple glTF models. This is intended to be the base
|
||||
* class for such assets.
|
||||
*
|
||||
* The lifetime of instances of this class should be managed by reference
|
||||
* counting with {@link IntrusivePointer}.
|
||||
*
|
||||
* @tparam T The type that is _deriving_ from this class. For example, you
|
||||
* should declare your class as
|
||||
* `class MyClass : public SharedAsset<MyClass> { ... };`
|
||||
*
|
||||
* @remarks @parblock
|
||||
* A `SharedAsset` can be in one of three possible states:
|
||||
*
|
||||
* **Independent Asset**
|
||||
* An independent asset isn't affiliated with an asset depot at all.
|
||||
* Its lifetime is controlled exclusively by IntrusivePointer / reference
|
||||
* counting. When the asset's reference count goes to zero, it deletes itself.
|
||||
* An independent asset's {@link getDepot} returns nullptr.
|
||||
*
|
||||
* **Active Depot Asset**
|
||||
* This is an asset that is owned by an asset depot and that is in use, meaning
|
||||
* it has a reference count greater than zero. The asset depot owns the asset
|
||||
* via an `std::unique_ptr`, not via adding to the reference count. So when the
|
||||
* reference count goes to zero, only the asset depot itself still has a
|
||||
* reference to it, so it becomes an inactive depot asset.
|
||||
*
|
||||
* **Inactive Depot Asset**
|
||||
* This is also an asset that is owned by the asset depot, but there are no
|
||||
* other references to it (it has a reference count of zero). It is found in the
|
||||
* asset depot's `deletionCandidates` list. When a reference to it is added, it
|
||||
* is removed from `deletionCandidates` and it becomes an active depot asset.
|
||||
* @endparblock
|
||||
*/
|
||||
template <typename T>
|
||||
class CESIUMUTILITY_API SharedAsset : public CesiumUtility::ExtensibleObject {
|
||||
public:
|
||||
/**
|
||||
* @brief Adds a counted reference to this object. Use
|
||||
* {@link CesiumUtility::IntrusivePointer} instead of calling this method
|
||||
* directly.
|
||||
*/
|
||||
void addReference() const noexcept { this->addReference(false); }
|
||||
|
||||
/**
|
||||
* @brief Removes a counted reference from this object. When the last
|
||||
* reference is removed, this method will delete this instance. Use
|
||||
* {@link CesiumUtility::IntrusivePointer} instead of calling this method
|
||||
* directly.
|
||||
*/
|
||||
void releaseReference() const noexcept { this->releaseReference(false); }
|
||||
|
||||
/**
|
||||
* @brief Gets the shared asset depot that owns this asset, or nullptr if this
|
||||
* asset is independent of an asset depot.
|
||||
*/
|
||||
const IDepotOwningAsset<T>* getDepot() const { return this->_pDepot; }
|
||||
|
||||
/**
|
||||
* @brief Gets the shared asset depot that owns this asset, or nullptr if this
|
||||
* asset is independent of an asset depot.
|
||||
*/
|
||||
IDepotOwningAsset<T>* getDepot() { return this->_pDepot; }
|
||||
|
||||
protected:
|
||||
SharedAsset() = default;
|
||||
~SharedAsset() { CESIUM_ASSERT(this->_referenceCount == 0); }
|
||||
|
||||
/**
|
||||
* Assets can be copied, but the fresh instance has no references and is not
|
||||
* in the asset depot.
|
||||
*/
|
||||
SharedAsset(const SharedAsset& rhs)
|
||||
: ExtensibleObject(rhs), _referenceCount(0), _pDepot(nullptr) {}
|
||||
|
||||
/**
|
||||
* After a move construction, the content of the asset is moved to the new
|
||||
* instance, but the asset depot still references the old instance.
|
||||
*/
|
||||
SharedAsset(SharedAsset&& rhs)
|
||||
: ExtensibleObject(std::move(rhs)),
|
||||
_referenceCount(0),
|
||||
_pDepot(nullptr) {}
|
||||
|
||||
/**
|
||||
* Assignment does not affect the asset's relationship with the depot, but is
|
||||
* useful to assign the data in derived classes.
|
||||
*/
|
||||
SharedAsset& operator=(const SharedAsset& rhs) {
|
||||
CesiumUtility::ExtensibleObject::operator=(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assignment does not affect the asset's relationship with the depot, but is
|
||||
* useful to assign the data in derived classes.
|
||||
*/
|
||||
SharedAsset& operator=(SharedAsset&& rhs) {
|
||||
CesiumUtility::ExtensibleObject::operator=(std::move(rhs));
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void addReference(bool threadOwnsDepotLock) const noexcept {
|
||||
const int32_t prevReferences = this->_referenceCount++;
|
||||
if (this->_pDepot && prevReferences <= 0) {
|
||||
this->_pDepot->unmarkDeletionCandidate(
|
||||
*static_cast<const T*>(this),
|
||||
threadOwnsDepotLock);
|
||||
}
|
||||
}
|
||||
|
||||
void releaseReference(bool threadOwnsDepotLock) const noexcept {
|
||||
CESIUM_ASSERT(this->_referenceCount > 0);
|
||||
const int32_t references = --this->_referenceCount;
|
||||
if (references == 0) {
|
||||
IDepotOwningAsset<T>* pDepot = this->_pDepot;
|
||||
if (pDepot) {
|
||||
// Let the depot manage this object's lifetime.
|
||||
pDepot->markDeletionCandidate(
|
||||
*static_cast<const T*>(this),
|
||||
threadOwnsDepotLock);
|
||||
} else {
|
||||
// No depot, so destroy this object directly.
|
||||
delete static_cast<const T*>(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutable std::atomic<std::int32_t> _referenceCount{0};
|
||||
IDepotOwningAsset<T>* _pDepot{nullptr};
|
||||
|
||||
// To allow the depot to modify _pDepot.
|
||||
template <typename TAssetType, typename TAssetKey>
|
||||
friend class CesiumAsync::SharedAssetDepot;
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
18
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h
vendored
Normal file
18
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/SpanHelper.h
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <span>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief This function converts between span types. This function
|
||||
* has the same rules with C++ reintepret_cast
|
||||
* https://en.cppreference.com/w/cpp/language/reinterpret_cast. So please use it
|
||||
* carefully
|
||||
*/
|
||||
template <typename To, typename From>
|
||||
std::span<To> reintepretCastSpan(const std::span<From>& from) noexcept {
|
||||
return std::span<To>(
|
||||
reinterpret_cast<To*>(from.data()),
|
||||
from.size() * sizeof(From) / sizeof(To));
|
||||
}
|
||||
} // namespace CesiumUtility
|
||||
22
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/StringHelpers.h
vendored
Normal file
22
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/StringHelpers.h
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace CesiumUtility {
|
||||
|
||||
/**
|
||||
* @brief Helper functions for working with strings.
|
||||
*/
|
||||
class StringHelpers {
|
||||
public:
|
||||
/**
|
||||
* @brief Converts a `u8string` to a `string` without changing its encoding.
|
||||
* The output string is encoded in UTF-8, just like the input.
|
||||
*
|
||||
* @param s The `std::u8string`.
|
||||
* @return The equivalent `std::string`.
|
||||
*/
|
||||
static std::string toStringUtf8(const std::u8string& s);
|
||||
};
|
||||
|
||||
} // namespace CesiumUtility
|
||||
349
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h
vendored
Normal file
349
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Tracing.h
vendored
Normal file
@ -0,0 +1,349 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CESIUM_OVERRIDE_TRACING
|
||||
|
||||
// If the build system doesn't enable the tracing support
|
||||
// consider it disabled by default.
|
||||
#ifndef CESIUM_TRACING_ENABLED
|
||||
#define CESIUM_TRACING_ENABLED 0
|
||||
#endif
|
||||
|
||||
#if !CESIUM_TRACING_ENABLED
|
||||
|
||||
#define CESIUM_TRACE_INIT(filename)
|
||||
#define CESIUM_TRACE_SHUTDOWN()
|
||||
#define CESIUM_TRACE(name)
|
||||
#define CESIUM_TRACE_BEGIN(name)
|
||||
#define CESIUM_TRACE_END(name)
|
||||
#define CESIUM_TRACE_BEGIN_IN_TRACK(name)
|
||||
#define CESIUM_TRACE_END_IN_TRACK(name)
|
||||
#define CESIUM_TRACE_DECLARE_TRACK_SET(id, name)
|
||||
#define CESIUM_TRACE_USE_TRACK_SET(id)
|
||||
#define CESIUM_TRACE_LAMBDA_CAPTURE_TRACK() tracingTrack = false
|
||||
#define CESIUM_TRACE_USE_CAPTURED_TRACK()
|
||||
|
||||
#else
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
// helper macros to avoid shadowing variables
|
||||
#define TRACE_NAME_AUX1(A, B) A##B
|
||||
#define TRACE_NAME_AUX2(A, B) TRACE_NAME_AUX1(A, B)
|
||||
|
||||
/**
|
||||
* @brief Initializes the tracing framework and begins recording to a given JSON
|
||||
* filename.
|
||||
*
|
||||
* @param filename The path and named of the file in which to record traces.
|
||||
*/
|
||||
#define CESIUM_TRACE_INIT(filename) \
|
||||
CesiumUtility::CesiumImpl::Tracer::instance().startTracing(filename)
|
||||
|
||||
/**
|
||||
* @brief Shuts down tracing and closes the JSON tracing file.
|
||||
*/
|
||||
#define CESIUM_TRACE_SHUTDOWN() \
|
||||
CesiumUtility::CesiumImpl::Tracer::instance().endTracing()
|
||||
|
||||
/**
|
||||
* @brief Measures and records the time spent in the current scope.
|
||||
*
|
||||
* The time is measured from the `CESIUM_TRACE` line to the end of the scope.
|
||||
* If the current thread is enlisted in an async process
|
||||
* ({@link CESIUM_TRACE_ASYNC_ENLIST}), the time is recorded against the async
|
||||
* process. Otherwise, it is recorded against the current thread.
|
||||
*
|
||||
* @param name The name of the measured operation.
|
||||
*/
|
||||
#define CESIUM_TRACE(name) \
|
||||
CesiumUtility::CesiumImpl::ScopedTrace TRACE_NAME_AUX2( \
|
||||
cesiumTrace, \
|
||||
__LINE__)(name)
|
||||
|
||||
/**
|
||||
* @brief Begins measuring an operation which may span scope but not threads.
|
||||
*
|
||||
* Begins measuring the time of an operation which completes with a
|
||||
* corresponding call to {@link CESIUM_TRACE_END}. If the calling thread is
|
||||
* operating in a track ({@link CESIUM_TRACE_USE_TRACK_SET}), the
|
||||
* time is recorded in the track. Otherwise, is is recorded against the current
|
||||
* thread.
|
||||
*
|
||||
* Extreme care must be taken to match calls to `CESIUM_TRACE_BEGIN` and
|
||||
* `CESIUM_TRACE_END`:
|
||||
*
|
||||
* * Paired calls must use an identical `name`.
|
||||
* * If either BEGIN or END is called from a thread operating in a track,
|
||||
* then both must be, and it must be the same track in
|
||||
* both cases. In this case BEGIN and END may be called from different
|
||||
* threads. However, it safer to use {@link CESIUM_TRACE_BEGIN_IN_TRACK}
|
||||
* in this scenario.
|
||||
* * If either BEGIN or END is called from a thread _not_ enlisted into a
|
||||
* track, then both must be called from the same thread and neither
|
||||
* thread may be in a track.
|
||||
* * Paired calls must not be interleaved with other BEGIN/END calls for the
|
||||
* same thread or track. Other BEGIN/END pairs may be fully
|
||||
* nested within this one, but this pair must not END in between a nested
|
||||
* measurement's BEGIN and END calls.
|
||||
*
|
||||
* Failure to ensure the above may lead to generation of a trace file that the
|
||||
* Chromium trace viewer is not able to correctly interpret.
|
||||
*
|
||||
* @param name The name of the measured operation.
|
||||
*/
|
||||
#define CESIUM_TRACE_BEGIN(name) \
|
||||
CesiumUtility::CesiumImpl::Tracer::instance().writeAsyncEventBegin(name)
|
||||
|
||||
/**
|
||||
* @brief Ends measuring an operation which may span scopes but not threads.
|
||||
*
|
||||
* Finishes measuring the time of an operation that began with a call to
|
||||
* {@link CESIUM_TRACE_BEGIN}. See the documentation for that macro for more
|
||||
* details and caveats.
|
||||
*
|
||||
* @param name The name of the measured operation.
|
||||
*/
|
||||
#define CESIUM_TRACE_END(name) \
|
||||
CesiumUtility::CesiumImpl::Tracer::instance().writeAsyncEventEnd(name)
|
||||
|
||||
/**
|
||||
* @brief Begins measuring an operation that may span both scopes and threads.
|
||||
*
|
||||
* This macro is identical to {@link CESIUM_TRACE_BEGIN} except that it does
|
||||
* nothing if the calling thread and scope are not operating as part of a
|
||||
* track. This allows it to be safely used to measure operations that span
|
||||
* threads. Use {@link CESIUM_TRACE_USE_TRACK_SET} to use a track from a set.
|
||||
*
|
||||
* @param name The name of the measured operation.
|
||||
*/
|
||||
#define CESIUM_TRACE_BEGIN_IN_TRACK(name) \
|
||||
if (CesiumUtility::CesiumImpl::TrackReference::current() != nullptr) { \
|
||||
CESIUM_TRACE_BEGIN(name); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ends measuring an operation that may span both scopes and threads.
|
||||
*
|
||||
* This macro is identical to {@link CESIUM_TRACE_END} except that it does
|
||||
* nothing if the calling thread and scope are not operating as part of a
|
||||
* track. This allows it to be safely used to measure operations that span
|
||||
* threads. Use {@link CESIUM_TRACE_USE_TRACK_SET} to use a track from a set.
|
||||
*
|
||||
* @param name The name of the measured operation.
|
||||
*/
|
||||
#define CESIUM_TRACE_END_IN_TRACK(name) \
|
||||
if (CesiumUtility::CesiumImpl::TrackReference::current() != nullptr) { \
|
||||
CESIUM_TRACE_END(name); \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Declares a set of tracing tracks as a field inside a class.
|
||||
*
|
||||
* A track is a sequential process that may take place across multiple threads.
|
||||
* An instance of a class may have multiple such tracks running simultaneously.
|
||||
* For example, a single 3D Tiles tile will load in a particular track, while
|
||||
* other tiles will be loading in other parallel tracks in the same set.
|
||||
*
|
||||
* Note that when the track set is destroyed, an assertion will check that no
|
||||
* tracks are still in progress.
|
||||
*
|
||||
* @param id The name of the field to hold the track set.
|
||||
* @param name A human-friendly name for this set of tracks.
|
||||
*/
|
||||
#define CESIUM_TRACE_DECLARE_TRACK_SET(id, name) \
|
||||
CesiumUtility::CesiumImpl::TrackSet id { name }
|
||||
|
||||
/**
|
||||
* @brief Begins using a track set in this thread.
|
||||
*
|
||||
* The calling thread will be allocated a track from the track set, and will
|
||||
* continue using it for the remainder of the current scope. In addition, if
|
||||
* the thread starts an async operation using {@link CesiumAsync::AsyncSystem},
|
||||
* all continuations of that async operation will use the same track as well.
|
||||
*
|
||||
* @param id The ID (field name) of the track set declared with
|
||||
* {@link CESIUM_TRACE_DECLARE_TRACK_SET}.
|
||||
*/
|
||||
#define CESIUM_TRACE_USE_TRACK_SET(id) \
|
||||
CesiumUtility::CesiumImpl::TrackReference TRACE_NAME_AUX2( \
|
||||
cesiumTraceEnlistTrack, \
|
||||
__LINE__)(id);
|
||||
|
||||
/**
|
||||
* @brief Capture the current tracing track for a lambda, so that the lambda may
|
||||
* use the same track.
|
||||
*
|
||||
* This macro should be used in a lambda's capture list to capture the track of
|
||||
* the current thread so that the lambda (which may execute in a different
|
||||
* thread) can use the same track by executing
|
||||
* {@link CESIUM_TRACE_USE_CAPTURED_TRACK}.
|
||||
*/
|
||||
#define CESIUM_TRACE_LAMBDA_CAPTURE_TRACK() \
|
||||
tracingTrack = CesiumUtility::CesiumImpl::LambdaCaptureTrack()
|
||||
|
||||
/**
|
||||
* @brief Uses a captured track for the current thread and the current scope.
|
||||
*
|
||||
* This macro should be used as the first line in a lambda that should inherit
|
||||
* the tracing track of the thread that created it. The lambda's capture list
|
||||
* must also contain {@link CESIUM_TRACE_USE_CAPTURED_TRACK}.
|
||||
*/
|
||||
#define CESIUM_TRACE_USE_CAPTURED_TRACK() \
|
||||
CESIUM_TRACE_USE_TRACK_SET(tracingTrack)
|
||||
|
||||
namespace CesiumUtility {
|
||||
namespace CesiumImpl {
|
||||
|
||||
// The following are internal classes used by the tracing framework, do not use
|
||||
// directly.
|
||||
|
||||
struct Trace {
|
||||
std::string name;
|
||||
int64_t start;
|
||||
int64_t duration;
|
||||
std::thread::id threadID;
|
||||
};
|
||||
|
||||
class TrackReference;
|
||||
|
||||
class Tracer {
|
||||
public:
|
||||
static Tracer& instance();
|
||||
|
||||
~Tracer();
|
||||
|
||||
void startTracing(const std::string& filePath = "trace.json");
|
||||
void endTracing();
|
||||
|
||||
void writeCompleteEvent(const Trace& trace);
|
||||
void writeAsyncEventBegin(const char* name, int64_t id);
|
||||
void writeAsyncEventBegin(const char* name);
|
||||
void writeAsyncEventEnd(const char* name, int64_t id);
|
||||
void writeAsyncEventEnd(const char* name);
|
||||
|
||||
int64_t allocateTrackID();
|
||||
|
||||
private:
|
||||
Tracer();
|
||||
|
||||
int64_t getCurrentThreadTrackID() const;
|
||||
void writeAsyncEvent(
|
||||
const char* category,
|
||||
const char* name,
|
||||
char type,
|
||||
int64_t id);
|
||||
|
||||
std::ofstream _output;
|
||||
uint32_t _numTraces;
|
||||
std::mutex _lock;
|
||||
std::atomic<int64_t> _lastAllocatedID;
|
||||
};
|
||||
|
||||
class ScopedTrace {
|
||||
public:
|
||||
explicit ScopedTrace(const std::string& message);
|
||||
~ScopedTrace();
|
||||
|
||||
void reset();
|
||||
|
||||
ScopedTrace(const ScopedTrace& rhs) = delete;
|
||||
ScopedTrace(ScopedTrace&& rhs) = delete;
|
||||
ScopedTrace& operator=(const ScopedTrace& rhs) = delete;
|
||||
ScopedTrace& operator=(ScopedTrace&& rhs) = delete;
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
std::chrono::steady_clock::time_point _startTime;
|
||||
std::thread::id _threadId;
|
||||
bool _reset;
|
||||
};
|
||||
|
||||
class TrackSet {
|
||||
public:
|
||||
explicit TrackSet(const char* name);
|
||||
~TrackSet();
|
||||
|
||||
size_t acquireTrack();
|
||||
void addReference(size_t trackIndex) noexcept;
|
||||
void releaseReference(size_t trackIndex) noexcept;
|
||||
|
||||
int64_t getTracingID(size_t trackIndex) noexcept;
|
||||
|
||||
TrackSet(TrackSet&& rhs) noexcept;
|
||||
TrackSet& operator=(TrackSet&& rhs) noexcept;
|
||||
|
||||
private:
|
||||
struct Track {
|
||||
Track(int64_t id_, bool inUse_)
|
||||
: id(id_), referenceCount(0), inUse(inUse_) {}
|
||||
|
||||
int64_t id;
|
||||
int32_t referenceCount;
|
||||
bool inUse;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<Track> tracks;
|
||||
std::mutex mutex;
|
||||
};
|
||||
|
||||
class LambdaCaptureTrack {
|
||||
public:
|
||||
LambdaCaptureTrack();
|
||||
LambdaCaptureTrack(LambdaCaptureTrack&& rhs) noexcept;
|
||||
LambdaCaptureTrack(const LambdaCaptureTrack& rhs) noexcept;
|
||||
~LambdaCaptureTrack();
|
||||
LambdaCaptureTrack& operator=(const LambdaCaptureTrack& rhs) noexcept;
|
||||
LambdaCaptureTrack& operator=(LambdaCaptureTrack&& rhs) noexcept;
|
||||
|
||||
private:
|
||||
TrackSet* pSet;
|
||||
size_t index;
|
||||
|
||||
friend class TrackReference;
|
||||
};
|
||||
|
||||
// An RAII object to reference an async operation track.
|
||||
// When the last instance associated with a particular track index is destroyed,
|
||||
// the track is released back to the track set.
|
||||
class TrackReference {
|
||||
public:
|
||||
static TrackReference* current();
|
||||
|
||||
TrackReference(TrackSet& set) noexcept;
|
||||
TrackReference(TrackSet& set, size_t index) noexcept;
|
||||
TrackReference(const LambdaCaptureTrack& lambdaCapture) noexcept;
|
||||
~TrackReference() noexcept;
|
||||
|
||||
operator bool() const noexcept;
|
||||
int64_t getTracingID() const noexcept;
|
||||
|
||||
TrackReference(const TrackReference& rhs) = delete;
|
||||
TrackReference(TrackReference&& rhs) = delete;
|
||||
TrackReference& operator=(const TrackReference& rhs) = delete;
|
||||
TrackReference& operator=(TrackReference&& rhs) = delete;
|
||||
|
||||
private:
|
||||
void enlistCurrentThread();
|
||||
void dismissCurrentThread();
|
||||
|
||||
TrackSet* pSet;
|
||||
size_t index;
|
||||
|
||||
static thread_local std::vector<TrackReference*> _threadEnlistedTracks;
|
||||
|
||||
friend class LambdaCaptureTrack;
|
||||
};
|
||||
|
||||
} // namespace CesiumImpl
|
||||
} // namespace CesiumUtility
|
||||
|
||||
#endif // CESIUM_TRACING_ENABLED
|
||||
|
||||
#endif
|
||||
211
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h
vendored
Normal file
211
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/Uri.h
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief A class for building and manipulating Uniform Resource Identifiers
|
||||
* (URIs).
|
||||
*/
|
||||
class Uri final {
|
||||
public:
|
||||
/**
|
||||
* @brief Attempts to resolve a relative URI using a base URI.
|
||||
*
|
||||
* For example, a relative URI `/v1/example` together with the base URI
|
||||
* `https://api.cesium.com` would resolve to
|
||||
* `https://api.cesium.com/v1/example`.
|
||||
*
|
||||
* @param base The base URI that the relative URI is relative to.
|
||||
* @param relative The relative URI to be resolved against the base URI.
|
||||
* @param useBaseQuery If true, any query parameters of the base URI will be
|
||||
* retained in the resolved URI.
|
||||
* @param assumeHttpsDefault If true, protocol-relative URIs (such as
|
||||
* `//api.cesium.com`) will be assumed to be `https`. If false, they will be
|
||||
* assumed to be `http`.
|
||||
* @returns The resolved URI.
|
||||
*/
|
||||
static std::string resolve(
|
||||
const std::string& base,
|
||||
const std::string& relative,
|
||||
bool useBaseQuery = false,
|
||||
bool assumeHttpsDefault = true);
|
||||
/**
|
||||
* @brief Adds the given key and value to the query string of a URI. For
|
||||
* example, `addQuery("https://api.cesium.com/v1/example", "key", "value")`
|
||||
* would produce the URL `https://api.cesium.com/v1/example?key=value`.
|
||||
*
|
||||
* @param uri The URI whose query string will be modified.
|
||||
* @param key The key to be added to the query string.
|
||||
* @param value The value to be added to the query string.
|
||||
* @returns The modified URI including the new query string parameter.
|
||||
*/
|
||||
static std::string addQuery(
|
||||
const std::string& uri,
|
||||
const std::string& key,
|
||||
const std::string& value);
|
||||
/**
|
||||
* @brief Obtains the value of the given key from the query string of the URI,
|
||||
* if possible.
|
||||
*
|
||||
* If the URI can't be parsed, or the key doesn't exist in the
|
||||
* query string, an empty string will be returned.
|
||||
*
|
||||
* @param uri The URI with a query string to obtain a value from.
|
||||
* @param key The key whose value will be obtained from the URI, if possible.
|
||||
* @returns The value of the given key in the query string, or an empty string
|
||||
* if not found.
|
||||
*/
|
||||
static std::string
|
||||
getQueryValue(const std::string& uri, const std::string& key);
|
||||
|
||||
/**
|
||||
* @brief A callback to fill-in a placeholder value in a URL.
|
||||
*
|
||||
* @param placeholder The text of the placeholder. For example, if the
|
||||
* placeholder was `{example}`, the value of `placeholder` will be `example`.
|
||||
* @returns The value to use in place of the placeholder.
|
||||
*/
|
||||
typedef std::string
|
||||
SubstitutionCallbackSignature(const std::string& placeholder);
|
||||
|
||||
/**
|
||||
* @brief Substitutes the placeholders in a templated URI with their
|
||||
* appropriate values obtained using a specified callback function.
|
||||
*
|
||||
* A templated URI has placeholders in the form of `{name}`. For example,
|
||||
* `https://example.com/{x}/{y}/{z}` has three placeholders, `x`, `y`, and `z`.
|
||||
* The callback will be called for each placeholder and they will be replaced
|
||||
* with the return value of this callback.
|
||||
*
|
||||
* @param templateUri The templated URI whose placeholders will be substituted
|
||||
* by this method.
|
||||
* @param substitutionCallback The callback that will be called for each
|
||||
* placeholder in the provided URI. See \ref SubstitutionCallbackSignature.
|
||||
*/
|
||||
static std::string substituteTemplateParameters(
|
||||
const std::string& templateUri,
|
||||
const std::function<SubstitutionCallbackSignature>& substitutionCallback);
|
||||
|
||||
/**
|
||||
* @brief Escapes a portion of a URI, percent-encoding disallowed characters.
|
||||
*
|
||||
* @param s The string to escape.
|
||||
* @return The escaped string.
|
||||
*/
|
||||
static std::string escape(const std::string& s);
|
||||
|
||||
/**
|
||||
* @brief Unescapes a portion of a URI, decoding any percent-encoded
|
||||
* characters.
|
||||
*
|
||||
* @param s The string to unescape.
|
||||
* @return The unescaped string.
|
||||
*/
|
||||
static std::string unescape(const std::string& s);
|
||||
|
||||
/**
|
||||
* @brief Converts a Unix file system path to a string suitable for use as the
|
||||
* path portion of a URI. Characters that are not allowed in the path portion
|
||||
* of a URI are percent-encoded as necessary.
|
||||
*
|
||||
* If the path is absolute (it starts with a slash), then the URI will start
|
||||
* with a slash as well.
|
||||
*
|
||||
* @param unixPath The file system path.
|
||||
* @return The URI path.
|
||||
*/
|
||||
static std::string unixPathToUriPath(const std::string& unixPath);
|
||||
|
||||
/**
|
||||
* @brief Converts a Windows file system path to a string suitable for use as
|
||||
* the path portion of a URI. Characters that are not allowed in the path
|
||||
* portion of a URI are percent-encoded as necessary.
|
||||
*
|
||||
* Either `/` or `\` may be used as a path separator on input, but the output
|
||||
* will contain only `/`.
|
||||
*
|
||||
* If the path is absolute (it starts with a slash or with C:\ or similar),
|
||||
* then the URI will start with a slash well.
|
||||
*
|
||||
* @param windowsPath The file system path.
|
||||
* @return The URI path.
|
||||
*/
|
||||
static std::string windowsPathToUriPath(const std::string& windowsPath);
|
||||
|
||||
/**
|
||||
* @brief Converts a file system path on the current system to a string
|
||||
* suitable for use as the path portion of a URI. Characters that are not
|
||||
* allowed in the path portion of a URI are percent-encoded as necessary.
|
||||
*
|
||||
* If the `_WIN32` preprocessor definition is defined when compiling
|
||||
* cesium-native, this is assumed to be a Windows-like system and this
|
||||
* function calls {@link windowsPathToUriPath}. Otherwise, this is assumed to
|
||||
* be a Unix-like system and this function calls {@link unixPathToUriPath}.
|
||||
*
|
||||
* @param nativePath The file system path.
|
||||
* @return The URI path.
|
||||
*/
|
||||
static std::string nativePathToUriPath(const std::string& nativePath);
|
||||
|
||||
/**
|
||||
* @brief Converts the path portion of a URI to a Unix file system path.
|
||||
* Percent-encoded characters in the URI are decoded.
|
||||
*
|
||||
* If the URI path is absolute (it starts with a slash), then the file system
|
||||
* path will start with a slash as well.
|
||||
*
|
||||
* @param uriPath The URI path.
|
||||
* @return The file system path.
|
||||
*/
|
||||
static std::string uriPathToUnixPath(const std::string& uriPath);
|
||||
|
||||
/**
|
||||
* @brief Converts the path portion of a URI to a Windows file system path.
|
||||
* Percent-encoded characters in the URI are decoded.
|
||||
*
|
||||
* If the URI path is absolute (it starts with a slash), then the file system
|
||||
* path will start with a slash or a drive letter.
|
||||
*
|
||||
* @param uriPath The URI path.
|
||||
* @return The file system path.
|
||||
*/
|
||||
static std::string uriPathToWindowsPath(const std::string& uriPath);
|
||||
|
||||
/**
|
||||
* @brief Converts the path portion of a URI to a file system path on the
|
||||
* current system. Percent-encoded characters in the URI are decoded.
|
||||
*
|
||||
* If the `_WIN32` preprocessor definition is defined when compiling
|
||||
* cesium-native, this is assumed to be a Windows-like system and this
|
||||
* function calls {@link uriPathToWindowsPath}. Otherwise, this is assumed to
|
||||
* be a Unix-like system and this function calls {@link uriPathToUnixPath}.
|
||||
*
|
||||
* @param uriPath The URI path.
|
||||
* @return The file system path.
|
||||
*/
|
||||
static std::string uriPathToNativePath(const std::string& uriPath);
|
||||
|
||||
/**
|
||||
* @brief Gets the path portion of the URI. This will not include path
|
||||
* parameters, if present.
|
||||
*
|
||||
* @param uri The URI from which to get the path.
|
||||
* @return The path, or empty string if the URI could not be parsed.
|
||||
*/
|
||||
static std::string getPath(const std::string& uri);
|
||||
|
||||
/**
|
||||
* @brief Sets the path portion of a URI to a new value. The other portions of
|
||||
* the URI are left unmodified, including any path parameters.
|
||||
*
|
||||
* @param uri The URI for which to set the path.
|
||||
* @param newPath The new path portion of the URI.
|
||||
* @returns The new URI after setting the path. If the original URI cannot be
|
||||
* parsed, it is returned unmodified.
|
||||
*/
|
||||
static std::string
|
||||
setPath(const std::string& uri, const std::string& newPath);
|
||||
};
|
||||
} // namespace CesiumUtility
|
||||
47
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h
vendored
Normal file
47
Plugins/CesiumForUnreal/Source/ThirdParty/include/CesiumUtility/joinToString.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
|
||||
namespace CesiumUtility {
|
||||
/**
|
||||
* @brief Joins multiple elements together into a string, separated by a given
|
||||
* separator.
|
||||
*
|
||||
* @tparam TIterator The type of the collection iterator.
|
||||
* @param begin An iterator referring to the first element to join.
|
||||
* @param end An iterator referring to one past the last element to join.
|
||||
* @param separator The string to use to separate successive elements.
|
||||
* @return The joined string.
|
||||
*/
|
||||
template <class TIterator>
|
||||
std::string
|
||||
joinToString(TIterator begin, TIterator end, const std::string& separator) {
|
||||
if (begin == end)
|
||||
return std::string();
|
||||
|
||||
std::string first = *begin;
|
||||
|
||||
return std::accumulate(
|
||||
++begin,
|
||||
end,
|
||||
std::move(first),
|
||||
[&separator](const std::string& acc, const std::string& element) {
|
||||
return acc + separator + element;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Joins multiple elements together into a string, separated by a given
|
||||
* separator.
|
||||
*
|
||||
* @tparam TIterator The type of the collection iterator.
|
||||
* @param collection The collection of elements to be joined.
|
||||
* @param separator The string to use to separate successive elements.
|
||||
* @return The joined string.
|
||||
*/
|
||||
template <class TCollection>
|
||||
std::string joinToString(TCollection collection, const std::string& separator) {
|
||||
return joinToString(collection.cbegin(), collection.cend(), separator);
|
||||
}
|
||||
} // namespace CesiumUtility
|
||||
Reference in New Issue
Block a user