Skip to content

Commit

Permalink
Use custom vector type in metadata to avoid dll linker warnings due t…
Browse files Browse the repository at this point in the history
…o stl types in the API
  • Loading branch information
Auburn committed May 9, 2024
1 parent a1d5337 commit 4d557e8
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 148 deletions.
7 changes: 5 additions & 2 deletions include/FastNoise/Generators/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ namespace FastNoise
member.description = nameDesc.desc;
member.type = MemberVariable::EEnum;
member.valueDefault = (int)defaultV;
member.enumNames = { enumNames... };
( member.enumNames.push_back( enumNames ), ... );

member.setFunc = [func]( Generator* g, MemberVariable::ValueUnion v )
{
Expand All @@ -282,7 +282,10 @@ namespace FastNoise
member.description = nameDesc.desc;
member.type = MemberVariable::EEnum;
member.valueDefault = (int)defaultV;
member.enumNames = { enumNames, enumNames + ENUM_NAMES };
for( const char* enumName : enumNames )
{
member.enumNames.push_back( enumName );
}

member.setFunc = [func]( Generator* g, MemberVariable::ValueUnion v )
{
Expand Down
208 changes: 123 additions & 85 deletions include/FastNoise/Metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

#include "Utility/Config.h"

#pragma warning( push )
#pragma warning( disable : 4251 )

namespace FastNoise
{
class Generator;
Expand All @@ -28,58 +25,30 @@ namespace FastNoise
// Node name, member name+types, functions to set members
struct FASTNOISE_API Metadata
{
static constexpr float kDefaultUiDragSpeedFloat = 0.02f;
static constexpr float kDefaultUiDragSpeedInt = 0.2f;

virtual ~Metadata() = default;

/// <returns>Array containing metadata for every FastNoise node type</returns>
static const std::vector<const Metadata*>& GetAll()
{
return sAllMetadata;
}

/// <returns>Metadata for given Metadata::id</returns>
static const Metadata* GetFromId( uint16_t nodeId )
{
// Metadata not loaded yet
// Don't try to create nodes from metadata during static initialisation
// Metadata is loaded using static variable and static variable init is done in a random order
assert( sAllMetadata.size() );

if( nodeId < sAllMetadata.size() )
{
return sAllMetadata[nodeId];
}

return nullptr;
}

/// <returns>Metadata for given node class</returns>
template<typename T>
static const Metadata& Get()
class FASTNOISE_API Vector
{
static_assert( std::is_base_of<Generator, T>::value, "This function should only be used for FastNoise node classes, for example FastNoise::Simplex" );
static_assert( std::is_member_function_pointer<decltype(&T::GetMetadata)>::value, "Cannot get Metadata for abstract node class, use a derived class, for example: Fractal -> FractalFBm" );

return Impl::GetMetadata<T>();
}

/// <summary>
/// Serialise node data and any source node datas (recursive)
/// </summary>
/// <param name="nodeData">Root node data</param>
/// <param name="fixUp">Remove dependency loops and invalid node types</param>
/// <returns>Empty string on error</returns>
static std::string SerialiseNodeData( NodeData* nodeData, bool fixUp = false );

/// <summary>
/// Deserialise a string created from SerialiseNodeData to a node data tree
/// </summary>
/// <param name="serialisedBase64NodeData">Encoded string to deserialise</param>
/// <param name="nodeDataOut">Storage for new node data</param>
/// <returns>Root node</returns>
static NodeData* DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector<std::unique_ptr<NodeData>>& nodeDataOut );
public:
using const_iterator = const T*;
// template solves dll linking when not inlining
template<typename = T> const_iterator begin() const { return data() + mStart; }
template<typename = T> const_iterator end() const { return data() + mEnd; }
template<typename = T> size_t size() const { return mEnd - mStart; }
template<typename = T> const T& operator []( size_t i ) const { return begin()[i]; }

private:
template<typename>
friend struct MetadataT;
friend struct Metadata;
friend class Generator;
using index_type = uint8_t;

T* data() const;
void push_back( const T& value );

index_type mStart = (index_type)-1;
index_type mEnd = (index_type)-1;
};

struct NameDesc
{
Expand All @@ -94,25 +63,9 @@ namespace FastNoise
{
const char* name = "";
const char* description = "";
int dimensionIdx = -1;
int dimensionIdx = -1;
};

/// <summary>
/// Add spaces to node names: DomainScale -> Domain Scale
/// </summary>
/// <param name="metadata">FastNoise node metadata</param>
/// <param name="removeGroups">Removes metadata groups from name: FractalFBm -> FBm</param>
/// <returns>string with formatted name</returns>
static std::string FormatMetadataNodeName( const Metadata* metadata, bool removeGroups = false );

/// <summary>
/// Adds dimension prefix to member varibles that per-dimension:
/// DomainAxisScale::Scale -> X Scale
/// </summary>
/// <param name="member">FastNoise node metadata member</param>
/// <returns>string with formatted name</returns>
static std::string FormatMetadataMemberName( const Member& member );

// float, int or enum value
struct MemberVariable : Member
{
Expand Down Expand Up @@ -157,7 +110,7 @@ namespace FastNoise
eType type;
ValueUnion valueDefault, valueMin, valueMax;
float valueUiDragSpeed = 0;
std::vector<const char*> enumNames;
Vector<const char*> enumNames;

// Function to set value for given generator
// Returns true if Generator is correct node class
Expand Down Expand Up @@ -187,15 +140,73 @@ namespace FastNoise
std::function<bool( Generator*, SmartNodeArg<> )> setNodeFunc;
};

uint16_t id;
const char* name = "";
const char* description = "";
const char* formattedName = nullptr;
std::vector<const char*> groups;
static std::pair<int32_t, const char*> DebugCheckVectorStorageSize( int i );

std::vector<MemberVariable> memberVariables;
std::vector<MemberNodeLookup> memberNodeLookups;
std::vector<MemberHybrid> memberHybrids;
virtual ~Metadata() = default;

/// <returns>Array containing metadata for every FastNoise node type</returns>
static const Vector<const Metadata*>& GetAll()
{
return sAllMetadata;
}

/// <returns>Metadata for given Metadata::id</returns>
static const Metadata* GetFromId( uint16_t nodeId )
{
// Metadata not loaded yet
// Don't try to create nodes from metadata during static initialisation
// Metadata is loaded using static variable and static variable init is done in a random order
assert( sAllMetadata.size() );

if( nodeId < sAllMetadata.size() )
{
return sAllMetadata[nodeId];
}

return nullptr;
}

/// <returns>Metadata for given node class</returns>
template<typename T>
static const Metadata& Get()
{
static_assert( std::is_base_of<Generator, T>::value, "This function should only be used for FastNoise node classes, for example FastNoise::Simplex" );
static_assert( std::is_member_function_pointer<decltype(&T::GetMetadata)>::value, "Cannot get Metadata for abstract node class, use a derived class, for example: Fractal -> FractalFBm" );

return Impl::GetMetadata<T>();
}

/// <summary>
/// Serialise node data and any source node datas (recursive)
/// </summary>
/// <param name="nodeData">Root node data</param>
/// <param name="fixUp">Remove dependency loops and invalid node types</param>
/// <returns>Empty string on error</returns>
static std::string SerialiseNodeData( NodeData* nodeData, bool fixUp = false );

/// <summary>
/// Deserialise a string created from SerialiseNodeData to a node data tree
/// </summary>
/// <param name="serialisedBase64NodeData">Encoded string to deserialise</param>
/// <param name="nodeDataOut">Storage for new node data</param>
/// <returns>Root node</returns>
static NodeData* DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector<std::unique_ptr<NodeData>>& nodeDataOut );

/// <summary>
/// Add spaces to node names: DomainScale -> Domain Scale
/// </summary>
/// <param name="metadata">FastNoise node metadata</param>
/// <param name="removeGroups">Removes metadata groups from name: FractalFBm -> FBm</param>
/// <returns>string with formatted name</returns>
static std::string FormatMetadataNodeName( const Metadata* metadata, bool removeGroups = false );

/// <summary>
/// Adds dimension prefix to member varibles that per-dimension:
/// DomainAxisScale::Scale -> X Scale
/// </summary>
/// <param name="member">FastNoise node metadata member</param>
/// <returns>string with formatted name</returns>
static std::string FormatMetadataMemberName( const Member& member );

/// <summary>
/// Create new instance of a FastNoise node from metadata
Expand All @@ -208,28 +219,57 @@ namespace FastNoise
/// <returns>SmartNode<T> is guaranteed not nullptr</returns>
virtual SmartNode<> CreateNode( FastSIMD::FeatureSet maxFeatureSet = FastSIMD::FeatureSet::Max ) const = 0;

uint16_t id;
Vector<MemberVariable> memberVariables;
Vector<MemberNodeLookup> memberNodeLookups;
Vector<MemberHybrid> memberHybrids;
Vector<const char*> groups;

const char* name = "";
const char* description = "";
const char* formattedName = nullptr;

protected:
Metadata()
{
id = AddMetadata( this );
}

static constexpr float kDefaultUiDragSpeedFloat = 0.02f;
static constexpr float kDefaultUiDragSpeedInt = 0.2f;

private:
static uint16_t AddMetadata( const Metadata* newMetadata )
{
sAllMetadata.emplace_back( newMetadata );
sAllMetadata.push_back( newMetadata );

return (uint16_t)sAllMetadata.size() - 1;
}

static std::vector<const Metadata*> sAllMetadata;
static Vector<const Metadata*> sAllMetadata;
};

// Stores data to create an instance of a FastNoise node
// Node type, member values
struct FASTNOISE_API NodeData
struct NodeData
{
NodeData( const Metadata* metadata );
NodeData( const Metadata* data )
{
if( ( metadata = data ) )
{
for( const Metadata::MemberVariable& value: metadata->memberVariables )
{
variables.push_back( value.valueDefault );
}

nodeLookups.assign( metadata->memberNodeLookups.size(), nullptr );

for( const Metadata::MemberHybrid& value: metadata->memberHybrids )
{
hybrids.emplace_back( nullptr, value.valueDefault );
}
}
}

const Metadata* metadata;
std::vector<Metadata::MemberVariable::ValueUnion> variables;
Expand All @@ -245,5 +285,3 @@ namespace FastNoise
}
};
}

#pragma warning( pop )
Loading

0 comments on commit 4d557e8

Please sign in to comment.