]> git.mxchange.org Git - flightgear.git/blob - src/Instrumentation/HUD/HUD_tape.cxx
Quiet some log output.
[flightgear.git] / src / Instrumentation / HUD / HUD_tape.cxx
1 // HUD_tape.cxx -- HUD Tape 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 #include "HUD_private.hxx"
24
25 static const float TICK_OFFSET = 2.f;
26
27
28 HUD::Tape::Tape(HUD *hud, const SGPropertyNode *n, float x, float y) :
29     Scale(hud, n, x, y),
30     _draw_tick_bottom(n->getBoolValue("tick-bottom", false)),
31     _draw_tick_top(n->getBoolValue("tick-top", false)),
32     _draw_tick_right(n->getBoolValue("tick-right", false)),
33     _draw_tick_left(n->getBoolValue("tick-left", false)),
34     _draw_cap_bottom(n->getBoolValue("cap-bottom", false)),
35     _draw_cap_top(n->getBoolValue("cap-top", false)),
36     _draw_cap_right(n->getBoolValue("cap-right", false)),
37     _draw_cap_left(n->getBoolValue("cap-left", false)),
38     _marker_offset(n->getFloatValue("marker-offset")),
39     _label_offset(n->getFloatValue("label-offset", 3.0)),
40     _label_gap(n->getFloatValue("label-gap-width") / 2.0),
41     _pointer(n->getBoolValue("enable-pointer", true)),
42     _format(n->getStringValue("format", "%d"))
43 {
44     _half_width_units = range_to_show() / 2.0;
45
46     const char *s;
47     s = n->getStringValue("pointer-type");
48     _pointer_type = strcmp(s, "moving") ? FIXED : MOVING;    // "fixed", "moving"
49
50     s = n->getStringValue("tick-type");
51     _tick_type = strcmp(s, "bullet") ? LINE : CIRCLE;        // "bullet", "line"
52
53     s = n->getStringValue("tick-length");                    // "variable", "constant"
54     _tick_length = strcmp(s, "constant") ? VARIABLE : CONSTANT;
55
56     _label_fmt = check_format(_format.c_str());
57     if (_label_fmt != INT && _label_fmt != LONG
58             && _label_fmt != FLOAT && _label_fmt != DOUBLE) {
59         SG_LOG(SG_INPUT, SG_ALERT, "HUD: invalid <format> '" << _format.c_str()
60                 << "' in <tape> '" << _name << "' (must be number format)");
61         _label_fmt = INT;
62         _format = "%d";
63     }
64
65     if (_minor_divs != 0.0f)
66         _div_ratio = int(_major_divs / _minor_divs + 0.5f);
67     else
68         _div_ratio = 0, _minor_divs = _major_divs;
69
70 //    int k; //odd or even values for ticks             // FIXME odd scale
71     _odd_type = false;
72     if (_input.max() + .5f < float(SGLimits<long>::max()))
73         _odd_type = long(floorf(_input.max() + 0.5f)) & 1 ? true : false;
74 }
75
76
77 void HUD::Tape::draw(void) //  (HUD_scale * pscale)
78 {
79     if (!_input.isValid())
80         return;
81
82     float value = _input.getFloatValue();
83
84     if (option_vert())
85         draw_vertical(value);
86     else
87         draw_horizontal(value);
88 }
89
90
91 void HUD::Tape::draw_vertical(float value)
92 {
93     float vmin = 0.0;//, vmax = 0.0;
94     float marker_xs;
95     float marker_xe;
96     float marker_ye;
97     float text_y = 0.0;
98
99     float top = _y + _h;
100     float right = _x + _w;
101
102
103     if (!_pointer) {
104         vmin = value - _half_width_units; // width units == needle travel
105 //        vmax = value + _half_width_units; // or picture unit span.
106         text_y = _center_y;
107
108     } else if (_pointer_type == MOVING) {
109         vmin = _input.min();
110 //        vmax = _input.max();
111
112     } else { // FIXED
113         vmin = value - _half_width_units; // width units == needle travel
114 //        vmax = value + _half_width_units; // or picture unit span.
115         text_y = _center_y;
116     }
117
118     // Bottom tick bar
119     if (_draw_tick_bottom)
120         draw_line(_x, _y, right, _y);
121
122     // Top tick bar
123     if (_draw_tick_top)
124         draw_line(_x, top, right, top);
125
126     marker_xs = _x;       // x start
127     marker_xe = right;    // x extent
128     marker_ye = top;
129
130     // We do not use else in the following so that combining the
131     // two options produces a "caged" display with double
132     // carrots. The same is done for horizontal card indicators.
133
134     // draw capping lines and pointers
135     if (option_left()) {    // Calculate x marker offset
136
137         if (_draw_cap_right)
138             draw_line(marker_xe, _y, marker_xe, marker_ye);
139
140         marker_xs = marker_xe - _w / 3.0;
141
142         // draw_line(marker_xs, _center_y, marker_xe, _center_y + _w / 6);
143         // draw_line(marker_xs, _center_y, marker_xe, _center_y - _w / 6);
144
145         if (_pointer) {
146             if (_pointer_type == MOVING) {
147                 float ycentre, ypoint, xpoint;
148                 float range, right;
149
150                 if (_input.min() >= 0.0)
151                     ycentre = _y;
152                 else if (_input.max() + _input.min() == 0.0)
153                     ycentre = _center_y;
154                 else if (_odd_type)
155                     ycentre = _y + (1.0 - _input.min()) * _h / (_input.max() - _input.min());
156                 else
157                     ycentre = _y + _input.min() * _h / (_input.max() - _input.min());
158
159                 range = _h;
160                 right = _x + _w;
161
162                 if (_odd_type)
163                     ypoint = ycentre + ((value - 1.0) * range / _val_span);
164                 else
165                     ypoint = ycentre + (value * range / _val_span);
166
167                 xpoint = right + _marker_offset;
168                 draw_line(xpoint, ycentre, xpoint, ypoint);
169                 draw_line(xpoint, ypoint, xpoint - _marker_offset, ypoint);
170                 draw_line(xpoint - _marker_offset, ypoint, xpoint - 5.0, ypoint + 5.0);
171                 draw_line(xpoint - _marker_offset, ypoint, xpoint - 5.0, ypoint - 5.0);
172
173             } else { // FIXED
174                 draw_fixed_pointer(_marker_offset + marker_xe, text_y + _w / 6,
175                         _marker_offset + marker_xs, text_y, _marker_offset + marker_xe,
176                         text_y - _w / 6);
177             }
178         }
179     } // if (option_left())
180
181
182     // draw capping lines and pointers
183     if (option_right()) {
184
185         if (_draw_cap_left)
186             draw_line(_x, _y, _x, marker_ye);
187
188         marker_xe = _x + _w / 3.0;
189         // Indicator carrot
190         // draw_line(_x, _center_y +  _w / 6, marker_xe, _center_y);
191         // draw_line(_x, _center_y -  _w / 6, marker_xe, _center_y);
192
193         if (_pointer) {
194             if (_pointer_type == MOVING) {
195                 float ycentre, ypoint, xpoint;
196                 float range;
197
198                 if (_input.min() >= 0.0)
199                     ycentre = _y;
200                 else if (_input.max() + _input.min() == 0.0)
201                     ycentre = _center_y;
202                 else if (_odd_type)
203                     ycentre = _y + (1.0 - _input.min()) * _h / (_input.max() - _input.min());
204                 else
205                     ycentre = _y + _input.min() * _h / (_input.max() - _input.min());
206
207                 range = _h;
208
209                 if (_odd_type)
210                     ypoint = ycentre + ((value - 1.0) * range / _val_span);
211                 else
212                     ypoint = ycentre + (value * range / _val_span);
213
214                 xpoint = _x - _marker_offset;
215                 draw_line(xpoint, ycentre, xpoint, ypoint);
216                 draw_line(xpoint, ypoint, xpoint + _marker_offset, ypoint);
217                 draw_line(xpoint + _marker_offset, ypoint, xpoint + 5.0, ypoint + 5.0);
218                 draw_line(xpoint + _marker_offset, ypoint, xpoint + 5.0, ypoint - 5.0);
219
220             } else { // FIXED
221                 draw_fixed_pointer(-_marker_offset + _x, text_y +  _w / 6,
222                         -_marker_offset + marker_xe, text_y, -_marker_offset + _x,
223                         text_y - _w / 6);
224             }
225         } // if (_pointer)
226     } // if (option_right())
227
228
229     // At this point marker x_start and x_end values are transposed.
230     // To keep this from confusing things they are now swapped.
231     if (option_both())
232         marker_ye = marker_xs, marker_xs = marker_xe, marker_xe = marker_ye;
233
234
235
236     // Work through from bottom to top of scale. Calculating where to put
237     // minor and major ticks.
238
239     // draw scale or tape
240     float vstart = floorf(vmin / _major_divs) * _major_divs;
241     float min_diff = _w / 6.0;    // length difference between major & minor tick
242
243     // FIXME consider oddtype
244     for (int i = 0; ; i++) {
245         float v = vstart + i * _minor_divs;
246
247         if (!_modulo) {
248             if (v < _input.min())
249                 continue;
250             else if (v > _input.max())
251                 break;
252         }
253
254         float y = _y + (v - vmin) * factor();
255
256         if (y < _y + TICK_OFFSET)
257             continue;
258         if (y > top - TICK_OFFSET)
259             break;
260
261         if (_div_ratio && i % _div_ratio) { // minor div
262             if (option_both()) {
263                 if (_tick_type == LINE) {
264                     if (_tick_length == VARIABLE) {
265                         draw_line(_x, y, marker_xs, y);
266                         draw_line(marker_xe, y, right, y);
267                     } else {
268                         draw_line(_x, y, marker_xs, y);
269                         draw_line(marker_xe, y, right, y);
270                     }
271
272                 } else { // _tick_type == CIRCLE
273                     draw_bullet(_x, y, 3.0);
274                 }
275
276             } else if (option_left()) {
277                 if (_tick_type == LINE) {
278                     if (_tick_length == VARIABLE) {
279                         draw_line(marker_xs + min_diff, y, marker_xe, y);
280                     } else {
281                         draw_line(marker_xs, y, marker_xe, y);
282                     }
283                 } else { // _tick_type == CIRCLE
284                     draw_bullet(marker_xs + 4, y, 3.0);
285                 }
286
287             } else { // if (option_right())
288                 if (_tick_type == LINE) {
289                     if (_tick_length == VARIABLE) {
290                         draw_line(marker_xs, y, marker_xe - min_diff, y);
291                     } else {
292                         draw_line(marker_xs, y, marker_xe, y);
293                     }
294
295                 } else { // _tick_type == CIRCLE
296                     draw_bullet(marker_xe - 4, y, 3.0);
297                 }
298             } // end huds both
299
300         } else { // major div
301             if (_modulo)
302                 v = fmodf(v + _modulo, _modulo);
303
304             float x;
305             int align;
306
307             if (option_both()) {
308                 if (_tick_type == LINE) {
309                     draw_line(_x, y, marker_xs, y);
310                     draw_line(marker_xs, y, right, y);
311
312                 } else { // _tick_type == CIRCLE
313                     draw_bullet(_x, y, 5.0);
314                 }
315
316                 x = marker_xs, align = CENTER;
317
318             } else {
319                 if (_tick_type == LINE)
320                     draw_line(marker_xs, y, marker_xe, y);
321                 else // _tick_type == CIRCLE
322                     draw_bullet(marker_xs + 4, y, 5.0);
323
324                 if (option_left())
325                     x = marker_xs - _label_offset, align = RIGHT|VCENTER;
326                 else
327                     x = marker_xe + _label_offset, align = LEFT|VCENTER;
328             }
329
330             if (!option_notext()) {
331                 char *s = format_value(v);
332
333                 float l, r, b, t;
334                 _hud->_text_list.align(s, align, &x, &y, &l, &r, &b, &t);
335
336                 if (b < _y || t > top)
337                     continue;
338
339                 if (_label_gap == 0.0
340                         || (b < _center_y - _label_gap && t < _center_y - _label_gap)
341                         || (b > _center_y + _label_gap && t > _center_y + _label_gap)) {
342                     draw_text(x, y, s);
343                 }
344             }
345         }
346     } // for
347 }
348
349
350 void HUD::Tape::draw_horizontal(float value)
351 {
352     float vmin = 0.0;//, vmax = 0.0;
353     float marker_xs;
354 //    float marker_xe;
355     float marker_ys;
356     float marker_ye;
357 //    float text_y = 0.0;
358
359     float top = _y + _h;
360     float right = _x + _w;
361
362
363     if (!_pointer) {
364         vmin = value - _half_width_units; // width units == needle travel
365 //        vmax = value + _half_width_units; // or picture unit span.
366 //        text_y = _center_y;
367
368     } else if (_pointer_type == MOVING) {
369         vmin = _input.min();
370 //        vmax = _input.max();
371
372     } else { // FIXED
373         vmin = value - _half_width_units; // width units == needle travel
374 //        vmax = value + _half_width_units; // or picture unit span.
375 //        text_y = _center_y;
376     }
377
378     // left tick bar
379     if (_draw_tick_left)
380         draw_line(_x, _y, _x, top);
381
382     // right tick bar
383     if (_draw_tick_right)
384         draw_line(right, _y, right, top);
385
386     marker_ys = _y;    // Starting point for
387     marker_ye = top;           // tick y location calcs
388 //    marker_xe = right;
389     marker_xs = _x + ((value - vmin) * factor());
390
391     if (option_top()) {
392         if (_draw_cap_bottom)
393             draw_line(_x, _y, right, _y);
394
395         // Tick point adjust
396         marker_ye  = _y + _h / 2;
397         // Bottom arrow
398         // draw_line(_center_x, marker_ye, _center_x - _h / 4, _y);
399         // draw_line(_center_x, marker_ye, _center_x + _h / 4, _y);
400         // draw pointer
401         if (_pointer) {
402             if (_pointer_type == MOVING) {
403                 float xcentre = _center_x;
404                 float range = _w;
405                 float xpoint = xcentre + (value * range / _val_span);
406                 float ypoint = _y - _marker_offset;
407                 draw_line(xcentre, ypoint, xpoint, ypoint);
408                 draw_line(xpoint, ypoint, xpoint, ypoint + _marker_offset);
409                 draw_line(xpoint, ypoint + _marker_offset, xpoint + 5.0, ypoint + 5.0);
410                 draw_line(xpoint, ypoint + _marker_offset, xpoint - 5.0, ypoint + 5.0);
411
412             } else { // FIXED
413                 draw_fixed_pointer(marker_xs - _h / 4, _y, marker_xs,
414                         marker_ye, marker_xs + _h / 4, _y);
415             }
416         }
417     } // if (option_top())
418
419     if (option_bottom()) {
420         if (_draw_cap_top)
421             draw_line(_x, top, right, top);
422
423         // Tick point adjust
424         marker_ys = top - _h / 2;
425         // Top arrow
426         // draw_line(_center_x + _h / 4, _y + _h, _center_x, marker_ys);
427         // draw_line(_center_x - _h / 4, _y + _h, _center_x , marker_ys);
428
429         if (_pointer) {
430             if (_pointer_type == MOVING) {
431                 float xcentre = _center_x;
432                 float range = _w;
433                 float hgt = _y + _h;
434                 float xpoint = xcentre + (value * range / _val_span);
435                 float ypoint = hgt + _marker_offset;
436                 draw_line(xcentre, ypoint, xpoint, ypoint);
437                 draw_line(xpoint, ypoint, xpoint, ypoint - _marker_offset);
438                 draw_line(xpoint, ypoint - _marker_offset, xpoint + 5.0, ypoint - 5.0);
439                 draw_line(xpoint, ypoint - _marker_offset, xpoint - 5.0, ypoint - 5.0);
440
441             } else { // FIXED
442                 draw_fixed_pointer(marker_xs + _h / 4, top, marker_xs, marker_ys,
443                         marker_xs - _h / 4, top);
444             }
445         }
446     } // if (option_bottom())
447
448
449     float vstart = floorf(vmin / _major_divs) * _major_divs;
450     float min_diff = _h / 6.0;    // length difference between major & minor tick
451
452     // FIXME consider oddtype
453     for (int i = 0; ; i++) {
454         float v = vstart + i * _minor_divs;
455
456         if (!_modulo) {
457             if (v < _input.min())
458                 continue;
459             else if (v > _input.max())
460                 break;
461         }
462
463         float x = _x + (v - vmin) * factor();
464
465         if (x < _x + TICK_OFFSET)
466             continue;
467         if (x > right - TICK_OFFSET)
468             break;
469
470         if (_div_ratio && i % _div_ratio) { // minor div
471             if (option_both()) {
472                 if (_tick_length == VARIABLE) {
473                     draw_line(x, _y, x, marker_ys - 4);
474                     draw_line(x, marker_ye + 4, x, top);
475                 } else {
476                     draw_line(x, _y, x, marker_ys);
477                     draw_line(x, marker_ye, x, top);
478                 }
479
480             } else {
481                 if (option_top()) {
482                     // draw minor ticks
483                     if (_tick_length == VARIABLE)
484                         draw_line(x, marker_ys, x, marker_ye - min_diff);
485                     else
486                         draw_line(x, marker_ys, x, marker_ye);
487
488                 } else if (_tick_length == VARIABLE) {
489                     draw_line(x, marker_ys + 4, x, marker_ye);
490                 } else {
491                     draw_line(x, marker_ys, x, marker_ye);
492                 }
493             }
494
495         } else { // major divs
496             if (_modulo)
497                 v = fmodf(v + _modulo, _modulo);
498
499             float y;
500             int align;
501
502             if (option_both()) {
503                 draw_line(x, _y, x, marker_ye);
504                 draw_line(x, marker_ye, x, _y + _h);
505                 y = marker_ys, align = CENTER;
506
507             } else {
508                 draw_line(x, marker_ys, x, marker_ye);
509
510                 if (option_top())
511                     y = top - _label_offset, align = TOP|HCENTER;
512                 else
513                     y = _y + _label_offset, align = BOTTOM|HCENTER;
514             }
515
516             if (!option_notext()) {
517                 char *s = format_value(v);
518
519                 float l, r, b, t;
520                 _hud->_text_list.align(s, align, &x, &y, &l, &r, &b, &t);
521
522                 if (l < _x || r > right)
523                     continue;
524
525                 if (_label_gap == 0.0
526                         || (l < _center_x - _label_gap && r < _center_x - _label_gap)
527                         || (l > _center_x + _label_gap && r > _center_x + _label_gap)) {
528                     draw_text(x, y, s);
529                 }
530             }
531         }
532     } // for
533 }
534
535
536 char *HUD::Tape::format_value(float v)
537 {
538     if (fabs(v) < 1e-8)   // avoid -0.0
539         v = 0.0f;
540
541     if (_label_fmt == INT)
542         snprintf(_buf, BUFSIZE, _format.c_str(), int(v));
543     else if (_label_fmt == LONG)
544         snprintf(_buf, BUFSIZE, _format.c_str(), long(v));
545     else if (_label_fmt == FLOAT)
546         snprintf(_buf, BUFSIZE, _format.c_str(), v);
547     else // _label_fmt == DOUBLE
548         snprintf(_buf, BUFSIZE, _format.c_str(), double(v));
549     return _buf;
550 }
551
552
553 void HUD::Tape::draw_fixed_pointer(float x1, float y1, float x2, float y2, float x3, float y3)
554 {
555     glBegin(GL_LINE_STRIP);
556     glVertex2f(x1, y1);
557     glVertex2f(x2, y2);
558     glVertex2f(x3, y3);
559     glEnd();
560 }
561
562