public Event ( String message ) : void | ||
message | String | The message to explain the event |
return | void |
public static bool Read(int skin, IFileEntry file, ref Dictionary<String, String> animations, Logger logger) { bool result = true; logger.Event("Parsing animation list: " + file.FileName ); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); StreamReader reader = new StreamReader(myInput); ParseAnimations(skin, reader, ref animations); reader.Close(); myInput.Close(); } catch { logger.Error("Failed to parse animation list: " + file.FileName); result = false; animations.Clear(); } return result; }
public static bool Read(RAFFileListEntry file, ref InibinFile data, Logger logger) { bool result = true; logger.Event("Reading inibin: " + file.FileName); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); result = ReadCharacterInibin(myInput, ref data, logger); int end = file.FileName.LastIndexOf("/"); String directory = file.FileName.Substring(0, end); String archive = file.RAFArchive.RAFFilePath; archive = archive.Replace("\\", "/"); end = archive.LastIndexOf("/"); archive = archive.Substring(0, end); data.directory = new DirectoryInfo(archive + "/" + directory); myInput.Close(); } catch(Exception e) { logger.Error("Unable to open memory stream: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
/// <summary> /// Read in binary .dds file from RAF. /// </summary> /// <param name="file">The file.</param> /// <param name="data">The contents of the file are stored in here.</param> /// <returns></returns> public static bool Read(RAFFileListEntry file, ref Bitmap bitmap, Logger logger) { bool result = true; logger.Event("Reading dds: " + file.FileName); try { // Create image. int[] images = new int[1]; Il.ilGenImages(1, images); // Bind image. Il.ilBindImage(images[0]); // Load the image data into DevIL. byte[] data = file.GetContent(); result = Il.ilLoadL(Il.IL_DDS, data, data.Length); if (result == true) { int width = Il.ilGetInteger(Il.IL_IMAGE_WIDTH); int height = Il.ilGetInteger(Il.IL_IMAGE_HEIGHT); ; // Create the bitmap. bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); Rectangle rect = new Rectangle(0, 0, width, height); // Store the DevIL image data into the bitmap. BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); Il.ilConvertImage(Il.IL_BGRA, Il.IL_UNSIGNED_BYTE); Il.ilCopyPixels(0, 0, 0, width, height, 1, Il.IL_BGRA, Il.IL_UNSIGNED_BYTE, bitmapData.Scan0); bitmap.UnlockBits(bitmapData); } // Free image. Il.ilDeleteImages(1, images); if (result == false) { throw new System.Exception("Unable to load image data."); } } catch(Exception e) { logger.Error("Unable to open dds file: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
/// <summary> /// Read in binary .anm file from RAF. /// </summary> /// <param name="file">The file.</param> /// <param name="data">The contents of the file are stored in here.</param> /// <returns></returns> public static bool Read(RAFFileListEntry file, ref ANMFile data, Logger logger) { bool result = true; logger.Event("Reading anm: " + file.FileName); try { // Get the data from the archive MemoryStream myInput = new MemoryStream( file.GetContent() ); result = ReadBinary(myInput, ref data, logger); myInput.Close(); } catch(Exception e) { logger.Error("Unable to open memory stream: " + file.FileName); logger.Error(e.Message); result = false; } return result; }
// // Helper creation function. // private bool Create(List<float> vertexPositions, List<float> vertexNormals, List<float> vertexTextureCoordinates, List<uint> indices, Logger logger) { bool result = true; logger.Event("Creating OpenGL static model."); numIndices = indices.Count; // Create Vertex Array Object if (result == true) { GL.GenVertexArrays(1, out vao); } ErrorCode error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Bind VAO if (result == true) { GL.BindVertexArray(vao); } // Create the VBOs int[] buffers = new int[4]; if (result == true) { GL.GenBuffers(4, buffers); } // Check for errors error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Store data and bind vertex buffer. if (result == true) { vertexPositionBuffer = buffers[0]; vertexNormalBuffer = buffers[1]; vertexTextureCoordinateBuffer = buffers[2]; indexBuffer = buffers[3]; GL.BindBuffer(BufferTarget.ArrayBuffer, vertexPositionBuffer); } // // // Set vertex data. // // if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexPositions.Count * sizeof(float)), vertexPositions.ToArray(), BufferUsageHint.StaticDraw); } // Check for errors. error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put vertices into attribute slot 0. if (result == true) { GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(0); } // // // Bind normal buffer. // // if (result == true) { GL.BindBuffer(BufferTarget.ArrayBuffer, vertexNormalBuffer); } // Set normal data. if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexNormals.Count * sizeof(float)), vertexNormals.ToArray(), BufferUsageHint.StaticDraw); } // Check for errors. error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put normals into attribute slot 1. if (result == true) { GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(1); } // // // Bind texture cordinates buffer. // // if (result == true) { GL.BindBuffer(BufferTarget.ArrayBuffer, vertexTextureCoordinateBuffer); } // Set Texture Coordinate Data if (result == true) { GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(vertexTextureCoordinates.Count * sizeof(float)), vertexTextureCoordinates.ToArray(), BufferUsageHint.StaticDraw); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Put texture coords into attribute slot 2. if (result == true) { GL.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 0, 0); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Enable the attribute index. if (result == true) { GL.EnableVertexAttribArray(2); } // Bind index buffer. if (result == true) { GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer); } // Set index data. if (result == true) { GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(indices.Count * sizeof(uint)), indices.ToArray(), BufferUsageHint.StaticDraw); } error = GL.GetError(); if (error != ErrorCode.NoError) { result = false; } // Unbind VAO from pipeline. if (result == true) { GL.BindVertexArray(0); } else { logger.Error("Failed to create OpenGL static model."); } return result; }
public MainWindow() { logger = new Logger(DEFAULT_LOG_FILE); // Not checking result. logger.Event("Program Start."); isGLLoaded = false; timer = new Stopwatch(); camera = new GLCamera(); camera.SetViewParameters(new Vector3(0.0f, 0.0f, 2.0f), Vector3.Zero); renderer = new GLRenderer(); // Set up the reader and initialize its root to the value in 'lolviewer.dat' if // the file exists. { reader = new LOLDirectoryReader(); bool isFileOpen = false; FileStream file = null; try { FileInfo fileInfo = new FileInfo(DEFAULT_DATA_FILE); if (fileInfo.Exists == true) { file = new FileStream(fileInfo.FullName, FileMode.Open); isFileOpen = true; } else { logger.Warning("Failed to locate " + DEFAULT_DATA_FILE + "."); } } catch { logger.Warning("Failed to open " + DEFAULT_DATA_FILE + "."); } if (isFileOpen == true) { BinaryReader fileReader = null; if (file != null) { try { logger.Event("Reading " + DEFAULT_DATA_FILE + "."); fileReader = new BinaryReader(file); reader.Root = fileReader.ReadString(); fileReader.Close(); } catch { logger.Warning("Failed to read " + DEFAULT_DATA_FILE + "."); file.Close(); } } } } InitializeComponent(); mainWindowProgressBar.Style = ProgressBarStyle.Marquee; mainWindowProgressBar.Value = 100; lastSearch = String.Empty; currentSearchSubset = new List<String>(); // Main window Callbacks this.Shown += new EventHandler(OnMainWindowShown); // GLControl Callbacks glControlMain.Load += new EventHandler(GLControlMainOnLoad); glControlMain.Resize += new EventHandler(GLControlMainOnResize); glControlMain.Paint += new PaintEventHandler(GLControlMainOnPaint); glControlMain.Disposed += new EventHandler(GLControlMainOnDispose); // Set mouse events glControlMain.MouseDown += new MouseEventHandler(GLControlOnMouseDown); glControlMain.MouseUp += new MouseEventHandler(GLControlOnMouseUp); glControlMain.MouseWheel += new MouseEventHandler(GLControlOnMouseWheel); glControlMain.MouseMove += new MouseEventHandler(GLControlOnMouseMove); // Set keyboard events glControlMain.KeyDown += new KeyEventHandler(GLControlMainOnKeyDown); glControlMain.KeyUp += new KeyEventHandler(GLControlMainOnKeyUp); // Menu Callbacks exitToolStripMenuItem.Click += new EventHandler(OnExit); aboutToolStripMenuItem.Click += new EventHandler(OnAbout); readDirectoryMainMenuStripItem.Click += new EventHandler(OnReadModels); readMainMenuStripItem.Click += new EventHandler(OnSetDirectory); // Model View Callbacks modelListBox.DoubleClick += new EventHandler(OnModelListDoubleClick); modelListBox.KeyPress += new KeyPressEventHandler(OnModelListKeyPress); // Buttons resetCameraButton.Click += new EventHandler(OnResetCameraButtonClick); backgroundColorButton.Click += new EventHandler(OnBackgroundColorButtonClick); fullscreenButton.Click += new EventHandler(OnFullscreenButtonClick); // // Animation Controller // // TODO: Pass the references and callbacks into constructor instead of doing them out here. // Kind of ugly code. :( animationController = new AnimationController(); // Set references animationController.enableAnimationButton = enableAnimationButton; animationController.currentAnimationComboBox = currentAnimationComboBox; animationController.playAnimationButton = playAnimationButton; animationController.glControlMain = glControlMain; animationController.timelineTrackBar = timelineTrackBar; animationController.mainWindowStatusLabel = mainWindowStatusLabel; animationController.renderer = renderer; // Set callbacks. enableAnimationButton.Click += new EventHandler(animationController.OnEnableAnimationButtonClick); playAnimationButton.Click += new EventHandler(animationController.OnPlayAnimationButtonClick); currentAnimationComboBox.SelectedIndexChanged += new EventHandler(animationController.OnCurrentAnimationComboBoxSelectedIndexChanged); timelineTrackBar.Scroll += new EventHandler(animationController.OnTimelineTrackBar); animationController.DisableAnimation(); // // End Animation Controller // // Search Box modelSearchBox.TextChanged += new EventHandler(OnModelSearchBoxTextChanged); modelSearchBox.KeyPress += new KeyPressEventHandler(OnModelSearchBoxKeyPress); modelSearchBox.KeyDown += new KeyEventHandler(OnModelSearchBoxKeyDown); }
private static bool ReadData(BinaryReader file, ref ANMFile data, Logger logger) { bool result = true; try { // File Header Information. data.id = new String(file.ReadChars(ANMFile.ID_SIZE)); data.version = file.ReadUInt32(); // Version 0, 1, 2, 3 Code if (data.version == 0 || data.version == 1 || data.version == 2 || data.version == 3) { // // Header information specific to these versions. // data.magic = file.ReadUInt32(); data.numberOfBones = file.ReadUInt32(); data.numberOfFrames = file.ReadUInt32(); data.playbackFPS = file.ReadUInt32(); // Read in all the bones for (UInt32 i = 0; i < data.numberOfBones; ++i) { ANMBone bone = new ANMBone(); bone.name = new String(file.ReadChars(ANMBone.BONE_NAME_LENGTH)); bone.name = RemoveAnimationNamePadding(bone.name); bone.name = bone.name.ToLower(); // Unknown file.ReadUInt32(); // For each bone, read in its value at each frame in the animation. for (UInt32 j = 0; j < data.numberOfFrames; ++j) { ANMFrame frame = new ANMFrame(); // Read in the frame's quaternion. frame.orientation[0] = file.ReadSingle(); // x frame.orientation[1] = file.ReadSingle(); // y frame.orientation[2] = file.ReadSingle(); // z frame.orientation[3] = file.ReadSingle(); // w // Read in the frame's position. frame.position[0] = file.ReadSingle(); // x frame.position[1] = file.ReadSingle(); // y frame.position[2] = file.ReadSingle(); // z bone.frames.Add(frame); } data.bones.Add(bone); } } // Version 4 Code else if (data.version == 4) { // // Based on the reverse engineering work of Hossein Ahmadi. // // In this version, position vectors and orientation quaternions are // stored separately in sorted, keyed blocks. The assumption is Riot // is removing duplicate vectors and quaternions by using an indexing scheme // to look up values. // // So, after the header, there are three data sections: a vector section, a quaternion // section, and a look up section. The number of vectors and quaternions // may not match the expected value based on the number of frames and bones. However, // the number of look ups should match this value and can be used to create the animation. // // Header information specific to version 4. // data.magic = file.ReadUInt32(); // Not sure what any of these mean. float unknown = file.ReadSingle(); unknown = file.ReadSingle(); unknown = file.ReadSingle(); data.numberOfBones = file.ReadUInt32(); data.numberOfFrames = file.ReadUInt32(); // Time per frame is stored in this file type. Need to invert it into FPS. data.playbackFPS = (UInt32) Math.Round(1.0f / file.ReadSingle()); // These are offsets to specific data sections in the file. UInt32 unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); UInt32 positionOffset = file.ReadUInt32(); UInt32 orientationOffset = file.ReadUInt32(); UInt32 indexOffset = file.ReadUInt32(); // These last three values are confusing. // They aren't a vector and they throw off the offset values // by 12 bytes. Just ignore them and keep reading. unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); unknownOffset = file.ReadUInt32(); // // Vector section. // List<float> positions = new List<float>(); UInt32 numberOfPositions = (orientationOffset - positionOffset) / sizeof(float); for (UInt32 i = 0; i < numberOfPositions; ++i) { positions.Add(file.ReadSingle()); } // // Quaternion section. // List<float> orientations = new List<float>(); UInt32 numberOfOrientations = (indexOffset - orientationOffset) / sizeof(float); for (UInt32 i = 0; i < numberOfOrientations; ++i) { orientations.Add(file.ReadSingle()); } // // Offset section. // // Note: Unlike versions 0-3, data in this version is // Frame 1: // Bone 1: // Bone 2: // ... // Frame 2: // Bone 1: // ... // Dictionary<UInt32, ANMBone> boneMap = new Dictionary<UInt32, ANMBone>(); for (Int32 i = 0; i < data.numberOfBones; ++i) { // // The first frame is a special case since we are allocating bones // as we read them in. // // Read in the offset data. UInt32 boneID = file.ReadUInt32(); UInt16 positionID = file.ReadUInt16(); UInt16 unknownIndex = file.ReadUInt16(); // Unknown. UInt16 orientationID = file.ReadUInt16(); unknownIndex = file.ReadUInt16(); // Unknown. Seems to always be zero. // Allocate the bone. ANMBone bone = new ANMBone(); bone.id = boneID; // Allocate all the frames for the bone. for (int j = 0; j < data.numberOfFrames; ++j) { bone.frames.Add(new ANMFrame()); } // Retrieve the data for the first frame. ANMFrame frame = bone.frames[0]; frame.position = LookUpVector(positionID, positions); frame.orientation = LookUpQuaternion(orientationID, orientations); // Store the bone in the dictionary by bone ID. boneMap[boneID] = bone; } Int32 currentFrame = 1; Int32 currentBone = 0; UInt32 numberOfLookUps = (data.numberOfFrames - 1) * data.numberOfBones; for (UInt32 i = 0; i < numberOfLookUps; ++i) { // // Normal case for all frames after the first. // // Read in the offset data. UInt32 boneID = file.ReadUInt32(); UInt16 positionID = file.ReadUInt16(); UInt16 unknownIndex = file.ReadUInt16(); // Unknown. UInt16 orientationID = file.ReadUInt16(); unknownIndex = file.ReadUInt16(); // Unknown. Seems to always be zero. // Retrieve the bone from the dictionary. // Note: The bones appear to be in the same order in every frame. So, a dictionary // isn't exactly needed and you could probably get away with a list. However, this way // feels safer just in case something ends up being out of order. ANMBone bone = boneMap[boneID]; ANMFrame frame = bone.frames[currentFrame]; frame.position = LookUpVector(positionID, positions); frame.orientation = LookUpQuaternion(orientationID, orientations); // This loop is slightly ambiguous. // // The problem is previous .anm versions contain data like: // foreach bone // foreach frame // // However, this version contains data like: // foreach frame // foreach bone // // So, reading one version is going to be a little goofy. currentBone++; if (currentBone >= data.numberOfBones) { currentBone = 0; currentFrame++; } } // Finally, we need to move all the data from the dictionary into the ANMFile. foreach(var bone in boneMap) { data.bones.Add(bone.Value); } // Currently returning false for this version. We can not render this version correctly yet. // So, we need to tell the viewer not to try and load it. result = false; } // Unknown version else { logger.Error("Unknown anm version: " + data.version); result = false; } } catch(Exception e) { logger.Error("Anm reading error."); logger.Error(e.Message); result = false; } logger.Event("File ID: " + data.id); logger.Event("Magic: " + data.magic); logger.Event("Version: " + data.version); logger.Event("Number of Bones: " + data.numberOfBones); logger.Event("Number of Frames: " + data.numberOfFrames); logger.Event("Playback FPS: " + data.playbackFPS); return result; }
private static bool ReadCharacterInibin(MemoryStream stream, ref InibinFile file, Logger logger) { bool result = true; file = new InibinFile(); stream.Seek( 0, SeekOrigin.Begin ); // Header Info int version = stream.ReadByte(); #if VERBOSE DebugOut("version", version); #endif int fileLen = (int) stream.Length; #if VERBOSE DebugOut("file length", fileLen); #endif int oldLen = (int)ReadShort(ref stream); #if VERBOSE DebugOut("old style length", oldLen); #endif int oldStyleOffset = fileLen - oldLen; #if VERBOSE DebugOut("old style offset", oldStyleOffset); #endif int format = (int) ReadShort(ref stream); #if VERBOSE DebugOut("format", format); #endif if ((format & 0x0001) == 0) { #if VERBOSE DebugOut("No U32 segment", "skipping"); #endif } else { // Reads values based on the hash keys. #if VERBOSE DebugOut("U32 properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { long val = (long)ReadInt32(ref stream); #if VERBOSE DebugOut("U32 prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // float values if ((format & 0x0002) == 0) { #if VERBOSE DebugOut("No float segment", "skipping"); #endif } else { #if VERBOSE DebugOut("Float properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { float val = ReadFloat(ref stream); #if VERBOSE DebugOut("float prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // U8 values if ((format & 0x0004) == 0) { #if VERBOSE DebugOut("No U8/10 segment", "skipping"); #endif } else { #if VERBOSE DebugOut("U8/10 properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { float val = stream.ReadByte() * 0.1F; #if VERBOSE DebugOut("U8/10 prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // U16 values if ((format & 0x0008) == 0) { #if VERBOSE DebugOut("No U16 segment", "skipping"); #endif } else { #if VERBOSE DebugOut("U16 properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { int val = (int)ReadShort(ref stream); #if VERBOSE DebugOut("U16 prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // U8 values if ((format & 0x0010) == 0) { #if VERBOSE DebugOut("No U8 segment", "skipping"); #endif } else { #if VERBOSE DebugOut("U8 properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { int val = 0xff & stream.ReadByte(); #if VERBOSE DebugOut("U8 prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // Boolean flags - single bit, ignoring if ((format & 0x0020) == 0) { #if VERBOSE DebugOut("No boolean segment", "skipping"); #endif } else { #if VERBOSE DebugOut("Boolean flags start position", stream.Position); #endif long[] booleanKeys = ReadSegmentKeys(ref stream); if (booleanKeys != null) { #if VERBOSE DebugOut("Boolean keys found", booleanKeys.Length); #endif int index = 0; for (int i = 0; i < 1 + ((booleanKeys.Length - 1) / 8); ++i) { int bits = stream.ReadByte(); for (int b = 0; b < 8; ++b) { long key = booleanKeys[index]; int val = 0x1 & bits; #if VERBOSE DebugOut("Boolean prop(" + key + ")", val); #endif file.AddProperty(key, val); bits = bits >> 1; if (++index == booleanKeys.Length) { break; } } } } } // 4-byte color values or something? if ((format & 0x0400) == 0) { #if VERBOSE DebugOut("No 4-byte color segment", "skipping"); #endif } else { #if VERBOSE DebugOut("Color? properties start position", stream.Position); #endif long[] keys = ReadSegmentKeys( ref stream ); if (keys != null) { foreach (long key in keys) { long val = (long)ReadInt32(ref stream); #if VERBOSE DebugOut("U32 color prop(" + key + ")", val); #endif file.AddProperty(key, val); } } } // Newer section. // I don't know what exactly these values represent. // I think it's related to champions with the new rage mechanic. // I'm just using it to increment the stream. // So, when I get to the part to read in strings, the pointer is at the // correct location. if ((format & 0x0080) == 0) { #if VERBOSE DebugOut("No offsets segment", "skipping"); #endif } else { #if VERBOSE DebugOut("Rage values start position", stream.Position); #endif long[] rageKeys = ReadSegmentKeys(ref stream); if (rageKeys != null) { #if VERBOSE DebugOut("Rage keys found", rageKeys.Length); #endif foreach (long key in rageKeys) { float val1 = ReadFloat(ref stream); float val2 = ReadFloat(ref stream); float val3 = ReadFloat(ref stream); #if VERBOSE DebugOut("Rage prop 1(" + key + ")", val1); DebugOut("Rage prop 2(" + key + ")", val2); DebugOut("Rage prop 3(" + key + ")", val3); #endif // If you actually need these values, figure out what 12 byte // structure they represent and add that property. // It's probably a Vector3. // file.AddProperty(key, MyRageKeyStructure); } } } // Old-style offsets to strings if ((format & 0x1000) == 0) { #if VERBOSE DebugOut("No offsets segment", "skipping"); #endif } else { #if VERBOSE DebugOut("Old style data position", stream.Position); #endif int lastOffset = -1; long[] keys = ReadSegmentKeys( ref stream ); // // New method to read the newer .inibins. // Why determine the offset by reading in data from the file header // when we can just compute it here? This seems to fix the problem // with newer .inibins. I'm not sure what the value in the header // is used for though. // if (keys != null) { oldStyleOffset = (int)stream.Position + keys.Length * 2; foreach (long key in keys) { int offset = (int)ReadShort(ref stream); #if VERBOSE DebugOut("String offset(" + key + ")", offset); #endif String val = ReadNullTerminatedString(ref stream, oldStyleOffset + offset); #if VERBOSE DebugOut("String prop(" + key + ")", val); #endif file.AddProperty(key, val); lastOffset = offset; } } } #if VERBOSE // Debuging Code //Debug.WriteLine("Skin #1 Name: " + file.properties[(long) InibinHashID.SKIN_ONE_NAME]); Debug.WriteLine("Skin #1 SKN: " + file.properties[(long) InibinHashID.SKIN_ONE_SKN]); Debug.WriteLine("Skin #1 SKL: " + file.properties[(long) InibinHashID.SKIN_ONE_SKL]); Debug.WriteLine("Skin #1 DDS: " + file.properties[(long) InibinHashID.SKIN_ONE_TEXTURE]); Debug.WriteLine("Skin #2 Name: " + file.properties[(long) InibinHashID.SKIN_TWO_NAME]); Debug.WriteLine("Skin #2 SKN: " + file.properties[(long) InibinHashID.SKIN_TWO_SKN]); Debug.WriteLine("Skin #2 SKL: " + file.properties[(long) InibinHashID.SKIN_TWO_SKL]); Debug.WriteLine("Skin #2 DDS: " + file.properties[(long) InibinHashID.SKIN_TWO_TEXTURE]); Debug.WriteLine("Skin #3 Name: " + file.properties[(long) InibinHashID.SKIN_THREE_NAME]); Debug.WriteLine("Skin #3 SKN: " + file.properties[(long) InibinHashID.SKIN_THREE_SKN]); Debug.WriteLine("Skin #3 SKL: " + file.properties[(long) InibinHashID.SKIN_THREE_SKL]); Debug.WriteLine("Skin #3 DDS: " + file.properties[(long) InibinHashID.SKIN_THREE_TEXTURE]); Debug.WriteLine("Skin #4 Name: " + file.properties[(long) InibinHashID.SKIN_FOUR_NAME]); Debug.WriteLine("Skin #4 SKN: " + file.properties[(long) InibinHashID.SKIN_FOUR_SKN]); Debug.WriteLine("Skin #4 SKL: " + file.properties[(long) InibinHashID.SKIN_FOUR_SKL]); Debug.WriteLine("Skin #4 DDS: " + file.properties[(long) InibinHashID.SKIN_FOUR_TEXTURE]); Debug.WriteLine("Skin #5 Name: " + file.properties[(long) InibinHashID.SKIN_FIVE_NAME]); Debug.WriteLine("Skin #5 SKN: " + file.properties[(long) InibinHashID.SKIN_FIVE_SKN]); Debug.WriteLine("Skin #5 SKL: " + file.properties[(long) InibinHashID.SKIN_FIVE_SKL]); Debug.WriteLine("Skin #5 DDS: " + file.properties[(long) InibinHashID.SKIN_FIVE_TEXTURE]); Debug.WriteLine("Skin #6 Name: " + file.properties[(long) InibinHashID.SKIN_SIX_NAME]); Debug.WriteLine("Skin #6 SKN: " + file.properties[(long) InibinHashID.SKIN_SIX_SKN]); Debug.WriteLine("Skin #6 SKL: " + file.properties[(long) InibinHashID.SKIN_SIX_SKL]); Debug.WriteLine("Skin #6 DDS: " + file.properties[(long) InibinHashID.SKIN_SIX_TEXTURE]); Debug.WriteLine("Skin #7 Name: " + file.properties[(long)InibinHashID.SKIN_SEVEN_NAME]); Debug.WriteLine("Skin #7 SKN: " + file.properties[(long)InibinHashID.SKIN_SEVEN_SKN]); Debug.WriteLine("Skin #7 SKL: " + file.properties[(long)InibinHashID.SKIN_SEVEN_SKL]); Debug.WriteLine("Skin #7 DDS: " + file.properties[(long)InibinHashID.SKIN_SEVEN_TEXTURE]); Debug.WriteLine("Skin #8 Name: " + file.properties[(long)InibinHashID.SKIN_EIGHT_NAME]); Debug.WriteLine("Skin #8 SKN: " + file.properties[(long)InibinHashID.SKIN_EIGHT_SKN]); Debug.WriteLine("Skin #8 SKL: " + file.properties[(long)InibinHashID.SKIN_EIGHT_SKL]); Debug.WriteLine("Skin #8 DDS: " + file.properties[(long)InibinHashID.SKIN_EIGHT_TEXTURE]); #endif logger.Event("Version: " + version); //if (file.properties.ContainsKey((long)InibinHashID.SKIN_ONE_NAME)) //logger.LogEvent("Skin #1 Name: " + file.properties[(long) InibinHashID.SKIN_ONE_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_ONE_SKN)) logger.Event("Skin #1 SKN: " + file.properties[(long)InibinHashID.SKIN_ONE_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_ONE_SKL)) logger.Event("Skin #1 SKL: " + file.properties[(long)InibinHashID.SKIN_ONE_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_ONE_TEXTURE)) logger.Event("Skin #1 DDS: " + file.properties[(long)InibinHashID.SKIN_ONE_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_TWO_NAME)) logger.Event("Skin #2 Name: " + file.properties[(long)InibinHashID.SKIN_TWO_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_TWO_SKN)) logger.Event("Skin #2 SKN: " + file.properties[(long)InibinHashID.SKIN_TWO_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_TWO_SKL)) logger.Event("Skin #2 SKL: " + file.properties[(long)InibinHashID.SKIN_TWO_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_TWO_TEXTURE)) logger.Event("Skin #2 DDS: " + file.properties[(long)InibinHashID.SKIN_TWO_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_THREE_NAME)) logger.Event("Skin #3 Name: " + file.properties[(long)InibinHashID.SKIN_THREE_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_THREE_SKN)) logger.Event("Skin #3 SKN: " + file.properties[(long)InibinHashID.SKIN_THREE_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_THREE_SKL)) logger.Event("Skin #3 SKL: " + file.properties[(long)InibinHashID.SKIN_THREE_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_THREE_TEXTURE)) logger.Event("Skin #3 DDS: " + file.properties[(long)InibinHashID.SKIN_THREE_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FOUR_NAME)) logger.Event("Skin #4 Name: " + file.properties[(long)InibinHashID.SKIN_FOUR_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FOUR_SKN)) logger.Event("Skin #4 SKN: " + file.properties[(long)InibinHashID.SKIN_FOUR_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FOUR_SKL)) logger.Event("Skin #4 SKL: " + file.properties[(long)InibinHashID.SKIN_FOUR_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FOUR_TEXTURE)) logger.Event("Skin #4 DDS: " + file.properties[(long)InibinHashID.SKIN_FOUR_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FIVE_NAME)) logger.Event("Skin #5 Name: " + file.properties[(long)InibinHashID.SKIN_FIVE_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FIVE_SKN)) logger.Event("Skin #5 SKN: " + file.properties[(long)InibinHashID.SKIN_FIVE_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FIVE_SKL)) logger.Event("Skin #5 SKL: " + file.properties[(long)InibinHashID.SKIN_FIVE_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_FIVE_TEXTURE)) logger.Event("Skin #5 DDS: " + file.properties[(long)InibinHashID.SKIN_FIVE_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SIX_NAME)) logger.Event("Skin #6 Name: " + file.properties[(long)InibinHashID.SKIN_SIX_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SIX_SKN)) logger.Event("Skin #6 SKN: " + file.properties[(long)InibinHashID.SKIN_SIX_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SIX_SKL)) logger.Event("Skin #6 SKL: " + file.properties[(long)InibinHashID.SKIN_SIX_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SIX_TEXTURE)) logger.Event("Skin #6 DDS: " + file.properties[(long)InibinHashID.SKIN_SIX_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SEVEN_NAME)) logger.Event("Skin #7 Name: " + file.properties[(long)InibinHashID.SKIN_SEVEN_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SEVEN_SKN)) logger.Event("Skin #7 SKN: " + file.properties[(long)InibinHashID.SKIN_SEVEN_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SEVEN_SKL)) logger.Event("Skin #7 SKL: " + file.properties[(long)InibinHashID.SKIN_SEVEN_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_SEVEN_TEXTURE)) logger.Event("Skin #7 DDS: " + file.properties[(long)InibinHashID.SKIN_SEVEN_TEXTURE]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_EIGHT_NAME)) logger.Event("Skin #8 Name: " + file.properties[(long)InibinHashID.SKIN_EIGHT_NAME]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_EIGHT_SKN)) logger.Event("Skin #8 SKN: " + file.properties[(long)InibinHashID.SKIN_EIGHT_SKN]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_EIGHT_SKL)) logger.Event("Skin #8 SKL: " + file.properties[(long)InibinHashID.SKIN_EIGHT_SKL]); if (file.properties.ContainsKey((long)InibinHashID.SKIN_EIGHT_TEXTURE)) logger.Event("Skin #8 DDS: " + file.properties[(long)InibinHashID.SKIN_EIGHT_TEXTURE]); return result; }
private static bool ReadData(BinaryReader file, ref SKNFile data, Logger logger) { bool result = true; try { // File Header Information. data.magic = file.ReadInt32(); data.version = file.ReadInt16(); data.numObjects = file.ReadInt16(); if (data.version == 1 || data.version == 2) { // Contains material headers. data.numMaterialHeaders = file.ReadInt32(); for (int i = 0; i < data.numMaterialHeaders; ++i) { // Read in the headers. SKNMaterial header = new SKNMaterial(); header.name = new String(file.ReadChars(SKNMaterial.MATERIAL_NAME_SIZE)); header.startVertex = file.ReadInt32(); header.numVertices = file.ReadInt32(); header.startIndex = file.ReadInt32(); header.numIndices = file.ReadInt32(); data.materialHeaders.Add(header); } // Read in model data. data.numIndices = file.ReadInt32(); data.numVertices = file.ReadInt32(); for (int i = 0; i < data.numIndices; ++i) { data.indices.Add(file.ReadInt16()); } for (int i = 0; i < data.numVertices; ++i) { SKNVertex vertex = new SKNVertex(); vertex.position[0] = file.ReadSingle(); // x vertex.position[1] = file.ReadSingle(); // y vertex.position[2] = file.ReadSingle(); // z for (int j = 0; j < SKNVertex.BONE_INDEX_SIZE; ++j) { int bone = (int)file.ReadByte(); vertex.boneIndex[j] = bone; } vertex.weights[0] = file.ReadSingle(); vertex.weights[1] = file.ReadSingle(); vertex.weights[2] = file.ReadSingle(); vertex.weights[3] = file.ReadSingle(); vertex.normal[0] = file.ReadSingle(); // x vertex.normal[1] = file.ReadSingle(); // y vertex.normal[2] = file.ReadSingle(); // z vertex.texCoords[0] = file.ReadSingle(); // u vertex.texCoords[1] = file.ReadSingle(); // v data.vertices.Add(vertex); } // Data exclusive to version two. if (data.version == 2) { data.endTab.Add(file.ReadInt32()); data.endTab.Add(file.ReadInt32()); data.endTab.Add(file.ReadInt32()); } } // Unknown Version else { logger.Error("Unknown skn version: " + data.version); result = false; } } catch(Exception e) { logger.Error("Skn reading error."); logger.Error(e.Message); result = false; } logger.Event("Magic: " + data.magic); logger.Event("Version: " + data.version); logger.Event("Number of Objects: " + data.numObjects); logger.Event("Number of Material Headers: " + data.numMaterialHeaders); logger.Event("Number of Vertices: " + data.numVertices); logger.Event("Number of Indices: " + data.numIndices); return result; }
private static bool ReadData(BinaryReader file, ref SKLFile data, Logger logger) { bool result = true; try { // File Header Information. data.id = new String(file.ReadChars(SKLFile.ID_SIZE)); data.version = file.ReadUInt32(); if (data.version == 1 || data.version == 2) { data.designerID = file.ReadUInt32(); // Read in the bones. data.numBones = file.ReadUInt32(); for (int i = 0; i < data.numBones; ++i) { SKLBone bone = new SKLBone(); bone.name = new String( file.ReadChars(SKLBone.BONE_NAME_SIZE)); bone.name = RemoveBoneNamePadding(bone.name); bone.name = bone.name.ToLower(); bone.ID = i; bone.parentID = file.ReadInt32(); bone.scale = file.ReadSingle(); // Read in transform matrix. float[] orientation = new float[SKLBone.ORIENTATION_SIZE]; for (int j = 0; j < SKLBone.ORIENTATION_SIZE; ++j) { orientation[j] = file.ReadSingle(); } bone.orientation = orientation; // Position from matrix. bone.position[0] = orientation[3]; bone.position[1] = orientation[7]; bone.position[2] = orientation[11]; data.bones.Add(bone); } // Version two contains bone IDs. if (data.version == 2) { data.numBoneIDs = file.ReadUInt32(); for (uint i = 0; i < data.numBoneIDs; ++i) { data.boneIDs.Add(file.ReadUInt32()); } } } // Newest version so far. else if (data.version == 0) { // Header Int16 zero = file.ReadInt16(); // ? data.numBones = (uint)file.ReadInt16(); data.numBoneIDs = file.ReadUInt32(); Int16 offsetToVertexData = file.ReadInt16(); // Should be 64. int unknown = file.ReadInt16(); // ? int offset1 = file.ReadInt32(); int offsetToAnimationIndices = file.ReadInt32(); int offset2 = file.ReadInt32(); int offset3 = file.ReadInt32(); int offsetToStrings = file.ReadInt32(); // Not sure what this data represents. // I think it's padding incase more header data is required later. file.BaseStream.Position += 20; file.BaseStream.Position = offsetToVertexData; for (int i = 0; i < data.numBones; ++i) { SKLBone bone = new SKLBone(); // The old scale was always 0.1. // For now, just go with it. bone.scale = 0.1f; zero = file.ReadInt16(); // ? bone.ID = file.ReadInt16(); bone.parentID = file.ReadInt16(); unknown = file.ReadInt16(); // ? int namehash = file.ReadInt32(); float twoPointOne = file.ReadSingle(); bone.position[0] = file.ReadSingle(); bone.position[1] = file.ReadSingle(); bone.position[2] = file.ReadSingle(); float one = file.ReadSingle(); // ? Maybe scales for X, Y, and Z one = file.ReadSingle(); one = file.ReadSingle(); bone.orientation[0] = file.ReadSingle(); bone.orientation[1] = file.ReadSingle(); bone.orientation[2] = file.ReadSingle(); bone.orientation[3] = file.ReadSingle(); float ctx = file.ReadSingle(); // ctx float cty = file.ReadSingle(); // cty float ctz = file.ReadSingle(); // ctz data.bones.Add(bone); // The rest of the bone data is unknown. Maybe padding? file.BaseStream.Position += 32; } file.BaseStream.Position = offset1; for (int i = 0; i < data.numBones; ++i) // Inds for version 4 animation. { // 8 bytes uint sklID = file.ReadUInt32(); uint anmID = file.ReadUInt32(); data.boneIDMap[anmID] = sklID; } file.BaseStream.Position = offsetToAnimationIndices; for (int i = 0; i < data.numBoneIDs; ++i) // Inds for animation { // 2 bytes UInt16 boneID = file.ReadUInt16(); data.boneIDs.Add(boneID); } file.BaseStream.Position = offsetToStrings; for (int i = 0; i < data.numBones; ++i) { // bone names string name = ""; while (name.Contains('\0') == false) { name += new string(file.ReadChars(4)); } name = RemoveBoneNamePadding(name); name = name.ToLower(); data.bones[i].name = name; } } // Unknown Version else { logger.Error("Unknown skl version: " + data.version); result = false; } } catch (Exception e) { logger.Error("Skl reading error."); logger.Error(e.Message); result = false; } logger.Event("File ID: " + data.id); logger.Event("Version: " + data.version); logger.Event("Designer ID: " + data.designerID); logger.Event("Number of Bones: " + data.numBones); logger.Event("Number of Bone IDs: " + data.numBoneIDs); return result; }
// Replacement for individual raf reading and individual filetype searching // Provide the directory of RADS\projects\lol_game_client\filearchives or the equivalent private bool ReadRAFs(DirectoryInfo dir, Logger logger) { try { RAFMasterFileList rafFiles = new RAFMasterFileList(dir.FullName); logger.Event("Opening the 'filearchives' directory: " + dir.FullName); foreach (RAFMasterFileList.RAFSearchResult result in rafFiles.SearchFileEntries(new string[] { ".dds", ".skn", ".skl", ".inibin", "animations.list", ".anm" }, RAFMasterFileList.RAFSearchType.All)) { RAFFileListEntry e = result.value; // Split off the actual file name from the full path String name = e.FileName.Substring(e.FileName.LastIndexOf('/') + 1).ToLower(); switch (result.searchPhrase) { case ".dds": // Try to parse out unwanted textures. if (!e.FileName.ToLower().Contains("loadscreen") && !e.FileName.ToLower().Contains("circle") && !e.FileName.ToLower().Contains("square") && e.FileName.ToLower().Contains("data") && e.FileName.ToLower().Contains("characters")) { // Check that the file isn't already in the dictionary if (!textures.ContainsKey(name)) { textures.Add(name, e); } else { logger.Warning("Duplicate texture " + name + ": " + e.FileName); } } break; case ".skn": if (!skns.ContainsKey(name)) { skns.Add(name, e); } else { logger.Warning("Duplicate skn " + name + ": " + e.FileName); } break; case ".skl": if (!skls.ContainsKey(name)) { skls.Add(name, e); } else { logger.Warning("Duplicate skn " + name + ": " + e.FileName); } break; case ".inibin": // Try to only read champion inibins if (e.FileName.ToLower().Contains("data") && e.FileName.ToLower().Contains("characters")) { inibins.Add(e); } else { logger.Warning("Excluding inibin " + name + ": " + e.FileName); } break; case "animations.list": // Riot changed their directory structure for some skins. // Originally, champion Animation.list files were stored in a directory structure like // "*/ChampionName/Animation.list". Now, some are stored like // "*/ChampionName/Skins/Skin01/Animation.list". if (e.FileName.ToLower().Contains("skin") == false && e.FileName.ToLower().Contains("base") == false) { // Original Case. // Remove the file name. name = e.FileName.Remove(e.FileName.LastIndexOf('/')); // Remove proceeding directories to get the parent directory name = name.Substring(name.LastIndexOf('/') + 1).ToLower(); } else { // Newer Case. string path = e.FileName.ToString(); string[] splitPath = path.Split('/'); // Sanity if (splitPath.Length > 3) { name = splitPath[splitPath.Length - 4].ToLower(); } } // Store. if (!animationLists.ContainsKey(name)) { animationLists.Add(name, e); } else { logger.Warning("Duplicate animation list " + name + ": " + e.FileName); } break; case ".anm": // Remove the .anm extension. name = name.Remove(name.Length - 4); if (!animations.ContainsKey(name)) { animations.Add(name, e); } else { logger.Warning("Duplicate anm " + name + ": " + e.FileName); } break; } } } catch (Exception e) { // Something went wrong. Most likely the RAF read failed due to a bad directory. logger.Error("Failed to open RAFs"); logger.Error(e.Message); return false; } return true; }
private void GenerateModelDefinitions(Logger logger) { foreach (RAFFileListEntry f in inibins) { InibinFile iniFile = new InibinFile(); bool readResult = InibinReader.Read(f, ref iniFile, logger); if (readResult == true) { // Add the models from this .inibin file List<ModelDefinition> modelDefs = iniFile.GetModelStrings(); for (int j = 0; j < modelDefs.Count; ++j) { // Name the model after the parent directory // of the .inibin plus the name from the .inibin. // Some things overlap without both. string path = f.FileName; string[] splitPath = path.Split('/'); string directoryName = splitPath[splitPath.Length - 2]; if (directoryName.Contains("Base") == true || directoryName.Contains("Skin") == true) { // The directory structure for this case will be something like // "*/ChampionName/Skins/Base/". // We just want the "ChampionName". directoryName = splitPath[splitPath.Length - 4]; } // Sometimes the name from the .inibin file is "". // So, just name it after the directory String name = modelDefs[j].name; if (name == "") { name = directoryName + "/" + directoryName; } else { name = directoryName + "/" + name; } try { LOLModel model; bool storeResult = StoreModel(modelDefs[j], out model, logger); if (storeResult == true) { // Try to store animations for model as well storeResult = StoreAnimations(ref model, logger); } if (storeResult == true) { if (models.ContainsKey(name) == false) { logger.Event("Adding model definition: " + name); models.Add(name, model); } else { logger.Warning("Duplicate model definition: " + name); } } } catch (Exception e) { logger.Error("Unable to store model definition: " + name); logger.Error(e.Message); } } } } }
public bool Read(Logger logger) { bool result = true; // Clear old data. models.Clear(); skls.Clear(); skns.Clear(); textures.Clear(); inibins.Clear(); animationLists.Clear(); animations.Clear(); DirectoryInfo rootDir = null; try { logger.Event("Reading models from: " + Root); rootDir = new DirectoryInfo(Root); } catch { logger.Error("Unable to get the directory information: " + Root); result = false; } // // Try to find the raf files and read them. // if (result == true) { try { result = GetRAFFiles(rootDir, logger); // If the finding or reading fails, bail. if (!result) { logger.Error("Unable to find the 'filearchives' directory: " + Root); } } catch (Exception e) { logger.Error("Unable to open directory: " + Root); logger.Error(e.Message); result = false; } } // Sanity if (result == true) { GenerateModelDefinitions(logger); } return result; }