4419aa2cb3
encapsulation, but a real namespace would probably be better) - extend alignment to optionally adjust x/y, and to return absolute l/r/b/t coordinates (as opposed to plib's relative ones!) - implement tape gaps as per Curt's order :-) - shuffling stuff around for fun
234 lines
6.6 KiB
C++
234 lines
6.6 KiB
C++
// HUD_label.cxx -- HUD Label
|
|
//
|
|
// Written by Michele America, started September 1997.
|
|
//
|
|
// Copyright (C) 1997 Michele F. America [micheleamerica#geocities:com]
|
|
// Copyright (C) 2006 Melchior FRANZ [mfranz#aon:at]
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License as
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <simgear/props/condition.hxx>
|
|
#include "HUD.hxx"
|
|
|
|
|
|
HUD::Label::Label(HUD *hud, const SGPropertyNode *n, float x, float y) :
|
|
Item(hud, n, x, y),
|
|
_input(n->getNode("input", false)),
|
|
_box(n->getBoolValue("box", false)),
|
|
_pointer_width(n->getFloatValue("pointer-width", 7.0)),
|
|
_pointer_length(n->getFloatValue("pointer-length", 5.0)),
|
|
_blink_condition(0),
|
|
_blink_interval(n->getFloatValue("blinking/interval", -1.0f)),
|
|
_blink_target(0.0),
|
|
_blink_state(true)
|
|
{
|
|
const SGPropertyNode *node = n->getNode("blinking/condition");
|
|
if (node)
|
|
_blink_condition = sgReadCondition(globals->get_props(), node);
|
|
|
|
const char *halign = n->getStringValue("halign", "center");
|
|
if (!strcmp(halign, "left"))
|
|
_halign = LEFT;
|
|
else if (!strcmp(halign, "right"))
|
|
_halign = RIGHT;
|
|
else
|
|
_halign = HCENTER;
|
|
|
|
_halign |= VCENTER;
|
|
|
|
const char *pre = n->getStringValue("prefix", 0);
|
|
const char *post = n->getStringValue("postfix", 0);
|
|
const char *fmt = n->getStringValue("format", 0);
|
|
|
|
if (pre)
|
|
_format = pre;
|
|
|
|
if (fmt)
|
|
_format += fmt;
|
|
else
|
|
_format += "%s";
|
|
|
|
if (post)
|
|
_format += post;
|
|
|
|
_mode = check_format(_format.c_str());
|
|
if (_mode == INVALID) {
|
|
SG_LOG(SG_INPUT, SG_ALERT, "HUD: invalid format '" << _format.c_str() << '\'');
|
|
_format = "INVALID";
|
|
_mode = NONE;
|
|
}
|
|
|
|
blink();
|
|
}
|
|
|
|
|
|
void HUD::Label::draw(void)
|
|
{
|
|
if (!(_mode == NONE || _input.isValid() && blink()))
|
|
return;
|
|
|
|
if (_box) {
|
|
float l, r, p;
|
|
float pw = _pointer_width / 2.0;
|
|
|
|
l = _center_x - pw;
|
|
r = _center_x + pw;
|
|
bool draw_parallel = fabsf(_pointer_width - _w) > 2.0; // draw lines left and right of arrow?
|
|
|
|
if (option_bottom()) {
|
|
if (draw_parallel) {
|
|
draw_line(_x, _y, l, _y);
|
|
draw_line(r, _y, _x + _w, _y);
|
|
}
|
|
p = _y - _pointer_length;
|
|
draw_line(l, _y, _center_x, p);
|
|
draw_line(_center_x, p, r, _y);
|
|
} else
|
|
draw_line(_x, _y, _x + _w, _y);
|
|
|
|
if (option_top()) {
|
|
if (draw_parallel) {
|
|
draw_line(_x, _y + _h, l, _y + _h);
|
|
draw_line(r, _y + _h, _x + _w, _y + _h);
|
|
}
|
|
p = _y + _h + _pointer_length;
|
|
draw_line(l, _y + _h, _center_x, p);
|
|
draw_line(_center_x, p, r, _y + _h);
|
|
} else
|
|
draw_line(_x + _w, _y + _h, _x, _y + _h);
|
|
|
|
l = _center_y - pw;
|
|
r = _center_y + pw;
|
|
draw_parallel = fabsf(_pointer_width - _h) > 2.0;
|
|
|
|
if (option_left()) {
|
|
if (draw_parallel) {
|
|
draw_line(_x, _y, _x, l);
|
|
draw_line(_x, r, _x, _y + _h);
|
|
}
|
|
p = _x - _pointer_length;
|
|
draw_line(_x, l, p, _center_y);
|
|
draw_line(p, _center_y, _x, r);
|
|
} else
|
|
draw_line(_x, _y + _h, _x, _y);
|
|
|
|
if (option_right()) {
|
|
if (draw_parallel) {
|
|
draw_line(_x + _w, _y, _x + _w, l);
|
|
draw_line(_x + _w, r, _x + _w, _y + _h);
|
|
}
|
|
p = _x + _w + _pointer_length;
|
|
draw_line(_x + _w, l, p, _center_y);
|
|
draw_line(p, _center_y, _x + _w, r);
|
|
} else
|
|
draw_line(_x + _w, _y, _x + _w, _y + _h);
|
|
}
|
|
|
|
const int BUFSIZE = 256;
|
|
char buf[BUFSIZE];
|
|
if (_mode == NONE)
|
|
snprintf(buf, BUFSIZE, _format.c_str());
|
|
else if (_mode == STRING)
|
|
snprintf(buf, BUFSIZE, _format.c_str(), _input.getStringValue());
|
|
else if (_mode == INT)
|
|
snprintf(buf, BUFSIZE, _format.c_str(), int(_input.getFloatValue()));
|
|
else if (_mode == LONG)
|
|
snprintf(buf, BUFSIZE, _format.c_str(), long(_input.getFloatValue()));
|
|
else if (_mode == FLOAT)
|
|
snprintf(buf, BUFSIZE, _format.c_str(), float(_input.getFloatValue()));
|
|
else if (_mode == DOUBLE) // not really supported yet
|
|
snprintf(buf, BUFSIZE, _format.c_str(), double(_input.getFloatValue()));
|
|
|
|
if (_halign & HCENTER)
|
|
draw_text(_center_x, _center_y, buf, _halign, get_digits());
|
|
else if (_halign & LEFT)
|
|
draw_text(_x, _center_y, buf, _halign, get_digits());
|
|
else // if (_halign & RIGHT)
|
|
draw_text(_x + _w, _center_y, buf, _halign, get_digits());
|
|
}
|
|
|
|
|
|
// make sure the format matches '[ -+#]?\d*(\.\d*)?(l?[df]|s)'
|
|
//
|
|
HUD::Label::Format HUD::Label::check_format(const char *f) const
|
|
{
|
|
bool l = false;
|
|
Format fmt = STRING;
|
|
|
|
for (; *f; f++) {
|
|
if (*f == '%') {
|
|
if (f[1] == '%')
|
|
f++;
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
if (*f++ != '%')
|
|
return NONE;
|
|
if (*f == ' ' || *f == '+' || *f == '-' || *f == '#')
|
|
f++;
|
|
while (*f && isdigit(*f))
|
|
f++;
|
|
if (*f == '.') {
|
|
f++;
|
|
while (*f && isdigit(*f))
|
|
f++;
|
|
}
|
|
if (*f == 'l')
|
|
l = true, f++;
|
|
|
|
if (*f == 'd')
|
|
fmt = l ? LONG : INT;
|
|
else if (*f == 'f')
|
|
fmt = l ? DOUBLE : FLOAT;
|
|
else if (*f == 's') {
|
|
if (l)
|
|
return INVALID;
|
|
fmt = STRING;
|
|
} else
|
|
return INVALID;
|
|
|
|
for (++f; *f; f++) {
|
|
if (*f == '%') {
|
|
if (f[1] == '%')
|
|
f++;
|
|
else
|
|
return INVALID;
|
|
}
|
|
}
|
|
return fmt;
|
|
}
|
|
|
|
|
|
bool HUD::Label::blink()
|
|
{
|
|
if (_blink_interval < 0.0f)
|
|
return true;
|
|
|
|
if (_blink_condition && !_blink_condition->test())
|
|
return true;
|
|
|
|
if (_hud->timer() < _blink_target)
|
|
return _blink_state;
|
|
|
|
_blink_target = _hud->timer() + _blink_interval;
|
|
return _blink_state = !_blink_state;
|
|
}
|
|
|
|
|