1 using System;
2 using System.Collections.Generic;
3 using System.Collections.ObjectModel;
4 using System.Globalization;
5 using System.Linq;
6 using OpenTK;
7 using Prism.Mvvm;
8 using TrainEditor2.Extensions;
9 using TrainEditor2.Models.Dialogs;
10 using TrainEditor2.Models.Others;
11 using TrainManager.Motor;
12 
13 namespace TrainEditor2.Models.Trains
14 {
15 	internal partial class Motor : BindableBase, ICloneable
16 	{
17 		internal class Vertex : BindableBase, ICloneable
18 		{
19 			private double x;
20 			private double y;
21 			private bool selected;
22 			private bool isOrigin;
23 
24 			internal double X
25 			{
26 				get
27 				{
28 					return x;
29 				}
30 				set
31 				{
32 					SetProperty(ref x, value);
33 				}
34 			}
35 
36 			internal double Y
37 			{
38 				get
39 				{
40 					return y;
41 				}
42 				set
43 				{
44 					SetProperty(ref y, value);
45 				}
46 			}
47 
48 			internal bool Selected
49 			{
50 				get
51 				{
52 					return selected;
53 				}
54 				set
55 				{
56 					SetProperty(ref selected, value);
57 				}
58 			}
59 
60 			internal bool IsOrigin
61 			{
62 				get
63 				{
64 					return isOrigin;
65 				}
66 				set
67 				{
68 					SetProperty(ref isOrigin, value);
69 				}
70 			}
71 
Vertex(double x, double y)72 			internal Vertex(double x, double y)
73 			{
74 				X = x;
75 				Y = y;
76 				Selected = false;
77 				IsOrigin = false;
78 			}
79 
Clone()80 			public object Clone()
81 			{
82 				return MemberwiseClone();
83 			}
84 		}
85 
86 		internal class Line : BindableBase, ICloneable
87 		{
88 			private int leftID;
89 			private int rightID;
90 			private bool selected;
91 
92 			internal int LeftID
93 			{
94 				get
95 				{
96 					return leftID;
97 				}
98 				private set
99 				{
100 					SetProperty(ref leftID, value);
101 				}
102 			}
103 
104 			internal int RightID
105 			{
106 				get
107 				{
108 					return rightID;
109 				}
110 				private set
111 				{
112 					SetProperty(ref rightID, value);
113 				}
114 			}
115 
116 			internal bool Selected
117 			{
118 				get
119 				{
120 					return selected;
121 				}
122 				set
123 				{
124 					SetProperty(ref selected, value);
125 				}
126 			}
127 
Line(int leftID, int rightID)128 			internal Line(int leftID, int rightID)
129 			{
130 				LeftID = leftID;
131 				RightID = rightID;
132 				Selected = false;
133 			}
134 
Clone()135 			public object Clone()
136 			{
137 				return MemberwiseClone();
138 			}
139 		}
140 
141 		internal class Area : BindableBase, ICloneable
142 		{
143 			private double leftX;
144 			private double rightX;
145 			private int index;
146 			private bool tbd;
147 
148 			internal double LeftX
149 			{
150 				get
151 				{
152 					return leftX;
153 				}
154 				set
155 				{
156 					SetProperty(ref leftX, value);
157 				}
158 			}
159 
160 			internal double RightX
161 			{
162 				get
163 				{
164 					return rightX;
165 				}
166 				set
167 				{
168 					SetProperty(ref rightX, value);
169 				}
170 			}
171 
172 			internal int Index
173 			{
174 				get
175 				{
176 					return index;
177 				}
178 				private set
179 				{
180 					SetProperty(ref index, value);
181 				}
182 			}
183 
184 			internal bool TBD
185 			{
186 				get
187 				{
188 					return tbd;
189 				}
190 				set
191 				{
192 					SetProperty(ref tbd, value);
193 				}
194 			}
195 
Area(double leftX, double rightX, int index)196 			internal Area(double leftX, double rightX, int index)
197 			{
198 				LeftX = leftX;
199 				RightX = rightX;
200 				Index = index;
201 				TBD = false;
202 			}
203 
Clone()204 			public object Clone()
205 			{
206 				return MemberwiseClone();
207 			}
208 		}
209 
210 		internal class VertexLibrary : ObservableDictionary<int, Vertex>, ICloneable
211 		{
212 			private int lastID;
213 
VertexLibrary()214 			internal VertexLibrary()
215 			{
216 				lastID = -1;
217 			}
218 
Add(Vertex vertex)219 			internal void Add(Vertex vertex)
220 			{
221 				if (this.Any(v => v.Value.X == vertex.X))
222 				{
223 					int id = this.First(v => v.Value.X == vertex.X).Key;
224 					base[id] = vertex;
225 				}
226 				else
227 				{
228 					Add(++lastID, vertex);
229 				}
230 			}
231 
Clone()232 			public object Clone()
233 			{
234 				VertexLibrary vertices = new VertexLibrary
235 				{
236 					lastID = lastID
237 				};
238 
239 				foreach (KeyValuePair<int, Vertex> vertex in this)
240 				{
241 					vertices.Add(vertex.Key, (Vertex)vertex.Value.Clone());
242 				}
243 
244 				return vertices;
245 			}
246 		}
247 
248 		internal class Track : ICloneable
249 		{
250 			internal VertexLibrary PitchVertices;
251 			internal ObservableCollection<Line> PitchLines;
252 
253 			internal VertexLibrary VolumeVertices;
254 			internal ObservableCollection<Line> VolumeLines;
255 
256 			internal ObservableCollection<Area> SoundIndices;
257 
Track()258 			internal Track()
259 			{
260 				PitchVertices = new VertexLibrary();
261 				PitchLines = new ObservableCollection<Line>();
262 
263 				VolumeVertices = new VertexLibrary();
264 				VolumeLines = new ObservableCollection<Line>();
265 
266 				SoundIndices = new ObservableCollection<Area>();
267 			}
268 
Clone()269 			public object Clone()
270 			{
271 				Track track = (Track)MemberwiseClone();
272 
273 				track.PitchVertices = (VertexLibrary)PitchVertices.Clone();
274 				track.PitchLines = new ObservableCollection<Line>(PitchLines.Select(l => (Line)l.Clone()));
275 
276 				track.VolumeVertices = (VertexLibrary)VolumeVertices.Clone();
277 				track.VolumeLines = new ObservableCollection<Line>(VolumeLines.Select(l => (Line)l.Clone()));
278 
279 				track.SoundIndices = new ObservableCollection<Area>(SoundIndices.Select(a => (Area)a.Clone()));
280 
281 				return track;
282 			}
283 
EntriesToTrack(BVEMotorSoundTableEntry[] entries)284 			internal static Track EntriesToTrack(BVEMotorSoundTableEntry[] entries)
285 			{
286 				Track track = new Track();
287 
288 				for (int i = 0; i < entries.Length; i++)
289 				{
290 					double velocity = 0.2 * i;
291 
292 					if (track.PitchVertices.Count >= 2)
293 					{
294 						KeyValuePair<int, Vertex>[] leftVertices = new KeyValuePair<int, Vertex>[] { track.PitchVertices.ElementAt(track.PitchVertices.Count - 2), track.PitchVertices.Last() };
295 						Func<double, double> f = x => leftVertices[0].Value.Y + (leftVertices[1].Value.Y - leftVertices[0].Value.Y) / (leftVertices[1].Value.X - leftVertices[0].Value.X) * (x - leftVertices[0].Value.X);
296 
297 						if (f(velocity) == entries[i].Pitch)
298 						{
299 							track.PitchVertices.Remove(leftVertices[1].Key);
300 						}
301 					}
302 
303 					track.PitchVertices.Add(new Vertex(velocity, 0.01 * Math.Round(100.0 * entries[i].Pitch)));
304 
305 					if (track.VolumeVertices.Count >= 2)
306 					{
307 						KeyValuePair<int, Vertex>[] leftVertices = new KeyValuePair<int, Vertex>[] { track.VolumeVertices.ElementAt(track.VolumeVertices.Count - 2), track.VolumeVertices.Last() };
308 						Func<double, double> f = x => leftVertices[0].Value.Y + (leftVertices[1].Value.Y - leftVertices[0].Value.Y) / (leftVertices[1].Value.X - leftVertices[0].Value.X) * (x - leftVertices[0].Value.X);
309 
310 						if (f(velocity) == entries[i].Gain)
311 						{
312 							track.VolumeVertices.Remove(leftVertices[1].Key);
313 						}
314 					}
315 
316 					track.VolumeVertices.Add(new Vertex(velocity, 0.01 * Math.Round(100.0 * entries[i].Gain)));
317 
318 					if (track.SoundIndices.Any())
319 					{
320 						Area leftArea = track.SoundIndices.Last();
321 
322 						if (entries[i].SoundIndex != leftArea.Index)
323 						{
324 							leftArea.RightX = velocity - 0.2;
325 							track.SoundIndices.Add(new Area(velocity, velocity, entries[i].SoundIndex));
326 						}
327 						else
328 						{
329 							leftArea.RightX = velocity;
330 						}
331 					}
332 					else
333 					{
334 						track.SoundIndices.Add(new Area(velocity, velocity, entries[i].SoundIndex));
335 					}
336 				}
337 
338 				for (int j = 0; j < track.PitchVertices.Count - 1; j++)
339 				{
340 					track.PitchLines.Add(new Line(track.PitchVertices.ElementAt(j).Key, track.PitchVertices.ElementAt(j + 1).Key));
341 				}
342 
343 				for (int j = 0; j < track.VolumeVertices.Count - 1; j++)
344 				{
345 					track.VolumeLines.Add(new Line(track.VolumeVertices.ElementAt(j).Key, track.VolumeVertices.ElementAt(j + 1).Key));
346 				}
347 
348 				if (track.SoundIndices.Any())
349 				{
350 					Area lastArea = track.SoundIndices.Last();
351 
352 					if (lastArea.LeftX == lastArea.RightX)
353 					{
354 						lastArea.RightX += 0.2;
355 					}
356 				}
357 
358 				return track;
359 			}
360 
TrackToEntries(Track track)361 			internal static BVEMotorSoundTableEntry[] TrackToEntries(Track track)
362 			{
363 				int n = 0;
364 
365 				if (track.PitchVertices.Any())
366 				{
367 					n = Math.Max(n, (int)Math.Round(5.0 * track.PitchVertices.Last().Value.X));
368 				}
369 
370 				if (track.VolumeVertices.Any())
371 				{
372 					n = Math.Max(n, (int)Math.Round(5.0 * track.VolumeVertices.Last().Value.X));
373 				}
374 
375 				BVEMotorSoundTableEntry[] entries = Enumerable.Repeat(new BVEMotorSoundTableEntry { SoundIndex = -1, Pitch = 100.0f, Gain = 128.0f }, n + 1).ToArray();
376 
377 				for (int i = 0; i < entries.Length; i++)
378 				{
379 					double velocity = 0.2 * i;
380 
381 					Line pitchLine = track.PitchLines.FirstOrDefault(l => track.PitchVertices[l.LeftID].X <= velocity && track.PitchVertices[l.RightID].X >= velocity);
382 
383 					if (pitchLine != null)
384 					{
385 						Vertex left = track.PitchVertices[pitchLine.LeftID];
386 						Vertex right = track.PitchVertices[pitchLine.RightID];
387 
388 						Func<double, double> f = x => left.Y + (right.Y - left.Y) / (right.X - left.X) * (x - left.X);
389 
390 						entries[i].Pitch = (float)(0.01 * Math.Round(100.0 * Math.Max(f(velocity), 0.0)));
391 					}
392 
393 					Line volumeLine = track.VolumeLines.FirstOrDefault(l => track.VolumeVertices[l.LeftID].X <= velocity && track.VolumeVertices[l.RightID].X >= velocity);
394 
395 					if (volumeLine != null)
396 					{
397 						Vertex left = track.VolumeVertices[volumeLine.LeftID];
398 						Vertex right = track.VolumeVertices[volumeLine.RightID];
399 
400 						Func<double, double> f = x => left.Y + (right.Y - left.Y) / (right.X - left.X) * (x - left.X);
401 
402 						entries[i].Gain = (float)(0.01 * Math.Round(100.0 * Math.Max(f(velocity), 0.0)));
403 					}
404 
405 					Area area = track.SoundIndices.FirstOrDefault(a => a.LeftX <= velocity && a.RightX >= velocity);
406 
407 					if (area != null)
408 					{
409 						entries[i].SoundIndex = area.Index;
410 					}
411 				}
412 
413 				return entries;
414 			}
415 
EntriesToMotorSoundTable(BVEMotorSoundTableEntry[] entries)416 			internal static BVEMotorSoundTable EntriesToMotorSoundTable(BVEMotorSoundTableEntry[] entries)
417 			{
418 				BVEMotorSoundTable table = new BVEMotorSoundTable
419 				{
420 					Entries = new BVEMotorSoundTableEntry[entries.Length]
421 				};
422 
423 				for (int i = 0; i < entries.Length; i++)
424 				{
425 					table.Entries[i].Pitch = (float)(0.01 * entries[i].Pitch);
426 					table.Entries[i].Gain = (float)Math.Pow(0.0078125 * entries[i].Gain, 0.25);
427 					table.Entries[i].SoundIndex = entries[i].SoundIndex;
428 				}
429 
430 				return table;
431 			}
432 		}
433 
434 		internal enum TrackInfo
435 		{
436 			Power1,
437 			Power2,
438 			Brake1,
439 			Brake2
440 		}
441 
442 		internal enum InputMode
443 		{
444 			Pitch,
445 			Volume,
446 			SoundIndex
447 		}
448 
449 		internal enum ToolMode
450 		{
451 			Select,
452 			Move,
453 			Dot,
454 			Line
455 		}
456 
457 		internal enum SimulationState
458 		{
459 			Disable,
460 			Stopped,
461 			Paused,
462 			Started
463 		}
464 
465 		internal class TrackState : ICloneable
466 		{
467 			internal TrackInfo Info
468 			{
469 				get;
470 				private set;
471 			}
472 
473 			internal Track Track
474 			{
475 				get;
476 				private set;
477 			}
478 
TrackState(TrackInfo info, Track track)479 			internal TrackState(TrackInfo info, Track track)
480 			{
481 				Info = info;
482 				Track = track;
483 			}
484 
Clone()485 			public object Clone()
486 			{
487 				TrackState state = (TrackState)MemberwiseClone();
488 				state.Track = (Track)Track.Clone();
489 				return state;
490 			}
491 		}
492 
493 		internal class SelectedRange
494 		{
495 			internal Box2d Range
496 			{
497 				get;
498 				private set;
499 			}
500 
501 			internal Vertex[] SelectedVertices
502 			{
503 				get;
504 				private set;
505 			}
506 
507 			internal Line[] SelectedLines
508 			{
509 				get;
510 				private set;
511 			}
512 
SelectedRange(Box2d range, Vertex[] selectedVertices, Line[] selectedLines)513 			private SelectedRange(Box2d range, Vertex[] selectedVertices, Line[] selectedLines)
514 			{
515 				Range = range;
516 				SelectedVertices = selectedVertices;
517 				SelectedLines = selectedLines;
518 			}
519 
CreateSelectedRange(VertexLibrary vertices, ObservableCollection<Line> lines, double leftX, double rightX, double topY, double bottomY)520 			internal static SelectedRange CreateSelectedRange(VertexLibrary vertices, ObservableCollection<Line> lines, double leftX, double rightX, double topY, double bottomY)
521 			{
522 				Func<Vertex, bool> conditionVertex = v => v.X >= leftX && v.X <= rightX && v.Y >= bottomY && v.Y <= topY;
523 
524 				Vertex[] selectedVertices = vertices.Values.Where(v => conditionVertex(v)).ToArray();
525 				Line[] selectedLines = lines.Where(l => selectedVertices.Any(v => v.X == vertices[l.LeftID].X) && selectedVertices.Any(v => v.X == vertices[l.RightID].X)).ToArray();
526 
527 				return new SelectedRange(new Box2d(leftX, topY, rightX, bottomY), selectedVertices, selectedLines);
528 			}
529 		}
530 
531 		private readonly CultureInfo culture;
532 
533 		private MessageBox messageBox;
534 		private ToolTipModel toolTipVertexPitch;
535 		private ToolTipModel toolTipVertexVolume;
536 		private InputEventModel.ModifierKeys currentModifierKeys;
537 		private InputEventModel.CursorType currentCursorType;
538 
539 		private TrackInfo selectedTrackInfo;
540 		private int selectedSoundIndex;
541 		private Track copyTrack;
542 		private double minVelocity;
543 		private double maxVelocity;
544 		private double minPitch;
545 		private double maxPitch;
546 		private double minVolume;
547 		private double maxVolume;
548 		private double nowVelocity;
549 		private double nowPitch;
550 		private double nowVolume;
551 
552 		private InputMode currentInputMode;
553 		private ToolMode currentToolMode;
554 		private SimulationState currentSimState;
555 
556 		private double lastMousePosX;
557 		private double lastMousePosY;
558 
559 		private bool isMoving;
560 		private Area previewArea;
561 		private SelectedRange selectedRange;
562 		private Vertex hoveredVertexPitch;
563 		private Vertex hoveredVertexVolume;
564 
565 		private int runIndex;
566 		private bool isPlayTrack1;
567 		private bool isPlayTrack2;
568 		private bool isLoop;
569 		private bool isConstant;
570 		private double acceleration;
571 		private double startSpeed;
572 		private double endSpeed;
573 
574 		private DateTime startTime;
575 		private double oldElapsedTime;
576 		private double nowSpeed;
577 
578 		private int glControlWidth;
579 		private int glControlHeight;
580 		private bool isRefreshGlControl;
581 
582 		internal ObservableCollection<Track> Tracks;
583 		internal ObservableCollection<TrackState> PrevTrackStates;
584 		internal ObservableCollection<TrackState> NextTrackStates;
585 
586 		internal MessageBox MessageBox
587 		{
588 			get
589 			{
590 				return messageBox;
591 			}
592 			set
593 			{
594 				SetProperty(ref messageBox, value);
595 			}
596 		}
597 
598 		internal ToolTipModel ToolTipVertexPitch
599 		{
600 			get
601 			{
602 				return toolTipVertexPitch;
603 			}
604 			set
605 			{
606 				SetProperty(ref toolTipVertexPitch, value);
607 			}
608 		}
609 
610 		internal ToolTipModel ToolTipVertexVolume
611 		{
612 			get
613 			{
614 				return toolTipVertexVolume;
615 			}
616 			set
617 			{
618 				SetProperty(ref toolTipVertexVolume, value);
619 			}
620 		}
621 
622 		internal InputEventModel.ModifierKeys CurrentModifierKeys
623 		{
624 			get
625 			{
626 				return currentModifierKeys;
627 			}
628 			set
629 			{
630 				SetProperty(ref currentModifierKeys, value);
631 			}
632 		}
633 
634 		internal InputEventModel.CursorType CurrentCursorType
635 		{
636 			get
637 			{
638 				return currentCursorType;
639 			}
640 			set
641 			{
642 				SetProperty(ref currentCursorType, value);
643 			}
644 		}
645 
646 		internal TrackInfo SelectedTrackInfo
647 		{
648 			get
649 			{
650 				return selectedTrackInfo;
651 			}
652 			set
653 			{
654 				SetProperty(ref selectedTrackInfo, value);
655 			}
656 		}
657 
658 		internal Track SelectedTrack
659 		{
660 			get
661 			{
662 				return Tracks[(int)SelectedTrackInfo];
663 			}
664 			set
665 			{
666 				Tracks[(int)SelectedTrackInfo] = value;
667 			}
668 		}
669 
670 		internal int SelectedSoundIndex
671 		{
672 			get
673 			{
674 				return selectedSoundIndex;
675 			}
676 			set
677 			{
678 				SetProperty(ref selectedSoundIndex, value);
679 			}
680 		}
681 
682 		internal Track CopyTrack
683 		{
684 			get
685 			{
686 				return copyTrack;
687 			}
688 			set
689 			{
690 				SetProperty(ref copyTrack, value);
691 			}
692 		}
693 
694 		internal double MinVelocity
695 		{
696 			get
697 			{
698 				return minVelocity;
699 			}
700 			set
701 			{
702 				SetProperty(ref minVelocity, value);
703 			}
704 		}
705 
706 		internal double MaxVelocity
707 		{
708 			get
709 			{
710 				return maxVelocity;
711 			}
712 			set
713 			{
714 				SetProperty(ref maxVelocity, value);
715 			}
716 		}
717 
718 		internal double MinPitch
719 		{
720 			get
721 			{
722 				return minPitch;
723 			}
724 			set
725 			{
726 				SetProperty(ref minPitch, value);
727 			}
728 		}
729 
730 		internal double MaxPitch
731 		{
732 			get
733 			{
734 				return maxPitch;
735 			}
736 			set
737 			{
738 				SetProperty(ref maxPitch, value);
739 			}
740 		}
741 
742 		internal double MinVolume
743 		{
744 			get
745 			{
746 				return minVolume;
747 			}
748 			set
749 			{
750 				SetProperty(ref minVolume, value);
751 			}
752 		}
753 
754 		internal double MaxVolume
755 		{
756 			get
757 			{
758 				return maxVolume;
759 			}
760 			set
761 			{
762 				SetProperty(ref maxVolume, value);
763 			}
764 		}
765 
766 		internal double NowVelocity
767 		{
768 			get
769 			{
770 				return nowVelocity;
771 			}
772 			set
773 			{
774 				SetProperty(ref nowVelocity, value);
775 			}
776 		}
777 
778 		internal double NowPitch
779 		{
780 			get
781 			{
782 				return nowPitch;
783 			}
784 			set
785 			{
786 				SetProperty(ref nowPitch, value);
787 			}
788 		}
789 
790 		internal double NowVolume
791 		{
792 			get
793 			{
794 				return nowVolume;
795 			}
796 			set
797 			{
798 				SetProperty(ref nowVolume, value);
799 			}
800 		}
801 
802 		internal InputMode CurrentInputMode
803 		{
804 			get
805 			{
806 				return currentInputMode;
807 			}
808 			set
809 			{
810 				SetProperty(ref currentInputMode, value);
811 			}
812 		}
813 
814 		internal ToolMode CurrentToolMode
815 		{
816 			get
817 			{
818 				return currentToolMode;
819 			}
820 			set
821 			{
822 				SetProperty(ref currentToolMode, value);
823 			}
824 		}
825 
826 		internal SimulationState CurrentSimState
827 		{
828 			get
829 			{
830 				return currentSimState;
831 			}
832 			set
833 			{
834 				SetProperty(ref currentSimState, value);
835 			}
836 		}
837 
838 		internal int RunIndex
839 		{
840 			get
841 			{
842 				return runIndex;
843 			}
844 			set
845 			{
846 				SetProperty(ref runIndex, value);
847 			}
848 		}
849 
850 		internal bool IsPlayTrack1
851 		{
852 			get
853 			{
854 				return isPlayTrack1;
855 			}
856 			set
857 			{
858 				SetProperty(ref isPlayTrack1, value);
859 			}
860 		}
861 
862 		internal bool IsPlayTrack2
863 		{
864 			get
865 			{
866 				return isPlayTrack2;
867 			}
868 			set
869 			{
870 				SetProperty(ref isPlayTrack2, value);
871 			}
872 		}
873 
874 		internal bool IsLoop
875 		{
876 			get
877 			{
878 				return isLoop;
879 			}
880 			set
881 			{
882 				SetProperty(ref isLoop, value);
883 			}
884 		}
885 
886 		internal bool IsConstant
887 		{
888 			get
889 			{
890 				return isConstant;
891 			}
892 			set
893 			{
894 				SetProperty(ref isConstant, value);
895 			}
896 		}
897 
898 		internal double Acceleration
899 		{
900 			get
901 			{
902 				return acceleration;
903 			}
904 			set
905 			{
906 				SetProperty(ref acceleration, value);
907 			}
908 		}
909 
910 		internal double StartSpeed
911 		{
912 			get
913 			{
914 				return startSpeed;
915 			}
916 			set
917 			{
918 				SetProperty(ref startSpeed, value);
919 			}
920 		}
921 
922 		internal double EndSpeed
923 		{
924 			get
925 			{
926 				return endSpeed;
927 			}
928 			set
929 			{
930 				SetProperty(ref endSpeed, value);
931 			}
932 		}
933 
934 		internal int GlControlWidth
935 		{
936 			get
937 			{
938 				return glControlWidth;
939 			}
940 			set
941 			{
942 				SetProperty(ref glControlWidth, value);
943 			}
944 		}
945 
946 		internal int GlControlHeight
947 		{
948 			get
949 			{
950 				return glControlHeight;
951 			}
952 			set
953 			{
954 				SetProperty(ref glControlHeight, value);
955 			}
956 		}
957 
958 		internal bool IsRefreshGlControl
959 		{
960 			get
961 			{
962 				return isRefreshGlControl;
963 			}
964 			set
965 			{
966 				SetProperty(ref isRefreshGlControl, value);
967 			}
968 		}
969 
Motor()970 		internal Motor()
971 		{
972 			culture = CultureInfo.InvariantCulture;
973 
974 			MessageBox = new MessageBox();
975 			ToolTipVertexPitch = new ToolTipModel();
976 			ToolTipVertexVolume = new ToolTipModel();
977 			CurrentCursorType = InputEventModel.CursorType.Arrow;
978 
979 			Tracks = new ObservableCollection<Track>();
980 
981 			for (int i = 0; i < 4; i++)
982 			{
983 				Tracks.Add(new Track());
984 			}
985 
986 			SelectedTrackInfo = TrackInfo.Power1;
987 			SelectedSoundIndex = -1;
988 
989 			PrevTrackStates = new ObservableCollection<TrackState>();
990 			NextTrackStates = new ObservableCollection<TrackState>();
991 
992 			MinVelocity = 0.0;
993 			MaxVelocity = 40.0;
994 
995 			MinPitch = 0.0;
996 			MaxPitch = 400.0;
997 
998 			MinVolume = 0.0;
999 			MaxVolume = 256.0;
1000 
1001 			CurrentSimState = SimulationState.Stopped;
1002 			RunIndex = -1;
1003 			IsPlayTrack1 = IsPlayTrack2 = true;
1004 			Acceleration = 2.6;
1005 			StartSpeed = 0.0;
1006 			EndSpeed = 160.0;
1007 
1008 			GlControlWidth = 568;
1009 			GlControlHeight = 593;
1010 		}
1011 
Clone()1012 		public object Clone()
1013 		{
1014 			Motor motor = (Motor)MemberwiseClone();
1015 			motor.MessageBox = new MessageBox();
1016 			ToolTipVertexPitch = new ToolTipModel();
1017 			ToolTipVertexVolume = new ToolTipModel();
1018 			motor.previewArea = null;
1019 			motor.selectedRange = null;
1020 			motor.Tracks = new ObservableCollection<Track>(Tracks.Select(x => (Track)x.Clone()));
1021 			motor.PrevTrackStates = new ObservableCollection<TrackState>(PrevTrackStates.Select(x => (TrackState)x.Clone()));
1022 			motor.NextTrackStates = new ObservableCollection<TrackState>(NextTrackStates.Select(x => (TrackState)x.Clone()));
1023 			return motor;
1024 		}
1025 	}
1026 }
1027