Search - User list
Full Version: Info on the Houdini Engine C# "API"?
Root » Houdini Engine for Unity » Info on the Houdini Engine C# "API"?
MartinBaadsgaard
I am digging through the C# scripts making up the Unity-side interface of the Houdini Engine.
Some of them seem to be for “internal mechanics” and some expose functions that I can use to automate some processes.

Is there any documentation or notes on these things anywhere?
I am having a hard time figuring out where to find what.


Right now I am trying to find a way to pre-populate parameters in a newly-instantiated Houdini Asset, so the artists won't have to worry about things like pointing to the right output, hooking up global textures etc.
seelan
I've been meaning to write documentation on using the plugin programmetically. Haven't had the opportunity yet, but I've added an RFE to do so.
In the mean time, there are decent code examples provided which should get you started. Take a look at:
Assets\Plugins\HoudiniEngineUnity\Scripts\Examples\HEU_ScriptParameterExample.cs
Assets\Plugins\HoudiniEngineUnity\Scripts\Parameters\HEU_ParameterAccessor.cs
Assets\Plugins\HoudiniEngineUnity\Scripts\Parameters\HEU_ParameterUtility.cs

HEU_ScriptParameterExample.cs has an example of accessing and setting parameters, then cooking. The others are helpers to query and change parameter values.

Here is a sample code to create an HDA from a file path, set an input gameobject, set a float parameter, and cook it with a callback.
public class TestProcessInputs
{
	public const string HDAPath = "Assets/HDAs/Input/polyreduce.hda";

	public static HEU_HoudiniAsset InstatiatedAsset(string assetPath)
	{
		// Instantiate the processor HDA. This will load and cook into Unity scene with defautl values.
		GameObject assetGO = HEU_HAPIUtility.InstantiateHDA(HDAPath, Vector3.zero, HEU_SessionManager.GetOrCreateDefaultSession(), false);
		if (assetGO != null && assetGO.GetComponent<HEU_HoudiniAssetRoot>() != null)
		{
			HEU_HoudiniAssetRoot assetRoot = assetGO.GetComponent<HEU_HoudiniAssetRoot>();
			if (assetRoot != null)
			{
				return assetRoot._houdiniAsset;
			}
		}
		return null;
	}

	// This will merge all selected inputs and submit to HDA. Result will be a merged output.
	[MenuItem("Test/ProcesInput")]
	public static void TestProcessInput()
	{
		GameObject[] selectedGOs = Selection.gameObjects;

		if(selectedGOs != null && selectedGOs.Length > 0)
		{
			// Instantiate the processor HDA. This will load and cook into Unity scene with defautl values.
			HEU_HoudiniAsset asset = InstatiatedAsset(HDAPath);
			if (asset)
			{
				// Now get the object path parameter (with name objpath1). We're going to add
				// selected gameobjects with meshes in as a list of inputs.
				HEU_ParameterData inputParam = asset.Parameters.GetParameter("objpath1");
				if (inputParam != null && inputParam._paramInputNode != null)
				{
					inputParam._paramInputNode.KeepWorldTransform = true;

					int numSelectedObjects = selectedGOs.Length;
					for (int i = 0; i < numSelectedObjects; ++i)
					{
						inputParam._paramInputNode.AddInputObjectAtEnd(selectedGOs[i]);
					}

					// Flag for upload of input meshes
					inputParam._paramInputNode.RequiresUpload = true;
				}

				// Set poly reduce param to 50%
				HEU_ParameterAccessor.SetFloat(asset, "percentage", 50f);

				// Add cooked callback
				asset._cookedEvent.AddListener(CookedCallback);

				// Cook the HDA asynchronously (can send false to bAsync if want to wait)
				asset.RequestCook(bCheckParametersChanged: true, bAsync: true, bSkipCookCheck: true, bUploadParameters: true);
			}
		}
	}

	public static void CookedCallback(HEU_HoudiniAsset asset, bool success, List<GameObject> outputs)
	{
		// Cooking done. Bake it out and remove the HDA.
		Debug.LogFormat("Asset {0} has cooked with result: {1}", asset.AssetName, success);

		asset.RequestBakeInPlace();
	}
}

Feel free to ask me questions on anything else here.
MartinBaadsgaard
Thank you for the example, that is very helpful!
MartinBaadsgaard
Ah, apologies.
I seem to have accidentally deleted HEU_ScriptParameterExample.cs from my project so hadn't spotted that.
Seems to give most of the answers.
MartinBaadsgaard
Okay question! This is mostly for best practices..

I can see I can either access the parameters with .Parameters.getParameter which gives a
Or I can use HEU_ParameterAccessor.GetColor/Float/Int/etc.

It seems like the ParameterAccessor is more for convenience, but if I want to change the parameter often, I should circumvent that and have a direct reference to the HEU_ParameterData, right?
Or is this not reliable for some reason?
seelan
HEU_ParameterData might get invalidated during a cook as parameters could be regenerated when an asset is cooked. But otherwise, between cooks, you can store and use HEU_ParameterData to query and modify the parameter values.

Your guess is correct that it is better to keep a reference if you are modifying the value often, since Parameters.getParameters does a search every time to get the parameter (though in reality, unless you have tons of parameters or calling this a lot, this shouldn't be an issue).

HEU_ParameterAccessor was provided for both convenience and as example.

My recommendation is to use HEU_ParameterAccessor unless it becomes slow. Otherwise you can keep a reference to HEU_ParameterData, and make sure to reacquire it after each cook.
MartinBaadsgaard
Great, thanks for the feedback!

I came across HEU_ParameterAccessor.SetInputNode()too and compared it to your example.
They are pretty much the same, except that your example sets inputParam._paramInputNode.RequiresUpload = true;
What does this property do exactly? I think I missed something there.

I am just hooking into the HEU_ParameterAccessor as much as I can, even though it would probably be more performant to just ask for the (currently out of scope) _parameterList from the HEU_Parameters on the HDA instance.
This points back to my initial confusion. It is a bit hard to spot what is meant as example code and what is meant as utility code as things stand right now. (So hard to know what I can make my own version of and what might need to be left as-is for future updates)

Anyway, thank you for your help and patience. I am still completely new to Houdini, but slowly getting an understanding of it.
seelan
inputParam._paramInputNode.RequiresUpload = true;flags the plugin to upload the mesh on cook because it had changed. Without that flag, it wouldn't upload the mesh. The reason for the flag is to reduce unnecessary input geometry upload into Houdini since these can be very slow depending on the geometry.

So the reason inputParam._paramInputNode.RequiresUpload = true;was missing from HEU_ParameterAccessor.SetInputNode()is because RequiresUpload was added after I had written HEU_ParameterAccessor.SetInputNode(). I should have updated it but hadn't done so yet. I just fixed it now.

The comment at top of the HEU_ParameterAccessor file says its meant to be used as an API for programmetically driving the parameters, so its best to use that, as they are less likely to change. The utility classes are used by the plugin code but you may use them with the understanding that they might change.

I think the confusion comes from the fact that there is no clear “public” API nor documentation about it. This will be coming in the future. I might create another folder that will contain a set of API classes very much like HEU_ParameterAccessor, and move HEU_ParameterAccessorinto it. At least that should provide a clear location to find them.

If you have suggestions please let me know.
MartinBaadsgaard
Great. Thanks for clearing that up.

Yea I was expecting the missing function call was just a question of getting around to all the places in your package.


As for suggestion for structure,
I currently just think about the separation between
internal stuff,
interface/“API”,
and examples

For, as you also said, to know what might change, what won't, what is just suggested approach etc. and then also to more easily get an overview of the “tools” available.
Quickly knowing what are your instanced classes, what are your tool classes and what are underlying classes makes it easy to see where you need to dig around for the functions to do something specific.
But it is just a different structure and would break how you arrange it right now.

Besides that, a quick documentation on the structure of things would probably also help.
Like “HEU_ParameterAccessor is to be used with HEU_HoudiniAsset to directly set parameters which are stored in a HEU_Parameters held by the HEU_HoudiniAsset. The parameters are of type HEU_ParameterData which can also be handled directly using functions etc. etc.”

That said, it's been a few days and I feel fairly comfortable with HEU now and anyone who makes an effort should have no problem getting started with it too.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB