public override void OnInspectorGUI() { HoudiniInstancer[] instancers = myAssetOTL.gameObject.GetComponentsInChildren< HoudiniInstancer >(); if( !myAssetOTL.isPrefab() && instancers.Length > 0 ) { generateAssetInstanceControls(); } Event current_event = Event.current; if ( current_event.type == EventType.ValidateCommand && current_event.commandName == "UndoRedoPerformed" ) { foreach( HoudiniInstancer instancer in instancers ) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); instancer.instanceObjects( progress_bar ); progress_bar.clearProgressBar(); } Repaint(); } }
public override void OnInspectorGUI() { HoudiniInstancer[] instancers = myAssetOTL.gameObject.GetComponentsInChildren <HoudiniInstancer>(); if (instancers.Length > 0) { generateAssetInstanceControls(); } Event current_event = Event.current; if ( current_event.type == EventType.ValidateCommand && current_event.commandName == "UndoRedoPerformed") { foreach (HoudiniInstancer instancer in instancers) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); instancer.instanceObjects(progress_bar); progress_bar.clearProgressBar(); } Repaint(); } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset(HoudiniProgressBar progress_bar) { // Try to find the otl if it has moved. #if UNITY_EDITOR #if UNITY_4_3 || UNITY_4_4 // Finding moved assets is not supported in Unity 4.4 and earlier versions. #else if (!System.IO.File.Exists(prAssetPath)) { string file_name = System.IO.Path.GetFileNameWithoutExtension(prAssetPath); string[] guids = AssetDatabase.FindAssets(file_name); if (guids.Length == 0) { throw new HoudiniError( "Houdini asset file has moved from last location: " + prAssetPath); } prAssetPath = AssetDatabase.GUIDToAssetPath(guids[0]); } #endif // UNITY_4_3 || UNITY_4_4 #endif // UNITY_EDITOR return(HoudiniHost.loadOTL( prAssetPath, prSplitGeosByGroup, prImportTemplatedGeos, progress_bar, false)); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset(HoudiniProgressBar progress_bar) { //return HoudiniHost.createInputAsset( transform.name ); return(HoudiniHost.instantiateAsset("SOP/merge", true)); }
protected override bool buildCreateObjects(bool reload_asset, ref HoudiniProgressBar progress_bar) { return(false); }
public override void onParmChange() { base.onParmChange(); if ( isPrefab() ) { if ( prParms.prLastChangedParmId != HoudiniConstants.HAPI_INVALID_PARM_ID ) { HAPI_ParmInfo parm_info = prParms.findParm( prParms.prLastChangedParmId ); prUpdatePrefabInstanceParmNames.Add( parm_info.name ); } HoudiniProgressBar progress_bar = new HoudiniProgressBar(); try { // only need to update parameters for prefab updateParameters( progress_bar ); } catch {} finally { progress_bar.clearProgressBar(); } #if UNITY_EDITOR EditorUtility.SetDirty( this ); #endif // UNITY_EDITOR } else { build( false, // reload_asset false, // unload_asset_first false, // serializatin_recovery_only false, // force_reconnect false, // is_duplication prCookingTriggersDownCooks, true // use_delay_for_progress_bar ); } // To keep things consistent with Unity workflow, we should not save parameter changes // while in Play mode. #if UNITY_EDITOR if ( !EditorApplication.isPlaying ) savePreset(); #endif // UNITY_EDITOR }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset(HoudiniProgressBar progress_bar) { return(HoudiniHost.createInputAsset(transform.name)); }
public void updateParameters( HoudiniProgressBar progress_bar ) { // Update prefab instance after parameter change on prefab if needed #if UNITY_EDITOR if ( isPrefabInstance() && prUpdatePrefabInstanceParmNames.Count > 0 ) { HoudiniAsset prefab_asset = getParentPrefabAsset(); foreach ( string parm_name in prUpdatePrefabInstanceParmNames ) { try { HAPI_ParmInfo parm_info = prParms.findParm( parm_name ); // Do not apply changes from prefab in the following cases: // Case 1: Parameter on prefab that has been changed is a // transform parameter // Case 2: Parameter on prefab that has been changed has been // overridden on this asset // Otherwise set the parameter change for this prefab if ( parm_name != "r" && parm_name != "s" && parm_name != "t" && !prParms.isParmOverridden( parm_info.id ) ) { // if the parameter is a string we need to manually // get the string value from the prefab because the // parameter strings are stored in a dictionary which // is not serialized so the value isn't overridden // automatically by the prefab value as it is done // with float and int parameters if ( parm_info.isString() && prefab_asset ) { HAPI_ParmInfo prefab_parm_info = prefab_asset.prParms.findParm( parm_name ); string[] values = prefab_asset.prParms.getParmStrings( prefab_parm_info ); prParms.setParmStrings( parm_info, values ); } prParms.setChangedParameterIntoHost( parm_info.id ); } } catch {} } prUpdatePrefabInstanceParmNames.Clear(); // Need to set prUpdatePrefabInstanceParmName back to empty on prefab if // it hasn't been already. We do not set prefab to be dirty so that other // prefab instances that still need this value will not be affected. if ( prefab_asset && prefab_asset.prUpdatePrefabInstanceParmNames.Count > 0 ) { prefab_asset.prUpdatePrefabInstanceParmNames.Clear(); } } #endif // UNITY_EDITOR prParms.setChangedParametersIntoHost(); HoudiniHost.cookAsset( prAssetId, prSplitGeosByGroup, prImportTemplatedGeos ); progress_bar.statusCheckLoop(); myProgressBarJustUsed = true; progress_bar.prTotal = prObjectCount; prParms.getParameterValues(); }
protected override bool buildCreateObjects( bool reload_asset, ref HoudiniProgressBar progress_bar ) { try { const int object_id = 0; const int geo_id = 0; // Write marshalled geo to Input Asset. HoudiniAssetUtility.setMesh( prAssetId, object_id, geo_id, ref myEditableMesh, null, myGeoAttributeManager ); // Apply the input asset transform to the marshaled object in the Houdini scene. HAPI_TransformEuler trans = HoudiniAssetUtility.getHapiTransform( transform.localToWorldMatrix ); HoudiniHost.setObjectTransform( prAssetId, object_id, ref trans ); // Marshall in the animation. Animation anim_component = GetComponent< Animation >(); if ( anim_component ) if ( anim_component.clip != null ) marshalCurvesFromClip( prObjectNodeId, anim_component.clip ); else foreach ( AnimationState anim_state in anim_component ) { AnimationClip clip = anim_component.GetClip( anim_state.name ); if ( clip != null ) { marshalCurvesFromClip( prObjectNodeId, clip ); break; } } HoudiniHost.repaint(); } catch ( HoudiniError ) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. //Debug.LogWarning( error.ToString() ); } return false; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset( HoudiniProgressBar progress_bar ) { return HoudiniHost.createInputAsset( transform.name ); }
protected override bool buildCreateObjects( bool reload_asset, ref HoudiniProgressBar progress_bar ) { bool needs_recook = false; for ( int object_index = 0; object_index < prObjectCount; ++object_index ) { progress_bar.incrementProgressBar(); try { if ( !prObjects[ object_index ].isInstancer && ( reload_asset || prObjects[ object_index ].hasTransformChanged || prObjects[ object_index ].haveGeosChanged ) ) { needs_recook |= createObject( object_index, reload_asset ); } } catch ( HoudiniError error ) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning( error.ToString() ); } } // Processing instancers. for ( int object_index = 0; object_index < prObjectCount; ++object_index ) { HAPI_ObjectInfo object_info = prObjects[ object_index ]; if ( object_info.isInstancer ) { try { if ( object_info.objectToInstanceId >= 0 && prGameObjects[ object_info.objectToInstanceId ] == null ) needs_recook |= createObject( object_info.objectToInstanceId, reload_asset ); if( reload_asset || object_info.haveGeosChanged ) instanceObjects( object_index, progress_bar ); } catch ( HoudiniError error ) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning( error.ToString() ); } } } // Enumerate edit and paint geos. HoudiniGeoControl[] geo_controls = gameObject.GetComponentsInChildren< HoudiniGeoControl >(); prEditPaintGeos.Clear(); foreach ( HoudiniGeoControl geo_control in geo_controls ) { if ( geo_control.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE && geo_control.GetType() == typeof( HoudiniGeoControl ) ) { prEditPaintGeos.Add( geo_control ); } } if ( prEditPaintGeos.Count > 0 && prActiveAttributeManager == null ) prActiveAttributeManager = prEditPaintGeos[ 0 ].prGeoAttributeManager; return needs_recook; }
protected override void buildFullBuildCustomWork( ref HoudiniProgressBar progress_bar, bool is_duplication ) { prCurve.initDefaultParameters(); }
protected override bool buildCreateObjects( bool reload_asset, ref HoudiniProgressBar progress_bar ) { try { prCurve.syncPointsWithParm(); prCurve.createObject( 0, 0 ); HoudiniHost.repaint(); } catch ( HoudiniError ) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. //Debug.LogWarning( error.ToString() ); } return false; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset( HoudiniProgressBar progress_bar ) { return HoudiniHost.createCurve(); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Private private void generateAssetBakeControls() { // Start Time { float value = myAsset.prBakeStartTime; bool changed = HoudiniGUI.floatField( "bake_start_time", "Start Time", ref value, myUndoInfo, ref myUndoInfo.bakeStartTime ); if ( changed ) myAsset.prBakeStartTime = value; } // End Time { float value = myAsset.prBakeEndTime; bool changed = HoudiniGUI.floatField( "bake_end_time", "End Time", ref value, myUndoInfo, ref myUndoInfo.bakeEndTime ); if ( changed ) myAsset.prBakeEndTime = value; } // Samples per second { int value = myAsset.prBakeSamplesPerSecond; bool changed = HoudiniGUI.intField( "bake_samples_per_second", "Samples Per Second", ref value, 1, 120, myUndoInfo, ref myUndoInfo.bakeSamplesPerSecond ); if ( changed ) myAsset.prBakeSamplesPerSecond = value; } if ( GUILayout.Button( "Bake Animation" ) ) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); progress_bar.prUseDelay = false; myAsset.bakeAnimations( myAsset.prBakeStartTime, myAsset.prBakeEndTime, myAsset.prBakeSamplesPerSecond, myAsset.gameObject, progress_bar ); progress_bar.clearProgressBar(); } }
public void instanceObjects( HoudiniProgressBar progress_bar ) { try { destroyChildren(); HAPI_ObjectInfo object_info = prAsset.prObjects[ prObjectId ]; // Get Detail info. HAPI_GeoInfo geo_info = new HAPI_GeoInfo(); HoudiniHost.getGeoInfo( prAsset.prAssetId, prObjectId, 0, out geo_info ); if ( geo_info.partCount == 0 ) return; cacheNumInstances(); HAPI_Transform[] instance_transforms = new HAPI_Transform[ myNumInstances ]; Utility.getArray4Id( prAsset.prAssetId, prObjectId, 0, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances ); // Get scale point attributes. HAPI_AttributeInfo scale_attr_info = new HAPI_AttributeInfo( "scale" ); float[] scale_attr = new float[ 0 ]; Utility.getAttribute( prAsset.prAssetId, prObjectId, 0, 0, "scale", ref scale_attr_info, ref scale_attr, HoudiniHost.getAttributeFloatData ); if ( scale_attr_info.exists && scale_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT ) throw new HoudiniErrorIgnorable( "I only understand scale as point attributes!" ); if ( scale_attr_info.exists && scale_attr.Length != myNumInstances * 3 ) throw new HoudiniError( "Unexpected scale array length found for asset: " + prAsset.prAssetId + "!\n" + "Expected length of: " + myNumInstances * 3 + " but given: " + scale_attr.Length ); HAPI_AttributeInfo script_attr_info = new HAPI_AttributeInfo( "Unity_Script" ); int[] script_attr = new int[ 0 ]; Utility.getAttribute( prAsset.prAssetId, prObjectId, 0, 0, "Unity_Script", ref script_attr_info, ref script_attr, HoudiniHost.getAttributeStringData ); if ( script_attr_info.exists && script_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT ) throw new HoudiniErrorIgnorable( "I only understand Unity_Script as point attributes!" ); if ( script_attr_info.exists && script_attr.Length != myNumInstances ) throw new HoudiniError( "Unexpected Unity_Script array length found for asset: " + prAsset.prAssetId + "!" ); int[] instance_attr = null; int[] name_attr = null; getInstanceAndNameAttrs(out instance_attr,out name_attr ); progress_bar.prTotal = myNumInstances; List <int> exclusion_list = new List<int>(); instanceOverriddenObjects( myNumInstances, exclusion_list ); List < string > unique_instantiated_names = new List< string >(); HoudiniInstancerPersistentData persistent_data = prPersistentData; if( persistent_data.variationChoice.Count != myNumInstances ) { if( myNumInstances > persistent_data.variationChoice.Count ) { int difference = myNumInstances - persistent_data.variationChoice.Count; for( int ii = 0; ii < difference; ii++ ) { persistent_data.variationChoice.Add( -1 ); } } else { int difference = persistent_data.variationChoice.Count - myNumInstances; persistent_data.variationChoice.RemoveRange( persistent_data.variationChoice.Count - difference, difference ); } } bool liveTransformPropagationSetting = false; bool syncAssetTransformSetting = false; bool enableCooking = true; for ( int ii = 0; ii < myNumInstances; ++ii ) { if ( exclusion_list.Contains( ii ) ) continue; GameObject objToInstantiate = null; if ( instance_attr.Length > 0 || name_attr.Length > 0 ) { if( name_attr.Length > 0 ) { string obj_name = HoudiniHost.getString( name_attr[ ii ] ); int object_index = prAsset.findObjectByName( obj_name ); if ( object_index >= 0 ) { objToInstantiate = prAsset.prGameObjects[ object_index ]; } else { objToInstantiate = prAsset.findPartByName( obj_name, true ); } if( objToInstantiate == null ) { objToInstantiate = GameObject.Find( obj_name ); } } else { string instanceObjectPath = HoudiniHost.getString( instance_attr[ ii ] ); string[] pathItems = instanceObjectPath.Split('/'); string instanceObjectName = pathItems[ pathItems.Length - 1 ]; int objectIndex = prAsset.findObjectByName( instanceObjectName ); if ( objectIndex >= 0 ) objToInstantiate = prAsset.prGameObjects[ objectIndex ]; else objToInstantiate = GameObject.Find( instanceObjectName ); } if ( objToInstantiate != null ) { HoudiniAsset hapi_asset = objToInstantiate.GetComponent< HoudiniAsset >(); if ( hapi_asset != null ) { liveTransformPropagationSetting = hapi_asset.prTransformChangeTriggersCooks; syncAssetTransformSetting = hapi_asset.prPushUnityTransformToHoudini; enableCooking = hapi_asset.prEnableCooking; hapi_asset.prTransformChangeTriggersCooks = false; hapi_asset.prPushUnityTransformToHoudini = false; hapi_asset.prEnableCooking = false; } } } else if ( object_info.objectToInstanceId >= 0 ) objToInstantiate = prAsset.prGameObjects[ object_info.objectToInstanceId ]; if ( objToInstantiate != null ) { // Set progress bar information. progress_bar.prCurrentValue = ii; progress_bar.prMessage = "Instancing: " + objToInstantiate.name + " (" + ii + " of " + myNumInstances + ")"; progress_bar.displayProgressBar(); if ( !unique_instantiated_names.Contains( objToInstantiate.name ) ) { unique_instantiated_names.Add( objToInstantiate.name ); } Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[ 0 ] = -instance_transforms[ ii ].position[ 0 ]; pos[ 1 ] = instance_transforms[ ii ].position[ 1 ]; pos[ 2 ] = instance_transforms[ ii ].position[ 2 ]; Quaternion quat = new Quaternion( instance_transforms[ ii ].rotationQuaternion[ 0 ], instance_transforms[ ii ].rotationQuaternion[ 1 ], instance_transforms[ ii ].rotationQuaternion[ 2 ], instance_transforms[ ii ].rotationQuaternion[ 3 ] ); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; Vector3 scale = new Vector3 ( instance_transforms[ ii ].scale[ 0 ], instance_transforms[ ii ].scale[ 1 ], instance_transforms[ ii ].scale[ 2 ] ); Matrix4x4 local_mat = new Matrix4x4(); local_mat.SetTRS( pos, Quaternion.Euler( euler ), scale ); // TODO: Now this *should* be the transform.localToWorldMatrix // but for some reason, after a scene load, we pick up compensating // factors in the local transform that cancel out the transform on the // asset. For now just use the asset's transform as the parent matrix. Matrix4x4 parent_mat = prAsset.transform.localToWorldMatrix; Matrix4x4 global_mat = parent_mat * local_mat; euler = HoudiniAssetUtility.getQuaternion( global_mat ).eulerAngles; pos = HoudiniAssetUtility.getPosition( global_mat ); scale = HoudiniAssetUtility.getScale( global_mat ); //mat.SetTRS( pos, string script_to_attach = ""; if( script_attr_info.exists ) script_to_attach = HoudiniHost.getString( script_attr[ ii ] ); instanceObject( objToInstantiate, pos, euler, ii, scale_attr_info.exists, scale, script_attr_info.exists, script_to_attach ); HoudiniAsset hapi_asset = objToInstantiate.GetComponent< HoudiniAsset >(); if ( hapi_asset != null ) { hapi_asset.prTransformChangeTriggersCooks = liveTransformPropagationSetting; hapi_asset.prPushUnityTransformToHoudini = syncAssetTransformSetting; hapi_asset.prEnableCooking = enableCooking; } } } updateUniqueInstantiatedNames( unique_instantiated_names ); } catch ( HoudiniError error ) { Debug.LogWarning( error.ToString() ); return; } }
protected override bool buildCreateObjects( bool reload_asset, ref HoudiniProgressBar progress_bar ) { return false; }
private void generateAssetInstanceControls() { HoudiniInstancerManager instancer_manager = myAssetOTL.gameObject.GetComponent< HoudiniInstancerManager >(); if( instancer_manager == null ) return; List< HoudiniInstancerPersistentData > instancer_persistent_data = instancer_manager.prInstancerPersistentData; HoudiniInstancer[] instancers = myAssetOTL.gameObject.GetComponentsInChildren< HoudiniInstancer >(); foreach( HoudiniInstancer instancer in instancers ) { HoudiniInstancerPersistentData persistent_data = null; for( int ii = 0; ii < instancer_persistent_data.Count; ii++ ) { HoudiniInstancerPersistentData data = instancer_persistent_data[ ii ]; if( data.instancerName == instancer.name ) { persistent_data = data; break; } } if( persistent_data == null ) { Debug.LogError("Can't find persistent data for instancer: " + instancer.name ); continue; } Undo.RecordObject( persistent_data, "Houdini Instancer Change" ); persistent_data.showInstancerGUI = HoudiniGUI.foldout( persistent_data.instancerName, persistent_data.showInstancerGUI, true ); if ( persistent_data.showInstancerGUI ) { bool changed = false; { Vector3 dummy = new Vector3(); changed |= HoudiniGUI.floatField( "RotationOffset", "Rotation Offset", ref persistent_data.rotationalOffset, null, ref dummy ); changed |= HoudiniGUI.floatField( "ScaleOffset", "Scale Offset", ref persistent_data.scaleOffset, null, ref dummy ); List< string > unique_names = persistent_data.uniqueNames; for ( int ii = 0; ii < unique_names.Count; ii++ ) { string instanced_name = unique_names[ ii ]; int base_index = persistent_data.baseIndex( ii ); for ( int jj = 0; jj < persistent_data.numObjsToInstantiate[ ii ]; jj++ ) { Object obj = (Object) persistent_data.objsToInstantiate[ base_index + jj ]; GUILayout.BeginHorizontal(); string label = ""; if ( jj == 0 ) label = instanced_name; changed |= HoudiniGUI.objectField( "object_to_instantiate", label, ref obj, typeof( GameObject ) ); if ( changed ) { persistent_data.objsToInstantiate[ base_index + jj ] = (GameObject) obj; } if ( GUILayout.Button( "+" ) ) { persistent_data.objsToInstantiate.Insert ( base_index + jj, null ); persistent_data.numObjsToInstantiate[ ii ]++; persistent_data.recalculateVariations[ ii ] = true; changed = true; break; } if ( GUILayout.Button( "-" ) ) { if ( persistent_data.numObjsToInstantiate[ ii ] == 1 ) { persistent_data.objsToInstantiate[ base_index ] = null; } else { persistent_data.objsToInstantiate.RemoveAt( base_index + jj ); persistent_data.numObjsToInstantiate[ ii ]--; } persistent_data.recalculateVariations[ ii ] = true; changed = true; break; } GUILayout.EndHorizontal(); } } if ( GUILayout.Button( "Recalculate Variations" ) ) { for( int ii = 0; ii < unique_names.Count; ii++ ) { persistent_data.recalculateVariations[ ii ] = true; } changed = true; } } if ( instancer.hasOverriddenInstances() ) { if ( GUILayout.Button( "UnPin All Instances" ) ) { instancer.unPinAllInstances(); changed = true; } } if ( changed ) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); instancer.instanceObjects( progress_bar ); progress_bar.clearProgressBar(); for( int ii = 0; ii < persistent_data.recalculateVariations.Count; ii++ ) { persistent_data.recalculateVariations[ ii ] = false; } } } EditorGUILayout.Separator(); } }
protected override void buildFullBuildCustomWork( ref HoudiniProgressBar progress_bar, bool is_duplication ) { // Initialize (or leave alone!) the pain structs. if ( prEditPaintGeos == null ) { prEditPaintGeos = new List< HoudiniGeoControl >(); prActiveAttributeManager = null; } else if ( is_duplication ) { prActiveAttributeManager = null; } progress_bar.prMessage = "Loading handles..."; // Get exposed handle information. prHandleInfos = new HAPI_HandleInfo[ prHandleCount ]; HoudiniAssetUtility.getArray1Id( prAssetId, HoudiniHost.getHandleInfo, prHandleInfos, prHandleCount ); // Get handles. prHandleBindingInfos = new List< HAPI_HandleBindingInfo[] >( prHandleCount ); for ( int handle_index = 0; handle_index < prHandleCount; ++handle_index ) { progress_bar.incrementProgressBar(); HAPI_HandleInfo handle_info = prHandleInfos[ handle_index ]; HAPI_HandleBindingInfo[] binding_infos = new HAPI_HandleBindingInfo[ handle_info.bindingsCount ]; HoudiniAssetUtility.getArray2Id( prAssetId, handle_index, HoudiniHost.getHandleBindingInfo, binding_infos, handle_info.bindingsCount ); prHandleBindingInfos.Add( binding_infos ); } }
public void bakeAnimations( float start_time, float end_time, int samples_per_second, GameObject parent_object, HoudiniProgressBar progress_bar ) { #if UNITY_EDITOR try { //This build is needed in case the user changed a geometry input to the asset. //The geometry to be instanced needs to be re-brought in. buildClientSide(); int num_objects = prObjects.Length; for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); obj_control.beginBakeAnimation(); } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); instancer.beginBakeAnimation(); } } } int num_samples = Mathf.CeilToInt(samples_per_second*( end_time - start_time )); float total_sim_time = ( end_time - start_time ); float delta_time = total_sim_time / (float) num_samples; progress_bar.prTotal = num_samples; progress_bar.prCurrentValue = 0; for ( float curr_time = start_time; curr_time <= end_time; curr_time += delta_time ) { HoudiniHost.setTime( curr_time ); HoudiniHost.cookAsset( prAssetId, prSplitGeosByGroup, prImportTemplatedGeos ); HAPI_State state = HAPI_State.HAPI_STATE_STARTING_LOAD; while ( (int) state > (int) HAPI_State.HAPI_STATE_MAX_READY_STATE ) state = (HAPI_State) HoudiniHost.getStatus( HAPI_StatusType.HAPI_STATUS_COOK_STATE ); if ( state == HAPI_State.HAPI_STATE_READY_WITH_COOK_ERRORS ) { state = HAPI_State.HAPI_STATE_READY; Debug.LogWarning( "Cook Errors at time: " + curr_time + "\n" + HoudiniHost.getCookErrorMessage() ); } else if ( state == HAPI_State.HAPI_STATE_READY_WITH_FATAL_ERRORS ) { state = HAPI_State.HAPI_STATE_READY; HoudiniHost.throwCookError(); } HAPI_Transform[] object_transforms = new HAPI_Transform[ prObjectCount ]; HoudiniAssetUtility.getArray2Id( prAssetId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getObjectTransforms, object_transforms, prObjectCount ); for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); obj_control.bakeAnimation( curr_time, parent_object, object_transforms[ ii ] ); } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); instancer.bakeAnimation( curr_time, parent_object ); } } } // Set progress bar information. progress_bar.prCurrentValue++; progress_bar.prMessage = "Baking: " + progress_bar.prCurrentValue + " of " + num_samples; progress_bar.displayProgressBar(); } bool found_anim = false; for ( int ii = 0; ii < num_objects; ii++ ) { GameObject game_object = prGameObjects[ ii ]; HAPI_ObjectInfo obj_info = prObjects[ ii ]; if ( game_object != null ) { if ( !obj_info.isInstancer ) { HoudiniObjectControl obj_control = game_object.GetComponent< HoudiniObjectControl >(); if ( obj_control.endBakeAnimation() ) found_anim = true; } else { HoudiniInstancer instancer = game_object.GetComponent< HoudiniInstancer >(); if ( instancer.endBakeAnimation( parent_object ) ) found_anim = true; } } } if ( !found_anim ) { EditorUtility.DisplayDialog( "Bake Error", "No animation was found to bake", "OK" ); } } catch ( HoudiniError error ) { Debug.LogWarning( error.ToString() ); } #endif // UNITY_EDITOR }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Private Methods private void instanceObjects( int object_id, HoudiniProgressBar progress_bar ) { HAPI_ObjectInfo object_info = prObjects[ object_id ]; HoudiniInstancer instancer = null; Transform old_instancer_transform = transform.Find( object_info.name ); if ( old_instancer_transform && old_instancer_transform.gameObject.GetComponent< HoudiniInstancer >() ) { instancer = old_instancer_transform.gameObject.GetComponent< HoudiniInstancer >(); } else { if( gameObject.GetComponent< HoudiniInstancerManager >() == null ) gameObject.AddComponent< HoudiniInstancerManager >(); GameObject main_object = new GameObject( object_info.name ); main_object.transform.parent = transform; main_object.AddComponent< HoudiniInstancer >(); prGameObjects[ object_id ] = main_object; instancer = main_object.GetComponent< HoudiniInstancer >(); HoudiniInstancerManager instancer_manager = gameObject.GetComponent< HoudiniInstancerManager >(); instancer_manager.updateInstancerData( instancer ); } instancer.prAsset = this; instancer.prObjectId = object_id; instancer.instanceObjects( progress_bar ); }
// Inherited classes should override this for work they need done during the full build step only. (Optional) protected virtual void buildFullBuildCustomWork( ref HoudiniProgressBar progress_bar, bool is_duplication ) {}
public void bakeAsset() { #if UNITY_EDITOR && ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) // Get/Create directory for the asset being baked. string baked_asset_path = HoudiniConstants.HAPI_BAKED_ASSETS_PATH + "/" + prAssetName; DirectoryInfo baked_asset_dir = new DirectoryInfo( baked_asset_path ); int i = 0; while ( baked_asset_dir.Exists ) { i++; if ( i > 1 ) baked_asset_path = baked_asset_path.Substring( 0, baked_asset_path.Length - 1 ) + i; else baked_asset_path = baked_asset_path + "_" + i; baked_asset_dir = new DirectoryInfo( baked_asset_path ); } baked_asset_dir.Create(); string rel_baked_asset_path = baked_asset_path.Replace( Application.dataPath, "Assets" ); // Get/Create directory for textures of the asset being baked. string textures_path = baked_asset_path + "/Textures"; string rel_textures_path = rel_baked_asset_path + "/Textures"; DirectoryInfo textures_dir = new DirectoryInfo( textures_path ); if ( !textures_dir.Exists ) textures_dir.Create(); // Get/Create directory for meshes of the asset being baked. string meshes_path = baked_asset_path + "/Meshes"; string rel_meshes_path = rel_baked_asset_path + "/Meshes"; DirectoryInfo meshes_dir = new DirectoryInfo( meshes_path ); if ( !meshes_dir.Exists ) meshes_dir.Create(); // Get/Create directory for materials of the asset being baked. string materials_path = baked_asset_path + "/Materials"; string rel_materials_path = rel_baked_asset_path + "/Materials"; DirectoryInfo materials_dir = new DirectoryInfo( materials_path ); if ( !materials_dir.Exists ) materials_dir.Create(); // Get/Create directory for shaders of the asset being baked. string shaders_path = baked_asset_path + "/Shaders"; string rel_shaders_path = rel_baked_asset_path + "/Shaders"; DirectoryInfo shaders_dir = new DirectoryInfo( shaders_path ); if ( !shaders_dir.Exists ) shaders_dir.Create(); // Create new game object that is a copy of this asset except with all the HAPI components // removed. This new game object will be used to create a prefab. GameObject new_object = Instantiate( gameObject ) as GameObject; // Bake all meshes and materials created by HAPI_PartControls. foreach ( HoudiniPartControl part_control in new_object.GetComponentsInChildren< HoudiniPartControl >() ) { if ( part_control.prObjectControl.GetComponent< HoudiniInstance >() ) continue; // We don't want to bake any intermediate meshes. if ( part_control.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE ) continue; // Bake meshes. MeshFilter mesh_filter = part_control.GetComponent< MeshFilter >(); if ( mesh_filter ) { Mesh mesh = mesh_filter.sharedMesh; string mesh_name = part_control.prGeoControl.prObjectControl.name + "_" + part_control.prGeoControl.name + "_" + part_control.name + "_" + "mesh"; string mesh_path = rel_meshes_path + "/" + mesh_name + ".asset"; Mesh mesh_copy = Mesh.Instantiate( mesh ) as Mesh; mesh_copy.name = mesh_name; mesh_filter.sharedMesh = mesh_copy; // Assigned saved mesh to mesh collider also. MeshCollider mesh_collider = part_control.GetComponent< MeshCollider >(); if ( mesh_collider ) { mesh_collider.sharedMesh = mesh_copy; mesh_collider.enabled = false; mesh_collider.enabled = true; } AssetDatabase.CreateAsset( mesh_filter.sharedMesh, mesh_path ); AssetDatabase.SaveAssets(); } // Bake materials. MeshRenderer mesh_renderer = part_control.GetComponent< MeshRenderer >(); if ( mesh_renderer ) { Material material = mesh_renderer.sharedMaterial; // Only bake material if using internal material. if ( !AssetDatabase.Contains( material ) ) { Material material_copy = Material.Instantiate( material ) as Material; mesh_renderer.sharedMaterial = material_copy; // Bake shader needed by material. if ( material_copy.shader ) { Shader shader_copy = Shader.Instantiate( material_copy.shader ) as Shader; string shader_name = shader_copy.name.Substring( Mathf.Max( 0, shader_copy.name.LastIndexOf( '/' ) + 1 ) ); string shader_path = rel_shaders_path + "/" + shader_name + ".asset"; AssetDatabase.CreateAsset( shader_copy, shader_path ); AssetDatabase.SaveAssets(); material_copy.shader = shader_copy; } // Bake texture needed by material. if ( material_copy.mainTexture ) { string texture_name = Path.GetFileName( AssetDatabase.GetAssetPath( material_copy.mainTexture ) ); if ( texture_name == "" ) { // This is for when we use in-memory textures. We need to actually // bake them out to file now. Texture2D orig_texture = material_copy.mainTexture as Texture2D; byte[] orig_texture_png = orig_texture.EncodeToPNG(); string name = part_control.prObjectName + "_" + part_control.prGeoName + "_" + part_control.prPartName + ".png"; string texture_path = rel_textures_path + "/" + name; File.WriteAllBytes( texture_path, orig_texture_png ); AssetDatabase.ImportAsset( texture_path, ImportAssetOptions.Default ); Texture2D texture = AssetDatabase.LoadAssetAtPath( texture_path, typeof(Texture2D) ) as Texture2D;; material_copy.mainTexture = texture; } else { string texture_path = rel_textures_path + "/" + texture_name; Texture2D texture = AssetDatabase.LoadAssetAtPath( texture_path, typeof(Texture2D) ) as Texture2D; if ( !texture ) { AssetDatabase.CopyAsset( AssetDatabase.GetAssetPath( material_copy.mainTexture ), texture_path ); AssetDatabase.ImportAsset( texture_path, ImportAssetOptions.Default ); texture = AssetDatabase.LoadAssetAtPath( texture_path, typeof(Texture2D) ) as Texture2D; } material_copy.mainTexture = texture; } } string material_name = part_control.prGeoControl.prObjectControl.name + "_" + part_control.prGeoControl.name + "_" + part_control.name + "_" + "mat"; string mat_path = rel_materials_path + "/" + material_name + ".asset"; material_copy.name = material_name; if ( !AssetDatabase.Contains( material_copy ) ) { AssetDatabase.CreateAsset( material_copy, mat_path ); AssetDatabase.SaveAssets(); } else { Debug.LogWarning( "Note: " + material_copy.name + " is an external Unity material " + "and will not be saved in the Baked Assets folder.\n" + "The prefab will depend on this material existing in:\n" + AssetDatabase.GetAssetPath( material_copy ) ); } } } } // Re-instance to have the instances use the copied (and baked) meshes from the // now-baked instanced objects. foreach ( HoudiniInstancer instancer in new_object.GetComponentsInChildren< HoudiniInstancer >() ) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); instancer.instanceObjects( progress_bar ); } // Delete all HAPI components from prefab. (Order here matters because of inter-dependencies!) // Note: If you move or edit this list please update the wiki reminder about this list // on the Runtime wiki page. removeComponentsFromChildren< HoudiniCurve >( new_object ); removeComponentsFromChildren< HoudiniMeshToPrefab >( new_object ); removeComponentsFromChildren< HoudiniInstancerManager >( new_object ); removeComponentsFromChildren< HoudiniInstancer >( new_object ); removeComponentsFromChildren< HoudiniInstance >( new_object ); removeComponentsFromChildren< HoudiniParms >( new_object ); removeComponentsFromChildren< HoudiniControl >( new_object ); // Create prefab. string prefab_path = rel_baked_asset_path + "/" + gameObject.name + ".prefab"; PrefabUtility.CreatePrefab( prefab_path, new_object ); AssetDatabase.SaveAssets(); // Destroy object we created because we don't need it anymore. DestroyImmediate( new_object ); #endif // UNITY_EDITOR && ( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) }
protected override void buildFullBuildCustomWork( ref HoudiniProgressBar progress_bar, bool is_duplication ) { cloneMesh(); if ( myGeoAttributeManager == null ) { MeshRenderer mesh_renderer = getOrCreateComponent< MeshRenderer >(); MeshCollider mesh_collider = getOrCreateComponent< MeshCollider >(); myGeoAttributeManager = ScriptableObject.CreateInstance< HoudiniGeoAttributeManager >(); myGeoAttributeManager.init( prEditableMesh, mesh_renderer, mesh_collider, transform ); } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods // Build Custom Work Methods ----------------------------------------------------------------------------------- // Inherited classes should override this with their specific call to the HAPI_Host asset create method. // For example: OTLs need to call HAPI_Host.loadOTL( path ), curves need to call HAPI_Host.createCurve(). protected abstract int buildCreateAsset( HoudiniProgressBar progress_bar );
private void generateAssetInstanceControls() { HoudiniInstancerManager instancer_manager = myAssetOTL.gameObject.GetComponent <HoudiniInstancerManager>(); if (instancer_manager == null) { return; } List <HoudiniInstancerPersistentData> instancer_persistent_data = instancer_manager.prInstancerPersistentData; HoudiniInstancer[] instancers = myAssetOTL.gameObject.GetComponentsInChildren <HoudiniInstancer>(); foreach (HoudiniInstancer instancer in instancers) { HoudiniInstancerPersistentData persistent_data = null; for (int ii = 0; ii < instancer_persistent_data.Count; ii++) { HoudiniInstancerPersistentData data = instancer_persistent_data[ii]; if (data.instancerName == instancer.name) { persistent_data = data; break; } } if (persistent_data == null) { Debug.LogError("Can't find persistent data for instancer: " + instancer.name); continue; } Undo.RecordObject(persistent_data, "Houdini Instancer Change"); persistent_data.showInstancerGUI = HoudiniGUI.foldout( persistent_data.instancerName, persistent_data.showInstancerGUI, true); if (persistent_data.showInstancerGUI) { bool changed = false; { Vector3 dummy = new Vector3(); changed |= HoudiniGUI.floatField( "RotationOffset", "Rotation Offset", ref persistent_data.rotationalOffset, null, ref dummy); changed |= HoudiniGUI.floatField( "ScaleOffset", "Scale Offset", ref persistent_data.scaleOffset, null, ref dummy); List <string> unique_names = persistent_data.uniqueNames; for (int ii = 0; ii < unique_names.Count; ii++) { string instanced_name = unique_names[ii]; int base_index = persistent_data.baseIndex(ii); for (int jj = 0; jj < persistent_data.numObjsToInstantiate[ii]; jj++) { Object obj = (Object)persistent_data.objsToInstantiate[base_index + jj]; GUILayout.BeginHorizontal(); string label = ""; if (jj == 0) { label = instanced_name; } changed |= HoudiniGUI.objectField( "object_to_instantiate", label, ref obj, typeof(GameObject)); if (changed) { persistent_data.objsToInstantiate[base_index + jj] = (GameObject)obj; } if (GUILayout.Button("+")) { persistent_data.objsToInstantiate.Insert (base_index + jj, null); persistent_data.numObjsToInstantiate[ii]++; persistent_data.recalculateVariations[ii] = true; changed = true; break; } if (GUILayout.Button("-")) { if (persistent_data.numObjsToInstantiate[ii] == 1) { persistent_data.objsToInstantiate[base_index] = null; } else { persistent_data.objsToInstantiate.RemoveAt(base_index + jj); persistent_data.numObjsToInstantiate[ii]--; } persistent_data.recalculateVariations[ii] = true; changed = true; break; } GUILayout.EndHorizontal(); } } if (GUILayout.Button("Recalculate Variations")) { for (int ii = 0; ii < unique_names.Count; ii++) { persistent_data.recalculateVariations[ii] = true; } changed = true; } } if (instancer.hasOverriddenInstances()) { if (GUILayout.Button("UnPin All Instances")) { instancer.unPinAllInstances(); changed = true; } } if (changed) { HoudiniProgressBar progress_bar = new HoudiniProgressBar(); instancer.instanceObjects(progress_bar); progress_bar.clearProgressBar(); for (int ii = 0; ii < persistent_data.recalculateVariations.Count; ii++) { persistent_data.recalculateVariations[ii] = false; } } } EditorGUILayout.Separator(); } }
// Inherited classes should override this with however they wish to load objects in the prObjects array. // Returns whether or not the objects require a recook. protected abstract bool buildCreateObjects( bool reload_asset, ref HoudiniProgressBar progress_bar );
protected override bool buildCreateObjects(bool reload_asset, ref HoudiniProgressBar progress_bar) { bool needs_recook = false; for (int object_index = 0; object_index < prObjectCount; ++object_index) { progress_bar.incrementProgressBar(); try { if (!prObjects[object_index].isInstancer && (reload_asset || prObjects[object_index].hasTransformChanged || prObjects[object_index].haveGeosChanged)) { needs_recook |= createObject(object_index, reload_asset); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } // Processing instancers. for (int object_index = 0; object_index < prObjectCount; ++object_index) { HAPI_ObjectInfo object_info = prObjects[object_index]; if (object_info.isInstancer) { try { if (object_info.objectToInstanceId >= 0 && prGameObjects[object_info.objectToInstanceId] == null) { needs_recook |= createObject(object_info.objectToInstanceId, reload_asset); } if (reload_asset || object_info.haveGeosChanged) { instanceObjects(object_index, progress_bar); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } } // Enumerate edit and paint geos. HoudiniGeoControl[] geo_controls = gameObject.GetComponentsInChildren <HoudiniGeoControl>(); prEditPaintGeos.Clear(); foreach (HoudiniGeoControl geo_control in geo_controls) { if (geo_control.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE && geo_control.GetType() == typeof(HoudiniGeoControl)) { prEditPaintGeos.Add(geo_control); } } if (prEditPaintGeos.Count > 0 && prActiveAttributeManager == null) { prActiveAttributeManager = prEditPaintGeos[0].prGeoAttributeManager; } return(needs_recook); }
public virtual bool build( bool reload_asset, bool unload_asset_first, bool serialization_recovery_only, bool force_reconnect, bool is_duplication, bool cook_downstream_assets, bool use_delay_for_progress_bar ) { // We can only build or do anything if we can link to our libraries. #if !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) return false; #pragma warning disable 0162 #endif // !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) if ( !HoudiniHost.isInstallationOk() ) return false; if ( !prEnableCooking ) return false; if ( isPrefabInstance() ) processParentPrefab(); // Run post-cook hook. foreach ( var asset_hook in prAssetHooks ) asset_hook.preCook( this ); HoudiniProgressBar progress_bar = new HoudiniProgressBar(); progress_bar.prUseDelay = use_delay_for_progress_bar; progress_bar.prAsset = this; try { progress_bar.prStartTime = System.DateTime.Now; bool is_first_time_build = false; // restore asset id and asset validation id from the backup whenever // reverting a prefab instance bool is_reverting_prefab_instance = isRevertingPrefabInstance(); if ( is_reverting_prefab_instance ) { prAssetId = prBackupAssetId; prAssetValidationId = prBackupAssetValidationId; } if ( reload_asset ) { if ( unload_asset_first ) { // There's no reason to abort the whole rebuild process because we can't unload // the asset first as that would leave the user with no options other than // to delete this HAPI asset and create a new one for this OTL. try { HoudiniHost.destroyAsset( prAssetId ); } catch ( HoudiniError ) {} // Once an asset is unloaded its id will is obviously no longer valid, so reset it here. prAssetId = -1; // Need to reset the parms as well. prParms.reset(); } try { int asset_id = 0; if ( prAssetId < 0 ) is_first_time_build = true; if ( unload_asset_first ) asset_id = buildCreateAsset( progress_bar ); else asset_id = prAssetId; // We need to update the prAssetId in case the cook is aborted/fails // and we need to clean up (unload the asset) in the catch. prAssetId = asset_id; prAssetInfo = HoudiniHost.getAssetInfo( asset_id ); HAPI_NodeInfo node_info = HoudiniHost.getNodeInfo( prAssetInfo.nodeId ); if ( reload_asset ) Debug.Log( "Houdini Engine: Asset Loaded - ID: " + prAssetInfo.id + "\n" + " Full Name: " + prAssetInfo.fullOpName + "\n" + " Version: " + prAssetInfo.version + "\n" + " Unique Node Id: " + node_info.uniqueHoudiniNodeId + "\n" + " Internal Node Path: " + node_info.internalNodePath + "\n" + " Asset Library File: " + prAssetInfo.filePath + "\n" ); } catch ( HoudiniError error ) { Debug.LogError( "Asset not loaded: " + error.ToString() ); // Nothing to build since the load failed. // Try to unload the asset so it doesn't dangle. if ( is_first_time_build ) { try { HoudiniHost.destroyAsset( prAssetId ); } catch ( HoudiniError ) {} } // Clean up. reset(); // If in play mode, disable live cooks. #if UNITY_EDITOR if ( EditorApplication.isPlaying ) #endif // UNITY_EDITOR { prPlaymodePerFrameCooking = false; } return false; // false for failed :( } } prAssetInfo = HoudiniHost.getAssetInfo( prAssetId ); // For convenience we copy some asset info properties locally (since they are constant anyway). // More imporantly, structs are not serialized and therefore putting them into their own // variables is required in order to maintain state between serialization cycles. prAssetId = prAssetInfo.id; prBackupAssetId = prAssetId; prAssetValidationId = prAssetInfo.validationId; prBackupAssetValidationId = prAssetValidationId; prNodeId = prAssetInfo.nodeId; prObjectNodeId = prAssetInfo.objectNodeId; prObjectCount = prAssetInfo.objectCount; prHandleCount = prAssetInfo.handleCount; prAssetName = prAssetInfo.name; prAssetOpName = prAssetInfo.fullOpName; prAssetHelp = prAssetInfo.helpText; prHAPIAssetType = prAssetInfo.type; prTransformInputCount = prAssetInfo.transformInputCount; prGeoInputCount = prAssetInfo.geoInputCount; #if UNITY_EDITOR if ( isPrefab() ) { string prefab_path = AssetDatabase.GetAssetPath( GetInstanceID() ); HoudiniHost.myCleanUpPrefabAssets[ prefab_path ] = prAssetId; } #endif // UNITY_EDITOR // Try to load presets. if ( ( reload_asset && ( unload_asset_first || is_reverting_prefab_instance ) ) #if UNITY_EDITOR // Only load presets during serialization recovery if we really need to. // The only such case is when we made changes DURING playmode and Unity // restores the parameter values from before going into playmode. // We only save presets while NOT in playmode which means to restore // the Houdini state to before playmode state we need to loadPreset() // with the last saved preset. In all other cases, like going INTO // playmode, we should avoid this step because loadPreset() WILL // cause a cook regardless if the parameters have changed or not which // is terrible for large assets. || ( serialization_recovery_only && !EditorApplication.isPlayingOrWillChangePlaymode && !prParms.prValuesEqualToHoudini ) #endif // UNITY_EDITOR ) { loadPreset(); progress_bar.statusCheckLoop(); // Transform may not have been saved as part of the presets so we have to rely // on the serialized value. if ( myLastLocalToWorld != Matrix4x4.zero && !isPrefab() ) { // If this is a prefab instance being reverted we don't want to use the // serialized value so don't change transform. if ( !is_reverting_prefab_instance ) { Matrix4x4 world_to_local = Matrix4x4.identity; if ( transform.parent ) world_to_local = transform.parent.worldToLocalMatrix; Matrix4x4 local = myLastLocalToWorld * world_to_local; transform.localPosition = HoudiniAssetUtility.getPosition( local ); transform.localRotation = HoudiniAssetUtility.getQuaternion( local ); Vector3 scale = HoudiniAssetUtility.getScale( local ); if ( !( Mathf.Approximately( 0.0f, scale.x ) && Mathf.Approximately( 0.0f, scale.y ) && Mathf.Approximately( 0.0f, scale.z ) ) ) { transform.localScale = HoudiniAssetUtility.getScale( local ); } } if ( prPushUnityTransformToHoudini ) { pushAssetTransformToHoudini(); } } } if ( reload_asset ) { progress_bar.prCurrentValue = 0; progress_bar.prTotal = prObjectCount + prHandleCount; progress_bar.displayProgressBar(); myProgressBarJustUsed = true; // Add input fields. if ( is_first_time_build || !force_reconnect ) initAssetConnections(); // Clean up. destroyChildren( transform ); prGameObjects = new GameObject[ prObjectCount ]; } if ( reload_asset || serialization_recovery_only ) { // Need to re-acquire all the params for all the child controls that have parms exposed. prParms.getParameterValues(); foreach ( HoudiniParms parms in GetComponentsInChildren< HoudiniParms >() ) parms.getParameterValues(); // Custom work during a full build (custom to each subclass). buildFullBuildCustomWork( ref progress_bar, is_duplication ); } if ( !reload_asset && !serialization_recovery_only ) { progress_bar.displayProgressBar(); updateParameters( progress_bar ); } // Create local object info caches (transforms need to be stored in a parallel array). if ( prObjects == null || prObjects.Length != prObjectCount ) prObjects = new HAPI_ObjectInfo[ prObjectCount ]; if ( prObjectTransforms == null || prObjectTransforms.Length != prObjectCount ) prObjectTransforms = new HAPI_Transform[ prObjectCount ]; // Refresh object info arrays as they are lost after serialization. HoudiniAssetUtility.getArray1Id( prAssetId, HoudiniHost.getObjects, prObjects, prObjectCount ); HoudiniAssetUtility.getArray2Id( prAssetId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getObjectTransforms, prObjectTransforms, prObjectCount ); bool objects_need_recook = false; if ( !serialization_recovery_only ) { // Set asset's transform. if ( prPushUnityTransformToHoudini ) HoudiniAssetUtility.getHoudiniTransformAndApply( prAssetId, prAssetName, transform ); progress_bar.prMessage = "Loading and composing objects..."; // Destroy/copy non-copiable but still serialized member data. if ( is_duplication ) { myAssetOTLUndoInfo = null; if ( myGeoAttributeManagerMap != null ) { myGeoAttributeManagerMap = myGeoAttributeManagerMap.copy(); myGeoAttributeManagerMap.name = prAssetName + "_GeoAttributeManagerMap"; } if ( myPresetsMap != null ) { myPresetsMap = myPresetsMap.clone(); myPresetsMap.name = prAssetName + "_PresetMap"; } } // Custom way to load objects (custom to each subclass). objects_need_recook = buildCreateObjects( reload_asset, ref progress_bar ); // Process dependent assets. if ( cook_downstream_assets ) processDependentAssets( serialization_recovery_only, force_reconnect, is_duplication, use_delay_for_progress_bar ); } // This tells Unity that values have been overridden for this prefab instance // (eg. asset id, validation id, node id, etc). #if UNITY_EDITOR if ( isPrefabInstance() ) PrefabUtility.RecordPrefabInstancePropertyModifications( this ); #endif // UNITY_EDITOR // A bit of a hack (but not terrible). If we have presets for other child controls // they set their presets by now so we need to rebuild with the new presets. if ( objects_need_recook ) { build( false, // reload_asset false, // unload_asset_first false, // serializatin_recovery_only false, // force_reconnect false, // is_duplication false, // cook_downstream_assets true // use_delay_for_progress_bar ); } } catch ( HoudiniErrorIgnorable ) {} catch ( HoudiniErrorProgressCancelled error ) { // If in play mode, disable live cooks. #if UNITY_EDITOR if ( EditorApplication.isPlaying ) #endif // UNITY_EDITOR { prPlaymodePerFrameCooking = false; } Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } catch ( HoudiniError error ) { Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } catch ( System.Exception error ) { Debug.LogError( error.ToString() + "\nSource: " + error.Source ); } finally { progress_bar.clearProgressBar(); myProgressBarJustUsed = false; // Run post-cook hook. foreach ( var asset_hook in prAssetHooks ) asset_hook.postCook( this ); } // We can only build or do anything if we can link to our libraries. #if !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) #pragma warning restore 0162 #endif // !( UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || ( UNITY_METRO && UNITY_EDITOR ) ) return true; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset(HoudiniProgressBar progress_bar) { return(HoudiniHost.createCurve()); }
public void instanceObjects(HoudiniProgressBar progress_bar) { try { destroyChildren(); HAPI_ObjectInfo object_info = HoudiniHost.getObjectInfo(prObjectId); // Get Detail info. HAPI_GeoInfo geo_info = HoudiniHost.getDisplayGeoInfo(prObjectId); if (geo_info.partCount == 0) { return; } cacheNumInstances(); HAPI_Transform[] instance_transforms = new HAPI_Transform[myNumInstances]; Utility.getArray2Id( geo_info.nodeId, HAPI_RSTOrder.HAPI_SRT, HoudiniHost.getInstanceTransforms, instance_transforms, myNumInstances); // Get scale point attributes. HAPI_AttributeInfo scale_attr_info = new HAPI_AttributeInfo("scale"); float[] scale_attr = new float[0]; Utility.getAttribute( geo_info.nodeId, 0, "scale", ref scale_attr_info, ref scale_attr, HoudiniHost.getAttributeFloatData); if (scale_attr_info.exists && scale_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT) { throw new HoudiniErrorIgnorable("I only understand scale as point attributes!"); } if (scale_attr_info.exists && scale_attr.Length != myNumInstances * 3) { throw new HoudiniError( "Unexpected scale array length found for asset: " + prAsset.prAssetId + "!\n" + "Expected length of: " + myNumInstances * 3 + " but given: " + scale_attr.Length); } HAPI_AttributeInfo script_attr_info = new HAPI_AttributeInfo("Unity_Script"); int[] script_attr = new int[0]; Utility.getAttribute( geo_info.nodeId, 0, "Unity_Script", ref script_attr_info, ref script_attr, HoudiniHost.getAttributeStringData); if (script_attr_info.exists && script_attr_info.owner != HAPI_AttributeOwner.HAPI_ATTROWNER_POINT) { throw new HoudiniErrorIgnorable("I only understand Unity_Script as point attributes!"); } if (script_attr_info.exists && script_attr.Length != myNumInstances) { throw new HoudiniError("Unexpected Unity_Script array length found for asset: " + prAsset.prAssetId + "!"); } int[] instance_attr = null; int[] name_attr = null; getInstanceAndNameAttrs(out instance_attr, out name_attr); progress_bar.prTotal = myNumInstances; List <int> exclusion_list = new List <int>(); instanceOverriddenObjects(myNumInstances, exclusion_list); List <string> unique_instantiated_names = new List <string>(); HoudiniInstancerPersistentData persistent_data = prPersistentData; if (persistent_data.variationChoice.Count != myNumInstances) { if (myNumInstances > persistent_data.variationChoice.Count) { int difference = myNumInstances - persistent_data.variationChoice.Count; for (int ii = 0; ii < difference; ii++) { persistent_data.variationChoice.Add(-1); } } else { int difference = persistent_data.variationChoice.Count - myNumInstances; persistent_data.variationChoice.RemoveRange( persistent_data.variationChoice.Count - difference, difference); } } bool liveTransformPropagationSetting = false; bool syncAssetTransformSetting = false; bool enableCooking = true; for (int i = 0; i < myNumInstances; ++i) { if (exclusion_list.Contains(i)) { continue; } GameObject obj_to_instance = null; if (instance_attr.Length > 0 || name_attr.Length > 0) { if (name_attr.Length > 0) { string obj_name = HoudiniHost.getString(name_attr[i]); int object_index = prAsset.findObjectByName(obj_name); if (object_index >= 0) { obj_to_instance = prAsset.prGameObjects[object_index]; } else { obj_to_instance = prAsset.findPartByName(obj_name, true); } if (obj_to_instance == null) { obj_to_instance = GameObject.Find(obj_name); } } else { string instanceObjectPath = HoudiniHost.getString(instance_attr[i]); string [] pathItems = instanceObjectPath.Split('/'); string instanceObjectName = pathItems[pathItems.Length - 1]; int objectIndex = prAsset.findObjectByName(instanceObjectName); if (objectIndex >= 0) { obj_to_instance = prAsset.prGameObjects[objectIndex]; } else { obj_to_instance = GameObject.Find(instanceObjectName); } } if (obj_to_instance != null) { HoudiniAsset hapi_asset = obj_to_instance.GetComponent <HoudiniAsset>(); if (hapi_asset != null) { liveTransformPropagationSetting = hapi_asset.prTransformChangeTriggersCooks; syncAssetTransformSetting = hapi_asset.prPushUnityTransformToHoudini; enableCooking = hapi_asset.prEnableCooking; hapi_asset.prTransformChangeTriggersCooks = false; hapi_asset.prPushUnityTransformToHoudini = false; hapi_asset.prEnableCooking = false; } } } else if (object_info.objectToInstanceId >= 0) { int object_to_instance_idx = prAsset.findObjectByNodeId(object_info.objectToInstanceId); if (object_to_instance_idx >= 0) { obj_to_instance = prAsset.prGameObjects[object_to_instance_idx]; } } if (obj_to_instance != null) { // Set progress bar information. progress_bar.prCurrentValue = i; progress_bar.prMessage = "Instancing: " + obj_to_instance.name + " (" + i + " of " + myNumInstances + ")"; progress_bar.displayProgressBar(); if (!unique_instantiated_names.Contains(obj_to_instance.name)) { unique_instantiated_names.Add(obj_to_instance.name); } Vector3 pos = new Vector3(); // Apply object transforms. // // Axis and Rotation conversions: // Note that Houdini's X axis points in the opposite direction that Unity's does. Also, Houdini's // rotation is right handed, whereas Unity is left handed. To account for this, we need to invert // the x coordinate of the translation, and do the same for the rotations (except for the x rotation, // which doesn't need to be flipped because the change in handedness AND direction of the left x axis // causes a double negative - yeah, I know). pos[0] = -instance_transforms[i].position[0]; pos[1] = instance_transforms[i].position[1]; pos[2] = instance_transforms[i].position[2]; Quaternion quat = new Quaternion(instance_transforms[i].rotationQuaternion[0], instance_transforms[i].rotationQuaternion[1], instance_transforms[i].rotationQuaternion[2], instance_transforms[i].rotationQuaternion[3]); Vector3 euler = quat.eulerAngles; euler.y = -euler.y; euler.z = -euler.z; Vector3 scale = new Vector3(instance_transforms[i].scale[0], instance_transforms[i].scale[1], instance_transforms[i].scale[2]); Matrix4x4 local_mat = new Matrix4x4(); local_mat.SetTRS(pos, Quaternion.Euler(euler), scale); // TODO: Now this *should* be the transform.localToWorldMatrix // but for some reason, after a scene load, we pick up compensating // factors in the local transform that cancel out the transform on the // asset. For now just use the asset's transform as the parent matrix. Matrix4x4 parent_mat = prAsset.transform.localToWorldMatrix; Matrix4x4 global_mat = parent_mat * local_mat; euler = HoudiniAssetUtility.getQuaternion(global_mat).eulerAngles; pos = HoudiniAssetUtility.getPosition(global_mat); scale = HoudiniAssetUtility.getScale(global_mat); //mat.SetTRS( pos, string script_to_attach = ""; if (script_attr_info.exists) { script_to_attach = HoudiniHost.getString(script_attr[i]); } instanceObject(obj_to_instance, pos, euler, i, scale_attr_info.exists, scale, script_attr_info.exists, script_to_attach); HoudiniAsset hapi_asset = obj_to_instance.GetComponent <HoudiniAsset>(); if (hapi_asset != null) { hapi_asset.prTransformChangeTriggersCooks = liveTransformPropagationSetting; hapi_asset.prPushUnityTransformToHoudini = syncAssetTransformSetting; hapi_asset.prEnableCooking = enableCooking; } } } updateUniqueInstantiatedNames(unique_instantiated_names); } catch (HoudiniError error) { Debug.LogWarning(error.ToString()); return; } }
protected override void buildFullBuildCustomWork(ref HoudiniProgressBar progress_bar, bool is_duplication) { prCurve.initDefaultParameters(); }
protected override void buildFullBuildCustomWork(ref HoudiniProgressBar progress_bar, bool is_duplication) { }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset( HoudiniProgressBar progress_bar ) { // Try to find the otl if it has moved. #if UNITY_EDITOR #if UNITY_4_3 || UNITY_4_4 // Finding moved assets is not supported in Unity 4.4 and earlier versions. #else if ( !System.IO.File.Exists( prAssetPath ) ) { string file_name = System.IO.Path.GetFileNameWithoutExtension( prAssetPath ); string[] guids = AssetDatabase.FindAssets( file_name ); if ( guids.Length == 0 ) { throw new HoudiniError( "Houdini asset file has moved from last location: " + prAssetPath ); } prAssetPath = AssetDatabase.GUIDToAssetPath( guids[ 0 ] ); } #endif // UNITY_4_3 || UNITY_4_4 #endif // UNITY_EDITOR return HoudiniHost.loadOTL( prAssetPath, prSplitGeosByGroup, prImportTemplatedGeos, progress_bar, false ); }
protected override bool buildCreateObjects(bool reload_asset, ref HoudiniProgressBar progress_bar) { bool needs_recook = false; for (int object_index = 0; object_index < prObjectCount; ++object_index) { progress_bar.incrementProgressBar(); try { if (!prObjects[object_index].isInstancer && (reload_asset || prObjects[object_index].hasTransformChanged || prObjects[object_index].haveGeosChanged)) { needs_recook |= createObject(object_index, reload_asset); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } // Processing instancers. for (int object_index = 0; object_index < prObjectCount; ++object_index) { HAPI_ObjectInfo object_info = prObjects[object_index]; if (object_info.isInstancer) { try { if (object_info.objectToInstanceId >= 0) { int instanced_object_index = findObjectByNodeId(object_info.objectToInstanceId); if (instanced_object_index >= 0) { needs_recook |= createObject(instanced_object_index, reload_asset); } } if (reload_asset || object_info.haveGeosChanged) { instanceObjects(object_info.nodeId, object_index, progress_bar); } } catch (HoudiniError error) { // Per-object errors are not re-thrown so that the rest of the asset has a chance to load. Debug.LogWarning(error.ToString()); } } } if (prObjectCount <= 0) { bool needs_init = prObjectInfo.nodeId < 0 || reload_asset; if (prNodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_OBJ) { prObjectInfo = HoudiniHost.getObjectInfo(prAssetId); } else if (prNodeInfo.type == HAPI_NodeType.HAPI_NODETYPE_SOP) { prObjectInfo = HoudiniHost.getObjectInfo(prNodeInfo.parentId); } else { Debug.LogError("Unsupported asset type!"); return(needs_recook); } if (needs_init) { init( prAssetId, prNodeId, prAsset, prObjectInfo.nodeId, prObjectInfo.name, prObjectInfo.isVisible); } needs_recook = refresh(reload_asset, prObjectInfo); } // Enumerate edit and paint geos. HoudiniGeoControl[] geo_controls = gameObject.GetComponentsInChildren <HoudiniGeoControl>(); prEditPaintGeos.Clear(); foreach (HoudiniGeoControl geo_control in geo_controls) { if (geo_control.prGeoType == HAPI_GeoType.HAPI_GEOTYPE_INTERMEDIATE && geo_control.GetType() == typeof(HoudiniGeoControl)) { prEditPaintGeos.Add(geo_control); } } if (prEditPaintGeos.Count > 0 && prActiveAttributeManager == null) { prActiveAttributeManager = prEditPaintGeos[0].prGeoAttributeManager; } return(needs_recook); }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Protected Methods protected override int buildCreateAsset( HoudiniProgressBar progress_bar ) { //return HoudiniHost.createInputAsset( transform.name ); return HoudiniHost.instantiateAsset( "SOP/merge", true ); }