assetImporter.cpp 146 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463
  1. #include "assetImporter.h"
  2. #include "assetImporter_ScriptBinding.h"
  3. #include "core/strings/findMatch.h"
  4. #include "ImageAsset.h"
  5. #include "ShapeAsset.h"
  6. #include "SoundAsset.h"
  7. #include "MaterialAsset.h"
  8. #include "ShapeAnimationAsset.h"
  9. #include "ts/collada/colladaUtils.h"
  10. #include "ts/collada/colladaAppNode.h"
  11. #include "ts/collada/colladaShapeLoader.h"
  12. #include "ts/assimp/assimpShapeLoader.h"
  13. #include "ts/tsShapeConstruct.h"
  14. #include "core/resourceManager.h"
  15. #include "materials/materialManager.h"
  16. #include "console/persistenceManager.h"
  17. #include "core/util/timeClass.h"
  18. ConsoleDocClass(AssetImportConfig,
  19. "@brief Defines properties for an AssetImprotConfig object.\n"
  20. "@AssetImportConfig is a SimObject derived object intended to act as a container for all the necessary configuration data when running the Asset Importer.\n"
  21. "@It dictates if and how any given asset type will be processed when running an import action. This is because the Asset Importer utilizes a lot of informed logic\n"
  22. "@to try and automate as much of the import process as possible. In theory, you would run the import on a given file, and based on your config the importer will do\n"
  23. "@everything from importing the designated file, as well as finding and importing any associated files such as images or materials, and prepping the objects at time\n"
  24. "@of import to avoid as much manual post-processing as possible.\n\n"
  25. "@ingroup Assets\n"
  26. );
  27. IMPLEMENT_CONOBJECT(AssetImportConfig);
  28. AssetImportConfig::AssetImportConfig() :
  29. DuplicateAutoResolution("AutoRename"),
  30. WarningsAsErrors(false),
  31. PreventImportWithErrors(true),
  32. AutomaticallyPromptMissingFiles(false),
  33. AddDirectoryPrefixToAssetName(false),
  34. ImportMesh(true),
  35. AlwaysAddShapeSuffix(false),
  36. AddedShapeSuffix("_shape"),
  37. UseManualShapeConfigRules(false),
  38. DoUpAxisOverride(false),
  39. UpAxisOverride("Z_AXIS"),
  40. DoScaleOverride(false),
  41. ScaleOverride(false),
  42. IgnoreNodeScale(false),
  43. AdjustCenter(false),
  44. AdjustFloor(false),
  45. CollapseSubmeshes(false),
  46. LODType("TrailingNumber"),
  47. AlwaysImportedNodes(""),
  48. AlwaysIgnoreNodes(""),
  49. AlwaysImportMeshes(""),
  50. AlwaysIgnoreMeshes(""),
  51. convertLeftHanded(false),
  52. calcTangentSpace(false),
  53. removeRedundantMats(false),
  54. genUVCoords(false),
  55. TransformUVs(false),
  56. flipUVCoords(false),
  57. findInstances(false),
  58. limitBoneWeights(false),
  59. JoinIdenticalVerts(false),
  60. reverseWindingOrder(false),
  61. invertNormals(false),
  62. ImportMaterials(true),
  63. AlwaysAddMaterialSuffix(true),
  64. AddedMaterialSuffix("_mat"),
  65. CreateORMConfig(true),
  66. UseDiffuseSuffixOnOriginImage(false),
  67. UseExistingMaterials(false),
  68. IgnoreMaterials(""),
  69. PopulateMaterialMaps(true),
  70. ImportAnimations(true),
  71. SeparateAnimations(false),
  72. SeparateAnimationPrefix(""),
  73. animTiming("FrameCount"),
  74. animFPS(false),
  75. AlwaysAddShapeAnimationSuffix(true),
  76. AddedShapeAnimationSuffix("_anim"),
  77. GenerateCollisions(false),
  78. GenCollisionType(""),
  79. CollisionMeshPrefix(""),
  80. GenerateLOSCollisions(false),
  81. GenLOSCollisionType(""),
  82. LOSCollisionMeshPrefix(""),
  83. importImages(true),
  84. AlwaysAddImageSuffix(true),
  85. AddedImageSuffix("_image"),
  86. ImageType("GUI"),
  87. DiffuseTypeSuffixes("_ALBEDO,_DIFFUSE,_ALB,_DIF,_COLOR,_COL,_A,_C,-ALBEDO,-DIFFUSE,-ALB,-DIF,-COLOR,-COL,-A,-C"),
  88. NormalTypeSuffixes("_NORMAL,_NORM,_N,-NORMAL,-NORM,-N"),
  89. MetalnessTypeSuffixes("_METAL,_MET,_METALNESS,_METALLIC,_M,-METAL,-MET,-METALNESS,-METALLIC,-M"),
  90. RoughnessTypeSuffixes("_ROUGH,_ROUGHNESS,_R,-ROUGH,-ROUGHNESS,-R"),
  91. SmoothnessTypeSuffixes("_SMOOTH,_SMOOTHNESS,_S,-SMOOTH,-SMOOTHNESS,-S"),
  92. AOTypeSuffixes("_AO,_AMBIENT,_AMBIENTOCCLUSION,-AO,-AMBIENT,-AMBIENTOCCLUSION"),
  93. PBRTypeSuffixes("_COMP,_COMPOSITE,_PBR,-COMP,-COMPOSITE,-PBR,_ORM,-ORM"),
  94. TextureFilteringMode("Bilinear"),
  95. UseMips(true),
  96. IsHDR(false),
  97. Scaling(false),
  98. ImagesCompressed(false),
  99. GenerateMaterialOnImport(true),
  100. importSounds(true),
  101. VolumeAdjust(false),
  102. PitchAdjust(false),
  103. SoundsCompressed(false),
  104. AlwaysAddSoundSuffix(false),
  105. AddedSoundSuffix("_sound")
  106. {
  107. }
  108. AssetImportConfig::~AssetImportConfig()
  109. {
  110. }
  111. bool AssetImportConfig::onAdd()
  112. {
  113. if (!Parent::onAdd())
  114. return false;
  115. return true;
  116. }
  117. void AssetImportConfig::onRemove()
  118. {
  119. Parent::onRemove();
  120. }
  121. /// Engine.
  122. void AssetImportConfig::initPersistFields()
  123. {
  124. docsURL;
  125. Parent::initPersistFields();
  126. addGroup("General");
  127. addField("DuplicateAutoResolution", TypeRealString, Offset(DuplicateAutoResolution, AssetImportConfig), "Duplicate Asset Auto-Resolution Action. Options are None, AutoPrune, AutoRename, FolderPrefix");
  128. addField("WarningsAsErrors", TypeBool, Offset(WarningsAsErrors, AssetImportConfig), "Indicates if warnings should be treated as errors");
  129. addField("PreventImportWithErrors", TypeBool, Offset(PreventImportWithErrors, AssetImportConfig), "Indicates if importing should be prevented from completing if any errors are detected at all");
  130. addField("AutomaticallyPromptMissingFiles", TypeBool, Offset(AutomaticallyPromptMissingFiles, AssetImportConfig), "Should the importer automatically prompt to find missing files if they are not detected automatically by the importer");
  131. addField("AddDirectoryPrefixToAssetName", TypeBool, Offset(AddDirectoryPrefixToAssetName, AssetImportConfig), "Should the importer add the folder name as a prefix to the assetName. Helps prevent name collisions.");
  132. endGroup("General");
  133. addGroup("Meshes");
  134. addField("ImportMesh", TypeBool, Offset(ImportMesh, AssetImportConfig), "Indicates if this config supports importing meshes");
  135. addField("AlwaysAddShapeSuffix", TypeBool, Offset(AlwaysAddShapeSuffix, AssetImportConfig), "When importing a shape, this indicates if it should automatically add a standard suffix onto the name");
  136. addField("AddedShapeSuffix", TypeString, Offset(AddedShapeSuffix, AssetImportConfig), " If AlwaysAddShapeSuffix is on, this is the suffix to be added");
  137. addField("UseManualShapeConfigRules", TypeBool, Offset(UseManualShapeConfigRules, AssetImportConfig), "Indicates if this config should override the per-format sis files with the config's specific settings");
  138. addField("DoUpAxisOverride", TypeBool, Offset(DoUpAxisOverride, AssetImportConfig), "Indicates if the up axis in the model file should be overridden");
  139. addField("UpAxisOverride", TypeRealString, Offset(UpAxisOverride, AssetImportConfig), "If overriding, what axis should be used as up. Options are X_AXIS, Y_AXIS, Z_AXIS");
  140. addField("DoScaleOverride", TypeBool, Offset(DoScaleOverride, AssetImportConfig), "Indicates if the scale in the model file should be overridden");
  141. addField("ScaleOverride", TypeF32, Offset(ScaleOverride, AssetImportConfig), "If overriding, what scale should be used");
  142. addField("IgnoreNodeScale", TypeBool, Offset(IgnoreNodeScale, AssetImportConfig), "Indicates if scale of nodes should be ignored");
  143. addField("AdjustCenter", TypeBool, Offset(AdjustCenter, AssetImportConfig), "Indicates if the center of the model file should be automatically recentered");
  144. addField("AdjustFloor", TypeBool, Offset(AdjustFloor, AssetImportConfig), "Indicates if the floor height of the model file should be automatically zero'd");
  145. addField("CollapseSubmeshes", TypeBool, Offset(CollapseSubmeshes, AssetImportConfig), "Indicates if submeshes should be collapsed down into a single main mesh");
  146. addField("LODType", TypeRealString, Offset(LODType, AssetImportConfig), "Indicates what LOD mode the model file should utilize to process out LODs. Options are TrailingNumber, DetectDTS, SingleSize");
  147. addField("singleDetailSize", TypeS32, Offset(singleDetailSize, AssetImportConfig), "what lod value to use if all submeshes are set to the same detail level");
  148. addField("AlwaysImportedNodes", TypeRealString, Offset(AlwaysImportedNodes, AssetImportConfig), " A list of what nodes should be guaranteed to be imported if found in the model file. Separated by either , or ;");
  149. addField("AlwaysIgnoreNodes", TypeRealString, Offset(AlwaysIgnoreNodes, AssetImportConfig), "A list of what nodes should be guaranteed to not be imported if found in the model file. Separated by either , or ;");
  150. addField("AlwaysImportMeshes", TypeRealString, Offset(AlwaysImportMeshes, AssetImportConfig), "A list of what mesh objects should be guaranteed to be imported if found in the model file. Separated by either , or ;");
  151. addField("AlwaysIgnoreMeshes", TypeRealString, Offset(AlwaysIgnoreMeshes, AssetImportConfig), "A list of what mesh objects should be guaranteed to not be imported if found in the model file. Separated by either , or ;");
  152. addField("convertLeftHanded", TypeBool, Offset(convertLeftHanded, AssetImportConfig), "Flag to indicate the shape loader should convert to a left-handed coordinate system");
  153. addField("calcTangentSpace", TypeBool, Offset(calcTangentSpace, AssetImportConfig), "Should the shape loader calculate tangent space values");
  154. addField("removeRedundantMats", TypeBool, Offset(removeRedundantMats, AssetImportConfig), "Should the shape loader automatically prune redundant/duplicate materials");
  155. addField("genUVCoords", TypeBool, Offset(genUVCoords, AssetImportConfig), "Should the shape loader auto-generate UV Coordinates for the mesh.");
  156. addField("TransformUVs", TypeBool, Offset(TransformUVs, AssetImportConfig), "Should the UV coordinates be transformed");
  157. addField("flipUVCoords", TypeBool, Offset(flipUVCoords, AssetImportConfig), "Should the UV coordinates be flipped");
  158. addField("findInstances", TypeBool, Offset(findInstances, AssetImportConfig), "Should the shape loader automatically look for instanced submeshes in the model file");
  159. addField("limitBoneWeights", TypeBool, Offset(limitBoneWeights, AssetImportConfig), "Should the shape loader limit the bone weights");
  160. addField("JoinIdenticalVerts", TypeBool, Offset(JoinIdenticalVerts, AssetImportConfig), "Should the shape loader automatically merge identical/duplicate verts");
  161. addField("reverseWindingOrder", TypeBool, Offset(reverseWindingOrder, AssetImportConfig), "Should the shape loader reverse the winding order of the mesh's face indicies");
  162. addField("invertNormals", TypeBool, Offset(invertNormals, AssetImportConfig), "Should the normals on the model be inverted");
  163. endGroup("Meshes");
  164. addGroup("Materials");
  165. addField("ImportMaterials", TypeBool, Offset(ImportMaterials, AssetImportConfig), "Does this config allow for importing of materials");
  166. addField("AlwaysAddMaterialSuffix", TypeBool, Offset(AlwaysAddMaterialSuffix, AssetImportConfig), "When importing a material, this indicates if it should automatically add a standard suffix onto the name");
  167. addField("AddedMaterialSuffix", TypeString, Offset(AddedMaterialSuffix, AssetImportConfig), " If AlwaysAddMaterialSuffix is on, this is the suffix to be added");
  168. addField("CreateORMConfig", TypeBool, Offset(PreventImportWithErrors, AssetImportConfig), "When importing a material, should it automatically attempt to merge Roughness, AO and Metalness maps into a single, composited PBR Configuration map");
  169. addField("UseDiffuseSuffixOnOriginImage", TypeBool, Offset(UseDiffuseSuffixOnOriginImage, AssetImportConfig), "When generating a material off of an importing image, should the importer force appending a diffusemap suffix onto the end to avoid potential naming confusion.\n e.g. MyCoolStuff.png is imported, generating MyCoolStuff material asset and MyCoolStuff_Diffuse image asset");
  170. addField("UseExistingMaterials", TypeBool, Offset(UseExistingMaterials, AssetImportConfig), "Should the importer try and use existing material assets in the game directory if at all possible. (Not currently utilized)");
  171. addField("IgnoreMaterials", TypeRealString, Offset(IgnoreMaterials, AssetImportConfig), "A list of material names that should not be imported. Separated by either , or ;");
  172. addField("PopulateMaterialMaps", TypeBool, Offset(PopulateMaterialMaps, AssetImportConfig), "When processing a material asset, should the importer attempt to populate the various material maps on it by looking up common naming conventions for potentially relevent image files.\n e.g. If MyCoolStuff_Diffuse.png is imported, generating MyCoolStuff material, it would also find MyCoolStuff_Normal and MyCoolStuff_PBR images and map them to the normal and ORMConfig maps respectively automatically");
  173. endGroup("Materials");
  174. addGroup("Animation");
  175. addField("ImportAnimations", TypeBool, Offset(ImportAnimations, AssetImportConfig), "Does this config allow for importing Shape Animations");
  176. addField("SeparateAnimations", TypeBool, Offset(SeparateAnimations, AssetImportConfig), "When importing a shape file, should the animations within be separated out into unique files");
  177. addField("SeparateAnimationPrefix", TypeRealString, Offset(SeparateAnimationPrefix, AssetImportConfig), "If separating animations out from a source file, what prefix should be added to the names for grouping association");
  178. addField("animTiming", TypeRealString, Offset(animTiming, AssetImportConfig), "Defines the animation timing for the given animation sequence. Options are FrameTime, Seconds, Milliseconds");
  179. addField("animFPS", TypeBool, Offset(animFPS, AssetImportConfig), "The FPS of the animation sequence");
  180. addField("AlwaysAddShapeAnimationSuffix", TypeBool, Offset(AlwaysAddShapeAnimationSuffix, AssetImportConfig), "When importing a shape animation, this indicates if it should automatically add a standard suffix onto the name");
  181. addField("AddedShapeAnimationSuffix", TypeString, Offset(AddedShapeAnimationSuffix, AssetImportConfig), " If AlwaysAddShapeAnimationSuffix is on, this is the suffix to be added");
  182. endGroup("Animation");
  183. addGroup("Collision");
  184. addField("GenerateCollisions", TypeBool, Offset(GenerateCollisions, AssetImportConfig), "Does this configuration generate collision geometry when importing. (Not currently enabled)");
  185. addField("GenCollisionType", TypeRealString, Offset(GenCollisionType, AssetImportConfig), "What sort of collision geometry is generated. (Not currently enabled)");
  186. addField("CollisionMeshPrefix", TypeRealString, Offset(CollisionMeshPrefix, AssetImportConfig), "What prefix is added to the collision geometry generated. (Not currently enabled)");
  187. addField("GenerateLOSCollisions", TypeBool, Offset(GenerateLOSCollisions, AssetImportConfig), "Does this configuration generate Line of Sight collision geometry. (Not currently enabled)");
  188. addField("GenLOSCollisionType", TypeRealString, Offset(GenLOSCollisionType, AssetImportConfig), "What sort of Line of Sight collision geometry is generated. (Not currently enabled)");
  189. addField("LOSCollisionMeshPrefix", TypeRealString, Offset(LOSCollisionMeshPrefix, AssetImportConfig), "What prefix is added to the Line of Sight collision geometry generated. (Not currently enabled)");
  190. endGroup("Collision");
  191. addGroup("Images");
  192. addField("importImages", TypeBool, Offset(importImages, AssetImportConfig), "Does this configuration support importing images.");
  193. addField("AlwaysAddImageSuffix", TypeBool, Offset(AlwaysAddImageSuffix, AssetImportConfig), "When importing an image, this indicates if it should automatically add a standard suffix onto the name");
  194. addField("AddedImageSuffix", TypeString, Offset(AddedImageSuffix, AssetImportConfig), " If AlwaysAddImageSuffix is on, this is the suffix to be added");
  195. addField("ImageType", TypeRealString, Offset(ImageType, AssetImportConfig), "What is the default ImageType images are imported as. Options are: N/A, Diffuse, Normal, Metalness, Roughness, AO, ORMConfig, GUI, Cubemap");
  196. addField("DiffuseTypeSuffixes", TypeRealString, Offset(DiffuseTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a diffuse map. \n e.g. _Albedo or _Color");
  197. addField("NormalTypeSuffixes", TypeRealString, Offset(NormalTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a normal map. \n e.g. _Normal or _Norm");
  198. addField("MetalnessTypeSuffixes", TypeRealString, Offset(MetalnessTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a metalness map. \n e.g. _Metalness or _Metal");
  199. addField("RoughnessTypeSuffixes", TypeRealString, Offset(RoughnessTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a roughness map.\n e.g. _roughness or _rough");
  200. addField("SmoothnessTypeSuffixes", TypeRealString, Offset(SmoothnessTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a smoothness map. \n e.g. _smoothness or _smooth");
  201. addField("AOTypeSuffixes", TypeRealString, Offset(AOTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a ambient occlusion map. \n e.g. _ambient or _ao");
  202. addField("PBRTypeSuffixes", TypeRealString, Offset(PBRTypeSuffixes, AssetImportConfig), "What type of suffixes are scanned to detect if an importing image is a ORMConfig map.\n e.g. _Composite or _PBR");
  203. addField("TextureFilteringMode", TypeRealString, Offset(TextureFilteringMode, AssetImportConfig), "Indicates what filter mode images imported with this configuration utilizes. Options are Linear, Bilinear, Trilinear");
  204. addField("UseMips", TypeBool, Offset(UseMips, AssetImportConfig), "Indicates if images imported with this configuration utilize mipmaps");
  205. addField("IsHDR", TypeBool, Offset(IsHDR, AssetImportConfig), "Indicates if images imported with this configuration are in an HDR format");
  206. addField("Scaling", TypeF32, Offset(Scaling, AssetImportConfig), "Indicates what amount of scaling images imported with this configuration use");
  207. addField("ImagesCompressed", TypeBool, Offset(ImagesCompressed, AssetImportConfig), "Indicates if images imported with this configuration are compressed");
  208. addField("GenerateMaterialOnImport", TypeBool, Offset(GenerateMaterialOnImport, AssetImportConfig), "Indicates if images imported with this configuration generate a parent material for it as well");
  209. endGroup("Images");
  210. addGroup("Sounds");
  211. addField("importSounds", TypeBool, Offset(importSounds, AssetImportConfig), "Indicates if sounds are imported with this configuration");
  212. addField("VolumeAdjust", TypeF32, Offset(VolumeAdjust, AssetImportConfig), "Indicates what amount the volume is adjusted on sounds imported with this configuration");
  213. addField("PitchAdjust", TypeF32, Offset(PitchAdjust, AssetImportConfig), "Indicates what amount the pitch is adjusted on sounds imported with this configuration");
  214. addField("SoundsCompressed", TypeBool, Offset(SoundsCompressed, AssetImportConfig), "Indicates if sounds imported with this configuration are compressed");
  215. endGroup("Sounds");
  216. }
  217. void AssetImportConfig::loadImportConfig(Settings* configSettings, String configName)
  218. {
  219. //General
  220. DuplicateAutoResolution = configSettings->value(String(configName + "/General/DuplicateAutoResolution").c_str());
  221. WarningsAsErrors = dAtob(configSettings->value(String(configName + "/General/WarningsAsErrors").c_str()));
  222. PreventImportWithErrors = dAtob(configSettings->value(String(configName + "/General/PreventImportWithErrors").c_str()));
  223. AutomaticallyPromptMissingFiles = dAtob(configSettings->value(String(configName + "/General/AutomaticallyPromptMissingFiles").c_str()));
  224. AddDirectoryPrefixToAssetName = dAtob(configSettings->value(String(configName + "/General/AddDirectoryPrefixToAssetName").c_str()));
  225. //Meshes
  226. ImportMesh = dAtob(configSettings->value(String(configName + "/Meshes/ImportMesh").c_str()));
  227. AlwaysAddShapeSuffix = dAtob(configSettings->value(String(configName + "/Meshes/AlwaysAddShapeSuffix").c_str()));
  228. AddedShapeSuffix = configSettings->value(String(configName + "/Meshes/AddedShapeSuffix").c_str());
  229. UseManualShapeConfigRules = dAtob(configSettings->value(String(configName + "/Meshes/UseManualShapeConfigRules").c_str()));
  230. DoUpAxisOverride = dAtob(configSettings->value(String(configName + "/Meshes/DoUpAxisOverride").c_str()));
  231. UpAxisOverride = configSettings->value(String(configName + "/Meshes/UpAxisOverride").c_str());
  232. DoScaleOverride = dAtob(configSettings->value(String(configName + "/Meshes/DoScaleOverride").c_str()));
  233. ScaleOverride = dAtof(configSettings->value(String(configName + "/Meshes/ScaleOverride").c_str()));
  234. IgnoreNodeScale = dAtob(configSettings->value(String(configName + "/Meshes/IgnoreNodeScale").c_str()));
  235. AdjustCenter = dAtob(configSettings->value(String(configName + "/Meshes/AdjustCenter").c_str()));
  236. AdjustFloor = dAtob(configSettings->value(String(configName + "/Meshes/AdjustFloor").c_str()));
  237. CollapseSubmeshes = dAtob(configSettings->value(String(configName + "/Meshes/CollapseSubmeshes").c_str()));
  238. LODType = configSettings->value(String(configName + "/Meshes/LODType").c_str());
  239. singleDetailSize = dAtoi(configSettings->value(String(configName + "/Meshes/singleDetailSize").c_str()));
  240. AlwaysImportedNodes = configSettings->value(String(configName + "/Meshes/AlwaysImportedNodes").c_str());
  241. AlwaysIgnoreNodes = configSettings->value(String(configName + "/Meshes/AlwaysIgnoreNodes").c_str());
  242. AlwaysImportMeshes = configSettings->value(String(configName + "/Meshes/AlwaysImportMeshes").c_str());
  243. AlwaysIgnoreMeshes = configSettings->value(String(configName + "/Meshes/AlwaysIgnoreMeshes").c_str());
  244. //Assimp/Collada
  245. convertLeftHanded = dAtob(configSettings->value(String(configName + "/Meshes/convertLeftHanded").c_str()));
  246. calcTangentSpace = dAtob(configSettings->value(String(configName + "/Meshes/calcTangentSpace").c_str()));
  247. removeRedundantMats = dAtob(configSettings->value(String(configName + "/Meshes/removeRedundantMats").c_str()));
  248. genUVCoords = dAtob(configSettings->value(String(configName + "/Meshes/genUVCoords").c_str()));
  249. TransformUVs = dAtob(configSettings->value(String(configName + "/Meshes/TransformUVs").c_str()));
  250. flipUVCoords = dAtob(configSettings->value(String(configName + "/Meshes/flipUVCoords").c_str()));
  251. findInstances = dAtob(configSettings->value(String(configName + "/Meshes/findInstances").c_str()));
  252. limitBoneWeights = dAtob(configSettings->value(String(configName + "/Meshes/limitBoneWeights").c_str()));
  253. JoinIdenticalVerts = dAtob(configSettings->value(String(configName + "/Meshes/JoinIdenticalVerts").c_str()));
  254. reverseWindingOrder = dAtob(configSettings->value(String(configName + "/Meshes/reverseWindingOrder").c_str()));
  255. invertNormals = dAtob(configSettings->value(String(configName + "/Meshes/invertNormals").c_str()));
  256. //Materials
  257. ImportMaterials = dAtob(configSettings->value(String(configName + "/Materials/ImportMaterials").c_str()));
  258. AlwaysAddMaterialSuffix = dAtob(configSettings->value(String(configName + "/Materials/AlwaysAddMaterialSuffix").c_str()));
  259. AddedMaterialSuffix = configSettings->value(String(configName + "/Materials/AddedMaterialSuffix").c_str());
  260. CreateORMConfig = dAtob(configSettings->value(String(configName + "/Materials/CreateORMConfig").c_str()));
  261. UseDiffuseSuffixOnOriginImage = dAtob(configSettings->value(String(configName + "/Materials/UseDiffuseSuffixOnOriginImage").c_str()));
  262. UseExistingMaterials = dAtob(configSettings->value(String(configName + "/Materials/UseExistingMaterials").c_str()));
  263. IgnoreMaterials = configSettings->value(String(configName + "/Materials/IgnoreMaterials").c_str());
  264. PopulateMaterialMaps = dAtob(configSettings->value(String(configName + "/Materials/PopulateMaterialMaps").c_str()));
  265. //Animations
  266. ImportAnimations = dAtob(configSettings->value(String(configName + "/Animations/ImportAnimations").c_str()));
  267. SeparateAnimations = dAtob(configSettings->value(String(configName + "/Animations/SeparateAnimations").c_str()));
  268. SeparateAnimationPrefix = configSettings->value(String(configName + "/Animations/SeparateAnimationPrefix").c_str());
  269. animTiming = configSettings->value(String(configName + "/Animations/animTiming").c_str());
  270. animFPS = dAtof(configSettings->value(String(configName + "/Animations/animFPS").c_str()));
  271. AlwaysAddShapeAnimationSuffix = dAtob(configSettings->value(String(configName + "/Animations/AlwaysAddShapeAnimationSuffix").c_str()));
  272. AddedShapeAnimationSuffix = configSettings->value(String(configName + "/Animations/AddedShapeAnimationSuffix").c_str());
  273. //Collisions
  274. GenerateCollisions = dAtob(configSettings->value(String(configName + "/Collision/GenerateCollisions").c_str()));
  275. GenCollisionType = configSettings->value(String(configName + "/Collision/GenCollisionType").c_str());
  276. CollisionMeshPrefix = configSettings->value(String(configName + "/Collision/CollisionMeshPrefix").c_str());
  277. GenerateLOSCollisions = dAtob(configSettings->value(String(configName + "/Collision/GenerateLOSCollisions").c_str()));
  278. GenLOSCollisionType = configSettings->value(String(configName + "/Collision/GenLOSCollisionType").c_str());
  279. LOSCollisionMeshPrefix = configSettings->value(String(configName + "/Collision/LOSCollisionMeshPrefix").c_str());
  280. //Images
  281. importImages = dAtob(configSettings->value(String(configName + "/Images/importImages").c_str()));
  282. AlwaysAddImageSuffix = dAtob(configSettings->value(String(configName + "/Images/AlwaysAddImageSuffix").c_str()));
  283. AddedImageSuffix = configSettings->value(String(configName + "/Images/AddedImageSuffix").c_str());
  284. ImageType = configSettings->value(String(configName + "/Images/ImageType").c_str());
  285. DiffuseTypeSuffixes = configSettings->value(String(configName + "/Images/DiffuseTypeSuffixes").c_str());
  286. NormalTypeSuffixes = configSettings->value(String(configName + "/Images/NormalTypeSuffixes").c_str());
  287. MetalnessTypeSuffixes = configSettings->value(String(configName + "/Images/MetalnessTypeSuffixes").c_str());
  288. RoughnessTypeSuffixes = configSettings->value(String(configName + "/Images/RoughnessTypeSuffixes").c_str());
  289. SmoothnessTypeSuffixes = configSettings->value(String(configName + "/Images/SmoothnessTypeSuffixes").c_str());
  290. AOTypeSuffixes = configSettings->value(String(configName + "/Images/AOTypeSuffixes").c_str());
  291. PBRTypeSuffixes = configSettings->value(String(configName + "/Images/PBRTypeSuffixes").c_str());
  292. TextureFilteringMode = configSettings->value(String(configName + "/Images/TextureFilteringMode").c_str());
  293. UseMips = dAtob(configSettings->value(String(configName + "/Images/UseMips").c_str()));
  294. IsHDR = dAtob(configSettings->value(String(configName + "/Images/IsHDR").c_str()));
  295. Scaling = dAtof(configSettings->value(String(configName + "/Images/Scaling").c_str()));
  296. ImagesCompressed = dAtob(configSettings->value(String(configName + "/Images/Compressed").c_str()));
  297. GenerateMaterialOnImport = dAtob(configSettings->value(String(configName + "/Images/GenerateMaterialOnImport").c_str()));
  298. //Sounds
  299. VolumeAdjust = dAtof(configSettings->value(String(configName + "/Sounds/VolumeAdjust").c_str()));
  300. PitchAdjust = dAtof(configSettings->value(String(configName + "/Sounds/PitchAdjust").c_str()));
  301. SoundsCompressed = dAtob(configSettings->value(String(configName + "/Sounds/Compressed").c_str()));
  302. AlwaysAddSoundSuffix = dAtob(configSettings->value(String(configName + "/Sounds/AlwaysAddSoundSuffix").c_str()));
  303. AddedSoundSuffix = configSettings->value(String(configName + "/Sounds/AddedSoundSuffix").c_str());
  304. }
  305. void AssetImportConfig::CopyTo(AssetImportConfig* target) const
  306. {
  307. target->DuplicateAutoResolution = DuplicateAutoResolution;
  308. target->WarningsAsErrors = WarningsAsErrors;
  309. target->PreventImportWithErrors = PreventImportWithErrors;
  310. target->AutomaticallyPromptMissingFiles = AutomaticallyPromptMissingFiles;
  311. target->AddDirectoryPrefixToAssetName = AddDirectoryPrefixToAssetName;
  312. //Meshes
  313. target->ImportMesh = ImportMesh;
  314. target->AlwaysAddShapeSuffix = AlwaysAddShapeSuffix;
  315. target->AddedShapeSuffix = AddedShapeSuffix;
  316. target->UseManualShapeConfigRules = UseManualShapeConfigRules;
  317. target->DoUpAxisOverride = DoUpAxisOverride;
  318. target->UpAxisOverride = UpAxisOverride;
  319. target->DoScaleOverride = DoScaleOverride;
  320. target->ScaleOverride = ScaleOverride;
  321. target->IgnoreNodeScale = IgnoreNodeScale;
  322. target->AdjustCenter = AdjustCenter;
  323. target->AdjustFloor = AdjustFloor;
  324. target->CollapseSubmeshes = CollapseSubmeshes;
  325. target->LODType = LODType;
  326. target->singleDetailSize = singleDetailSize;
  327. target->AlwaysImportedNodes = AlwaysImportedNodes;
  328. target->AlwaysIgnoreNodes = AlwaysIgnoreNodes;
  329. target->AlwaysImportMeshes = AlwaysImportMeshes;
  330. target->AlwaysIgnoreMeshes = AlwaysIgnoreMeshes;
  331. //Assimp/Collada
  332. target->convertLeftHanded = convertLeftHanded;
  333. target->calcTangentSpace = calcTangentSpace;
  334. target->removeRedundantMats = removeRedundantMats;
  335. target->genUVCoords = genUVCoords;
  336. target->TransformUVs = TransformUVs;
  337. target->flipUVCoords = flipUVCoords;
  338. target->findInstances = findInstances;
  339. target->limitBoneWeights = limitBoneWeights;
  340. target->JoinIdenticalVerts = JoinIdenticalVerts;
  341. target->reverseWindingOrder = reverseWindingOrder;
  342. target->invertNormals = invertNormals;
  343. //Materials
  344. target->ImportMaterials = ImportMaterials;
  345. target->AlwaysAddMaterialSuffix = AlwaysAddMaterialSuffix;
  346. target->AddedMaterialSuffix = AddedMaterialSuffix;
  347. target->CreateORMConfig = CreateORMConfig;
  348. target->UseDiffuseSuffixOnOriginImage = UseDiffuseSuffixOnOriginImage;
  349. target->UseExistingMaterials = UseExistingMaterials;
  350. target->IgnoreMaterials = IgnoreMaterials;
  351. target->PopulateMaterialMaps = PopulateMaterialMaps;
  352. //Animations
  353. target->ImportAnimations = ImportAnimations;
  354. target->SeparateAnimations = SeparateAnimations;
  355. target->SeparateAnimationPrefix = SeparateAnimationPrefix;
  356. target->animTiming = animTiming;
  357. target->animFPS = animFPS;
  358. target->AlwaysAddShapeAnimationSuffix = AlwaysAddShapeAnimationSuffix;
  359. target->AddedShapeAnimationSuffix = AddedShapeAnimationSuffix;
  360. //Collisions
  361. target->GenerateCollisions = GenerateCollisions;
  362. target->GenCollisionType = GenCollisionType;
  363. target->CollisionMeshPrefix = CollisionMeshPrefix;
  364. target->GenerateLOSCollisions = GenerateLOSCollisions;
  365. target->GenLOSCollisionType = GenLOSCollisionType;
  366. target->LOSCollisionMeshPrefix = LOSCollisionMeshPrefix;
  367. //Images
  368. target->importImages = importImages;
  369. target->AlwaysAddImageSuffix = AlwaysAddImageSuffix;
  370. target->AddedImageSuffix = AddedImageSuffix;
  371. target->ImageType = ImageType;
  372. target->DiffuseTypeSuffixes = DiffuseTypeSuffixes;
  373. target->NormalTypeSuffixes = NormalTypeSuffixes;
  374. target->MetalnessTypeSuffixes = MetalnessTypeSuffixes;
  375. target->RoughnessTypeSuffixes = RoughnessTypeSuffixes;
  376. target->SmoothnessTypeSuffixes = SmoothnessTypeSuffixes;
  377. target->AOTypeSuffixes = AOTypeSuffixes;
  378. target->PBRTypeSuffixes = PBRTypeSuffixes;
  379. target->TextureFilteringMode = TextureFilteringMode;
  380. target->UseMips = UseMips;
  381. target->IsHDR = IsHDR;
  382. target->Scaling = Scaling;
  383. target->ImagesCompressed = ImagesCompressed;
  384. target->GenerateMaterialOnImport = GenerateMaterialOnImport;
  385. //Sounds
  386. target->VolumeAdjust = VolumeAdjust;
  387. target->PitchAdjust = PitchAdjust;
  388. target->SoundsCompressed = SoundsCompressed;
  389. target->AlwaysAddSoundSuffix = AlwaysAddSoundSuffix;
  390. target->AddedSoundSuffix = AddedSoundSuffix;
  391. }
  392. ConsoleDocClass(AssetImportObject,
  393. "@brief Defines properties for an AssetImportObject object.\n"
  394. "@AssetImportObject is a SimObject derived object intended to act as a stand-in for the to-be imported objects.\n"
  395. "@It contains important info such as dependencies, if it's been processed, any error/status issues and the originating file\n"
  396. "@or if it's been programmatically generated as part of the import process.\n\n"
  397. "@ingroup Assets\n"
  398. );
  399. IMPLEMENT_CONOBJECT(AssetImportObject);
  400. AssetImportObject::AssetImportObject() :
  401. dirty(false),
  402. importStatus(AssetImportObject::NotProcessed),
  403. generatedAsset(false),
  404. parentAssetItem(nullptr),
  405. tamlFilePath(""),
  406. imageSuffixType(""),
  407. shapeInfo(nullptr),
  408. filePathString(StringTable->EmptyString())
  409. {
  410. }
  411. AssetImportObject::~AssetImportObject()
  412. {
  413. }
  414. bool AssetImportObject::onAdd()
  415. {
  416. if (!Parent::onAdd())
  417. return false;
  418. return true;
  419. }
  420. void AssetImportObject::onRemove()
  421. {
  422. Parent::onRemove();
  423. }
  424. void AssetImportObject::initPersistFields()
  425. {
  426. docsURL;
  427. Parent::initPersistFields();
  428. addField("assetType", TypeRealString, Offset(assetType, AssetImportObject), "What type is the importing asset");
  429. addProtectedField("filePath", TypeFilename, Offset(filePathString, AssetImportObject), &_setFilePath, &defaultProtectedGetFn, "What is the source file path of the importing asset");
  430. addField("assetName", TypeRealString, Offset(assetName, AssetImportObject), "What is the asset's name");
  431. addField("cleanAssetName", TypeRealString, Offset(cleanAssetName, AssetImportObject), "What is the original, unmodified by processing, asset name");
  432. addField("status", TypeRealString, Offset(status, AssetImportObject), "What is the current status of this asset item in it's import process");
  433. addField("statusType", TypeRealString, Offset(statusType, AssetImportObject), "If there is a warning or error status, what type is the condition for this asset item");
  434. addField("statusInfo", TypeRealString, Offset(statusInfo, AssetImportObject), "What is the articulated information of the status of the asset. Contains the error or warning log data");
  435. addField("dirty", TypeBool, Offset(dirty, AssetImportObject), "Is the asset item currently flagged as dirty");
  436. addField("generatedAsset", TypeBool, Offset(generatedAsset, AssetImportObject), "Is this specific asset item generated as part of the import process of another item");
  437. addField("tamlFilePath", TypeRealString, Offset(tamlFilePath, AssetImportObject), "What is the ultimate asset taml file path for this import item");
  438. addField("imageType", TypeRealString, Offset(imageSuffixType, AssetImportObject), "Specific to ImageAsset type. What is the image asset's suffix type. Options are: Albedo, Normal, Roughness, AO, Metalness, ORMConfig");
  439. addField("shapeInfo", TYPEID< GuiTreeViewCtrl >(), Offset(shapeInfo, AssetImportObject), "Specific to ShapeAsset type. Processed information about the shape file. Contains numbers and lists of meshes, materials and animations");
  440. }
  441. bool AssetImportObject::_setFilePath(void* obj, const char* index, const char* data)
  442. {
  443. AssetImportObject* importObj = static_cast<AssetImportObject*>(obj);
  444. importObj->setFilePath(StringTable->insert(data));
  445. return false;
  446. }
  447. void AssetImportObject::setFilePath(StringTableEntry pFilePath)
  448. {
  449. filePathString = pFilePath;
  450. filePath = Torque::Path(pFilePath);
  451. }
  452. ConsoleDocClass(AssetImporter,
  453. "@brief Defines properties for an AssetImportObject object.\n"
  454. "@AssetImportObject is a SimObject derived object intended to act as a stand-in for the to-be imported objects.\n"
  455. "@It contains important info such as dependencies, if it's been processed, any error/status issues and the originating file\n"
  456. "@or if it's been programmatically generated as part of the import process.\n\n"
  457. "@ingroup Assets\n"
  458. );
  459. IMPLEMENT_CONOBJECT(AssetImporter);
  460. AssetImporter::AssetImporter() :
  461. importIssues(false),
  462. isReimport(false),
  463. assetHeirarchyChanged(false),
  464. importLogBuffer(""),
  465. activeImportConfig(nullptr),
  466. mDumpLogs(true)
  467. {
  468. }
  469. AssetImporter::~AssetImporter()
  470. {
  471. }
  472. bool AssetImporter::onAdd()
  473. {
  474. if (!Parent::onAdd())
  475. return false;
  476. return true;
  477. }
  478. void AssetImporter::onRemove()
  479. {
  480. Parent::onRemove();
  481. }
  482. void AssetImporter::initPersistFields()
  483. {
  484. docsURL;
  485. Parent::initPersistFields();
  486. addField("targetModuleId", TypeRealString, Offset(targetModuleId, AssetImporter), "The Id of the module the assets are to be imported into");
  487. addField("finalImportedAssetPath", TypeRealString, Offset(finalImportedAssetPath, AssetImporter), "The Id of the module the assets are to be imported into");
  488. addField("targetPath", TypeRealString, Offset(targetPath, AssetImporter), "The path any imported assets are placed in as their destination");
  489. addField("dumpLogs", TypeBool, Offset(mDumpLogs, AssetImporter), "Indicates if the importer always dumps its logs or not");
  490. }
  491. //
  492. // Utility Functions
  493. //
  494. AssetImportObject* AssetImporter::addImportingFile(Torque::Path filePath)
  495. {
  496. String assetType = getAssetTypeByFile(filePath);
  497. if (assetType.isEmpty())
  498. {
  499. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Unable to import file %s because it is of an unrecognized/unsupported type.", filePath.getFullPath().c_str());
  500. activityLog.push_back(importLogBuffer);
  501. return nullptr;
  502. }
  503. AssetImportObject* newAssetItem = addImportingAsset(assetType, filePath, nullptr, "");
  504. originalImportingFiles.push_back(filePath);
  505. return newAssetItem;
  506. }
  507. void AssetImporter::addImportingAssetItem(AssetImportObject* assetItem, AssetImportObject* parentItem)
  508. {
  509. if (assetItem == nullptr)
  510. {
  511. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Cannot add a null AssetImportObject to import session!");
  512. activityLog.push_back(importLogBuffer);
  513. return;
  514. }
  515. if (parentItem != nullptr)
  516. {
  517. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Added Child Importing Asset to %s", parentItem->assetName.c_str());
  518. activityLog.push_back(importLogBuffer);
  519. parentItem->childAssetItems.push_back(assetItem);
  520. assetItem->parentAssetItem = parentItem;
  521. }
  522. else
  523. {
  524. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Added Importing Asset");
  525. activityLog.push_back(importLogBuffer);
  526. importingAssets.push_back(assetItem);
  527. }
  528. dSprintf(importLogBuffer, sizeof(importLogBuffer), " Asset Info: Name: %s | Type: %s", assetItem->assetName.c_str(), assetItem->assetType.c_str());
  529. activityLog.push_back(importLogBuffer);
  530. if (!assetItem->filePath.isEmpty())
  531. {
  532. dSprintf(importLogBuffer, sizeof(importLogBuffer), " File: %s", assetItem->filePath.getFullPath().c_str());
  533. activityLog.push_back(importLogBuffer);
  534. }
  535. }
  536. AssetImportObject* AssetImporter::addImportingAsset(String assetType, Torque::Path filePath, AssetImportObject* parentItem, String assetNameOverride)
  537. {
  538. String assetName;
  539. String origionalName;
  540. //In some cases(usually generated assets on import, like materials) we'll want to specifically define the asset name instead of peeled from the filePath
  541. if (assetNameOverride.isNotEmpty())
  542. assetName = assetNameOverride;
  543. else
  544. assetName = filePath.getFileName();
  545. AssetImportObject* assetImportObj = new AssetImportObject();
  546. assetImportObj->registerObject();
  547. //sanitize
  548. String processedString = assetName;
  549. U32 start;
  550. U32 end;
  551. String firstNumber = String::GetFirstNumber(processedString, start, end);
  552. if (!firstNumber.isEmpty() && processedString.startsWith(firstNumber.c_str()))
  553. processedString = processedString.replace(firstNumber, "");
  554. processedString = processedString.replace(" ", "_");
  555. U32 len = processedString.length() + 1;
  556. char* sanitizedStr = Con::getReturnBuffer(len);
  557. dStrcpy(sanitizedStr, processedString.c_str(), len);
  558. U32 pos = dStrcspn(sanitizedStr, "-+*/%$&�=()[].?\\\"#,;!~<>|�^{}");
  559. while (pos < dStrlen(sanitizedStr))
  560. {
  561. dStrcpy(sanitizedStr + pos, sanitizedStr + pos + 1, (dsize_t)(len - pos));
  562. pos = dStrcspn(sanitizedStr, "-+*/%$&�=()[].?\\\"#,;!~<>|�^{}");
  563. }
  564. origionalName = assetName;
  565. //If we did, indeed, modify the name, update it now
  566. if (String(sanitizedStr) != assetName)
  567. {
  568. assetName = sanitizedStr;
  569. }
  570. assetImportObj->assetType = assetType;
  571. assetImportObj->filePath = filePath;
  572. assetImportObj->filePathString = StringTable->insert(filePath.getFullPath().c_str());
  573. assetImportObj->assetName = assetName;
  574. assetImportObj->cleanAssetName = origionalName;
  575. assetImportObj->moduleName = targetModuleId;
  576. assetImportObj->status = "";
  577. assetImportObj->statusType = "";
  578. assetImportObj->statusInfo = "";
  579. assetImportObj->dirty = false;
  580. assetImportObj->importStatus = AssetImportObject::NotProcessed;
  581. assetImportObj->generatedAsset = false;
  582. //If the config is marked to always set the directory prefix, do that now
  583. if (activeImportConfig->AddDirectoryPrefixToAssetName)
  584. {
  585. assetName = getFolderPrefixedName(assetImportObj);
  586. assetImportObj->assetName = assetName;
  587. assetImportObj->cleanAssetName = assetName;
  588. }
  589. if (parentItem != nullptr)
  590. {
  591. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Added Child Importing Asset to %s", parentItem->assetName.c_str());
  592. activityLog.push_back(importLogBuffer);
  593. parentItem->childAssetItems.push_back(assetImportObj);
  594. assetImportObj->parentAssetItem = parentItem;
  595. }
  596. else
  597. {
  598. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Added Importing Asset");
  599. activityLog.push_back(importLogBuffer);
  600. importingAssets.push_back(assetImportObj);
  601. }
  602. dSprintf(importLogBuffer, sizeof(importLogBuffer), " Asset Info: Name: %s | Type: %s", assetImportObj->assetName.c_str(), assetImportObj->assetType.c_str());
  603. activityLog.push_back(importLogBuffer);
  604. if (!filePath.isEmpty())
  605. {
  606. dSprintf(importLogBuffer, sizeof(importLogBuffer), " File: %s", filePath.getFullPath().c_str());
  607. activityLog.push_back(importLogBuffer);
  608. }
  609. return assetImportObj;
  610. }
  611. void AssetImporter::deleteImportingAsset(AssetImportObject* assetItem)
  612. {
  613. assetItem->importStatus = AssetImportObject::Skipped;
  614. //log it
  615. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Deleting Importing Asset %s and all it's child items", assetItem->assetName.c_str());
  616. activityLog.push_back(importLogBuffer);
  617. }
  618. AssetImportObject* AssetImporter::findImportingAssetByName(String assetName, AssetImportObject* assetItem)
  619. {
  620. Vector<AssetImportObject*> itemList = importingAssets;
  621. if (assetItem != nullptr)
  622. itemList = assetItem->childAssetItems;
  623. for (U32 i = 0; i < itemList.size(); i++)
  624. {
  625. if (itemList[i]->cleanAssetName == assetName)
  626. {
  627. return itemList[i];
  628. }
  629. //If it wasn't a match, try recusing on the children(if any)
  630. AssetImportObject* retItem = findImportingAssetByName(assetName, itemList[i]);
  631. if (retItem != nullptr)
  632. return retItem;
  633. }
  634. return nullptr;
  635. }
  636. ModuleDefinition* AssetImporter::getModuleFromPath(Torque::Path filePath)
  637. {
  638. // Use a relative path so modules on mounted file systems will be found.
  639. ModuleDefinition* moduleDef = ModuleDatabase.findModuleByFilePath(Platform::makeRelativePathName(filePath.getFullPath().c_str(), NULL));
  640. return moduleDef;
  641. }
  642. String AssetImporter::parseImageSuffixes(String assetName, String* suffixType)
  643. {
  644. //Here, we loop over our different suffix lists progressively.
  645. //This lets us walk through a list of suffixes in the Import Config, such as DiffuseTypeSuffixes
  646. //And then iterate over the delinated list of items within it to look for a match.
  647. //If we don't find a match, we then increment our list switch index and scan through the next list.
  648. U32 suffixTypeIdx = 0;
  649. while (suffixTypeIdx < 6)
  650. {
  651. String suffixList;
  652. switch (suffixTypeIdx)
  653. {
  654. case 0:
  655. suffixList = activeImportConfig->DiffuseTypeSuffixes;
  656. suffixType->insert(0, "Albedo", 6);
  657. break;
  658. case 1:
  659. suffixList = activeImportConfig->NormalTypeSuffixes;
  660. suffixType->insert(0, "Normal", 6);
  661. break;
  662. case 2:
  663. suffixList = activeImportConfig->RoughnessTypeSuffixes;
  664. suffixType->insert(0, "Roughness", 9);
  665. break;
  666. case 3:
  667. suffixList = activeImportConfig->AOTypeSuffixes;
  668. suffixType->insert(0, "AO", 2);
  669. break;
  670. case 4:
  671. suffixList = activeImportConfig->MetalnessTypeSuffixes;
  672. suffixType->insert(0, "Metalness", 9);
  673. break;
  674. case 5:
  675. suffixList = activeImportConfig->PBRTypeSuffixes;
  676. suffixType->insert(0, "ORMConfig", 9);
  677. break;
  678. default:
  679. suffixList = "";
  680. }
  681. suffixTypeIdx++;
  682. U32 suffixCount = StringUnit::getUnitCount(suffixList, ",;\t");
  683. for (U32 i = 0; i < suffixCount; i++)
  684. {
  685. String suffix = StringUnit::getUnit(suffixList, i, ",;\t");
  686. String searchSuffix = String("*") + suffix;
  687. if (FindMatch::isMatch(searchSuffix.c_str(), assetName.c_str(), false))
  688. {
  689. //We have a match, so indicate as such
  690. S32 pos = assetName.length();
  691. pos -= searchSuffix.length();
  692. suffix = assetName.substr(pos+1);
  693. return suffix;
  694. }
  695. }
  696. }
  697. suffixType->clear();
  698. return "";
  699. }
  700. String AssetImporter::getAssetTypeByFile(Torque::Path filePath)
  701. {
  702. String fileExt = String::ToLower(filePath.getExtension());
  703. String fileName = String::ToLower(filePath.getFileName());
  704. if (fileExt == String("dts") && fileName.endsWith("cached"))
  705. return "";
  706. if (fileExt == String("png") || fileExt == String("jpg") || fileExt == String("jpeg") || fileExt == String("dds"))
  707. return "ImageAsset";
  708. else if (fileExt == String("dae") || fileExt == String("fbx") || fileExt == String("blend") || fileExt == String("obj") || fileExt == String("dts") || fileExt == String("gltf") || fileExt == String("glb"))
  709. return "ShapeAsset";
  710. else if (fileExt == String("dsq"))
  711. return "ShapeAnimationAsset";
  712. else if (fileExt == String("ogg") || fileExt == String("wav") || fileExt == String("mp3"))
  713. return "SoundAsset";
  714. else if (fileExt == String("zip"))
  715. return "Zip";
  716. else if (fileExt.isEmpty())
  717. return "Folder";
  718. return "";
  719. }
  720. String AssetImporter::getTrueFilename(const String& fileName)
  721. {
  722. Torque::Path pth(fileName);
  723. String pattern = pth.getFullPath() + "*";
  724. static const String sSlash("/");
  725. Vector<String> findFilesResults;
  726. String sPattern(Torque::Path::CleanSeparators(pattern));
  727. if (sPattern.isEmpty())
  728. {
  729. Con::errorf("findFirstFile() requires a search pattern");
  730. return "";
  731. }
  732. char scriptFilenameBuffer[1024];
  733. if (!Con::expandScriptFilename(scriptFilenameBuffer, sizeof(scriptFilenameBuffer), sPattern.c_str()))
  734. {
  735. Con::errorf("findFirstFile() given initial directory cannot be expanded: '%s'", pattern.c_str());
  736. return "";
  737. }
  738. sPattern = String::ToString(scriptFilenameBuffer);
  739. String::SizeType slashPos = sPattern.find('/', 0, String::Right);
  740. // if(slashPos == String::NPos)
  741. // {
  742. // Con::errorf("findFirstFile() missing search directory or expression: '%s'", sPattern.c_str());
  743. // return -1;
  744. // }
  745. // Build the initial search path
  746. Torque::Path givenPath(Torque::Path::CompressPath(sPattern));
  747. givenPath.setFileName("*");
  748. givenPath.setExtension("*");
  749. if (givenPath.getPath().length() > 0 && givenPath.getPath().find('*', 0, String::Right) == givenPath.getPath().length() - 1)
  750. {
  751. // Deal with legacy searches of the form '*/*.*'
  752. String suspectPath = givenPath.getPath();
  753. String::SizeType newLen = suspectPath.length() - 1;
  754. if (newLen > 0 && suspectPath.find('/', 0, String::Right) == suspectPath.length() - 2)
  755. {
  756. --newLen;
  757. }
  758. givenPath.setPath(suspectPath.substr(0, newLen));
  759. }
  760. Torque::FS::FileSystemRef fs = Torque::FS::GetFileSystem(givenPath);
  761. //Torque::Path path = fs->mapTo(givenPath);
  762. Torque::Path path = givenPath;
  763. // Make sure that we have a root so the correct file system can be determined when using zips
  764. if (givenPath.isRelative())
  765. path = Torque::Path::Join(Torque::FS::GetCwd(), '/', givenPath);
  766. path.setFileName(String::EmptyString);
  767. path.setExtension(String::EmptyString);
  768. if (!Torque::FS::IsDirectory(path))
  769. {
  770. Con::errorf("findFirstFile() invalid initial search directory: '%s'", path.getFullPath().c_str());
  771. return "";
  772. }
  773. // Build the search expression
  774. const String expression(slashPos != String::NPos ? sPattern.substr(slashPos + 1) : sPattern);
  775. if (expression.isEmpty())
  776. {
  777. Con::errorf("findFirstFile() requires a search expression: '%s'", sPattern.c_str());
  778. return "";
  779. }
  780. S32 results = Torque::FS::FindByPattern(path, expression, false, findFilesResults, false);
  781. if (givenPath.isRelative() && results > 0)
  782. {
  783. // Strip the CWD out of the returned paths
  784. // MakeRelativePath() returns incorrect results (it adds a leading ..) so doing this the dirty way
  785. const String cwd = Torque::FS::GetCwd().getFullPath();
  786. for (S32 i = 0; i < findFilesResults.size(); ++i)
  787. {
  788. String str = findFilesResults[i];
  789. if (str.compare(cwd, cwd.length(), String::NoCase) == 0)
  790. str = str.substr(cwd.length());
  791. findFilesResults[i] = str;
  792. }
  793. }
  794. for (U32 i = 0; i < findFilesResults.size(); i++)
  795. {
  796. if (!findFilesResults[i].compare(fileName, 0, String::NoCase|String::Left))
  797. return findFilesResults[i];
  798. }
  799. return "";
  800. }
  801. void AssetImporter::resetImportSession(bool hardClearSession)
  802. {
  803. importingAssets.clear();
  804. activityLog.clear();
  805. if (hardClearSession)
  806. {
  807. originalImportingFiles.clear();
  808. }
  809. else
  810. {
  811. Vector<Torque::Path> tempImportingFiles = originalImportingFiles;
  812. originalImportingFiles.clear();
  813. for (U32 i = 0; i < tempImportingFiles.size(); i++)
  814. {
  815. addImportingFile(tempImportingFiles[i]);
  816. }
  817. }
  818. }
  819. S32 AssetImporter::getActivityLogLineCount()
  820. {
  821. return activityLog.size();
  822. }
  823. String AssetImporter::getActivityLogLine(U32 line)
  824. {
  825. if (line >= activityLog.size())
  826. return "";
  827. return activityLog[line];
  828. }
  829. void AssetImporter::dumpActivityLog()
  830. {
  831. if (!mDumpLogs)
  832. return;
  833. FileObject logFile;
  834. //If there's nothing logged, don't bother
  835. if (activityLog.size() == 0)
  836. return;
  837. Torque::Time::DateTime curTime;
  838. Torque::Time::getCurrentDateTime(curTime);
  839. String logName = String("tools/logs/AssetImportLog_") + String::ToString(curTime.year + 1900) + "-" +
  840. String::ToString(curTime.month + 1) + "-" + String::ToString(curTime.day) + "_" +
  841. String::ToString(curTime.hour) + "-" + String::ToString(curTime.minute) + "-" + String::ToString(curTime.second)
  842. + "-" + String::ToString(curTime.microsecond) + ".log";
  843. if (logFile.openForWrite(logName.c_str()))
  844. {
  845. for (U32 i = 0; i < activityLog.size(); i++)
  846. {
  847. logFile.writeLine((const U8*)activityLog[i].c_str());
  848. }
  849. logFile.close();
  850. Con::warnf("Asset Import log file dumped to: %s", logName.c_str());
  851. }
  852. else
  853. {
  854. Con::errorf("Error: Failed to open log file for writing! Dumping log results to console!");
  855. for (U32 i = 0; i < activityLog.size(); i++)
  856. {
  857. Con::printf(activityLog[i].c_str());
  858. }
  859. }
  860. }
  861. S32 AssetImporter::getAssetItemCount()
  862. {
  863. return importingAssets.size();
  864. }
  865. AssetImportObject* AssetImporter::getAssetItem(U32 index)
  866. {
  867. if (index >= importingAssets.size())
  868. return nullptr;
  869. return importingAssets[index];
  870. }
  871. S32 AssetImporter::getAssetItemChildCount(AssetImportObject* assetItem)
  872. {
  873. return assetItem->childAssetItems.size();
  874. }
  875. AssetImportObject* AssetImporter::getAssetItemChild(AssetImportObject* assetItem, U32 index)
  876. {
  877. if (index >= assetItem->childAssetItems.size())
  878. return nullptr;
  879. return assetItem->childAssetItems[index];
  880. }
  881. //
  882. // Processing
  883. //
  884. // Helper struct for counting nodes, meshes and polygons down through the scene
  885. // hierarchy
  886. struct SceneStats
  887. {
  888. S32 numNodes;
  889. S32 numMeshes;
  890. S32 numPolygons;
  891. S32 numMaterials;
  892. S32 numLights;
  893. S32 numClips;
  894. SceneStats() : numNodes(0), numMeshes(0), numPolygons(0), numMaterials(0), numLights(0), numClips(0) { }
  895. };
  896. // Recurse through the <visual_scene> adding nodes and geometry to the GuiTreeView control
  897. static void processNode(GuiTreeViewCtrl* tree, domNode* node, S32 parentID, SceneStats& stats)
  898. {
  899. stats.numNodes++;
  900. S32 nodeID = tree->insertItem(parentID, _GetNameOrId(node), "node", "", 0, 0);
  901. // Update mesh and poly counts
  902. for (S32 i = 0; i < node->getContents().getCount(); i++)
  903. {
  904. domGeometry* geom = 0;
  905. const char* elemName = "";
  906. daeElement* child = node->getContents()[i];
  907. switch (child->getElementType())
  908. {
  909. case COLLADA_TYPE::INSTANCE_GEOMETRY:
  910. {
  911. domInstance_geometry* instgeom = daeSafeCast<domInstance_geometry>(child);
  912. if (instgeom)
  913. {
  914. geom = daeSafeCast<domGeometry>(instgeom->getUrl().getElement());
  915. elemName = _GetNameOrId(geom);
  916. }
  917. break;
  918. }
  919. case COLLADA_TYPE::INSTANCE_CONTROLLER:
  920. {
  921. domInstance_controller* instctrl = daeSafeCast<domInstance_controller>(child);
  922. if (instctrl)
  923. {
  924. domController* ctrl = daeSafeCast<domController>(instctrl->getUrl().getElement());
  925. elemName = _GetNameOrId(ctrl);
  926. if (ctrl && ctrl->getSkin())
  927. geom = daeSafeCast<domGeometry>(ctrl->getSkin()->getSource().getElement());
  928. else if (ctrl && ctrl->getMorph())
  929. geom = daeSafeCast<domGeometry>(ctrl->getMorph()->getSource().getElement());
  930. }
  931. break;
  932. }
  933. case COLLADA_TYPE::INSTANCE_LIGHT:
  934. stats.numLights++;
  935. tree->insertItem(nodeID, _GetNameOrId(node), "light", "", 0, 0);
  936. break;
  937. }
  938. if (geom && geom->getMesh())
  939. {
  940. const char* name = _GetNameOrId(node);
  941. if (dStrEqual(name, "null") || dStrEndsWith(name, "PIVOT"))
  942. name = _GetNameOrId(daeSafeCast<domNode>(node->getParent()));
  943. stats.numMeshes++;
  944. tree->insertItem(nodeID, name, "mesh", "", 0, 0);
  945. for (S32 j = 0; j < geom->getMesh()->getTriangles_array().getCount(); j++)
  946. stats.numPolygons += geom->getMesh()->getTriangles_array()[j]->getCount();
  947. for (S32 j = 0; j < geom->getMesh()->getTristrips_array().getCount(); j++)
  948. stats.numPolygons += geom->getMesh()->getTristrips_array()[j]->getCount();
  949. for (S32 j = 0; j < geom->getMesh()->getTrifans_array().getCount(); j++)
  950. stats.numPolygons += geom->getMesh()->getTrifans_array()[j]->getCount();
  951. for (S32 j = 0; j < geom->getMesh()->getPolygons_array().getCount(); j++)
  952. stats.numPolygons += geom->getMesh()->getPolygons_array()[j]->getCount();
  953. for (S32 j = 0; j < geom->getMesh()->getPolylist_array().getCount(); j++)
  954. stats.numPolygons += geom->getMesh()->getPolylist_array()[j]->getCount();
  955. }
  956. }
  957. // Recurse into child nodes
  958. for (S32 i = 0; i < node->getNode_array().getCount(); i++)
  959. processNode(tree, node->getNode_array()[i], nodeID, stats);
  960. for (S32 i = 0; i < node->getInstance_node_array().getCount(); i++)
  961. {
  962. domInstance_node* instnode = node->getInstance_node_array()[i];
  963. domNode* dNode = daeSafeCast<domNode>(instnode->getUrl().getElement());
  964. if (dNode)
  965. processNode(tree, dNode, nodeID, stats);
  966. }
  967. }
  968. static bool enumColladaForImport(const char* shapePath, GuiTreeViewCtrl* tree, bool loadCachedDts)
  969. {
  970. // Check if a cached DTS is available => no need to import the collada file
  971. // if we can load the DTS instead
  972. Torque::Path path(shapePath);
  973. if (loadCachedDts && ColladaShapeLoader::canLoadCachedDTS(path))
  974. return false;
  975. // Check if this is a Sketchup file (.kmz) and if so, mount the zip filesystem
  976. // and get the path to the DAE file.
  977. String mountPoint;
  978. Torque::Path daePath;
  979. bool isSketchup = ColladaShapeLoader::checkAndMountSketchup(path, mountPoint, daePath);
  980. // Load the Collada file into memory
  981. domCOLLADA* root = ColladaShapeLoader::getDomCOLLADA(daePath);
  982. if (!root)
  983. {
  984. TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
  985. return false;
  986. }
  987. if (isSketchup)
  988. {
  989. // Unmount the zip if we mounted it
  990. Torque::FS::Unmount(mountPoint);
  991. }
  992. // Initialize tree
  993. tree->removeItem(0);
  994. S32 nodesID = tree->insertItem(0, "Shape", "", "", 0, 0);
  995. S32 matsID = tree->insertItem(0, "Materials", "", "", 0, 0);
  996. S32 animsID = tree->insertItem(0, "Animations", "", "", 0, 0);
  997. SceneStats stats;
  998. // Query DOM for shape summary details
  999. for (S32 i = 0; i < root->getLibrary_visual_scenes_array().getCount(); i++)
  1000. {
  1001. const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[i];
  1002. for (S32 j = 0; j < libScenes->getVisual_scene_array().getCount(); j++)
  1003. {
  1004. const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[j];
  1005. for (S32 k = 0; k < visualScene->getNode_array().getCount(); k++)
  1006. processNode(tree, visualScene->getNode_array()[k], nodesID, stats);
  1007. }
  1008. }
  1009. // Get material count
  1010. for (S32 i = 0; i < root->getLibrary_materials_array().getCount(); i++)
  1011. {
  1012. const domLibrary_materials* libraryMats = root->getLibrary_materials_array()[i];
  1013. stats.numMaterials += (S32)libraryMats->getMaterial_array().getCount();
  1014. for (S32 j = 0; j < libraryMats->getMaterial_array().getCount(); j++)
  1015. {
  1016. domMaterial* mat = libraryMats->getMaterial_array()[j];
  1017. tree->insertItem(matsID, _GetNameOrId(mat), "", "", 0, 0);
  1018. }
  1019. }
  1020. // Get images count
  1021. for (S32 i = 0; i < root->getLibrary_images_array().getCount(); i++)
  1022. {
  1023. const domLibrary_images* libraryImages = root->getLibrary_images_array()[i];
  1024. for (S32 j = 0; j < libraryImages->getImage_array().getCount(); j++)
  1025. {
  1026. domImage* img = libraryImages->getImage_array()[j];
  1027. String imageName = _GetNameOrId(img);
  1028. S32 materialID = tree->findItemByName(imageName.c_str());
  1029. if (materialID == 0)
  1030. {
  1031. bool materialFound = false;
  1032. String matName = "";
  1033. //If we don't have an immediate name match, we'll have to actually go look it up
  1034. for (S32 e = 0; e < root->getLibrary_effects_array().getCount(); e++)
  1035. {
  1036. const domLibrary_effects* libraryEffects = root->getLibrary_effects_array()[e];
  1037. for (S32 f = 0; f < libraryEffects->getEffect_array().getCount(); f++)
  1038. {
  1039. domEffect* efct = libraryEffects->getEffect_array()[f];
  1040. String effectName = efct->getID();
  1041. for (S32 p = 0; p < efct->getFx_profile_abstract_array().getCount(); p++)
  1042. {
  1043. domProfile_COMMON* profile = daeSafeCast<domProfile_COMMON>(efct->getFx_profile_abstract_array()[p]);
  1044. for (S32 n = 0; n < profile->getNewparam_array().getCount(); n++)
  1045. {
  1046. domCommon_newparam_typeRef param = profile->getNewparam_array()[n];
  1047. String paramName = param->getSid();
  1048. if (paramName.endsWith("-surface"))
  1049. {
  1050. //ok it's surface data, parse out the name
  1051. String surfaceName = paramName.substr(0, paramName.length() - 8);
  1052. if (surfaceName == imageName)
  1053. {
  1054. //got a match!
  1055. matName = effectName;
  1056. if (matName.endsWith("-effect"))
  1057. {
  1058. matName = matName.substr(0, matName.length() - 7);
  1059. materialFound = true;
  1060. break;
  1061. }
  1062. }
  1063. }
  1064. }
  1065. if (materialFound)
  1066. break;
  1067. }
  1068. if (materialFound)
  1069. {
  1070. materialID = tree->findItemByName(matName.c_str());
  1071. }
  1072. if (materialID != 0)
  1073. break;
  1074. }
  1075. }
  1076. //if we STILL haven't found a match, then yes, we've failed
  1077. if (materialID == 0)
  1078. continue;
  1079. }
  1080. String imagePath = img->getInit_from()->getValue().str().c_str();
  1081. if (imagePath.startsWith("/"))
  1082. imagePath = imagePath.substr(1, imagePath.length() - 1);
  1083. tree->setItemValue(materialID, StringTable->insert(imagePath.c_str()));
  1084. }
  1085. }
  1086. // Get animation count
  1087. for (S32 i = 0; i < root->getLibrary_animation_clips_array().getCount(); i++)
  1088. {
  1089. const domLibrary_animation_clips* libraryClips = root->getLibrary_animation_clips_array()[i];
  1090. stats.numClips += (S32)libraryClips->getAnimation_clip_array().getCount();
  1091. for (S32 j = 0; j < libraryClips->getAnimation_clip_array().getCount(); j++)
  1092. {
  1093. domAnimation_clip* clip = libraryClips->getAnimation_clip_array()[j];
  1094. tree->insertItem(animsID, _GetNameOrId(clip), "animation", "", 0, 0);
  1095. }
  1096. }
  1097. if (stats.numClips == 0)
  1098. {
  1099. // No clips => check if there are any animations (these will be added to a default clip)
  1100. for (S32 i = 0; i < root->getLibrary_animations_array().getCount(); i++)
  1101. {
  1102. const domLibrary_animations* libraryAnims = root->getLibrary_animations_array()[i];
  1103. if (libraryAnims->getAnimation_array().getCount())
  1104. {
  1105. stats.numClips = 1;
  1106. tree->insertItem(animsID, "ambient", "animation", "", 0, 0);
  1107. break;
  1108. }
  1109. }
  1110. }
  1111. // Extract the global scale and up_axis from the top level <asset> element,
  1112. F32 unit = 1.0f;
  1113. domUpAxisType upAxis = UPAXISTYPE_Z_UP;
  1114. if (root->getAsset()) {
  1115. if (root->getAsset()->getUnit())
  1116. unit = root->getAsset()->getUnit()->getMeter();
  1117. if (root->getAsset()->getUp_axis())
  1118. upAxis = root->getAsset()->getUp_axis()->getValue();
  1119. }
  1120. TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
  1121. // Store shape information in the tree control
  1122. tree->setDataField(StringTable->insert("_nodeCount"), 0, avar("%d", stats.numNodes));
  1123. tree->setDataField(StringTable->insert("_meshCount"), 0, avar("%d", stats.numMeshes));
  1124. tree->setDataField(StringTable->insert("_polygonCount"), 0, avar("%d", stats.numPolygons));
  1125. tree->setDataField(StringTable->insert("_materialCount"), 0, avar("%d", stats.numMaterials));
  1126. tree->setDataField(StringTable->insert("_lightCount"), 0, avar("%d", stats.numLights));
  1127. tree->setDataField(StringTable->insert("_animCount"), 0, avar("%d", stats.numClips));
  1128. tree->setDataField(StringTable->insert("_unit"), 0, avar("%g", unit));
  1129. if (upAxis == UPAXISTYPE_X_UP)
  1130. tree->setDataField(StringTable->insert("_upAxis"), 0, "X_AXIS");
  1131. else if (upAxis == UPAXISTYPE_Y_UP)
  1132. tree->setDataField(StringTable->insert("_upAxis"), 0, "Y_AXIS");
  1133. else
  1134. tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
  1135. char shapesStr[16];
  1136. dSprintf(shapesStr, 16, "%i", stats.numMeshes);
  1137. char materialsStr[16];
  1138. dSprintf(materialsStr, 16, "%i", stats.numMaterials);
  1139. char animationsStr[16];
  1140. dSprintf(animationsStr, 16, "%i", stats.numClips);
  1141. tree->setItemValue(nodesID, StringTable->insert(shapesStr));
  1142. tree->setItemValue(matsID, StringTable->insert(materialsStr));
  1143. tree->setItemValue(animsID, StringTable->insert(animationsStr));
  1144. return true;
  1145. }
  1146. static bool enumDTSForImport(const char* shapePath, GuiTreeViewCtrl* tree)
  1147. {
  1148. // Check if a cached DTS is available => no need to import the collada file
  1149. // if we can load the DTS instead
  1150. Torque::Path path(shapePath);
  1151. Resource<TSShape> dtsShape = ResourceManager::get().load(shapePath);
  1152. if (!dtsShape)
  1153. return false;
  1154. // Initialize tree
  1155. tree->removeItem(0);
  1156. S32 nodesID = tree->insertItem(0, "Shape", "", "", 0, 0);
  1157. S32 matsID = tree->insertItem(0, "Materials", "", "", 0, 0);
  1158. S32 animsID = tree->insertItem(0, "Animations", "", "", 0, 0);
  1159. SceneStats stats;
  1160. // Query DOM for shape summary details
  1161. for (S32 i = 0; i < dtsShape->objects.size(); i++)
  1162. {
  1163. tree->insertItem(nodesID, dtsShape->names[dtsShape->objects[i].nameIndex], "", "", 0, 0);
  1164. stats.numMeshes++;
  1165. }
  1166. // Get material count
  1167. for (S32 i = 0; i < dtsShape->materialList->size(); i++)
  1168. {
  1169. S32 matId = tree->insertItem(matsID, dtsShape->materialList->getMaterialName(i).c_str(), "", "", 0, 0);
  1170. stats.numMaterials++;
  1171. GFXTextureObject* difTex = dtsShape->materialList->getDiffuseTexture(i);
  1172. if (difTex)
  1173. {
  1174. tree->insertItem(matId, difTex->getPath().c_str(), "", "", 0, 0);
  1175. }
  1176. }
  1177. // Get animation count
  1178. for (S32 i = 0; i < dtsShape->sequences.size(); i++)
  1179. {
  1180. tree->insertItem(animsID, dtsShape->names[dtsShape->sequences[i].nameIndex], "animation", "", 0, 0);
  1181. stats.numClips++;
  1182. }
  1183. /*if (stats.numClips == 0)
  1184. {
  1185. // No clips => check if there are any animations (these will be added to a default clip)
  1186. for (S32 i = 0; i < root->getLibrary_animations_array().getCount(); i++)
  1187. {
  1188. const domLibrary_animations* libraryAnims = root->getLibrary_animations_array()[i];
  1189. if (libraryAnims->getAnimation_array().getCount())
  1190. {
  1191. stats.numClips = 1;
  1192. tree->insertItem(animsID, "ambient", "animation", "", 0, 0);
  1193. break;
  1194. }
  1195. }
  1196. }*/
  1197. F32 unit = 1.0f;
  1198. // Store shape information in the tree control
  1199. tree->setDataField(StringTable->insert("_nodeCount"), 0, avar("%d", stats.numNodes));
  1200. tree->setDataField(StringTable->insert("_meshCount"), 0, avar("%d", stats.numMeshes));
  1201. tree->setDataField(StringTable->insert("_polygonCount"), 0, avar("%d", stats.numPolygons));
  1202. tree->setDataField(StringTable->insert("_materialCount"), 0, avar("%d", stats.numMaterials));
  1203. tree->setDataField(StringTable->insert("_lightCount"), 0, avar("%d", stats.numLights));
  1204. tree->setDataField(StringTable->insert("_animCount"), 0, avar("%d", stats.numClips));
  1205. tree->setDataField(StringTable->insert("_unit"), 0, avar("%g", unit));
  1206. tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
  1207. char shapesStr[16];
  1208. dSprintf(shapesStr, 16, "%i", stats.numMeshes);
  1209. char materialsStr[16];
  1210. dSprintf(materialsStr, 16, "%i", stats.numMaterials);
  1211. char animationsStr[16];
  1212. dSprintf(animationsStr, 16, "%i", stats.numClips);
  1213. tree->setItemValue(nodesID, StringTable->insert(shapesStr));
  1214. tree->setItemValue(matsID, StringTable->insert(materialsStr));
  1215. tree->setItemValue(animsID, StringTable->insert(animationsStr));
  1216. return true;
  1217. }
  1218. void AssetImportConfig::loadSISFile(Torque::Path filePath)
  1219. {
  1220. String settingsFilePath = "Tools";
  1221. Settings* editorSettings;
  1222. //See if we can get our editor settings
  1223. if (Sim::findObject("EditorSettings", editorSettings))
  1224. {
  1225. settingsFilePath = editorSettings->value("defaultSettingsPath", "Tools");
  1226. }
  1227. String fileExtension = filePath.getExtension();
  1228. String settingsFile = settingsFilePath + "/" + fileExtension + ".sis";
  1229. FileObject* fileObj = new FileObject();
  1230. if (Torque::FS::IsFile(settingsFile))
  1231. {
  1232. if (!fileObj->readMemory(settingsFile.c_str()))
  1233. {
  1234. Con::errorf("AssetImporter::loadSISFile() - Error opening file to load settings: %s", settingsFile.c_str());
  1235. fileObj->deleteObject();
  1236. return;
  1237. }
  1238. }
  1239. else
  1240. {
  1241. return;
  1242. }
  1243. String headerLine = (const char*)fileObj->readLine();
  1244. if (headerLine.substr(0, 4).compare("SISV", 0U, String::NoCase) != 0)
  1245. return; //not a sis file?
  1246. while (!fileObj->isEOF())
  1247. {
  1248. const char* line = (const char*)fileObj->readLine();
  1249. String key = StringUnit::getUnit(line, 0, "\t");
  1250. String value = StringUnit::getUnit(line, 1, "\t");
  1251. if (key.compare("DoUpAxisOverride", 0U, String::NoCase) == 0)
  1252. DoUpAxisOverride = dAtob(value.c_str());
  1253. else if (key.compare("UpAxisOverride", 0U, String::NoCase) == 0)
  1254. UpAxisOverride = value.c_str();
  1255. else if (key.compare("DoScaleOverride", 0U, String::NoCase) == 0)
  1256. DoScaleOverride = dAtob(value.c_str());
  1257. else if (key.compare("ScaleOverride", 0U, String::NoCase) == 0)
  1258. ScaleOverride = dAtof(value.c_str());
  1259. else if (key.compare("IgnoreNodeScale", 0U, String::NoCase) == 0)
  1260. IgnoreNodeScale = dAtob(value.c_str());
  1261. else if (key.compare("AdjustCenter", 0U, String::NoCase) == 0)
  1262. AdjustCenter = dAtob(value.c_str());
  1263. else if (key.compare("AdjustFloor", 0U, String::NoCase) == 0)
  1264. AdjustFloor = dAtob(value.c_str());
  1265. else if (key.compare("CollapseSubmeshes", 0U, String::NoCase) == 0)
  1266. CollapseSubmeshes = dAtob(value.c_str());
  1267. else if (key.compare("LODType", 0U, String::NoCase) == 0)
  1268. LODType = value.c_str();
  1269. else if (key.compare("singleDetailSize", 0U, String::NoCase) == 0)
  1270. singleDetailSize = dAtoi(value.c_str());
  1271. else if (key.compare("AlwaysImportedNodes", 0U, String::NoCase) == 0)
  1272. AlwaysImportedNodes = value.c_str();
  1273. else if (key.compare("AlwaysIgnoreNodes", 0U, String::NoCase) == 0)
  1274. AlwaysIgnoreNodes = value.c_str();
  1275. else if (key.compare("AlwaysImportMeshes", 0U, String::NoCase) == 0)
  1276. AlwaysImportMeshes = value.c_str();
  1277. else if (key.compare("AlwaysIgnoreMeshes", 0U, String::NoCase) == 0)
  1278. AlwaysIgnoreMeshes = value.c_str();
  1279. else if (key.compare("convertLeftHanded", 0U, String::NoCase) == 0)
  1280. convertLeftHanded = dAtob(value.c_str());
  1281. else if (key.compare("calcTangentSpace", 0U, String::NoCase) == 0)
  1282. calcTangentSpace = dAtob(value.c_str());
  1283. else if (key.compare("removeRedundantMats", 0U, String::NoCase) == 0)
  1284. removeRedundantMats = dAtob(value.c_str());
  1285. else if (key.compare("genUVCoords", 0U, String::NoCase) == 0)
  1286. genUVCoords = dAtob(value.c_str());
  1287. else if (key.compare("TransformUVs", 0U, String::NoCase) == 0)
  1288. TransformUVs = dAtob(value.c_str());
  1289. else if (key.compare("flipUVCoords", 0U, String::NoCase) == 0)
  1290. flipUVCoords = dAtob(value.c_str());
  1291. else if (key.compare("findInstances", 0U, String::NoCase) == 0)
  1292. findInstances = dAtob(value.c_str());
  1293. else if (key.compare("limitBoneWeights", 0U, String::NoCase) == 0)
  1294. limitBoneWeights = dAtob(value.c_str());
  1295. else if (key.compare("JoinIdenticalVerts", 0U, String::NoCase) == 0)
  1296. JoinIdenticalVerts = dAtob(value.c_str());
  1297. else if (key.compare("reverseWindingOrder", 0U, String::NoCase) == 0)
  1298. reverseWindingOrder = dAtob(value.c_str());
  1299. else if (key.compare("invertNormals", 0U, String::NoCase) == 0)
  1300. invertNormals = dAtob(value.c_str());
  1301. }
  1302. fileObj->close();
  1303. fileObj->deleteObject();
  1304. }
  1305. void AssetImporter::processImportAssets(AssetImportObject* assetItem)
  1306. {
  1307. Vector<AssetImportObject*> itemList = importingAssets;
  1308. if (assetItem != nullptr)
  1309. itemList = assetItem->childAssetItems;
  1310. assetHeirarchyChanged = false;
  1311. for (U32 i = 0; i < itemList.size(); i++)
  1312. {
  1313. AssetImportObject* item = itemList[i];
  1314. if (item->importStatus != AssetImportObject::NotProcessed)
  1315. continue;
  1316. //Sanitize before modifying our asset name(suffix additions, etc)
  1317. if (item->assetName != item->cleanAssetName)
  1318. item->assetName = item->cleanAssetName;
  1319. //process the asset items
  1320. if (item->assetType == String("ImageAsset"))
  1321. {
  1322. processImageAsset(item);
  1323. }
  1324. else if (item->assetType == String("ShapeAsset"))
  1325. {
  1326. processShapeAsset(item);
  1327. }
  1328. else if (item->assetType == String("SoundAsset"))
  1329. {
  1330. processSoundAsset(item);
  1331. }
  1332. else if (item->assetType == String("MaterialAsset"))
  1333. {
  1334. processMaterialAsset(item);
  1335. }
  1336. else if (item->assetType == String("ShapeAnimationAsset"))
  1337. {
  1338. processShapeAnimationAsset(item);
  1339. }
  1340. else
  1341. {
  1342. String processCommand = "process";
  1343. processCommand += item->assetType;
  1344. if (isMethod(processCommand.c_str()))
  1345. Con::executef(this, processCommand.c_str(), item);
  1346. }
  1347. //If we've already set our status in the processing phase, don't override that new status
  1348. if(item->importStatus == AssetImportObject::NotProcessed)
  1349. item->importStatus = AssetImportObject::Processed;
  1350. //try recusing on the children(if any)
  1351. processImportAssets(item);
  1352. }
  1353. //If our hierarchy changed, it's because we did so during processing
  1354. //so we'll loop back through again until everything has been processed
  1355. if (assetHeirarchyChanged)
  1356. processImportAssets();
  1357. }
  1358. void AssetImporter::processImageAsset(AssetImportObject* assetItem)
  1359. {
  1360. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Image for Import: %s", assetItem->assetName.c_str());
  1361. activityLog.push_back(importLogBuffer);
  1362. if ((activeImportConfig->GenerateMaterialOnImport && assetItem->parentAssetItem == nullptr)/* || assetItem->parentAssetItem != nullptr*/)
  1363. {
  1364. //find our suffix match, if any
  1365. String noSuffixName = assetItem->assetName;
  1366. String suffixType;
  1367. String suffix = parseImageSuffixes(assetItem->assetName, &suffixType);
  1368. if (suffix.isNotEmpty())
  1369. {
  1370. assetItem->imageSuffixType = suffixType;
  1371. S32 suffixPos =assetItem->assetName.find(suffix, 0, String::NoCase|String::Left);
  1372. noSuffixName = assetItem->assetName.substr(0, suffixPos);
  1373. }
  1374. //We try to automatically populate materials under the naming convention: materialName: Rock, image maps: Rock_Albedo, Rock_Normal, etc
  1375. AssetImportObject* materialAsset = findImportingAssetByName(noSuffixName);
  1376. if (materialAsset != nullptr && materialAsset->assetType != String("MaterialAsset"))
  1377. {
  1378. //We may have a situation where an asset matches the no-suffix name, but it's not a material asset. Ignore this
  1379. //asset item for now
  1380. materialAsset = nullptr;
  1381. }
  1382. //If we didn't find a matching material asset in our current items, we'll make one now
  1383. if (materialAsset == nullptr)
  1384. {
  1385. if (!assetItem->filePath.isEmpty())
  1386. {
  1387. materialAsset = addImportingAsset("MaterialAsset", assetItem->filePath, nullptr, noSuffixName);
  1388. }
  1389. }
  1390. //Not that, one way or another, we have the generated material asset, lets move on to associating our image with it
  1391. if (materialAsset != nullptr && materialAsset != assetItem->parentAssetItem)
  1392. {
  1393. if (assetItem->parentAssetItem != nullptr)
  1394. {
  1395. //If the image had an existing parent, it gets removed from that parent's child item list
  1396. assetItem->parentAssetItem->childAssetItems.remove(assetItem);
  1397. }
  1398. else
  1399. {
  1400. //If it didn't have one, we're going to pull it from the importingAssets list
  1401. importingAssets.remove(assetItem);
  1402. }
  1403. //Now we can add it to the correct material asset
  1404. materialAsset->childAssetItems.push_back(assetItem);
  1405. assetItem->parentAssetItem = materialAsset;
  1406. assetHeirarchyChanged = true;
  1407. }
  1408. //Now to do some cleverness. If we're generating a material, we can parse like assets being imported(similar filenames) but different suffixes
  1409. //If we find these, we'll just populate into the original's material
  1410. //if we need to append the diffuse suffix and indeed didn't find a suffix on the name, do that here
  1411. if (suffixType.isEmpty())
  1412. {
  1413. if (activeImportConfig->UseDiffuseSuffixOnOriginImage)
  1414. {
  1415. String diffuseToken = StringUnit::getUnit(activeImportConfig->DiffuseTypeSuffixes, 0, ",;\t");
  1416. assetItem->assetName = assetItem->assetName + diffuseToken;
  1417. //assetItem->cleanAssetName = assetItem->assetName;
  1418. }
  1419. else
  1420. {
  1421. //We need to ensure that our image asset doesn't match the same name as the material asset, so if we're not trying to force the diffuse suffix
  1422. //we'll give it a generic one
  1423. if ((materialAsset && materialAsset->assetName.compare(assetItem->assetName) == 0) || activeImportConfig->AlwaysAddImageSuffix)
  1424. {
  1425. assetItem->assetName = assetItem->assetName + activeImportConfig->AddedImageSuffix;
  1426. //assetItem->cleanAssetName = assetItem->assetName;
  1427. }
  1428. }
  1429. //Assume for abledo if it has no suffix matches
  1430. assetItem->imageSuffixType = "Albedo";
  1431. }
  1432. else
  1433. {
  1434. }
  1435. }
  1436. else
  1437. {
  1438. //If we're processing an unaffiliated image without generating materials for it, we can check some other bits
  1439. if (assetItem->parentAssetItem == nullptr)
  1440. {
  1441. if (assetItem->typeHint != String::EmptyString)
  1442. {
  1443. ImageAssetType type = ImageAsset::getImageTypeFromName(StringTable->insert(assetItem->typeHint.c_str()));
  1444. if (type == ImageAssetType::GUI)
  1445. {
  1446. }
  1447. }
  1448. }
  1449. }
  1450. if(assetItem->assetName == assetItem->cleanAssetName && activeImportConfig->AlwaysAddImageSuffix)
  1451. {
  1452. if (!assetItem->assetName.endsWith(activeImportConfig->AddedImageSuffix.c_str()))
  1453. assetItem->assetName = assetItem->assetName + activeImportConfig->AddedImageSuffix;
  1454. }
  1455. assetItem->importStatus = AssetImportObject::Processed;
  1456. }
  1457. void AssetImporter::processMaterialAsset(AssetImportObject* assetItem)
  1458. {
  1459. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Material for Import: %s", assetItem->assetName.c_str());
  1460. activityLog.push_back(importLogBuffer);
  1461. String filePath = assetItem->filePath.getFullPath();
  1462. String fileName = assetItem->filePath.getFileName();
  1463. String fileExt = assetItem->filePath.getExtension();
  1464. const char* assetName = assetItem->assetName.c_str();
  1465. assetItem->generatedAsset = true;
  1466. if (activeImportConfig->IgnoreMaterials.isNotEmpty())
  1467. {
  1468. U32 ignoredMatNameCount = StringUnit::getUnitCount(activeImportConfig->IgnoreMaterials, ",;\t");
  1469. for (U32 i = 0; i < ignoredMatNameCount; i++)
  1470. {
  1471. String ignoredName = StringUnit::getUnit(activeImportConfig->IgnoreMaterials, i, ",;\t");
  1472. if (FindMatch::isMatch(ignoredName.c_str(), assetName, false))
  1473. {
  1474. assetItem->importStatus = AssetImportObject::Skipped;
  1475. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Material %s has been ignored due to it's name being listed in the IgnoreMaterials list in the Import Config.", assetItem->assetName.c_str());
  1476. activityLog.push_back(importLogBuffer);
  1477. return;
  1478. }
  1479. }
  1480. }
  1481. bool foundExistingMaterial = false;
  1482. if (activeImportConfig->UseExistingMaterials)
  1483. {
  1484. //So if the material already exists, we should just use that. So first, let's find out if it already exists
  1485. //check to see if the definition for this already exists
  1486. StringTableEntry existingMatAsset = MaterialAsset::getAssetIdByMaterialName(StringTable->insert(assetName));
  1487. if (existingMatAsset != StringTable->EmptyString() && existingMatAsset != StringTable->insert("Core_Rendering:NoMaterial"))
  1488. {
  1489. assetItem->importStatus = AssetImportObject::UseForDependencies;
  1490. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Material %s has been skipped because we already found an asset Id that uses that material definition. The found assetId is: %s", assetItem->assetName.c_str(), existingMatAsset);
  1491. activityLog.push_back(importLogBuffer);
  1492. return;
  1493. }
  1494. //If there was no existing assetId, then lets see if it already exists in a legacy file, like a materials.cs or materials.tscript
  1495. //If it does, we'll just make our asset point to that instead of a new file
  1496. Material* mat;
  1497. Sim::findObject(assetName, mat);
  1498. if (!mat)
  1499. mat = MATMGR->getMaterialDefinitionByMapTo(assetName);
  1500. if (!mat && assetItem->assetName != assetItem->cleanAssetName)
  1501. {
  1502. mat = MATMGR->getMaterialDefinitionByName(assetItem->cleanAssetName);
  1503. if (!mat)
  1504. mat = MATMGR->getMaterialDefinitionByMapTo(assetItem->cleanAssetName);
  1505. }
  1506. if(mat)
  1507. {
  1508. //We found a match, so just modify our asset item's info to point against it. This will create the asset definition, but otherwise leave the material definition as-is.
  1509. assetItem->filePath = (Torque::Path)(mat->getFilename());
  1510. foundExistingMaterial = true;
  1511. }
  1512. }
  1513. if(!foundExistingMaterial)
  1514. {
  1515. if (activeImportConfig->AlwaysAddMaterialSuffix) //we only opt to force on the suffix if we're not obligating using the original material defs
  1516. {
  1517. if(!assetItem->assetName.endsWith(activeImportConfig->AddedMaterialSuffix.c_str()))
  1518. assetItem->assetName += activeImportConfig->AddedMaterialSuffix;
  1519. }
  1520. if (activeImportConfig->PopulateMaterialMaps)
  1521. {
  1522. //If we're trying to populate the rest of our material maps, we need to go looking
  1523. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Attempting to Auto-Populate Material Maps");
  1524. activityLog.push_back(importLogBuffer);
  1525. AssetImportObject* matchedImageTypes[ImageAsset::ImageTypeCount] = { nullptr };
  1526. String materialImageNoSuffix;
  1527. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  1528. {
  1529. AssetImportObject* childAssetItem = assetItem->childAssetItems[i];
  1530. if (childAssetItem->importStatus == AssetImportObject::Skipped || childAssetItem->assetType != String("ImageAsset"))
  1531. continue;
  1532. for (S32 t = 0; t < ImageAsset::ImageTypeCount; t++)
  1533. {
  1534. //If the imageType name and child asset image type match, check it off our list
  1535. if (!dStricmp(ImageAsset::getImageTypeNameFromType((ImageAsset::ImageTypes)t), childAssetItem->imageSuffixType.c_str()))
  1536. {
  1537. matchedImageTypes[t] = childAssetItem;
  1538. if (t == ImageAsset::ImageTypes::Albedo)
  1539. {
  1540. String sufType;
  1541. String suffix = parseImageSuffixes(childAssetItem->assetName, &sufType);
  1542. String imageAssetName = childAssetItem->assetName;
  1543. if (suffix.isEmpty())
  1544. materialImageNoSuffix = imageAssetName;
  1545. else
  1546. materialImageNoSuffix = imageAssetName.erase(imageAssetName.length() - suffix.length(), suffix.length());//cache this for later as we may need it for file association lookups
  1547. }
  1548. }
  1549. }
  1550. }
  1551. //Now that we've checked off any existingly matched image types, process through the unmatched to look for files that associate
  1552. for (S32 t = 0; t < ImageAsset::ImageTypeCount; t++)
  1553. {
  1554. //This type wasn't found, so try and find a match based on suffix
  1555. String suffixList;
  1556. switch (t)
  1557. {
  1558. case ImageAsset::Albedo:
  1559. suffixList = activeImportConfig->DiffuseTypeSuffixes;
  1560. break;
  1561. case ImageAsset::Normal:
  1562. suffixList = activeImportConfig->NormalTypeSuffixes;
  1563. break;
  1564. case ImageAsset::ORMConfig:
  1565. suffixList = activeImportConfig->PBRTypeSuffixes;
  1566. break;
  1567. case ImageAsset::Metalness:
  1568. suffixList = activeImportConfig->MetalnessTypeSuffixes;
  1569. break;
  1570. case ImageAsset::AO:
  1571. suffixList = activeImportConfig->AOTypeSuffixes;
  1572. break;
  1573. case ImageAsset::Roughness:
  1574. suffixList = activeImportConfig->RoughnessTypeSuffixes;
  1575. break;
  1576. //TODO: Glow map lookup too
  1577. }
  1578. if (!matchedImageTypes[t])
  1579. {
  1580. U32 suffixCount = StringUnit::getUnitCount(suffixList.c_str(), ",;\t");
  1581. for (U32 i = 0; i < suffixCount; i++)
  1582. {
  1583. //First, try checking based on the material's assetName for our patternbase
  1584. String testPath = assetItem->filePath.getRootAndPath();
  1585. testPath += "/" + assetItem->cleanAssetName + StringUnit::getUnit(suffixList.c_str(), i, ",;\t");
  1586. String imagePath = AssetImporter::findImagePath(testPath);
  1587. if (imagePath.isNotEmpty())
  1588. {
  1589. //got a match!
  1590. AssetImportObject* newImageAssetObj = addImportingAsset("ImageAsset", imagePath, assetItem, "");
  1591. newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType((ImageAsset::ImageTypes)t);
  1592. matchedImageTypes[t] = newImageAssetObj;
  1593. break;
  1594. }
  1595. else
  1596. {
  1597. //Check to see if our target module has a matching assetId for this slot already
  1598. String testAssetId = targetModuleId + ":" + assetItem->cleanAssetName + StringUnit::getUnit(suffixList.c_str(), i, ",;\t");
  1599. bool localAssetFound = false;
  1600. if (AssetDatabase.isDeclaredAsset(testAssetId.c_str()))
  1601. localAssetFound = true;
  1602. if (localAssetFound == false)
  1603. //Didn't work, try checking the common default type suffix
  1604. testAssetId = targetModuleId + ":" + assetItem->cleanAssetName + StringUnit::getUnit(suffixList.c_str(), i, ",;\t") + activeImportConfig->AddedImageSuffix;
  1605. if (localAssetFound)
  1606. {
  1607. //got a match!
  1608. ImageAsset* foundImageAsset = AssetDatabase.acquireAsset<ImageAsset>(testAssetId.c_str());
  1609. imagePath = foundImageAsset->getImagePath();
  1610. AssetImportObject* newImageAssetObj = addImportingAsset("ImageAsset", imagePath, assetItem, "");
  1611. newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType((ImageAsset::ImageTypes)t);
  1612. newImageAssetObj->importStatus = AssetImportObject::UseForDependencies; //we aren't going to actually IMPORT an already imported asset,
  1613. //so mark it as dependency use only
  1614. matchedImageTypes[t] = newImageAssetObj;
  1615. break;
  1616. }
  1617. if (materialImageNoSuffix.isNotEmpty())
  1618. {
  1619. testPath = assetItem->filePath.getRootAndPath();
  1620. testPath += "/" + materialImageNoSuffix + StringUnit::getUnit(suffixList.c_str(), i, ",;\t");
  1621. imagePath = AssetImporter::findImagePath(testPath);
  1622. if (imagePath.isNotEmpty())
  1623. {
  1624. //got a match!
  1625. AssetImportObject* newImageAssetObj = addImportingAsset("ImageAsset", imagePath, assetItem, "");
  1626. newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType((ImageAsset::ImageTypes)t);
  1627. matchedImageTypes[t] = newImageAssetObj;
  1628. break;
  1629. }
  1630. //Check to see if our target module has a matching assetId for this slot already based on our trimmed mat name
  1631. testAssetId = targetModuleId + ":" + materialImageNoSuffix + StringUnit::getUnit(suffixList.c_str(), i, ",;\t");
  1632. localAssetFound = false;
  1633. if (AssetDatabase.isDeclaredAsset(testAssetId.c_str()))
  1634. localAssetFound = true;
  1635. if (localAssetFound == false)
  1636. //Didn't work, try checking the common default type suffix
  1637. testAssetId = targetModuleId + ":" + materialImageNoSuffix + StringUnit::getUnit(suffixList.c_str(), i, ",;\t") + activeImportConfig->AddedImageSuffix;
  1638. if (localAssetFound)
  1639. {
  1640. //got a match!
  1641. ImageAsset* foundImageAsset = AssetDatabase.acquireAsset<ImageAsset>(testAssetId.c_str());
  1642. imagePath = foundImageAsset->getImagePath();
  1643. AssetImportObject* newImageAssetObj = addImportingAsset("ImageAsset", imagePath, assetItem, "");
  1644. newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType((ImageAsset::ImageTypes)t);
  1645. newImageAssetObj->importStatus = AssetImportObject::UseForDependencies; //we aren't going to actually IMPORT an already imported asset,
  1646. //so mark it as dependency use only
  1647. matchedImageTypes[t] = newImageAssetObj;
  1648. break;
  1649. }
  1650. }
  1651. }
  1652. }
  1653. //If we're the abledo slot and after all that we didn't find anything, it probably is a suffixless image
  1654. if (t == ImageAsset::Albedo && matchedImageTypes[t] == nullptr)
  1655. {
  1656. String testPath = assetItem->filePath.getRootAndPath() + "/" + assetItem->cleanAssetName;
  1657. String imagePath = AssetImporter::findImagePath(testPath);
  1658. if (imagePath.isNotEmpty())
  1659. {
  1660. //got a match!
  1661. AssetImportObject* newImageAssetObj = addImportingAsset("ImageAsset", imagePath, assetItem, "");
  1662. //In the event that the names match, we want to avoid duplications, so we'll go ahead and append a suffix onto our new image asset
  1663. if (newImageAssetObj->assetName == assetItem->assetName)
  1664. {
  1665. newImageAssetObj->assetName += StringUnit::getUnit(suffixList.c_str(), 0, ",;\t");
  1666. //newImageAssetObj->cleanAssetName = newImageAssetObj->assetName;
  1667. }
  1668. newImageAssetObj->imageSuffixType = ImageAsset::getImageTypeNameFromType(ImageAsset::ImageTypes::Albedo);
  1669. matchedImageTypes[t] = newImageAssetObj;
  1670. }
  1671. }
  1672. }
  1673. else
  1674. {
  1675. //just a bit of cleanup and logical testing for matches
  1676. //in the event we KNOW what the type is, but we don't have a suffix, such as a found image on a material lookup
  1677. //that doesn't have a suffix, we assume it to be the albedo, so we'll just append the suffix to avoid collisions if
  1678. //the name already matches our material name, similar to above logic
  1679. if (matchedImageTypes[t]->assetName == assetItem->assetName)
  1680. {
  1681. matchedImageTypes[t]->assetName += StringUnit::getUnit(suffixList.c_str(), 0, ",;\t");
  1682. //matchedImageTypes[t]->cleanAssetName = matchedImageTypes[t]->assetName;
  1683. }
  1684. }
  1685. }
  1686. }
  1687. }
  1688. assetItem->importStatus = AssetImportObject::Processed;
  1689. }
  1690. void AssetImporter::processShapeAsset(AssetImportObject* assetItem)
  1691. {
  1692. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Shape for Import: %s", assetItem->assetName.c_str());
  1693. activityLog.push_back(importLogBuffer);
  1694. String filePath = assetItem->filePath.getFullPath();
  1695. String fileName = assetItem->filePath.getFileName();
  1696. String fileExt = assetItem->filePath.getExtension();
  1697. if (assetItem->shapeInfo == nullptr)
  1698. {
  1699. GuiTreeViewCtrl* shapeInfo = new GuiTreeViewCtrl();
  1700. shapeInfo->registerObject();
  1701. if (fileExt.compare("dae") == 0)
  1702. {
  1703. enumColladaForImport(filePath, shapeInfo, false);
  1704. }
  1705. else if (fileExt.compare("dts") == 0)
  1706. {
  1707. enumDTSForImport(filePath, shapeInfo);
  1708. }
  1709. else
  1710. {
  1711. // Check if a cached DTS is available => no need to import the source file
  1712. // if we can load the DTS instead
  1713. AssimpShapeLoader loader;
  1714. loader.fillGuiTreeView(filePath.c_str(), shapeInfo);
  1715. }
  1716. assetItem->shapeInfo = shapeInfo;
  1717. }
  1718. if (activeImportConfig->AlwaysAddShapeSuffix)
  1719. {
  1720. if(!assetItem->assetName.endsWith(activeImportConfig->AddedShapeSuffix.c_str()))
  1721. assetItem->assetName += activeImportConfig->AddedShapeSuffix;
  1722. }
  1723. S32 meshCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_meshCount"), nullptr));
  1724. S32 animCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_animCount"), nullptr));
  1725. S32 materialCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_materialCount"), nullptr));
  1726. S32 matItem = assetItem->shapeInfo->findItemByName("Materials");
  1727. dSprintf(importLogBuffer, sizeof(importLogBuffer), " Shape Info: Mesh Count: %i | Material Count: %i | Anim Count: %i", meshCount, animCount, materialCount);
  1728. activityLog.push_back(importLogBuffer);
  1729. AssetImportConfig* cachedConfig = new AssetImportConfig();;
  1730. cachedConfig->registerObject();
  1731. activeImportConfig->CopyTo(cachedConfig);
  1732. if (!activeImportConfig->UseManualShapeConfigRules)
  1733. {
  1734. //Try and load a sis file if it exists for this format
  1735. activeImportConfig->loadSISFile(assetItem->filePath);
  1736. }
  1737. if (activeImportConfig->ImportMesh && meshCount > 0)
  1738. {
  1739. }
  1740. if (activeImportConfig->ImportAnimations && animCount > 0)
  1741. {
  1742. //If we have animations but no meshes, then this is a pure animation file so we can swap the asset type here
  1743. if (meshCount == 0)
  1744. {
  1745. assetItem->assetType = "ShapeAnimationAsset";
  1746. }
  1747. }
  1748. if (activeImportConfig->ImportMaterials && materialCount > 0)
  1749. {
  1750. S32 materialId = assetItem->shapeInfo->getChildItem(matItem);
  1751. processShapeMaterialInfo(assetItem, materialId);
  1752. materialId = assetItem->shapeInfo->getNextSiblingItem(materialId);
  1753. while (materialId != 0)
  1754. {
  1755. processShapeMaterialInfo(assetItem, materialId);
  1756. materialId = assetItem->shapeInfo->getNextSiblingItem(materialId);
  1757. }
  1758. }
  1759. //restore the cached version just in case we loaded a sis file
  1760. cachedConfig->CopyTo(activeImportConfig);
  1761. cachedConfig->deleteObject();
  1762. assetItem->importStatus = AssetImportObject::Processed;
  1763. }
  1764. void AssetImporter::processShapeAnimationAsset(AssetImportObject* assetItem)
  1765. {
  1766. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Shape Animation for Import: %s", assetItem->assetName.c_str());
  1767. activityLog.push_back(importLogBuffer);
  1768. String filePath = assetItem->filePath.getFullPath();
  1769. String fileName = assetItem->filePath.getFileName();
  1770. String fileExt = assetItem->filePath.getExtension();
  1771. if (assetItem->shapeInfo == nullptr)
  1772. {
  1773. GuiTreeViewCtrl* shapeInfo = new GuiTreeViewCtrl();
  1774. shapeInfo->registerObject();
  1775. if (fileExt.compare("dae") == 0)
  1776. {
  1777. enumColladaForImport(filePath, shapeInfo, false);
  1778. }
  1779. else if (fileExt.compare("dts") == 0 || fileExt.compare("dsq") == 0)
  1780. {
  1781. enumDTSForImport(filePath, shapeInfo);
  1782. }
  1783. else
  1784. {
  1785. // Check if a cached DTS is available => no need to import the source file
  1786. // if we can load the DTS instead
  1787. AssimpShapeLoader loader;
  1788. loader.fillGuiTreeView(filePath.c_str(), shapeInfo);
  1789. }
  1790. assetItem->shapeInfo = shapeInfo;
  1791. }
  1792. if (activeImportConfig->AlwaysAddShapeAnimationSuffix)
  1793. {
  1794. if (!assetItem->assetName.endsWith(activeImportConfig->AddedShapeAnimationSuffix.c_str()))
  1795. assetItem->assetName += activeImportConfig->AddedShapeAnimationSuffix;
  1796. }
  1797. S32 animCount = dAtoi(assetItem->shapeInfo->getDataField(StringTable->insert("_animCount"), nullptr));
  1798. dSprintf(importLogBuffer, sizeof(importLogBuffer), " Shape Animation Info: Anim Count: %i", animCount);
  1799. activityLog.push_back(importLogBuffer);
  1800. AssetImportConfig* cachedConfig = new AssetImportConfig();;
  1801. cachedConfig->registerObject();
  1802. activeImportConfig->CopyTo(cachedConfig);
  1803. if (!activeImportConfig->UseManualShapeConfigRules)
  1804. {
  1805. //Try and load a sis file if it exists for this format
  1806. activeImportConfig->loadSISFile(assetItem->filePath);
  1807. }
  1808. if (activeImportConfig->ImportAnimations && animCount > 0)
  1809. {
  1810. }
  1811. //restore the cached version just in case we loaded a sis file
  1812. cachedConfig->CopyTo(activeImportConfig);
  1813. cachedConfig->deleteObject();
  1814. assetItem->importStatus = AssetImportObject::Processed;
  1815. }
  1816. void AssetImporter::processShapeMaterialInfo(AssetImportObject* assetItem, S32 materialItemId)
  1817. {
  1818. String matName = assetItem->shapeInfo->getItemText(materialItemId);
  1819. String matAssetName = matName;
  1820. if (matName == assetItem->assetName)
  1821. {
  1822. //So apparently we managed to name the material the same as the shape. So we'll tweak the name
  1823. matAssetName += activeImportConfig->AddedMaterialSuffix;
  1824. }
  1825. //Do a check so we don't import materials that are on our ignore list
  1826. if (activeImportConfig->IgnoreMaterials.isNotEmpty())
  1827. {
  1828. U32 ignoredMatNamesCount = StringUnit::getUnitCount(activeImportConfig->IgnoreMaterials, ",;\t");
  1829. for (U32 i = 0; i < ignoredMatNamesCount; i++)
  1830. {
  1831. const char* ignoreMatName = StringUnit::getUnit(activeImportConfig->IgnoreMaterials, i, ",;\t");
  1832. if (FindMatch::isMatch(ignoreMatName, matName.c_str(), false))
  1833. {
  1834. //If we have a match to one of our ignore names, just bail out here and skip the material wholesale
  1835. return;
  1836. }
  1837. }
  1838. }
  1839. String materialItemValue = assetItem->shapeInfo->getItemValue(materialItemId);
  1840. AssetImportObject* matAssetItem = nullptr;
  1841. //If it happens to just be a color value instead of an image, we'll go ahead and skip doing any lookups
  1842. //TODO: properly map the 'texture' color to the material that gets created
  1843. if (materialItemValue.startsWith("Color:"))
  1844. {
  1845. matAssetItem = addImportingAsset("MaterialAsset", "", assetItem, matName);
  1846. }
  1847. else
  1848. {
  1849. Torque::Path filePath = materialItemValue;
  1850. String fullFilePath = filePath.getFullPath().c_str();
  1851. String shapePathBase = assetItem->filePath.getRootAndPath();
  1852. if (fullFilePath.isNotEmpty())
  1853. {
  1854. if (!Torque::FS::IsFile(fullFilePath.c_str()))
  1855. {
  1856. //could be a stale path reference, such as if it was downloaded elsewhere. Trim to just the filename and see
  1857. //if we can find it there
  1858. //trim (not found) if needbe
  1859. fullFilePath = fullFilePath.replace(" (Not Found)", "");
  1860. fullFilePath = fullFilePath.replace(" (not found)", "");
  1861. if(filePath.getPath().isEmpty())
  1862. fullFilePath = shapePathBase + "/" + fullFilePath;
  1863. if (Torque::FS::IsFile(fullFilePath.c_str()))
  1864. {
  1865. filePath = Torque::Path(fullFilePath);
  1866. }
  1867. else
  1868. {
  1869. //Hmm, didn't find it. It could be that the in-model filename could be different by virtue of
  1870. //image extension. Some files have source content files like psd's, but the mesh was exported to use
  1871. //a dds or png, etc
  1872. Torque::Path testFilePath = fullFilePath;
  1873. String imgFileName = AssetImporter::findImagePath(testFilePath.getPath() + "/" + testFilePath.getFileName());
  1874. if (imgFileName.isNotEmpty())
  1875. filePath = imgFileName;
  1876. else
  1877. filePath = Torque::Path(""); //no luck, so we just won't try importing in the image
  1878. }
  1879. }
  1880. matAssetItem = addImportingAsset("MaterialAsset", shapePathBase + "/" + matName, assetItem, matName);
  1881. if (!filePath.isEmpty())
  1882. {
  1883. AssetImportObject* imageAssetItem = addImportingAsset("ImageAsset", filePath, matAssetItem, "");
  1884. String suffixType;
  1885. String suffix = parseImageSuffixes(imageAssetItem->assetName, &suffixType);
  1886. if (suffix.isNotEmpty())
  1887. {
  1888. imageAssetItem->imageSuffixType = suffixType;
  1889. }
  1890. else
  1891. {
  1892. //we'll assume it's albedo
  1893. imageAssetItem->imageSuffixType = "Albedo";
  1894. }
  1895. }
  1896. }
  1897. else
  1898. {
  1899. matAssetItem = addImportingAsset("MaterialAsset", shapePathBase + "/" + matName, assetItem, matName);
  1900. }
  1901. }
  1902. //In the event we modified the asset name(such as appending _Mat to avoid naming conflicts) update the name here
  1903. //This preseves the 'clean asset name' which we can later use for lookups and the like as needed
  1904. if (matAssetItem && matAssetName != matName)
  1905. matAssetItem->assetName = matAssetName;
  1906. }
  1907. void AssetImporter::processSoundAsset(AssetImportObject* assetItem)
  1908. {
  1909. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Preparing Sound for Import: %s", assetItem->assetName.c_str());
  1910. activityLog.push_back(importLogBuffer);
  1911. if (activeImportConfig->AlwaysAddSoundSuffix)
  1912. {
  1913. if (!assetItem->assetName.endsWith(activeImportConfig->AddedSoundSuffix.c_str()))
  1914. assetItem->assetName += activeImportConfig->AddedSoundSuffix;
  1915. }
  1916. assetItem->importStatus = AssetImportObject::Processed;
  1917. }
  1918. //
  1919. // Validation
  1920. //
  1921. bool AssetImporter::validateAssets()
  1922. {
  1923. importIssues = false;
  1924. resetAssetValidationStatus();
  1925. for (U32 i = 0; i < importingAssets.size(); i++)
  1926. {
  1927. validateAsset(importingAssets[i]);
  1928. resolveAssetItemIssues(importingAssets[i]);
  1929. }
  1930. return importIssues;
  1931. }
  1932. void AssetImporter::validateAsset(AssetImportObject* assetItem)
  1933. {
  1934. if (assetItem->importStatus == AssetImportObject::Skipped || assetItem->importStatus == AssetImportObject::NotProcessed
  1935. || assetItem->importStatus == AssetImportObject::UseForDependencies)
  1936. return;
  1937. //If this item's already been marked as being in error, don't bother with it. It knows what it did.
  1938. //This avoids running collision checks on an item already known to have a collision, which could erroneously
  1939. //mark the original, not-colliding item as colliding with this item, invaliding both
  1940. if (assetItem->status == String("Error") || assetItem->statusType.isNotEmpty())
  1941. {
  1942. importIssues = true;
  1943. return;
  1944. }
  1945. //Runm this item against our other importing assets and check for any collisions
  1946. if (checkAssetForCollision(assetItem))
  1947. {
  1948. importIssues = true;
  1949. return;
  1950. }
  1951. if (!isReimport)
  1952. {
  1953. AssetQuery aQuery;
  1954. U32 numAssetsFound = AssetDatabase.findAllAssets(&aQuery);
  1955. for (U32 i = 0; i < numAssetsFound; i++)
  1956. {
  1957. StringTableEntry assetId = aQuery.mAssetList[i];
  1958. ModuleDefinition* moduleDef = AssetDatabase.getAssetModuleDefinition(assetId);
  1959. if ((moduleDef == NULL) || moduleDef->getModuleId() != StringTable->insert(targetModuleId.c_str()))
  1960. continue;
  1961. StringTableEntry assetName = AssetDatabase.getAssetName(assetId);
  1962. if (assetName == StringTable->insert(assetItem->assetName.c_str()))
  1963. {
  1964. assetItem->status = "Error";
  1965. assetItem->statusType = "DuplicateAsset";
  1966. assetItem->statusInfo = "Duplicate asset names found within the target module!\nAsset \"" + assetItem->assetName + "\" of type \"" + assetItem->assetType + "\" has a matching name.\nPlease rename it and try again!";
  1967. //log it
  1968. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Asset %s has an identically named asset in the target module.", assetItem->assetName.c_str());
  1969. activityLog.push_back(importLogBuffer);
  1970. break;
  1971. }
  1972. }
  1973. }
  1974. if (!assetItem->filePath.isEmpty() && !assetItem->generatedAsset && !Torque::FS::IsFile(assetItem->filePath.getFullPath().c_str()))
  1975. {
  1976. assetItem->status = "Error";
  1977. assetItem->statusType = "MissingFile";
  1978. assetItem->statusInfo = "Unable to find file to be imported with provided path: " + assetItem->filePath + "\n Please select a valid file.";
  1979. //log it
  1980. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Asset %s's file at %s was not found.", assetItem->assetName.c_str(), assetItem->filePath.getFullPath().c_str());
  1981. activityLog.push_back(importLogBuffer);
  1982. }
  1983. if (assetItem->status == String("Warning"))
  1984. {
  1985. if (activeImportConfig->WarningsAsErrors)
  1986. {
  1987. assetItem->status = "Error";
  1988. //log it
  1989. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Import configuration has treated an import warning as an error.", assetItem->assetName.c_str());
  1990. activityLog.push_back(importLogBuffer);
  1991. }
  1992. }
  1993. if (assetItem->status == String("Error"))
  1994. importIssues = true;
  1995. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  1996. {
  1997. validateAsset(assetItem->childAssetItems[i]);
  1998. resolveAssetItemIssues(assetItem->childAssetItems[i]);
  1999. }
  2000. return;
  2001. }
  2002. void AssetImporter::resetAssetValidationStatus(AssetImportObject* assetItem)
  2003. {
  2004. Vector<AssetImportObject*> itemList = importingAssets;
  2005. if (assetItem != nullptr)
  2006. itemList = assetItem->childAssetItems;
  2007. for (U32 i = 0; i < itemList.size(); i++)
  2008. {
  2009. if (itemList[i]->importStatus == AssetImportObject::Skipped)
  2010. continue;
  2011. itemList[i]->status = "";
  2012. itemList[i]->statusType = "";
  2013. itemList[i]->statusInfo = "";
  2014. //If it wasn't a match, try recusing on the children(if any)
  2015. resetAssetValidationStatus(itemList[i]);
  2016. }
  2017. }
  2018. bool AssetImporter::checkAssetForCollision(AssetImportObject* assetItemToCheck, AssetImportObject* assetItem)
  2019. {
  2020. bool results = false;
  2021. Vector<AssetImportObject*> itemList = importingAssets;
  2022. if (assetItem != nullptr)
  2023. itemList = assetItem->childAssetItems;
  2024. for (U32 i = 0; i < itemList.size(); i++)
  2025. {
  2026. AssetImportObject* importingAsset = itemList[i];
  2027. if (importingAsset->importStatus == AssetImportObject::Skipped || importingAsset->importStatus == AssetImportObject::UseForDependencies)
  2028. continue;
  2029. if ((assetItemToCheck->assetName.compare(importingAsset->assetName) == 0) && (assetItemToCheck->getId() != importingAsset->getId()))
  2030. {
  2031. //we do have a collision, note the collsion and bail out
  2032. assetItemToCheck->status = "Warning";
  2033. assetItemToCheck->statusType = "DuplicateImportAsset";
  2034. assetItemToCheck->statusInfo = "Duplicate asset names found with importing assets!\nAsset \"" + importingAsset->assetName + "\" of the type \"" + importingAsset->assetType + "\" and \"" +
  2035. assetItemToCheck->assetName + "\" of the type \"" + assetItemToCheck->assetType + "\" have matching names.\nPlease rename one of them.";
  2036. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Warning! Asset %s, type %s has a naming collision with another importing asset: %s, type %s",
  2037. assetItemToCheck->assetName.c_str(), assetItemToCheck->assetType.c_str(),
  2038. importingAsset->assetName.c_str(), importingAsset->assetType.c_str());
  2039. activityLog.push_back(importLogBuffer);
  2040. return true;
  2041. }
  2042. //If it wasn't a match, try recusing on the children(if any)
  2043. results = checkAssetForCollision(assetItemToCheck, importingAsset);
  2044. if (results)
  2045. return results;
  2046. }
  2047. return results;
  2048. }
  2049. void AssetImporter::resolveAssetItemIssues(AssetImportObject* assetItem)
  2050. {
  2051. if(assetItem->importStatus == AssetImportObject::UseForDependencies)
  2052. {
  2053. //if we've already marked as only existing for dependency reasons, we'll just skip resolving any issues with it
  2054. importIssues = false;
  2055. return;
  2056. }
  2057. if (assetItem->statusType == String("DuplicateImportAsset") || assetItem->statusType == String("DuplicateAsset"))
  2058. {
  2059. String humanReadableReason = assetItem->statusType == String("DuplicateImportAsset") ? "Importing asset was duplicate of another importing asset" : "Importing asset was duplicate of an existing asset";
  2060. //get the config value for duplicateAutoResolution
  2061. if (activeImportConfig->DuplicateAutoResolution == String("AutoPrune"))
  2062. {
  2063. //delete the item
  2064. if (assetItem->parentAssetItem == nullptr)
  2065. {
  2066. //if there's no parent, just delete
  2067. deleteImportingAsset(assetItem);
  2068. }
  2069. else
  2070. {
  2071. //otherwise, we'll likely want to retain our dependency for our parent
  2072. assetItem->importStatus = AssetImportObject::UseForDependencies;
  2073. }
  2074. //log it's deletion
  2075. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Asset %s was autopruned due to %s as part of the Import Configuration", assetItem->assetName.c_str(), humanReadableReason.c_str());
  2076. activityLog.push_back(importLogBuffer);
  2077. importIssues = false;
  2078. }
  2079. else if (activeImportConfig->DuplicateAutoResolution == String("AutoRename"))
  2080. {
  2081. //Set trailing number
  2082. String renamedAssetName = assetItem->assetName;
  2083. String renamedAssetId = assetItem->moduleName + ":" + renamedAssetName;
  2084. String addedSuffix;
  2085. if (assetItem->assetType == String("ShapeAsset"))
  2086. addedSuffix = activeImportConfig->AddedShapeSuffix;
  2087. else if (assetItem->assetType == String("MaterialAsset"))
  2088. addedSuffix = activeImportConfig->AddedMaterialSuffix;
  2089. else if (assetItem->assetType == String("ImageAsset"))
  2090. addedSuffix = activeImportConfig->AddedImageSuffix;
  2091. else if (assetItem->assetType == String("SoundAsset"))
  2092. addedSuffix = activeImportConfig->AddedSoundSuffix;
  2093. //do the suffix if it isn't already on it
  2094. if (!renamedAssetName.endsWith(addedSuffix.c_str()))
  2095. {
  2096. renamedAssetName += addedSuffix;
  2097. renamedAssetId = assetItem->moduleName + ":" + renamedAssetName;
  2098. assetItem->assetName = renamedAssetName;
  2099. }
  2100. //if still conflicted
  2101. //add the directory prefix
  2102. if (AssetDatabase.isDeclaredAsset(renamedAssetId.c_str()))
  2103. {
  2104. renamedAssetName = getFolderPrefixedName(assetItem);
  2105. renamedAssetId = assetItem->moduleName + ":" + renamedAssetName;
  2106. assetItem->assetName = renamedAssetName;
  2107. }
  2108. bool appendedNumber = false;
  2109. U32 uniqueNumber = 0;
  2110. while (AssetDatabase.isDeclaredAsset(renamedAssetId.c_str()))
  2111. {
  2112. uniqueNumber++;
  2113. renamedAssetId = assetItem->moduleName + ":" + renamedAssetName + String::ToString(uniqueNumber);
  2114. appendedNumber = true;
  2115. }
  2116. if (appendedNumber)
  2117. {
  2118. renamedAssetName += String::ToString(uniqueNumber);
  2119. }
  2120. //Log it's renaming
  2121. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Asset %s was renamed due to %s as part of the Import Configuration", assetItem->assetName.c_str(), humanReadableReason.c_str());
  2122. activityLog.push_back(importLogBuffer);
  2123. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Asset %s was renamed to %s", assetItem->assetName.c_str(), renamedAssetName.c_str());
  2124. activityLog.push_back(importLogBuffer);
  2125. assetItem->assetName = renamedAssetName;
  2126. //Whatever status we had prior is no longer relevent, so reset the status
  2127. resetAssetValidationStatus(assetItem);
  2128. importIssues = false;
  2129. }
  2130. else if (activeImportConfig->DuplicateAutoResolution == String("UseExisting"))
  2131. {
  2132. }
  2133. else if (activeImportConfig->DuplicateAutoResolution == String("FolderPrefix"))
  2134. {
  2135. String renamedAssetName = getFolderPrefixedName(assetItem);
  2136. //Log it's renaming
  2137. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Asset %s was renamed due to %s as part of the Import Configuration", assetItem->assetName.c_str(), humanReadableReason.c_str());
  2138. activityLog.push_back(importLogBuffer);
  2139. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Asset %s was renamed to %s", assetItem->assetName.c_str(), renamedAssetName.c_str());
  2140. activityLog.push_back(importLogBuffer);
  2141. assetItem->assetName = renamedAssetName;
  2142. //Whatever status we had prior is no longer relevent, so reset the status
  2143. resetAssetValidationStatus(assetItem);
  2144. importIssues = false;
  2145. }
  2146. }
  2147. else if (assetItem->statusType == String("MissingFile"))
  2148. {
  2149. //Trigger callback to look?
  2150. }
  2151. }
  2152. void AssetImporter::resetImportConfig()
  2153. {
  2154. //use a default import config
  2155. if (activeImportConfig == nullptr)
  2156. {
  2157. activeImportConfig = new AssetImportConfig();
  2158. activeImportConfig->registerObject();
  2159. }
  2160. Settings* editorSettings;
  2161. //See if we can get our editor settings
  2162. if (Sim::findObject("EditorSettings", editorSettings))
  2163. {
  2164. String defaultImportConfig = editorSettings->value("Assets/AssetImporDefaultConfig");
  2165. //If we found it, grab the import configs
  2166. Settings* importConfigs;
  2167. if (Sim::findObject("AssetImportSettings", importConfigs))
  2168. {
  2169. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Loading import config: %s!", defaultImportConfig.c_str());
  2170. activityLog.push_back(importLogBuffer);
  2171. //Now load the editor setting-deigned config!
  2172. activeImportConfig->loadImportConfig(importConfigs, defaultImportConfig.c_str());
  2173. }
  2174. }
  2175. }
  2176. //
  2177. // Importing
  2178. //
  2179. StringTableEntry AssetImporter::autoImportFile(Torque::Path filePath, String typeHint)
  2180. {
  2181. //Just in case we're reusing the same importer object from another import session, nuke any existing files
  2182. resetImportSession(true);
  2183. String assetType = getAssetTypeByFile(filePath);
  2184. if (assetType == String("Folder") || assetType == String("Zip"))
  2185. {
  2186. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Unable to import file %s because it is a folder or zip.", filePath.getFullPath().c_str());
  2187. activityLog.push_back(importLogBuffer);
  2188. dumpActivityLog();
  2189. return StringTable->EmptyString();
  2190. }
  2191. if (assetType.isEmpty())
  2192. {
  2193. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Unable to import file %s because it is of an unrecognized/unsupported type.", filePath.getFullPath().c_str());
  2194. activityLog.push_back(importLogBuffer);
  2195. dumpActivityLog();
  2196. return StringTable->EmptyString();
  2197. }
  2198. //Find out if the filepath has an associated module to it. If we're importing in-place, it needs to be within a module's directory
  2199. ModuleDefinition* targetModuleDef = AssetImporter::getModuleFromPath(filePath);
  2200. if (targetModuleDef == nullptr)
  2201. {
  2202. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Unable to import file %s because it is not in a valid module folder.", filePath.getFullPath().c_str());
  2203. activityLog.push_back(importLogBuffer);
  2204. dumpActivityLog();
  2205. return StringTable->EmptyString();
  2206. }
  2207. else
  2208. {
  2209. targetModuleId = targetModuleDef->getModuleId();
  2210. }
  2211. //set our path
  2212. targetPath = filePath.getPath();
  2213. resetImportConfig();
  2214. AssetImportObject* assetItem = addImportingAsset(assetType, filePath, nullptr, "");
  2215. processImportAssets();
  2216. bool hasIssues = validateAssets();
  2217. if (hasIssues)
  2218. {
  2219. //log it
  2220. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Import process has failed due to issues discovered during validation!");
  2221. activityLog.push_back(importLogBuffer);
  2222. }
  2223. else
  2224. {
  2225. importAssets();
  2226. acquireAssets();
  2227. }
  2228. dumpActivityLog();
  2229. if (hasIssues ||
  2230. assetItem->importStatus == AssetImportObject::Skipped ||
  2231. assetItem->importStatus == AssetImportObject::UseForDependencies ||
  2232. assetItem->importStatus == AssetImportObject::Error)
  2233. {
  2234. return StringTable->EmptyString();
  2235. }
  2236. else
  2237. {
  2238. String assetId = targetModuleId + ":" + assetItem->assetName;
  2239. return StringTable->insert(assetId.c_str());
  2240. }
  2241. }
  2242. void AssetImporter::importAssets(AssetImportObject* assetItem)
  2243. {
  2244. ModuleDefinition* moduleDef = ModuleDatabase.findModule(targetModuleId.c_str(), 1);
  2245. if (moduleDef == nullptr)
  2246. {
  2247. dSprintf(importLogBuffer, sizeof(importLogBuffer), "AssetImporter::importAssets - Unable to find moduleId %s", targetModuleId.c_str());
  2248. activityLog.push_back(importLogBuffer);
  2249. dumpActivityLog();
  2250. return;
  2251. }
  2252. Vector<AssetImportObject*> itemList = importingAssets;
  2253. if (assetItem != nullptr)
  2254. itemList = assetItem->childAssetItems;
  2255. for (U32 i = 0; i < itemList.size(); i++)
  2256. {
  2257. AssetImportObject* item = itemList[i];
  2258. if (!item->canImport())
  2259. continue;
  2260. Torque::Path assetPath;
  2261. if (item->assetType == String("ImageAsset"))
  2262. {
  2263. assetPath = importImageAsset(item);
  2264. }
  2265. else if (item->assetType == String("ShapeAsset"))
  2266. {
  2267. assetPath = importShapeAsset(item);
  2268. }
  2269. else if (item->assetType == String("SoundAsset"))
  2270. {
  2271. assetPath = importSoundAsset(item);
  2272. }
  2273. else if (item->assetType == String("MaterialAsset"))
  2274. {
  2275. assetPath = importMaterialAsset(item);
  2276. }
  2277. else if (item->assetType == String("ShapeAnimationAsset"))
  2278. {
  2279. assetPath = importShapeAnimationAsset(item);
  2280. }
  2281. else
  2282. {
  2283. finalImportedAssetPath = String::EmptyString;
  2284. String processCommand = "import";
  2285. processCommand += item->assetType;
  2286. if (isMethod(processCommand.c_str()))
  2287. {
  2288. Con::executef(this, processCommand.c_str(), item);
  2289. assetPath = finalImportedAssetPath;
  2290. }
  2291. }
  2292. /*else if (importingAssets[i]->assetType == String("ShapeAnimationAsset"))
  2293. assetPath = ShapeAnimationAsset::importAsset(importingAssets[i]);*/
  2294. if (assetPath.isEmpty() && item->assetType != String("MaterialAsset"))
  2295. {
  2296. dSprintf(importLogBuffer, sizeof(importLogBuffer), "AssetImporter::importAssets - Import attempt of %s failed, so skipping asset.", item->assetName.c_str());
  2297. activityLog.push_back(importLogBuffer);
  2298. continue;
  2299. }
  2300. else
  2301. {
  2302. //If we got a valid filepath back from the import action, then we know we're good to go and we can go ahead and register the asset!
  2303. if (!isReimport)
  2304. {
  2305. bool registerSuccess = AssetDatabase.addDeclaredAsset(moduleDef, assetPath.getFullPath().c_str());
  2306. String assetIdStr = item->moduleName + ":" + item->assetName;
  2307. StringTableEntry assetId = StringTable->insert(assetIdStr.c_str());
  2308. if (!registerSuccess)
  2309. {
  2310. dSprintf(importLogBuffer, sizeof(importLogBuffer), "AssetImporter::importAssets - Failed to successfully register new asset at path %s to moduleId %s", assetPath.getFullPath().c_str(), targetModuleId.c_str());
  2311. activityLog.push_back(importLogBuffer);
  2312. }
  2313. else
  2314. {
  2315. //Any special-case post-reg stuff here
  2316. if (item->assetType == String("ShapeAsset") || item->assetType == String("ShapeAnimationAsset"))
  2317. {
  2318. //forcefully update it's shape constructor
  2319. TSShapeConstructor* tss = TSShapeConstructor::findShapeConstructorByAssetId(assetId);
  2320. if(tss)
  2321. tss->setShapeAssetId(assetId);
  2322. }
  2323. }
  2324. }
  2325. else
  2326. {
  2327. String assetId = item->moduleName + ":" + item->assetName;
  2328. bool refreshSuccess = AssetDatabase.refreshAsset(assetId.c_str());
  2329. if (!refreshSuccess)
  2330. {
  2331. dSprintf(importLogBuffer, sizeof(importLogBuffer), "AssetImporter::importAssets - Failed to refresh reimporting asset %s.", item->assetName.c_str());
  2332. activityLog.push_back(importLogBuffer);
  2333. }
  2334. }
  2335. }
  2336. //Mark us as successfully imported
  2337. item->importStatus = AssetImportObject::Imported;
  2338. //recurse if needed
  2339. importAssets(item);
  2340. }
  2341. dumpActivityLog();
  2342. }
  2343. void AssetImporter::acquireAssets(AssetImportObject* assetItem)
  2344. {
  2345. Vector<AssetImportObject*> itemList = importingAssets;
  2346. if (assetItem != nullptr)
  2347. itemList = assetItem->childAssetItems;
  2348. for (U32 i = 0; i < itemList.size(); i++)
  2349. {
  2350. AssetImportObject* item = itemList[i];
  2351. if (item->importStatus == AssetImportObject::Skipped ||
  2352. item->importStatus == AssetImportObject::NotProcessed ||
  2353. item->importStatus == AssetImportObject::Error)
  2354. continue;
  2355. //recurse if needed, we want to process child items first for dependency reasons
  2356. acquireAssets(item);
  2357. //Go ahead and force the asset to load now just to kick it for immediate use
  2358. String assetId = item->moduleName + ":" + item->assetName;
  2359. if (AssetDatabase.isDeclaredAsset(assetId))
  2360. {
  2361. AssetDatabase.acquireAsset<AssetBase>(assetId);
  2362. AssetDatabase.releaseAsset(assetId);
  2363. }
  2364. }
  2365. }
  2366. //
  2367. // Type-specific import logic
  2368. //
  2369. Torque::Path AssetImporter::importImageAsset(AssetImportObject* assetItem)
  2370. {
  2371. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning importing of Image Asset: %s", assetItem->assetName.c_str());
  2372. activityLog.push_back(importLogBuffer);
  2373. ImageAsset* newAsset = new ImageAsset();
  2374. newAsset->registerObject();
  2375. StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
  2376. String imageFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension();
  2377. String assetPath = targetPath + "/" + imageFileName;
  2378. String tamlPath = targetPath + "/" + assetName + ".asset.taml";
  2379. String originalPath = assetItem->filePath.getFullPath().c_str();
  2380. char qualifiedFromFile[2048];
  2381. char qualifiedToFile[2048];
  2382. #ifndef TORQUE_SECURE_VFS
  2383. Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile));
  2384. Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile));
  2385. #else
  2386. dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile));
  2387. dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile));
  2388. #endif
  2389. newAsset->setAssetName(assetName);
  2390. newAsset->setImageFileName(imageFileName.c_str());
  2391. //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
  2392. //file path for reimporting support later
  2393. if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile))
  2394. {
  2395. newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
  2396. }
  2397. if (assetItem->typeHint != String::EmptyString)
  2398. {
  2399. newAsset->setImageType(ImageAsset::getImageTypeFromName(StringTable->insert(assetItem->typeHint.c_str())));
  2400. }
  2401. else
  2402. {
  2403. ImageAsset::ImageTypes imageType = ImageAsset::getImageTypeFromName(assetItem->imageSuffixType.c_str());
  2404. newAsset->setImageType(imageType);
  2405. }
  2406. Taml tamlWriter;
  2407. bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
  2408. if (!importSuccessful)
  2409. {
  2410. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
  2411. activityLog.push_back(importLogBuffer);
  2412. return "";
  2413. }
  2414. if (!isReimport)
  2415. {
  2416. bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile);
  2417. if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport))
  2418. {
  2419. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", assetItem->filePath.getFullPath().c_str());
  2420. activityLog.push_back(importLogBuffer);
  2421. return "";
  2422. }
  2423. }
  2424. return tamlPath;
  2425. }
  2426. Torque::Path AssetImporter::importMaterialAsset(AssetImportObject* assetItem)
  2427. {
  2428. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning importing of Material Asset: %s", assetItem->assetName.c_str());
  2429. activityLog.push_back(importLogBuffer);
  2430. MaterialAsset* newAsset = new MaterialAsset();
  2431. newAsset->registerObject();
  2432. StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
  2433. String tamlPath = targetPath + "/" + assetName + ".asset.taml";
  2434. String originalPath = assetItem->filePath.getFullPath().c_str();
  2435. char qualifiedFromFile[2048];
  2436. #ifndef TORQUE_SECURE_VFS
  2437. Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile));
  2438. #else
  2439. dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile));
  2440. #endif
  2441. newAsset->setAssetName(assetName);
  2442. if (!isReimport && Torque::FS::IsFile(qualifiedFromFile))
  2443. {
  2444. newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
  2445. }
  2446. newAsset->setDataField(StringTable->insert("materialDefinitionName"), nullptr, assetName);
  2447. //iterate through and write out the material maps dependencies
  2448. S32 dependencySlotId = 0;
  2449. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  2450. {
  2451. AssetImportObject* childItem = assetItem->childAssetItems[i];
  2452. if ((!childItem->canImport() && childItem->importStatus != AssetImportObject::UseForDependencies) || childItem->assetType.compare("ImageAsset") != 0)
  2453. continue;
  2454. char dependencyFieldName[64];
  2455. dSprintf(dependencyFieldName, 64, "imageMap%i", dependencySlotId);
  2456. char dependencyFieldDef[512];
  2457. dSprintf(dependencyFieldDef, 512, "%s=%s:%s", ASSET_ID_SIGNATURE, targetModuleId.c_str(), childItem->assetName.c_str());
  2458. newAsset->setDataField(StringTable->insert(dependencyFieldName), nullptr, dependencyFieldDef);
  2459. dependencySlotId++;
  2460. }
  2461. //build the ORMConfig file if we're flagged to and have valid image maps
  2462. if (activeImportConfig->CreateORMConfig)
  2463. {
  2464. AssetImportObject* ormMap = nullptr;
  2465. AssetImportObject* roughnessMap = nullptr;
  2466. AssetImportObject* metalnessMap = nullptr;
  2467. AssetImportObject* aoMap = nullptr;
  2468. //We need to find any/all respective image maps for the given channels
  2469. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  2470. {
  2471. AssetImportObject* childItem = assetItem->childAssetItems[i];
  2472. if (childItem->canImport() || childItem->assetType.compare("ImageAsset") != 0)
  2473. continue;
  2474. if (childItem->imageSuffixType.compare("ORMConfig") == 0)
  2475. ormMap = childItem;
  2476. else if(childItem->imageSuffixType.compare("Roughness") == 0)
  2477. roughnessMap = childItem;
  2478. else if (childItem->imageSuffixType.compare("Metalness") == 0)
  2479. metalnessMap = childItem;
  2480. else if (childItem->imageSuffixType.compare("AO") == 0)
  2481. aoMap = childItem;
  2482. }
  2483. if (ormMap != nullptr && ormMap->generatedAsset)
  2484. {
  2485. if (roughnessMap != nullptr || metalnessMap != nullptr || aoMap != nullptr)
  2486. {
  2487. U32 channelKey[4] = { 0,1,2,3 };
  2488. GFX->getTextureManager()->saveCompositeTexture(aoMap->filePath.getFullPath(), roughnessMap->filePath.getFullPath(), metalnessMap->filePath.getFullPath(), "",
  2489. channelKey, ormMap->filePath.getFullPath(), &GFXTexturePersistentProfile);
  2490. }
  2491. }
  2492. }
  2493. //If we're not using existing materials, or the material in question doesn't actually already exist, spool it up
  2494. if (!activeImportConfig->UseExistingMaterials || !Sim::findObject(assetName))
  2495. {
  2496. Material* newMat = new Material();
  2497. newMat->registerObject(assetName);
  2498. newMat->mMapTo = assetItem->cleanAssetName;
  2499. bool hasRoughness = false;
  2500. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  2501. {
  2502. AssetImportObject* childItem = assetItem->childAssetItems[i];
  2503. if ((!childItem->canImport() && childItem->importStatus != AssetImportObject::UseForDependencies) || childItem->assetType.compare("ImageAsset") != 0)
  2504. continue;
  2505. ImageAsset::ImageTypes imageType = ImageAsset::getImageTypeFromName(childItem->imageSuffixType);
  2506. String assetMapFillIn = targetModuleId + ":" + childItem->assetName;
  2507. StringTableEntry assetMapFillInStr = StringTable->insert(assetMapFillIn.c_str());
  2508. if (imageType == ImageAsset::ImageTypes::Albedo || childItem->imageSuffixType.isEmpty())
  2509. {
  2510. newMat->mDiffuseMapAssetId[0] = assetMapFillInStr;
  2511. }
  2512. else if (imageType == ImageAsset::ImageTypes::Normal)
  2513. {
  2514. newMat->mNormalMapAssetId[0] = assetMapFillInStr;
  2515. }
  2516. else if (imageType == ImageAsset::ImageTypes::ORMConfig)
  2517. {
  2518. newMat->mORMConfigMapAssetId[0] = assetMapFillInStr;
  2519. }
  2520. else if (imageType == ImageAsset::ImageTypes::Metalness)
  2521. {
  2522. newMat->mMetalMapAssetId[0] = assetMapFillInStr;
  2523. }
  2524. else if (imageType == ImageAsset::ImageTypes::AO)
  2525. {
  2526. newMat->mAOMapAssetId[0] = assetMapFillInStr;
  2527. }
  2528. else if (imageType == ImageAsset::ImageTypes::Roughness)
  2529. {
  2530. newMat->mRoughMapAssetId[0] = assetMapFillInStr;
  2531. hasRoughness = true;
  2532. }
  2533. }
  2534. if (hasRoughness)
  2535. {
  2536. newMat->mInvertRoughness[0] = true;
  2537. }
  2538. newAsset->addObject(newMat);
  2539. }
  2540. else
  2541. {
  2542. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Set to use an existing material, so avoiding writing a material definition to new asset definition for material: %s", assetName);
  2543. activityLog.push_back(importLogBuffer);
  2544. return "";
  2545. }
  2546. Taml tamlWriter;
  2547. bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
  2548. if (!importSuccessful)
  2549. {
  2550. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
  2551. activityLog.push_back(importLogBuffer);
  2552. return "";
  2553. }
  2554. return tamlPath;
  2555. }
  2556. Torque::Path AssetImporter::importShapeAsset(AssetImportObject* assetItem)
  2557. {
  2558. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning importing of Shape Asset: %s", assetItem->assetName.c_str());
  2559. activityLog.push_back(importLogBuffer);
  2560. ShapeAsset* newAsset = new ShapeAsset();
  2561. newAsset->registerObject();
  2562. StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
  2563. String shapeFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension();
  2564. String constructorFileName = assetItem->filePath.getFileName() + "." TORQUE_SCRIPT_EXTENSION;
  2565. String assetPath = targetPath + "/" + shapeFileName;
  2566. String constructorPath = targetPath + "/" + constructorFileName;
  2567. String tamlPath = targetPath + "/" + assetName + ".asset.taml";
  2568. String originalPath = assetItem->filePath.getFullPath().c_str();
  2569. String originalConstructorPath = assetItem->filePath.getPath() + "/" + constructorFileName;
  2570. char qualifiedFromFile[2048];
  2571. char qualifiedToFile[2048];
  2572. char qualifiedFromCSFile[2048];
  2573. char qualifiedToCSFile[2048];
  2574. #ifndef TORQUE_SECURE_VFS
  2575. Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile));
  2576. Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile));
  2577. Platform::makeFullPathName(originalConstructorPath.c_str(), qualifiedFromCSFile, sizeof(qualifiedFromCSFile));
  2578. Platform::makeFullPathName(constructorPath.c_str(), qualifiedToCSFile, sizeof(qualifiedToCSFile));
  2579. #else
  2580. dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile));
  2581. dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile));
  2582. dStrcpy(qualifiedFromCSFile, originalConstructorPath.c_str(), sizeof(qualifiedFromCSFile));
  2583. dStrcpy(qualifiedToCSFile, constructorPath.c_str(), sizeof(qualifiedToCSFile));
  2584. #endif
  2585. newAsset->setAssetName(assetName);
  2586. newAsset->setShapeFile(shapeFileName.c_str());
  2587. newAsset->setShapeConstructorFile(constructorFileName.c_str());
  2588. AssetImportConfig* cachedConfig = new AssetImportConfig();
  2589. cachedConfig->registerObject();
  2590. activeImportConfig->CopyTo(cachedConfig);
  2591. if (!activeImportConfig->UseManualShapeConfigRules)
  2592. {
  2593. //Try and load a sis file if it exists for this format
  2594. activeImportConfig->loadSISFile(assetItem->filePath);
  2595. }
  2596. //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
  2597. //file path for reimporting support later
  2598. if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile))
  2599. {
  2600. newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
  2601. }
  2602. //iterate through and write out the material maps dependencies
  2603. S32 dependencySlotId = 0;
  2604. for (U32 i = 0; i < assetItem->childAssetItems.size(); i++)
  2605. {
  2606. AssetImportObject* childItem = assetItem->childAssetItems[i];
  2607. if (!childItem->canImport() && childItem->importStatus != AssetImportObject::UseForDependencies)
  2608. continue;
  2609. if (childItem->assetType.compare("MaterialAsset") == 0)
  2610. {
  2611. char dependencyFieldName[64];
  2612. dSprintf(dependencyFieldName, 64, "materialSlot%i", dependencySlotId);
  2613. char dependencyFieldDef[512];
  2614. dSprintf(dependencyFieldDef, 512, "%s=%s:%s", ASSET_ID_SIGNATURE, targetModuleId.c_str(), childItem->assetName.c_str());
  2615. newAsset->setDataField(StringTable->insert(dependencyFieldName), nullptr, dependencyFieldDef);
  2616. dependencySlotId++;
  2617. }
  2618. else if (childItem->assetType.compare("ShapeAnimationAsset") == 0)
  2619. {
  2620. char dependencyFieldName[64];
  2621. dSprintf(dependencyFieldName, 64, "animationSequence%i", dependencySlotId);
  2622. char dependencyFieldDef[512];
  2623. dSprintf(dependencyFieldDef, 512, "%s=%s:%s", ASSET_ID_SIGNATURE, targetModuleId.c_str(), childItem->assetName.c_str());
  2624. newAsset->setDataField(StringTable->insert(dependencyFieldName), nullptr, dependencyFieldDef);
  2625. dependencySlotId++;
  2626. }
  2627. }
  2628. if (Con::getBoolVariable("$TSLastDetail::dumpImposters", false))
  2629. {
  2630. String imposterPath = assetItem->assetName + "_imposter.png";
  2631. String normalsPath = assetItem->assetName + "_imposter_normals.png";
  2632. newAsset->setDiffuseImposterFile(imposterPath.c_str());
  2633. newAsset->setNormalImposterFile(normalsPath.c_str());
  2634. }
  2635. Taml tamlWriter;
  2636. bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
  2637. if (!importSuccessful)
  2638. {
  2639. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
  2640. activityLog.push_back(importLogBuffer);
  2641. return "";
  2642. }
  2643. bool makeNewConstructor = true;
  2644. if (!isReimport)
  2645. {
  2646. bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile);
  2647. if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport))
  2648. {
  2649. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", qualifiedFromFile);
  2650. activityLog.push_back(importLogBuffer);
  2651. return "";
  2652. }
  2653. if (!isInPlace)
  2654. {
  2655. if (Torque::FS::IsFile(qualifiedFromCSFile))
  2656. {
  2657. if (!Torque::FS::CopyFile(qualifiedFromCSFile, qualifiedToCSFile, !isReimport))
  2658. {
  2659. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", qualifiedFromCSFile);
  2660. activityLog.push_back(importLogBuffer);
  2661. }
  2662. else
  2663. {
  2664. //We successfully copied the original constructor file, so no extra work required
  2665. makeNewConstructor = false;
  2666. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Successfully copied original TSShape Constructor file %s", qualifiedFromCSFile);
  2667. activityLog.push_back(importLogBuffer);
  2668. }
  2669. }
  2670. }
  2671. else
  2672. {
  2673. //We're doing an in-place import, so double check we've already got a constructor file in the expected spot
  2674. if (Torque::FS::IsFile(qualifiedFromCSFile))
  2675. {
  2676. //Yup, found it, we're good to go
  2677. makeNewConstructor = false;
  2678. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", qualifiedFromCSFile);
  2679. activityLog.push_back(importLogBuffer);
  2680. }
  2681. else
  2682. {
  2683. //Didn't work, but it's possible it's using the old .cs extension when our extension variable is set to something else, so check that one as well just to be sure
  2684. Torque::Path constrFilePath = qualifiedFromCSFile;
  2685. constrFilePath.setExtension("cs");
  2686. if (Torque::FS::IsFile(constrFilePath.getFullPath().c_str()))
  2687. {
  2688. //Yup, found it, we're good to go
  2689. makeNewConstructor = false;
  2690. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Existing TSShape Constructor file %s found", constrFilePath.getFullPath().c_str());
  2691. activityLog.push_back(importLogBuffer);
  2692. }
  2693. }
  2694. }
  2695. }
  2696. if (makeNewConstructor)
  2697. {
  2698. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning creation of new TSShapeConstructor file: %s", qualifiedToCSFile);
  2699. activityLog.push_back(importLogBuffer);
  2700. //find/create shape constructor
  2701. TSShapeConstructor* constructor = TSShapeConstructor::findShapeConstructorByFilename(Torque::Path(qualifiedToFile).getFullPath());
  2702. if (constructor == nullptr)
  2703. {
  2704. String fullAssetName = assetItem->moduleName + ":" + assetItem->assetName;
  2705. constructor = new TSShapeConstructor(StringTable->insert(fullAssetName.c_str()));
  2706. String constructorName = assetItem->filePath.getFileName() + assetItem->filePath.getExtension().substr(0, 3);
  2707. constructorName.replace(" ", "_");
  2708. constructorName.replace("-", "_");
  2709. constructorName.replace(".", "_");
  2710. constructorName = Sim::getUniqueName(constructorName.c_str());
  2711. constructor->registerObject(constructorName.c_str());
  2712. }
  2713. //now we write the import config logic into the constructor itself to ensure we load like we wanted it to
  2714. String neverImportMats;
  2715. if (activeImportConfig->IgnoreMaterials.isNotEmpty())
  2716. {
  2717. U32 ignoredMatNamesCount = StringUnit::getUnitCount(activeImportConfig->IgnoreMaterials, ",;\t");
  2718. for (U32 i = 0; i < ignoredMatNamesCount; i++)
  2719. {
  2720. if (i == 0)
  2721. neverImportMats = StringUnit::getUnit(activeImportConfig->IgnoreMaterials, i, ",;\t");
  2722. else
  2723. neverImportMats += String("\t") + StringUnit::getUnit(activeImportConfig->IgnoreMaterials, i, ",;\t");
  2724. }
  2725. }
  2726. if (activeImportConfig->DoUpAxisOverride)
  2727. {
  2728. S32 upAxis = domUpAxisType::UPAXISTYPE_Z_UP;
  2729. if (activeImportConfig->UpAxisOverride.compare("X_AXIS") == 0)
  2730. {
  2731. upAxis = domUpAxisType::UPAXISTYPE_X_UP;
  2732. }
  2733. else if (activeImportConfig->UpAxisOverride.compare("Y_AXIS") == 0)
  2734. {
  2735. upAxis = domUpAxisType::UPAXISTYPE_Y_UP;
  2736. }
  2737. else if (activeImportConfig->UpAxisOverride.compare("Z_AXIS") == 0)
  2738. {
  2739. upAxis = domUpAxisType::UPAXISTYPE_Z_UP;
  2740. }
  2741. constructor->mOptions.upAxis = (domUpAxisType)upAxis;
  2742. }
  2743. if (activeImportConfig->DoScaleOverride)
  2744. constructor->mOptions.unit = activeImportConfig->ScaleOverride;
  2745. else
  2746. constructor->mOptions.unit = -1;
  2747. enum eAnimTimingType
  2748. {
  2749. FrameCount = 0,
  2750. Seconds = 1,
  2751. Milliseconds = 1000
  2752. };
  2753. S32 lodType = ColladaUtils::ImportOptions::eLodType::TrailingNumber;
  2754. if (activeImportConfig->LODType.compare("TrailingNumber") == 0)
  2755. lodType = ColladaUtils::ImportOptions::eLodType::TrailingNumber;
  2756. else if (activeImportConfig->LODType.compare("SingleSize") == 0)
  2757. lodType = ColladaUtils::ImportOptions::eLodType::SingleSize;
  2758. else if (activeImportConfig->LODType.compare("DetectDTS") == 0)
  2759. lodType = ColladaUtils::ImportOptions::eLodType::DetectDTS;
  2760. constructor->mOptions.lodType = (ColladaUtils::ImportOptions::eLodType)lodType;
  2761. constructor->mOptions.singleDetailSize = activeImportConfig->singleDetailSize;
  2762. constructor->mOptions.alwaysImport = activeImportConfig->AlwaysImportedNodes;
  2763. constructor->mOptions.neverImport = activeImportConfig->AlwaysIgnoreNodes;
  2764. constructor->mOptions.alwaysImportMesh = activeImportConfig->AlwaysImportMeshes;
  2765. constructor->mOptions.neverImportMesh = activeImportConfig->AlwaysIgnoreMeshes;
  2766. constructor->mOptions.ignoreNodeScale = activeImportConfig->IgnoreNodeScale;
  2767. constructor->mOptions.adjustCenter = activeImportConfig->AdjustCenter;
  2768. constructor->mOptions.adjustFloor = activeImportConfig->AdjustFloor;
  2769. constructor->mOptions.convertLeftHanded = activeImportConfig->convertLeftHanded;
  2770. constructor->mOptions.calcTangentSpace = activeImportConfig->calcTangentSpace;
  2771. constructor->mOptions.genUVCoords = activeImportConfig->genUVCoords;
  2772. constructor->mOptions.flipUVCoords = activeImportConfig->flipUVCoords;
  2773. constructor->mOptions.findInstances = activeImportConfig->findInstances;
  2774. constructor->mOptions.limitBoneWeights = activeImportConfig->limitBoneWeights;
  2775. constructor->mOptions.joinIdenticalVerts = activeImportConfig->JoinIdenticalVerts;
  2776. constructor->mOptions.reverseWindingOrder = activeImportConfig->reverseWindingOrder;
  2777. constructor->mOptions.invertNormals = activeImportConfig->invertNormals;
  2778. constructor->mOptions.removeRedundantMats = activeImportConfig->removeRedundantMats;
  2779. S32 animTimingType;
  2780. if (activeImportConfig->animTiming.compare("FrameCount") == 0)
  2781. animTimingType = ColladaUtils::ImportOptions::eAnimTimingType::FrameCount;
  2782. else if (activeImportConfig->animTiming.compare("Seconds") == 0)
  2783. animTimingType = ColladaUtils::ImportOptions::eAnimTimingType::Seconds;
  2784. else// (activeImportConfig->animTiming.compare("Milliseconds") == 0)
  2785. animTimingType = ColladaUtils::ImportOptions::eAnimTimingType::Milliseconds;
  2786. constructor->mOptions.animTiming = (ColladaUtils::ImportOptions::eAnimTimingType)animTimingType;
  2787. constructor->mOptions.animFPS = activeImportConfig->animFPS;
  2788. constructor->mOptions.neverImportMat = neverImportMats;
  2789. PersistenceManager* constructorPersist = new PersistenceManager();
  2790. constructorPersist->registerObject();
  2791. constructorPersist->setDirty(constructor, qualifiedToCSFile);
  2792. if (!constructorPersist->saveDirtyObject(constructor))
  2793. {
  2794. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Failed to save shape constructor file to %s", constructorPath.c_str());
  2795. activityLog.push_back(importLogBuffer);
  2796. }
  2797. else
  2798. {
  2799. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Finished creating shape constructor file to %s", constructorPath.c_str());
  2800. activityLog.push_back(importLogBuffer);
  2801. }
  2802. constructorPersist->destroySelf();
  2803. }
  2804. //restore the cached version just in case we loaded a sis file
  2805. cachedConfig->CopyTo(activeImportConfig);
  2806. cachedConfig->deleteObject();
  2807. return tamlPath;
  2808. }
  2809. Torque::Path AssetImporter::importSoundAsset(AssetImportObject* assetItem)
  2810. {
  2811. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning importing of Sound Asset: %s", assetItem->assetName.c_str());
  2812. activityLog.push_back(importLogBuffer);
  2813. SoundAsset* newAsset = new SoundAsset();
  2814. newAsset->registerObject();
  2815. StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
  2816. String soundFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension();
  2817. String assetPath = targetPath + "/" + soundFileName;
  2818. String tamlPath = targetPath + "/" + assetName + ".asset.taml";
  2819. String originalPath = assetItem->filePath.getFullPath().c_str();
  2820. char qualifiedFromFile[2048];
  2821. char qualifiedToFile[2048];
  2822. #ifndef TORQUE_SECURE_VFS
  2823. Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile));
  2824. Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile));
  2825. #else
  2826. dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile));
  2827. dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile));
  2828. #endif
  2829. newAsset->setAssetName(assetName);
  2830. newAsset->_setSoundFile(newAsset, "0", soundFileName.c_str());
  2831. //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
  2832. //file path for reimporting support later
  2833. if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile))
  2834. {
  2835. newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
  2836. }
  2837. Taml tamlWriter;
  2838. bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
  2839. if (!importSuccessful)
  2840. {
  2841. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
  2842. activityLog.push_back(importLogBuffer);
  2843. return "";
  2844. }
  2845. if (!isReimport)
  2846. {
  2847. bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile);
  2848. if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport))
  2849. {
  2850. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", assetItem->filePath.getFullPath().c_str());
  2851. activityLog.push_back(importLogBuffer);
  2852. return "";
  2853. }
  2854. }
  2855. return tamlPath;
  2856. }
  2857. Torque::Path AssetImporter::importShapeAnimationAsset(AssetImportObject* assetItem)
  2858. {
  2859. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Beginning importing of Shape Animation Asset: %s", assetItem->assetName.c_str());
  2860. activityLog.push_back(importLogBuffer);
  2861. ShapeAnimationAsset* newAsset = new ShapeAnimationAsset();
  2862. newAsset->registerObject();
  2863. StringTableEntry assetName = StringTable->insert(assetItem->assetName.c_str());
  2864. String imageFileName = assetItem->filePath.getFileName() + "." + assetItem->filePath.getExtension();
  2865. String assetPath = targetPath + "/" + imageFileName;
  2866. String tamlPath = targetPath + "/" + assetName + ".asset.taml";
  2867. String originalPath = assetItem->filePath.getFullPath().c_str();
  2868. char qualifiedFromFile[2048];
  2869. char qualifiedToFile[2048];
  2870. #ifndef TORQUE_SECURE_VFS
  2871. Platform::makeFullPathName(originalPath.c_str(), qualifiedFromFile, sizeof(qualifiedFromFile));
  2872. Platform::makeFullPathName(assetPath.c_str(), qualifiedToFile, sizeof(qualifiedToFile));
  2873. #else
  2874. dStrcpy(qualifiedFromFile, originalPath.c_str(), sizeof(qualifiedFromFile));
  2875. dStrcpy(qualifiedToFile, assetPath.c_str(), sizeof(qualifiedToFile));
  2876. #endif
  2877. newAsset->setAssetName(assetName);
  2878. newAsset->setAnimationFile(imageFileName.c_str());
  2879. //If it's not a re-import, check that the file isn't being in-place imported. If it isn't, store off the original
  2880. //file path for reimporting support later
  2881. if (!isReimport && String::compare(qualifiedFromFile, qualifiedToFile) && Torque::FS::IsFile(qualifiedFromFile))
  2882. {
  2883. newAsset->setDataField(StringTable->insert("originalFilePath"), nullptr, qualifiedFromFile);
  2884. }
  2885. Taml tamlWriter;
  2886. bool importSuccessful = tamlWriter.write(newAsset, tamlPath.c_str());
  2887. if (!importSuccessful)
  2888. {
  2889. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to write asset taml file %s", tamlPath.c_str());
  2890. activityLog.push_back(importLogBuffer);
  2891. return "";
  2892. }
  2893. if (!isReimport)
  2894. {
  2895. bool isInPlace = !String::compare(qualifiedFromFile, qualifiedToFile);
  2896. if (!isInPlace && !Torque::FS::CopyFile(qualifiedFromFile, qualifiedToFile, !isReimport))
  2897. {
  2898. dSprintf(importLogBuffer, sizeof(importLogBuffer), "Error! Unable to copy file %s", assetItem->filePath.getFullPath().c_str());
  2899. activityLog.push_back(importLogBuffer);
  2900. return "";
  2901. }
  2902. }
  2903. return tamlPath;
  2904. }