public static bool SetAttribute<T>(HAPI_NodeId geoID, HAPI_PartId partID, string attrName, ref HAPI_AttributeInfo attrInfo, T[] items, SetAttributeArrayFunc<T> setFunc)
		{
			return SetAttributeArray(geoID, partID, attrName, ref attrInfo, items, setFunc, attrInfo.count);
		}
		public static bool SetAttributeArray<T>(HAPI_NodeId geoID, HAPI_PartId partID, string attrName, ref HAPI_AttributeInfo attrInfo, T[] items, SetAttributeArrayFunc<T> setFunc, int count)
		{
			bool bResult = false;

			int maxArraySize = 0;
			if(typeof(T) == typeof(string))
			{
				int maxStringLength = 1;
				foreach(T s in items)
				{
					string str = (string)(object)s;
					if(str.Length > maxStringLength)
					{
						maxStringLength = str.Length;
					}
				}
				maxArraySize = HEU_Defines.HAPI_MAX_PAGE_SIZE / (maxStringLength * Marshal.SizeOf(typeof(char)) * attrInfo.tupleSize);
			}
			else
			{
				maxArraySize = HEU_Defines.HAPI_MAX_PAGE_SIZE / (Marshal.SizeOf(typeof(T)) * attrInfo.tupleSize);
			}

			int localCount = count;
			int currentIndex = 0;

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

				T[] localArray = new T[length * attrInfo.tupleSize];

				// Copy subset to temp array
				for(int i = currentIndex; i < currentIndex + length; ++i)
				{
					for(int j = 0; j < attrInfo.tupleSize; ++j)
					{
						localArray[(i - currentIndex) * attrInfo.tupleSize + j] = items[i * attrInfo.tupleSize + j];
					}
				}

				bResult = setFunc(geoID, partID, attrName, ref attrInfo, localArray, currentIndex, length);
				if (!bResult)
				{
					break;
				}

				currentIndex += length;
			}

			return bResult;
		}