]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/HUD/HUD_gauge.cxx
fix <modulo> feature (required for the compass tape)
[flightgear.git] / src / Instrumentation / HUD / HUD_gauge.cxx
1 // HUD_gauge.cxx -- HUD Gauge Instrument
2 //
3 // Written by Michele America, started September 1997.
4 //
5 // Copyright (C) 1997  Michele F. America  [micheleamerica#geocities:com]
6 // Copyright (C) 2006  Melchior FRANZ  [mfranz#aon:at]
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
22 #include "HUD.hxx"
23
24
25 HUD::Gauge::Gauge(HUD *hud, const SGPropertyNode *n, float x, float y) :
26     Scale(hud, n, x, y)
27 {
28 }
29
30
31 // As implemented, draw only correctly draws a horizontal or vertical
32 // scale. It should contain a variation that permits clock type displays.
33 // Now is supports "tickless" displays such as control surface indicators.
34 // This routine should be worked over before using. Current value would be
35 // fetched and not used if not commented out. Clearly that is intollerable.
36
37 void HUD::Gauge::draw(void)
38 {
39     if (!_input.isValid())
40         return;
41
42     float marker_xs, marker_xe;
43     float marker_ys, marker_ye;
44     float text_x, text_y;
45     float width, height, bottom_4;
46     float lenstr;
47     int i;
48     const int BUFSIZE = 80;
49     char buf[BUFSIZE];
50     bool condition;
51     int disp_val = 0;
52     float vmin = _input.min();
53     float vmax = _input.max();
54     Point mid_scr = get_centroid();
55     float cur_value = _input.getFloatValue();
56
57     width = _x + _w;                                            // FIXME huh?
58     height = _y + _h;
59     bottom_4 = _h / 4.0;
60
61     // Draw the basic markings for the scale...
62     if (option_vert()) { // Vertical scale
63         // Bottom tick bar
64         draw_line(_x, _y, width, _y);
65
66         // Top tick bar
67         draw_line(_x, height, width, height);
68
69         marker_xs = _x;
70         marker_xe = width;
71
72         if (option_left()) { // Read left, so line down right side
73             draw_line(width, _y, width, height);
74             marker_xs  = marker_xe - _w / 3.0;   // Adjust tick
75         }
76
77         if (option_right()) {     // Read  right, so down left sides
78             draw_line(_x, _y, _x, height);
79             marker_xe = _x + _w / 3.0;   // Adjust tick
80         }
81
82         // At this point marker x_start and x_end values are transposed.
83         // To keep this from confusing things they are now interchanged.
84         if (option_both()) {
85             marker_ye = marker_xs;
86             marker_xs = marker_xe;
87             marker_xe = marker_ye;
88         }
89
90         // Work through from bottom to top of scale. Calculating where to put
91         // minor and major ticks.
92
93         if (!option_noticks()) {    // If not no ticks...:)
94             // Calculate x marker offsets
95             int last = (int)vmax + 1;
96             i = (int)vmin;
97
98             for (; i < last; i++) {
99                 // Calculate the location of this tick
100                 marker_ys = _y + (i - vmin) * factor()/* +.5f*/;
101
102                 // We compute marker_ys even though we don't know if we will use
103                 // either major or minor divisions. Simpler.
104
105                 if (_minor_divs) {                  // Minor tick marks
106                     if (!(i % (int)_minor_divs)) {
107                         if (option_left() && option_right()) {
108                             draw_line(_x, marker_ys, marker_xs - 3, marker_ys);
109                             draw_line(marker_xe + 3, marker_ys, width, marker_ys);
110
111                         } else if (option_left()) {
112                             draw_line(marker_xs + 3, marker_ys, marker_xe, marker_ys);
113                         } else {
114                             draw_line(marker_xs, marker_ys, marker_xe - 3, marker_ys);
115                         }
116                     }
117                 }
118
119                 // Now we work on the major divisions. Since these are also labeled
120                 // and no labels are drawn otherwise, we label inside this if
121                 // statement.
122
123                 if (_major_divs) {                  // Major tick mark
124                     if (!(i % (int)_major_divs)) {
125                         if (option_left() && option_right()) {
126                             draw_line(_x, marker_ys, marker_xs, marker_ys);
127                             draw_line(marker_xe, marker_ys, width, marker_ys);
128                         } else {
129                             draw_line(marker_xs, marker_ys, marker_xe, marker_ys);
130                         }
131
132                         if (!option_notext()) {
133                             disp_val = i;
134                             snprintf(buf, BUFSIZE, "%d",
135                                     int(disp_val * _input.factor()/*+.5*/));  /// was data_scaling(), which makes no sense
136
137                             lenstr = text_width(buf);
138
139                             if (option_left() && option_right()) {
140                                 text_x = mid_scr.x - lenstr/2 ;
141
142                             } else if (option_left()) {
143                                 text_x = marker_xs - lenstr;
144                             } else {
145                                 text_x = marker_xe - lenstr;
146                             }
147                             // Now we know where to put the text.
148                             text_y = marker_ys;
149                             draw_text(text_x, text_y, buf, 0);
150                         }
151                     }
152                 }
153             }
154         }
155
156         // Now that the scale is drawn, we draw in the pointer(s). Since labels
157         // have been drawn, text_x and text_y may be recycled. This is used
158         // with the marker start stops to produce a pointer for each side reading
159
160         text_y = _y + ((cur_value - vmin) * factor() /*+.5f*/);
161         //    text_x = marker_xs - _x;
162
163         if (option_right()) {
164             glBegin(GL_LINE_STRIP);
165             glVertex2f(_x, text_y + 5);
166             glVertex2f(marker_xe, text_y);
167             glVertex2f(_x, text_y - 5);
168             glEnd();
169         }
170         if (option_left()) {
171             glBegin(GL_LINE_STRIP);
172             glVertex2f(width, text_y + 5);
173             glVertex2f(marker_xs, text_y);
174             glVertex2f(width, text_y - 5);
175             glEnd();
176         }
177         // End if VERTICAL SCALE TYPE
178
179     } else {                             // Horizontal scale by default
180         // left tick bar
181         draw_line(_x, _y, _x, height);
182
183         // right tick bar
184         draw_line(width, _y, width, height );
185
186         marker_ys = _y;                       // Starting point for
187         marker_ye = height;                              // tick y location calcs
188         marker_xs = _x + (cur_value - vmin) * factor() /*+ .5f*/;
189
190         if (option_top()) {
191             // Bottom box line
192             draw_line(_x, _y, width, _y);
193
194             marker_ye = _y + _h / 2.0;   // Tick point adjust
195             // Bottom arrow
196             glBegin(GL_LINE_STRIP);
197             glVertex2f(marker_xs - bottom_4, _y);
198             glVertex2f(marker_xs, marker_ye);
199             glVertex2f(marker_xs + bottom_4, _y);
200             glEnd();
201         }
202
203         if (option_bottom()) {
204             // Top box line
205             draw_line(_x, height, width, height);
206             // Tick point adjust
207             marker_ys = height - _h / 2.0;
208
209             // Top arrow
210             glBegin(GL_LINE_STRIP);
211             glVertex2f(marker_xs + bottom_4, height);
212             glVertex2f(marker_xs, marker_ys );
213             glVertex2f(marker_xs - bottom_4, height);
214             glEnd();
215         }
216
217
218         int last = (int)vmax + 1;
219         i = (int)vmin;
220         for (; i <last ; i++) {
221             condition = true;
222             if (!_modulo && i < _input.min())
223                     condition = false;
224
225             if (condition) {
226                 marker_xs = _x + (i - vmin) * factor()/* +.5f*/;
227                 //        marker_xs = _x + (int)((i - vmin) * factor() + .5f);
228                 if (_minor_divs) {
229                     if (!(i % (int)_minor_divs)) {
230                         // draw in ticks only if they aren't too close to the edge.
231                         if (((marker_xs + 5) > _x)
232                                || ((marker_xs - 5) < (width))) {
233
234                             if (option_both()) {
235                                 draw_line(marker_xs, _y, marker_xs, marker_ys - 4);
236                                 draw_line(marker_xs, marker_ye + 4, marker_xs, height);
237
238                             } else if (option_top()) {
239                                 draw_line(marker_xs, marker_ys, marker_xs, marker_ye - 4);
240                             } else {
241                                 draw_line(marker_xs, marker_ys + 4, marker_xs, marker_ye);
242                             }
243                         }
244                     }
245                 }
246
247                 if (_major_divs) {
248                     if (!(i % (int)_major_divs)) {
249                         if (_modulo) {
250                             if (disp_val < 0) {
251                                 while (disp_val < 0)
252                                     disp_val += _modulo;
253                             }
254                             disp_val = i % (int)_modulo;
255                         } else {
256                             disp_val = i;
257                         }
258                         snprintf(buf, BUFSIZE, "%d",
259                                 int(disp_val * _input.factor()/* +.5*/)); // was data_scaling(), which makes no sense
260                         lenstr = text_width(buf);
261
262                         // Draw major ticks and text only if far enough from the edge.
263                         if (((marker_xs - 10) > _x)
264                                 && ((marker_xs + 10) < width)) {
265                             if (option_both()) {
266                                 draw_line(marker_xs, _y, marker_xs, marker_ys);
267                                 draw_line(marker_xs, marker_ye, marker_xs, height);
268
269                                 if (!option_notext())
270                                     draw_text(marker_xs - lenstr, marker_ys + 4, buf, 0);
271
272                             } else {
273                                 draw_line(marker_xs, marker_ys, marker_xs, marker_ye);
274
275                                 if (!option_notext()) {
276                                     if (option_top())
277                                         draw_text(marker_xs - lenstr, height - 10, buf, 0);
278                                     else
279                                         draw_text(marker_xs - lenstr, _y, buf, 0);
280                                 }
281                             }
282                         }
283                     }
284                 }
285             }
286         }
287     }
288 }
289
290