| 1 | using System; | 
 
 
 
 
 | 2 | using System.Globalization; | 
 
 
 
 
 | 3 | using System.Xml; | 
 
 
 
 
 | 4 | using Oni.Imaging; | 
 
 
 
 
 | 5 | using Oni.Metadata; | 
 
 
 
 
 | 6 |  | 
 
 
 
 
 | 7 | namespace Oni.Xml | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | using Oni.Particles; | 
 
 
 
 
 | 10 |  | 
 
 
 
 
 | 11 | internal class ParticleXmlImporter : ParticleXml | 
 
 
 
 
 | 12 | { | 
 
 
 
 
 | 13 | #region Private data | 
 
 
 
 
 | 14 | private XmlReader xml; | 
 
 
 
 
 | 15 | private Particle particle; | 
 
 
 
 
 | 16 | #endregion | 
 
 
 
 
 | 17 |  | 
 
 
 
 
 | 18 | public ParticleXmlImporter(XmlReader xml) | 
 
 
 
 
 | 19 | { | 
 
 
 
 
 | 20 | this.xml = xml; | 
 
 
 
 
 | 21 | this.particle = new Particle(); | 
 
 
 
 
 | 22 | } | 
 
 
 
 
 | 23 |  | 
 
 
 
 
 | 24 | public static void Import(XmlReader xml, BinaryWriter writer) | 
 
 
 
 
 | 25 | { | 
 
 
 
 
 | 26 | int lengthPosition = writer.Position; | 
 
 
 
 
 | 27 |  | 
 
 
 
 
 | 28 | writer.WriteUInt16(0); | 
 
 
 
 
 | 29 | writer.WriteUInt16(18); | 
 
 
 
 
 | 30 |  | 
 
 
 
 
 | 31 | var reader = new ParticleXmlImporter(xml); | 
 
 
 
 
 | 32 | reader.Read(); | 
 
 
 
 
 | 33 | reader.particle.Write(writer); | 
 
 
 
 
 | 34 |  | 
 
 
 
 
 | 35 | int length = writer.Position - lengthPosition; | 
 
 
 
 
 | 36 | writer.PushPosition(lengthPosition); | 
 
 
 
 
 | 37 | writer.WriteUInt16(length); | 
 
 
 
 
 | 38 | writer.PopPosition(); | 
 
 
 
 
 | 39 | } | 
 
 
 
 
 | 40 |  | 
 
 
 
 
 | 41 | public void Read() | 
 
 
 
 
 | 42 | { | 
 
 
 
 
 | 43 | ReadOptions(); | 
 
 
 
 
 | 44 | ReadProperties(); | 
 
 
 
 
 | 45 | ReadAppearance(); | 
 
 
 
 
 | 46 | ReadAttractor(); | 
 
 
 
 
 | 47 | ReadVariables(); | 
 
 
 
 
 | 48 | ReadEmitters(); | 
 
 
 
 
 | 49 | ReadEvents(); | 
 
 
 
 
 | 50 | } | 
 
 
 
 
 | 51 |  | 
 
 
 
 
 | 52 | private void ReadOptions() | 
 
 
 
 
 | 53 | { | 
 
 
 
 
 | 54 | if (!xml.IsStartElement("Options")) | 
 
 
 
 
 | 55 | return; | 
 
 
 
 
 | 56 |  | 
 
 
 
 
 | 57 | xml.ReadStartElement(); | 
 
 
 
 
 | 58 |  | 
 
 
 
 
 | 59 | while (xml.IsStartElement()) | 
 
 
 
 
 | 60 | { | 
 
 
 
 
 | 61 | switch (xml.LocalName) | 
 
 
 
 
 | 62 | { | 
 
 
 
 
 | 63 | case "DisableDetailLevel": | 
 
 
 
 
 | 64 | particle.DisableDetailLevel = MetaEnum.Parse<DisableDetailLevel>(xml.ReadElementContentAsString()); | 
 
 
 
 
 | 65 | continue; | 
 
 
 
 
 | 66 |  | 
 
 
 
 
 | 67 | case "Lifetime": | 
 
 
 
 
 | 68 | particle.Lifetime = ReadValueFloat(); | 
 
 
 
 
 | 69 | continue; | 
 
 
 
 
 | 70 |  | 
 
 
 
 
 | 71 | case "CollisionRadius": | 
 
 
 
 
 | 72 | particle.CollisionRadius = ReadValueFloat(); | 
 
 
 
 
 | 73 | continue; | 
 
 
 
 
 | 74 |  | 
 
 
 
 
 | 75 | case "FlyBySoundName": | 
 
 
 
 
 | 76 | particle.FlyBySoundName = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 77 | continue; | 
 
 
 
 
 | 78 |  | 
 
 
 
 
 | 79 | case "AIAlertRadius": | 
 
 
 
 
 | 80 | particle.AIAlertRadius = xml.ReadElementContentAsFloat(); | 
 
 
 
 
 | 81 | continue; | 
 
 
 
 
 | 82 |  | 
 
 
 
 
 | 83 | case "AIDodgeRadius": | 
 
 
 
 
 | 84 | particle.AIDodgeRadius = xml.ReadElementContentAsFloat(); | 
 
 
 
 
 | 85 | continue; | 
 
 
 
 
 | 86 |  | 
 
 
 
 
 | 87 | default: | 
 
 
 
 
 | 88 | if (ReadFlag1() || ReadFlag2()) | 
 
 
 
 
 | 89 | continue; | 
 
 
 
 
 | 90 | break; | 
 
 
 
 
 | 91 | } | 
 
 
 
 
 | 92 |  | 
 
 
 
 
 | 93 | throw new FormatException(string.Format("Unknown option {0}", xml.LocalName)); | 
 
 
 
 
 | 94 | } | 
 
 
 
 
 | 95 |  | 
 
 
 
 
 | 96 | xml.ReadEndElement(); | 
 
 
 
 
 | 97 | } | 
 
 
 
 
 | 98 |  | 
 
 
 
 
 | 99 | private void ReadProperties() | 
 
 
 
 
 | 100 | { | 
 
 
 
 
 | 101 | if (!xml.IsStartElement("Properties")) | 
 
 
 
 
 | 102 | return; | 
 
 
 
 
 | 103 |  | 
 
 
 
 
 | 104 | xml.ReadStartElement(); | 
 
 
 
 
 | 105 |  | 
 
 
 
 
 | 106 | while (xml.IsStartElement()) | 
 
 
 
 
 | 107 | { | 
 
 
 
 
 | 108 | if (ReadFlag1()) | 
 
 
 
 
 | 109 | continue; | 
 
 
 
 
 | 110 |  | 
 
 
 
 
 | 111 | throw new FormatException(string.Format("Unknown property {0}", xml.LocalName)); | 
 
 
 
 
 | 112 | } | 
 
 
 
 
 | 113 |  | 
 
 
 
 
 | 114 | xml.ReadEndElement(); | 
 
 
 
 
 | 115 | } | 
 
 
 
 
 | 116 |  | 
 
 
 
 
 | 117 | private void ReadAppearance() | 
 
 
 
 
 | 118 | { | 
 
 
 
 
 | 119 | if (!xml.IsStartElement("Appearance")) | 
 
 
 
 
 | 120 | return; | 
 
 
 
 
 | 121 |  | 
 
 
 
 
 | 122 | Appearance appearance = particle.Appearance; | 
 
 
 
 
 | 123 |  | 
 
 
 
 
 | 124 | xml.ReadStartElement(); | 
 
 
 
 
 | 125 |  | 
 
 
 
 
 | 126 | while (xml.IsStartElement()) | 
 
 
 
 
 | 127 | { | 
 
 
 
 
 | 128 | switch (xml.LocalName) | 
 
 
 
 
 | 129 | { | 
 
 
 
 
 | 130 | case "DisplayType": | 
 
 
 
 
 | 131 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 132 |  | 
 
 
 
 
 | 133 | switch (text) | 
 
 
 
 
 | 134 | { | 
 
 
 
 
 | 135 | case "Geometry": | 
 
 
 
 
 | 136 | particle.Flags1 |= ParticleFlags1.Geometry; | 
 
 
 
 
 | 137 | break; | 
 
 
 
 
 | 138 | case "Vector": | 
 
 
 
 
 | 139 | particle.Flags2 |= ParticleFlags2.Vector; | 
 
 
 
 
 | 140 | break; | 
 
 
 
 
 | 141 | case "Decal": | 
 
 
 
 
 | 142 | particle.Flags2 |= ParticleFlags2.Decal; | 
 
 
 
 
 | 143 | break; | 
 
 
 
 
 | 144 | default: | 
 
 
 
 
 | 145 | particle.SpriteType = MetaEnum.Parse<SpriteType>(text); | 
 
 
 
 
 | 146 | break; | 
 
 
 
 
 | 147 | } | 
 
 
 
 
 | 148 |  | 
 
 
 
 
 | 149 | continue; | 
 
 
 
 
 | 150 |  | 
 
 
 
 
 | 151 | case "TexGeom": | 
 
 
 
 
 | 152 | appearance.TextureName = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 153 | continue; | 
 
 
 
 
 | 154 |  | 
 
 
 
 
 | 155 | case "Scale": | 
 
 
 
 
 | 156 | appearance.Scale = ReadValueFloat(); | 
 
 
 
 
 | 157 | continue; | 
 
 
 
 
 | 158 | case "YScale": | 
 
 
 
 
 | 159 | appearance.YScale = ReadValueFloat(); | 
 
 
 
 
 | 160 | continue; | 
 
 
 
 
 | 161 | case "Rotation": | 
 
 
 
 
 | 162 | appearance.Rotation = ReadValueFloat(); | 
 
 
 
 
 | 163 | continue; | 
 
 
 
 
 | 164 | case "Alpha": | 
 
 
 
 
 | 165 | appearance.Alpha = ReadValueFloat(); | 
 
 
 
 
 | 166 | continue; | 
 
 
 
 
 | 167 | case "XOffset": | 
 
 
 
 
 | 168 | appearance.XOffset = ReadValueFloat(); | 
 
 
 
 
 | 169 | continue; | 
 
 
 
 
 | 170 | case "XShorten": | 
 
 
 
 
 | 171 | appearance.XShorten = ReadValueFloat(); | 
 
 
 
 
 | 172 | continue; | 
 
 
 
 
 | 173 | case "Tint": | 
 
 
 
 
 | 174 | appearance.Tint = ReadValueColor(); | 
 
 
 
 
 | 175 | continue; | 
 
 
 
 
 | 176 | case "EdgeFadeMin": | 
 
 
 
 
 | 177 | appearance.EdgeFadeMin = ReadValueFloat(); | 
 
 
 
 
 | 178 | continue; | 
 
 
 
 
 | 179 | case "EdgeFadeMax": | 
 
 
 
 
 | 180 | appearance.EdgeFadeMax = ReadValueFloat(); | 
 
 
 
 
 | 181 | continue; | 
 
 
 
 
 | 182 | case "MaxContrailDistance": | 
 
 
 
 
 | 183 | appearance.MaxContrail = ReadValueFloat(); | 
 
 
 
 
 | 184 | continue; | 
 
 
 
 
 | 185 | case "LensFlareDistance": | 
 
 
 
 
 | 186 | appearance.LensFlareDistance = ReadValueFloat(); | 
 
 
 
 
 | 187 | continue; | 
 
 
 
 
 | 188 | case "LensFlareFadeInFrames": | 
 
 
 
 
 | 189 | appearance.LensFlareFadeInFrames = xml.ReadElementContentAsInt(); | 
 
 
 
 
 | 190 | continue; | 
 
 
 
 
 | 191 | case "LensFlareFadeOutFrames": | 
 
 
 
 
 | 192 | appearance.LensFlareFadeOutFrames = xml.ReadElementContentAsInt(); | 
 
 
 
 
 | 193 | continue; | 
 
 
 
 
 | 194 | case "MaxDecals": | 
 
 
 
 
 | 195 | appearance.MaxDecals = xml.ReadElementContentAsInt(); | 
 
 
 
 
 | 196 | continue; | 
 
 
 
 
 | 197 | case "DecalFadeFrames": | 
 
 
 
 
 | 198 | appearance.DecalFadeFrames = xml.ReadElementContentAsInt(); | 
 
 
 
 
 | 199 | continue; | 
 
 
 
 
 | 200 | case "DecalWrapAngle": | 
 
 
 
 
 | 201 | appearance.DecalWrapAngle = ReadValueFloat(); | 
 
 
 
 
 | 202 | continue; | 
 
 
 
 
 | 203 | default: | 
 
 
 
 
 | 204 | if (ReadFlag1() || ReadFlag2()) | 
 
 
 
 
 | 205 | continue; | 
 
 
 
 
 | 206 | break; | 
 
 
 
 
 | 207 | } | 
 
 
 
 
 | 208 |  | 
 
 
 
 
 | 209 | throw new FormatException(string.Format("Unknown appearance property {0}", xml.LocalName)); | 
 
 
 
 
 | 210 | } | 
 
 
 
 
 | 211 |  | 
 
 
 
 
 | 212 | xml.ReadEndElement(); | 
 
 
 
 
 | 213 | } | 
 
 
 
 
 | 214 |  | 
 
 
 
 
 | 215 | private void ReadAttractor() | 
 
 
 
 
 | 216 | { | 
 
 
 
 
 | 217 | if (!xml.IsStartElement("Attractor")) | 
 
 
 
 
 | 218 | return; | 
 
 
 
 
 | 219 |  | 
 
 
 
 
 | 220 | xml.ReadStartElement(); | 
 
 
 
 
 | 221 |  | 
 
 
 
 
 | 222 | Attractor attractor = particle.Attractor; | 
 
 
 
 
 | 223 |  | 
 
 
 
 
 | 224 | while (xml.IsStartElement()) | 
 
 
 
 
 | 225 | { | 
 
 
 
 
 | 226 | switch (xml.LocalName) | 
 
 
 
 
 | 227 | { | 
 
 
 
 
 | 228 | case "Target": | 
 
 
 
 
 | 229 | attractor.Target = (AttractorTarget)Enum.Parse(typeof(AttractorTarget), xml.ReadElementContentAsString()); | 
 
 
 
 
 | 230 | continue; | 
 
 
 
 
 | 231 | case "Selector": | 
 
 
 
 
 | 232 | attractor.Selector = (AttractorSelector)Enum.Parse(typeof(AttractorSelector), xml.ReadElementContentAsString()); | 
 
 
 
 
 | 233 | continue; | 
 
 
 
 
 | 234 | case "Class": | 
 
 
 
 
 | 235 | attractor.ClassName = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 236 | continue; | 
 
 
 
 
 | 237 | case "MaxDistance": | 
 
 
 
 
 | 238 | attractor.MaxDistance = ReadValueFloat(); | 
 
 
 
 
 | 239 | continue; | 
 
 
 
 
 | 240 | case "MaxAngle": | 
 
 
 
 
 | 241 | attractor.MaxAngle = ReadValueFloat(); | 
 
 
 
 
 | 242 | continue; | 
 
 
 
 
 | 243 | case "AngleSelectMax": | 
 
 
 
 
 | 244 | attractor.AngleSelectMax = ReadValueFloat(); | 
 
 
 
 
 | 245 | continue; | 
 
 
 
 
 | 246 | case "AngleSelectMin": | 
 
 
 
 
 | 247 | attractor.AngleSelectMin = ReadValueFloat(); | 
 
 
 
 
 | 248 | continue; | 
 
 
 
 
 | 249 | case "AngleSelectWeight": | 
 
 
 
 
 | 250 | attractor.AngleSelectWeight = ReadValueFloat(); | 
 
 
 
 
 | 251 | continue; | 
 
 
 
 
 | 252 | } | 
 
 
 
 
 | 253 |  | 
 
 
 
 
 | 254 | throw new FormatException(string.Format("Unknown attractor property {0}", xml.LocalName)); | 
 
 
 
 
 | 255 | } | 
 
 
 
 
 | 256 |  | 
 
 
 
 
 | 257 | xml.ReadEndElement(); | 
 
 
 
 
 | 258 | } | 
 
 
 
 
 | 259 |  | 
 
 
 
 
 | 260 | private void ReadVariables() | 
 
 
 
 
 | 261 | { | 
 
 
 
 
 | 262 | if (!xml.IsStartElement("Variables")) | 
 
 
 
 
 | 263 | return; | 
 
 
 
 
 | 264 |  | 
 
 
 
 
 | 265 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 266 | { | 
 
 
 
 
 | 267 | xml.ReadStartElement(); | 
 
 
 
 
 | 268 | } | 
 
 
 
 
 | 269 | else | 
 
 
 
 
 | 270 | { | 
 
 
 
 
 | 271 | xml.ReadStartElement(); | 
 
 
 
 
 | 272 |  | 
 
 
 
 
 | 273 | while (xml.IsStartElement()) | 
 
 
 
 
 | 274 | particle.Variables.Add(ReadVariable()); | 
 
 
 
 
 | 275 |  | 
 
 
 
 
 | 276 | xml.ReadEndElement(); | 
 
 
 
 
 | 277 | } | 
 
 
 
 
 | 278 | } | 
 
 
 
 
 | 279 |  | 
 
 
 
 
 | 280 | private Variable ReadVariable() | 
 
 
 
 
 | 281 | { | 
 
 
 
 
 | 282 | string typeName = xml.LocalName; | 
 
 
 
 
 | 283 | string name = xml.GetAttribute("Name"); | 
 
 
 
 
 | 284 |  | 
 
 
 
 
 | 285 | switch (typeName) | 
 
 
 
 
 | 286 | { | 
 
 
 
 
 | 287 | case "Float": | 
 
 
 
 
 | 288 | return new Variable(name, StorageType.Float, ReadValueFloat()); | 
 
 
 
 
 | 289 |  | 
 
 
 
 
 | 290 | case "Color": | 
 
 
 
 
 | 291 | return new Variable(name, StorageType.Color, ReadValueColor()); | 
 
 
 
 
 | 292 |  | 
 
 
 
 
 | 293 | case "PingPongState": | 
 
 
 
 
 | 294 | return new Variable(name, StorageType.PingPongState, ReadValueInt()); | 
 
 
 
 
 | 295 |  | 
 
 
 
 
 | 296 | default: | 
 
 
 
 
 | 297 | throw new XmlException(string.Format("Unknown variable type '{0}'", typeName)); | 
 
 
 
 
 | 298 |  | 
 
 
 
 
 | 299 | } | 
 
 
 
 
 | 300 | } | 
 
 
 
 
 | 301 |  | 
 
 
 
 
 | 302 | private void ReadEmitters() | 
 
 
 
 
 | 303 | { | 
 
 
 
 
 | 304 | if (!xml.IsStartElement("Emitters")) | 
 
 
 
 
 | 305 | return; | 
 
 
 
 
 | 306 |  | 
 
 
 
 
 | 307 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 308 | { | 
 
 
 
 
 | 309 | xml.ReadStartElement(); | 
 
 
 
 
 | 310 | } | 
 
 
 
 
 | 311 | else | 
 
 
 
 
 | 312 | { | 
 
 
 
 
 | 313 | xml.ReadStartElement(); | 
 
 
 
 
 | 314 |  | 
 
 
 
 
 | 315 | while (xml.IsStartElement()) | 
 
 
 
 
 | 316 | particle.Emitters.Add(ReadEmitter()); | 
 
 
 
 
 | 317 |  | 
 
 
 
 
 | 318 | xml.ReadEndElement(); | 
 
 
 
 
 | 319 | } | 
 
 
 
 
 | 320 | } | 
 
 
 
 
 | 321 |  | 
 
 
 
 
 | 322 | private Emitter ReadEmitter() | 
 
 
 
 
 | 323 | { | 
 
 
 
 
 | 324 | xml.ReadStartElement(); | 
 
 
 
 
 | 325 |  | 
 
 
 
 
 | 326 | Emitter emitter = new Emitter(); | 
 
 
 
 
 | 327 |  | 
 
 
 
 
 | 328 | while (xml.IsStartElement()) | 
 
 
 
 
 | 329 | { | 
 
 
 
 
 | 330 | switch (xml.LocalName) | 
 
 
 
 
 | 331 | { | 
 
 
 
 
 | 332 | case "Class": | 
 
 
 
 
 | 333 | emitter.ParticleClass = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 334 | continue; | 
 
 
 
 
 | 335 |  | 
 
 
 
 
 | 336 | case "Flags": | 
 
 
 
 
 | 337 | emitter.Flags = MetaEnum.Parse<EmitterFlags>(xml.ReadElementContentAsString()); | 
 
 
 
 
 | 338 | continue; | 
 
 
 
 
 | 339 |  | 
 
 
 
 
 | 340 | case "TurnOffTreshold": | 
 
 
 
 
 | 341 | emitter.TurnOffTreshold = xml.ReadElementContentAsInt(); | 
 
 
 
 
 | 342 | continue; | 
 
 
 
 
 | 343 |  | 
 
 
 
 
 | 344 | case "Probability": | 
 
 
 
 
 | 345 | emitter.Probability = (int)(xml.ReadElementContentAsFloat() * 65535.0f); | 
 
 
 
 
 | 346 | continue; | 
 
 
 
 
 | 347 |  | 
 
 
 
 
 | 348 | case "Copies": | 
 
 
 
 
 | 349 | emitter.Copies = xml.ReadElementContentAsFloat(); | 
 
 
 
 
 | 350 | continue; | 
 
 
 
 
 | 351 |  | 
 
 
 
 
 | 352 | case "LinkTo": | 
 
 
 
 
 | 353 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 354 | if (!string.IsNullOrEmpty(text)) | 
 
 
 
 
 | 355 | { | 
 
 
 
 
 | 356 | if (text == "this") | 
 
 
 
 
 | 357 | emitter.LinkTo = 1; | 
 
 
 
 
 | 358 | else if (text == "link") | 
 
 
 
 
 | 359 | emitter.LinkTo = 10; | 
 
 
 
 
 | 360 | else | 
 
 
 
 
 | 361 | emitter.LinkTo = int.Parse(text, CultureInfo.InvariantCulture) + 2; | 
 
 
 
 
 | 362 | } | 
 
 
 
 
 | 363 | continue; | 
 
 
 
 
 | 364 |  | 
 
 
 
 
 | 365 | case "Rate": | 
 
 
 
 
 | 366 | xml.ReadStartElement(); | 
 
 
 
 
 | 367 | ReadEmitterRate(emitter); | 
 
 
 
 
 | 368 | xml.ReadEndElement(); | 
 
 
 
 
 | 369 | continue; | 
 
 
 
 
 | 370 |  | 
 
 
 
 
 | 371 | case "Position": | 
 
 
 
 
 | 372 | xml.ReadStartElement(); | 
 
 
 
 
 | 373 | ReadEmitterPosition(emitter); | 
 
 
 
 
 | 374 | xml.ReadEndElement(); | 
 
 
 
 
 | 375 | continue; | 
 
 
 
 
 | 376 |  | 
 
 
 
 
 | 377 | case "Speed": | 
 
 
 
 
 | 378 | xml.ReadStartElement(); | 
 
 
 
 
 | 379 | ReadEmitterSpeed(emitter); | 
 
 
 
 
 | 380 | xml.ReadEndElement(); | 
 
 
 
 
 | 381 | continue; | 
 
 
 
 
 | 382 |  | 
 
 
 
 
 | 383 | case "Direction": | 
 
 
 
 
 | 384 | xml.ReadStartElement(); | 
 
 
 
 
 | 385 | ReadEmitterDirection(emitter); | 
 
 
 
 
 | 386 | xml.ReadEndElement(); | 
 
 
 
 
 | 387 | continue; | 
 
 
 
 
 | 388 |  | 
 
 
 
 
 | 389 | case "Orientation": | 
 
 
 
 
 | 390 | emitter.OrientationDir = MetaEnum.Parse<EmitterOrientation>(xml.ReadElementContentAsString()); | 
 
 
 
 
 | 391 | continue; | 
 
 
 
 
 | 392 |  | 
 
 
 
 
 | 393 | case "OrientationUp": | 
 
 
 
 
 | 394 | emitter.OrientationUp = MetaEnum.Parse<EmitterOrientation>(xml.ReadElementContentAsString()); | 
 
 
 
 
 | 395 | continue; | 
 
 
 
 
 | 396 | } | 
 
 
 
 
 | 397 |  | 
 
 
 
 
 | 398 | throw new FormatException(string.Format("Unknown emitter property '{0}'", xml.LocalName)); | 
 
 
 
 
 | 399 | } | 
 
 
 
 
 | 400 |  | 
 
 
 
 
 | 401 | xml.ReadEndElement(); | 
 
 
 
 
 | 402 |  | 
 
 
 
 
 | 403 | return emitter; | 
 
 
 
 
 | 404 | } | 
 
 
 
 
 | 405 |  | 
 
 
 
 
 | 406 | private void ReadEmitterRate(Emitter emitter) | 
 
 
 
 
 | 407 | { | 
 
 
 
 
 | 408 | emitter.Rate = MetaEnum.Parse<EmitterRate>(xml.LocalName); | 
 
 
 
 
 | 409 |  | 
 
 
 
 
 | 410 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 411 | { | 
 
 
 
 
 | 412 | xml.ReadStartElement(); | 
 
 
 
 
 | 413 | } | 
 
 
 
 
 | 414 | else | 
 
 
 
 
 | 415 | { | 
 
 
 
 
 | 416 | xml.ReadStartElement(); | 
 
 
 
 
 | 417 |  | 
 
 
 
 
 | 418 | switch (emitter.Rate) | 
 
 
 
 
 | 419 | { | 
 
 
 
 
 | 420 | case EmitterRate.Continous: | 
 
 
 
 
 | 421 | emitter.Parameters[0] = ReadValueFloat("Interval"); | 
 
 
 
 
 | 422 | break; | 
 
 
 
 
 | 423 | case EmitterRate.Random: | 
 
 
 
 
 | 424 | emitter.Parameters[0] = ReadValueFloat("MinInterval"); | 
 
 
 
 
 | 425 | emitter.Parameters[1] = ReadValueFloat("MaxInterval"); | 
 
 
 
 
 | 426 | break; | 
 
 
 
 
 | 427 | case EmitterRate.Distance: | 
 
 
 
 
 | 428 | emitter.Parameters[0] = ReadValueFloat("Distance"); | 
 
 
 
 
 | 429 | break; | 
 
 
 
 
 | 430 | case EmitterRate.Attractor: | 
 
 
 
 
 | 431 | emitter.Parameters[0] = ReadValueFloat("RechargeTime"); | 
 
 
 
 
 | 432 | emitter.Parameters[1] = ReadValueFloat("CheckInterval"); | 
 
 
 
 
 | 433 | break; | 
 
 
 
 
 | 434 |  | 
 
 
 
 
 | 435 | } | 
 
 
 
 
 | 436 |  | 
 
 
 
 
 | 437 | xml.ReadEndElement(); | 
 
 
 
 
 | 438 | } | 
 
 
 
 
 | 439 | } | 
 
 
 
 
 | 440 |  | 
 
 
 
 
 | 441 | private void ReadEmitterPosition(Emitter emitter) | 
 
 
 
 
 | 442 | { | 
 
 
 
 
 | 443 | emitter.Position = MetaEnum.Parse<EmitterPosition>(xml.LocalName); | 
 
 
 
 
 | 444 |  | 
 
 
 
 
 | 445 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 446 | { | 
 
 
 
 
 | 447 | xml.ReadStartElement(); | 
 
 
 
 
 | 448 | } | 
 
 
 
 
 | 449 | else | 
 
 
 
 
 | 450 | { | 
 
 
 
 
 | 451 | xml.ReadStartElement(); | 
 
 
 
 
 | 452 |  | 
 
 
 
 
 | 453 | switch (emitter.Position) | 
 
 
 
 
 | 454 | { | 
 
 
 
 
 | 455 | case EmitterPosition.Line: | 
 
 
 
 
 | 456 | emitter.Parameters[2] = ReadValueFloat("Radius"); | 
 
 
 
 
 | 457 | break; | 
 
 
 
 
 | 458 | case EmitterPosition.Circle: | 
 
 
 
 
 | 459 | case EmitterPosition.Sphere: | 
 
 
 
 
 | 460 | emitter.Parameters[2] = ReadValueFloat("InnerRadius"); | 
 
 
 
 
 | 461 | emitter.Parameters[3] = ReadValueFloat("OuterRadius"); | 
 
 
 
 
 | 462 | break; | 
 
 
 
 
 | 463 | case EmitterPosition.Offset: | 
 
 
 
 
 | 464 | emitter.Parameters[2] = ReadValueFloat("X"); | 
 
 
 
 
 | 465 | emitter.Parameters[3] = ReadValueFloat("Y"); | 
 
 
 
 
 | 466 | emitter.Parameters[4] = ReadValueFloat("Z"); | 
 
 
 
 
 | 467 | break; | 
 
 
 
 
 | 468 | case EmitterPosition.Cylinder: | 
 
 
 
 
 | 469 | emitter.Parameters[2] = ReadValueFloat("Height"); | 
 
 
 
 
 | 470 | emitter.Parameters[3] = ReadValueFloat("InnerRadius"); | 
 
 
 
 
 | 471 | emitter.Parameters[4] = ReadValueFloat("OuterRadius"); | 
 
 
 
 
 | 472 | break; | 
 
 
 
 
 | 473 | case EmitterPosition.BodySurface: | 
 
 
 
 
 | 474 | case EmitterPosition.BodyBones: | 
 
 
 
 
 | 475 | emitter.Parameters[2] = ReadValueFloat("OffsetRadius"); | 
 
 
 
 
 | 476 | break; | 
 
 
 
 
 | 477 | } | 
 
 
 
 
 | 478 |  | 
 
 
 
 
 | 479 | xml.ReadEndElement(); | 
 
 
 
 
 | 480 | } | 
 
 
 
 
 | 481 | } | 
 
 
 
 
 | 482 |  | 
 
 
 
 
 | 483 | private void ReadEmitterDirection(Emitter emitter) | 
 
 
 
 
 | 484 | { | 
 
 
 
 
 | 485 | emitter.Direction = MetaEnum.Parse<EmitterDirection>(xml.LocalName); | 
 
 
 
 
 | 486 |  | 
 
 
 
 
 | 487 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 488 | { | 
 
 
 
 
 | 489 | xml.ReadStartElement(); | 
 
 
 
 
 | 490 | } | 
 
 
 
 
 | 491 | else | 
 
 
 
 
 | 492 | { | 
 
 
 
 
 | 493 | xml.ReadStartElement(); | 
 
 
 
 
 | 494 |  | 
 
 
 
 
 | 495 | switch (emitter.Direction) | 
 
 
 
 
 | 496 | { | 
 
 
 
 
 | 497 | case EmitterDirection.Cone: | 
 
 
 
 
 | 498 | emitter.Parameters[5] = ReadValueFloat("Angle"); | 
 
 
 
 
 | 499 | emitter.Parameters[6] = ReadValueFloat("CenterBias"); | 
 
 
 
 
 | 500 | break; | 
 
 
 
 
 | 501 | case EmitterDirection.Ring: | 
 
 
 
 
 | 502 | emitter.Parameters[5] = ReadValueFloat("Angle"); | 
 
 
 
 
 | 503 | emitter.Parameters[6] = ReadValueFloat("Offset"); | 
 
 
 
 
 | 504 | break; | 
 
 
 
 
 | 505 | case EmitterDirection.Offset: | 
 
 
 
 
 | 506 | emitter.Parameters[5] = ReadValueFloat("X"); | 
 
 
 
 
 | 507 | emitter.Parameters[6] = ReadValueFloat("Y"); | 
 
 
 
 
 | 508 | emitter.Parameters[7] = ReadValueFloat("Z"); | 
 
 
 
 
 | 509 | break; | 
 
 
 
 
 | 510 | case EmitterDirection.Inaccurate: | 
 
 
 
 
 | 511 | emitter.Parameters[5] = ReadValueFloat("BaseAngle"); | 
 
 
 
 
 | 512 | emitter.Parameters[6] = ReadValueFloat("Inaccuracy"); | 
 
 
 
 
 | 513 | emitter.Parameters[7] = ReadValueFloat("CenterBias"); | 
 
 
 
 
 | 514 | break; | 
 
 
 
 
 | 515 | } | 
 
 
 
 
 | 516 |  | 
 
 
 
 
 | 517 | xml.ReadEndElement(); | 
 
 
 
 
 | 518 | } | 
 
 
 
 
 | 519 | } | 
 
 
 
 
 | 520 |  | 
 
 
 
 
 | 521 | private void ReadEmitterSpeed(Emitter emitter) | 
 
 
 
 
 | 522 | { | 
 
 
 
 
 | 523 | emitter.Speed = MetaEnum.Parse<EmitterSpeed>(xml.LocalName); | 
 
 
 
 
 | 524 |  | 
 
 
 
 
 | 525 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 526 | { | 
 
 
 
 
 | 527 | xml.ReadStartElement(); | 
 
 
 
 
 | 528 | } | 
 
 
 
 
 | 529 | else | 
 
 
 
 
 | 530 | { | 
 
 
 
 
 | 531 | xml.ReadStartElement(); | 
 
 
 
 
 | 532 |  | 
 
 
 
 
 | 533 | switch (emitter.Speed) | 
 
 
 
 
 | 534 | { | 
 
 
 
 
 | 535 | case EmitterSpeed.Uniform: | 
 
 
 
 
 | 536 | emitter.Parameters[8] = ReadValueFloat("Speed"); | 
 
 
 
 
 | 537 | break; | 
 
 
 
 
 | 538 | case EmitterSpeed.Stratified: | 
 
 
 
 
 | 539 | emitter.Parameters[8] = ReadValueFloat("Speed1"); | 
 
 
 
 
 | 540 | emitter.Parameters[9] = ReadValueFloat("Speed2"); | 
 
 
 
 
 | 541 | break; | 
 
 
 
 
 | 542 | } | 
 
 
 
 
 | 543 |  | 
 
 
 
 
 | 544 | xml.ReadEndElement(); | 
 
 
 
 
 | 545 | } | 
 
 
 
 
 | 546 | } | 
 
 
 
 
 | 547 |  | 
 
 
 
 
 | 548 | private void ReadEvents() | 
 
 
 
 
 | 549 | { | 
 
 
 
 
 | 550 | if (!xml.IsStartElement("Events")) | 
 
 
 
 
 | 551 | return; | 
 
 
 
 
 | 552 |  | 
 
 
 
 
 | 553 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 554 | { | 
 
 
 
 
 | 555 | xml.ReadStartElement(); | 
 
 
 
 
 | 556 | } | 
 
 
 
 
 | 557 | else | 
 
 
 
 
 | 558 | { | 
 
 
 
 
 | 559 | xml.ReadStartElement(); | 
 
 
 
 
 | 560 |  | 
 
 
 
 
 | 561 | while (xml.IsStartElement()) | 
 
 
 
 
 | 562 | ReadEvent(); | 
 
 
 
 
 | 563 |  | 
 
 
 
 
 | 564 | xml.ReadEndElement(); | 
 
 
 
 
 | 565 | } | 
 
 
 
 
 | 566 | } | 
 
 
 
 
 | 567 |  | 
 
 
 
 
 | 568 | private void ReadEvent() | 
 
 
 
 
 | 569 | { | 
 
 
 
 
 | 570 | Event e = new Event((EventType)Enum.Parse(typeof(EventType), xml.LocalName)); | 
 
 
 
 
 | 571 |  | 
 
 
 
 
 | 572 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 573 | { | 
 
 
 
 
 | 574 | xml.ReadStartElement(); | 
 
 
 
 
 | 575 | } | 
 
 
 
 
 | 576 | else | 
 
 
 
 
 | 577 | { | 
 
 
 
 
 | 578 | xml.ReadStartElement(); | 
 
 
 
 
 | 579 |  | 
 
 
 
 
 | 580 | while (xml.IsStartElement()) | 
 
 
 
 
 | 581 | e.Actions.Add(ReadEventAction()); | 
 
 
 
 
 | 582 |  | 
 
 
 
 
 | 583 | xml.ReadEndElement(); | 
 
 
 
 
 | 584 | } | 
 
 
 
 
 | 585 |  | 
 
 
 
 
 | 586 | particle.Events.Add(e); | 
 
 
 
 
 | 587 | } | 
 
 
 
 
 | 588 |  | 
 
 
 
 
 | 589 | private EventAction ReadEventAction() | 
 
 
 
 
 | 590 | { | 
 
 
 
 
 | 591 | EventAction action = new EventAction((EventActionType)Enum.Parse(typeof(EventActionType), xml.LocalName)); | 
 
 
 
 
 | 592 | EventActionInfo info = eventActionInfoTable[(int)action.Type]; | 
 
 
 
 
 | 593 |  | 
 
 
 
 
 | 594 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 595 | { | 
 
 
 
 
 | 596 | xml.ReadStartElement(); | 
 
 
 
 
 | 597 | } | 
 
 
 
 
 | 598 | else | 
 
 
 
 
 | 599 | { | 
 
 
 
 
 | 600 | xml.ReadStartElement(); | 
 
 
 
 
 | 601 |  | 
 
 
 
 
 | 602 | for (int i = 0; xml.IsStartElement(); i++) | 
 
 
 
 
 | 603 | { | 
 
 
 
 
 | 604 | if (i < info.OutCount) | 
 
 
 
 
 | 605 | { | 
 
 
 
 
 | 606 | action.Variables.Add(new VariableReference(xml.ReadElementContentAsString())); | 
 
 
 
 
 | 607 | continue; | 
 
 
 
 
 | 608 | } | 
 
 
 
 
 | 609 |  | 
 
 
 
 
 | 610 | if (i >= info.Parameters.Length) | 
 
 
 
 
 | 611 | throw new XmlException(string.Format("Too many arguments for action '{0}'", action.Type)); | 
 
 
 
 
 | 612 |  | 
 
 
 
 
 | 613 | switch (info.Parameters[i].Type) | 
 
 
 
 
 | 614 | { | 
 
 
 
 
 | 615 | case StorageType.Float: | 
 
 
 
 
 | 616 | case StorageType.BlastFalloff: | 
 
 
 
 
 | 617 | action.Parameters.Add(ReadValueFloat()); | 
 
 
 
 
 | 618 | continue; | 
 
 
 
 
 | 619 |  | 
 
 
 
 
 | 620 | case StorageType.Color: | 
 
 
 
 
 | 621 | action.Parameters.Add(ReadValueColor()); | 
 
 
 
 
 | 622 | continue; | 
 
 
 
 
 | 623 |  | 
 
 
 
 
 | 624 | case StorageType.ActionIndex: | 
 
 
 
 
 | 625 | case StorageType.Emitter: | 
 
 
 
 
 | 626 | case StorageType.CoordFrame: | 
 
 
 
 
 | 627 | case StorageType.CollisionOrient: | 
 
 
 
 
 | 628 | case StorageType.Boolean: | 
 
 
 
 
 | 629 | case StorageType.PingPongState: | 
 
 
 
 
 | 630 | case StorageType.ImpactModifier: | 
 
 
 
 
 | 631 | case StorageType.DamageType: | 
 
 
 
 
 | 632 | case StorageType.Direction: | 
 
 
 
 
 | 633 | action.Parameters.Add(ReadValueInt()); | 
 
 
 
 
 | 634 | continue; | 
 
 
 
 
 | 635 |  | 
 
 
 
 
 | 636 | case StorageType.ImpulseSoundName: | 
 
 
 
 
 | 637 | case StorageType.AmbientSoundName: | 
 
 
 
 
 | 638 | case StorageType.ImpactName: | 
 
 
 
 
 | 639 | action.Parameters.Add(ReadValueInstance()); | 
 
 
 
 
 | 640 | continue; | 
 
 
 
 
 | 641 | } | 
 
 
 
 
 | 642 | } | 
 
 
 
 
 | 643 |  | 
 
 
 
 
 | 644 | xml.ReadEndElement(); | 
 
 
 
 
 | 645 | } | 
 
 
 
 
 | 646 |  | 
 
 
 
 
 | 647 | return action; | 
 
 
 
 
 | 648 | } | 
 
 
 
 
 | 649 |  | 
 
 
 
 
 | 650 | private Value ReadValueInstance() | 
 
 
 
 
 | 651 | { | 
 
 
 
 
 | 652 | return new Value(ValueType.InstanceName, xml.ReadElementContentAsString()); | 
 
 
 
 
 | 653 | } | 
 
 
 
 
 | 654 |  | 
 
 
 
 
 | 655 | private Value ReadValueInt() | 
 
 
 
 
 | 656 | { | 
 
 
 
 
 | 657 | Value value = null; | 
 
 
 
 
 | 658 | xml.ReadStartElement(); | 
 
 
 
 
 | 659 |  | 
 
 
 
 
 | 660 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 661 | int i; | 
 
 
 
 
 | 662 |  | 
 
 
 
 
 | 663 | if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) | 
 
 
 
 
 | 664 | value = new Value(i); | 
 
 
 
 
 | 665 | else | 
 
 
 
 
 | 666 | value = new Value(ValueType.Variable, text.Trim()); | 
 
 
 
 
 | 667 |  | 
 
 
 
 
 | 668 | xml.ReadEndElement(); | 
 
 
 
 
 | 669 | return value; | 
 
 
 
 
 | 670 | } | 
 
 
 
 
 | 671 |  | 
 
 
 
 
 | 672 | private Value ReadValueFloat(string name) | 
 
 
 
 
 | 673 | { | 
 
 
 
 
 | 674 | if (xml.LocalName != name) | 
 
 
 
 
 | 675 | throw new XmlException(string.Format(CultureInfo.CurrentCulture, "Unexpected '{0}' element found at line {1}", xml.LocalName, 0)); | 
 
 
 
 
 | 676 |  | 
 
 
 
 
 | 677 | return ReadValueFloat(); | 
 
 
 
 
 | 678 | } | 
 
 
 
 
 | 679 |  | 
 
 
 
 
 | 680 | private Value ReadValueFloat() | 
 
 
 
 
 | 681 | { | 
 
 
 
 
 | 682 | if (xml.IsEmptyElement) | 
 
 
 
 
 | 683 | { | 
 
 
 
 
 | 684 | xml.Read(); | 
 
 
 
 
 | 685 | return new Value(0.0f); | 
 
 
 
 
 | 686 | } | 
 
 
 
 
 | 687 |  | 
 
 
 
 
 | 688 | Value value = null; | 
 
 
 
 
 | 689 |  | 
 
 
 
 
 | 690 | xml.ReadStartElement(); | 
 
 
 
 
 | 691 |  | 
 
 
 
 
 | 692 | if (xml.NodeType == XmlNodeType.Text) | 
 
 
 
 
 | 693 | { | 
 
 
 
 
 | 694 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 695 | float f; | 
 
 
 
 
 | 696 |  | 
 
 
 
 
 | 697 | if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out f)) | 
 
 
 
 
 | 698 | value = new Value(f); | 
 
 
 
 
 | 699 | else | 
 
 
 
 
 | 700 | value = new Value(ValueType.Variable, text.Trim()); | 
 
 
 
 
 | 701 | } | 
 
 
 
 
 | 702 | else if (xml.NodeType == XmlNodeType.Element) | 
 
 
 
 
 | 703 | { | 
 
 
 
 
 | 704 | string name = xml.LocalName; | 
 
 
 
 
 | 705 |  | 
 
 
 
 
 | 706 | if (name == "Random") | 
 
 
 
 
 | 707 | { | 
 
 
 
 
 | 708 | float min = float.Parse(xml.GetAttribute("Min"), CultureInfo.InvariantCulture); | 
 
 
 
 
 | 709 | float max = float.Parse(xml.GetAttribute("Max"), CultureInfo.InvariantCulture); | 
 
 
 
 
 | 710 | value = new Value(ValueType.FloatRandom, min, max); | 
 
 
 
 
 | 711 | } | 
 
 
 
 
 | 712 | else if (name == "BellCurve") | 
 
 
 
 
 | 713 | { | 
 
 
 
 
 | 714 | float mean = float.Parse(xml.GetAttribute("Mean"), CultureInfo.InvariantCulture); | 
 
 
 
 
 | 715 | float stddev = float.Parse(xml.GetAttribute("StdDev"), CultureInfo.InvariantCulture); | 
 
 
 
 
 | 716 | value = new Value(ValueType.FloatBellCurve, mean, stddev); | 
 
 
 
 
 | 717 | } | 
 
 
 
 
 | 718 | else | 
 
 
 
 
 | 719 | { | 
 
 
 
 
 | 720 | throw new XmlException(string.Format(CultureInfo.CurrentCulture, "Unknown value type '{0}'", name)); | 
 
 
 
 
 | 721 | } | 
 
 
 
 
 | 722 |  | 
 
 
 
 
 | 723 | xml.ReadStartElement(); | 
 
 
 
 
 | 724 | } | 
 
 
 
 
 | 725 |  | 
 
 
 
 
 | 726 | xml.ReadEndElement(); | 
 
 
 
 
 | 727 | return value; | 
 
 
 
 
 | 728 | } | 
 
 
 
 
 | 729 |  | 
 
 
 
 
 | 730 | private Value ReadValueColor() | 
 
 
 
 
 | 731 | { | 
 
 
 
 
 | 732 | Value value = null; | 
 
 
 
 
 | 733 |  | 
 
 
 
 
 | 734 | xml.ReadStartElement(); | 
 
 
 
 
 | 735 |  | 
 
 
 
 
 | 736 | if (xml.NodeType == XmlNodeType.Text) | 
 
 
 
 
 | 737 | { | 
 
 
 
 
 | 738 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 739 | Color c; | 
 
 
 
 
 | 740 |  | 
 
 
 
 
 | 741 | if (Color.TryParse(text, out c)) | 
 
 
 
 
 | 742 | value = new Value(c); | 
 
 
 
 
 | 743 | else | 
 
 
 
 
 | 744 | value = new Value(ValueType.Variable, text.Trim()); | 
 
 
 
 
 | 745 | } | 
 
 
 
 
 | 746 | else if (xml.NodeType == XmlNodeType.Element) | 
 
 
 
 
 | 747 | { | 
 
 
 
 
 | 748 | string name = xml.LocalName; | 
 
 
 
 
 | 749 |  | 
 
 
 
 
 | 750 | if (name == "Random") | 
 
 
 
 
 | 751 | { | 
 
 
 
 
 | 752 | Color min = Color.Parse(xml.GetAttribute("Min")); | 
 
 
 
 
 | 753 | Color max = Color.Parse(xml.GetAttribute("Max")); | 
 
 
 
 
 | 754 | value = new Value(ValueType.ColorRandom, min, max); | 
 
 
 
 
 | 755 | } | 
 
 
 
 
 | 756 | else if (name == "BellCurve") | 
 
 
 
 
 | 757 | { | 
 
 
 
 
 | 758 | Color mean = Color.Parse(xml.GetAttribute("Mean")); | 
 
 
 
 
 | 759 | Color stddev = Color.Parse(xml.GetAttribute("StdDev")); | 
 
 
 
 
 | 760 | value = new Value(ValueType.ColorBellCurve, mean, stddev); | 
 
 
 
 
 | 761 | } | 
 
 
 
 
 | 762 | else | 
 
 
 
 
 | 763 | { | 
 
 
 
 
 | 764 | throw new XmlException(string.Format(CultureInfo.CurrentCulture, "Unknown value type '{0}'", name)); | 
 
 
 
 
 | 765 | } | 
 
 
 
 
 | 766 |  | 
 
 
 
 
 | 767 | xml.ReadStartElement(); | 
 
 
 
 
 | 768 | } | 
 
 
 
 
 | 769 |  | 
 
 
 
 
 | 770 | xml.ReadEndElement(); | 
 
 
 
 
 | 771 | return value; | 
 
 
 
 
 | 772 | } | 
 
 
 
 
 | 773 |  | 
 
 
 
 
 | 774 | private bool ReadFlag1() | 
 
 
 
 
 | 775 | { | 
 
 
 
 
 | 776 | ParticleFlags1 flag; | 
 
 
 
 
 | 777 |  | 
 
 
 
 
 | 778 | try | 
 
 
 
 
 | 779 | { | 
 
 
 
 
 | 780 | flag = (ParticleFlags1)Enum.Parse(typeof(ParticleFlags1), xml.LocalName); | 
 
 
 
 
 | 781 | } | 
 
 
 
 
 | 782 | catch | 
 
 
 
 
 | 783 | { | 
 
 
 
 
 | 784 | return false; | 
 
 
 
 
 | 785 | } | 
 
 
 
 
 | 786 |  | 
 
 
 
 
 | 787 | if (ReadFlagValue()) | 
 
 
 
 
 | 788 | particle.Flags1 |= flag; | 
 
 
 
 
 | 789 |  | 
 
 
 
 
 | 790 | return true; | 
 
 
 
 
 | 791 | } | 
 
 
 
 
 | 792 |  | 
 
 
 
 
 | 793 | private bool ReadFlag2() | 
 
 
 
 
 | 794 | { | 
 
 
 
 
 | 795 | ParticleFlags2 flag; | 
 
 
 
 
 | 796 |  | 
 
 
 
 
 | 797 | try | 
 
 
 
 
 | 798 | { | 
 
 
 
 
 | 799 | flag = (ParticleFlags2)Enum.Parse(typeof(ParticleFlags2), xml.LocalName); | 
 
 
 
 
 | 800 | } | 
 
 
 
 
 | 801 | catch | 
 
 
 
 
 | 802 | { | 
 
 
 
 
 | 803 | return false; | 
 
 
 
 
 | 804 | } | 
 
 
 
 
 | 805 |  | 
 
 
 
 
 | 806 | if (ReadFlagValue()) | 
 
 
 
 
 | 807 | particle.Flags2 |= flag; | 
 
 
 
 
 | 808 |  | 
 
 
 
 
 | 809 | return true; | 
 
 
 
 
 | 810 | } | 
 
 
 
 
 | 811 |  | 
 
 
 
 
 | 812 | private bool ReadFlagValue() | 
 
 
 
 
 | 813 | { | 
 
 
 
 
 | 814 | string text = xml.ReadElementContentAsString(); | 
 
 
 
 
 | 815 |  | 
 
 
 
 
 | 816 | switch (text) | 
 
 
 
 
 | 817 | { | 
 
 
 
 
 | 818 | case "false": | 
 
 
 
 
 | 819 | return false; | 
 
 
 
 
 | 820 | case "true": | 
 
 
 
 
 | 821 | return true; | 
 
 
 
 
 | 822 | default: | 
 
 
 
 
 | 823 | throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Unknown value '{0}'", text)); | 
 
 
 
 
 | 824 | } | 
 
 
 
 
 | 825 | } | 
 
 
 
 
 | 826 | } | 
 
 
 
 
 | 827 | } |