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 |
} |