public SceneDataLoader(string fileName, WWorld world) { m_world = world; if (m_sActorDescriptors == null) { // Load the Actor Descriptors from disk. m_sActorDescriptors = new List <MapActorDescriptor>(); foreach (var file in Directory.GetFiles("resources/templates/")) { MapActorDescriptor descriptor = JsonConvert.DeserializeObject <MapActorDescriptor>(File.ReadAllText(file)); m_sActorDescriptors.Add(descriptor); } } 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); ChunkHeader chunk = new ChunkHeader(fourCC, 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 List <WActorNode> GetMapEntities() { var loadedActors = new List <WActorNode>(); foreach (var chunk in m_chunkList) { m_reader.BaseStream.Position = chunk.ChunkOffset; MapActorDescriptor template = m_sActorDescriptors.Find(x => x.FourCC == chunk.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC: {0}", chunk.FourCC); continue; } switch (chunk.FourCC) { // Don't turn these into map actors, as they will be handled elsewhere. //case "RTBL": case "MECO": case "MEMA": break; default: for (int i = 0; i < chunk.ElementCount; i++) { var newActor = LoadActorFromChunk(chunk.FourCC, template); newActor.Layer = chunk.Layer; loadedActors.Add(newActor); } break; } } var dict = new Dictionary <string, List <WActorNode> >(); foreach (var actor in loadedActors) { if (!dict.ContainsKey(actor.FourCC)) { dict[actor.FourCC] = new List <WActorNode>(); } dict[actor.FourCC].Add(actor); } string[] nodes = new[] { "EnvR", "Pale", "Virt", "Colo" }; foreach (var node in nodes) { if (dict.ContainsKey(node)) { Console.WriteLine("{0} Count: {1}", node, dict[node].Count); } } return(loadedActors); }
public List <WDOMNode> GetMapEntities() { var loadedActors = new List <WDOMNode>(); foreach (var chunk in m_chunkList) { m_reader.BaseStream.Position = chunk.ChunkOffset; MapActorDescriptor template = Globals.ActorDescriptors.Find(x => x.FourCC == chunk.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC: {0}", chunk.FourCC); continue; } switch (chunk.FourCC) { // Don't turn these into map actors, as they will be handled elsewhere. //case "RTBL": case FourCC.MECO: case FourCC.MEMA: break; default: for (int i = 0; i < chunk.ElementCount; i++) { Type actorType = Type.GetType($"WindEditor.{template.ClassName}"); SerializableDOMNode entity = (SerializableDOMNode)Activator.CreateInstance(actorType, chunk.FourCC, m_world); entity.Load(m_reader); entity.PostLoad(); entity.Layer = chunk.Layer; loadedActors.Add(entity); } break; } } // var dict = new Dictionary<string, List<WDOMNode>>(); // foreach(var actor in loadedActors) // { // if (!dict.ContainsKey(actor.FourCC)) // dict[actor.FourCC] = new List<WDOMNode>(); // dict[actor.FourCC].Add(actor); // } // // string[] nodes = new[] { "EnvR", "Pale", "Virt", "Colo" }; // foreach(var node in nodes) // { // if (dict.ContainsKey(node)) // Console.WriteLine("{0} Count: {1}", node, dict[node].Count); // // } return(loadedActors); }
public WWindEditor() { // Add the default Editor World. m_editorWorlds.Add(new WWorld()); // Load our global data foreach (var file in Directory.GetFiles("resources/templates/")) { MapActorDescriptor descriptor = JsonConvert.DeserializeObject <MapActorDescriptor>(File.ReadAllText(file)); Globals.ActorDescriptors.Add(descriptor); } }
public SceneDataExporter() { if (m_sActorDescriptors == null) { // Load the Actor Descriptors from disk. m_sActorDescriptors = new List <MapActorDescriptor>(); foreach (var file in Directory.GetFiles("resources/templates/")) { MapActorDescriptor descriptor = JsonConvert.DeserializeObject <MapActorDescriptor>(File.ReadAllText(file)); m_sActorDescriptors.Add(descriptor); } } }
public List <WDOMNode> GetMapEntities() { var loadedActors = new List <WDOMNode>(); foreach (var chunk in m_chunkList) { m_reader.BaseStream.Position = chunk.ChunkOffset; MapActorDescriptor template = Globals.ActorDescriptors.Find(x => x.FourCC == chunk.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC: {0}", chunk.FourCC); continue; } switch (chunk.FourCC) { // Don't turn these into map actors, as they will be handled elsewhere. //case "RTBL": case FourCC.MECO: case FourCC.MEMA: break; case FourCC.SCOB: case FourCC.SCO0: case FourCC.SCO1: case FourCC.SCO2: case FourCC.SCO3: case FourCC.SCO4: case FourCC.SCO5: case FourCC.SCO6: case FourCC.SCO7: case FourCC.SCO8: case FourCC.SCO9: case FourCC.SCOa: case FourCC.SCOb: case FourCC.TGSC: for (int i = 0; i < chunk.ElementCount; i++) { // We need to read the entity name so we can load the right derived class for it string entity_name = Encoding.ASCII.GetString(m_reader.PeekReadBytes(8)).Trim('\0'); Type actorType = WResourceManager.GetTypeByName(entity_name); SerializableDOMNode entity = (SerializableDOMNode)Activator.CreateInstance(actorType, chunk.FourCC, m_world); entity.Load(m_reader); entity.Layer = chunk.Layer; entity.Transform.LocalScale = new Vector3(m_reader.ReadByte() / 10f, m_reader.ReadByte() / 10f, m_reader.ReadByte() / 10f); int padding = m_reader.ReadByte(); loadedActors.Add(entity); } break; case FourCC.ACTR: case FourCC.ACT0: case FourCC.ACT1: case FourCC.ACT2: case FourCC.ACT3: case FourCC.ACT4: case FourCC.ACT5: case FourCC.ACT6: case FourCC.ACT7: case FourCC.ACT8: case FourCC.ACT9: case FourCC.ACTa: case FourCC.ACTb: case FourCC.TGOB: case FourCC.TGDR: for (int i = 0; i < chunk.ElementCount; i++) { // We need to read the entity name so we can load the right derived class for it string entity_name = Encoding.ASCII.GetString(m_reader.PeekReadBytes(8)).Trim('\0'); Type actorType = WResourceManager.GetTypeByName(entity_name); SerializableDOMNode entity = (SerializableDOMNode)Activator.CreateInstance(actorType, chunk.FourCC, m_world); entity.Load(m_reader); entity.Layer = chunk.Layer; loadedActors.Add(entity); } break; case FourCC.RTBL: for (int i = 0; i < chunk.ElementCount; i++) { int entry_offset = m_reader.ReadInt32(); int next_offset = (int)m_reader.BaseStream.Position; m_reader.BaseStream.Seek(entry_offset, SeekOrigin.Begin); RoomTableEntryNode rtbl_entry = new RoomTableEntryNode(chunk.FourCC, m_world, m_reader); loadedActors.Add(rtbl_entry); m_reader.BaseStream.Seek(next_offset, SeekOrigin.Begin); } break; default: for (int i = 0; i < chunk.ElementCount; i++) { Type actorType = Type.GetType($"WindEditor.{template.ClassName}"); SerializableDOMNode entity = (SerializableDOMNode)Activator.CreateInstance(actorType, chunk.FourCC, m_world); entity.Load(m_reader); entity.Layer = chunk.Layer; loadedActors.Add(entity); } break; } } // var dict = new Dictionary<string, List<WDOMNode>>(); // foreach(var actor in loadedActors) // { // if (!dict.ContainsKey(actor.FourCC)) // dict[actor.FourCC] = new List<WDOMNode>(); // dict[actor.FourCC].Add(actor); // } // // string[] nodes = new[] { "EnvR", "Pale", "Virt", "Colo" }; // foreach(var node in nodes) // { // if (dict.ContainsKey(node)) // Console.WriteLine("{0} Count: {1}", node, dict[node].Count); // // } AssignPaths(loadedActors); return(loadedActors); }
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 <string, List <WActorNode> >(); foreach (var child in scene) { WActorNode actor = child as WActorNode; if (actor != null) { string fixedFourCC = ChunkHeader.LayerToFourCC(actor.FourCC, actor.Layer); if (!actorCategories.ContainsKey(fixedFourCC)) { actorCategories[fixedFourCC] = new List <WActorNode>(); } actorCategories[fixedFourCC].Add(actor); } } // 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 <WActorNode>[] dictionaryData = new List <WActorNode> [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 <WActorNode> actors = dictionaryData[i]; foreach (var actor in actors) { MapActorDescriptor template = m_sActorDescriptors.Find(x => x.FourCC == actor.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC (\"{0}\") for exporting!", actor.FourCC); continue; } 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(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((byte)0xFF); } }
private void WriteActorToChunk(WActorNode actor, MapActorDescriptor template, EndianBinaryWriter writer) { // Just convert their rotation to Euler Angles now instead of doing it in parts later. Vector3 eulerRot = actor.Transform.Rotation.ToEulerAngles(); foreach (var field in template.Fields) { IPropertyValue propValue = actor.Properties.Find(x => x.Name == field.FieldName); if (field.FieldName == "Position") { propValue = new TVector3PropertyValue(actor.Transform.Position, "Position"); } else if (field.FieldName == "X Rotation") { short xRotShort = WMath.RotationFloatToShort(eulerRot.X); propValue = new TShortPropertyValue(xRotShort, "X Rotation"); } else if (field.FieldName == "Y Rotation") { short yRotShort = WMath.RotationFloatToShort(eulerRot.Y); propValue = new TShortPropertyValue(yRotShort, "Y Rotation"); } else if (field.FieldName == "Z Rotation") { short zRotShort = WMath.RotationFloatToShort(eulerRot.Z); propValue = new TShortPropertyValue(zRotShort, "Z Rotation"); } else if (field.FieldName == "X Scale") { float xScale = actor.Transform.LocalScale.X; propValue = new TBytePropertyValue((byte)(xScale * 10), "X Scale"); } else if (field.FieldName == "Y Scale") { float yScale = actor.Transform.LocalScale.Y; propValue = new TBytePropertyValue((byte)(yScale * 10), "Y Scale"); } else if (field.FieldName == "Z Scale") { float zScale = actor.Transform.LocalScale.Z; propValue = new TBytePropertyValue((byte)(zScale * 10), "Z Scale"); } switch (field.FieldType) { case PropertyValueType.Byte: writer.Write((byte)propValue.GetValue()); break; case PropertyValueType.Bool: writer.Write((bool)propValue.GetValue()); break; case PropertyValueType.Short: writer.Write((short)propValue.GetValue()); break; case PropertyValueType.Int: writer.Write((int)propValue.GetValue()); break; case PropertyValueType.Float: writer.Write((float)propValue.GetValue()); break; case PropertyValueType.String: writer.Write(System.Text.Encoding.ASCII.GetBytes((string)propValue.GetValue())); break; case PropertyValueType.FixedLengthString: string fixedLenStr = (string)propValue.GetValue(); for (int i = 0; i < field.Length; i++) { writer.Write(i < fixedLenStr.Length ? (byte)fixedLenStr[i] : (byte)0); } //writer.WriteFixedString((string)propValue.GetValue(), (int)field.Length); break; break; case PropertyValueType.Vector2: Vector2 vec2Val = (Vector2)propValue.GetValue(); writer.Write(vec2Val.X); writer.Write(vec2Val.Y); break; case PropertyValueType.Vector3: Vector3 vec3Val = (Vector3)propValue.GetValue(); writer.Write(vec3Val.X); writer.Write(vec3Val.Y); writer.Write(vec3Val.Z); break; case PropertyValueType.XRotation: case PropertyValueType.YRotation: case PropertyValueType.ZRotation: writer.Write((short)propValue.GetValue()); break; case PropertyValueType.Color24: WLinearColor color24 = (WLinearColor)propValue.GetValue(); writer.Write((byte)color24.R); writer.Write((byte)color24.G); writer.Write((byte)color24.B); break; case PropertyValueType.Color32: WLinearColor color32 = (WLinearColor)propValue.GetValue(); writer.Write((byte)color32.R); writer.Write((byte)color32.G); writer.Write((byte)color32.B); writer.Write((byte)color32.A); break; default: Console.WriteLine("Unsupported PropertyValueType: {0}", field.FieldType); break; } } }
public void CreateEntity(string fourCC) { if (m_world.Map == null || m_world.Map.FocusedScene == null) { return; } var actorDescriptors = new List <MapActorDescriptor>(); foreach (var file in Directory.GetFiles("resources/templates/")) { MapActorDescriptor descriptor = JsonConvert.DeserializeObject <MapActorDescriptor>(File.ReadAllText(file)); actorDescriptors.Add(descriptor); } MapActorDescriptor entityDescriptor = actorDescriptors.Find(x => string.Compare(x.FourCC, fourCC, true) == 0); if (entityDescriptor == null) { Console.WriteLine("Attempted to spawn unsupported FourCC: {0}", fourCC); return; } List <IPropertyValue> actorProperties = new List <IPropertyValue>(); foreach (var field in entityDescriptor.Fields) { switch (field.FieldName) { case "Position": case "X Rotation": case "Y Rotation": case "Z Rotation": case "X Scale": case "Y Scale": case "Z Scale": continue; } IPropertyValue propValue = null; switch (field.FieldType) { case PropertyValueType.Byte: propValue = new TBytePropertyValue(0, field.FieldName); break; case PropertyValueType.Bool: propValue = new TBoolPropertyValue(false, field.FieldName); break; case PropertyValueType.Short: propValue = new TShortPropertyValue(0, field.FieldName); break; case PropertyValueType.Int: propValue = new TIntPropertyValue(0, field.FieldName); break; case PropertyValueType.Float: propValue = new TFloatPropertyValue(0f, field.FieldName); break; case PropertyValueType.FixedLengthString: case PropertyValueType.String: propValue = new TStringPropertyValue("", field.FieldName); break; case PropertyValueType.Vector2: propValue = new TVector2PropertyValue(new OpenTK.Vector2(0f, 0f), field.FieldName); break; case PropertyValueType.Vector3: propValue = new TVector3PropertyValue(new OpenTK.Vector3(0f, 0f, 0f), field.FieldName); break; case PropertyValueType.XRotation: case PropertyValueType.YRotation: case PropertyValueType.ZRotation: propValue = new TShortPropertyValue(0, field.FieldName); break; case PropertyValueType.Color24: propValue = new TLinearColorPropertyValue(new WLinearColor(1f, 1f, 1f), field.FieldName); break; case PropertyValueType.Color32: propValue = new TLinearColorPropertyValue(new WLinearColor(1f, 1f, 1f, 1f), field.FieldName); break; default: Console.WriteLine("Unsupported PropertyValueType: {0}", field.FieldType); break; } propValue.SetUndoStack(m_world.UndoStack); actorProperties.Add(propValue); } var newActor = new WActorNode(fourCC, m_world); newActor.Transform.Position = new OpenTK.Vector3(0, 200, 0); newActor.SetParent(m_world.Map.FocusedScene); newActor.Properties.AddRange(actorProperties); newActor.PostFinishedLoad(); ModifySelection(SelectionType.Add, newActor, true); }
public static Type GetTypeFromEnum(FourCC value) { MapActorDescriptor template = Globals.ActorDescriptors.Find(x => x.FourCC == value); return(Type.GetType($"WindEditor.{template.ClassName}")); }
public List <EnvironmentLighting> GetLightingData() { // Bah... var loadedActors = new List <WActorNode>(); foreach (var chunk in m_chunkList) { m_reader.BaseStream.Position = chunk.ChunkOffset; MapActorDescriptor template = m_sActorDescriptors.Find(x => x.FourCC == chunk.FourCC); if (template == null) { Console.WriteLine("Unsupported FourCC: {0}", chunk.FourCC); continue; } switch (chunk.FourCC) { // We're only going to re-load the lighting-based actors... case "EnvR": case "Colo": case "Pale": case "Virt": for (int i = 0; i < chunk.ElementCount; i++) { var newActor = LoadActorFromChunk(chunk.FourCC, template); newActor.Layer = chunk.Layer; loadedActors.Add(newActor); } break; } } var dict = new Dictionary <string, List <WActorNode> >(); foreach (var actor in loadedActors) { if (!dict.ContainsKey(actor.FourCC)) { dict[actor.FourCC] = new List <WActorNode>(); } dict[actor.FourCC].Add(actor); } // Load Skybox Lighting Data var virtList = new List <LightingSkyboxColors>(); var paleList = new List <LightingPalette>(); var coloList = new List <LightingTimePreset>(); if (dict.ContainsKey("virt") && dict.ContainsKey("pale") && dict.ContainsKey("Colo")) { foreach (var virt in dict["Virt"]) { WLinearColor unknown1, unknown2, unknown3, unknown4, horizonCloud, centerCloud, sky, falseSea, horizon; virt.TryGetValue("Unknown 1", out unknown1); virt.TryGetValue("Unknown 2", out unknown2); virt.TryGetValue("Unknown 3", out unknown3); virt.TryGetValue("Unknown 4", out unknown4); virt.TryGetValue("Horizon Cloud Color", out horizonCloud); virt.TryGetValue("Center Cloud Color", out centerCloud); virt.TryGetValue("Sky Color", out sky); virt.TryGetValue("False Sea Color", out falseSea); virt.TryGetValue("Horizon Color", out horizon); LightingSkyboxColors virtEntry = new LightingSkyboxColors { Unknown1 = unknown1, Unknown2 = unknown2, Unknown3 = unknown3, Unknown4 = unknown4, HorizonCloud = horizonCloud, CenterCloud = centerCloud, Sky = sky, FalseSea = falseSea, Horizon = horizon }; virtList.Add(virtEntry); } foreach (var pale in dict["Pale"]) { WLinearColor shadow, actorAmbient, roomLight, roomAmbient, wave, ocean, unknown1, unknown2, doorway, unknown3, fog; byte virtIndex; float fogFarPlane, fogNearPlane; pale.TryGetValue("Shadow Color", out shadow); pale.TryGetValue("Actor Ambient Color", out actorAmbient); pale.TryGetValue("Room Light Color", out roomLight); pale.TryGetValue("Room Ambient Color", out roomAmbient); pale.TryGetValue("Wave Color", out wave); pale.TryGetValue("Ocean Color", out ocean); pale.TryGetValue("Unknown White 1", out unknown1); pale.TryGetValue("Unknown White 2", out unknown2); pale.TryGetValue("Door Backfill", out doorway); pale.TryGetValue("Unknown 3", out unknown3); pale.TryGetValue("Fog Color", out fog); pale.TryGetValue("Skybox Color Index", out virtIndex); pale.TryGetValue("Fog Far Plane", out fogFarPlane); pale.TryGetValue("Fog Near Plane", out fogNearPlane); LightingPalette lightPalette = new LightingPalette { Shadow = shadow, ActorAmbient = actorAmbient, RoomLight = roomLight, RoomAmbient = roomAmbient, WaveColor = wave, OceanColor = ocean, UnknownWhite1 = unknown1, UnknownWhite2 = unknown2, Doorway = doorway, UnknownColor3 = unknown3, Skybox = virtList[virtIndex], Fog = fog, FogNearPlane = fogNearPlane, FogFarPlane = fogFarPlane, }; paleList.Add(lightPalette); } foreach (var colo in dict["Colo"]) { byte[] setA = new byte[6]; byte[] setB = new byte[6]; colo.TryGetValue("Dawn A", out setA[0]); colo.TryGetValue("Morning A", out setA[1]); colo.TryGetValue("Noon A", out setA[2]); colo.TryGetValue("Afternoon A", out setA[3]); colo.TryGetValue("Dusk A", out setA[4]); colo.TryGetValue("Night A", out setA[5]); colo.TryGetValue("Dawn B", out setB[0]); colo.TryGetValue("Morning B", out setB[1]); colo.TryGetValue("Noon B", out setB[2]); colo.TryGetValue("Afternoon B", out setB[3]); colo.TryGetValue("Dusk B", out setB[4]); colo.TryGetValue("Night B", out setB[5]); LightingTimePreset timePreset = new LightingTimePreset(); for (int i = 0; i < 6; i++) { timePreset.TimePresetA[i] = paleList[setA[i]]; } //for (int i = 0; i < 6; i++) //timePreset.TimePresetB[i] = paleList[setB[i]]; coloList.Add(timePreset); } } var envrList = new List <EnvironmentLighting>(); if (paleList.Count > 0 && coloList.Count > 0) { foreach (var envr in dict["EnvR"]) { byte[] setA = new byte[4]; byte[] setB = new byte[4]; envr.TryGetValue("Clear Color A", out setA[0]); envr.TryGetValue("Raining Color A", out setA[1]); envr.TryGetValue("Snowing A", out setA[2]); envr.TryGetValue("Unknown A", out setA[3]); envr.TryGetValue("Clear Color B", out setB[0]); envr.TryGetValue("Raining Color B", out setB[1]); envr.TryGetValue("Snowing B", out setB[2]); envr.TryGetValue("Unknown B", out setB[3]); EnvironmentLighting envrPreset = new EnvironmentLighting(); for (int i = 0; i < 4; i++) { envrPreset.WeatherA[i] = coloList[setA[i]]; } for (int i = 0; i < 4; i++) { envrPreset.WeatherB[i] = coloList[setB[i]]; } envrList.Add(envrPreset); } } return(envrList); }
private WActorNode LoadActorFromChunk(string fourCC, MapActorDescriptor template) { var newActor = new WActorNode(fourCC, m_world); List <IPropertyValue> actorProperties = new List <IPropertyValue>(); foreach (var field in template.Fields) { IPropertyValue propValue = null; switch (field.FieldType) { case PropertyValueType.Byte: propValue = new TBytePropertyValue(m_reader.ReadByte(), field.FieldName); break; case PropertyValueType.Bool: propValue = new TBoolPropertyValue(m_reader.ReadBoolean(), field.FieldName); break; case PropertyValueType.Short: propValue = new TShortPropertyValue(m_reader.ReadInt16(), field.FieldName); break; case PropertyValueType.Int: propValue = new TIntPropertyValue(m_reader.ReadInt32(), field.FieldName); break; case PropertyValueType.Float: propValue = new TFloatPropertyValue(m_reader.ReadSingle(), field.FieldName); break; case PropertyValueType.FixedLengthString: case PropertyValueType.String: string stringVal = (field.Length == 0) ? m_reader.ReadStringUntil('\0') : m_reader.ReadString(field.Length); stringVal = stringVal.Trim(new[] { '\0' }); propValue = new TStringPropertyValue(stringVal, field.FieldName); break; case PropertyValueType.Vector2: propValue = new TVector2PropertyValue(new OpenTK.Vector2(m_reader.ReadSingle(), m_reader.ReadSingle()), field.FieldName); break; case PropertyValueType.Vector3: propValue = new TVector3PropertyValue(new OpenTK.Vector3(m_reader.ReadSingle(), m_reader.ReadSingle(), m_reader.ReadSingle()), field.FieldName); break; case PropertyValueType.XRotation: case PropertyValueType.YRotation: case PropertyValueType.ZRotation: propValue = new TShortPropertyValue(m_reader.ReadInt16(), field.FieldName); break; case PropertyValueType.Color24: propValue = new TLinearColorPropertyValue(new WLinearColor(m_reader.ReadByte() / 255f, m_reader.ReadByte() / 255f, m_reader.ReadByte() / 255f), field.FieldName); break; case PropertyValueType.Color32: propValue = new TLinearColorPropertyValue(new WLinearColor(m_reader.ReadByte() / 255f, m_reader.ReadByte() / 255f, m_reader.ReadByte() / 255f, m_reader.ReadByte() / 255f), field.FieldName); break; default: Console.WriteLine("Unsupported PropertyValueType: {0}", field.FieldType); break; } propValue.SetUndoStack(m_world.UndoStack); actorProperties.Add(propValue); } // Now that we have loaded all properties out of it, we need to post-process them. IPropertyValue positionProperty = actorProperties.Find(x => x.Name == "Position"); IPropertyValue xRotProperty = actorProperties.Find(x => x.Name == "X Rotation"); IPropertyValue yRotProperty = actorProperties.Find(x => x.Name == "Y Rotation"); IPropertyValue zRotProperty = actorProperties.Find(x => x.Name == "Z Rotation"); IPropertyValue xScaleProperty = actorProperties.Find(x => x.Name == "X Scale"); IPropertyValue yScaleProperty = actorProperties.Find(x => x.Name == "Y Scale"); IPropertyValue zScaleProperty = actorProperties.Find(x => x.Name == "Z Scale"); // Remove these properties from the actor so they don't get added to the UI. actorProperties.Remove(positionProperty); actorProperties.Remove(xRotProperty); actorProperties.Remove(yRotProperty); actorProperties.Remove(zRotProperty); actorProperties.Remove(xScaleProperty); actorProperties.Remove(yScaleProperty); actorProperties.Remove(zScaleProperty); if (positionProperty != null) { newActor.Transform.Position = (Vector3)positionProperty.GetValue(); } float xRot = 0, yRot = 0, zRot = 0; if (xRotProperty != null) { xRot = WMath.RotationShortToFloat((short)xRotProperty.GetValue()); } if (yRotProperty != null) { yRot = WMath.RotationShortToFloat((short)yRotProperty.GetValue()); } if (zRotProperty != null) { zRot = WMath.RotationShortToFloat((short)zRotProperty.GetValue()); } // Build rotation with ZYX order. Quaternion xRotQ = Quaternion.FromAxisAngle(new Vector3(1, 0, 0), WMath.DegreesToRadians(xRot)); Quaternion yRotQ = Quaternion.FromAxisAngle(new Vector3(0, 1, 0), WMath.DegreesToRadians(yRot)); Quaternion zRotQ = Quaternion.FromAxisAngle(new Vector3(0, 0, 1), WMath.DegreesToRadians(zRot)); newActor.Transform.Rotation = zRotQ * yRotQ * xRotQ; float xScale = 1, yScale = 1, zScale = 1; if (xScaleProperty != null) { xScale = ((byte)xScaleProperty.GetValue()) / 10f; } if (yScaleProperty != null) { yScale = ((byte)yScaleProperty.GetValue()) / 10f; } if (zScaleProperty != null) { zScale = ((byte)zScaleProperty.GetValue()) / 10f; } newActor.Transform.LocalScale = new Vector3(xScale, yScale, zScale); newActor.Properties.AddRange(actorProperties); newActor.PostFinishedLoad(); return(newActor); }
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); } }