public void AddObjectToDictionary(SerializableDOMNode actor, Dictionary <FourCC, List <SerializableDOMNode> > actorCategories) { string rawFourCC = FourCCConversion.GetStringFromEnum(actor.FourCC); string fixedFourCC = ChunkHeader.LayerToFourCC(rawFourCC, actor.Layer); FourCC fixedFourCCEnum = FourCCConversion.GetEnumFromString(fixedFourCC); if (!actorCategories.ContainsKey(fixedFourCCEnum)) { actorCategories[fixedFourCCEnum] = new List <SerializableDOMNode>(); } actorCategories[fixedFourCCEnum].Add(actor); }
public SceneDataLoader(string fileName, WWorld world) { m_world = world; m_reader = new EndianBinaryReader(File.ReadAllBytes(fileName), System.Text.Encoding.ASCII, Endian.Big); m_chunkList = new List <ChunkHeader>(); int chunkCount = m_reader.ReadInt32(); for (int i = 0; i < chunkCount; i++) { string fourCC = m_reader.ReadString(4); MapLayer layer = ChunkHeader.FourCCToLayer(ref fourCC); FourCC enumFourCC = FourCCConversion.GetEnumFromString(fourCC); ChunkHeader chunk = new ChunkHeader(enumFourCC, m_reader.ReadInt32(), m_reader.ReadInt32()); chunk.Layer = layer; m_chunkList.Add(chunk); } var sortedList = m_chunkList.OrderBy(x => x.ChunkOffset); m_chunkList = new List <ChunkHeader>(sortedList); }
public WScene(WWorld world) : base(world) { m_fourCCGroups = new Dictionary <FourCC, WDOMNode>(); // We're going to iterate through the enum values to create DOM nodes for them. // We're skipping all of the actors, scaleable objects, and treasure chests though, because they're special. foreach (FourCC f in Enum.GetValues(typeof(FourCC))) { // Skip Actors/Scaleable Objects/Treasure Chests if (f.ToString().Contains("ACT") || f.ToString().Contains("SCO") || f.ToString().Contains("TRE") || f == FourCC.NONE) { continue; } if (!m_fourCCLocations.ContainsKey(f) || this is WStage && m_fourCCLocations[f] == SourceScene.Stage || this is WRoom && m_fourCCLocations[f] == SourceScene.Room) { m_fourCCGroups[f] = new WDOMGroupNode(f, m_world); } } // To handle the fact that actors/scaleable/treasure chests have layers, we're going to create DOM nodes using // the default layer's FourCC (ACTR/SCOB/TRES). This DOM node won't interact directly with the entities, rather // it will be the parent node of the nodes that do. WDOMGroupNode.ToString() is overridden to return a more general // description of them ("ACTR (Actors)", etc) instead of the FourCC's FourCCConversion.GetDescriptionFromEnum() value. m_fourCCGroups[FourCC.ACTR] = new WDOMGroupNode(FourCC.ACTR, m_world); m_fourCCGroups[FourCC.SCOB] = new WDOMGroupNode(FourCC.SCOB, m_world); m_fourCCGroups[FourCC.TRES] = new WDOMGroupNode(FourCC.TRES, m_world); // Now we add the default layer for each object type. WDOMLayeredGroupNode directly interacts with the entities. WDOMLayeredGroupNode actrDefLayer = new WDOMLayeredGroupNode(FourCC.ACTR, MapLayer.Default, m_world); actrDefLayer.SetParent(m_fourCCGroups[FourCC.ACTR]); WDOMLayeredGroupNode scobDefLayer = new WDOMLayeredGroupNode(FourCC.SCOB, MapLayer.Default, m_world); scobDefLayer.SetParent(m_fourCCGroups[FourCC.SCOB]); WDOMLayeredGroupNode tresDefLayer = new WDOMLayeredGroupNode(FourCC.TRES, MapLayer.Default, m_world); tresDefLayer.SetParent(m_fourCCGroups[FourCC.TRES]); // Now we add layers 0 to 11 for each object type. // Note that we do (i + 1) for the MapLayer cast in order to skip the Default enum value. for (int i = 0; i < 12; i++) { WDOMLayeredGroupNode actrLayer = new WDOMLayeredGroupNode(FourCCConversion.GetEnumFromString($"ACT{ i.ToString("x") }"), (MapLayer)i + 1, m_world); actrLayer.SetParent(m_fourCCGroups[FourCC.ACTR]); WDOMLayeredGroupNode scobLayer = new WDOMLayeredGroupNode(FourCCConversion.GetEnumFromString($"SCO{ i.ToString("x") }"), (MapLayer)i + 1, m_world); scobLayer.SetParent(m_fourCCGroups[FourCC.SCOB]); WDOMLayeredGroupNode tresLayer = new WDOMLayeredGroupNode(FourCCConversion.GetEnumFromString($"TRE{ i.ToString("x") }"), (MapLayer)i + 1, m_world); tresLayer.SetParent(m_fourCCGroups[FourCC.TRES]); } /*m_fourCCGroups["ACTR (Actors)"] = new WDOMGroupNode("ACTR (Actors)", m_world); * WDOMGroupNode actrDefault = new WDOMGroupNode("ACTR", m_world); * actrDefault.SetParent(m_fourCCGroups["ACTR (Actors)"]); * * m_fourCCGroups["SCOB (Scaleable Objects)"] = new WDOMGroupNode("SCOB (Scaleable Objects)", m_world); * WDOMGroupNode scobDefault = new WDOMGroupNode("SCOB", m_world); * scobDefault.SetParent(m_fourCCGroups["SCOB (Scaleable Objects)"]); * * m_fourCCGroups["TRES (Treasure Chests)"] = new WDOMGroupNode("TRES (Treasure Chests)", m_world); * WDOMGroupNode tresDefault = new WDOMGroupNode("TRES", m_world); * tresDefault.SetParent(m_fourCCGroups["TRES (Treasure Chests)"]); * * for (int i = 0; i < 12; i++) * { * WDOMGroupNode actX = new WDOMGroupNode($"ACT{ i.ToString("x") }", m_world); * actX.SetParent(m_fourCCGroups["ACTR (Actors)"]); * * WDOMGroupNode scoX = new WDOMGroupNode($"SCO{ i.ToString("x") }", m_world); * scoX.SetParent(m_fourCCGroups["SCOB (Scaleable Objects)"]); * * WDOMGroupNode treX = new WDOMGroupNode($"TRE{ i.ToString("x") }", m_world); * treX.SetParent(m_fourCCGroups["TRES (Treasure Chests)"]); * }*/ }
public void CreateEntity() { if (!EditorSelection.SingleObjectSelected) { return; } WDOMNode selected = EditorSelection.PrimarySelectedObject; SerializableDOMNode newNode = null; if (selected is SerializableDOMNode) { SerializableDOMNode origNode = selected as SerializableDOMNode; Type selType = selected.GetType(); newNode = (SerializableDOMNode)Activator.CreateInstance(selType, origNode.FourCC, m_world); newNode.PostLoad(); newNode.SetParent(selected.Parent); if (origNode.Parent is WDOMLayeredGroupNode) { newNode.Layer = origNode.Layer; } } else if (selected is WDOMLayeredGroupNode) { WDOMLayeredGroupNode lyrNode = selected as WDOMLayeredGroupNode; Type newObjType = null; if (lyrNode.FourCC >= FourCC.ACTR && lyrNode.FourCC <= FourCC.ACTb) { newObjType = typeof(Actor); } else if (lyrNode.FourCC >= FourCC.SCOB && lyrNode.FourCC <= FourCC.SCOb) { newObjType = typeof(ScaleableObject); } else if (lyrNode.FourCC >= FourCC.TRES && lyrNode.FourCC <= FourCC.TREb) { newObjType = typeof(TreasureChest); } string unlayedFourCC = lyrNode.FourCC.ToString(); MapLayer layer = ChunkHeader.FourCCToLayer(ref unlayedFourCC); FourCC enumVal = FourCCConversion.GetEnumFromString(unlayedFourCC); newNode = (SerializableDOMNode)Activator.CreateInstance(newObjType, enumVal, m_world); newNode.Layer = layer; newNode.PostLoad(); newNode.SetParent(lyrNode); } else if (selected is WDOMGroupNode) { WDOMGroupNode grpNode = selected as WDOMGroupNode; if (grpNode.FourCC == FourCC.ACTR || grpNode.FourCC == FourCC.SCOB || grpNode.FourCC == FourCC.TRES) { return; } Type newObjType = FourCCConversion.GetTypeFromEnum(grpNode.FourCC); newNode = (SerializableDOMNode)Activator.CreateInstance(newObjType, grpNode.FourCC, m_world); newNode.PostLoad(); newNode.SetParent(grpNode); } else { return; } if (newNode != null) { EditorSelection.ClearSelection(); EditorSelection.AddToSelection(newNode); } // ToDo: This can spawn specific classes the same way that the actor loader does. }
public void ExportToStream(EndianBinaryWriter writer, WScene scene) { // Build a dictionary which lists unique FourCC's and a list of all relevant actors. var actorCategories = new Dictionary <FourCC, List <SerializableDOMNode> >(); foreach (var child in scene) { var groupNode = child as WDOMGroupNode; if (groupNode == null) { continue; } // If this is an ACTR, SCOB, or TRES group node, we have to dig into it to get the layers. if (groupNode.FourCC == FourCC.ACTR || groupNode.FourCC == FourCC.SCOB || groupNode.FourCC == FourCC.TRES) { foreach (var layer in groupNode.Children) { foreach (var obj in layer.Children) { var actor = obj as SerializableDOMNode; if (actor != null) { AddObjectToDictionary(actor, actorCategories); } } } } else { foreach (var obj in groupNode.Children) { var actor = obj as SerializableDOMNode; if (actor != null) { AddObjectToDictionary(actor, actorCategories); } } } } // Create a chunk header for each one. var chunkHeaders = new List <ChunkHeader>(); foreach (var kvp in actorCategories) { ChunkHeader header = new ChunkHeader(); header.FourCC = kvp.Key; header.ElementCount = kvp.Value.Count; chunkHeaders.Add(header); } long chunkStart = writer.BaseStream.Position; // Write the Header writer.Write(chunkHeaders.Count); for (int i = 0; i < chunkHeaders.Count; i++) { writer.Write((int)0); // Dummy Placeholder values for the Chunk Header. writer.Write((int)0); writer.Write((int)0); } // For each chunk, write the data for that chunk. Before writing the data, get the current offset and update the header. List <SerializableDOMNode>[] dictionaryData = new List <SerializableDOMNode> [actorCategories.Count]; actorCategories.Values.CopyTo(dictionaryData, 0); for (int i = 0; i < chunkHeaders.Count; i++) { ChunkHeader header = chunkHeaders[i]; chunkHeaders[i] = new ChunkHeader(header.FourCC, header.ElementCount, (int)(writer.BaseStream.Position - chunkStart)); List <SerializableDOMNode> actors = dictionaryData[i]; foreach (var actor in actors) { MapActorDescriptor template = Globals.ActorDescriptors.Find(x => x.FourCC == actor.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC (\"{0}\") for exporting!", actor.FourCC); continue; } actor.PreSave(); actor.Save(writer); //WriteActorToChunk(actor, template, writer); } } // Now that we've written every actor to file we can go back and re-write the headers now that we know their offsets. writer.BaseStream.Position = chunkStart + 0x4; // 0x4 is the offset to the Chunk Headers foreach (var header in chunkHeaders) { writer.WriteFixedString(FourCCConversion.GetStringFromEnum(header.FourCC), 4); // FourCC writer.Write(header.ElementCount); // Number of Entries writer.Write(header.ChunkOffset); // Offset from start of file. } // Seek to the end of the file, and then pad us to 32-byte alignment. writer.BaseStream.Seek(0, SeekOrigin.End); int delta = WMath.Pad32Delta(writer.BaseStream.Position); for (int i = 0; i < delta; i++) { writer.Write(0xFF); } }