Phi: nicer scroll animation for METAR widget
[fg:fgdata.git] / Nasal / redout.nas
1 # Damped G value - starts at 1.
2 var GDamped = 1.0;
3 var previousG = 1.0;
4 var running_redout = 0;
5 var running_compression = 0;
6 var fdm = "jsb";
7
8 var blackout_start = nil;
9 var blackout_end = nil;
10 var redout_start = nil;
11 var redout_end = nil;
12 var compression_rate = nil;
13 var internal = nil;
14
15 var lp_black = nil;
16 var lp_red = nil;
17
18 var run = func {
19
20   if (running_redout or running_compression)
21   {
22     var GCurrent = 1.0;
23
24     if (fdm == "jsb")
25     {
26       GCurrent = getprop("/accelerations/pilot/z-accel-fps_sec");
27       if (GCurrent != nil) GCurrent = - GCurrent / 32;
28     }
29     else
30     {
31       GCurrent = getprop("/accelerations/pilot-g[0]");
32     }
33
34     if (GCurrent == nil)
35     {
36       GCurrent = 1.0;
37     }
38
39     # Updated the GDamped using a filter.
40     if (GDamped < 0)
41     {
42         # Redout happens faster and clears quicker
43         GDamped = lp_red.filter(GCurrent);
44     }
45     else
46     {
47         GDamped = lp_black.filter(GCurrent);
48     }
49
50     setprop("/accelerations/pilot-gdamped", GDamped);
51
52     if (internal)
53     {
54       if (running_redout)
55       {
56         if (GDamped > blackout_start)
57         {
58           # Blackout
59           setprop("/sim/rendering/redout/red",0);
60           setprop("/sim/rendering/redout/alpha",
61             (GDamped - blackout_start) / (blackout_end - blackout_start));
62         }
63         elsif (GDamped < redout_start)
64         {
65           # Redout
66           setprop("/sim/rendering/redout/red",1);
67           setprop("/sim/rendering/redout/alpha",
68             abs((GDamped - redout_start) / (redout_end - redout_start)));
69         }
70         else
71         {
72           setprop("/sim/rendering/redout/alpha",0);
73         }
74       }
75
76       if (running_compression)
77       {
78         # Apply any compression due to G-forces
79         if (GDamped != previousG)
80         {
81           var current_y_offset = getprop("/sim/current-view/y-offset-m");
82           setprop("/sim/current-view/y-offset-m", current_y_offset - (GDamped - previousG) * compression_rate);
83           previousG = GDamped;
84         }
85       }
86     }
87     else
88     {
89         # Not in cockpit view - remove all redout/blackout
90         setprop("/sim/rendering/redout/alpha",0);
91     }
92
93     settimer(run, 0);
94   }
95   else
96   {
97     # Disabled - remove all redout/blackout
98     setprop("/sim/rendering/redout/alpha",0);
99   }
100 }
101
102 var check_params = func() {
103   blackout_start = getprop("/sim/rendering/redout/parameters/blackout-onset-g");
104   blackout_end = getprop("/sim/rendering/redout/parameters/blackout-complete-g");
105   redout_start = getprop("/sim/rendering/redout/parameters/redout-onset-g");
106   redout_end = getprop("/sim/rendering/redout/parameters/redout-complete-g");
107   if ((blackout_start == nil) or
108       (blackout_end == nil)   or
109       (redout_start == nil)   or
110       (redout_end == nil)       )
111   {
112     # No valid properties - no point running
113     running_redout = 0;
114   }
115 }
116
117 var fdm_init_listener = _setlistener("/sim/signals/fdm-initialized",
118   func {
119     removelistener(fdm_init_listener); # uninstall, so we're only called once
120     fdm = getprop("/sim/flight-model");
121     running_redout = getprop("/sim/rendering/redout/enabled");
122     running_compression = getprop("/sim/rendering/headshake/enabled");
123     internal = getprop("/sim/current-view/internal");
124     lp_black = aircraft.lowpass.new(0.2);
125     lp_red = aircraft.lowpass.new(0.25);
126
127     setlistener("/sim/rendering/redout/parameters", func {
128       # one parameter has changed, read them all in again
129       check_params();
130     }, 1, 2);
131
132     setlistener("/sim/current-view/internal", func(n) {
133       internal = n.getBoolValue();
134     });
135
136     setlistener("/sim/rendering/headshake/rate-m-g", func(n) {
137       compression_rate = n.getValue();
138     }, 1);
139
140     setlistener("/sim/rendering/headshake/enabled", func(n) {
141       if ((running_compression == 0) and (running_redout == 0) and n.getBoolValue())
142       {
143         running_compression = 1;
144         # start new timer now
145         run();
146       }
147       else
148       {
149         running_compression = n.getBoolValue();
150       }
151     }, 1);
152
153     setlistener("/sim/rendering/redout/enabled", func(n) {
154       if ((running_compression == 0) and (running_redout == 0) and n.getBoolValue())
155       {
156         running_redout = 1;
157         # start new timer now
158         run();
159       }
160       else
161       {
162         running_redout = n.getBoolValue();
163       }
164     }, 1);
165
166     # Now we've set up the listeners (which will have triggered), run it.
167     run();
168   }
169 );