view RTXFile.cs @ 0:82db9430c2e4 default tip

Initial commit under GPLv3
author IBBoard <dev@ibboard.co.uk>
date Sat, 06 Oct 2018 19:49:25 +0100
parents
children
line wrap: on
line source

// This file is a part of the Relic Tools and is copyright 2006-2018 IBBoard.
//
// The file and the library/program it is in are licensed under the GNU GPL license, either version 3 of the License or (at your option) any later version. Please see COPYING for more information and the full license.
using System;
using System.IO;
using IBBoard.Relic.RelicTools.Exceptions;
using IBBoard.Relic.RelicTools.Collections;


namespace IBBoard.Relic.RelicTools
{
	/// <summary>
	/// Summary description for WTPFile.
	/// </summary>
	public class RTXFile:RelicChunkyFile
	{
		int width = 0;
		int height = 0;
		int id = 0;

		public RTXFile(string filename, ChunkyFolder folder)
			:this(filename, new ChunkyStructureCollection(new RelicChunkyStructure(folder))){}
		
		public RTXFile(string filename, ChunkyCollection col)
			:this(filename, new ChunkyStructureCollection(new RelicChunkyStructure(col))){}

		public RTXFile(string filename, ChunkyStructureCollection col): base(filename, col)
		{	
			int lastIndex = filename.LastIndexOf('_');
			
			if (lastIndex == -1 ||  filename.IndexOf('_')==lastIndex)
			{
				throw new InvalidFileException("RTX file name specified must end with a skin name and number e.g. _default_0.rtx");
			}

			try
			{
				int dot = filename.LastIndexOf('.');
				lastIndex++;
				id = int.Parse(filename.Substring(lastIndex, dot - lastIndex));
			}
			catch(FormatException)
			{
				throw new InvalidFileException("RTX file name specified must end with a skin name and number e.g. _default_0.rtx");
			}

			FindAttributes((ChunkyFolder)this.ChunkyStructures[0].RootChunks[0]);			
		}

		private void FindAttributes(ChunkyFolder folder)
		{
			int children = folder.Children.Count;
			ChunkyChunk chunk = null;
			ChunkyDataATTR attr = null;

			for (int i = 0; i<children; i++)
			{
				chunk = folder.Children[i];

				if (chunk is ChunkyDataATTR)
				{
					attr = (ChunkyDataATTR)chunk;
					width = attr.Width;
					height = attr.Height;
					break;
				}
				else if (chunk is ChunkyFolder)
				{
					FindAttributes((ChunkyFolder)chunk);
				}
			}
		}

		public void SaveParts(DirectoryInfo destination)
		{
			string filenamebase = filename.Substring(0, filename.LastIndexOf('.'));

			saveFolder((ChunkyFolder)this.ChunkyStructures[0].RootChunks[0], destination, filenamebase);
		}

		private void saveFolder(ChunkyFolder folder, DirectoryInfo destination, string filenamebase)
		{
			int children = folder.Children.Count;
			ChunkyChunk chunk = null;

			for (int i = 0; i<children; i++)
			{
				chunk = folder.Children[i];

				if (chunk is ChunkyFolder)
				{
					this.saveFolder((ChunkyFolder)chunk, destination, filenamebase);
				}
				/*else if (chunk is ChunkyDataATTR)
				{
					attr = (ChunkyDataATTR)chunk;
					imagetype = attr.ImageType;
					mipmaps = attr.MipMaps;
				}*/
				else if (chunk is ChunkyDataDATAIMAG)
				{
					((ChunkyDataDATAIMAG)chunk).Save(destination, filenamebase);
				}
			}
		}

		public static RTXFile Create(string filepath)
		{
			string baseFileName = filepath.Substring(filepath.LastIndexOf(Path.DirectorySeparatorChar)+1);
			string baseFileNameLower = baseFileName.ToLower();

			string directory = "";

			if (filepath.IndexOf(Path.DirectorySeparatorChar)!=-1)
			{
				directory = filepath.Substring(0, filepath.LastIndexOf(Path.DirectorySeparatorChar))+Path.DirectorySeparatorChar;
			}
			
			if(baseFileNameLower.EndsWith(".dds"))
			{
				baseFileName = baseFileName.Substring(0, baseFileName.Length-4);
			}
			else
			{
				throw new InvalidFileException("File path specified is not valid for a RTX file");
			}

			string unit_name = "";
			int lastUnderscore = baseFileName.LastIndexOf('_');

			if (lastUnderscore!=-1)
			{
				unit_name = baseFileName.Substring(0, lastUnderscore);//trim the number

				try
				{
					int id = int.Parse(baseFileName.Substring(lastUnderscore+1));
				}
				catch
				{
					throw new InvalidFileException("DDS file name specified must end with a number to identify RTX e.g. _default_0.dds");
				}

				lastUnderscore = unit_name.LastIndexOf('_');
				if (lastUnderscore!=-1)
				{
					unit_name = unit_name.Substring(0, lastUnderscore);
				}
				else
				{
					throw new InvalidFileException("DDS file name specified must end with a skin name followed by a number e.g. _default_0.dds");
				}
			}
			else
			{
				throw new InvalidFileException("DDS file name specified must end with a skin name and number e.g. _default_0.dds");
			}

			ChunkyDataDATA defaultData = null;
			ChunkyData attr = null;
			byte [] data;

			int width = 0;
			int height = 0;
			int mipmaps = 0;

			if (File.Exists(directory+baseFileName+".dds"))
			{
				CompilationEvent("Reading "+baseFileName+".dds");
				FileInfo file = new FileInfo(directory+baseFileName+".dds");
				BinaryReader br = new BinaryReader(file.OpenRead());
				br.BaseStream.Seek(0, SeekOrigin.Begin);
				data = br.ReadBytes((int)file.Length);

				defaultData = ChunkyDataDATAIMAG.CreateFromDDS(2, "", data);
				
				br.BaseStream.Seek(12,SeekOrigin.Begin);
				height = br.ReadInt32();
				width = br.ReadInt32();
				int size = br.ReadInt32();
				br.BaseStream.Seek(4, SeekOrigin.Current);
				mipmaps = br.ReadInt32();
				br.Close();

				byte type = 0x8;

				if (size==width*height)
				{
					type = 0xb;
				}

				data = new byte[]{type, 0x0, 0x0, 0x0, (byte)width, (byte)(width>>8), (byte)(width>>16), (byte)(width>>24), (byte)(height), (byte)(height>>8), (byte)(height>>16), (byte)(height>>24), (byte)mipmaps, (byte)(mipmaps>>8), (byte)(mipmaps>>16), (byte)(mipmaps>>24)};
				attr = new ChunkyDataUnknown("ATTR", 2, "", data);
			}
			else
			{
				throw new RelicTools.Exceptions.FileNotFoundException("RTX files must be made from a DDS file");
			}

			ChunkyFolder defaultFolder = new ChunkyFolder("IMAG", 1, "");

			defaultFolder.Children.Add(attr);
			defaultFolder.Children.Add(defaultData);

			ChunkyData head = new ChunkyDataUnknown("HEAD", 1, "", new byte[]{0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00});


			CompilationEvent("Compiling RTX File");
			ChunkyFolder txtr = new ChunkyFolder("TXTR", 1, unit_name);
			txtr.Children.Add(head);
			txtr.Children.Add(defaultFolder);
			return new RTXFile(baseFileName+".rtx", txtr);
			//RelicChunkyFile.SaveChunky(directory+baseFileName+".rtx", txtr.GetBytes());
		}
	}
}