#pragma once #include #include #include #include #include #include "FastNoise_Config.h" #include "FastSIMD/FastSIMD.h" namespace FastNoise { class Generator; template struct PerDimensionVariable; struct NodeData; struct Metadata { Metadata( const char* className ) { name = className; id = AddMetadataClass( this ); } static const std::vector& GetMetadataClasses() { return sMetadataClasses; } static const Metadata* GetMetadataClass( std::uint16_t nodeId ) { if( nodeId < sMetadataClasses.size() ) { return sMetadataClasses[nodeId]; } return nullptr; } static std::string SerialiseNodeData( NodeData* nodeData, bool fixUp = false ); static SmartNode<> DeserialiseSmartNode( const char* serialisedBase64NodeData, FastSIMD::eLevel level = FastSIMD::Level_Null ); static NodeData* DeserialiseNodeData( const char* serialisedBase64NodeData, std::vector>& nodeDataOut ); struct MemberVariable { enum eType { EFloat, EInt, EEnum }; union ValueUnion { float f; std::int32_t i; ValueUnion( float v = 0 ) { f = v; } ValueUnion( std::int32_t v ) { i = v; } operator float() { return f; } operator std::int32_t() { return i; } bool operator ==( const ValueUnion& rhs ) const { return i == rhs.i; } }; const char* name; eType type; int dimensionIdx = -1; ValueUnion valueDefault, valueMin, valueMax; std::vector enumNames; std::function setFunc; }; template>> void AddVariable( const char* name, T defaultV, U&& func, T minV = 0, T maxV = 0 ) { MemberVariable member; member.name = name; member.valueDefault = defaultV; member.valueMin = minV; member.valueMax = maxV; member.type = std::is_same_v ? MemberVariable::EFloat : MemberVariable::EInt; member.setFunc = [func]( Generator* g, MemberVariable::ValueUnion v ) { func( dynamic_cast>(g), v ); }; memberVariables.push_back( member ); } template>> void AddVariable( const char* name, T defaultV, void(U::* func)(T), T minV = 0, T maxV = 0 ) { MemberVariable member; member.name = name; member.valueDefault = defaultV; member.valueMin = minV; member.valueMax = maxV; member.type = std::is_same_v ? MemberVariable::EFloat : MemberVariable::EInt; member.setFunc = [func]( Generator* g, MemberVariable::ValueUnion v ) { (dynamic_cast(g)->*func)(v); }; memberVariables.push_back( member ); } template>, typename... NAMES> void AddVariableEnum( const char* name, T defaultV, void(U::* func)(T), NAMES... names ) { MemberVariable member; member.name = name; member.type = MemberVariable::EEnum; member.valueDefault = (int32_t)defaultV; member.enumNames = { names... }; member.setFunc = [func]( Generator* g, MemberVariable::ValueUnion v ) { (dynamic_cast(g)->*func)((T)v.i); }; memberVariables.push_back( member ); } template>> void AddPerDimensionVariable( const char* name, T defaultV, U&& func, T minV = 0, T maxV = 0 ) { for( int idx = 0; (size_t)idx < sizeof( PerDimensionVariable::varArray ) / sizeof( *PerDimensionVariable::varArray ); idx++ ) { MemberVariable member; member.name = name; member.valueDefault = defaultV; member.valueMin = minV; member.valueMax = maxV; member.type = std::is_same_v ? MemberVariable::EFloat : MemberVariable::EInt; member.dimensionIdx = idx; member.setFunc = [func, idx]( Generator* g, MemberVariable::ValueUnion v ) { func( dynamic_cast>(g) ).get()[idx] = v; }; memberVariables.push_back( member ); } } struct MemberNode { const char* name; int dimensionIdx = -1; std::function )> setFunc; }; template void AddGeneratorSource( const char* name, void(U::* func)(SmartNodeArg) ) { MemberNode member; member.name = name; member.setFunc = [func]( Generator* g, SmartNodeArg<> s ) { SmartNode downCast = std::dynamic_pointer_cast(s); if( downCast ) { (dynamic_cast(g)->*func)( downCast ); } return (bool)downCast; }; memberNodes.push_back( member ); } template void AddPerDimensionGeneratorSource( const char* name, U&& func ) { using GeneratorSourceT = typename std::invoke_result_t>::type::Type; using T = typename GeneratorSourceT::Type; for( int idx = 0; (size_t)idx < sizeof( PerDimensionVariable::varArray ) / sizeof( *PerDimensionVariable::varArray ); idx++ ) { MemberNode member; member.name = name; member.dimensionIdx = idx; member.setFunc = [func, idx]( auto* g, SmartNodeArg<> s ) { SmartNode downCast = std::dynamic_pointer_cast(s); if( downCast ) { g->SetSourceMemberVariable( func( dynamic_cast>(g) ).get()[idx], downCast ); } return (bool)downCast; }; memberNodes.push_back( member ); } } struct MemberHybrid { const char* name; float valueDefault = 0.0f; int dimensionIdx = -1; std::function setValueFunc; std::function )> setNodeFunc; }; template void AddHybridSource( const char* name, float defaultValue, void(U::* funcNode)(SmartNodeArg), void(U::* funcValue)(float) ) { MemberHybrid member; member.name = name; member.valueDefault = defaultValue; member.setNodeFunc = [funcNode]( auto* g, SmartNodeArg<> s ) { SmartNode downCast = std::dynamic_pointer_cast(s); if( downCast ) { (dynamic_cast(g)->*funcNode)( downCast ); } return (bool)downCast; }; member.setValueFunc = [funcValue]( Generator* g, float v ) { (dynamic_cast(g)->*funcValue)(v); }; memberHybrids.push_back( member ); } template void AddPerDimensionHybridSource( const char* name, float defaultV, U&& func ) { using HybridSourceT = typename std::invoke_result_t>::type::Type; using T = typename HybridSourceT::Type; for( int idx = 0; (size_t)idx < sizeof( PerDimensionVariable::varArray ) / sizeof( *PerDimensionVariable::varArray ); idx++ ) { MemberHybrid member; member.name = name; member.valueDefault = defaultV; member.dimensionIdx = idx; member.setNodeFunc = [func, idx]( auto* g, SmartNodeArg<> s ) { SmartNode downCast = std::dynamic_pointer_cast(s); if( downCast ) { g->SetSourceMemberVariable( func( dynamic_cast>(g) ).get()[idx], downCast ); } return (bool)downCast; }; member.setValueFunc = [func, idx]( Generator* g, float v ) { func( dynamic_cast>(g) ).get()[idx] = v; }; memberHybrids.push_back( member ); } } std::uint16_t id; const char* name; std::vector groups; std::vector memberVariables; std::vector memberNodes; std::vector memberHybrids; virtual Generator* NodeFactory( FastSIMD::eLevel level = FastSIMD::Level_Null ) const = 0; private: template static std::tuple GetArg_Helper( Ret( F::* )(Args...) const ); template using GetArg = std::tuple_element_t; static std::uint16_t AddMetadataClass( const Metadata* newMetadata ) { sMetadataClasses.emplace_back( newMetadata ); return (std::uint16_t)sMetadataClasses.size() - 1; } static std::vector sMetadataClasses; }; struct NodeData { NodeData( const Metadata* metadata ); const Metadata* metadata; std::vector variables; std::vector nodes; std::vector> hybrids; bool operator ==( const NodeData& rhs ) const { return metadata == rhs.metadata && variables == rhs.variables && nodes == rhs.nodes && hybrids == rhs.hybrids; } }; } #define FASTNOISE_METADATA( ... ) public:\ FASTSIMD_LEVEL_SUPPORT( FastNoise::SUPPORTED_SIMD_LEVELS );\ const FastNoise::Metadata* GetMetadata() const override;\ struct Metadata : __VA_ARGS__::Metadata{\ Generator* NodeFactory( FastSIMD::eLevel ) const override; #define FASTNOISE_METADATA_ABSTRACT( ... ) public:\ struct Metadata : __VA_ARGS__::Metadata{