private void SaveAllTextures() { if (TexDict?.Textures?.data_items == null) { return; } if (FolderBrowserDialog.ShowDialogNew() != DialogResult.OK) { return; } var folder = FolderBrowserDialog.SelectedPath; foreach (var tex in TexDict.Textures.data_items) { byte[] dds = DDSIO.GetDDSFile(tex); string bpath = folder + "\\" + tex.Name; string fpath = bpath + ".dds"; int c = 1; while (File.Exists(fpath)) { fpath = bpath + "_Copy" + c.ToString() + ".dds"; c++; } File.WriteAllBytes(fpath, dds); } }
private Texture OpenDDSFile() { if (OpenDDSFileDialog.ShowDialog() != DialogResult.OK) { return(null); } var fn = OpenDDSFileDialog.FileName; if (!File.Exists(fn)) { return(null); //couldn't find file? } try { var dds = File.ReadAllBytes(fn); var tex = DDSIO.GetTexture(dds); tex.Name = Path.GetFileNameWithoutExtension(fn); tex.NameHash = JenkHash.GenHash(tex.Name?.ToLowerInvariant()); JenkIndex.Ensure(tex.Name?.ToLowerInvariant()); return(tex); } catch { MessageBox.Show("Unable to load " + fn + ".\nAre you sure it's a valid .dds file?"); } return(null); }
private void DisplayTexture(Texture tex, int mip) { try { int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); byte[] pixels = DDSIO.GetPixels(tex, cmip); int w = tex.Width >> cmip; int h = tex.Height >> cmip; Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); if (pixels != null) { var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = bmpData.Stride * bmp.Height; Marshal.Copy(pixels, 0, ptr, bytes); bmp.UnlockBits(bmpData); } SelDrawableTexturePictureBox.Image = bmp; SelTextureDimensionsLabel.Text = w.ToString() + " x " + h.ToString(); } catch (Exception ex) { MessageBox.Show("Error reading texture mip:\n" + ex.ToString()); SelDrawableTexturePictureBox.Image = null; } }
public override void ReadXml(XmlNode node, string ddsfolder) { base.ReadXml(node, ddsfolder); Width = (ushort)Xml.GetChildUIntAttribute(node, "Width", "value"); Height = (ushort)Xml.GetChildUIntAttribute(node, "Height", "value"); Levels = (byte)Xml.GetChildUIntAttribute(node, "MipLevels", "value"); Format = Xml.GetChildEnumInnerText <TextureFormat>(node, "Format"); var filename = Xml.GetChildInnerText(node, "FileName"); try { var filepath = Path.Combine(ddsfolder, filename); if (File.Exists(filepath)) { var dds = File.ReadAllBytes(filepath); var tex = DDSIO.GetTexture(dds); if (tex != null) { Data = tex.Data; Width = tex.Width; Height = tex.Height; Depth = tex.Depth; Levels = tex.Levels; Format = tex.Format; Stride = tex.Stride; } } } catch { } }
public override void WriteXml(StringBuilder sb, int indent, string ddsfolder) { base.WriteXml(sb, indent, ddsfolder); YtdXml.ValueTag(sb, indent, "Width", Width.ToString()); YtdXml.ValueTag(sb, indent, "Height", Height.ToString()); YtdXml.ValueTag(sb, indent, "MipLevels", Levels.ToString()); YtdXml.StringTag(sb, indent, "Format", Format.ToString()); YtdXml.StringTag(sb, indent, "Usage", Usage.ToString()); YtdXml.StringTag(sb, indent, "UsageFlags", UsageFlags.ToString()); YtdXml.ValueTag(sb, indent, "ExtraFlags", ExtraFlags.ToString()); YtdXml.StringTag(sb, indent, "FileName", YtdXml.XmlEscape((Name ?? "null") + ".dds")); try { if (!string.IsNullOrEmpty(ddsfolder)) { if (!Directory.Exists(ddsfolder)) { Directory.CreateDirectory(ddsfolder); } var filepath = Path.Combine(ddsfolder, (Name ?? "null") + ".dds"); var dds = DDSIO.GetDDSFile(this); File.WriteAllBytes(filepath, dds); } } catch { } }
public void Export(string fileName) { try { // only DDS supported DDSIO.SaveTextureData(texture, fileName); } catch { } }
public void Import(string fileName) { try { // only DDS supported DDSIO.LoadTextureData(texture, fileName); } catch { } }
private void ShowTextureMip(Texture tex, int mip, bool mipchange) { if (tex == null) { SelTexturePictureBox.Image = null; SelTextureNameTextBox.Text = string.Empty; SelTextureDimensionsLabel.Text = "-"; SelTextureMipLabel.Text = "0"; SelTextureMipTrackBar.Value = 0; SelTextureMipTrackBar.Maximum = 0; return; } if (mipchange) { if (mip >= tex.Levels) { mip = tex.Levels - 1; } } else { SelTextureMipTrackBar.Maximum = tex.Levels - 1; } SelTextureNameTextBox.Text = tex.Name; try { int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); byte[] pixels = DDSIO.GetPixels(tex, cmip); int w = tex.Width >> cmip; int h = tex.Height >> cmip; Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); if (pixels != null) { var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = bmpData.Stride * bmp.Height; Marshal.Copy(pixels, 0, ptr, bytes); bmp.UnlockBits(bmpData); } SelTexturePictureBox.Image = bmp; SelTextureDimensionsLabel.Text = w.ToString() + " x " + h.ToString(); } catch (Exception ex) { MessageBox.Show("Error reading texture mip:\n" + ex.ToString()); SelTexturePictureBox.Image = null; } }
private void SaveAllTexturesButton_Click(object sender, EventArgs e) { if (FolderBrowserDialog.ShowDialogNew() != DialogResult.OK) { return; } string folderpath = FolderBrowserDialog.SelectedPath; if (!folderpath.EndsWith("\\")) { folderpath += "\\"; } var texs = new List <Texture>(); foreach (TreeNode modelnode in SelDrawableTexturesTreeView.Nodes) { foreach (TreeNode geomnode in modelnode.Nodes) { foreach (TreeNode texnode in geomnode.Nodes) { var texbase = texnode.Tag as TextureBase; var tex = texbase as Texture; string errstr = ""; if ((tex == null) && (texbase != null)) { tex = TryGetTexture(texbase, out _, ref errstr); } if (tex != null) { if (!texs.Contains(tex)) { texs.Add(tex); } } } } } foreach (var tex in texs) { string fpath = folderpath + tex.Name + ".dds"; byte[] dds = DDSIO.GetDDSFile(tex); File.WriteAllBytes(fpath, dds); } }
private void SaveTextureAs() { if (CurrentTexture == null) { return; } string fname = CurrentTexture.Name + ".dds"; SaveDDSFileDialog.FileName = fname; if (SaveDDSFileDialog.ShowDialog() != DialogResult.OK) { return; } string fpath = SaveDDSFileDialog.FileName; byte[] dds = DDSIO.GetDDSFile(CurrentTexture); File.WriteAllBytes(fpath, dds); }
private void SaveTexture(Texture tex, RpfEntry entry, string folder) { //DirectXTex byte[] dds = DDSIO.GetDDSFile(tex); string bpath = folder + "\\" + entry.Name + "_" + tex.Name; string fpath = bpath + ".dds"; int c = 1; while (File.Exists(fpath)) { fpath = bpath + "_Copy" + c.ToString() + ".dds"; c++; } File.WriteAllBytes(fpath, dds); }
private void SaveTextureButton_Click(object sender, EventArgs e) { if (currentTex == null) { return; } string fname = currentTex.Name + ".dds"; SaveFileDialog.FileName = fname; if (SaveFileDialog.ShowDialog() != DialogResult.OK) { return; } string fpath = SaveFileDialog.FileName; byte[] dds = DDSIO.GetDDSFile(currentTex); File.WriteAllBytes(fpath, dds); }
private void ShowTextureMip(Texture tex, int mip, bool mipchange) { CurrentTexture = tex; UpdateSaveTextureAs(); if (tex == null) { SelTexturePictureBox.Image = null; SelTextureNameTextBox.Text = string.Empty; SelTextureDimensionsLabel.Text = "-"; SelTextureMipLabel.Text = "0"; SelTextureMipTrackBar.Value = 0; SelTextureMipTrackBar.Maximum = 0; DetailsPropertyGrid.SelectedObject = null; RemoveTextureButton.Enabled = false; ReplaceTextureButton.Enabled = false; UpdateStatus(GetTexCountStr()); return; } RemoveTextureButton.Enabled = true; ReplaceTextureButton.Enabled = true; if (mipchange) { if (mip >= tex.Levels) { mip = tex.Levels - 1; } } else { SelTextureMipTrackBar.Maximum = tex.Levels - 1; } SelTextureNameTextBox.Text = tex.Name; DetailsPropertyGrid.SelectedObject = tex; try { int cmip = Math.Min(Math.Max(mip, 0), tex.Levels - 1); byte[] pixels = DDSIO.GetPixels(tex, cmip); int w = tex.Width >> cmip; int h = tex.Height >> cmip; Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb); if (pixels != null) { var BoundsRect = new System.Drawing.Rectangle(0, 0, w, h); BitmapData bmpData = bmp.LockBits(BoundsRect, ImageLockMode.WriteOnly, bmp.PixelFormat); IntPtr ptr = bmpData.Scan0; int bytes = bmpData.Stride * bmp.Height; Marshal.Copy(pixels, 0, ptr, bytes); bmp.UnlockBits(bmpData); } var dimstr = w.ToString() + " x " + h.ToString(); SelTexturePictureBox.Image = bmp; SelTextureDimensionsLabel.Text = dimstr; var str1 = GetTexCountStr(); var str2 = tex.Name + ", mip " + cmip.ToString() + ", " + dimstr; if (!string.IsNullOrEmpty(str1)) { UpdateStatus(str1 + ". " + str2); } else { UpdateStatus(str2); } } catch (Exception ex) { UpdateStatus("Error reading texture mip: " + ex.ToString()); SelTexturePictureBox.Image = null; } UpdateZoom(); }
static void ExtractFilesInRPF(RpfFile rpf, string directoryOffset) { try { using (BinaryReader br = new BinaryReader(File.OpenRead(rpf.GetPhysicalFilePath()))) { foreach (RpfEntry entry in rpf.AllEntries) { if (!entry.NameLower.EndsWith(".rpf")) //don't try to extract rpf's, they will be done separately.. { if (entry is RpfBinaryFileEntry) { RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); if (data == null) { if (binentry.FileSize == 0) { Console.WriteLine("Invalid binary file size!"); } else { Console.WriteLine("data is null!"); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("binary meme -> " + entry.NameLower); File.WriteAllBytes(directoryOffset + entry.NameLower, data); } } else if (entry is RpfResourceFileEntry) { RpfResourceFileEntry resentry = entry as RpfResourceFileEntry; byte[] data = rpf.ExtractFileResource(resentry, br); data = ResourceBuilder.Compress(data); //not completely ideal to recompress it... data = ResourceBuilder.AddResourceHeader(resentry, data); if (data == null) { if (resentry.FileSize == 0) { Console.WriteLine("{0} : Resource FileSize is 0.", entry.Path); } else { Console.WriteLine("{0} : {1}", entry.Path); } } else if (data.Length == 0) { Console.WriteLine("{0} : Decompressed output was empty.", entry.Path); } else { Console.WriteLine("Potential meme -> " + entry.NameLower); foreach (KeyValuePair <string, string[]> extentionMap in extensions) { foreach (string extention in extentionMap.Value) { if (entry.NameLower.EndsWith(extention)) { Console.WriteLine("Resource meme -> " + entry.NameLower); if (extention.Equals(".ytd")) { RpfFileEntry rpfent = entry as RpfFileEntry; byte[] ytddata = rpfent.File.ExtractFile(rpfent); bool needsResized = ytddata.Length > 5242880; // 5MB YtdFile ytd = new YtdFile(); ytd.Load(ytddata, rpfent); Dictionary <uint, Texture> Dicts = new Dictionary <uint, Texture>(); bool somethingResized = false; foreach (KeyValuePair <uint, Texture> texture in ytd.TextureDict.Dict) { if (texture.Value.Width > 1440 || needsResized && texture.Value.Width > 550) // Only resize if it is greater than 1440p or 550p if vehicle is oversized { byte[] dds = DDSIO.GetDDSFile(texture.Value); string fileName = $"{texture.Value.Name}.dds"; fileName = String.Concat(fileName.Where(c => !Char.IsWhiteSpace(c))); File.WriteAllBytes("./NConvert/" + fileName, dds); Process p = new Process(); p.StartInfo.FileName = @"./NConvert/nconvert.exe"; p.StartInfo.Arguments = @"-out dds -resize 50% 50% -overwrite ./NConvert/" + fileName; p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.Start(); //Wait for the process to end. p.WaitForExit(); // Move file back File.Move("./NConvert/" + fileName, directoryOffset + fileName); byte[] resizedData = File.ReadAllBytes(directoryOffset + fileName); Texture resizedTex = DDSIO.GetTexture(resizedData); resizedTex.Name = texture.Value.Name; Console.WriteLine(resizedData.Length.ToString()); Dicts.Add(texture.Key, resizedTex); // Yeet the file, we are done with it File.Delete(directoryOffset + fileName); somethingResized = true; } else { Dicts.Add(texture.Key, texture.Value); } } // No point rebuilding the ytd when nothing was resized if (!somethingResized) { break; } TextureDictionary dic = new TextureDictionary(); dic.Textures = new ResourcePointerList64 <Texture>(); dic.TextureNameHashes = new ResourceSimpleList64_uint(); dic.Textures.data_items = Dicts.Values.ToArray(); dic.TextureNameHashes.data_items = Dicts.Keys.ToArray(); dic.BuildDict(); ytd.TextureDict = dic; byte[] resizedYtdData = ytd.Save(); File.WriteAllBytes(directoryOffset + entry.NameLower, resizedYtdData); Console.WriteLine("Done some ytd resize memes -> " + entry.NameLower); break; } File.WriteAllBytes(directoryOffset + entry.NameLower, data); break; } } } if (entry.NameLower.EndsWith(".ytd")) { latestModelName = entry.NameLower.Remove(entry.NameLower.Length - 4); } } } } else { // Write file first RpfBinaryFileEntry binentry = entry as RpfBinaryFileEntry; byte[] data = rpf.ExtractFileBinary(binentry, br); File.WriteAllBytes(directoryOffset + entry.NameLower, data); RpfFile subRPF = new RpfFile(directoryOffset + entry.NameLower, directoryOffset + entry.NameLower); if (subRPF.ScanStructure(null, null)) { //recursive memes ExtractFilesInRPF(subRPF, directoryOffset); } //yeet File.Delete(directoryOffset + entry.NameLower); } } } } catch (Exception e) { Console.WriteLine("Exception memes!"); Console.WriteLine(e.Message); } }
public static JObject Deamon_GetDrawableJSON(GtaDrawable drawable, string drawablePath) { Console.WriteLine("Requested drawable : " + drawable.Name.Value); var txds = Deamon_LoadExternalTextures(drawablePath); var data = new JObject() { ["shaderGroup"] = new JObject() { ["shaders"] = new JArray(), ["textures"] = new JArray() }, ["models"] = new JObject() { ["high"] = new JArray(), ["medium"] = new JArray(), ["low"] = new JArray(), ["verylow"] = new JArray(), ["x"] = new JArray(), } }; var jShaders = (JArray)data["shaderGroup"]["shaders"]; var jTextures = (JArray)data["shaderGroup"]["textures"]; for (int i = 0; i < drawable.ShaderGroup.Shaders.Count; i++) { var shader = drawable.ShaderGroup.Shaders[i]; var jShader = new JObject() { ["textures"] = new JObject() }; for (int j = 0; j < shader.ParametersList.Parameters.Count; j++) { var param = shader.ParametersList.Parameters[j]; if (param.Data is TextureDX11) { var tx = param.Data as TextureDX11; var txName = tx.Name.Value.ToLowerInvariant(); switch (param.Unknown_1h) { case 0: jShader["textures"]["diffuse"] = txName; break; case 2: jShader["textures"]["specular"] = txName; break; case 3: jShader["textures"]["bump"] = txName; break; } } else if (param.Data is Texture) { var txName = (param.Data as Texture).Name.Value.ToLowerInvariant(); for (int k = 0; k < txds.Length; k++) { var txd = txds[k]; for (int l = 0; l < txd.TextureDictionary.Textures.Entries.Count; l++) { var tx = txd.TextureDictionary.Textures.Entries[l]; var txName2 = tx.Name.Value.ToLowerInvariant(); if (txName == txName2) { switch (param.Unknown_1h) { case 0: jShader["textures"]["diffuse"] = txName; break; case 2: jShader["textures"]["specular"] = txName; break; case 3: jShader["textures"]["bump"] = txName; break; } break; } } } } } jShaders.Add(jShader); } for (int i = 0; i < txds.Length; i++) { var txd = txds[i]; for (int j = 0; j < txd.TextureDictionary.Textures.Entries.Count; j++) { var tx = txd.TextureDictionary.Textures.Entries[j]; var txWrapper = new TextureWrapper_GTA5_pc(tx); var txName = tx.Name.Value.ToLowerInvariant(); var path = Path.GetTempPath() + "\\gtautil_texture_" + txName + ".dds"; for (int m = 0; m < jShaders.Count; m++) { var jShader = (JObject)jShaders[m]; if ((string)jShader["textures"]["diffuse"] == txName || (string)jShader["textures"]["specular"] == txName || (string)jShader["textures"]["bump"] == txName) { Console.WriteLine("Reusing external texture " + txName); DDSIO.SaveTextureData(txWrapper, path); Utils.Hash(txName); var jTx = new JObject(); var txNameHash = Jenkins.Hash(txName); jTx["hash"] = txNameHash; jTx["name"] = txName; jTx["path"] = path; jTx["width"] = tx.Width; jTx["height"] = tx.Height; jTextures.Add(jTx); } } } } for (int i = 0; i < drawable.ShaderGroup.TextureDictionary.Textures.Entries.Count; i++) { var tx = drawable.ShaderGroup.TextureDictionary.Textures.Entries[i]; var txWrapper = new TextureWrapper_GTA5_pc(tx); var txName = tx.Name.Value.ToLowerInvariant(); var path = Path.GetTempPath() + "\\gtautil_texture_" + txName + ".dds"; DDSIO.SaveTextureData(txWrapper, path); Utils.Hash(txName); var jTx = new JObject(); var txNameHash = drawable.ShaderGroup.TextureDictionary.TextureNameHashes.Entries[i].Value; jTx["hash"] = txNameHash; jTx["name"] = txName; jTx["path"] = path; jTx["width"] = tx.Width; jTx["height"] = tx.Height; jTextures.Add(jTx); } for (int i = 0; i < drawable.DrawableModelsHigh.Entries.Count; i++) { var jModel = Deamon_GetModelData(drawable.DrawableModelsHigh?.Entries[i]); ((JArray)data["models"]["high"]).Add(jModel); } for (int i = 0; i < drawable.DrawableModelsMedium?.Entries.Count; i++) { var jModel = Deamon_GetModelData(drawable.DrawableModelsMedium.Entries[i]); ((JArray)data["models"]["medium"]).Add(jModel); } for (int i = 0; i < drawable.DrawableModelsLow?.Entries.Count; i++) { var jModel = Deamon_GetModelData(drawable.DrawableModelsLow.Entries[i]); ((JArray)data["models"]["low"]).Add(jModel); } for (int i = 0; i < drawable.DrawableModelsVeryLow?.Entries.Count; i++) { var jModel = Deamon_GetModelData(drawable.DrawableModelsVeryLow.Entries[i]); ((JArray)data["models"]["verylow"]).Add(jModel); } for (int i = 0; i < drawable.DrawableModelsX?.Entries.Count; i++) { var jModel = Deamon_GetModelData(drawable.DrawableModelsX.Entries[i]); ((JArray)data["models"]["x"]).Add(jModel); } return(data); }
public Exporter(string name, ResourcePointerList64 <DrawableModel> models, GameFileCache Cache) { using (StreamWriter FBXwriter = new StreamWriter("FBX/" + name + ".fbx")) { var timestamp = DateTime.Now; int BaseId = 10000; StringBuilder fbx = new StringBuilder(); StringBuilder ob = new StringBuilder(); //Objects builder StringBuilder cb = new StringBuilder(); //Connections builder StringBuilder mb = new StringBuilder(); //Materials builder to get texture count in advance StringBuilder cb2 = new StringBuilder(); //and keep connections ordered cb.Append("\n}\n"); //Objects end cb.Append("\nConnections: {"); List <DrawableGeometry> Geoms = new List <DrawableGeometry>(); List <ShaderFX> Shaders = new List <ShaderFX>(); List <Texture> Textures = new List <Texture>(); //Models for (int mi = 0; mi < models.data_items.Length; mi++) { var model = models.data_items[mi]; //SubMesh & Materials foreach (var geom in model.Geometries.data_items) { if ((geom.Shader != null) && (geom.Shader.ParametersList != null) && (geom.Shader.ParametersList.Hashes != null)) { Geoms.Add(geom); Shaders.Add(geom.Shader); var gname = "Geom" + Geoms.Count; //创建节点 ob.AppendFormat("\n\tModel: 1{0}, \"Model::{1}\", \"Mesh\" {{", BaseId + Geoms.Count, gname); ob.Append("\n\t\tVersion: 232"); ob.Append("\n\t\tProperties70: {"); ob.Append("\n\t\t\tP: \"InheritType\", \"enum\", \"\", \"\",1"); ob.Append("\n\t\t\tP: \"ScalingMax\", \"Vector3D\", \"Vector\", \"\",0,0,0"); ob.Append("\n\t\t\tP: \"DefaultAttributeIndex\", \"int\", \"Integer\", \"\",0"); ob.AppendFormat("\n\t\t\tP: \"Lcl Translation\", \"Lcl Translation\", \"\", \"A\",{0},{1},{2}", 0, 0, 0); ob.AppendFormat("\n\t\t\tP: \"Lcl Rotation\", \"Lcl Rotation\", \"\", \"A\",{0},{1},{2}", 0, 0, 0);//handedness is switched in quat ob.AppendFormat("\n\t\t\tP: \"Lcl Scaling\", \"Lcl Scaling\", \"\", \"A\",{0},{1},{2}", 1, 1, 1); ob.Append("\n\t\t}"); ob.Append("\n\t\tShading: T"); ob.Append("\n\t\tCulling: \"CullingOff\"\n\t}"); //把节点挂在根节点上 cb.AppendFormat("\n\n\t;Model::{0}, Model::RootNode", gname); cb.AppendFormat("\n\tC: \"OO\",1{0},0", BaseId + Geoms.Count); //把几何体挂在节点上 cb2.AppendFormat("\n\n\t;Geometry::, Model::{0}", gname); cb2.AppendFormat("\n\tC: \"OO\",3{0},1{1}", BaseId + Geoms.Count, BaseId + Geoms.Count); //把材质挂在节点上 cb2.AppendFormat("\n\n\t;Material::, Model::{0}", gname); cb2.AppendFormat("\n\tC: \"OO\",6{0},1{1}", BaseId + Shaders.Count, BaseId + Geoms.Count); var pl = geom.Shader.ParametersList; var h = pl.Hashes; var p = pl.Parameters; for (int ip = 0; ip < h.Length; ip++) { var hash = pl.Hashes[ip]; var parm = pl.Parameters[ip]; var tex = parm.Data as TextureBase; if (tex != null) { var t = tex as Texture; if (t == null) { YtdFile file = Cache.TryGetTextureDictForTexture(tex.NameHash); if (file != null) { t = file.TextureDict.Lookup(tex.NameHash); } } var tstr = tex.Name.Trim(); if (t != null) { Textures.Add(t); cb2.AppendFormat("\n\n\t;Texture::, Material::{0}", geom.Shader.Name); cb2.AppendFormat("\n\tC: \"OP\",7{0},6{1}, ", BaseId + Textures.Count, BaseId + Shaders.Count); switch (hash.ToString().Trim()) { case "DiffuseSampler": cb2.Append("\"DiffuseColor\""); break; case "BumpSampler": cb2.Append("\"NormalMap\""); break; case "SpecSampler": cb2.Append("\"SpecularColor\""); break; case "DetailSampler": break; } } } } } } } fbx.Append("; FBX 7.1.0 project file"); fbx.Append("\nFBXHeaderExtension: {\n\tFBXHeaderVersion: 1003\n\tFBXVersion: 7100\n\tCreationTimeStamp: {\n\t\tVersion: 1000"); fbx.Append("\n\t\tYear: " + timestamp.Year); fbx.Append("\n\t\tMonth: " + timestamp.Month); fbx.Append("\n\t\tDay: " + timestamp.Day); fbx.Append("\n\t\tHour: " + timestamp.Hour); fbx.Append("\n\t\tMinute: " + timestamp.Minute); fbx.Append("\n\t\tSecond: " + timestamp.Second); fbx.Append("\n\t\tMillisecond: " + timestamp.Millisecond); fbx.Append("\n\t}\n\tCreator: \"Unity Studio by Chipicao\"\n}\n"); fbx.Append("\nGlobalSettings: {"); fbx.Append("\n\tVersion: 1000"); fbx.Append("\n\tProperties70: {"); fbx.Append("\n\t\tP: \"UpAxis\", \"int\", \"Integer\", \"\",1"); fbx.Append("\n\t\tP: \"UpAxisSign\", \"int\", \"Integer\", \"\",1"); fbx.Append("\n\t\tP: \"FrontAxis\", \"int\", \"Integer\", \"\",2"); fbx.Append("\n\t\tP: \"FrontAxisSign\", \"int\", \"Integer\", \"\",1"); fbx.Append("\n\t\tP: \"CoordAxis\", \"int\", \"Integer\", \"\",0"); fbx.Append("\n\t\tP: \"CoordAxisSign\", \"int\", \"Integer\", \"\",1"); fbx.Append("\n\t\tP: \"OriginalUpAxis\", \"int\", \"Integer\", \"\",1"); fbx.Append("\n\t\tP: \"OriginalUpAxisSign\", \"int\", \"Integer\", \"\",1"); fbx.AppendFormat("\n\t\tP: \"UnitScaleFactor\", \"double\", \"Number\", \"\",1"); fbx.Append("\n\t\tP: \"OriginalUnitScaleFactor\", \"double\", \"Number\", \"\",1.0"); fbx.Append("\n\t}\n}\n"); fbx.Append("\nDocuments: {"); fbx.Append("\n\tCount: 1"); fbx.Append("\n\tDocument: 1234567890, \"\", \"Scene\" {"); fbx.Append("\n\t\tProperties70: {"); fbx.Append("\n\t\t\tP: \"SourceObject\", \"object\", \"\", \"\""); fbx.Append("\n\t\t\tP: \"ActiveAnimStackName\", \"KString\", \"\", \"\", \"\""); fbx.Append("\n\t\t}"); fbx.Append("\n\t\tRootNode: 0"); fbx.Append("\n\t}\n}\n"); fbx.Append("\nReferences: {\n}\n"); fbx.Append("\nDefinitions: {"); fbx.Append("\n\tVersion: 100"); // fbx.AppendFormat("\n\tCount: {0}", 1 + 2 * GameObjects.Count + Materials.Count + 2 * Textures.Count + ((bool)Properties.Settings.Default["exportDeformers"] ? Skins.Count + DeformerCount + Skins.Count + 1 : 0)); fbx.Append("\n\tObjectType: \"GlobalSettings\" {"); fbx.Append("\n\t\tCount: 1"); fbx.Append("\n\t}"); fbx.Append("\n\tObjectType: \"Model\" {"); fbx.AppendFormat("\n\t\tCount: {0}", 1); fbx.Append("\n\t}"); fbx.Append("\n\tObjectType: \"Geometry\" {"); fbx.AppendFormat("\n\t\tCount: {0}", Geoms.Count); fbx.Append("\n\t}"); fbx.Append("\n\tObjectType: \"Material\" {"); fbx.AppendFormat("\n\t\tCount: {0}", Shaders.Count); fbx.Append("\n\t}"); fbx.Append("\n\tObjectType: \"Texture\" {"); fbx.AppendFormat("\n\t\tCount: {0}", Textures.Count); fbx.Append("\n\t}"); fbx.Append("\n}\n"); fbx.Append("\nObjects: {"); FBXwriter.Write(fbx); fbx.Clear(); for (int i = 0; i < Shaders.Count; i++) { ShaderFX Shader = Shaders[i]; mb.AppendFormat("\n\tMaterial: 6{0}, \"Material::{1}\", \"\" {{", BaseId + i + 1, Shader.Name); mb.Append("\n\t\tVersion: 102"); mb.Append("\n\t\tShadingModel: \"phong\""); mb.Append("\n\t\tMultiLayer: 0"); mb.Append("\n\t\tProperties70: {"); mb.Append("\n\t\t\tP: \"ShadingModel\", \"KString\", \"\", \"\", \"phong\""); //mb.Append("\n\t\t\tP: \"SpecularFactor\", \"Number\", \"\", \"A\",0"); mb.Append("\n\t\t}"); mb.Append("\n\t}"); } for (int i = 0; i < Geoms.Count; i++) { MeshFBX(Geoms[i], BaseId + i + 1, ob); //write data 8MB at a time if (ob.Length > (8 * 0x100000)) { FBXwriter.Write(ob); ob.Clear(); } } for (int i = 0; i < Textures.Count; i++) { Texture t = Textures[i]; //TODO check texture type and set path accordingly; eg. CubeMap, Texture3D string texFilename = Path.GetFullPath("FBX/" + t.Name + ".png"); byte[] bytes = DDSIO.GetPixels(t, 0); FileStream stream = new FileStream(texFilename, FileMode.Create); PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Interlace = PngInterlaceOption.On; encoder.Frames.Add(BitmapFrame.Create(BitmapSource.Create(t.Width, t.Height, 96, 96, PixelFormats.Bgra32, null, bytes, t.Width * 4))); encoder.Save(stream); stream.Close(); // File.WriteAllBytes(texFilename, DDSIO.GetDDSFile(t)); ob.AppendFormat("\n\tTexture: 7{0}, \"Texture::{1}\", \"\" {{", BaseId + i + 1, t.Name); ob.Append("\n\t\tType: \"TextureVideoClip\""); ob.Append("\n\t\tVersion: 202"); ob.AppendFormat("\n\t\tTextureName: \"Texture::{0}\"", t.Name); ob.Append("\n\t\tProperties70: {"); ob.Append("\n\t\t\tP: \"UVSet\", \"KString\", \"\", \"\", \"UVChannel_0\""); ob.Append("\n\t\t\tP: \"UseMaterial\", \"bool\", \"\", \"\",1"); ob.Append("\n\t\t}"); ob.AppendFormat("\n\t\tMedia: \"Video::{0}\"", t.Name); ob.AppendFormat("\n\t\tFileName: \"{0}\"", texFilename); ob.AppendFormat("\n\t\tRelativeFilename: \"{0}\"", texFilename); ob.Append("\n\t}"); } ob.Append(mb); mb.Clear(); cb.Append(cb2); cb2.Clear(); FBXwriter.Write(ob); ob.Clear(); cb.Append("\n}");//Connections end FBXwriter.Write(cb); cb.Clear(); } }