/// <summary> /// Returns list of HEU_TreePrototypeInfo formed by querying data from given part. /// </summary> /// <param name="session">Houdini Engine session</param> /// <param name="geoID">Geometry object</param> /// <param name="partID">Part ID</param> /// <returns>Returns list of HEU_TreePrototypeInfo or null if none found.</returns> public static List<HEU_TreePrototypeInfo> GetTreePrototypeInfosFromPart(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID) { List<HEU_TreePrototypeInfo> treePrototypes = new List<HEU_TreePrototypeInfo>(); // Each TreePrototype data is stored as a string attribute, under the 'HEU_Defines.HEIGHTFIELD_TREEPROTOTYPE + index' // name. So check and parse until no more valid attributes found. int index = 0; while (true) { // Does this attribute exist? string attrName = HEU_Defines.HEIGHTFIELD_TREEPROTOTYPE + index.ToString(); if (!HEU_GeneralUtility.HasAttribute(session, geoID, partID, attrName, HAPI_AttributeOwner.HAPI_ATTROWNER_PRIM)) { break; } index++; // Get the string value HAPI_AttributeInfo treeAttrInfo = new HAPI_AttributeInfo(); string[] protoAttrString = HEU_GeneralUtility.GetAttributeStringData(session, geoID, partID, attrName, ref treeAttrInfo); if (protoAttrString == null || protoAttrString.Length == 0 || string.IsNullOrEmpty(protoAttrString[0])) { break; } // Parse the attribute string value: // Only expecting a single element here, comma-separated for the asset path and bend factor: // => asset_path,bend_factor string[] properties = protoAttrString[0].Split(','); if (properties.Length > 0 && !string.IsNullOrEmpty(properties[0])) { HEU_TreePrototypeInfo prototype = new HEU_TreePrototypeInfo(); prototype._prefabPath = properties[0]; if (properties.Length >= 2) { float.TryParse(properties[1], out prototype._bendfactor); } treePrototypes.Add(prototype); } } return treePrototypes.Count > 0 ? treePrototypes : null; }