#pragma once #include #include #include #include #include #include "FastNoise_Config.h" #pragma warning( push ) #pragma warning( disable : 4251 ) namespace FastNoise { class Generator; template struct PerDimensionVariable; struct Metadata; struct NodeData; namespace Impl { template FASTNOISE_API const Metadata& GetMetadata(); } // Stores definition of a FastNoise node class // Node name, member name+types, functions to set members struct FASTNOISE_API Metadata { virtual ~Metadata() = default; /// Array containing metadata for every FastNoise node type static const std::vector& GetAll() { return sAllMetadata; } /// Metadata for given Metadata::id 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; } /// Metadata for given node class template static const Metadata& Get() { static_assert( std::is_base_of::value, "This function should only be used for FastNoise node classes, for example FastNoise::Simplex" ); static_assert( std::is_member_function_pointer::value, "Cannot get Metadata for abstract node class, use a derived class, for example: Fractal -> FractalFBm" ); return Impl::GetMetadata(); } /// /// Serialise node data and any source node datas (recursive) /// /// Root node data /// Remove dependency loops and invalid node types /// Empty string on error static std::string SerialiseNodeData( NodeData* nodeData, bool fixUp = false ); /// /// Deserialise a string created from SerialiseNodeData to a node data tree /// /// Encoded string to deserialise /// Storage for new node data /// Root node static NodeData* DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector>& nodeDataOut ); struct NameDesc { const char* name; const char* desc; NameDesc( const char* name, const char* desc = "" ) : name( name ), desc( desc ) {} }; // Base member struct struct Member { const char* name = ""; const char* description = ""; int dimensionIdx = -1; }; /// /// Add spaces to node names: DomainScale -> Domain Scale /// /// FastNoise node metadata /// Removes metadata groups from name: FractalFBm -> FBm /// string with formatted name static std::string FormatMetadataNodeName( const Metadata* metadata, bool removeGroups = false ); /// /// Adds dimension prefix to member varibles that per-dimension: /// DomainAxisScale::Scale -> X Scale /// /// FastNoise node metadata member /// string with formatted name static std::string FormatMetadataMemberName( const Member& member ); // float, int or enum value struct MemberVariable : Member { enum eType { EFloat, EInt, EEnum }; union ValueUnion { float f; int i; ValueUnion( float v = 0 ) { f = v; } ValueUnion( int v ) { i = v; } operator float() { return f; } operator int() { return i; } bool operator ==( const ValueUnion& rhs ) const { return i == rhs.i; } }; eType type; ValueUnion valueDefault, valueMin, valueMax; std::vector enumNames; // Function to set value for given generator // Returns true if Generator is correct node class std::function setFunc; }; // Node lookup (must be valid for node to function) struct MemberNodeLookup : Member { // Function to set source for given generator // Returns true if Generator* is correct node class and SmartNodeArg<> is correct node class std::function )> setFunc; }; // Either a constant float or node lookup struct MemberHybrid : Member { float valueDefault = 0.0f; // Function to set value for given generator // Returns true if Generator is correct node class std::function setValueFunc; // Function to set source for given generator // Source takes priority if value is also set // Returns true if Generator is correct node class and SmartNodeArg<> is correct node class std::function )> setNodeFunc; }; uint16_t id; const char* name = ""; const char* description = ""; std::vector groups; std::vector memberVariables; std::vector memberNodeLookups; std::vector memberHybrids; /// /// Create new instance of a FastNoise node from metadata /// /// /// auto node = metadata->CreateNode(); /// metadata->memberVariables[0].setFunc( node.get(), 1.5f ); /// /// Max SIMD level, Null = Auto /// SmartNode is guaranteed not nullptr virtual SmartNode<> CreateNode( FastSIMD::eLevel maxSimdLevel = FastSIMD::Level_Null ) const = 0; protected: Metadata() { id = AddMetadata( this ); } private: static uint16_t AddMetadata( const Metadata* newMetadata ) { sAllMetadata.emplace_back( newMetadata ); return (uint16_t)sAllMetadata.size() - 1; } static std::vector sAllMetadata; }; // Stores data to create an instance of a FastNoise node // Node type, member values struct FASTNOISE_API NodeData { NodeData( const Metadata* metadata ); const Metadata* metadata; std::vector variables; std::vector nodeLookups; std::vector> hybrids; bool operator ==( const NodeData& rhs ) const { return metadata == rhs.metadata && variables == rhs.variables && nodeLookups == rhs.nodeLookups && hybrids == rhs.hybrids; } }; } #pragma warning( pop )