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();
		}
	}
Esempio n. 2
0
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 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();
        }
    }
Esempio n. 3
0
    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();
        }
    }
Esempio n. 4
0
	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;
	}
Esempio n. 5
0
	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
	}
Esempio n. 6
0
    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();
        }
    }
	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();
		}
	}
Esempio n. 8
0
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// 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();
		}
	}