assetImporter.cpp 146 KB

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