1 // HUD_gauge.cxx -- HUD Gauge Instrument
3 // Written by Michele America, started September 1997.
5 // Copyright (C) 1997 Michele F. America [micheleamerica#geocities:com]
6 // Copyright (C) 2006 Melchior FRANZ [mfranz#aon:at]
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.
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.
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.
25 HUD::Gauge::Gauge(HUD *hud, const SGPropertyNode *n, float x, float y) :
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.
37 void HUD::Gauge::draw(void)
39 if (!_input.isValid())
42 float marker_xs, marker_xe;
43 float marker_ys, marker_ye;
45 float width, height, bottom_4;
48 const int BUFSIZE = 80;
52 float vmin = _input.min();
53 float vmax = _input.max();
54 Point mid_scr = get_centroid();
55 float cur_value = _input.getFloatValue();
56 Rect scrn_rect = get_location();
58 width = scrn_rect.left + scrn_rect.right;
59 height = scrn_rect.top + scrn_rect.bottom;
60 bottom_4 = scrn_rect.bottom / 4.0;
62 // Draw the basic markings for the scale...
63 if (option_vert()) { // Vertical scale
65 draw_line(scrn_rect.left, scrn_rect.top, width, scrn_rect.top);
68 draw_line( scrn_rect.left, height, width, height);
70 marker_xs = scrn_rect.left;
73 if (option_left()) { // Read left, so line down right side
74 draw_line(width, scrn_rect.top, width, height);
75 marker_xs = marker_xe - scrn_rect.right / 3.0; // Adjust tick
78 if (option_right()) { // Read right, so down left sides
79 draw_line(scrn_rect.left, scrn_rect.top, scrn_rect.left, height);
80 marker_xe = scrn_rect.left + scrn_rect.right / 3.0; // Adjust tick
83 // At this point marker x_start and x_end values are transposed.
84 // To keep this from confusing things they are now interchanged.
86 marker_ye = marker_xs;
87 marker_xs = marker_xe;
88 marker_xe = marker_ye;
91 // Work through from bottom to top of scale. Calculating where to put
92 // minor and major ticks.
94 if (!option_noticks()) { // If not no ticks...:)
95 // Calculate x marker offsets
96 int last = (int)vmax + 1;
99 for (; i < last; i++) {
100 // Calculate the location of this tick
101 marker_ys = scrn_rect.top + (i - vmin) * factor()/* +.5f*/;
103 // We compute marker_ys even though we don't know if we will use
104 // either major or minor divisions. Simpler.
106 if (_minor_divs) { // Minor tick marks
107 if (!(i % (int)_minor_divs)) {
108 if (option_left() && option_right()) {
109 draw_line(scrn_rect.left, marker_ys, marker_xs - 3, marker_ys);
110 draw_line(marker_xe + 3, marker_ys, width, marker_ys);
112 } else if (option_left()) {
113 draw_line(marker_xs + 3, marker_ys, marker_xe, marker_ys);
115 draw_line(marker_xs, marker_ys, marker_xe - 3, marker_ys);
120 // Now we work on the major divisions. Since these are also labeled
121 // and no labels are drawn otherwise, we label inside this if
124 if (_major_divs) { // Major tick mark
125 if (!(i % (int)_major_divs)) {
126 if (option_left() && option_right()) {
127 draw_line(scrn_rect.left, marker_ys, marker_xs, marker_ys);
128 draw_line(marker_xe, marker_ys, width, marker_ys);
130 draw_line(marker_xs, marker_ys, marker_xe, marker_ys);
133 if (!option_notext()) {
135 snprintf(buf, BUFSIZE, "%d",
136 int(disp_val * _input.factor()/*+.5*/)); /// was data_scaling(), which makes no sense
138 lenstr = text_width(buf);
140 if (option_left() && option_right()) {
141 text_x = mid_scr.x - lenstr/2 ;
143 } else if (option_left()) {
144 text_x = marker_xs - lenstr;
146 text_x = marker_xe - lenstr;
148 // Now we know where to put the text.
150 draw_text(text_x, text_y, buf, 0);
157 // Now that the scale is drawn, we draw in the pointer(s). Since labels
158 // have been drawn, text_x and text_y may be recycled. This is used
159 // with the marker start stops to produce a pointer for each side reading
161 text_y = scrn_rect.top + ((cur_value - vmin) * factor() /*+.5f*/);
162 // text_x = marker_xs - scrn_rect.left;
164 if (option_right()) {
165 glBegin(GL_LINE_STRIP);
166 glVertex2f(scrn_rect.left, text_y + 5);
167 glVertex2f(marker_xe, text_y);
168 glVertex2f(scrn_rect.left, text_y - 5);
172 glBegin(GL_LINE_STRIP);
173 glVertex2f(width, text_y + 5);
174 glVertex2f(marker_xs, text_y);
175 glVertex2f(width, text_y - 5);
178 // End if VERTICAL SCALE TYPE
180 } else { // Horizontal scale by default
182 draw_line(scrn_rect.left, scrn_rect.top, scrn_rect.left, height);
185 draw_line(width, scrn_rect.top, width, height );
187 marker_ys = scrn_rect.top; // Starting point for
188 marker_ye = height; // tick y location calcs
189 marker_xs = scrn_rect.left + (cur_value - vmin) * factor() /*+ .5f*/;
193 draw_line(scrn_rect.left, scrn_rect.top, width, scrn_rect.top);
195 marker_ye = scrn_rect.top + scrn_rect.bottom / 2.0; // Tick point adjust
197 glBegin(GL_LINE_STRIP);
198 glVertex2f(marker_xs - bottom_4, scrn_rect.top);
199 glVertex2f(marker_xs, marker_ye);
200 glVertex2f(marker_xs + bottom_4, scrn_rect.top);
204 if (option_bottom()) {
206 draw_line(scrn_rect.left, height, width, height);
208 marker_ys = height - scrn_rect.bottom / 2.0;
211 glBegin(GL_LINE_STRIP);
212 glVertex2f(marker_xs + bottom_4, height);
213 glVertex2f(marker_xs, marker_ys );
214 glVertex2f(marker_xs - bottom_4, height);
219 int last = (int)vmax + 1;
221 for (; i <last ; i++) {
223 if (!modulo() && i < _input.min())
227 marker_xs = scrn_rect.left + (i - vmin) * factor()/* +.5f*/;
228 // marker_xs = scrn_rect.left + (int)((i - vmin) * factor() + .5f);
230 if (!(i % (int)_minor_divs)) {
231 // draw in ticks only if they aren't too close to the edge.
232 if (((marker_xs + 5) > scrn_rect.left)
233 || ((marker_xs - 5) < (width))) {
236 draw_line(marker_xs, scrn_rect.top, marker_xs, marker_ys - 4);
237 draw_line(marker_xs, marker_ye + 4, marker_xs, height);
239 } else if (option_top()) {
240 draw_line(marker_xs, marker_ys, marker_xs, marker_ye - 4);
242 draw_line(marker_xs, marker_ys + 4, marker_xs, marker_ye);
249 if (!(i % (int)_major_divs)) {
253 disp_val += modulo();
255 disp_val = i % (int)modulo();
259 snprintf(buf, BUFSIZE, "%d",
260 int(disp_val * _input.factor()/* +.5*/)); // was data_scaling(), which makes no sense
261 lenstr = text_width(buf);
263 // Draw major ticks and text only if far enough from the edge.
264 if (((marker_xs - 10) > scrn_rect.left)
265 && ((marker_xs + 10) < width)) {
267 draw_line(marker_xs, scrn_rect.top, marker_xs, marker_ys);
268 draw_line(marker_xs, marker_ye, marker_xs, height);
270 if (!option_notext())
271 draw_text(marker_xs - lenstr, marker_ys + 4, buf, 0);
274 draw_line(marker_xs, marker_ys, marker_xs, marker_ye);
276 if (!option_notext()) {
278 draw_text(marker_xs - lenstr, height - 10, buf, 0);
280 draw_text(marker_xs - lenstr, scrn_rect.top, buf, 0);