444 lines
19 KiB
C++
444 lines
19 KiB
C++
/*
|
|
* Copyright (c) <2017> Side Effects Software Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
#include "HoudiniParamUtils.h"
|
|
|
|
#include "HoudiniApi.h"
|
|
#include "HoudiniEngineRuntimePrivatePCH.h"
|
|
|
|
#include "HoudiniAssetInput.h"
|
|
#include "HoudiniAssetInstanceInput.h"
|
|
#include "HoudiniAssetParameter.h"
|
|
#include "HoudiniAssetParameterButton.h"
|
|
#include "HoudiniAssetParameterChoice.h"
|
|
#include "HoudiniAssetParameterColor.h"
|
|
#include "HoudiniAssetParameterFile.h"
|
|
#include "HoudiniAssetParameterFloat.h"
|
|
#include "HoudiniAssetParameterFolder.h"
|
|
#include "HoudiniAssetParameterFolderList.h"
|
|
#include "HoudiniAssetParameterInt.h"
|
|
#include "HoudiniAssetParameterLabel.h"
|
|
#include "HoudiniAssetParameterMultiparm.h"
|
|
#include "HoudiniAssetParameterRamp.h"
|
|
#include "HoudiniAssetParameterSeparator.h"
|
|
#include "HoudiniAssetParameterString.h"
|
|
#include "HoudiniAssetParameterToggle.h"
|
|
#include "HoudiniEngine.h"
|
|
#include "HoudiniEngineString.h"
|
|
#include "HoudiniEngineUtils.h"
|
|
#include "HoudiniRuntimeSettings.h"
|
|
|
|
|
|
bool
|
|
FHoudiniParamUtils::Build( HAPI_NodeId AssetId, class UObject* PrimaryObject,
|
|
TMap< HAPI_ParmId, class UHoudiniAssetParameter * >& CurrentParameters,
|
|
TMap< HAPI_ParmId, class UHoudiniAssetParameter * >& NewParameters )
|
|
{
|
|
if( !FHoudiniEngineUtils::IsValidNodeId( AssetId ) )
|
|
{
|
|
// There's no Houdini asset, we can return.
|
|
return false;
|
|
}
|
|
|
|
bool bTreatRampParametersAsMultiparms = false;
|
|
const UHoudiniRuntimeSettings * HoudiniRuntimeSettings = GetDefault< UHoudiniRuntimeSettings >();
|
|
if( HoudiniRuntimeSettings )
|
|
bTreatRampParametersAsMultiparms = HoudiniRuntimeSettings->bTreatRampParametersAsMultiparms;
|
|
|
|
HAPI_Result Result = HAPI_RESULT_SUCCESS;
|
|
|
|
HAPI_AssetInfo AssetInfo;
|
|
HOUDINI_CHECK_ERROR_RETURN( FHoudiniApi::GetAssetInfo(
|
|
FHoudiniEngine::Get().GetSession(), AssetId, &AssetInfo ), false );
|
|
|
|
HAPI_NodeInfo NodeInfo;
|
|
HOUDINI_CHECK_ERROR_RETURN( FHoudiniApi::GetNodeInfo(
|
|
FHoudiniEngine::Get().GetSession(), AssetInfo.nodeId, &NodeInfo ), false );
|
|
|
|
if( NodeInfo.parmCount > 0 )
|
|
{
|
|
// Retrieve parameters.
|
|
TArray< HAPI_ParmInfo > ParmInfos;
|
|
ParmInfos.SetNumUninitialized( NodeInfo.parmCount );
|
|
HOUDINI_CHECK_ERROR_RETURN(
|
|
FHoudiniApi::GetParameters(
|
|
FHoudiniEngine::Get().GetSession(), AssetInfo.nodeId, &ParmInfos[ 0 ], 0,
|
|
NodeInfo.parmCount ), false );
|
|
|
|
// Create name lookup cache
|
|
TMap<FString, UHoudiniAssetParameter*> CurrentParametersByName;
|
|
CurrentParametersByName.Reserve( CurrentParameters.Num() );
|
|
for( auto& ParmPair : CurrentParameters )
|
|
{
|
|
if ( ParmPair.Value && !ParmPair.Value->IsPendingKill() )
|
|
CurrentParametersByName.Add( ParmPair.Value->GetParameterName(), ParmPair.Value );
|
|
}
|
|
|
|
// Create properties for parameters.
|
|
for( int32 ParamIdx = 0; ParamIdx < NodeInfo.parmCount; ++ParamIdx )
|
|
{
|
|
// Retrieve param info at this index.
|
|
const HAPI_ParmInfo & ParmInfo = ParmInfos[ ParamIdx ];
|
|
|
|
// If the parameter is corrupt, skip it
|
|
if( ParmInfo.id < 0 || ParmInfo.childIndex < 0 )
|
|
{
|
|
HOUDINI_LOG_WARNING( TEXT( "Corrupt parameter %d detected, skipping. Note: Plug-in does not support nested Multiparm parameters" ), ParamIdx );
|
|
continue;
|
|
}
|
|
|
|
// If parameter is invisible, skip it.
|
|
if( ParmInfo.invisible )
|
|
continue;
|
|
|
|
// Check if any parent folder of this parameter is invisible
|
|
bool SkipParm = false;
|
|
HAPI_ParmId ParentId = ParmInfo.parentId;
|
|
while( ParentId > 0 && !SkipParm )
|
|
{
|
|
if( const HAPI_ParmInfo* ParentInfoPtr = ParmInfos.FindByPredicate( [=]( const HAPI_ParmInfo& Info ) {
|
|
return Info.id == ParentId;
|
|
} ) )
|
|
{
|
|
if( ParentInfoPtr->invisible && ParentInfoPtr->type == HAPI_PARMTYPE_FOLDER )
|
|
SkipParm = true;
|
|
ParentId = ParentInfoPtr->parentId;
|
|
}
|
|
else
|
|
{
|
|
HOUDINI_LOG_ERROR( TEXT( "Could not find parent of parameter %d" ), ParmInfo.id );
|
|
SkipParm = true;
|
|
}
|
|
}
|
|
|
|
if( SkipParm )
|
|
continue;
|
|
|
|
UHoudiniAssetParameter * HoudiniAssetParameter = nullptr;
|
|
|
|
// See if this parameter has already been created.
|
|
// We can't use HAPI_ParmId because that is not unique to parameter instances, so instead
|
|
// we find the existing parameter by name
|
|
FString NewParmName;
|
|
FHoudiniEngineString( ParmInfo.nameSH ).ToFString( NewParmName );
|
|
UHoudiniAssetParameter ** FoundHoudiniAssetParameter = CurrentParametersByName.Find( NewParmName );
|
|
|
|
// If parameter exists, we can reuse it.
|
|
if( FoundHoudiniAssetParameter && *FoundHoudiniAssetParameter && !(*FoundHoudiniAssetParameter)->IsPendingKill() )
|
|
{
|
|
// sanity check that type and tuple size hasn't changed
|
|
if( (*FoundHoudiniAssetParameter)->GetTupleSize() == ParmInfo.size )
|
|
{
|
|
UClass* FoundClass = (*FoundHoudiniAssetParameter)->GetClass();
|
|
bool FailedTypeCheck = true;
|
|
switch( ParmInfo.type )
|
|
{
|
|
case HAPI_PARMTYPE_STRING:
|
|
if( !ParmInfo.choiceCount )
|
|
FailedTypeCheck &= !FoundClass->IsChildOf< UHoudiniAssetParameterString >();
|
|
else
|
|
FailedTypeCheck &= !FoundClass->IsChildOf< UHoudiniAssetParameterChoice >();
|
|
break;
|
|
case HAPI_PARMTYPE_INT:
|
|
if( !ParmInfo.choiceCount )
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterInt>();
|
|
else
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterChoice>();
|
|
break;
|
|
case HAPI_PARMTYPE_FLOAT:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterFloat>();
|
|
break;
|
|
case HAPI_PARMTYPE_TOGGLE:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterToggle>();
|
|
break;
|
|
case HAPI_PARMTYPE_COLOR:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterColor>();
|
|
break;
|
|
case HAPI_PARMTYPE_LABEL:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterLabel>();
|
|
break;
|
|
case HAPI_PARMTYPE_BUTTON:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterButton>();
|
|
break;
|
|
case HAPI_PARMTYPE_SEPARATOR:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterSeparator>();
|
|
break;
|
|
case HAPI_PARMTYPE_FOLDERLIST:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterFolderList>();
|
|
break;
|
|
case HAPI_PARMTYPE_FOLDER:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterFolder>();
|
|
break;
|
|
case HAPI_PARMTYPE_MULTIPARMLIST:
|
|
if( !bTreatRampParametersAsMultiparms && ( HAPI_RAMPTYPE_FLOAT == ParmInfo.rampType ||
|
|
HAPI_RAMPTYPE_COLOR == ParmInfo.rampType ) )
|
|
{
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterRamp>();
|
|
}
|
|
else
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterMultiparm>();
|
|
break;
|
|
case HAPI_PARMTYPE_PATH_FILE:
|
|
case HAPI_PARMTYPE_PATH_FILE_DIR:
|
|
case HAPI_PARMTYPE_PATH_FILE_GEO:
|
|
case HAPI_PARMTYPE_PATH_FILE_IMAGE:
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterFile>();
|
|
break;
|
|
case HAPI_PARMTYPE_NODE:
|
|
if( ParmInfo.inputNodeType == HAPI_NODETYPE_ANY ||
|
|
ParmInfo.inputNodeType == HAPI_NODETYPE_SOP ||
|
|
ParmInfo.inputNodeType == HAPI_NODETYPE_OBJ )
|
|
{
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetInput>();
|
|
}
|
|
else
|
|
{
|
|
FailedTypeCheck &= !FoundClass->IsChildOf<UHoudiniAssetParameterString>();
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( !FailedTypeCheck )
|
|
{
|
|
HoudiniAssetParameter = *FoundHoudiniAssetParameter;
|
|
|
|
// Transfer param object from current map to new map
|
|
CurrentParameters.Remove( HoudiniAssetParameter->GetParmId() );
|
|
CurrentParametersByName.Remove( NewParmName );
|
|
|
|
// Reinitialize parameter and add it to map.
|
|
HoudiniAssetParameter->CreateParameter( PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
NewParameters.Add( ParmInfo.id, HoudiniAssetParameter );
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch( ParmInfo.type )
|
|
{
|
|
case HAPI_PARMTYPE_STRING:
|
|
{
|
|
if( !ParmInfo.choiceCount )
|
|
HoudiniAssetParameter = UHoudiniAssetParameterString::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
else
|
|
HoudiniAssetParameter = UHoudiniAssetParameterChoice::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_INT:
|
|
{
|
|
if( !ParmInfo.choiceCount )
|
|
HoudiniAssetParameter = UHoudiniAssetParameterInt::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
else
|
|
HoudiniAssetParameter = UHoudiniAssetParameterChoice::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_FLOAT:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterFloat::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_TOGGLE:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterToggle::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_COLOR:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterColor::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_LABEL:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterLabel::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_BUTTON:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterButton::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_SEPARATOR:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterSeparator::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_FOLDERLIST:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterFolderList::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_FOLDER:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterFolder::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_MULTIPARMLIST:
|
|
{
|
|
if( !bTreatRampParametersAsMultiparms && ( HAPI_RAMPTYPE_FLOAT == ParmInfo.rampType ||
|
|
HAPI_RAMPTYPE_COLOR == ParmInfo.rampType ) )
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterRamp::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
}
|
|
else
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterMultiparm::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_PATH_FILE:
|
|
case HAPI_PARMTYPE_PATH_FILE_DIR:
|
|
case HAPI_PARMTYPE_PATH_FILE_GEO:
|
|
case HAPI_PARMTYPE_PATH_FILE_IMAGE:
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterFile::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
break;
|
|
}
|
|
|
|
case HAPI_PARMTYPE_NODE:
|
|
{
|
|
if( ParmInfo.inputNodeType == HAPI_NODETYPE_ANY ||
|
|
ParmInfo.inputNodeType == HAPI_NODETYPE_SOP ||
|
|
ParmInfo.inputNodeType == HAPI_NODETYPE_OBJ )
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetInput::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
}
|
|
else
|
|
{
|
|
HoudiniAssetParameter = UHoudiniAssetParameterString::Create(
|
|
PrimaryObject, nullptr, AssetInfo.nodeId, ParmInfo );
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
// Just ignore unsupported types for now.
|
|
HOUDINI_LOG_WARNING( TEXT( "Parameter Type (%d) is unsupported" ), static_cast<int32>( ParmInfo.type ) );
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ( HoudiniAssetParameter && !HoudiniAssetParameter->IsPendingKill() )
|
|
{
|
|
// Add this parameter to the map.
|
|
NewParameters.Add( ParmInfo.id, HoudiniAssetParameter );
|
|
}
|
|
}
|
|
|
|
// We a pass over the new params to patch parent links.
|
|
for( int32 ParamIdx = 0; ParamIdx < NodeInfo.parmCount; ++ParamIdx )
|
|
{
|
|
// Retrieve param info at this index.
|
|
const HAPI_ParmInfo & ParmInfo = ParmInfos[ ParamIdx ];
|
|
|
|
// Locate corresponding parameter.
|
|
UHoudiniAssetParameter * const * FoundHoudiniAssetParameter = NewParameters.Find( ParmInfo.id );
|
|
if (!FoundHoudiniAssetParameter)
|
|
continue;
|
|
|
|
UHoudiniAssetParameter * HoudiniAssetParameter = *FoundHoudiniAssetParameter;
|
|
if ( !HoudiniAssetParameter || HoudiniAssetParameter->IsPendingKill() )
|
|
continue;
|
|
|
|
// Get parent parm id.
|
|
UHoudiniAssetParameter * HoudiniAssetParentParameter = nullptr;
|
|
HAPI_ParmId ParentParmId = HoudiniAssetParameter->GetParmParentId();
|
|
if( ParentParmId != -1 )
|
|
{
|
|
// Locate corresponding parent parameter.
|
|
UHoudiniAssetParameter * const * FoundHoudiniAssetParentParameter = NewParameters.Find( ParentParmId );
|
|
if( FoundHoudiniAssetParentParameter )
|
|
HoudiniAssetParentParameter = *FoundHoudiniAssetParentParameter;
|
|
}
|
|
|
|
// Set parent for this parameter.
|
|
HoudiniAssetParameter->SetParentParameter( HoudiniAssetParentParameter );
|
|
|
|
if( ParmInfo.type == HAPI_PARMTYPE_FOLDERLIST )
|
|
{
|
|
// For folder lists we need to add children manually.
|
|
HoudiniAssetParameter->ResetChildParameters();
|
|
|
|
for( int32 ChildIdx = 0; ChildIdx < ParmInfo.size; ++ChildIdx )
|
|
{
|
|
// Children folder parm infos come after folder list parm info.
|
|
const HAPI_ParmInfo & ChildParmInfo = ParmInfos[ ParamIdx + ChildIdx + 1 ];
|
|
|
|
UHoudiniAssetParameter * const * FoundHoudiniAssetParameterChild =
|
|
NewParameters.Find( ChildParmInfo.id );
|
|
|
|
if( FoundHoudiniAssetParameterChild )
|
|
{
|
|
UHoudiniAssetParameter * HoudiniAssetParameterChild = *FoundHoudiniAssetParameterChild;
|
|
if ( HoudiniAssetParameterChild && !HoudiniAssetParameterChild->IsPendingKill() )
|
|
HoudiniAssetParameterChild->SetParentParameter( HoudiniAssetParameter );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Another pass to notify parameters that all children parameters have been assigned
|
|
for( auto& NewParamPair : NewParameters )
|
|
{
|
|
if (NewParamPair.Value && !NewParamPair.Value->IsPendingKill() )
|
|
continue;
|
|
|
|
if( NewParamPair.Value->HasChildParameters() )
|
|
NewParamPair.Value->NotifyChildParametersCreated();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|