#pragma once #include #include #include #include #include "RE/I/IAnimationGraphManagerHolder.h" namespace F4T::AnimationDescriptor { // Forward declarations struct AnimationVariableSnapshot; class F4AnimationDescriptor; // Variable type enumeration enum class VariableType : std::uint8_t { Float, Bool, Int, }; // Snapshot of animation graph variables (used for action replay) struct AnimationVariableSnapshot { std::vector floats; std::vector bools; std::vector ints; }; // Animation descriptor for a specific graph type (humanoid, creature, etc.) // Uses indexed variable cache read/write instead of string-based lookups // This matches TiltedEvolution's descriptor model for optimal performance class F4AnimationDescriptor { public: // Default constructor (public for singleton initialization) F4AnimationDescriptor() = default; // Get the humanoid master behavior graph descriptor (most common) static const F4AnimationDescriptor& GetHumanoidDescriptor(); // Prevent copies (singleton pattern) F4AnimationDescriptor(const F4AnimationDescriptor&) = delete; F4AnimationDescriptor& operator=(const F4AnimationDescriptor&) = delete; // Get variable names by index const std::string& GetFloatVariableName(std::size_t a_index) const; const std::string& GetBoolVariableName(std::size_t a_index) const; const std::string& GetIntVariableName(std::size_t a_index) const; // Get index by variable name (for reverse lookup) std::size_t GetFloatVariableIndex(const std::string& a_name) const; std::size_t GetBoolVariableIndex(const std::string& a_name) const; std::size_t GetIntVariableIndex(const std::string& a_name) const; // Check if variable exists bool HasFloatVariable(const std::string& a_name) const; bool HasBoolVariable(const std::string& a_name) const; bool HasIntVariable(const std::string& a_name) const; // Bulk read animation variables from actor's graph cache // Locks the graph manager during read bool SaveAnimationVariablesFromCache( RE::IAnimationGraphManagerHolder& a_holder, AnimationVariableSnapshot& a_snapshot) const; // Bulk write animation variables to actor's graph cache // Locks the graph manager during write bool LoadAnimationVariablesToCache( RE::IAnimationGraphManagerHolder& a_holder, const AnimationVariableSnapshot& a_snapshot) const; // Get counts of each variable type std::size_t GetFloatVariableCount() const { return m_floatVariables.size(); } std::size_t GetBoolVariableCount() const { return m_boolVariables.size(); } std::size_t GetIntVariableCount() const { return m_intVariables.size(); } private: // Variable name tables (indices match animation system's variable cache) std::vector m_floatVariables; std::vector m_boolVariables; std::vector m_intVariables; // Reverse lookup tables (name → index) for faster search std::unordered_map m_floatVariableIndexMap; std::unordered_map m_boolVariableIndexMap; std::unordered_map m_intVariableIndexMap; // Initialize humanoid descriptor tables // Called once at startup; contains FO4-specific graph variable indices void InitializeHumanoidVariables(); // Helper: Try to read a variable by index from graph cache bool TryReadFloatVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, float& a_outValue) const; bool TryReadBoolVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, bool& a_outValue) const; bool TryReadIntVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, std::uint32_t& a_outValue) const; // Helper: Try to write a variable by index to graph cache bool TryWriteFloatVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, float a_value) const; bool TryWriteBoolVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, bool a_value) const; bool TryWriteIntVariable( RE::IAnimationGraphManagerHolder& a_holder, std::size_t a_index, std::uint32_t a_value) const; // Friend for logging friend class F4TProxyAnimationSync; }; }