/// Returns a (possibly shared) ExportFileReference for the uri. /// The destination file: /// - will have no path components in it /// - will not collide with any other destination files /// - will be similar to suggestedName (if suggestedName is passed) public static ExportFileReference GetOrCreateSafeLocal( DisambiguationContext disambiguationContext, string sourceUri, string uriBase, string suggestedName = null) { if (IsHttp(sourceUri)) { throw new ArgumentException("sourceUri"); } // Passing the same source file multiple times should give the same destination file string sourcePath = GetFullPathForUri(sourceUri, uriBase); if (disambiguationContext.m_filesByOriginalLocation.TryGetValue( sourcePath, out var existingRef)) { return(existingRef); } // A newly-seen source file should get an unused destination string exportedFileName = ExportUtils.CreateUniqueName( Path.GetFileName(suggestedName ?? sourcePath), disambiguationContext.m_exportedFileNames); var fileRef = CreateSafeLocal(sourcePath, exportedFileName); disambiguationContext.m_filesByOriginalLocation[fileRef.m_originalLocation] = fileRef; return(fileRef); }
public void TestCreateUniqueName() { HashSet <string> names = new HashSet <string>(); string Create(string name) => ExportUtils.CreateUniqueName(name, names); Assert.AreEqual("main.png", Create("main.png")); Assert.AreEqual("main_1.png", Create("main.png")); Assert.AreEqual("main_1_1.png", Create("main_1.png")); // perverse Assert.AreEqual("main_2.png", Create("main.png")); Assert.AreEqual("initialShadingGroup", Create("initialShadingGroup")); Assert.AreEqual("initialShadingGroup_1", Create("initialShadingGroup")); }
internal static FbxSurfaceMaterial CreateFbxMaterial( FbxExportGlobals G, string meshNamespace, IExportableMaterial exportableMaterial, HashSet <string> createdMaterialNames) { string materialName; if (exportableMaterial is BrushDescriptor) { // Toolkit uses this guid (in "N" format) to look up a BrushDescriptor. // See Toolkit's ModelImportSettings.GetDescriptorForStroke materialName = $"{exportableMaterial.UniqueName:N}_{meshNamespace}_{exportableMaterial.DurableName}"; } else if (exportableMaterial is DynamicExportableMaterial dem) { // Comes from {fbx,obj,gltf,...} import from {Poly, Media Library} // This is a customized version of a BrushDescriptor -- almost certainly // Pbr{Blend,Opaque}{Double,Single}Sided with maybe an added texture and // some of its params customized. // TBT will merge the material created by Unity for this FbxMaterial with // the premade material it has for the parent guid. materialName = $"{dem.Parent.m_Guid:N}_{meshNamespace}_{dem.DurableName}"; } else { Debug.LogWarning($"Unknown class {exportableMaterial.GetType().Name}"); materialName = $"{meshNamespace}_{exportableMaterial.DurableName}"; } // If only ExportFbx were a non-static class we could merge it with FbxExportGlobals materialName = ExportUtils.CreateUniqueName(materialName, createdMaterialNames); FbxSurfaceLambert material = FbxSurfaceLambert.Create(G.m_scene, materialName); material.Ambient.Set(new FbxDouble3(0, 0, 0)); material.Diffuse.Set(new FbxDouble3(1.0, 1.0, 1.0)); if (exportableMaterial.EmissiveFactor > 0) { material.EmissiveFactor.Set(exportableMaterial.EmissiveFactor); material.Emissive.Set(new FbxDouble3(1.0, 1.0, 1.0)); } if (exportableMaterial.BlendMode != ExportableMaterialBlendMode.None) { var blendMode = FbxProperty.Create(material, Globals.FbxStringDT, "BlendMode"); switch (exportableMaterial.BlendMode) { case ExportableMaterialBlendMode.AlphaMask: blendMode.SetString(new FbxString("AlphaMask")); material.TransparencyFactor.Set(0.2); break; case ExportableMaterialBlendMode.AdditiveBlend: blendMode.SetString(new FbxString("AdditiveBlend")); break; } } // Export the texture if (exportableMaterial.HasExportTexture()) { // This is not perfectly unique, but it is good enough for fbx export // better would be to use <durable>_<guid> but that's ugly, and nobody uses // the textures anyway, so... let's leave well enough alone for now. string albedoTextureName = exportableMaterial.DurableName; var fullTextureDir = Path.Combine(G.m_outputDir, kRelativeTextureDir); if (!Directory.Exists(fullTextureDir)) { if (!FileUtils.InitializeDirectoryWithUserError(fullTextureDir)) { throw new IOException("Cannot write textures"); } } string src = exportableMaterial.GetExportTextureFilename(); var textureFileName = albedoTextureName + ".png"; var textureFilePath = Path.Combine(fullTextureDir, textureFileName); FileInfo srcInfo = new FileInfo(src); if (srcInfo.Exists && !new FileInfo(textureFilePath).Exists) { srcInfo.CopyTo(textureFilePath); } FbxFileTexture texture = FbxFileTexture.Create(G.m_scene, albedoTextureName + "_texture"); texture.SetFileName(textureFilePath); texture.SetTextureUse(FbxTexture.ETextureUse.eStandard); texture.SetMappingType(FbxTexture.EMappingType.eUV); texture.SetMaterialUse(FbxFileTexture.EMaterialUse.eModelMaterial); texture.UVSet.Set(new FbxString("uv0")); material.Diffuse.ConnectSrcObject(texture); material.TransparentColor.ConnectSrcObject(texture); } else { foreach (var kvp in exportableMaterial.TextureUris) { string parameterName = kvp.Key; string textureUri = kvp.Value; if (ExportFileReference.IsHttp(textureUri)) { // fbx can't deal with http references to textures continue; } ExportFileReference fileRef = ExportFileReference.GetOrCreateSafeLocal( G.m_disambiguationContext, textureUri, exportableMaterial.UriBase, $"{meshNamespace}_{Path.GetFileName(textureUri)}"); AddTextureToMaterial(G, fileRef, material, parameterName); } } return(material); }