//find the chunk, replace the chunk, perhaps create or remove the reference public static void ReplaceChunk(this GenericRCOLResource rcolResource, MLOD.Mesh mesh, string field, IResourceKey rk, ARCOLBlock block) { ARCOLBlock current = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, (GenericRCOLResource.ChunkReference)mesh[field].Value) as ARCOLBlock; if (block != null) { if (current != null) // replacing is easy { if (current.Tag != block.Tag) { throw new Exception(string.Format("mesh field {0} is '{1}' but replacement is '{2}'.", field, current.Tag, block.Tag)); } // ...not entirely sure if these are required... current.Data = block.Data; block = current; } else // adding is okay { rcolResource.ChunkEntries.Add(new GenericRCOLResource.ChunkEntry(0, null, new TGIBlock(0, null, rk), block)); mesh[field] = new TypedValue(typeof(GenericRCOLResource.ChunkReference), GenericRCOLResource.ChunkReference.CreateReference(rcolResource, rk), "X"); } } else // deleting is not allowed - we can only null the reference, not remove the chunk { mesh[field] = new TypedValue(typeof(GenericRCOLResource.ChunkReference), new GenericRCOLResource.ChunkReference(0, null, 0), "X"); } }
//Match what Wes's compiler does public static void FixUVScales(this GenericRCOLResource rcolResource, MLOD.Mesh mesh) { MATD matd = GetMATDforMesh(rcolResource, mesh.MaterialIndex); if (matd == null) { throw new ArgumentException("No MATD found for requested mesh"); } foreach (FieldType ft in new FieldType[] { FieldType.UVScales, FieldType.DiffuseUVSelector, FieldType.SpecularUVSelector, }) { ShaderData data = (matd.Version < 0x0103 ? matd.Mtrl.SData : matd.Mtnf.SData).Find(x => x.Field == ft); if (data == null) { continue; } if (!(data is ElementFloat3)) { throw new InvalidOperationException(String.Format("Found " + ft + " of type '{0}'; expected 'ElementFloat3'.", data.GetType().Name)); } ElementFloat3 e = data as ElementFloat3; e.Data0 = 1f / short.MaxValue; e.Data1 = 0f; e.Data2 = 0f; } }
void loadVPXY(Stream data) { try { rcol = new GenericRCOLResource(0, data); } catch { rcol = null; } if (rcol == null || rcol.ChunkEntries.Count != 1 || rcol.ChunkEntries[0].RCOLBlock.Tag != "VPXY") { throw new Exception("RCOL was not a VPXY resource."); } vpxy = rcol.ChunkEntries[0].RCOLBlock as VPXY; if (vpxy == null) { throw new Exception("VPXY resource contains invalid RCOL Chunk."); } FillPartsTLP(); nudLowerX.Value = new Decimal(vpxy.Bounds.Min.X); nudLowerY.Value = new Decimal(vpxy.Bounds.Min.Y); nudLowerZ.Value = new Decimal(vpxy.Bounds.Min.Z); nudUpperX.Value = new Decimal(vpxy.Bounds.Max.X); nudUpperY.Value = new Decimal(vpxy.Bounds.Max.Y); nudUpperZ.Value = new Decimal(vpxy.Bounds.Max.Z); tbcFTPT.Enabled = ckbModular.Checked = vpxy.Modular; tbcFTPT.TGIBlocks = vpxy.TGIBlocks; tbcFTPT.SelectedIndex = vpxy.Modular && vpxy.FTPTIndex < vpxy.TGIBlocks.Count ? (int)vpxy.FTPTIndex : -1; rcol.ResourceChanged += new EventHandler(rcol_ResourceChanged); }
public MainWindow(GenericRCOLResource s) : this() { rcol = s; rbTextured.Visibility = Visibility.Collapsed; InitScene(); rbSolid.IsChecked = true; }
public static GenericRCOLResource.ChunkReference GetMLODChunkRefforMODL(this GenericRCOLResource rcolResource) { var lodEntry = (rcolResource.ChunkEntries[0].RCOLBlock as MODL).Entries .Find(l => l.ModelLodIndex.RefType == GenericRCOLResource.ReferenceType.Public || l.ModelLodIndex.RefType == GenericRCOLResource.ReferenceType.Private); return(lodEntry == null ? null : lodEntry.ModelLodIndex); }
public VBUF(int APIversion, EventHandler handler, uint version, FormatFlags flags, GenericRCOLResource.ChunkReference swizzleInfo, byte[] buffer) : this(APIversion, handler) { mVersion = version; mFlags = flags; mSwizzleInfo = swizzleInfo; mBuffer = buffer; }
public JazzGraphContainer(int index, JazzPackage jp, IResourceIndexEntry rie, Control view, TabPage page) { this.Index = index; this.UndoRedo = new UndoManager(); this.SaveState = JazzSaveState.Saved; this.Key = new RK(rie); this.Comp = rie.Compressed == 0xFFFF; this.JP = jp; this.RIE = rie; IResource res = null; GenericRCOLResource rcol = null; try { res = WrapperDealer.GetResource(0, jp.Package, rie); } catch (Exception ex) { MainForm.ShowException(ex, "Could not load JAZZ resource: " + this.Key + "\n", MainForm.kName + ": Unable to load JAZZ resource"); } if (res != null) { rcol = res as GenericRCOLResource; if (rcol != null) { this.Scene = new StateMachineScene( new StateMachine(rcol), view, this); KKLayoutAlgorithm <StateNode, StateEdge> layout = new KKLayoutAlgorithm <StateNode, StateEdge>( this.Scene.StateGraph, this.Scene); layout.LengthFactor = 1.25f; this.Scene.Layout = layout; layout.ShuffleNodes(); this.Scene.LayoutPaused = true; this.Scene.StartLayout(); } else { this.Scene = null; } } if (!KeyNameReg.TryFindName(rie.Instance, out this.mName)) { this.mName = "0x" + rie.Instance.ToString("X16"); } if (this.Scene != null) { this.mPage = page; this.mPage.Controls.Add(view); this.mPage.Text = this.mName; this.mPage.SizeChanged += new EventHandler(this.OnTabSizeChanged); } }
public static VBSI FromMLOD(MLOD mlod, GenericRCOLResource container) { var vbsi = new VBSI(0, null); foreach (var mesh in mlod.Meshes) { var vrtf = (VRTF)GenericRCOLResource.ChunkReference.GetBlock(container, mesh.VertexFormatIndex); vbsi.Segments.Add(SegmentInfo.FromMesh(mesh, vrtf)); } return(vbsi); }
public static MATD GetMATDforMesh(this GenericRCOLResource rcolResource, GenericRCOLResource.ChunkReference reference) { IRCOLBlock materialRef = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, reference); if (materialRef is MATD) { return(materialRef as MATD); } if (materialRef is MTST) { return(GetMATDforMesh(rcolResource, (materialRef as MTST).Index)); } return(null); }
static int Main(params string[] args) { #if DEBUG if (args.Length == 0) { TGIBlock tgib = new TGIBlock(0, null, "ITG", 0x736884F1, 0, 0); ARCOLBlock rcol = GenericRCOLResourceHandler.CreateRCOLBlock(0, null, 0x736884F1); GenericRCOLResource.ChunkEntry ce = new GenericRCOLResource.ChunkEntry(0, null, tgib, rcol); GenericRCOLResource grr = new GenericRCOLResource(0, null); grr.ChunkEntries.Add(ce); Clipboard.SetData(DataFormats.Serializable, grr.Stream); } #endif return(s3pi.Helpers.RunHelper.Run(typeof(MainForm), args)); }
static int Main(params string[] args) { #if DEBUG if (args.Length == 0) { TGIBlock tgib = new TGIBlock(0, null, "ITG", 0x736884F1, 0, 0); ARCOLBlock rcol = GenericRCOLResourceHandler.CreateRCOLBlock(0, null, 0x736884F1); GenericRCOLResource.ChunkEntry ce = new GenericRCOLResource.ChunkEntry(0, null, tgib, rcol); GenericRCOLResource grr = new GenericRCOLResource(0, null); grr.ChunkEntries.Add(ce); Clipboard.SetData(DataFormats.Serializable, grr.Stream); } #endif return s3pi.Helpers.RunHelper.Run(typeof(MainForm), args); }
private void SlurpKinRCOLTGIBlocks() { GenericRCOLResource rcol = base.resource as GenericRCOLResource; if (rcol != null) { for (int i = 0; i < rcol.ChunkEntries.Count; i++) { if (this.GetChunkType(rcol.ChunkEntries[i].TGIBlock) == ChunkEntryType.Kindred) { base.kindredRCOLChunkKeys.Add(rcol.ChunkEntries[i].TGIBlock); } } } }
public void Export_MLOD(StreamWriter w, GenericRCOLResource rcolResource, MLOD mlod, MLOD.Mesh mesh) { float[] uvScales = rcolResource.GetUVScales(mesh); if (mesh.GeometryStates.Count > 0) { w.WriteLine(";"); w.WriteLine("; Extended format: GeoStates follow IBUF"); w.WriteLine(";"); } if (mesh.Flags != 0) { w.WriteLine(";"); w.WriteLine("; Extended format: MeshFlags follow IBUF" + (mesh.GeometryStates.Count > 0 ? " and GeoStates" : "")); w.WriteLine("; (They are ignored on import.)"); w.WriteLine(";"); } VRTF vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.VertexFormatIndex) as VRTF; bool isDefault = vrtf == null; if (isDefault) { vrtf = VRTF.CreateDefaultForMesh(mesh); w.WriteLine(";;-marker: vrtf is default for mesh"); } w.Export_VRTF(mpb, vrtf); w.Export_SKIN(mpb, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.SkinControllerIndex) as SKIN, mesh); Export_VBUF_Main(w, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.VertexBufferIndex) as VBUF, vrtf, uvScales, mesh); Export_IBUF_Main(w, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF, mesh); //For backward compatibility, these come after the IBUFs Export_MeshGeoStates(w, vrtf, uvScales, mlod, mesh, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.VertexBufferIndex) as VBUF, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF); if (mesh.Flags != 0) { w.WriteLine(";"); w.WriteLine("; Extended format: MeshFlags"); w.WriteLine(";"); w.WriteLine("flags " + mesh.Flags); w.Flush(); } }
public void Export_MLOD(StreamWriter w, GenericRCOLResource rcolResource, MLOD mlod, MLOD.Mesh mesh) { float[] uvScales = rcolResource.GetUVScales(mesh); VRTF vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.VertexFormatIndex) as VRTF; bool isDefault = vrtf == null; if (isDefault) { vrtf = VRTF.CreateDefaultForMesh(mesh); w.WriteLine(";;-marker: vrtf is default for mesh"); } w.Export_VRTF(mpb, vrtf); w.Export_SKIN(mpb, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.SkinControllerIndex) as SKIN, mesh); Export_VBUF_Main(w, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.VertexBufferIndex) as VBUF, vrtf, uvScales, mesh); Export_IBUF_Main(w, GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF, mesh); }
private static void Main(params String[] args) { GenericRCOLResource rcol = null; using (Stream s = File.OpenRead(args[0])) { rcol = new GenericRCOLResource(0, s); } var app = new Application(); try { var self = Process.GetCurrentProcess(); var caller = self.GetParent(); if (caller != null) { caller.EnableRaisingEvents = true; caller.Exited += (sender, eventArgs) => self.CloseMainWindow();; } } catch { MessageBox.Show( "Unable to locate parent process. If this was started through another program, you will have to close it manually."); } var win = new MainWindow(rcol); for (int i = 1; i < args.Length; i++) { switch (args[i]) { case "-texture": win.TextureSource = args[++i]; break; case "-title": win.Title += " - " + args[++i]; break; default: break; } } app.Run(win); }
private static void Main(params String[] args) { GenericRCOLResource rcol = null; using (Stream s = File.OpenRead(args[0])) { rcol = new GenericRCOLResource(0, s); } var app = new Application(); // try // { // var self = Process.GetCurrentProcess(); // var caller = self.GetParent(); // if (caller != null) // { // caller.EnableRaisingEvents = true; // caller.Exited += (sender, eventArgs) => self.CloseMainWindow(); ; // } // } // catch // { // MessageBox.Show( // "Unable to locate parent process. If this was started through another program, you will have to close it manually."); // } var win = new MainWindow(rcol); for (int i = 1; i < args.Length; i++) { switch (args[i]) { case "-texture": win.TextureSource = args[++i]; break; case "-title": win.Title += " - " + args[++i]; break; default: break; } } app.Run(win); }
public static float[] GetUVScales(this GenericRCOLResource rcolResource, MLOD.Mesh mesh) { MATD matd = GetMATDforMesh(rcolResource, mesh.MaterialIndex); if (matd != null) { ShaderData data = (matd.Version < 0x0103 ? matd.Mtrl.SData : matd.Mtnf.SData).Find(x => x.Field == FieldType.UVScales); if (data != null) { if (data is ElementFloat3) { ElementFloat3 e = data as ElementFloat3; return(new float[] { e.Data0, e.Data1, e.Data2, }); } else { throw new InvalidOperationException(String.Format("Found UVScales of type '{0}'; expected 'ElementFloat3'.", data.GetType().Name)); } } } return(new float[] { 1f / 32767f, 0f, 0f, }); }
private static void Main(params String[] args) { byte[] buffer = null; using (Stream s = File.OpenRead(args[0])) { buffer = new byte[s.Length]; s.Read(buffer, 0, buffer.Length); } var app = new Application(); var resource = new GenericRCOLResource(0, new MemoryStream(buffer)); var viewModel = new AnimViewModel(resource); var win = new MainWindow(viewModel); app.Run(win); if (viewModel.IsSaving) { byte[] output = resource.AsBytes; using (FileStream s = File.Create(args[0])) { s.Write(output, 0, output.Length); } } }
private static MATD FindMainMATD(GenericRCOLResource rcol, IRCOLBlock material) { float[] scales = null; if (material == null) { return(null); } if (material is MATD) { return(material as MATD); } else if (material is MTST) { var mtst = material as MTST; try { material = GenericRCOLResource.ChunkReference.GetBlock(rcol, mtst.Index); } catch (NotImplementedException e) { MessageBox.Show("Material is external, unable to locate UV scales."); return(null); } if (material is MATD) { var matd = (MATD)material; return(matd); } } else { throw new ArgumentException("Material must be of type MATD or MTST", "material"); } return(null); }
public AnimViewModel(GenericRCOLResource rcolResource) { IsSaving = false; mANIM = (ANIM)rcolResource.ChunkEntries.FirstOrDefault().RCOLBlock; CurrentFrameIndex = -1; SyncFrames(); CommitCommand = new UserCommand <AnimViewModel>(x => true, y => { IsSaving = true; Application.Current.Shutdown(); }); CancelCommand = new UserCommand <AnimViewModel>(x => true, y => { IsSaving = false; Application.Current.Shutdown(); }); RemoveFrameCommand = new UserCommand <AnimViewModel>(x => CurrentFrameIndex >= 0, RemoveFrame); AddFrameCommand = new UserCommand <AnimViewModel>(x => true, AddFrame); ShiftFrameUpCommand = new UserCommand <AnimViewModel>(x => x != null && x.CurrentFrameIndex > 0, ShiftFrameUp); ShiftFrameDownCommand = new UserCommand <AnimViewModel>(x => x != null && x.CurrentFrameIndex < x.Frames.Count - 1 && x.CurrentFrameIndex != -1, ShiftFrameDown); ImportCommand = new UserCommand <AnimViewModel>(x => x != null && x.GetSelectedFrame() != null, ImportDds); ExportCommand = new UserCommand <AnimViewModel>(x => x != null && x.GetSelectedFrame() != null && x.GetSelectedFrame().Frame.Stream.Length > 0, ExportDds); }
public AnimViewModel(GenericRCOLResource rcolResource) { IsSaving = false; mANIM = (ANIM) rcolResource.ChunkEntries.FirstOrDefault().RCOLBlock; CurrentFrameIndex = -1; SyncFrames(); CommitCommand = new UserCommand<AnimViewModel>(x => true, y => { IsSaving = true; Application.Current.Shutdown(); }); CancelCommand = new UserCommand<AnimViewModel>(x => true, y => { IsSaving = false; Application.Current.Shutdown(); }); RemoveFrameCommand = new UserCommand<AnimViewModel>(x => CurrentFrameIndex >= 0, RemoveFrame); AddFrameCommand = new UserCommand<AnimViewModel>(x => true, AddFrame); ShiftFrameUpCommand = new UserCommand<AnimViewModel>(x => x != null && x.CurrentFrameIndex > 0, ShiftFrameUp); ShiftFrameDownCommand = new UserCommand<AnimViewModel>(x => x != null && x.CurrentFrameIndex < x.Frames.Count - 1 && x.CurrentFrameIndex != -1, ShiftFrameDown); ImportCommand = new UserCommand<AnimViewModel>(x => x != null && x.GetSelectedFrame() != null, ImportDds); ExportCommand = new UserCommand<AnimViewModel>(x => x != null && x.GetSelectedFrame() != null && x.GetSelectedFrame().Frame.Stream.Length > 0, ExportDds); }
public static MATD GetMATDforMesh(this GenericRCOLResource rcolResource, GenericRCOLResource.ChunkReference reference) { IRCOLBlock materialRef = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, reference); if (materialRef is MATD) return materialRef as MATD; if (materialRef is MTST) return GetMATDforMesh(rcolResource, (materialRef as MTST).Index); return null; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (String.IsNullOrEmpty(value as string)) { return(null); } var path = value as string; if (path != null && File.Exists(path)) { using (FileStream s = File.OpenRead(path)) { var rcol = new GenericRCOLResource(0, s); MLOD mlod = rcol.ChunkEntries .Where(x => x.RCOLBlock is MLOD) .Select(x => x.RCOLBlock) .Cast <MLOD>() .FirstOrDefault(); double minX = double.MaxValue, minZ = double.MaxValue, maxX = double.MinValue, maxZ = double.MinValue; var pnty = new List <Point[]>(); foreach (MLOD.Mesh mesh in mlod.Meshes) { var vbuf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.VertexBufferIndex) as VBUF; var ibuf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.IndexBufferIndex) as IBUF; var vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.VertexFormatIndex) as VRTF; if (vrtf == null) { continue; } Vertex[] verts = vbuf.GetVertices(mesh, vrtf, null); int[] indices = ibuf.GetIndices(mesh); for (int i = 0; i < indices.Length / 3; i++) { var tst = new int[3]; var poly = new Point[3]; for (int j = 0; j < 3; j++) { Vertex vert = verts[indices[i * 3 + j]]; double x = (Offset + (vert.Position[0] * Scale)); double z = -(Offset + (vert.Position[2] * Scale)); poly[j] = new Point((int)x, (int)z); if (poly[j].X > maxX) { maxX = poly[j].X; } if (poly[j].X < minX) { minX = poly[j].X; } if (poly[j].Y > maxZ) { maxZ = poly[j].Y; } if (poly[j].Y < minZ) { minZ = poly[j].Y; } } pnty.Add(poly); } } var width = (int)(maxX - minX); var height = (int)(maxZ - minZ); var bmp = new Bitmap(width, height); Graphics gBmp = Graphics.FromImage(bmp); gBmp.CompositingMode = CompositingMode.SourceCopy; float bright = 1.1f; System.Drawing.Color c = System.Drawing.Color.FromArgb(255, Fill.R, Fill.G, Fill.B); System.Drawing.Color c2 = System.Drawing.Color.FromArgb(255, Stroke.R, Stroke.G, Stroke.B); var b = new SolidBrush(c); var b2 = new SolidBrush(c2); var pen = new Pen(b2); foreach (Point[] pointse in pnty) { Point[] scaled = pointse.Select(old => new Point((int)(old.X - minX), (int)(old.Y - minZ))).ToArray(); gBmp.FillPolygon(b, scaled); } foreach (Point[] pointse in pnty) { Point[] scaled = pointse.Select(old => new Point((int)(old.X - minX), (int)(old.Y - minZ))).ToArray(); gBmp.DrawPolygon(pen, scaled); } var bmpImg = new BitmapImage(); var ms = new MemoryStream(); bmp.Save(ms, ImageFormat.Png); ms.Position = 0L; bmpImg.BeginInit(); bmpImg.StreamSource = ms; bmpImg.EndInit(); return(bmpImg); } } return(null); }
private void Import_Shown(object sender, EventArgs e) { try { ofdImport.Title += " -- Test version " + typeof(ImportForm).Assembly.GetName().Version.ToString(); DialogResult dr = ofdImport.ShowDialog(); if (dr != DialogResult.OK) { Environment.ExitCode = 1; return; } string folder = Path.GetDirectoryName(ofdImport.FileName); string filebase = Path.GetFileNameWithoutExtension(ofdImport.FileName).Replace("_filebase", ""); if (!File.Exists(Path.Combine(folder, string.Format("{0}_filebase.s3asc", filebase)))) { CopyableMessageBox.Show("File name must end \"_filebase.s3asc\"", "Base file not found", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } bool updateBBs = false; int q = CopyableMessageBox.Show("Update mesh bounding boxes?", Application.ProductName, CopyableMessageBoxButtons.YesNoCancel, CopyableMessageBoxIcon.Question); if (q == 0) updateBBs = true; else if (q == 2) { Environment.ExitCode = 1; return; } bool updateUVs = false; q = CopyableMessageBox.Show("Maximise mapping area?", Application.ProductName, CopyableMessageBoxButtons.YesNoCancel, CopyableMessageBoxIcon.Question); if (q == 0) updateUVs = true; else if (q == 2) { Environment.ExitCode = 1; return; } try { GenericRCOLResource rcolResource = new GenericRCOLResource(0, stream); MLOD mlod = null; IResourceKey rk = null; if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01661233)//MODL { this.Text = "Import MODL..."; var lodRef = rcolResource.GetMLODChunkRefforMODL(); if (lodRef == null) { CopyableMessageBox.Show("MODL (0x01661233) with no MLOD (0x01D10F34).", "Invalid MODL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } rk = GenericRCOLResource.ChunkReference.GetKey(rcolResource, lodRef); mlod = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, lodRef) as MLOD; } else if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01D10F34)//MLOD { this.Text = "Import MLOD..."; rk = rcolResource.ChunkEntries[0].TGIBlock; mlod = rcolResource.ChunkEntries[0].RCOLBlock as MLOD; } else { CopyableMessageBox.Show("RCOL resource must be MODL (0x01661233) or MLOD (0x01D10F34).", "Invalid RCOL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } Import import = new Import(new MyProgressBar(label1, pb)); int m = 0; List<meshExpImp.ModelBlocks.Vertex[]> lmverts = new List<meshExpImp.ModelBlocks.Vertex[]>(); while (true) { string fnMesh = Path.Combine(folder, string.Format("{0}_group{1:D2}.s3ascg", filebase, m)); if (!File.Exists(fnMesh)) break; using (FileStream fsMesh = new FileStream(fnMesh, FileMode.Open, FileAccess.Read)) { meshExpImp.ModelBlocks.Vertex[] mverts; import.Import_Mesh(new StreamReader(fsMesh), mlod.Meshes[m++], rcolResource, mlod, rk, out mverts); lmverts.Add(mverts); fsMesh.Close(); } } List<Import.offScale> offScales = import.VertsToVBUFs(rcolResource, mlod, rk, lmverts, updateBBs, updateUVs); if (offScales.Count > 0) { while (true) { switch ( CopyableMessageBox.Show( Application.ProductName + " has detected some off-scale UV mappings.\n" + "This may mean your mapping is not stored as you intended.\n" + "This is often caused by UV-mapping too close to the edge of the map.\n\n" + "Click 'Commit' to commit the change or 'Cancel' to abandon.", Application.ProductName, CopyableMessageBoxIcon.Warning, new String[] { "C&ommit", "&View", "C&ancel", }, 0, 2)) { case 0: //commit goto Commit; case 1: //view System.Text.StringBuilder sb = new System.Text.StringBuilder(); offScales.ForEach(x => sb.AppendLine(x.ToString())); CopyableMessageBox.Show(sb.ToString(), Application.ProductName, CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Information); break; default: //cancel Environment.ExitCode = 1; return; } } } Commit: result = (byte[])rcolResource.AsBytes.Clone(); Environment.ExitCode = 0; } catch (Exception ex) { CopyableMessageBox.IssueException(ex, "Error processing " + Program.Filename); throw ex; } } finally { this.Close(); } }
public List<offScale> VertsToVBUFs(GenericRCOLResource rcolResource, MLOD mlod, IResourceKey defaultRK, List<meshExpImp.ModelBlocks.Vertex[]> lmverts, bool updateBBs, bool updateUVs) { // List of UV elements going off scale List<offScale> offScales = new List<offScale>(); // Find everything for each mesh group Dictionary<GenericRCOLResource.ChunkReference, List<int>> meshGroups = new Dictionary<GenericRCOLResource.ChunkReference, List<int>>(); Dictionary<int, VRTF> meshVRTF = new Dictionary<int, VRTF>(); Dictionary<int, float[]> meshUVScales = new Dictionary<int, float[]>(); for (int m = 0; m < mlod.Meshes.Count; m++) { if (meshGroups.ContainsKey(mlod.Meshes[m].MaterialIndex)) meshGroups[mlod.Meshes[m].MaterialIndex].Add(m); else meshGroups.Add(mlod.Meshes[m].MaterialIndex, new List<int> { m }); VRTF vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mlod.Meshes[m].VertexFormatIndex) as VRTF ?? VRTF.CreateDefaultForMesh(mlod.Meshes[m]); meshVRTF.Add(m, vrtf); if (updateUVs) rcolResource.FixUVScales(mlod.Meshes[m]); meshUVScales.Add(m, rcolResource.GetUVScales(mlod.Meshes[m])); } // Update the VBUFs for each mesh group and set the mesh bounds whilst we're here foreach (var key in meshGroups.Keys) { foreach (int m in meshGroups[key]) { VBUF vbuf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mlod.Meshes[m].VertexBufferIndex) as VBUF; if (vbuf == null) vbuf = new VBUF(rcolResource.RequestedApiVersion, null) { Version = 0x00000101, Flags = VBUF.FormatFlags.None, SwizzleInfo = new GenericRCOLResource.ChunkReference(0, null, 0), }; offScales.AddRange(getOffScales(m, -1, lmverts[m], meshUVScales[m])); vbuf.SetVertices(mlod, m, meshVRTF[m], lmverts[m], meshUVScales[m]); IResourceKey vbufRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mlod.Meshes[m].VertexBufferIndex); if (vbufRK == null)//means we created the VBUF: create a RK and add it vbufRK = new TGIBlock(0, null, defaultRK) { ResourceType = vbuf.ResourceType, }; rcolResource.ReplaceChunk(mlod.Meshes[m], "VertexBufferIndex", vbufRK, vbuf); if (updateBBs) mlod.Meshes[m].Bounds = vbuf.GetBoundingBox(mlod.Meshes[m], meshVRTF[m]); } } return offScales; }
public GenericRCOLResource ExportToResource(ulong instanceId, IDictionary<ulong, string> nameMap, bool exportAllNames) { this.mInstanceId = instanceId; GenericRCOLResource rcol = new GenericRCOLResource(0, null); AChunkObject[] chunks = this.FindAllChunks(false); GenericRCOLResource.ChunkEntryList chunkEntries = rcol.ChunkEntries; for (int i = 0; i < chunks.Length; i++) { chunkEntries.Add(chunks[i].Export(nameMap, exportAllNames)); } // TODO: Ensure the data in rcol is flushed to its Stream. // Currently this is done automatically when its Stream is // retrieved because adding to the chunk entry list triggers its // OnResourceChanged() listener, which marks it dirty, causing // its Unparse() to be invoked when its Stream is retrieved. return rcol; }
private void Export_Shown(object sender, EventArgs e) { try { sfdExport.Title += " -- Test version " + typeof(ExportForm).Assembly.GetName().Version.ToString(); DialogResult dr = sfdExport.ShowDialog(); if (dr != DialogResult.OK) { Environment.ExitCode = 1; return; } string folder = Path.GetDirectoryName(sfdExport.FileName); string filebase = Path.GetFileNameWithoutExtension(sfdExport.FileName).Replace("_filebase", ""); try { using (FileStream fs = new FileStream(Path.Combine(folder, string.Format("{0}_filebase.s3asc", filebase)), FileMode.Create, FileAccess.Write)) { fs.Close(); } GenericRCOLResource rcolResource = new GenericRCOLResource(0, stream); MLOD mlod = null; if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01661233)//MODL { this.Text = "Export MODL..."; var lodRef = rcolResource.GetMLODChunkRefforMODL(); if (lodRef == null) { CopyableMessageBox.Show("MODL (0x01661233) with no MLOD (0x01D10F34).", "Invalid MODL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } mlod = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, lodRef) as MLOD; } else if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01D10F34)//MLOD { this.Text = "Export MLOD..."; mlod = rcolResource.ChunkEntries[0].RCOLBlock as MLOD; } else { CopyableMessageBox.Show("RCOL resource must be MODL (0x01661233) or MLOD (0x01D10F34).", "Invalid RCOL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } Export export = new Export(new MyProgressBar(label1, pb)); for (int m = 0; m < mlod.Meshes.Count; m++) { string fnMesh = Path.Combine(folder, string.Format("{0}_group{1:D2}.s3ascg", filebase, m)); using (FileStream fsMesh = new FileStream(fnMesh, FileMode.Create, FileAccess.Write)) { export.Export_MLOD(new StreamWriter(fsMesh), rcolResource, mlod, mlod.Meshes[m]); fsMesh.Close(); } } Environment.ExitCode = 0; } catch (Exception ex) { CopyableMessageBox.IssueException(ex, "Error processing " + Program.Filename); throw ex; } } finally { this.Close(); } }
private void TattooGo_button_Click(object sender, EventArgs e) { float sortOrder; try { sortOrder = float.Parse(CASPsortOrder.Text); } catch { MessageBox.Show("Please enter a valid number for Sort Order in CAS"); return; } if (String.CompareOrdinal(TattooName.Text, " ") <= 0) { MessageBox.Show("Please enter a name for the tattoo"); return; } if (dds == null) { MessageBox.Show("Please select an image for the tattoo"); return; } ulong tatInstance; string tatName; if (TattooName.Text.IndexOf("uutattoo") < 0) { tatName = "uutattoo" + TattooName.Text; } else { tatName = TattooName.Text; } if (String.CompareOrdinal(TattooInstance.Text, " ") > 0) { if (!UInt64.TryParse(TattooInstance.Text, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out tatInstance)) { MessageBox.Show("Please enter a valid Tattoo Instance number in hexidecimal, or leave it blank"); return; } } else { tatInstance = FNVhash.FNV64(tatName); } PleaseWait_label.Visible = true; this.Refresh(); uint tatGroup = FNVhash.FNV24(tatName); ulong txtcInstance = FNVhash.FNV64(tatName + "TattooTemplate_Top_diffuse"); Package myPack; myPack = (Package)Package.NewPackage(0); NameMapResource.NameMapResource myMap = new NameMapResource.NameMapResource(0, null); myMap.Add(tatInstance, tatName); myMap.Add(tatGroup, tatName); myMap.Add(txtcInstance, tatName + "TattooTemplate_Top_diffuse"); XmlDocument doc1 = PresetBuilder.presetXML(tatName, tatInstance, presets[0], ChannelR_checkBox.Checked, ChannelG_checkBox.Checked, ChannelB_checkBox.Checked, ChannelA_checkBox.Checked); XmlDocument doc2 = PresetBuilder.presetXML(tatName, tatInstance, presets[1], ChannelR_checkBox.Checked, ChannelG_checkBox.Checked, ChannelB_checkBox.Checked, ChannelA_checkBox.Checked); XmlDocument doc3 = PresetBuilder.presetXML(tatName, tatInstance, presets[2], ChannelR_checkBox.Checked, ChannelG_checkBox.Checked, ChannelB_checkBox.Checked, ChannelA_checkBox.Checked); CASPartResource.CASPartResource myCasp; myCasp = new CASPartResource.CASPartResource(0, null); CASPartResource.CASPartResource.Preset pre1 = new CASPartResource.CASPartResource.Preset(0, null, doc1.OuterXml, 1); CASPartResource.CASPartResource.Preset pre2 = new CASPartResource.CASPartResource.Preset(0, null, doc2.OuterXml, 2); CASPartResource.CASPartResource.Preset pre3 = new CASPartResource.CASPartResource.Preset(0, null, doc3.OuterXml, 3); myCasp.Presets = new CASPartResource.CASPartResource.PresetList(null); myCasp.Presets.Add(pre1); myCasp.Presets.Add(pre2); myCasp.Presets.Add(pre3); myCasp.Unknown1 = tatName; myCasp.SortPriority = sortOrder; myCasp.Clothing = ClothingType.TattooTemplate; myCasp.DataType = DataTypeFlags.Body; myCasp.AgeGender = new AgeGenderFlags(0, null, (CASPtodder_checkBox.Checked ? AgeFlags.Toddler : 0) | (CASPchild_checkBox.Checked ? AgeFlags.Child : 0) | (CASPteen_checkBox.Checked ? AgeFlags.Teen : 0) | (CASPadult_checkBox.Checked ? AgeFlags.YoungAdult | AgeFlags.Adult : 0) | (CASPelder_checkBox.Checked ? AgeFlags.Elder : 0), (CASPfemale_checkBox.Checked ? GenderFlags.Female : 0) | (CASPmale_checkBox.Checked ? GenderFlags.Male : 0), 0, 0); myCasp.ClothingCategory = ClothingCategoryFlags.Athletic | ClothingCategoryFlags.Career | ClothingCategoryFlags.Everyday | ClothingCategoryFlags.FireFighting | ClothingCategoryFlags.Formalwear | ClothingCategoryFlags.Makeover | ClothingCategoryFlags.MartialArts | ClothingCategoryFlags.Naked | ClothingCategoryFlags.Outerwear | ClothingCategoryFlags.SkinnyDippingTowel | ClothingCategoryFlags.Sleepwear | ClothingCategoryFlags.Swimwear | ClothingCategoryFlags.Singed | ClothingCategoryFlags.ValidForMaternity; myCasp.CasPart1Index = 2; myCasp.CasPart2Index = 2; myCasp.BlendInfoFatIndex = 3; myCasp.BlendInfoFitIndex = 4; myCasp.BlendInfoThinIndex = 5; myCasp.BlendInfoSpecialIndex = 6; myCasp.OverlayPriority = 2u; myCasp.VPXYIndexes = new ByteIndexList(null); myCasp.VPXYIndexes.Add(7); myCasp.Diffuse1Indexes = new ByteIndexList(null); myCasp.Diffuse1Indexes.Add(8); myCasp.Specular1Indexes = new ByteIndexList(null); myCasp.Specular1Indexes.Add(9); myCasp.BONDIndexes = new ByteIndexList(null); myCasp.BONDIndexes.AddRange(new List <byte> { 2, 2, 2, 2, 2 }); myCasp.Unknown4 = "bare"; myCasp.TGIBlocks = new CountedTGIBlockList(null); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.DDS, 0, tatInstance)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.XML, 0, 0xF7FC14B9EA85B390)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, 0, 0, 0)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.BBLN, 0, 0xCBE03A305F80FF50)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.BBLN, 0, 0xCBE032305F80F1F8)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.BBLN, 0, 0x540F4B31F0B42342)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.BBLN, 0, 0x82F02E48897E22B4)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.VPXY, 1, tatGroup)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.TXTC, tatGroup, txtcInstance)); myCasp.TGIBlocks.Add(new TGIBlock(0, null, (uint)ResourceTypes.TXTC, tatGroup, 0xCBF29CE484222325)); uint fakeType = (uint)tatInstance; uint fakeGroup = (uint)(tatInstance >> 32); ulong fakeInstance = (ulong)ResourceTypes.DDS << 32; TxtcResource.TxtcResource txtc = TattooTextureCompositor.TattooTxtc(new TGIBlock(0, null, fakeType, fakeGroup, fakeInstance)); VPXY vpxy = new VPXY(0, null, 4, null, 2, new BoundingBox(0, null, new Vertex(0, null, -.0060f, 1.7157f, -.0060f), new Vertex(0, null, .0060f, 1.7277f, .0060f)), new byte[] { 0, 0, 0, 0 }, 0, 0, new TGIBlockList(null)); GenericRCOLResource vpxyRcol = new GenericRCOLResource(0, null); vpxyRcol.Version = 3; vpxyRcol.PublicChunks = 1; vpxyRcol.ChunkEntries = new GenericRCOLResource.ChunkEntryList(null); GenericRCOLResource.ChunkEntry vpxyChunk = new GenericRCOLResource.ChunkEntry(0, null, new TGIBlock(0, null, "ITG", (uint)ResourceTypes.VPXY, 1, tatGroup), vpxy); vpxyRcol.ChunkEntries.Add(vpxyChunk); IResourceIndexEntry rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.KEY, 0, tatInstance), myMap.Stream, true); rs.Compressed = (ushort)0xFFFF; rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.CASP, 0, tatInstance), myCasp.Stream, true); rs.Compressed = (ushort)0xFFFF; rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.TXTC, tatGroup, txtcInstance), txtc.Stream, true); rs.Compressed = (ushort)0xFFFF; rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.VPXY, 1, tatGroup), vpxyRcol.Stream, true); rs.Compressed = (ushort)0xFFFF; MemoryStream ms = new MemoryStream(); doc1.Save(ms); rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.XML, 0, tatInstance), ms, true); rs.Compressed = (ushort)0xFFFF; MemoryStream ms2 = new MemoryStream(); dds.UseDXT = false; dds.AlphaDepth = 8; dds.GenerateMipmaps = true; dds.Save(ms2); rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.DDS, 0, tatInstance), ms2, true); rs.Compressed = (ushort)0xFFFF; if (thumbNail != null) { MemoryStream ms3 = new MemoryStream(); thumbNail.Save(ms3, System.Drawing.Imaging.ImageFormat.Png); rs = myPack.AddResource(new TGIBlock(0, null, (uint)ResourceTypes.THUM, 1, tatInstance), ms3, true); rs.Compressed = (ushort)0xFFFF; } PleaseWait_label.Visible = false; SaveFileDialog saveFileDialog1 = new SaveFileDialog(); saveFileDialog1.Filter = PackageFilter; saveFileDialog1.Title = "Save as a new package"; saveFileDialog1.FileName = TattooName.Text + ".package"; saveFileDialog1.FilterIndex = 1; saveFileDialog1.CheckFileExists = false; saveFileDialog1.CheckPathExists = true; saveFileDialog1.OverwritePrompt = true; if (saveFileDialog1.ShowDialog() == DialogResult.OK) { myPack.SaveAs(saveFileDialog1.FileName); } ms.Dispose(); ms2.Dispose(); }
//-- public void Import_Mesh(StreamReader r, MLOD.Mesh mesh, GenericRCOLResource rcolResource, MLOD mlod, IResourceKey defaultRK, out meshExpImp.ModelBlocks.Vertex[] mverts) { #region Import VRTF bool isDefaultVRTF = false; VRTF defaultForMesh = VRTF.CreateDefaultForMesh(mesh); VRTF vrtf = new VRTF(rcolResource.RequestedApiVersion, null) { Version = 2, Layouts = null, }; r.Import_VRTF(mpb, vrtf); IResourceKey vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.VertexFormatIndex); if (vrtfRK == null) { vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (vrtfRK == null) { vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.ScaleOffsetIndex); } if (vrtfRK == null) { vrtfRK = new TGIBlock(0, null, 0, 0, System.Security.Cryptography.FNV64.GetHash(DateTime.UtcNow.ToString() + defaultRK.ToString())); } vrtfRK = new TGIBlock(0, null, vrtfRK) { ResourceType = vrtf.ResourceType, }; } if (vrtf.Equals(defaultForMesh)) { isDefaultVRTF = true; mesh.VertexFormatIndex = new GenericRCOLResource.ChunkReference(0, null, 0);//Clear the reference } else { rcolResource.ReplaceChunk(mesh, "VertexFormatIndex", vrtfRK, vrtf); } #endregion #region Import SKIN // we need to read the data in the file... SKIN skin = new SKIN(rcolResource.RequestedApiVersion, null) { Version = 1, Bones = null, }; r.Import_SKIN(mpb, skin); // However, we do *NOT* want to update the RCOL with what we read - we are not replacing the object skeleton here #if UNDEF if (skin.Bones != null) { IResourceKey skinRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (skinRK == null) { skinRK = new TGIBlock(0, null, vrtfRK) { ResourceType = skin.ResourceType, } } ; rcolResource.ReplaceChunk(mesh, "SkinControllerIndex", skinRK, skin); } #endif #endregion mverts = Import_VBUF_Main(r, mlod, mesh, vrtf, isDefaultVRTF); #region Import IBUF IBUF ibuf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF; if (ibuf == null) { ibuf = new IBUF(rcolResource.RequestedApiVersion, null) { Version = 2, Flags = IBUF.FormatFlags.DifferencedIndices, DisplayListUsage = 0, } } ; Import_IBUF_Main(r, mlod, mesh, ibuf); IResourceKey ibufRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.IndexBufferIndex); if (ibufRK == null) { ibufRK = new TGIBlock(0, null, defaultRK) { ResourceType = ibuf.ResourceType, } } ; rcolResource.ReplaceChunk(mesh, "IndexBufferIndex", ibufRK, ibuf); #endregion #region Update the JointReferences UIntList joints = CreateJointReferences(mesh, mverts, skin); List <uint> added = new List <uint>(joints); List <uint> removed = new List <uint>(); foreach (var j in mesh.JointReferences) { if (joints.Contains(j)) { added.Remove(j); } else { removed.Add(j); } } // Remove root removed.Remove(0xCD68F001); if (added.Count != 0) { mesh.JointReferences.AddRange(added); System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with newly assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, added.Count, String.Join(", ", added.ConvertAll <string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } // with the 20120601 change to export, this warning on import has lost its severity... and been dropped. #if UNDEF if (removed.Count != 0) { //#if UNDEF // http://dino.drealm.info/den/denforum/index.php?topic=394.msg3876#msg3876 removed.ForEach(j => mesh.JointReferences[mesh.JointReferences.IndexOf(j)] = 0); //#endif // However, OM felt more comfortable if there was some indication something a little odd was going on. System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with no assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, removed.Count, String.Join(", ", removed.ConvertAll <string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } #endif #endregion } ModelBlocks.Vertex[] Import_VBUF_Main(StreamReader r, MLOD mlod, MLOD.Mesh mesh, VRTF vrtf, bool isDefaultVRTF) { string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 2) { throw new InvalidDataException("Invalid tag line read for 'vbuf'."); } if (split[0] != "vbuf") { throw new InvalidDataException("Expected line tag 'vbuf' not found."); } int count; if (!int.TryParse(split[1], out count)) { throw new InvalidDataException("'vbuf' line has invalid count."); } //Wes's MilkShape plug-in sends back the first line in all subsequent lines of a dropShadow. return(r.Import_VBUF(mpb, count, vrtf, (mesh.Flags & MeshFlags.ShadowCaster) == 0)); } void Import_IBUF_Main(StreamReader r, MLOD mlod, MLOD.Mesh mesh, IBUF ibuf) { string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 2) { throw new InvalidDataException("Invalid tag line read for 'ibuf'."); } if (split[0] != "ibuf") { throw new InvalidDataException("Expected line tag 'ibuf' not found."); } int count; if (!int.TryParse(split[1], out count)) { throw new InvalidDataException("'ibuf' line has invalid count."); } ibuf.SetIndices(mlod, mesh, r.Import_IBUF(mpb, IBUF.IndexCountFromPrimitiveType(mesh.PrimitiveType), count)); } UIntList CreateJointReferences(MLOD.Mesh mesh, ModelBlocks.Vertex[] mverts, SKIN skin) { if (skin == null || skin.Bones == null) { return(new UIntList(null)); } int maxReference = -1; foreach (var vert in mverts) { if (vert.BlendIndices != null) { foreach (var reference in vert.BlendIndices) { if ((sbyte)reference > maxReference) { maxReference = reference; } } } } return(maxReference > -1 ? new UIntList(null, skin.Bones.GetRange(0, maxReference + 1).ConvertAll <uint>(x => x.NameHash)) : new UIntList(null)); }
private void Import_Shown(object sender, EventArgs e) { try { ofdImport.Title += " -- Test version " + typeof(ImportForm).Assembly.GetName().Version.ToString(); DialogResult dr = ofdImport.ShowDialog(); if (dr != DialogResult.OK) { Environment.ExitCode = 1; return; } string folder = Path.GetDirectoryName(ofdImport.FileName); string filebase = Path.GetFileNameWithoutExtension(ofdImport.FileName).Replace("_filebase", ""); if (!File.Exists(Path.Combine(folder, string.Format("{0}_filebase.s3m2b", filebase)))) { CopyableMessageBox.Show("File name must end \"_filebase.s3m2b\"", "Base file not found", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } bool updateBBs = false; int q = CopyableMessageBox.Show("Update mesh bounding boxes?", Application.ProductName, CopyableMessageBoxButtons.YesNoCancel, CopyableMessageBoxIcon.Question); if (q == 0) { updateBBs = true; } else if (q == 2) { Environment.ExitCode = 1; return; } bool updateUVs = false; q = CopyableMessageBox.Show("Maximise mapping area?", Application.ProductName, CopyableMessageBoxButtons.YesNoCancel, CopyableMessageBoxIcon.Question); if (q == 0) { updateUVs = true; } else if (q == 2) { Environment.ExitCode = 1; return; } try { GenericRCOLResource rcolResource = new GenericRCOLResource(0, stream); MLOD mlod = null; IResourceKey rk = null; if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01661233)//MODL { this.Text = "Import MODL..."; var lodRef = rcolResource.GetMLODChunkRefforMODL(); if (lodRef == null) { CopyableMessageBox.Show("MODL (0x01661233) with no MLOD (0x01D10F34).", "Invalid MODL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } rk = GenericRCOLResource.ChunkReference.GetKey(rcolResource, lodRef); mlod = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, lodRef) as MLOD; } else if (rcolResource.ChunkEntries[0].TGIBlock.ResourceType == 0x01D10F34)//MLOD { this.Text = "Import MLOD..."; rk = rcolResource.ChunkEntries[0].TGIBlock; mlod = rcolResource.ChunkEntries[0].RCOLBlock as MLOD; } else { CopyableMessageBox.Show("RCOL resource must be MODL (0x01661233) or MLOD (0x01D10F34).", "Invalid RCOL resource", CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Error); Environment.ExitCode = 1; return; } Import import = new Import(new MyProgressBar(label1, pb)); int m = 0; List <meshExpImp.ModelBlocks.Vertex[]> lmverts = new List <meshExpImp.ModelBlocks.Vertex[]>(); List <List <meshExpImp.ModelBlocks.Vertex[]> > llverts = new List <List <meshExpImp.ModelBlocks.Vertex[]> >(); while (true) { string fnMesh = Path.Combine(folder, string.Format("{0}_group{1:D2}.s3m2bg", filebase, m)); if (!File.Exists(fnMesh)) { break; } using (FileStream fsMesh = new FileStream(fnMesh, FileMode.Open, FileAccess.Read)) { meshExpImp.ModelBlocks.Vertex[] mverts; List <meshExpImp.ModelBlocks.Vertex[]> lverts; import.Import_Mesh(new StreamReader(fsMesh), mlod.Meshes[m++], rcolResource, mlod, rk, out mverts, out lverts); lmverts.Add(mverts); llverts.Add(lverts); fsMesh.Close(); } } List <Import.offScale> offScales = import.VertsToVBUFs(rcolResource, mlod, rk, lmverts, llverts, updateBBs, updateUVs); if (offScales.Count > 0) { while (true) { switch ( CopyableMessageBox.Show( Application.ProductName + " has detected some off-scale UV mappings.\n" + "This may mean your mapping is not stored as you intended.\n" + "This is often caused by UV-mapping too close to the edge of the map.\n\n" + "Click 'Commit' to commit the change or 'Cancel' to abandon.", Application.ProductName, CopyableMessageBoxIcon.Warning, new String[] { "C&ommit", "&View", "C&ancel", }, 0, 2)) { case 0: //commit goto Commit; case 1: //view System.Text.StringBuilder sb = new System.Text.StringBuilder(); offScales.ForEach(x => sb.AppendLine(x.ToString())); CopyableMessageBox.Show(sb.ToString(), Application.ProductName, CopyableMessageBoxButtons.OK, CopyableMessageBoxIcon.Information); break; default: //cancel Environment.ExitCode = 1; return; } } } Commit: result = (byte[])rcolResource.AsBytes.Clone(); Environment.ExitCode = 0; } catch (Exception ex) { CopyableMessageBox.IssueException(ex, "Error processing " + Program.Filename); throw ex; } } finally { this.Close(); } }
//-- public void Import_Mesh(StreamReader r, MLOD.Mesh mesh, GenericRCOLResource rcolResource, MLOD mlod, IResourceKey defaultRK, out meshExpImp.ModelBlocks.Vertex[] mverts, out List <meshExpImp.ModelBlocks.Vertex[]> lverts) { #region Import VRTF bool isDefaultVRTF = false; VRTF defaultForMesh = VRTF.CreateDefaultForMesh(mesh); VRTF vrtf = new VRTF(rcolResource.RequestedApiVersion, null) { Version = 2, Layouts = null, }; r.Import_VRTF(mpb, vrtf); IResourceKey vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.VertexFormatIndex); if (vrtfRK == null) { vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (vrtfRK == null) { vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.ScaleOffsetIndex); } if (vrtfRK == null) { vrtfRK = new TGIBlock(0, null, 0, 0, System.Security.Cryptography.FNV64.GetHash(DateTime.UtcNow.ToString() + defaultRK.ToString())); } vrtfRK = new TGIBlock(0, null, vrtfRK) { ResourceType = vrtf.ResourceType, }; } if (vrtf.Equals(defaultForMesh)) { isDefaultVRTF = true; mesh.VertexFormatIndex = new GenericRCOLResource.ChunkReference(0, null, 0);//Clear the reference } else { rcolResource.ReplaceChunk(mesh, "VertexFormatIndex", vrtfRK, vrtf); } #endregion #region Import SKIN // we need to read the data in the file... SKIN skin = new SKIN(rcolResource.RequestedApiVersion, null) { Version = 1, Bones = null, }; r.Import_SKIN(mpb, skin); // However, we do *NOT* want to update the RCOL with what we read - we are not replacing the object skeleton here #if UNDEF if (skin.Bones != null) { IResourceKey skinRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (skinRK == null) { skinRK = new TGIBlock(0, null, vrtfRK) { ResourceType = skin.ResourceType, } } ; rcolResource.ReplaceChunk(mesh, "SkinControllerIndex", skinRK, skin); } #endif #endregion mverts = Import_VBUF_Main(r, mlod, mesh, vrtf, isDefaultVRTF); #region Import IBUF IBUF ibuf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF; if (ibuf == null) { ibuf = new IBUF(rcolResource.RequestedApiVersion, null) { Version = 2, Flags = IBUF.FormatFlags.DifferencedIndices, DisplayListUsage = 0, } } ; Import_IBUF_Main(r, mlod, mesh, ibuf); IResourceKey ibufRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.IndexBufferIndex); if (ibufRK == null) { ibufRK = new TGIBlock(0, null, defaultRK) { ResourceType = ibuf.ResourceType, } } ; rcolResource.ReplaceChunk(mesh, "IndexBufferIndex", ibufRK, ibuf); #endregion // This reads both VBUF Vertex[]s and the ibufs; but the ibufs just go straight in quite happily lverts = Import_MeshGeoStates(r, mlod, mesh, vrtf, isDefaultVRTF, ibuf); #region Update the JointReferences UIntList joints = CreateJointReferences(mesh, mverts, lverts ?? new List <meshExpImp.ModelBlocks.Vertex[]>(), skin); List <uint> added = new List <uint>(joints); List <uint> removed = new List <uint>(); foreach (var j in mesh.JointReferences) { if (joints.Contains(j)) { added.Remove(j); } else { removed.Add(j); } } // Remove root removed.Remove(0xCD68F001); if (added.Count != 0) { mesh.JointReferences.AddRange(added); System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with newly assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, added.Count, String.Join(", ", added.ConvertAll <string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } // with the 20120601 change to export, this warning on import has lost its severity... and been dropped. #if UNDEF if (removed.Count != 0) { //#if UNDEF // http://dino.drealm.info/den/denforum/index.php?topic=394.msg3876#msg3876 removed.ForEach(j => mesh.JointReferences[mesh.JointReferences.IndexOf(j)] = 0); //#endif // However, OM felt more comfortable if there was some indication something a little odd was going on. System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with no assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, removed.Count, String.Join(", ", removed.ConvertAll <string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } #endif #endregion } meshExpImp.ModelBlocks.Vertex[] Import_VBUF_Main(StreamReader r, MLOD mlod, MLOD.Mesh mesh, VRTF vrtf, bool isDefaultVRTF) { string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 2) { throw new InvalidDataException("Invalid tag line read for 'vbuf'."); } if (split[0] != "vbuf") { throw new InvalidDataException("Expected line tag 'vbuf' not found."); } int count; if (!int.TryParse(split[1], out count)) { throw new InvalidDataException("'vbuf' line has invalid count."); } return(r.Import_VBUF(mpb, count, vrtf)); } void Import_IBUF_Main(StreamReader r, MLOD mlod, MLOD.Mesh mesh, IBUF ibuf) { string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 2) { throw new InvalidDataException("Invalid tag line read for 'ibuf'."); } if (split[0] != "ibuf") { throw new InvalidDataException("Expected line tag 'ibuf' not found."); } int count; if (!int.TryParse(split[1], out count)) { throw new InvalidDataException("'ibuf' line has invalid count."); } ibuf.SetIndices(mlod, mesh, r.Import_IBUF(mpb, IBUF.IndexCountFromPrimitiveType(mesh.PrimitiveType), count)); } List <meshExpImp.ModelBlocks.Vertex[]> Import_MeshGeoStates(StreamReader r, MLOD mlod, MLOD.Mesh mesh, VRTF vrtf, bool isDefaultVRTF, IBUF ibuf) { MLOD.GeometryStateList oldGeos = new MLOD.GeometryStateList(null, mesh.GeometryStates); r.Import_GEOS(mpb, mesh); if (mesh.GeometryStates.Count <= 0) { return(null); } List <meshExpImp.ModelBlocks.Vertex[]> lverts = new List <meshExpImp.ModelBlocks.Vertex[]>(); for (int g = 0; g < mesh.GeometryStates.Count; g++) { lverts.Add(Import_VBUF_Geos(r, mlod, mesh, g, vrtf, isDefaultVRTF)); Import_IBUF_Geos(r, mlod, mesh, g, ibuf); } return(lverts); } UIntList CreateJointReferences(MLOD.Mesh mesh, meshExpImp.ModelBlocks.Vertex[] mverts, List <meshExpImp.ModelBlocks.Vertex[]> lverts, SKIN skin) { if (skin == null || skin.Bones == null) { return(new UIntList(null)); } int maxReference = -1; lverts.Insert(0, mverts); foreach (var vertices in lverts) { if (vertices != null) { foreach (var vert in vertices) { if (vert.BlendIndices != null) { foreach (var reference in vert.BlendIndices) { if ((sbyte)reference > maxReference) { maxReference = reference; } } } } } } lverts.Remove(mverts); return(maxReference > -1 ? new UIntList(null, skin.Bones.GetRange(0, maxReference + 1).ConvertAll <uint>(x => x.NameHash)) : new UIntList(null)); } meshExpImp.ModelBlocks.Vertex[] Import_VBUF_Geos(StreamReader r, MLOD mlod, MLOD.Mesh mesh, int geoStateIndex, VRTF vrtf, bool isDefaultVRTF) { //w.WriteLine(string.Format("vbuf {0} {1} {2}", geoStateIndex, mesh.GeometryStates[geoStateIndex].MinVertexIndex, mesh.GeometryStates[geoStateIndex].VertexCount)); string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 4) { throw new InvalidDataException(string.Format("Invalid tag line read for geoState {0} 'vbuf'.", geoStateIndex)); } if (split[0] != "vbuf") { throw new InvalidDataException("Expected line tag 'vbuf' not found."); } int lineIndex; if (!int.TryParse(split[1], out lineIndex)) { throw new InvalidDataException(string.Format("geoState {0} 'vbuf' line has invalid geoStateIndex.", geoStateIndex)); } if (lineIndex != geoStateIndex) { throw new InvalidDataException(string.Format("geoState {0} 'vbuf' line has incorrect geoStateIndex value {1}.", geoStateIndex, lineIndex)); } int minVertexIndex; if (!int.TryParse(split[2], out minVertexIndex)) { throw new InvalidDataException(string.Format("geoState {0} 'vbuf' line has invalid MinVertexIndex.", geoStateIndex)); } int vertexCount; if (!int.TryParse(split[3], out vertexCount)) { throw new InvalidDataException(string.Format("geoState {0} 'vbuf' line has invalid VertexCount.", geoStateIndex)); } if (minVertexIndex + vertexCount <= mesh.MinVertexIndex + mesh.VertexCount) { mesh.GeometryStates[geoStateIndex].MinVertexIndex = minVertexIndex; mesh.GeometryStates[geoStateIndex].VertexCount = vertexCount; return(null); } if (minVertexIndex != mesh.GeometryStates[geoStateIndex].MinVertexIndex) { throw new InvalidDataException(string.Format("geoState {0} 'vbuf' line has unexpected MinVertexIndex {1}; expected {2}.", geoStateIndex, minVertexIndex, mesh.GeometryStates[geoStateIndex].MinVertexIndex)); } return(r.Import_VBUF(mpb, vertexCount, vrtf)); } void Import_IBUF_Geos(StreamReader r, MLOD mlod, MLOD.Mesh mesh, int geoStateIndex, IBUF ibuf) { //w.WriteLine(string.Format("ibuf {0} {1} {2}", geoStateIndex, mesh.GeometryStates[geoStateIndex].StartIndex, mesh.GeometryStates[geoStateIndex].PrimitiveCount)); string tagLine = r.ReadTag(); string[] split = tagLine.Split(new char[] { ' ', }, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 4) { throw new InvalidDataException("Invalid tag line read for 'ibuf'."); } if (split[0] != "ibuf") { throw new InvalidDataException("Expected line tag 'ibuf' not found."); } int lineIndex; if (!int.TryParse(split[1], out lineIndex)) { throw new InvalidDataException(string.Format("geoState {0} 'ibuf' line has invalid geoStateIndex.", geoStateIndex)); } if (lineIndex != geoStateIndex) { throw new InvalidDataException(string.Format("geoState {0} 'ibuf' line has incorrect geoStateIndex value {1}.", geoStateIndex, lineIndex)); } int startIndex; if (!int.TryParse(split[2], out startIndex)) { throw new InvalidDataException(string.Format("geoState {0} 'ibuf' line has invalid StartIndex.", geoStateIndex)); } int primitiveCount; if (!int.TryParse(split[3], out primitiveCount)) { throw new InvalidDataException(string.Format("geoState {0} 'ibuf' line has invalid PrimitiveCount.", geoStateIndex)); } int sizePerPrimitive = IBUF.IndexCountFromPrimitiveType(mesh.PrimitiveType); if (startIndex + primitiveCount * sizePerPrimitive <= mesh.StartIndex + mesh.PrimitiveCount * sizePerPrimitive) { mesh.GeometryStates[geoStateIndex].StartIndex = startIndex; mesh.GeometryStates[geoStateIndex].PrimitiveCount = primitiveCount; return; } if (startIndex != mesh.GeometryStates[geoStateIndex].StartIndex) { throw new InvalidDataException(string.Format("geoState {0} 'ibuf' line has unexpected StartIndex {1}; expected {2}.", geoStateIndex, startIndex, mesh.GeometryStates[geoStateIndex].StartIndex)); } ibuf.SetIndices(mlod, mesh, geoStateIndex, r.Import_IBUF(mpb, IBUF.IndexCountFromPrimitiveType(mesh.PrimitiveType), primitiveCount)); }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (String.IsNullOrEmpty(value as string)) { return null; } var path = value as string; if (path != null && File.Exists(path)) { using (FileStream s = File.OpenRead(path)) { var rcol = new GenericRCOLResource(0, s); MLOD mlod = rcol.ChunkEntries .Where(x => x.RCOLBlock is MLOD) .Select(x => x.RCOLBlock) .Cast<MLOD>() .FirstOrDefault(); double minX = double.MaxValue, minZ = double.MaxValue, maxX = double.MinValue, maxZ = double.MinValue; var pnty = new List<Point[]>(); foreach (MLOD.Mesh mesh in mlod.Meshes) { var vbuf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.VertexBufferIndex) as VBUF; var ibuf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.IndexBufferIndex) as IBUF; var vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcol, mesh.VertexFormatIndex) as VRTF; if (vrtf == null) continue; Vertex[] verts = vbuf.GetVertices(mesh, vrtf, null); int[] indices = ibuf.GetIndices(mesh); for (int i = 0; i < indices.Length/3; i++) { var tst = new int[3]; var poly = new Point[3]; for (int j = 0; j < 3; j++) { Vertex vert = verts[indices[i*3 + j]]; double x = (Offset + (vert.Position[0]*Scale)); double z = -(Offset + (vert.Position[2]*Scale)); poly[j] = new Point((int) x, (int) z); if (poly[j].X > maxX) maxX = poly[j].X; if (poly[j].X < minX) minX = poly[j].X; if (poly[j].Y > maxZ) maxZ = poly[j].Y; if (poly[j].Y < minZ) minZ = poly[j].Y; } pnty.Add(poly); } } var width = (int) (maxX - minX); var height = (int) (maxZ - minZ); var bmp = new Bitmap(width, height); Graphics gBmp = Graphics.FromImage(bmp); gBmp.CompositingMode = CompositingMode.SourceCopy; float bright = 1.1f; System.Drawing.Color c = System.Drawing.Color.FromArgb(255, Fill.R, Fill.G, Fill.B); System.Drawing.Color c2 = System.Drawing.Color.FromArgb(255, Stroke.R, Stroke.G, Stroke.B); var b = new SolidBrush(c); var b2 = new SolidBrush(c2); var pen = new Pen(b2); foreach (Point[] pointse in pnty) { Point[] scaled = pointse.Select(old => new Point((int) (old.X - minX), (int) (old.Y - minZ))).ToArray(); gBmp.FillPolygon(b, scaled); } foreach (Point[] pointse in pnty) { Point[] scaled = pointse.Select(old => new Point((int) (old.X - minX), (int) (old.Y - minZ))).ToArray(); gBmp.DrawPolygon(pen, scaled); } var bmpImg = new BitmapImage(); var ms = new MemoryStream(); bmp.Save(ms, ImageFormat.Png); ms.Position = 0L; bmpImg.BeginInit(); bmpImg.StreamSource = ms; bmpImg.EndInit(); return bmpImg; } } return null; }
private List <IResourceConnection> MATD_GetDiffuseSpecular() { string rootStr = this.GetContentPathRootName(); List <IResourceConnection> results = new List <IResourceConnection>(); GenericRCOLResource rcol = base.Resource as GenericRCOLResource; if (rcol == null) { return(results); } string absolutePath, absoluteName; Diagnostics.Log("MATD_GetDiffuseSpecular: " + ResourceGraph.PrintRKTag(base.originalKey, rootStr)); for (int i = 0; i < rcol.ChunkEntries.Count; i++) { MATD matd = rcol.ChunkEntries[i].RCOLBlock as MATD; if (matd == null) { continue; } ShaderDataList sdataList; if (matd.ContentFields.Contains("Mtnf")) { sdataList = matd.Mtnf.SData; absolutePath = rootStr + ".ChunkEntries[" + i + "].RCOLBlock.Mtnf.SData["; } else { sdataList = matd.Mtrl.SData; absolutePath = rootStr + ".ChunkEntries[" + i + "].RCOLBlock.Mtrl.SData["; } for (int j = 0; j < sdataList.Count; j++) { ElementTextureRef texRef = sdataList[i] as ElementTextureRef; if (texRef != null && IsWantedImage(texRef.Field)) { TGIBlock tgiblock = rcol.Resources[texRef.Data.TGIBlockIndex]; if (ResourceGraph.IsDDS(tgiblock.ResourceType)) { absoluteName = rootStr + ".Resources[" + texRef.Data.TGIBlockIndex + "]"; results.Add(new DefaultConnection(tgiblock, tgiblock, ResourceDataActions.FindWrite, absoluteName)); } } else { ElementTextureKey texKey = sdataList[i] as ElementTextureKey; if (texKey != null && IsWantedImage(texKey.Field)) { if (ResourceGraph.IsDDS(texKey.Data.ResourceType)) { absoluteName = absolutePath + j + "].Data"; results.Add(new DefaultConnection(texKey.Data, texKey, ResourceDataActions.FindWrite, absoluteName, rootStr + ".Data")); } } } } } return(results); }
protected List <IResourceConnection> SlurpAllRKs() { List <IResourceConnection> results = new List <IResourceConnection>(); string rootStr = this.GetContentPathRootName(); if (!RKContainer.IsLegalFieldName(rootStr)) { Diagnostics.Log("Illegal Root Field Name for " + ResourceGraph.PrintRK(base.originalKey) + ":" + rootStr); rootStr = "root"; } if (base.resource is GenericRCOLResource) { Diagnostics.Log("Slurping RCOL Resource RKs for " + rootStr + ":" + ResourceGraph.PrintRK(base.originalKey)); GenericRCOLResource rcol = base.resource as GenericRCOLResource; TGIBlock tgiBlock; int i, count = rcol.Resources.Count; for (i = 0; i < count; i++) { tgiBlock = rcol.Resources[i]; if (includeDDSes || !ResourceGraph.IsDDS(tgiBlock.ResourceType)) { results.Add(new DefaultConnection(tgiBlock, tgiBlock, ResourceDataActions.FindWrite, rootStr + ".Resources[" + i + "]")); } } Diagnostics.Log("Slurping RCOL ChunkEntry RKs for " + rootStr + ":" + ResourceGraph.PrintRK(base.originalKey)); string absolutePath; GenericRCOLResource.ChunkEntry chunk; count = rcol.ChunkEntries.Count; for (i = 0; i < count; i++) { absolutePath = rootStr + ".ChunkEntries[" + i + "].RCOLBlock"; chunk = rcol.ChunkEntries[i]; tgiBlock = chunk.TGIBlock; switch (GetChunkType(tgiBlock)) { case ChunkEntryType.Kindred: this.kindredRCOLChunkKeys.Add(tgiBlock); results.AddRange(RKContainer.SlurpRKsFromField(absolutePath, chunk.RCOLBlock, this.rkContainers, this.ICanSlurpRK)); break; case ChunkEntryType.Internal: results.AddRange(RKContainer.SlurpRKsFromField(absolutePath, chunk.RCOLBlock, this.rkContainers, this.ICanSlurpRK)); break; case ChunkEntryType.Unique: results.Add(new DefaultConnection(tgiBlock, chunk.RCOLBlock, ResourceDataActions.None, absolutePath)); break; } } } else if (base.resource is AApiVersionedFields) { Diagnostics.Log("Slurping RKs for " + rootStr + ":" + ResourceGraph.PrintRK(base.originalKey)); results.AddRange(RKContainer.SlurpRKsFromField(rootStr, base.resource as AApiVersionedFields, this.rkContainers, this.ICanSlurpRK)); } return(results); }
//-- public void Import_Mesh(StreamReader r, MLOD.Mesh mesh, GenericRCOLResource rcolResource, MLOD mlod, IResourceKey defaultRK, out meshExpImp.ModelBlocks.Vertex[] mverts) { #region Import VRTF bool isDefaultVRTF = false; VRTF defaultForMesh = VRTF.CreateDefaultForMesh(mesh); VRTF vrtf = new VRTF(rcolResource.RequestedApiVersion, null) { Version = 2, Layouts = null, }; r.Import_VRTF(mpb, vrtf); IResourceKey vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.VertexFormatIndex); if (vrtfRK == null) { vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (vrtfRK == null) vrtfRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.ScaleOffsetIndex); if (vrtfRK == null) vrtfRK = new TGIBlock(0, null, 0, 0, System.Security.Cryptography.FNV64.GetHash(DateTime.UtcNow.ToString() + defaultRK.ToString())); vrtfRK = new TGIBlock(0, null, vrtfRK) { ResourceType = vrtf.ResourceType, }; } if (vrtf.Equals(defaultForMesh)) { isDefaultVRTF = true; mesh.VertexFormatIndex = new GenericRCOLResource.ChunkReference(0, null, 0);//Clear the reference } else rcolResource.ReplaceChunk(mesh, "VertexFormatIndex", vrtfRK, vrtf); #endregion #region Import SKIN // we need to read the data in the file... SKIN skin = new SKIN(rcolResource.RequestedApiVersion, null) { Version = 1, Bones = null, }; r.Import_SKIN(mpb, skin); // However, we do *NOT* want to update the RCOL with what we read - we are not replacing the object skeleton here #if UNDEF if (skin.Bones != null) { IResourceKey skinRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.SkinControllerIndex); if (skinRK == null) skinRK = new TGIBlock(0, null, vrtfRK) { ResourceType = skin.ResourceType, }; rcolResource.ReplaceChunk(mesh, "SkinControllerIndex", skinRK, skin); } #endif #endregion mverts = Import_VBUF_Main(r, mlod, mesh, vrtf, isDefaultVRTF); #region Import IBUF IBUF ibuf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mesh.IndexBufferIndex) as IBUF; if (ibuf == null) ibuf = new IBUF(rcolResource.RequestedApiVersion, null) { Version = 2, Flags = IBUF.FormatFlags.DifferencedIndices, DisplayListUsage = 0, }; Import_IBUF_Main(r, mlod, mesh, ibuf); IResourceKey ibufRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mesh.IndexBufferIndex); if (ibufRK == null) ibufRK = new TGIBlock(0, null, defaultRK) { ResourceType = ibuf.ResourceType, }; rcolResource.ReplaceChunk(mesh, "IndexBufferIndex", ibufRK, ibuf); #endregion #region Update the JointReferences UIntList joints = CreateJointReferences(mesh, mverts, skin); List<uint> added = new List<uint>(joints); List<uint> removed = new List<uint>(); foreach (var j in mesh.JointReferences) { if (joints.Contains(j)) added.Remove(j); else removed.Add(j); } // Remove root removed.Remove(0xCD68F001); if (added.Count != 0) { mesh.JointReferences.AddRange(added); System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with newly assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, added.Count, String.Join(", ", added.ConvertAll<string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } // with the 20120601 change to export, this warning on import has lost its severity... and been dropped. #if UNDEF if (removed.Count != 0) { //#if UNDEF // http://dino.drealm.info/den/denforum/index.php?topic=394.msg3876#msg3876 removed.ForEach(j => mesh.JointReferences[mesh.JointReferences.IndexOf(j)] = 0); //#endif // However, OM felt more comfortable if there was some indication something a little odd was going on. System.Windows.Forms.CopyableMessageBox.Show(String.Format("Mesh: 0x{0:X8}\nJointReferences with no assigned (via BlendIndex) vertex: {1}\n({2})", mesh.Name, removed.Count, String.Join(", ", removed.ConvertAll<string>(a => "0x" + a.ToString("X8")).ToArray())), "Warning", System.Windows.Forms.CopyableMessageBoxButtons.OK, System.Windows.Forms.CopyableMessageBoxIcon.Warning); } #endif #endregion }
public FootprintEditorViewModel(GenericRCOLResource rcol) { mRcol = rcol; mFootprint = rcol.ChunkEntries[0].RCOLBlock as FTPT; mFootprintAreas = new ObservableCollection <AreaViewModel>(mFootprint.FootprintAreas.Select(x => new AreaViewModel(this, x))); mSlotAreas = new ObservableCollection <AreaViewModel>(mFootprint.SlotAreas.Select(x => new AreaViewModel(this, x))); AddSlotCommand = new UserCommand <FootprintEditorViewModel>(x => x != null, x => x.AddSlotArea()); CloneSlotCommand = new UserCommand <FootprintEditorViewModel>(x => x != null && x.CheckSlotArea(), x => x.CopySlotArea()); DeleteSlotCommand = new UserCommand <FootprintEditorViewModel>(x => x != null && x.CheckSlotArea(), x => x.DeleteArea()); AddFootprintCommand = new UserCommand <FootprintEditorViewModel>(x => x != null, x => x.AddFootprintArea()); CloneFootprintCommand = new UserCommand <FootprintEditorViewModel>(x => x != null && x.CheckFootprintArea(), x => x.CopyFootprintArea()); DeleteFootprintCommand = new UserCommand <FootprintEditorViewModel>(x => x != null && x.CheckFootprintArea(), x => x.DeleteArea()); CommitCommand = new UserCommand <FootprintEditorViewModel>(x => true, y => { mIsSaving = true; Application.Current.Shutdown(); }); CancelCommand = new UserCommand <FootprintEditorViewModel>(x => true, y => { mIsSaving = false; Application.Current.Shutdown(); }); SetBackgroundImageCommand = new UserCommand <FootprintEditorViewModel>( x => true, y => { var d = new OpenFileDialog { CheckFileExists = true, Multiselect = false }; if (d.ShowDialog() == true) { BackgroundImagePath = d.FileName; } } ); ClearBackgroundImageCommand = new UserCommand <FootprintEditorViewModel>( x => x != null && !String.IsNullOrEmpty(x.BackgroundImagePath), y => y.BackgroundImagePath = null ); SetReferenceMeshCommand = new UserCommand <FootprintEditorViewModel>( x => true, y => { var d = new OpenFileDialog { CheckFileExists = true, Multiselect = false }; if (d.ShowDialog() == true) { ReferenceMesh = d.FileName; } } ); ClearReferenceMeshCommand = new UserCommand <FootprintEditorViewModel>( x => x != null && !String.IsNullOrEmpty(x.ReferenceMesh), y => y.ReferenceMesh = null ); SelectedFootprint = FootprintAreas.FirstOrDefault(); if (SelectedArea == null) { SelectedSlot = SlotAreas.FirstOrDefault(); } }
public List <offScale> VertsToVBUFs(GenericRCOLResource rcolResource, MLOD mlod, IResourceKey defaultRK, List <meshExpImp.ModelBlocks.Vertex[]> lmverts, List <List <meshExpImp.ModelBlocks.Vertex[]> > llverts, bool updateBBs, bool updateUVs) { // List of UV elements going off scale List <offScale> offScales = new List <offScale>(); // Find everything for each mesh group Dictionary <GenericRCOLResource.ChunkReference, List <int> > meshGroups = new Dictionary <GenericRCOLResource.ChunkReference, List <int> >(); Dictionary <int, VRTF> meshVRTF = new Dictionary <int, VRTF>(); Dictionary <int, float[]> meshUVScales = new Dictionary <int, float[]>(); for (int m = 0; m < mlod.Meshes.Count; m++) { if (meshGroups.ContainsKey(mlod.Meshes[m].MaterialIndex)) { meshGroups[mlod.Meshes[m].MaterialIndex].Add(m); } else { meshGroups.Add(mlod.Meshes[m].MaterialIndex, new List <int> { m }); } VRTF vrtf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mlod.Meshes[m].VertexFormatIndex) as VRTF ?? VRTF.CreateDefaultForMesh(mlod.Meshes[m]); meshVRTF.Add(m, vrtf); if (updateUVs) { rcolResource.FixUVScales(mlod.Meshes[m]); } meshUVScales.Add(m, rcolResource.GetUVScales(mlod.Meshes[m])); } // Update the VBUFs for each mesh group and set the mesh bounds whilst we're here foreach (var key in meshGroups.Keys) { foreach (int m in meshGroups[key]) { VBUF vbuf = GenericRCOLResource.ChunkReference.GetBlock(rcolResource, mlod.Meshes[m].VertexBufferIndex) as VBUF; if (vbuf == null) { vbuf = new VBUF(rcolResource.RequestedApiVersion, null) { Version = 0x00000101, Flags = VBUF.FormatFlags.None, SwizzleInfo = new GenericRCOLResource.ChunkReference(0, null, 0), } } ; offScales.AddRange(getOffScales(m, -1, lmverts[m], meshUVScales[m])); vbuf.SetVertices(mlod, m, meshVRTF[m], lmverts[m], meshUVScales[m]); if (llverts[m] != null) { for (int g = 0; g < llverts[m].Count; g++) { if (llverts[m][g] != null) { offScales.AddRange(getOffScales(m, g, llverts[m][g], meshUVScales[m])); vbuf.SetVertices(mlod, mlod.Meshes[m], g, meshVRTF[m], llverts[m][g], meshUVScales[m]); } } } IResourceKey vbufRK = GenericRCOLResource.ChunkReference.GetKey(rcolResource, mlod.Meshes[m].VertexBufferIndex); if (vbufRK == null)//means we created the VBUF: create a RK and add it { vbufRK = new TGIBlock(0, null, defaultRK) { ResourceType = vbuf.ResourceType, } } ; rcolResource.ReplaceChunk(mlod.Meshes[m], "VertexBufferIndex", vbufRK, vbuf); if (updateBBs) { mlod.Meshes[m].Bounds = vbuf.GetBoundingBox(mlod.Meshes[m], meshVRTF[m]); } } } return(offScales); }
public StateMachine(GenericRCOLResource jazzResource) : this("") { if (jazzResource == null) { throw new ArgumentNullException("jazzResource"); } GenericRCOLResource.ChunkEntryList chunkEntries = jazzResource.ChunkEntries; if (chunkEntries == null || chunkEntries.Count == 0) { throw new ArgumentException( "RCOL Resource is empty", "jazzResource"); } KeyNameReg.RefreshKeyNameMaps(); uint hash; string name; int i, j, index = -1; State state; ActorDefinition ad; ParamDefinition pd; DecisionGraphNode dgn; JazzStateMachine jazzSM = null; GenericRCOLResource.ChunkEntry ce; AChunkObject[] chunks = new AChunkObject[chunkEntries.Count]; List<ActorDefinition> actorDefs = new List<ActorDefinition>(); List<ParamDefinition> paramDefs = new List<ParamDefinition>(); #region Phase 1: Instantiate Chunks and Copy over value fields for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; hash = ce.TGIBlock.ResourceType; switch (hash) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = new PlayAnimationNode(); lan.ClipKey = new RK(jpan.ClipResource); lan.TrackMaskKey = new RK(jpan.TkmkResource); // lan.SlotSetup copied over later lan.AdditiveClipKey = new RK(jpan.AdditiveClipResource); lan.ClipPattern = jpan.Animation; lan.AdditiveClipPattern = jpan.AdditiveAnimation; lan.Flags = jpan.AnimationNodeFlags; lan.Priority = jpan.AnimationPriority1; lan.BlendInTime = jpan.BlendInTime; lan.BlendOutTime = jpan.BlendOutTime; lan.Speed = jpan.Speed; // lan.Actor set later lan.TimingPriority = jpan.TimingPriority; chunks[i] = lan; break; case StopAnimationNode.ResourceType: JazzStopAnimationNode jsan = ce.RCOLBlock as JazzStopAnimationNode; StopAnimationNode san = new StopAnimationNode(); san.Flags = jsan.AnimationFlags; san.Priority = jsan.AnimationPriority1; san.BlendInTime = jsan.BlendInTime; san.BlendOutTime = jsan.BlendOutTime; san.Speed = jsan.Speed; // san.Actor set later san.TimingPriority = jsan.TimingPriority; chunks[i] = san; break; case ActorOperationNode.ResourceType: JazzActorOperationNode jaon = ce.RCOLBlock as JazzActorOperationNode; ActorOperationNode aon = new ActorOperationNode(jaon.ActorOp); // aon.Target set later aon.Operand = jaon.Operand != 0; chunks[i] = aon; break; case CreatePropNode.ResourceType: JazzCreatePropNode jcpn = ce.RCOLBlock as JazzCreatePropNode; CreatePropNode cpn = new CreatePropNode(); // cpn.PropActor set later // cpn.PropParameter set later cpn.PropKey = new RK(jcpn.PropResource); chunks[i] = cpn; break; case RandomNode.ResourceType: JazzRandomNode jrand = ce.RCOLBlock as JazzRandomNode; RandomNode rand = new RandomNode(); // rand.Slices set later rand.Flags = jrand.Properties; chunks[i] = rand; break; case SelectOnParameterNode.ResourceType: // sopn.Parameter set later // sopn.Cases set later chunks[i] = new SelectOnParameterNode(); break; case SelectOnDestinationNode.ResourceType: // sodn.Cases set later chunks[i] = new SelectOnDestinationNode(); break; case NextStateNode.ResourceType: // nsn.NextState set later chunks[i] = new NextStateNode(); break; case DecisionGraph.ResourceType: // dg.State set later // dg.DecisionMakers set later // dg.EntryPoints set later chunks[i] = new DecisionGraph(); break; case State.ResourceType: JazzState js = ce.RCOLBlock as JazzState; hash = js.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); state = new State(name); state.Flags = js.Properties; // state.DecisionGraph set later // state.Transitions set later state.AwarenessOverlayLevel = js.AwarenessOverlayLevel; chunks[i] = state; break; case ParamDefinition.ResourceType: JazzParameterDefinition jpd = ce.RCOLBlock as JazzParameterDefinition; hash = jpd.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd = new ParamDefinition(name); hash = jpd.DefaultValue; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd.DefaultValue = name; chunks[i] = pd; paramDefs.Add(pd); break; case ActorDefinition.ResourceType: JazzActorDefinition jad = ce.RCOLBlock as JazzActorDefinition; hash = jad.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); chunks[i] = ad; actorDefs.Add(ad); break; case StateMachine.ResourceType: if (index != -1) { throw new Exception( "More than one State Machine in RCOL"); } index = i; jazzSM = ce.RCOLBlock as JazzStateMachine; hash = jazzSM.NameHash; if (hash == 0) { name = null; this.bNameIsHash = true; } else if (!KeyNameReg.TryFindName(hash, out name)) { name = KeyNameReg.UnhashName(hash); this.bNameIsHash = true; } else { this.bNameIsHash = false; } this.mName = name; this.mNameHash = hash; // this.mActorDefinitions set later // this.mParameterDefinitions set later // this.mStates set later this.mFlags = jazzSM.Properties; this.mDefaultPriority = jazzSM.AutomationPriority; this.mAwarenessOverlayLevel = jazzSM.AwarenessOverlayLevel; chunks[i] = this; break; } } if (index == -1) { throw new Exception("RCOL does not contain a Jazz Graph"); } #endregion #region Phase 2: Copy over fields referencing other chunks for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; switch (ce.TGIBlock.ResourceType) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = chunks[i] as PlayAnimationNode; index = jpan.ActorDefinitionIndex.TGIBlockIndex; lan.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case StopAnimationNode.ResourceType: JazzStopAnimationNode jsan = ce.RCOLBlock as JazzStopAnimationNode; StopAnimationNode san = chunks[i] as StopAnimationNode; index = jsan.ActorDefinitionIndex.TGIBlockIndex; san.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case ActorOperationNode.ResourceType: JazzActorOperationNode jaon = ce.RCOLBlock as JazzActorOperationNode; ActorOperationNode aon = chunks[i] as ActorOperationNode; index = jaon.ActorDefinitionIndex.TGIBlockIndex; aon.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case CreatePropNode.ResourceType: JazzCreatePropNode jcpn = ce.RCOLBlock as JazzCreatePropNode; CreatePropNode cpn = chunks[i] as CreatePropNode; index = jcpn.ActorDefinitionIndex.TGIBlockIndex; cpn.PropActor = index < 0 ? null : chunks[index + 1] as ActorDefinition; index = jcpn.ParameterDefinitionIndex.TGIBlockIndex; cpn.PropParam = index < 0 ? null : chunks[index + 1] as ParamDefinition; break; case RandomNode.ResourceType: JazzRandomNode jrand = ce.RCOLBlock as JazzRandomNode; RandomNode rand = chunks[i] as RandomNode; RandomNode.Slice slice; List<RandomNode.Slice> slices = rand.Slices; foreach (JazzRandomNode.Outcome oc in jrand.Outcomes) { slice = new RandomNode.Slice(oc.Weight); foreach (GenericRCOLResource.ChunkReference cr in oc.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; slice.Targets.Add(dgn); } slices.Add(slice); } break; case SelectOnParameterNode.ResourceType: JazzSelectOnParameterNode jsopn = ce.RCOLBlock as JazzSelectOnParameterNode; SelectOnParameterNode sopn = chunks[i] as SelectOnParameterNode; index = jsopn.ParameterDefinitionIndex.TGIBlockIndex; sopn.Parameter = index < 0 ? null : chunks[index + 1] as ParamDefinition; foreach (JazzSelectOnParameterNode.Match mp in jsopn.Matches) { hash = mp.TestValue; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); foreach (GenericRCOLResource.ChunkReference cr in mp.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; sopn.AddCaseTarget(name, dgn); } } break; case SelectOnDestinationNode.ResourceType: JazzSelectOnDestinationNode jsodn = ce.RCOLBlock as JazzSelectOnDestinationNode; SelectOnDestinationNode sodn = chunks[i] as SelectOnDestinationNode; foreach (JazzSelectOnDestinationNode.Match md in jsodn.Matches) { index = md.StateIndex.TGIBlockIndex; state = index < 0 ? null : chunks[index + 1] as State; foreach (GenericRCOLResource.ChunkReference cr in md.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; sodn.AddCaseTarget(state, dgn); } } break; case NextStateNode.ResourceType: JazzNextStateNode jnsn = ce.RCOLBlock as JazzNextStateNode; NextStateNode nsn = chunks[i] as NextStateNode; index = jnsn.StateIndex.TGIBlockIndex; nsn.NextState = index < 0 ? null : chunks[index + 1] as State; break; case DecisionGraph.ResourceType: JazzDecisionGraph jdg = ce.RCOLBlock as JazzDecisionGraph; DecisionGraph dg = chunks[i] as DecisionGraph; foreach (GenericRCOLResource.ChunkReference dm in jdg.OutboundDecisionGraphIndexes) { index = dm.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; dg.AddDecisionMaker(dgn); } foreach (GenericRCOLResource.ChunkReference ep in jdg.InboundDecisionGraphIndexes) { index = ep.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; dg.AddEntryPoint(dgn); } break; case State.ResourceType: State transition; JazzState js = ce.RCOLBlock as JazzState; state = chunks[i] as State; index = js.DecisionGraphIndex.TGIBlockIndex; state.DecisionGraph = index < 0 ? null : chunks[index + 1] as DecisionGraph; foreach (GenericRCOLResource.ChunkReference trans in js.OutboundStateIndexes) { index = trans.TGIBlockIndex; transition = index < 0 ? null : chunks[index + 1] as State; state.AddTransition(transition); } break; case ParamDefinition.ResourceType: case ActorDefinition.ResourceType: break; case StateMachine.ResourceType: jazzSM = ce.RCOLBlock as JazzStateMachine; foreach (GenericRCOLResource.ChunkReference jad in jazzSM.ActorDefinitionIndexes) { index = jad.TGIBlockIndex; ad = index < 0 ? null : chunks[index + 1] as ActorDefinition; this.AddActorDefinition(ad); } foreach (GenericRCOLResource.ChunkReference jpd in jazzSM.PropertyDefinitionIndexes) { index = jpd.TGIBlockIndex; pd = index < 0 ? null : chunks[index + 1] as ParamDefinition; this.AddParamDefinition(pd); } foreach (GenericRCOLResource.ChunkReference jst in jazzSM.StateIndexes) { index = jst.TGIBlockIndex; state = index < 0 ? null : chunks[index + 1] as State; this.AddState(state); } break; } } #endregion #region Phase 3: Copy over animation slots and Find "Extras" for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; switch (ce.TGIBlock.ResourceType) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = chunks[i] as PlayAnimationNode; SlotSetupBuilder ssb = lan.SlotSetup; foreach (JazzPlayAnimationNode.ActorSlot slot in jpan.ActorSlots) { ssb.AddSlotAssignment(slot.ChainId, slot.SlotId, slot.ActorNameHash, slot.SlotNameHash); } foreach (JazzPlayAnimationNode.ActorSuffix suffix in jpan.ActorSuffixes) { hash = suffix.ActorNameHash; ad = null; if (hash != 0) { index = -1; for (i = actorDefs.Count - 1; i >= 0 && index == -1; i--) { ad = actorDefs[i]; if (ad.NameHash == hash) { index = i; } } if (index < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); actorDefs.Add(ad); this.mExtraActors.Add(ad); } } hash = suffix.SuffixHash; pd = null; if (hash != 0) { index = -1; for (i = paramDefs.Count - 1; i >= 0 && index == -1; i--) { pd = paramDefs[i]; if (pd.NameHash == hash) { index = i; } } if (index < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd = new ParamDefinition(name); paramDefs.Add(pd); this.mExtraParams.Add(pd); } } ssb.AddNamespaceSlotSuffix(ad, pd); } break; case State.ResourceType: state = chunks[i] as State; index = this.mStates.IndexOf(state); if (index < 0) { this.mExtraStates.Add(state); } break; case ParamDefinition.ResourceType: pd = chunks[i] as ParamDefinition; index = this.mParamDefinitions.IndexOf(pd); if (index < 0) { this.mExtraParams.Add(pd); } break; case ActorDefinition.ResourceType: ad = chunks[i] as ActorDefinition; index = this.mActorDefinitions.IndexOf(ad); if (index < 0) { this.mExtraActors.Add(ad); } break; } } #endregion #region Phase 4: Copy over Animation CLIP Namespace Map RK rk; List<RK> rks = this.SlurpReferencedRKs(); List<uint> foldedClipInstances = new List<uint>(rks.Count); for (i = rks.Count - 1; i >= 0; i--) { rk = rks[i]; if (rk.TID == 0x6b20c4f3) { hash = (uint)((rk.IID >> 0x20) ^ (rk.IID & 0xffffffff)); foldedClipInstances.Add(hash); } else { rks.RemoveAt(i); } } index = 0; Anim animation; Anim[] animations = new Anim[jazzSM.Animations.Count]; foreach (JazzStateMachine.Animation anim in jazzSM.Animations) { hash = anim.NameHash; if (!foldedClipInstances.Contains(hash)) { animation = new Anim(); animation.SrcFileHash = hash; if (KeyNameReg.TryFindName(hash, out name)) { animation.SrcFileName = name; animation.SrcFileIsValid = true; } else { animation.SrcFileName = KeyNameReg.UnhashName(hash); animation.SrcFileIsValid = false; } hash = anim.Actor1Hash; if (KeyNameReg.TryFindName(hash, out name)) { animation.Namespace = name; } else { animation.Namespace = string.Concat("0x", hash.ToString("X8")); } hash = anim.Actor2Hash; ad = null; if (hash != 0) { j = -1; for (i = actorDefs.Count - 1; i >= 0 && j < 0; i--) { ad = actorDefs[i]; if (ad.NameHash == hash) { j = i; } } if (j < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); actorDefs.Add(ad); this.mExtraActors.Add(ad); } } animation.Actor = ad; animations[index++] = animation; } } ulong clipHash; Dictionary<ulong, string> keyNameMap = new Dictionary<ulong, string>(); for (i = index - 1; i >= 0; i--) { animation = animations[i]; this.mNamespaceMap.SetNamespaceMap( animation.SrcFileName, animation.Namespace, animation.Actor); if (animation.SrcFileIsValid) { clipHash = FNVHash.HashString64(animation.SrcFileName); keyNameMap[clipHash] = animation.SrcFileName; } } // Update the Key to Filename Map of the Namespace Map SortedDictionary<RK, string> k2fn = this.mNamespaceMap.KeyToFilenameMap; k2fn.Clear(); for (i = rks.Count - 1; i >= 0; i--) { rk = rks[i]; if (keyNameMap.TryGetValue(rk.IID, out name) || KeyNameReg.TryFindName(rk.IID, out name)) { k2fn[rk] = name; } } #endregion }