Problems with setting parameters in an HDA

   1486   1   1
User Avatar
Member
3 posts
Joined: Dec. 2019
Offline
Hi there,

I am trying to set parameters in a Digital Asset using the following code. Unfortunately this works
not right.When I set the parameters, the note Cook and display the parameters again, they have not changed.

The goal is to set two paths, trigger a toggle and a button.

What am I doing wrong?

Thanks
Sascha


#include <HAPI.h>
#include <iostream>
#include <string>

#define ENSURE_SUCCESS( result ) \
if ( (result) != HAPI_RESULT_SUCCESS ) \
{ \
    std::cout << "Failure at " << __FILE__ << ": " << __LINE__ << std::endl; \
    std::cout << getLastError() << std::endl; \
    exit( 1 ); \
}

#define ENSURE_COOK_SUCCESS( result ) \
if ( (result) != HAPI_RESULT_SUCCESS ) \
{ \
    std::cout << "Failure at " << __FILE__ << ": " << __LINE__ << std::endl; \
    std::cout << getLastCookError() << std::endl; \
    exit( 1 ); \
}

static std::string getLastError();
static std::string getLastCookError();
static std::string getString(HAPI_StringHandle stringHandle);
static void printHDAParamInfos(HAPI_NodeInfo & nodeInfo, HAPI_ParmInfo * parmInfos, HAPI_Session & session, HAPI_NodeId & nodeId);
static void CookSession(HAPI_Session & session, HAPI_NodeId & nodeId, HAPI_CookOptions & cookOptions);

int main(int argc, char** argv)
{
    const char* hdaFile = argc == 2 ? argv[1] : "test.hda";

    int inputFileParamID = 41;
    int outputFileParamID = 42;
    int mergeParamID = 39;
    int executeParamID = 43;

    const char* inPath = "test_mesh.fbx";
    const char* outPath = "change.fbx";

    HAPI_Session session;
    bool bUseInProcess = false;

    if (bUseInProcess)
    {
        // Creates an in process session
        HAPI_CreateInProcessSession(&session);
    }
    else
    {
        // Start and connect to an out of process session
        HAPI_ThriftServerOptions serverOptions{ 0 };
        serverOptions.autoClose = true;
        serverOptions.timeoutMs = 3000.0f;

        // Start a HARS named-pipe server named "hapi"
        ENSURE_SUCCESS(HAPI_StartThriftNamedPipeServer(&serverOptions, "hapi", nullptr));
        // and create a new HAPI session to use that server
        ENSURE_SUCCESS(HAPI_CreateThriftNamedPipeSession(&session, "hapi"));
    }

    HAPI_CookOptions cookOptions = HAPI_CookOptions_Create();
    ENSURE_SUCCESS(HAPI_Initialize(&session,
        &cookOptions,
        true,
        -1,
        nullptr,
        nullptr,
        nullptr,
        nullptr,
        nullptr));

    HAPI_AssetLibraryId assetLibId;
    ENSURE_SUCCESS(HAPI_LoadAssetLibraryFromFile(&session, hdaFile, true, &assetLibId));

    int assetCount;
    ENSURE_SUCCESS(HAPI_GetAvailableAssetCount(&session, assetLibId, &assetCount));
    if (assetCount > 1)
    {
        std::cout << "Should only be loading 1 asset here" << std::endl;
        exit(1);
    }

    HAPI_StringHandle assetSh;
    ENSURE_SUCCESS(HAPI_GetAvailableAssets(&session, assetLibId, &assetSh, assetCount));

    std::string assetName = getString(assetSh);
    HAPI_NodeId nodeId;
    
    ENSURE_SUCCESS(HAPI_CreateNode(&session, -1, assetName.c_str(), "AnAsset", false, &nodeId));
    CookSession(session, nodeId, cookOptions);

    HAPI_NodeInfo nodeInfo;
    ENSURE_SUCCESS(HAPI_GetNodeInfo(&session, nodeId, &nodeInfo));

    HAPI_ParmInfo* parmInfos = new HAPI_ParmInfo[nodeInfo.parmCount];

    ENSURE_SUCCESS(HAPI_GetParameters(&session, nodeId, parmInfos, 0, nodeInfo.parmCount));

    // Print parameter info
    printHDAParamInfos(nodeInfo, parmInfos, session, nodeId);

    HAPI_ParmInfo inputFileParmInfo;
    ENSURE_SUCCESS(HAPI_GetParmInfo(&session, nodeId, inputFileParamID, &inputFileParmInfo));
   
    HAPI_ParmInfo outputFileParmInfo;
    ENSURE_SUCCESS(HAPI_GetParmInfo(&session, nodeId, outputFileParamID, &outputFileParmInfo));

    HAPI_ParmInfo mergeParmInfo;
    ENSURE_SUCCESS(HAPI_GetParmInfo(&session, nodeId, mergeParamID, &mergeParmInfo));

    HAPI_ParmInfo executeParmInfo;
    ENSURE_SUCCESS(HAPI_GetParmInfo(&session, nodeId, executeParamID, &executeParmInfo));

    //Set new parameters
    ENSURE_SUCCESS(HAPI_SetParmIntValue(&session, nodeId, getString(mergeParmInfo.nameSH).c_str(), mergeParmInfo.intValuesIndex, 1));

    ENSURE_SUCCESS(HAPI_SetParmStringValue(&session, nodeId, inPath, inputFileParmInfo.id, inputFileParmInfo.stringValuesIndex));

    ENSURE_SUCCESS(HAPI_SetParmStringValue(&session, nodeId, outPath, outputFileParmInfo.id, outputFileParmInfo.stringValuesIndex));

    ENSURE_SUCCESS(HAPI_SetParmIntValue(&session, nodeId, getString(executeParmInfo.nameSH).c_str(), executeParmInfo.intValuesIndex, 1));

    CookSession(session, nodeId, cookOptions);
    std::cout << std::endl << "---------------------- New parameter ----------------------" << std::endl << std::endl;

    ENSURE_SUCCESS(HAPI_GetNodeInfo(&session, nodeId, &nodeInfo));

    delete[] parmInfos;
    parmInfos = new HAPI_ParmInfo[nodeInfo.parmCount];

    ENSURE_SUCCESS(HAPI_GetParameters(&session, nodeId, parmInfos, 0, nodeInfo.parmCount));

    // Print parameter info
    printHDAParamInfos(nodeInfo, parmInfos, session, nodeId);

    delete[] parmInfos;
    char in;
    std::cout << "Press any key to exit" << std::endl;
    std::cin >> in;

    HAPI_Cleanup(&session);

    return 0;
}

static std::string getLastError()
{
    int bufferLength;
    HAPI_GetStatusStringBufLength(nullptr,
        HAPI_STATUS_CALL_RESULT,
        HAPI_STATUSVERBOSITY_ERRORS,
        &bufferLength);
    char* buffer = new char[bufferLength];
    HAPI_GetStatusString(nullptr, HAPI_STATUS_CALL_RESULT, buffer, bufferLength);
    std::string result(buffer);
    delete[] buffer;
    return result;
}

static std::string getLastCookError()
{
    int bufferLength;
    HAPI_GetStatusStringBufLength(nullptr,
        HAPI_STATUS_COOK_RESULT,
        HAPI_STATUSVERBOSITY_ERRORS,
        &bufferLength);
    char* buffer = new char[bufferLength];
    HAPI_GetStatusString(nullptr, HAPI_STATUS_COOK_RESULT, buffer, bufferLength);
    std::string result(buffer);
    delete[] buffer;
    return result;
}

static std::string getString(HAPI_StringHandle stringHandle)
{
    if (stringHandle == 0)
    {
        return "";
    }
    int bufferLength;
    HAPI_GetStringBufLength(nullptr,
        stringHandle,
        &bufferLength);
    char* buffer = new char[bufferLength];
    HAPI_GetString(nullptr, stringHandle, buffer, bufferLength);
    std::string result(buffer);
    delete[] buffer;
    return result;
}

static void printHDAParamInfos(HAPI_NodeInfo& nodeInfo, HAPI_ParmInfo* parmInfos, HAPI_Session& session, HAPI_NodeId& nodeId)
{
    std::cout << "Parameters: " << std::endl;
    for (int i = 0; i < nodeInfo.parmCount; ++i)
    {
        std::cout << "==========" << std::endl;
        std::cout << "   Name: "
            << getString(parmInfos[i].nameSH)
            << std::endl;
        std::cout << "   Values: (";
        if (HAPI_ParmInfo_IsInt(&parmInfos[i]))
        {
            std::cout << "<Int parameter>";

            int parmIntCount = HAPI_ParmInfo_GetIntValueCount(&parmInfos[i]);

            int* parmIntValues = new int[parmIntCount];

            ENSURE_SUCCESS(HAPI_GetParmIntValues(&session,
                nodeId, parmIntValues,
                parmInfos[i].intValuesIndex,
                parmIntCount));

            std::cout << "[ID " << parmInfos[i].id << "] Value: ";

            for (int v = 0; v < parmIntCount; ++v)
            {
                if (v != 0)
                    std::cout << ", ";
                std::cout << parmIntValues[v];
            }

            delete[] parmIntValues;
        }
        else if (HAPI_ParmInfo_IsFloat(&parmInfos[i]))
        {
            std::cout << "<Float parameter>";

            int parmFloatCount = HAPI_ParmInfo_GetFloatValueCount(&parmInfos[i]);
            float* parmFloatValues = new float[parmFloatCount];

            ENSURE_SUCCESS(HAPI_GetParmFloatValues(&session,
                nodeId, parmFloatValues,
                parmInfos[i].floatValuesIndex,
                parmFloatCount));

            std::cout << " [ID " << parmInfos[i].id << "] Value: ";

            for (int v = 0; v < parmFloatCount; ++v)
            {
                if (v != 0)
                    std::cout << ", ";
                std::cout << parmFloatValues[v];
            }

            delete[] parmFloatValues;
        }
        else if (HAPI_ParmInfo_IsString(&parmInfos[i]))
        {
            std::cout << "<String parameter>";

            int parmStringCount = HAPI_ParmInfo_GetStringValueCount(&parmInfos[i]);
            HAPI_StringHandle* parmSHValues = new HAPI_StringHandle[parmStringCount];

            ENSURE_SUCCESS(HAPI_GetParmStringValues(&session,
                nodeId,
                true, parmSHValues,
                parmInfos[i].stringValuesIndex,
                parmStringCount));

            std::cout << " [ID " << parmInfos[i].id << "] Value: ";

            for (int v = 0; v < parmStringCount; ++v)
            {
                if (v != 0)
                    std::cout << ", ";

                std::cout << getString(parmSHValues[v]);
            }
            delete[] parmSHValues;
        }

        std::cout << ")" << std::endl;
    }
}

static void CookSession(HAPI_Session& session, HAPI_NodeId& nodeId, HAPI_CookOptions& cookOptions)
{
    ENSURE_SUCCESS(HAPI_CookNode(&session, nodeId, &cookOptions));
    
    int cookStatus;
    HAPI_Result cookResult;
    do
    {
        cookResult = HAPI_GetStatus(&session, HAPI_STATUS_COOK_STATE, &cookStatus);
    } while (cookStatus > HAPI_STATE_MAX_READY_STATE && cookResult == HAPI_RESULT_SUCCESS);
    ENSURE_SUCCESS(cookResult);
    ENSURE_COOK_SUCCESS(cookStatus);
}

Attachments:
test.hda (24.0 KB)

User Avatar
Member
603 posts
Joined: Sept. 2016
Offline
The call to HAPI_SetParmIntValue is asynchronous when you are initialized to use the cooking thread, so you need to wait for HAPI_GetStatus to return a ‘ready’ enum before proceeding to the next thing.


///
///         @note In threaded mode, this is an _async call_!
///
///         This API will invoke the cooking thread if threading is
///         enabled. This means it will return immediately. Use
///         the status and cooking count APIs under DIAGNOSTICS to get
///         a sense of the progress. All other API calls will block
///         until the cook operation has finished.
///
///         Also note that the cook result won't be of type
///         ::HAPI_STATUS_CALL_RESULT like all calls (including this one).
///         Whenever the threading cook is done it will fill the
///         @a cook result which is queried using
///         ::HAPI_STATUS_COOK_RESULT.

As far as debugging, you may want to use the debugger / SessionSync in an interactive Houdini session so that you can see what changes are occurring in the scene.
http://www.sidefx.com/docs/houdini/ref/henginesessionsync.html [www.sidefx.com]
Edited by chrisgreb - June 3, 2020 12:34:27
  • Quick Links