lfsdash/lfsdash.c

995 lines
29 KiB
C

#include <GL/glfw.h>
#include <FTGL/ftgl.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include "outgauge.h"
#include "cars.h"
#include "config.h"
#include "gauge.h"
#include "socket.h"
#include "audio.h"
#include "text.h"
#include "insim.h"
#include "network_worker.h"
static GLuint s_symbols[1];
struct sympos {
float a, b, c, d;
int flag;
struct colour off;
struct colour on;
};
/*
DL_SHIFT, // bit 0 - shift light
DL_FULLBEAM, // bit 1 - full beam
DL_HANDBRAKE, // bit 2 - handbrake
DL_PITSPEED, // bit 3 - pit speed limiter
DL_TC, // bit 4 - TC active or switched off
DL_SIGNAL_L, // bit 5 - left turn signal
DL_SIGNAL_R, // bit 6 - right turn signal
DL_SIGNAL_ANY, // bit 7 - shared turn signal
DL_OILWARN, // bit 8 - oil pressure warning
DL_BATTERY, // bit 9 - battery warning
DL_ABS, // bit 10 - ABS active or switched off
DL_SPARE, // bit 11
*/
static int dl_to_sympos[] = {
18, 0, 12, 17, 11, 15, 16, 2, 10, 9, 14, 13
};
static struct sympos s_sympos[] = {
{ 0.0, 0.0, 0.125, 0.125, (1 << DL_FULLBEAM), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 0.15, 1.0, 1.0 } },
{ 0.125, 0.0, 0.25, 0.125, 0, { 0.1, 0.1, 0.1, 1.0 }, { 0.5, 0.5, 1.0, 1.0 } },
{ 0.25, 0.0, 0.375, 0.125, (1 << DL_SIGNAL_ANY), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 1.0, 0.15, 1.0 } },
{ 0.375, 0.0, 0.5, 0.125, 0, { 0.1, 0.1, 0.1, 1.0 }, { 0.5, 0.5, 1.0, 1.0 } },
{ 0.0, 0.125, 0.125, 0.25, 0, { 1.0, 1.0, 1.0, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
{ 0.125, 0.125, 0.25, 0.25, 0, { 1.0, 1.0, 1.0, 1.0 }, { 0.15, 0.15, 1.0, 1.0 } },
{ 0.25, 0.125, 0.375, 0.25, 0, { 1.0, 1.0, 1.0, 1.0 }, { 0.15, 0.15, 1.0, 1.0 } },
{ 0.375, 0.125, 0.5, 0.25, 0, { 1.0, 1.0, 1.0, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
{ 0.5, 0.125, 0.625, 0.25, 0, { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 0.15, 0.15, 1.0 } },
{ 0.0, 0.25, 0.125, 0.375, (1 << DL_BATTERY), { 0.1, 0.1, 0.1, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
{ 0.125, 0.25, 0.25, 0.375, (1 << DL_OILWARN), { 0.1, 0.1, 0.1, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
{ 0.25, 0.25, 0.375, 0.375, (1 << DL_TC), { 0.1, 0.1, 0.1, 1.0 }, { 1.0, 0.5, 0.0, 1.0 } },
{ 0.375, 0.25, 0.5, 0.375, (1 << DL_HANDBRAKE), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 0.15, 1.0, 1.0 } },
{ 0.5, 0.25, 0.625, 0.375, 0, { 0.1, 0.1, 0.1, 1.0 }, { 0.25, 0.25, 1.0, 1.0 } },
{ 0.625, 0.25, 0.75, 0.375, (1 << DL_ABS), { 0.1, 0.1, 0.1, 1.0 }, { 1.0, 0.5, 0.0, 1.0 } },
{ 0.0, 0.375, 0.125, 0.5, (1 << DL_SIGNAL_L), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 1.0, 0.15, 1.0 } },
{ 0.125, 0.375, 0.25, 0.5, (1 << DL_SIGNAL_R), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 1.0, 0.15, 1.0 } },
{ 0.25, 0.375, 0.375, 0.5, (1 << DL_PITSPEED), { 0.1, 0.1, 0.1, 1.0 }, { 0.15, 1.0, 0.15, 1.0 } },
{ 0.375, 0.375, 0.5, 0.5, (1 << DL_SHIFT), { 0.1, 0.1, 0.1, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
{ 0.5, 0.0, 0.625, 0.125, 0, { 1.0, 0.5, 0.0, 1.0 }, { 1.0, 0.15, 0.15, 1.0 } },
};
void drawSymbol(int symbol, int on, int map)
{
if (map) symbol = dl_to_sympos[symbol];
struct sympos *s = &s_sympos[symbol];
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, s_symbols[0]);
if (on) {
glColor4f(s->on.r, s->on.g, s->on.b, s->on.a);
} else {
glColor4f(s->off.r, s->off.g, s->off.b, s->off.a);
}
glBegin(GL_QUADS);
glTexCoord2f(s->a, (on ? 0.5 : 1.0) - s->d);
glVertex3f(-0.5, -0.5, 0.0);
glTexCoord2f(s->c, (on ? 0.5 : 1.0) - s->d);
glVertex3f(0.5, -0.5, 0.0);
glTexCoord2f(s->c, (on ? 0.5 : 1.0) - s->b);
glVertex3f(0.5, 0.5, 0.0);
glTexCoord2f(s->a, (on ? 0.5 : 1.0) - s->b);
glVertex3f(-0.5, 0.5, 0.0);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void drawSymbol2(int symbol, int on, int map, float x, float y, float xs, float ys)
{
glPushMatrix();
glTranslatef(x, y, 0.0f);
glScalef(xs, ys, 1.0f);
drawSymbol(symbol, on, map);
glPopMatrix();
}
int g_outgauge_port;
int g_insim_port;
int main(int argc, char **argv)
{
g_fade = 0;
int width;
int height;
int fullscreen;
int volume;
int rpmleft;
int dofade;
char *insim_host;
float warn_fuel1;
float warn_fuel2;
config_init("lfsdash.txt");
if (!config_get_int("port", &g_outgauge_port)) g_outgauge_port = 4000;
if (!config_get_int("fullscreen", &fullscreen)) fullscreen = 0;
if (!config_get_int("width", &width)) width = 1024;
if (!config_get_int("height", &height)) height = 600;
if (!config_get_int("volume", &volume)) volume = 100;
if (!config_get_int("rpmleft", &rpmleft)) rpmleft = 0;
if (!config_get_int("fade", &dofade)) dofade = 1;
if (!config_get_string("insim_host", &insim_host)) insim_host = strdup("localhost");
if (!config_get_int("insim_port", &g_insim_port)) g_insim_port = 29999;
if (!config_get_float("warn_fuel1", &warn_fuel1)) warn_fuel1 = 0.05f;
if (!config_get_float("warn_fuel2", &warn_fuel2)) warn_fuel2 = 0.01f;
network_worker_init();
socket_init();
outgauge_init(g_outgauge_port);
insim_init(insim_host, g_insim_port);
init_cars();
glfwInit();
glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 1);
if (!glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, fullscreen ? GLFW_FULLSCREEN : GLFW_WINDOW))
{
glfwTerminate();
return 0;
}
glfwSetWindowTitle("GL LFS Dashboard");
audio_init();
struct gauge speed;
speed.radius = 200.0;
speed.anglemin = (180 + 45) * M_PI / 180.0;
speed.anglemax = (180 + 315) * M_PI / 180.0;
speed.rangemin = 0;
speed.rangemax = 160.0;
speed.majorstep = 10.0;
speed.majorwidth = 3.0;
speed.majorstart = 0.9;
speed.majorend = 1.0;
speed.major.r = 0.15;
speed.major.g = 0.15;
speed.major.b = 1.0;
speed.major.a = 1.0;
speed.minorstep = 2.0;
speed.minorwidth = 1.0;
speed.minorstart = 0.95;
speed.minorend = 1.0;
speed.minor.r = 0.15;
speed.minor.g = 0.15;
speed.minor.b = 1.0;
speed.minor.a = 1.0;
speed.dial.r = 1.0;
speed.dial.g = 1.0;
speed.dial.b = 1.0;
speed.dial.a = 0.8;
struct gauge speed2;
speed2.radius = 200.0;
speed2.anglemin = (180 + 45) * M_PI / 180.0;
speed2.anglemax = (180 + 315) * M_PI / 180.0;
speed2.rangemin = 0;
speed2.rangemax = 160.0;
speed2.majorstep = 10.0;
speed2.majorwidth = 1.5;
speed2.majorstart = 0.92;
speed2.majorend = 1.0;
speed2.major.r = 0.15;
speed2.major.g = 0.15;
speed2.major.b = 1.0;
speed2.major.a = 0.5;
speed2.minorstep = 2.0;
speed2.minorwidth = 1.0;
speed2.minorstart = 0.95;
speed2.minorend = 1.0;
speed2.minor.r = 0.15;
speed2.minor.g = 0.15;
speed2.minor.b = 1.0;
speed2.minor.a = 0.5;
speed2.dial.r = 1.0;
speed2.dial.g = 1.0;
speed2.dial.b = 1.0;
speed2.dial.a = 0.0;
struct gauge rpm;
rpm.radius = 200.0;
rpm.anglemin = (180 + 45) * M_PI / 180.0;
rpm.anglemax = (180 + 315) * M_PI / 180.0;
rpm.rangemin = 0;
rpm.rangemax = 10000.0;
rpm.majorstep = 1000.0;
rpm.majorwidth = 3.0;
rpm.majorstart = 0.9;
rpm.majorend = 1.0;
rpm.major.r = 0.15;
rpm.major.g = 0.15;
rpm.major.b = 1.0;
rpm.major.a = 1.0;
rpm.minorstep = 200.0;
rpm.minorwidth = 1.0;
rpm.minorstart = 0.95;
rpm.minorend = 1.0;
rpm.minor.r = 0.15;
rpm.minor.g = 0.15;
rpm.minor.b = 1.0;
rpm.minor.a = 1.0;
rpm.dial.r = 1.0;
rpm.dial.g = 1.0;
rpm.dial.b = 1.0;
rpm.dial.a = 0.8;
struct gauge mpg;
mpg.radius = 160.0;
mpg.anglemin = 120 * M_PI / 180.0;
mpg.anglemax = 60 * M_PI / 180.0;
mpg.rangemin = 0;
mpg.rangemax = 100.0;
mpg.majorstep = 20.0;
mpg.majorwidth = 3.0;
mpg.majorstart = 0.95;
mpg.majorend = 1.0;
mpg.major.r = 0.15;
mpg.major.g = 0.15;
mpg.major.b = 1.0;
mpg.major.a = 1.0;
mpg.minorstep = 10.0;
mpg.minorwidth = 1.0;
mpg.minorstart = 0.95;
mpg.minorend = 1.0;
mpg.minor.r = 0.15;
mpg.minor.g = 0.15;
mpg.minor.b = 1.0;
mpg.minor.a = 1.0;
mpg.dial.r = 1.0;
mpg.dial.g = 1.0;
mpg.dial.b = 1.0;
mpg.dial.a = 0.8;
struct gauge boost;
boost.radius = 160.0;
boost.anglemin = 240 * M_PI / 180.0;
boost.anglemax = 300 * M_PI / 180.0;
boost.rangemin = 0.0;
boost.rangemax = 2.0;
boost.majorstep = 0.5;
boost.majorwidth = 2.0;
boost.majorstart = 0.95;
boost.majorend = 1.0;
boost.major.r = 0.15;
boost.major.g = 0.15;
boost.major.b = 1.0;
boost.major.a = 1.0;
boost.minorstep = 0.1;
boost.minorwidth = 1.0;
boost.minorstart = 0.95;
boost.minorend = 1.0;
boost.minor.r = 0.15;
boost.minor.g = 0.15;
boost.minor.b = 1.0;
boost.minor.a = 1.0;
boost.dial.r = 1.0;
boost.dial.g = 1.0;
boost.dial.b = 1.0;
boost.dial.a = 0.8;
struct gauge fuel;
fuel.radius = 160.0;
fuel.anglemin = 240 * M_PI / 180.0;
fuel.anglemax = 300 * M_PI / 180.0;
fuel.rangemin = 0.0;
fuel.rangemax = 1.0;
fuel.majorstep = 0.5;
fuel.majorwidth = 2.0;
fuel.majorstart = 0.95;
fuel.majorend = 1.0;
fuel.major.r = 0.15;
fuel.major.g = 0.15;
fuel.major.b = 1.0;
fuel.major.a = 1.0;
fuel.minorstep = 0.1;
fuel.minorwidth = 1.0;
fuel.minorstart = 0.95;
fuel.minorend = 1.0;
fuel.minor.r = 0.15;
fuel.minor.g = 0.15;
fuel.minor.b = 1.0;
fuel.minor.a = 1.0;
fuel.dial.r = 1.0;
fuel.dial.g = 1.0;
fuel.dial.b = 1.0;
fuel.dial.a = 0.8;
struct gauge oil;
oil.radius = 160.0;
oil.anglemin = 120 * M_PI / 180.0;
oil.anglemax = 60 * M_PI / 180.0;
oil.rangemin = 0.0;
oil.rangemax = 2.0;
oil.majorstep = 0.5;
oil.majorwidth = 2.0;
oil.majorstart = 0.95;
oil.majorend = 1.0;
oil.major.r = 0.15;
oil.major.g = 0.15;
oil.major.b = 1.0;
oil.major.a = 1.0;
oil.minorstep = 0.1;
oil.minorwidth = 1.0;
oil.minorstart = 0.95;
oil.minorend = 1.0;
oil.minor.r = 0.15;
oil.minor.g = 0.15;
oil.minor.b = 1.0;
oil.minor.a = 1.0;
oil.dial.r = 1.0;
oil.dial.g = 1.0;
oil.dial.b = 1.0;
oil.dial.a = 0.8;
/*
struct gauge clock;
clock.radius = 60.0;
clock.anglemin = 0 * M_PI / 180.0;
clock.anglemax = 360 * M_PI / 180.0;
clock.rangemin = 0.0;
clock.rangemax = 12.0;
clock.majorstep = 1.0;
clock.majorwidth = 2.0;
clock.majorstart = 0.9;
clock.majorend = 1.0;
clock.major.r = 0.15;
clock.major.g = 0.15;
clock.major.b = 1.0;
clock.major.a = 1.0;
clock.minorstep = 0.25;
clock.minorwidth = 1.0;
clock.minorstart = 0.95;
clock.minorend = 1.0;
clock.minor.r = 0.15;
clock.minor.g = 0.15;
clock.minor.b = 1.0;
clock.minor.a = 1.0;
clock.dial.r = 1.0;
clock.dial.g = 1.0;
clock.dial.b = 1.0;
clock.dial.a = 0.8;
*/
char text[40];
//float last_fuel = 1.0;
//float consumption = 0.0;
double next = glfwGetTime();
double last_time = next;
struct car car;
int running = 1;
//int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
//void *(*start_routine)(void*), void *arg);
pthread_t thread;
pthread_create(&thread, NULL, &socket_run, NULL);
FTGLfont *font = ftglCreateTextureFont("arialbd.ttf");//"Arial.ttf");//"/usr/share/fonts/truetype/msttcorefonts/Arial.ttf");
//DS_DIGII
if (!font) return 0;
ftglSetFontFaceSize(font, TEXT_SIZE, TEXT_SIZE);
glGenTextures(1, s_symbols);
glBindTexture(GL_TEXTURE_2D, s_symbols[0]);
glfwLoadTexture2D("symbols512.tga", GLFW_BUILD_MIPMAPS_BIT);
// Use trilinear interpolation for minification
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Use bilinear interpolation for magnification
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Enable texturing
//glEnable(GL_TEXTURE_2D);
int s1 = FX_OFF;
int s2 = FX_OFF;
int s3 = FX_OFF;
int s6 = FX_OFF;
float fade = 0.0f;
float flash = 0.0f;
float binger = 0.0f;
audio_volume(volume * 0.01);
int bing = 0;
int mode = 0;
uint32_t mode_timer = 0;
float hold = 0;
int hold2 = 0;
int ack = 0;
get_car("UF1", &car);
rpm.rangemax = (int)(car.maxrpm / 1000 + 2) * 1000.0;
float maxspeed = 0;
float speedtimer = 0;
float zoom = 65536.0;
while (running) {
double curtime = glfwGetTime();
if (curtime >= next)
{
next = curtime + 0.01;
float interval = curtime - last_time;
flash += interval;
if (flash >= 1) flash = 0;
if (bing == 2)
{
binger += interval;
if (binger >= 1) {
binger = 0;
if (!g_fade) audio_play(3, FX_BING);
}
}
last_time = curtime;
if (speedtimer > 0) {
speedtimer -= interval;
if (speedtimer <= 0)
{
speedtimer = 0;
maxspeed = 0;
}
}
if (g_pressed == 3) {
if (g_outgauge.time - g_shift_time > 1000 &&
g_outgauge.time - g_ctrl_time > 1000)
{
//if (g_released == 3)
//{
g_pressed = 0;
g_released = 0;
audio_play(4, FX_BIP);
mode++;
mode_timer = g_outgauge.time;
//}
}
}
if (ack == 0) {
if (mode == 1) {
if (g_pressed == 1 && volume > 0) {
volume -= 10;
if (volume < 0) volume = 0;
audio_volume(volume * 0.01);
audio_play(4, FX_BOP);
ack = 1;
}
if (g_pressed == 2 && volume < 100) {
volume += 10;
if (volume > 100) volume = 100;
audio_volume(volume * 0.01);
audio_play(4, FX_BIP);
ack = 1;
}
}
}
// Acknowledge key release
if (g_released)
{
g_pressed &= ~g_released;
g_released = 0;
mode_timer = g_outgauge.time;
ack = 0;
}
if (mode && g_outgauge.time - mode_timer > 2000)
{
mode = 0;
}
/*
}
if (g_released == 1) {
volume -= 10;
if (volume < 0) volume = 0;
audio_volume(volume * 0.01);
audio_play(4, FX_BOP);
}
if (g_released == 2) {
volume += 10;
if (volume > 100) volume = 100;
audio_volume(volume * 0.01);
audio_play(4, FX_BIP);
}
if (g_released == 3) {
g_pressed = 0;
g_released = 0;
}
}*/
}
glfwGetWindowSize(&width, &height);
height = height > 0 ? height : 1;
glViewport(0, 0, width, height);
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);
glEnable(GL_LINE_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, 0, height, -100, 100);
//socket_run();
/* Car change */
if (*g_outgauge.car != '\0' && strcmp(g_outgauge.car, car.tag))
{
int carnum = get_car(g_outgauge.car, &car);
if (carnum > -1)
{
rpm.rangemax = (int)(car.maxrpm / 1000 + 2) * 1000.0;
}
}
float speedunit = (g_outgauge.flags & OG_KM) ? 3.6 : 2.23693629;
float distunit = (g_outgauge.flags & OG_KM) ? 0.001 : 0.0006215;
if (g_outgauge.speed > maxspeed) {
maxspeed = g_outgauge.speed;
speedtimer = 15.0f;
}
float litres = g_consumption * car.maxfuel * 60 * 60;
float hurr;
if (g_outgauge.flags & OG_KM)
{
hurr = litres / (g_outgauge.speed * speedunit) * 100;
speed.rangemax = (int)(car.maxspeed * 1.609f / 10) * 10 + 10;
speed2.rangemax = speed.rangemax / 1.609f;
}
else
{
float gal = litres * 0.219969157;
hurr = g_outgauge.speed * speedunit / gal;
//printf("mpg %f\n", hurr);
speed.rangemax = car.maxspeed;
speed2.rangemax = speed.rangemax * 1.609f;
}
if (hurr < 0) hurr = 0;
if (hurr > 100) hurr = 100;
if (speed.rangemax < 150) {
speed.majorstep = 10;
speed.minorstep = 2;
} else {
speed.majorstep = 20;
speed.minorstep = 10;
}
if (speed2.rangemax < 150) {
speed2.majorstep = 10;
speed2.minorstep = 2;
} else {
speed2.majorstep = 20;
speed2.minorstep = 10;
}
float gsize = width * 0.20;
if (gsize > height * 0.4) gsize = height * 0.4;
speed.radius = gsize * 0.9;
speed2.radius = speed.radius * 0.6;
rpm.radius = speed.radius;
float msize = gsize * 0.2;
float symsize = gsize * 0.22;
float sgsize = height * 0.25;
fuel.radius = sgsize * 0.8;
boost.radius = sgsize * 0.8;
mpg.radius = sgsize * 0.8;
oil.radius = sgsize * 0.8;
float lsize = sgsize * 0.16;
glPushMatrix();
if (rpmleft) {
glTranslatef(width * 0.5 + gsize * 1.5, height - gsize, 0);
} else {
glTranslatef(width * 0.5 - gsize * 1.5, height - gsize, 0);
}
glColor4f(1.0, 1.0, 1.0, 1.0);
snprintf(text, sizeof text, "%d", (int)(g_outgauge.speed * speedunit));
drawText(text, font, 20, -speed.radius * 0.8, msize, msize, TA_RIGHT, TA_BOTTOM);
drawText((g_outgauge.flags & OG_KM) ? "km/h" : "mph", font, 26, -speed.radius * 0.8, msize * 0.3, msize * 0.4, TA_LEFT, TA_BOTTOM);
if (g_outgauge.dashlights & (1 << DL_PITSPEED)) {
drawSymbol2(DL_PITSPEED, g_outgauge.showlights & (1 << DL_PITSPEED), 1, 0, gsize * -0.4, symsize * 1.3, symsize * 1.3);
}
if (maxspeed > 0.001f)
{
glPushMatrix();
glScalef(speed.radius, speed.radius, 1.0);
drawDial(&speed, maxspeed * speedunit, GT_LINE);
glPopMatrix();
if (speedtimer < 13)
{
snprintf(text, sizeof text, "%0.1f%s", maxspeed * speedunit, (g_outgauge.flags & OG_KM) ? "km/h" : "mph");
drawText(text, font, 0, -speed.radius * 0.6, msize, msize, TA_CENTRE, TA_BOTTOM);
}
}
draw_gauge(&speed2, 0, -1, font, GT_NONE);
draw_gauge(&speed, g_outgauge.speed * speedunit, -1, font, GT_NEEDLE);
glPopMatrix();
glPushMatrix();
if (rpmleft) {
glTranslatef(width * 0.5 - gsize * 1.5, height - gsize, 0);
} else {
glTranslatef(width * 0.5 + gsize * 1.5, height - gsize, 0);
}
glColor4f(1.0, 1.0, 1.0, 1.0);
snprintf(text, sizeof text, "%d", (int)(g_outgauge.rpm));
drawText(text, font, 40, -rpm.radius * 0.8, msize, msize, TA_RIGHT, TA_BOTTOM);
drawText("rpm", font, 46, -rpm.radius * 0.8, msize * 0.3, msize * 0.4, TA_LEFT, TA_BOTTOM);
if (g_outgauge.dashlights & (1 << DL_SHIFT)) {
drawSymbol2(DL_SHIFT, g_outgauge.showlights & (1 << DL_SHIFT), 1, 0, gsize * -0.4, symsize * 1.3, symsize * 1.3);
}
draw_gauge(&rpm, g_outgauge.rpm, car.maxrpm, font, GT_NEEDLE);
glPopMatrix();
if (g_owncar == g_outgauge.playerid) {
glPushMatrix();
glTranslatef(width * 0.5 - gsize * 1.5, fuel.radius * 0.75, 0);
drawSymbol2(4, 0, 0, fuel.radius * -0.65, 0, lsize, lsize);
if (g_outgauge.fuel <= warn_fuel2) {
if (flash < 0.5) {
drawSymbol2(19, 1, 0, -fuel.radius * 0.6, -fuel.radius * 0.3, lsize, lsize);
}
}
else if (g_outgauge.fuel <= warn_fuel1) {
drawSymbol2(19, 0, 0, -fuel.radius * 0.6, -fuel.radius * 0.3, lsize * 0.6, lsize * 0.6);
}
draw_gauge(&fuel, g_outgauge.fuel, -1, font, GT_BAR);
drawSymbol2(5, 0, 0, mpg.radius * 0.65, 0, lsize, lsize);
draw_gauge(&mpg, hurr, -1, font, GT_BAR);
float tcsize = sgsize * 0.08;
glColor4f(1.0, 1.0, 1.0, 1.0);
drawText("Trip Computer", font, 0, tcsize * 4.8, tcsize, tcsize, TA_CENTRE, TA_BOTTOM);
//snprintf(text, sizeof text, "dist %0.1f time %0.1f fuel %0.1f", s_cars[carnum].dist * distunit, s_cars[carnum].time, s_cars[carnum].cons);
snprintf(text, sizeof text, "Rem: %0.1f%%", g_outgauge.fuel * 100);
drawText(text, font, -fuel.radius * 0.3, tcsize * 3.6, tcsize, tcsize, TA_LEFT, TA_BOTTOM);
snprintf(text, sizeof text, "Eco: %0.1f %s", hurr, (g_outgauge.flags & OG_KM) ? "l/100km" : "mpg");
drawText(text, font, -fuel.radius * 0.3, tcsize * 2.4, tcsize, tcsize, TA_LEFT, TA_BOTTOM);
float dist = litres / (g_outgauge.speed * speedunit) * (g_outgauge.fuel * car.maxfuel) * distunit;
snprintf(text, sizeof text, "Dist: %0.1f %s", dist, (g_outgauge.flags & OG_KM) ? "km" : "miles");
drawText(text, font, -fuel.radius * 0.3, tcsize * 1.2, tcsize, tcsize, TA_LEFT, TA_BOTTOM);
glPopMatrix();
}
glPushMatrix();
glTranslatef(width * 0.5 + gsize * 1.5, oil.radius * 0.75, 0);
if (g_outgauge.flags & OG_TURBO)
{
if (g_outgauge.flags & OG_BAR) {
boost.majorstep = 0.4;
boost.minorstep = 0.1;
} else {
boost.majorstep = 2.0;
boost.minorstep = 1.0;
}
float mult = (g_outgauge.flags & OG_BAR) ? 1.0 : 14.5037738;
boost.rangemax = (int)(car.maxboost * mult / boost.majorstep + 1) * boost.majorstep;
drawSymbol2(6, 0, 0, boost.radius * -0.65, 0, lsize, lsize);
draw_gauge(&boost, g_outgauge.turbo * mult, -1, font, GT_BAR);
}
//drawSymbol2(7, 0, 0, oil.radius * 0.65, 0, lsize, lsize);
//draw_gauge(&oil, g_outgauge.oiltemp, -1, font, GT_BAR);
glPopMatrix();
//glPushMatrix();
//glTranslatef(width * 0.5 + gsize * 1.5, boost.radius * 0.75, 0);
time_t rawtime;
time(&rawtime);
struct tm *timeinfo = localtime(&rawtime);
//draw_gauge(&clock, (timeinfo->tm_hour % 12) + timeinfo->tm_min / 60.0, -1, font, GT_NEEDLE);
//glPopMatrix();
//printf("%f %f\n", g_outgauge.oilpressure, g_outgauge.oiltemp);
float symspace = symsize * -1.2;
/*
glPushMatrix();
glTranslatef(width * 0.5 + symspace, height - gsize * 0.25 + symspace * 6, 0.0f);
input.radius = symsize * 0.5;
input.dial.r = 0; input.dial.g = 0; input.dial.b = 1;
draw_gauge(&input, g_outgauge.clutch, -1, font, GT_BAR);
glTranslatef(-symspace, 0, 0);
input.dial.r = 1; input.dial.g = 0; input.dial.b = 0;
draw_gauge(&input, g_outgauge.brake, -1, font, GT_BAR);
glTranslatef(-symspace, 0, 0);
input.dial.r = 0; input.dial.g = 1; input.dial.b = 0;
draw_gauge(&input, g_outgauge.throttle, -1, font, GT_BAR);
glPopMatrix();
*/
glPushMatrix();
glTranslatef(width * 0.5, height - gsize * 0.25, 0.0f);
if (g_outgauge.dashlights & (1 << DL_SIGNAL_ANY))
{
drawSymbol2(DL_SIGNAL_ANY, g_outgauge.showlights & (1 << DL_SIGNAL_ANY), 1, 0, 0, symsize, symsize);
} else {
if (g_outgauge.dashlights & (1 << DL_SIGNAL_L)) {
drawSymbol2(DL_SIGNAL_L, g_outgauge.showlights & (1 << DL_SIGNAL_L), 1, -symsize * 0.75, 0, symsize, symsize);
}
if (g_outgauge.dashlights & (1 << DL_SIGNAL_R)) {
drawSymbol2(DL_SIGNAL_R, g_outgauge.showlights & (1 << DL_SIGNAL_R), 1, symsize * 0.75, 0, symsize, symsize);
}
}
if (g_outgauge.dashlights & (1 << DL_FULLBEAM)) {
drawSymbol2(DL_FULLBEAM, g_outgauge.showlights & (1 << DL_FULLBEAM), 1, 0, symspace, symsize, symsize);
}
if (g_outgauge.dashlights & (1 << DL_HANDBRAKE)) {
drawSymbol2(DL_HANDBRAKE, g_outgauge.showlights & (1 << DL_HANDBRAKE), 1, 0, symspace * 2, symsize, symsize);
}
if (g_outgauge.dashlights & (1 << DL_ABS)) {
drawSymbol2(DL_ABS, g_outgauge.showlights & (1 << DL_ABS), 1, 0, symspace * 3, symsize, symsize);
}
if (g_outgauge.dashlights & (1 << DL_TC)) {
drawSymbol2(DL_TC, g_outgauge.showlights & (1 << DL_TC), 1, 0, symspace * 4, symsize, symsize);
}
if (g_outgauge.dashlights & (1 << DL_OILWARN)) {
if (g_outgauge.dashlights & (1 << DL_BATTERY)) {
drawSymbol2(DL_BATTERY, g_outgauge.showlights & (1 << DL_BATTERY), 1, -symsize * 0.75, symspace * 5, symsize, symsize);
}
drawSymbol2(DL_OILWARN, g_outgauge.showlights & (1 << DL_OILWARN), 1, symsize * 0.75, symspace * 5, symsize, symsize);
} else {
if (g_outgauge.dashlights & (1 << DL_BATTERY)) {
drawSymbol2(DL_BATTERY, g_outgauge.showlights & (1 << DL_BATTERY), 1, 0, symspace * 5, symsize, symsize);
}
}
glPopMatrix();
glPushMatrix();
glTranslatef(width, 0, 0);
glScalef(-height * 0.075, height * 0.075, 1.0);
glColor4f(0.15, 1.0, 0.15, 0.8);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(0.25, 0.0, 0.0);
glVertex3f(0.0, g_outgauge.throttle, 0.0);
glVertex3f(0.25, g_outgauge.throttle, 0.0);
glEnd();
glColor4f(1.0, 0.15, 0.15, 0.8);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0.30, 0.0, 0.0);
glVertex3f(0.55, 0.0, 0.0);
glVertex3f(0.30, g_outgauge.brake, 0.0);
glVertex3f(0.55, g_outgauge.brake, 0.0);
glEnd();
glColor4f(0.15, 0.15, 1.0, 0.8);
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(0.60, 0.0, 0.0);
glVertex3f(0.85, 0.0, 0.0);
glVertex3f(0.60, g_outgauge.clutch, 0.0);
glVertex3f(0.85, g_outgauge.clutch, 0.0);
glEnd();
glPopMatrix();
glPushMatrix();
glColor4f(0.15, 0.15, 1.0, 1.0);
glTranslatef(width * 0.5, 0, 0.0f);
if (g_outgauge.gear == 0) {
snprintf(text, sizeof text, "R");
} else if (g_outgauge.gear == 1) {
snprintf(text, sizeof text, "N");
} else {
snprintf(text, sizeof text, "%d", g_outgauge.gear - 1);
}
drawText(text, font, 0, sgsize * 0.7, sgsize * 0.7, sgsize * 0.7, TA_CENTRE, TA_BOTTOM);
snprintf(text, sizeof text, "%s", s_carinfo[g_outgauge.playerid].cname);
drawText(text, font, 0, sgsize * 0.4, sgsize * 0.2, sgsize * 0.2, TA_CENTRE, TA_BOTTOM);
snprintf(text, sizeof text, "%s", s_conninfo[s_carinfo[g_outgauge.playerid].ucid].uname);
drawText(text, font, 0, sgsize * 0.2, sgsize * 0.15, sgsize * 0.15, TA_CENTRE, TA_BOTTOM);
//snprintf(text, sizeof text, "dist %0.1f time %0.1f fuel %0.1f", s_cars[carnum].dist * distunit, s_cars[carnum].time, s_cars[carnum].cons);
//snprintf(text, sizeof text, "p %d r %d; %d %d, %u", g_pressed, g_released, volume, mode, mode_timer);
//drawText(text, font, 0, sgsize * 1.2, sgsize * 0.2, sgsize * 0.2, TA_CENTRE, TA_CENTRE);
//snprintf(text, sizeof text, "s %u c %u; %u", g_shift_time, g_ctrl_time, g_outgauge.time);
//drawText(text, font, 0, sgsize * 1.5, sgsize * 0.2, sgsize * 0.2, TA_CENTRE, TA_CENTRE);
snprintf(text, sizeof text, "%02d:%02d", timeinfo->tm_hour, timeinfo->tm_min);
drawText(text, font, 0, sgsize * 1.3, sgsize * 0.2, sgsize * 0.2, TA_CENTRE, TA_BOTTOM);
glPopMatrix();
/*
int ox = s_carinfo[g_outgauge.playerid].x;
int oy = s_carinfo[g_outgauge.playerid].y;
int oz = s_carinfo[g_outgauge.playerid].z;
int head = s_carinfo[g_outgauge.playerid].heading;
int speed = s_carinfo[g_outgauge.playerid].speed;
glPushMatrix();
glTranslatef(width / 2, height / 2, 0);
int i;
for (i = 0; i < 256; i++)
{
struct carinfo *ci = s_carinfo + i;
if (!ci->active) continue;
float dx = (ci->x - ox) / zoom;
float dy = (ci->y - oy) / zoom;
//float ddx = (ci->x - ox) / 65536.0;
//float ddy = (ci->y - oy) / 65536.0;
//ci->dist = sqrtf(ddx * ddx + ddy * ddy);
// if (ci->dist >= width / 2 && ci->dist >= height / 2) continue;
const struct conninfo *pi = s_conninfo + ci->ucid;
int idx = (ci->x - ox) >> 16;
int idy = (ci->y - oy) >> 16;
int dist = sqrt(idx * idx + idy * idy);
snprintf(text, sizeof text, "%s - %d (%0.1f %s)", pi->uname, dist, (ci->speed - speed) / 327.68f * speedunit, (g_outgauge.flags & OG_KM) ? "km/h" : "mph");
//printf("%d %s %d %d\n", i, text, head / 182, ci->heading / 182);
glPushMatrix();
glRotatef(-head / 182.0444f, 0.0, 0.0, 1.0);
glTranslatef(dx, dy, 0);
if (ci->hist > 0) {
glBegin(GL_LINE_STRIP);
int j;
for (j = CARPATHSIZE; j > 0; j--)
{
int d = (j + ci->hist - 1) % CARPATHSIZE;
if (ci->hist_x[d] == 0 && ci->hist_y[d] == 0) continue;
glColor4f(ci->hist_s[d] / 32768.0f, 1.0 - ci->hist_s[d] / 32768.0f, 0.0, 0.9);
glVertex3f((ci->hist_x[d] - ci->x) / zoom, (ci->hist_y[d] - ci->y) / zoom, 0.0);
}
glEnd();
}
if (pi->state == 1) {
glColor4f(1.0, 0.0, 0.0, 0.5);
} else if (pi->state == 2) {
glColor4f(0.0, 1.0, 1.0, 0.5);
} else {
glColor4f(2.0, 1.0, 1.0, 0.5);
}
glRotatef(head / 182.0444f, 0.0, 0.0, 1.0);
drawText(text, font, 5, 3, 10, 10, TA_LEFT, TA_TOP);
glRotatef(-(head - ci->heading) / 182.0444, 0.0, 0.0, 1.0);
glBegin(GL_TRIANGLES);
glVertex3f(0, 5, 0);
glVertex3f(2.5, -5, 0);
glVertex3f(-2.5, -5, 0);
glEnd();
glPopMatrix();
}
glPopMatrix();
*/
int os1 = (g_outgauge.showlights & (1 << DL_SIGNAL_L)) ? FX_ON : FX_OFF;
int os2 = (g_outgauge.showlights & (1 << DL_SIGNAL_R)) ? FX_ON : FX_OFF;
int os3 = (g_outgauge.showlights & (1 << DL_SIGNAL_ANY)) ? FX_ON : FX_OFF;
int os6 = (g_outgauge.showlights & (1 << DL_PITSPEED)) ? FX_ON : FX_OFF;
if (s1 != os1) {
s1 = os1;
if (!g_fade) audio_play(0, s1);
}
if (s2 != os2) {
s2 = os2;
if (!g_fade) audio_play(1, s2);
}
if (s3 != os3) {
s3 = os3;
if (!g_fade) audio_play(2, s3);
}
if (s6 != os6) {
s6 = os6;
if (!g_fade) audio_play(5, s6);
}
if (g_outgauge.fuel > warn_fuel1 || g_outgauge.rpm == 0)
{
bing = 0;
}
else if (g_outgauge.fuel <= warn_fuel2)
{
bing = 2;
}
else if (bing != 1 && g_outgauge.fuel <= warn_fuel1)
{
bing = 1;
if (!g_fade) audio_play(3, FX_BING);
}
if (g_fade && fade < 0.8) {
fade = fade + 0.01;
} else if (!g_fade && fade > 0.0) {
fade = fade - 0.01;
}
//glPopMatrix();
if (dofade && fade > 0) {
glColor4f(0.0, 0.0, 0.0, fade);
glBegin(GL_QUADS);
glVertex3f(0.0, 0.0, 0.0);
glVertex3f(width, 0.0, 0.0);
glVertex3f(width, height, 0.0);
glVertex3f(0.0, height, 0.0);
glEnd();
}
glfwSwapBuffers();
// printf("%f\n", g_outgauge.speed * 2.23693629);
running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam( GLFW_OPENED) && !glfwGetMouseButton(1);
/*
int wheel = glfwGetMouseWheel();
if (wheel >= 1) {
zoom = 65536.0 * wheel;
} else {
zoom = 65536 / (-wheel + 2);
}
*/
//printf("%u %u %u\n", g_outgauge.flags, g_outgauge.dashlights, g_outgauge.showlights);
usleep(100);
}
s_running = 0;
audio_deinit();
glfwTerminate();
network_worker_deinit();
config_set_int("port", g_outgauge_port);
config_set_int("fullscreen", fullscreen);
config_set_int("width", width);
config_set_int("height", height);
config_set_int("volume", volume);
config_set_int("rpmleft", rpmleft);
config_set_int("fade", dofade);
config_set_string("insim_host", insim_host);
config_set_int("insim_port", g_insim_port);
config_set_float("warn_fuel1", warn_fuel1);
config_set_float("warn_fuel2", warn_fuel2);
config_deinit();
return 0;
}