// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #include <frantic/max3d/geopipe/get_inodes.hpp> #include <frantic/max3d/parameter_extraction.hpp> #pragma warning( push, 3 ) #include <IParticleObjectExt.h> #include <ParticleFlow/IPFActionList.h> #include <ParticleFlow/IPFActionListSet.h> #include <ParticleFlow/IPFRender.h> #include <ParticleFlow/IParticleGroup.h> #pragma warning( pop ) namespace frantic { namespace max3d { namespace particles { //<-- Copied from ParticleFlow/PFOperatorRender_ParamBlock.h --> enum { kPFRender_type }; enum { kPFRender_mainPBlockIndex }; enum { kPFRender_type_none, kPFRender_type_boundingBoxes, kPFRender_type_geometry, kPFRender_type_phantom, kPFRender_type_num = 4 }; //<-- End copy --> inline Object* get_render_operator( IParticleGroup* pGroup ) { if( !pGroup ) throw std::runtime_error( "get_render_operator() - called w/ a NULL IParticleGroup" ); IPFActionList* pActions = NULL; Object* pRenderOp = NULL; // Get the local render operator pActions = PFActionListInterface( pGroup->GetActionList() ); if( !pActions->IsActivated() || !pActions->HasUpStream() ) return NULL; // Node cannot have particles if its deactivated or has no incoming particles for( int i = 0; !pRenderOp && i < pActions->NumActions(); ++i ) { if( PFRenderInterface( pActions->GetAction( i ) ) && pActions->IsActionActive( i ) ) pRenderOp = GetPFObject( pActions->GetAction( i )->GetObjectRef() ); } // Get the global render operator if this group didn't have one INode* pSysNode = pGroup->GetParticleSystem(); if( !pSysNode ) throw std::runtime_error( "get_render_operator() - called w/ a NULL IPFSystem" ); // BUG: Getting the system node from a group is wrong in at least one Box 2 scene. // std::string name = pSysNode->GetName(); pActions = PFActionListInterface( pSysNode ); if( pActions->IsActivated() ) { for( int i = 0; !pRenderOp && i < pActions->NumActions(); ++i ) { if( PFRenderInterface( pActions->GetAction( i ) ) && pActions->IsActionActive( i ) ) pRenderOp = GetPFObject( pActions->GetAction( i )->GetObjectRef() ); } } return pRenderOp; } inline int get_render_operator_type( Object* pRenderOp ) { if( !PFRenderInterface( pRenderOp ) ) throw std::runtime_error( "get_render_operator_type() - the Object* passed was not a PFRenderOperator" ); IParamBlock2* pb = static_cast<Animatable*>( pRenderOp )->GetParamBlock( kPFRender_mainPBlockIndex ); if( !pb ) throw std::runtime_error( "get_render_operator_type() - Could not get pblock from render op" ); return pb->GetInt( kPFRender_type ); } inline int get_render_operator_type( IParticleGroup* pGroup ) { if( Object* pRenderOp = get_render_operator( pGroup ) ) return get_render_operator_type( pRenderOp ); return -1; } // This function used to be in the particles namespace // extracts all particle groups of a particular type from a node. inline void extract_geometry_particle_groups( std::set<INode*>& groups, INode* node ) { if( !node ) throw std::runtime_error( "frantic::max3d::extract_geometry_particle_groups passed a null INode" ); Object* node_obj = node->GetObjectRef(); // first, make sure this inode has something to do with particles. if( node_obj && GetParticleObjectExtInterface( node_obj ) ) { // try to get the groups from the node. std::vector<INode*> inodes; frantic::max3d::get_referring_inodes( inodes, node ); // mprintf("checking %d inodes\n", inodes.size()); std::vector<INode*>::iterator i = inodes.begin(); for( ; i != inodes.end(); i++ ) { if( *i ) { Object* obj = ( *i )->GetObjectRef(); if( obj ) { if( IParticleGroup* pGroup = ParticleGroupInterface( obj ) ) { if( get_render_operator_type( pGroup ) == 2 ) groups.insert( *i ); } } } } } } } // namespace particles } // namespace max3d } // namespace frantic