public static bool GetAttribute<T>(HEU_SessionBase session, HAPI_NodeId geoID, HAPI_PartId partID, string name, ref HAPI_AttributeInfo info, ref T[] data, GetAttributeArrayInputFunc<T> getFunc)
		{
			int originalTupleSize = info.tupleSize;
			bool bResult = false;
			for (HAPI_AttributeOwner type = 0; type < HAPI_AttributeOwner.HAPI_ATTROWNER_MAX; ++type)
			{
				bResult = session.GetAttributeInfo(geoID, partID, name, type, ref info);
				if (bResult && info.exists)
				{
					break;
				}
			}

			if (!bResult || !info.exists)
			{
				return false;
			}

			if (originalTupleSize > 0)
			{
				info.tupleSize = originalTupleSize;
			}

			data = new T[info.count * info.tupleSize];
			return GetAttributeArray(geoID, partID, name, ref info, data, getFunc, info.count);
		}
		public static bool GetAttributeArray<T>(HAPI_NodeId geoID, HAPI_PartId partID, string name, ref HAPI_AttributeInfo info, T[] items, GetAttributeArrayInputFunc<T> getFunc, int count)
		{
			int maxArraySize = HEU_Defines.HAPI_MAX_PAGE_SIZE / (Marshal.SizeOf(typeof(T)) * info.tupleSize);

			int localCount = count;
			int currentIndex = 0;

			bool bResult = false;

			while (localCount > 0)
			{
				int length = 0;
				if (localCount > maxArraySize)
				{
					length = maxArraySize;
					localCount -= maxArraySize;
				}
				else
				{
					length = localCount;
					localCount = 0;
				}

				T[] localArray = new T[length * info.tupleSize];
				bResult = getFunc(geoID, partID, name, ref info, localArray, currentIndex, length);
				if (!bResult)
				{
					break;
				}

				// Copy data from temporary array
				for (int i = currentIndex; i < currentIndex + length; ++i)
				{
					for (int j = 0; j < info.tupleSize; ++j)
					{
						items[i * info.tupleSize + j] = localArray[(i - currentIndex) * info.tupleSize + j];
					}
				}

				currentIndex += length;
			}

			return bResult;
		}