Skip to content

File SkeletonSetupManager.cpp

File List > api > cppSDK > SDKBase > SkeletonSetupManager.cpp

Go to the documentation of this file

#include <mutex>
#include <vector>
#include <string>
#include <atomic>

#include "ManusSDKExtendedTypes.h"

#include "SkeletonSetupManager.hpp"

#include "SkeletonSetup.hpp"
#include "Logging.hpp"
// shared code for both windows and android versions of the SDK.

namespace ManusSDK
{
    SkeletonSetupManager::~SkeletonSetupManager()
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        ClearAllTemporarySkeletonsFromBuffer();
    }

    void SkeletonSetupManager::IfEmptyClearSkeletonSetupBuffer()
    {
        for (size_t i = 0; i < m_SkeletonSetupBuffer.size(); i++)
        {
            if (m_SkeletonSetupBuffer[i] != nullptr)
                return;
        }
        m_SkeletonSetupBuffer.clear();
    }

    SDKReturnCode SkeletonSetupManager::CreateSkeletonSetup(const SkeletonSetupInfo& p_SkeletonSetupInfo, uint32_t& p_SkeletonSetupIndex)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = new SkeletonSetup(p_SkeletonSetupInfo);
        for (size_t i = 0; i < m_SkeletonSetupBuffer.size(); i++)
        {
            if (m_SkeletonSetupBuffer[i] == nullptr)
            {
                p_SkeletonSetupIndex = (uint32_t)i;
                m_SkeletonSetupBuffer[p_SkeletonSetupIndex] = t_Skl;
                return SDKReturnCode::SDKReturnCode_Success;
            }
        }
        if (m_SkeletonSetupBuffer.size() == MAX_NUMBER_OF_SKELETONS_PER_SESSION)
        {
            delete t_Skl;
            Log::Warn(__FUNCTION__, "The max number of temporary skeletons per session has been reached, either load or clear a temporary skeleton.");
            return SDKReturnCode::SDKReturnCode_ArgumentSizeMismatch;
        }
        p_SkeletonSetupIndex = (uint32_t)m_SkeletonSetupBuffer.size();
        m_SkeletonSetupBuffer.push_back(t_Skl);

        return SDKReturnCode::SDKReturnCode_Success;
    }


    SDKReturnCode SkeletonSetupManager::AddNodeToSkeletonSetup(uint32_t p_SkeletonSetupIndex, const NodeSetup& p_Node)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Skl->nodes.push_back(new NodeSetup(p_Node));

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::OverwriteChainToSkeletonSetup(uint32_t p_SkeletonSetupIndex, const ChainSetup& p_Chain)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }
        for (size_t i = 0; i < t_Skl->chains.size(); i++)
        {
            if (t_Skl->chains[i]->id == p_Chain.id)
            {
                delete t_Skl->chains[i];
                t_Skl->chains[i] = new ChainSetup(p_Chain);
                return SDKReturnCode::SDKReturnCode_Success;
            }
        }
        return SDKReturnCode::SDKReturnCode_InvalidID;
    }

    SDKReturnCode SkeletonSetupManager::OverwriteNodeToSkeletonSetup(uint32_t p_SkeletonSetupIndex, const NodeSetup& p_Node)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        for (size_t i = 0; i < t_Skl->nodes.size(); i++)
        {
            if (t_Skl->nodes[i]->id == p_Node.id)
            {
                delete t_Skl->nodes[i];
                t_Skl->nodes[i] = new NodeSetup(p_Node);
                return SDKReturnCode::SDKReturnCode_Success;
            }
        }
        return SDKReturnCode::SDKReturnCode_InvalidID;
    }

    SDKReturnCode SkeletonSetupManager::AddChainToSkeletonSetup(uint32_t p_SkeletonSetupIndex, const ChainSetup& p_Chain)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Skl->chains.push_back(new ChainSetup(p_Chain));
        return SDKReturnCode::SDKReturnCode_Success;
    }


    SDKReturnCode SkeletonSetupManager::AddColliderToSkeletonSetup(uint32_t p_SkeletonSetupIndex, const ColliderSetup& p_Collider)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Skl->colliders.push_back(new ColliderSetup(p_Collider));
        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::AddMeshSetupToSkeletonSetup(uint32_t p_SkeletonSetupIndex, uint32_t p_NodeId, uint32_t& p_MeshSetupIndex)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Skl->meshes.push_back(new MeshSetup(p_NodeId));
        p_MeshSetupIndex = (uint32_t)(t_Skl->meshes.size() - 1);

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::AddVertexToMeshSetup(uint32_t p_SkeletonSetupIndex, uint32_t p_MeshSetupIndex, const Vertex& p_Vertex)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        MeshSetup* t_Mesh = nullptr;
        if (t_Skl->meshes.size() > p_MeshSetupIndex)
        {
            t_Mesh = t_Skl->meshes[p_MeshSetupIndex];
        }

        if (t_Mesh == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Mesh->vertices.push_back(new Vertex(p_Vertex));
        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::AddTriangleToMeshSetup(uint32_t p_SkeletonSetupIndex, uint32_t p_MeshSetupIndex, const Triangle& p_Triangle)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        MeshSetup* t_Mesh = nullptr;
        if (t_Skl->meshes.size() > p_MeshSetupIndex)
        {
            t_Mesh = t_Skl->meshes[p_MeshSetupIndex];
        }

        if (t_Mesh == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        t_Mesh->triangles.push_back(new Triangle(p_Triangle));
        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetMeshSetupInfo(uint32_t p_SkeletonSetupIndex, uint32_t p_MeshSetupIndex, MeshSetupInfo& p_MeshSetupInfo)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        MeshSetup* t_Mesh = nullptr;
        if (t_Skl->meshes.size() > p_MeshSetupIndex)
        {
            t_Mesh = t_Skl->meshes[p_MeshSetupIndex];
        }

        if (t_Mesh == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        p_MeshSetupInfo.nodeId = t_Mesh->nodeID;
        p_MeshSetupInfo.vertexCount = (uint32_t)t_Mesh->vertices.size();
        p_MeshSetupInfo.triangleCount = (uint32_t)t_Mesh->triangles.size();

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetVertexData(uint32_t p_SkeletonSetupIndex, uint32_t p_MeshSetupIndex, uint32_t p_VertexIndex, Vertex& p_Vertex)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        MeshSetup* t_Mesh = nullptr;
        if (t_Skl->meshes.size() > p_MeshSetupIndex)
        {
            t_Mesh = t_Skl->meshes[p_MeshSetupIndex];
        }

        if (t_Mesh == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        Vertex* t_Vertex = nullptr;
        if (t_Mesh->vertices.size() > p_VertexIndex)
        {
            t_Vertex = t_Mesh->vertices[p_VertexIndex];
        }

        if (t_Vertex == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        p_Vertex = *t_Vertex;

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetTriangleData(uint32_t p_SkeletonSetupIndex, uint32_t p_MeshSetupIndex, uint32_t p_TriangleIndex, Triangle& p_Triangle)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        MeshSetup* t_Mesh = nullptr;
        if (t_Skl->meshes.size() > p_MeshSetupIndex)
        {
            t_Mesh = t_Skl->meshes[p_MeshSetupIndex];
        }

        if (t_Mesh == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        Triangle* t_Triangle = nullptr;
        if (t_Mesh->triangles.size() > p_TriangleIndex)
        {
            t_Triangle = t_Mesh->triangles[p_TriangleIndex];
        }

        if (t_Triangle == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        p_Triangle = *t_Triangle;

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SkeletonSetup* SkeletonSetupManager::GetSkeletonSetup(uint32_t p_SkeletonSetupIndex)
    {
        SkeletonSetup* t_Skl = nullptr;
        if (m_SkeletonSetupBuffer.size() > p_SkeletonSetupIndex)
        {
            t_Skl = m_SkeletonSetupBuffer[p_SkeletonSetupIndex];
        }
        return t_Skl;
    }

    void SkeletonSetupManager::ClearSkeletonSetup(uint32_t p_SkeletonSetupIndex)
    {
        if (p_SkeletonSetupIndex >= m_SkeletonSetupBuffer.size())
        {
            Log::Error(__FUNCTION__, "tried to delete non existing skeleton setup.");
            return;
        }
        delete m_SkeletonSetupBuffer[p_SkeletonSetupIndex];
        m_SkeletonSetupBuffer[p_SkeletonSetupIndex] = nullptr;
        IfEmptyClearSkeletonSetupBuffer();
    }

    void SkeletonSetupManager::InsertSkeletonSetup(uint32_t p_SkeletonSetupIndex, SkeletonSetup* p_LocalSkl)
    {
        if (m_SkeletonSetupBuffer.size() > p_SkeletonSetupIndex)
        {
            if (m_SkeletonSetupBuffer[p_SkeletonSetupIndex] == nullptr) delete m_SkeletonSetupBuffer[p_SkeletonSetupIndex];
            m_SkeletonSetupBuffer[p_SkeletonSetupIndex] = p_LocalSkl;
        }
        else
        {
            for (uint32_t i = (uint32_t)m_SkeletonSetupBuffer.size(); i < p_SkeletonSetupIndex; i++)
            {
                m_SkeletonSetupBuffer.push_back(nullptr);
            }
            m_SkeletonSetupBuffer.push_back(p_LocalSkl);
        }
    }

    void SkeletonSetupManager::ClearAllTemporarySkeletonsFromBuffer()
    {       
        for (size_t i = 0; i < m_SkeletonSetupBuffer.size(); i++)
        {
            if (m_SkeletonSetupBuffer[i] != nullptr)
            {
                delete m_SkeletonSetupBuffer[i];
            }
        }
        m_SkeletonSetupBuffer.clear();
    }


    SDKReturnCode SkeletonSetupManager::OverwriteSkeletonSetup(uint32_t p_SkeletonSetupIndex, const SkeletonSetupInfo& p_SkeletonSetupInfo)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        if (m_SkeletonSetupBuffer.size() <= p_SkeletonSetupIndex)
        {
            //SPDLOG_WARN("No skeleton setup with index {} was found to overwrite", p_SkeletonSetupIndex);
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        SkeletonSetup* t_Skl = new SkeletonSetup(p_SkeletonSetupInfo);

        if (m_SkeletonSetupBuffer[p_SkeletonSetupIndex] != nullptr)delete m_SkeletonSetupBuffer[p_SkeletonSetupIndex];

        m_SkeletonSetupBuffer[p_SkeletonSetupIndex] = t_Skl;

        if (m_SkeletonSetupBuffer[p_SkeletonSetupIndex] != nullptr)
        {
            return SDKReturnCode::SDKReturnCode_Success;
        }

        return SDKReturnCode::SDKReturnCode_NullPointer;
    }

    SDKReturnCode SkeletonSetupManager::GetSkeletonSetupArraySizes(uint32_t p_SkeletonSetupIndex, SkeletonSetupArraySizes& p_SkeletonInfo)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        p_SkeletonInfo.nodesCount = (uint32_t)t_Skl->nodes.size();
        p_SkeletonInfo.chainsCount = (uint32_t)t_Skl->chains.size();
        p_SkeletonInfo.collidersCount = (uint32_t)t_Skl->colliders.size();
        p_SkeletonInfo.meshCount = (uint32_t)t_Skl->meshes.size();

        return SDKReturnCode::SDKReturnCode_Success;
    }

    // p_SDK is a pre allocated array of chainsetups! check SkeletonSetupArraySizes  to determine its size before allocating!
    SDKReturnCode SkeletonSetupManager::GetSkeletonChains(uint32_t p_SkeletonSetupIndex, ChainSetup* p_SDK)
    {
        if (p_SDK == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_NullPointer;
        }
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        for (size_t i = 0; i < t_Skl->chains.size(); i++)
        {
            p_SDK[i] = *t_Skl->chains[i];
        }

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetSkeletonChains(uint32_t p_SkeletonSetupIndex, ChainSetup* p_ChainSetupArray, uint32_t p_ArraySize)
    {
        if (p_ChainSetupArray == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_NullPointer;
        }
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);

        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        if (p_ArraySize != t_Skl->chains.size())
        {
            return SDKReturnCode::SDKReturnCode_ArgumentSizeMismatch;
        }

        for (size_t i = 0; i < t_Skl->chains.size(); i++)
        {
            p_ChainSetupArray[i] = *t_Skl->chains[i];
        }

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetSkeletonSetupInfo(uint32_t p_SkeletonSetupIndex, SkeletonSetupInfo* p_SDK)
    {
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }
        p_SDK->id = t_Skl->info->id;
        p_SDK->type = t_Skl->info->type;
        for (int i = 0; i < MAX_NUM_CHARS_IN_SKELETON_NAME; i++) // note this is not a regular string. but an UTF8 array. hence this form of copy.
        {
            p_SDK->name[i] = t_Skl->info->name[i];
        }
        p_SDK->settings.collisionType = t_Skl->info->settings.collisionType;
        p_SDK->settings.scaleToTarget = t_Skl->info->settings.scaleToTarget;
        p_SDK->settings.skeletonGloveData.gloveID = t_Skl->info->settings.skeletonGloveData.gloveID;
        for (int i = 0; i < MAX_NUM_CHARS_IN_TARGET_ID; i++) // note this is not a regular string. but an UTF8 array. hence this form of copy.
        {
            p_SDK->settings.skeletonTargetAnimationData.id[i] = t_Skl->info->settings.skeletonTargetAnimationData.id[i];
        }
        p_SDK->settings.skeletonTargetUserData.userID = t_Skl->info->settings.skeletonTargetUserData.userID;
        p_SDK->settings.skeletonTargetUserIndexData.userIndex = t_Skl->info->settings.skeletonTargetUserIndexData.userIndex;
        p_SDK->settings.targetType = t_Skl->info->settings.targetType;
        p_SDK->settings.useEndPointApproximations = t_Skl->info->settings.useEndPointApproximations;

        return SDKReturnCode::SDKReturnCode_Success;
    }

    // p_SDK is a pre allocated array of nodesetups! check chainskeletoninfo to determine its size before allocating!
    SDKReturnCode SkeletonSetupManager::GetSkeletonNodes(uint32_t p_SkeletonSetupIndex, NodeSetup* p_SDK)
    {
        if (p_SDK == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_NullPointer;
        }
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        for (size_t i = 0; i < t_Skl->nodes.size(); i++)
        {
            p_SDK[i] = *t_Skl->nodes[i];
        }

        return SDKReturnCode::SDKReturnCode_Success;
    }

    SDKReturnCode SkeletonSetupManager::GetSkeletonNodes(uint32_t p_SkeletonSetupIndex, NodeSetup* p_NodeSetupArray, uint32_t p_ArraySize)
    {
        if (p_NodeSetupArray == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_NullPointer;
        }
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        if (p_ArraySize != t_Skl->nodes.size())
        {
            return SDKReturnCode::SDKReturnCode_ArgumentSizeMismatch;
        }

        for (size_t i = 0; i < t_Skl->nodes.size(); i++)
        {
            p_NodeSetupArray[i] = *t_Skl->nodes[i];
        }

        return SDKReturnCode::SDKReturnCode_Success;
    }

    // p_SDK is a pre allocated array of collider setups! check chainskeletoninfo to determine its size before allocating!
    SDKReturnCode SkeletonSetupManager::GetSkeletonColliders(uint32_t p_SkeletonSetupIndex, ColliderSetup* p_SDK)
    {
        if (p_SDK == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_NullPointer;
        }
        const std::lock_guard<std::mutex> t_ManagedMutexLock(m_SkeletonSetupMutex);
        SkeletonSetup* t_Skl = GetSkeletonSetup(p_SkeletonSetupIndex);

        if (t_Skl == nullptr)
        {
            return SDKReturnCode::SDKReturnCode_InvalidID;
        }

        for (size_t i = 0; i < t_Skl->colliders.size(); i++)
        {
            p_SDK[i] = *t_Skl->colliders[i];
        }

        return SDKReturnCode::SDKReturnCode_Success;
    }

    std::mutex& SkeletonSetupManager::GetSkeletonSetupMutex()
    {
        return m_SkeletonSetupMutex;
    }

    size_t SkeletonSetupManager::GetSkeletonSetupBufferSize()
    {
        return m_SkeletonSetupBuffer.size();
    }
}