@@ -71,16 +71,14 @@ public class HEU_GenerateGeoCache
7171
7272 public Dictionary < int , HEU_UnityMaterialInfo > _unityMaterialInfos ;
7373 public HAPI_AttributeInfo _unityMaterialAttrInfo ;
74- public HAPI_StringHandle [ ] _unityMaterialAttrName ;
74+ public int [ ] _unityMaterialAttrName ;
7575
76- public Dictionary < HAPI_StringHandle , string > _unityMaterialAttrStringsMap =
77- new Dictionary < HAPI_StringHandle , string > ( ) ;
76+ public List < string > _unityMaterialAttrStringsMap = new List < string > ( ) ;
7877
7978 public HAPI_AttributeInfo _substanceMaterialAttrNameInfo ;
80- public HAPI_StringHandle [ ] _substanceMaterialAttrName ;
79+ public int [ ] _substanceMaterialAttrName ;
8180
82- public Dictionary < HAPI_StringHandle , string > _substanceMaterialAttrStringsMap =
83- new Dictionary < HAPI_StringHandle , string > ( ) ;
81+ public List < string > _substanceMaterialAttrStringsMap = new List < string > ( ) ;
8482
8583 public HAPI_AttributeInfo _substanceMaterialAttrIndexInfo ;
8684 public int [ ] _substanceMaterialAttrIndex ;
@@ -246,6 +244,37 @@ public static HEU_GenerateGeoCache GetPopulatedGeoCache(HEU_SessionBase session,
246244 return geoCache ;
247245 }
248246
247+ public void GetStringAttributes ( HEU_SessionBase session , HAPI_NodeId geoID , HAPI_PartId partID , string name ,
248+ ref HAPI_AttributeInfo info , ref int [ ] stringIndices , ref List < string > stringTable )
249+ {
250+ // This a wrapper around HEU_GeneralUtility.GetAttribute(..., session.GetAttributeStringData)
251+ // which returns the strings in stringTable and an array stringIndices which reference these strings.
252+ // This is safer than storing HAPI string handles which can be transient in nature.
253+
254+ var stringHandles = new HAPI_StringHandle [ 0 ] ;
255+ HEU_GeneralUtility . GetAttribute ( session , GeoID , PartID , name , ref info , ref stringHandles , session . GetAttributeStringData ) ;
256+
257+ var stringLookup = new Dictionary < HAPI_StringHandle , int > ( ) ;
258+
259+ stringIndices = new int [ info . count * info . tupleSize ] ;
260+
261+ for ( int index = 0 ; index < stringHandles . Length ; index ++ )
262+ {
263+ HAPI_StringHandle strHandle = stringHandles [ index ] ;
264+
265+ // if we haven't encountered the string before, store it in the table and handle->string lookup dictionary.
266+ if ( ! stringLookup . ContainsKey ( strHandle ) )
267+ {
268+ string hapString = HEU_SessionManager . GetString ( strHandle , session ) ;
269+ int nextFreeIndex = stringTable . Count ;
270+ stringTable . Add ( hapString ) ;
271+ stringLookup [ strHandle ] = nextFreeIndex ;
272+ }
273+
274+ stringIndices [ index ] = stringLookup [ strHandle ] ;
275+ }
276+ }
277+
249278 /// <summary>
250279 /// Parse and populate materials in use by part.
251280 /// </summary>
@@ -255,56 +284,21 @@ public void PopulateUnityMaterialData(HEU_SessionBase session)
255284 // We fill up the following dictionary with unique Unity + Substance material information
256285 _unityMaterialInfos = new Dictionary < int , HEU_UnityMaterialInfo > ( ) ;
257286
258- _unityMaterialAttrInfo = new HAPI_AttributeInfo ( ) ;
259- _unityMaterialAttrName = new HAPI_StringHandle [ 0 ] ;
260- HEU_GeneralUtility . GetAttribute ( session , GeoID , PartID , HEU_PluginSettings . UnityMaterialAttribName ,
261- ref _unityMaterialAttrInfo , ref _unityMaterialAttrName , session . GetAttributeStringData ) ;
287+ GetStringAttributes ( session ,
288+ GeoID , PartID ,
289+ HEU_PluginSettings . UnityMaterialAttribName ,
290+ ref _unityMaterialAttrInfo , ref _unityMaterialAttrName , ref _unityMaterialAttrStringsMap ) ;
262291
263- // Store a local copy of the actual string values since the indices get overwritten by the next call to session.GetAttributeStringData.
264- // Using a dictionary to only query the unique strings, as doing all of them is very slow and unnecessary.
265- _unityMaterialAttrStringsMap = new Dictionary < HAPI_StringHandle , string > ( ) ;
266- foreach ( HAPI_StringHandle strHandle in _unityMaterialAttrName )
267- {
268- if ( ! _unityMaterialAttrStringsMap . ContainsKey ( strHandle ) )
269- {
270- string materialName = HEU_SessionManager . GetString ( strHandle , session ) ;
271- if ( ! string . IsNullOrEmpty ( materialName ) )
272- {
273- _unityMaterialAttrStringsMap . Add ( strHandle , materialName ) ;
274- }
275- else
276- {
277- // There are some cases (e.g. LOD input), where a material attribute should be empty.
278- // Warn user of empty string, but add it anyway to our map so we don't keep trying to parse it
279- // HEU_Logger.LogWarningFormat("Found empty material attribute value for part {0}.", _partName);
280- }
281- }
282- }
292+ GetStringAttributes ( session ,
293+ GeoID , PartID ,
294+ HEU_PluginSettings . UnitySubMaterialAttribName ,
295+ ref _substanceMaterialAttrNameInfo , ref _substanceMaterialAttrName , ref _substanceMaterialAttrStringsMap ) ;
283296
284297 _substanceMaterialAttrNameInfo = new HAPI_AttributeInfo ( ) ;
285298 _substanceMaterialAttrName = new HAPI_StringHandle [ 0 ] ;
286299 HEU_GeneralUtility . GetAttribute ( session , GeoID , PartID , HEU_PluginSettings . UnitySubMaterialAttribName ,
287300 ref _substanceMaterialAttrNameInfo , ref _substanceMaterialAttrName , session . GetAttributeStringData ) ;
288301
289- _substanceMaterialAttrStringsMap = new Dictionary < HAPI_StringHandle , string > ( ) ;
290- foreach ( HAPI_StringHandle strHandle in _substanceMaterialAttrName )
291- {
292- if ( ! _substanceMaterialAttrStringsMap . ContainsKey ( strHandle ) )
293- {
294- string substanceName = HEU_SessionManager . GetString ( strHandle , session ) ;
295- if ( string . IsNullOrEmpty ( substanceName ) )
296- {
297- // Warn user of empty string, but add it anyway to our map so we don't keep trying to parse it
298- HEU_Logger . LogWarningFormat (
299- "Found invalid substance material attribute value ({0}) for part {1}." ,
300- _partName , substanceName ) ;
301- }
302-
303- _substanceMaterialAttrStringsMap . Add ( strHandle , substanceName ) ;
304- //HEU_Logger.LogFormat("Added Substance material: " + substanceName);
305- }
306- }
307-
308302 _substanceMaterialAttrIndexInfo = new HAPI_AttributeInfo ( ) ;
309303 _substanceMaterialAttrIndex = new int [ 0 ] ;
310304 HEU_GeneralUtility . GetAttribute ( session , GeoID , PartID , HEU_PluginSettings . UnitySubMaterialIndexAttribName ,
@@ -323,7 +317,7 @@ public void PopulateUnityMaterialData(HEU_SessionBase session)
323317 }
324318 else
325319 {
326- for ( HAPI_StringHandle i = 0 ; i < _unityMaterialAttrName . Length ; ++ i )
320+ for ( int i = 0 ; i < _unityMaterialAttrName . Length ; ++ i )
327321 {
328322 CreateMaterialInfoEntryFromAttributeIndex ( this , i ) ;
329323 }
@@ -337,14 +331,13 @@ public static int GetMaterialKeyFromAttributeIndex(HEU_GenerateGeoCache geoCache
337331 unityMaterialName = null ;
338332 substanceName = null ;
339333 substanceIndex = - 1 ;
340- if ( attributeIndex < geoCache . _unityMaterialAttrName . Length &&
341- geoCache . _unityMaterialAttrStringsMap . TryGetValue ( geoCache . _unityMaterialAttrName [ attributeIndex ] ,
342- out unityMaterialName ) )
334+ if ( attributeIndex < geoCache . _unityMaterialAttrName . Length )
343335 {
336+ unityMaterialName = geoCache . _unityMaterialAttrStringsMap [ geoCache . _unityMaterialAttrName [ attributeIndex ] ] ;
337+
344338 if ( geoCache . _substanceMaterialAttrNameInfo . exists && geoCache . _substanceMaterialAttrName . Length > 0 )
345339 {
346- geoCache . _substanceMaterialAttrStringsMap . TryGetValue (
347- geoCache . _substanceMaterialAttrName [ attributeIndex ] , out substanceName ) ;
340+ substanceName = geoCache . _substanceMaterialAttrStringsMap [ geoCache . _substanceMaterialAttrName [ attributeIndex ] ] ;
348341 }
349342
350343 if ( geoCache . _substanceMaterialAttrIndexInfo . exists && string . IsNullOrEmpty ( substanceName ) &&
@@ -353,8 +346,7 @@ public static int GetMaterialKeyFromAttributeIndex(HEU_GenerateGeoCache geoCache
353346 substanceIndex = geoCache . _substanceMaterialAttrIndex [ attributeIndex ] ;
354347 }
355348
356- return HEU_MaterialFactory . GetUnitySubstanceMaterialKey ( unityMaterialName , substanceName ,
357- substanceIndex ) ;
349+ return HEU_MaterialFactory . GetUnitySubstanceMaterialKey ( unityMaterialName , substanceName , substanceIndex ) ;
358350 }
359351
360352 return HEU_Defines . HEU_INVALID_MATERIAL ;
@@ -366,8 +358,7 @@ public static void CreateMaterialInfoEntryFromAttributeIndex(HEU_GenerateGeoCach
366358 string unityMaterialName = null ;
367359 string substanceName = null ;
368360 int substanceIndex = - 1 ;
369- int materialKey = GetMaterialKeyFromAttributeIndex ( geoCache , materialAttributeIndex , out unityMaterialName ,
370- out substanceName , out substanceIndex ) ;
361+ int materialKey = GetMaterialKeyFromAttributeIndex ( geoCache , materialAttributeIndex , out unityMaterialName , out substanceName , out substanceIndex ) ;
371362 if ( ! geoCache . _unityMaterialInfos . ContainsKey ( materialKey ) )
372363 {
373364 geoCache . _unityMaterialInfos . Add ( materialKey ,
0 commit comments