separate label and aircraft label classes [in progress]

This commit is contained in:
nathan 2021-03-19 21:13:43 -07:00
parent 2c484dc5fd
commit 383081d0de
13 changed files with 890 additions and 643 deletions

View file

@ -30,34 +30,16 @@
// //
#include "Aircraft.h" #include "Aircraft.h"
#include "AircraftLabel.h"
Aircraft::Aircraft(uint32_t addr) { Aircraft::Aircraft(uint32_t addr) {
this->addr = addr; this->addr = addr;
prev_seen = 0; prev_seen = 0;
x = 0;
y = 0;
cx = 0;
cy = 0;
w = 0;
h = 0;
target_w = 0;
target_h = 0;
opacity = 0;
target_opacity = 0;
ox = 0;
oy = 0;
dox = 0;
doy = 0;
ddox = 0;
ddoy = 0;
lon = 0; lon = 0;
lat = 0; lat = 0;
labelLevel = 0; label = NULL;
next = NULL; next = NULL;
} }

View file

@ -35,6 +35,8 @@
#include <vector> #include <vector>
#include <chrono> #include <chrono>
class AircraftLabel;
class Aircraft { class Aircraft {
public: public:
uint32_t addr; // ICAO address uint32_t addr; // ICAO address
@ -55,6 +57,9 @@ public:
std::vector <float> lonHistory, latHistory, headingHistory; std::vector <float> lonHistory, latHistory, headingHistory;
std::vector <std::chrono::high_resolution_clock::time_point> timestampHistory; std::vector <std::chrono::high_resolution_clock::time_point> timestampHistory;
AircraftLabel *label;
// float oldLon[TRAIL_LENGTH]; // float oldLon[TRAIL_LENGTH];
// float oldLat[TRAIL_LENGTH]; // float oldLat[TRAIL_LENGTH];
// float oldHeading[TRAIL_LENGTH]; // float oldHeading[TRAIL_LENGTH];
@ -69,11 +74,12 @@ public:
//// label stuff -> should go to aircraft icon class //// label stuff -> should go to aircraft icon class
int x, y, cx, cy; // int x, y, cx, cy;
float w, h, target_w, target_h; int x, y;
float ox, oy, dox, doy, ddox, ddoy; // float w, h, target_w, target_h;
float labelLevel; // float ox, oy, dox, doy, ddox, ddoy;
float opacity, target_opacity; // float labelLevel;
// float opacity, target_opacity;
/// methods /// methods

424
AircraftLabel.cpp Normal file
View file

@ -0,0 +1,424 @@
#include "AircraftLabel.h"
#include "Aircraft.h"
#include "SDL2/SDL2_gfxPrimitives.h"
static float sign(float x) {
return (x > 0) - (x < 0);
}
void AircraftLabel::update() {
char flight[10] = "";
snprintf(flight,10," %s", p->flight);
flightLabel.setText(flight);
char alt[10] = "";
if (metric) {
snprintf(alt,10," %dm", (int) (p->altitude / 3.2828));
} else {
snprintf(alt,10," %d'", p->altitude);
}
altitudeLabel.setText(alt);
char speed[10] = "";
if (metric) {
snprintf(speed,10," %dkm/h", (int) (p->speed * 1.852));
} else {
snprintf(speed,10," %dmph", p->speed);
}
speedLabel.setText(speed);
}
void AircraftLabel::clearAcceleration() {
ddx = 0;
ddy = 0;
}
void AircraftLabel::calculateForces(Aircraft *check_p) {
int p_left = x;
int p_right = x + w;
int p_top = y;
int p_bottom = y + h;
float boxmid_x = (float)(p_left + p_right) / 2.0f;
float boxmid_y = (float)(p_top + p_bottom) / 2.0f;
float offset_x = boxmid_x - p->x;
float offset_y = boxmid_y - p->y;
float target_length_x = attachment_dist + w / 2.0f;
float target_length_y = attachment_dist + h / 2.0f;
// stay icon_dist away from own icon
ddx -= sign(offset_x) * attachment_force * (fabs(offset_x) - target_length_x);
ddy -= sign(offset_y) * attachment_force * (fabs(offset_y) - target_length_y);
// // //screen edge
if(p_left < edge_margin) {
ddx += boundary_force * (float)(edge_margin - p_left);
}
if(p_right > screen_width - edge_margin) {
ddx += boundary_force * (float)(screen_width - edge_margin - p_right);
}
if(p_top < edge_margin) {
ddy += boundary_force * (float)(edge_margin - p_top);
}
if(p_bottom > screen_height - edge_margin) {
ddy += boundary_force * (float)(screen_height - edge_margin - p_bottom);
}
float all_x = 0;
float all_y = 0;
int count = 0;
//check against other labels
float density_max = 0;
while(check_p) {
if(check_p->addr == p->addr) {
check_p = check_p->next;
continue;
}
if(!check_p->label) {
check_p = check_p->next;
continue;
}
//calculate density for label display level (inversely proportional to area of smallest box connecting this to neighbor)
float density = 1.0 / (0.001f + fabs(x - check_p->label->x) * fabs (x - check_p->label->y));
if(density > density_max) {
density_max = density;
}
density = 1.0 / (0.001f + fabs(x - check_p->x) * fabs(x - check_p->y));
if(density > density_max) {
density_max = density;
}
int check_left = check_p->label->x;
int check_right = check_p->label->x + check_p->label->w;
int check_top = check_p->label->y;
int check_bottom = check_p->label->y + check_p->label->h;
float icon_x = (float)check_p->x;
float icon_y = (float)check_p->y;
float checkboxmid_x = (float)(check_left + check_right) / 2.0f;
float checkboxmid_y = (float)(check_top + check_bottom) / 2.0f;
float offset_x = boxmid_x - checkboxmid_x;
float offset_y = boxmid_y - checkboxmid_y;
float target_length_x = label_dist + (float)(check_p->label->w + w) / 2.0f;
float target_length_y = label_dist + (float)(check_p->label->h + h) / 2.0f;
float x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
float y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
// stay at least label_dist away from other icons
if(x_mag > 0 && y_mag > 0) {
ddx += sign(offset_x) * label_force * x_mag;
ddy += sign(offset_y) * label_force * y_mag;
}
// stay at least icon_dist away from other icons
offset_x = boxmid_x - check_p->x;
offset_y = boxmid_y - check_p->y;
target_length_x = icon_dist + (float)check_p->label->w / 2.0f;
target_length_y = icon_dist + (float)check_p->label->h / 2.0f;
x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
if(x_mag > 0 && y_mag > 0) {
ddx += sign(offset_x) * icon_force * x_mag;
ddy += sign(offset_y) * icon_force * y_mag;
}
all_x += sign(boxmid_x - checkboxmid_x);
all_y += sign(boxmid_y - checkboxmid_y);
count++;
check_p = check_p -> next;
}
// move away from others
ddx += density_force * all_x / count;
ddy += density_force * all_y / count;
// label drawlevel hysteresis
float density_mult = 100.0f;
float level_rate = 0.0005f;
if(labelLevel < -1.25f + density_mult * density_max) {
labelLevel += level_rate;
} else if (labelLevel > 0.5f + density_mult * density_max) {
labelLevel -= level_rate;
}
}
void AircraftLabel::applyForces() {
dx += ddx;
dy += ddy;
dx *= damping_force;
dy *= damping_force;
if(fabs(dx) > velocity_limit) {
dx = sign(dx) * velocity_limit;
}
if(fabs(dy) > velocity_limit) {
dy = sign(dy) * velocity_limit;
}
if(fabs(dx) < 0.01f) {
dx = 0;
}
if(fabs(dy) < 0.01f) {
dy = 0;
}
x += dx;
y += dy;
// x = p->cx + (int)round(p->ox);
// y = p->cy + (int)round(p->oy);
}
void AircraftLabel::draw(SDL_Renderer *renderer) {
//don't draw first time
if(x == 0 || y == 0) {
return;
}
int totalWidth = 0;
int totalHeight = 0;
// int margin = 4 * screen_uiscale;
int margin = 4;
SDL_Rect outRect;
if(opacity == 0 && labelLevel < 2) {
target_opacity = 1.0f;
}
if(opacity > 0 && labelLevel >= 2) {
target_opacity = 0.0f;
}
opacity += 0.25f * (target_opacity - opacity);
if(opacity < 0.05f) {
opacity = 0;
}
if(w != 0) {
SDL_Color drawColor = style.labelLineColor;
drawColor.a = (int) (255.0f * opacity);
//this would need to be set in view (settable label level etc)
// if(p == selectedAircraft) {
// drawColor = style.selectedColor;
// }
int tick = 4;
int anchor_x, anchor_y, exit_x, exit_y;
if(x + w / 2 > p->x) {
anchor_x = x;
} else {
anchor_x = x + w;
}
if(y + h / 2 > p->y) {
anchor_y = y - margin;
} else {
anchor_y = y + h + margin;
}
if(abs(anchor_x - p->x) > abs(anchor_y - p->y)) {
exit_x = (anchor_x + p->x) / 2;
exit_y = anchor_y;
} else {
exit_x = anchor_x;
exit_y = (anchor_y + p->y) / 2;
}
Sint16 vx[3] = {
static_cast<Sint16>(p->x),
static_cast<Sint16>(exit_x),
static_cast<Sint16>(anchor_x)};
Sint16 vy[3] = {
static_cast<Sint16>(p->y),
static_cast<Sint16>(exit_y),
static_cast<Sint16>(anchor_y)};
boxRGBA(renderer, x, y, x + w, y + h, 0, 0, 0, 255);
bezierRGBA(renderer, vx, vy, 3, 2, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
//lineRGBA(renderer, x,y - margin, x + tick, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x,y - margin, x + w, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x,y - margin, x, y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
// lineRGBA(renderer, x + w, y - margin, x + w - tick, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x + w, y - margin, x + w, y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
//lineRGBA(renderer, x, y + h + margin, x + tick, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x, y + h + margin, x + w, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x, y + h + margin, x, y + h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
// lineRGBA(renderer, x + w, y + h + margin,x + w - tick, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, x + w, y + h + margin,x + w, y + h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
}
// if(labelLevel < 2 || p == selectedAircraft) {
//need externally settable label level
if(labelLevel < 2) {
// drawSignalMarks(p, x, y);
SDL_Color drawColor = style.labelColor;
drawColor.a = (int) (255.0f * opacity);
flightLabel.setFGColor(drawColor);
flightLabel.draw(renderer);
// outRect = drawString(flight, x, y, mapBoldFont, drawColor);
outRect = flightLabel.getRect();
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
}
// if(labelLevel < 1 || p == selectedAircraft) {
if(labelLevel < 1) {
SDL_Color drawColor = style.subLabelColor;
drawColor.a = (int) (255.0f * opacity);
// drawStringBG(alt, x, y + currentLine * mapFontHeight, mapFont, style.subLabelColor, style.labelBackground);
// outRect = drawString(alt, x, y + totalHeight, mapFont, drawColor);
altitudeLabel.setFGColor(drawColor);
altitudeLabel.draw(renderer);
outRect = altitudeLabel.getRect();
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
// drawStringBG(speed, x, y + currentLine * mapFontHeight, mapFont, style.subLabelColor, style.labelBackground);
// outRect = drawString(speed, x, y + totalHeight, mapFont, drawColor);
speedLabel.setFGColor(drawColor);
speedLabel.draw(renderer);
outRect = speedLabel.getRect();
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
}
//label debug
// char debug[25] = "";
// snprintf(debug,25,"%1.2f", p->labelLevel);
// drawString(debug, p->x, p->y + totalHeight, mapFont, style.red);
// if(maxCharCount > 1) {
// Sint16 vx[4] = {
// static_cast<Sint16>(p->cx),
// static_cast<Sint16>(p->cx + (p->x - p->cx) / 2),
// static_cast<Sint16>(p->x),
// static_cast<Sint16>(p->x)};
// Sint16 vy[4] = {
// static_cast<Sint16>(p->cy),
// static_cast<Sint16>(p->cy + (p->y - p->cy) / 2),
// static_cast<Sint16>(p->y - mapFontHeight),
// static_cast<Sint16>(p->y)};
// if(p->cy > p->y + currentLine * mapFontHeight) {
// vy[2] = p->y + currentLine * mapFontHeight + mapFontHeight;
// vy[3] = p->y + currentLine * mapFontHeight;
// }
// bezierRGBA(renderer,vx,vy,4,2,style.labelLineColor.r,style.labelLineColor.g,style.labelLineColor.b,SDL_ALPHA_OPAQUE);
// lineRGBA(renderer,p->x,p->y,p->x,p->y+currentLine*mapFontHeight,style.labelLineColor.r,style.labelLineColor.g,style.labelLineColor.b,SDL_ALPHA_OPAQUE);
// }
target_w = totalWidth;
target_h = totalHeight;
w += 0.25f * (target_w - w);
h += 0.25f * (target_h - h);
if(w < 0.05f) {
w = 0;
}
if(h < 0.05f) {
h = 0;
}
}
AircraftLabel::AircraftLabel(Aircraft *p, bool metric, int screen_width, int screen_height, TTF_Font *font) {
this->p = p;
this->metric = metric;
x = p->x;
y = p->y + 20; //*screen_uiscale
w = 0;
h = 0;
target_w = 0;
target_h = 0;
opacity = 0;
target_opacity = 0;
dx = 0;
dy = 0;
ddx = 0;
ddy = 0;
this->screen_width = screen_width;
this->screen_height = screen_height;
labelLevel = 0;
flightLabel.setFont(font);
altitudeLabel.setFont(font);
speedLabel.setFont(font);
}

70
AircraftLabel.h Normal file
View file

@ -0,0 +1,70 @@
#include <string>
#include "SDL2/SDL_ttf.h"
#include "Label.h"
#include "Style.h"
class Aircraft;
class AircraftLabel {
public:
void update();
void clearAcceleration();
void calculateForces(Aircraft *check_p);
void applyForces();
void draw(SDL_Renderer *renderer);
AircraftLabel(Aircraft *p, bool metric, int screen_width, int screen_height, TTF_Font *font);
private:
Aircraft *p;
Label flightLabel;
Label altitudeLabel;
Label speedLabel;
int labelLevel;
bool metric;
float x;
float y;
float w;
float h;
float target_w;
float target_h;
float dx;
float dy;
float ddx;
float ddy;
float opacity;
float target_opacity;
float pressure;
int screen_width;
int screen_height;
///////////
float label_force = 0.001f;
float label_dist = 2.0f;
float density_force = 0.05f;
float attachment_force = 0.0015f;
float attachment_dist = 10.0f;
float icon_force = 0.001f;
float icon_dist = 15.0f;
float boundary_force = 0.01f;
float damping_force = 0.85f;
float velocity_limit = 2.0f;
float edge_margin = 15.0f;
Style style;
};

78
Label.cpp Normal file
View file

@ -0,0 +1,78 @@
#include "Label.h"
#include <string>
void Label::draw(SDL_Renderer *renderer) {
SDL_Rect rect = getRect();
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, &rect);
SDL_DestroyTexture(texture);
}
void Label::makeSurface() {
// if(BGColor.a = 0) {
surface = TTF_RenderUTF8_Solid(font, text.c_str(), FGColor);
// } else {
// surface = TTF_RenderUTF8_Shaded(font, text.c_str(), FGColor, BGColor);
// }
if (surface == NULL)
{
printf("Couldn't create surface for String %s: %s\n", text.c_str(), SDL_GetError());
}
}
SDL_Rect Label::getRect() {
SDL_Rect rect = {0,0,0,0};
if(!text.length()) {
return rect;
}
if(surface == NULL) {
return rect;
}
rect.x = x;
rect.y = y;
rect.w = surface->w;
rect.h = surface->h;
return rect;
}
void Label::setText(std::string text) {
this->text = text;
makeSurface();
}
void Label::setPosition(int x, int y) {
this->x = x;
this->y = y;
}
void Label::setFont(TTF_Font *font) {
this->font = font;
}
void Label::setFGColor(SDL_Color color) {
this->FGColor = color;
}
void Label::setBGColor(SDL_Color color) {
this->BGColor = color;
}
Label::Label() {
BGColor = {0, 0, 0, 0};
surface = NULL;
}
Label::~Label() {
SDL_FreeSurface(surface);
}

32
Label.h Normal file
View file

@ -0,0 +1,32 @@
#include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h"
#include <string>
class Label {
public:
void draw(SDL_Renderer *renderer);
void setText(std::string text);
void setPosition(int x, int y);
void setFont(TTF_Font *font);
void setFGColor(SDL_Color color);
void setBGColor(SDL_Color color);
SDL_Rect getRect();
Label();
~Label();
private:
void makeSurface();
std::string text;
int x;
int y;
TTF_Font *font;
SDL_Color FGColor;
SDL_Color BGColor;
SDL_Surface *surface;
};

View file

@ -3,8 +3,8 @@
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local # sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
# #
CXXFLAGS=-O2 -std=c++11 CXXFLAGS=-O2 -std=c++11 -g
LIBS= -lm -lSDL2 -lSDL2_ttf -lSDL2_gfx LIBS= -lm -lSDL2 -lSDL2_ttf -lSDL2_gfx -g
CXX=g++ CXX=g++
all: viz1090 all: viz1090
@ -12,8 +12,8 @@ all: viz1090
%.o: %.c %.cpp %.o: %.c %.cpp
$(CXX) $(CXXFLAGS) $(EXTRACFLAGS) -c $< $(CXX) $(CXXFLAGS) $(EXTRACFLAGS) -c $<
viz1090: viz1090.o AppData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o viz1090: viz1090.o AppData.o AircraftList.o Aircraft.o Label.o AircraftLabel.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o
$(CXX) -o viz1090 viz1090.o AppData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o $(LIBS) $(LDFLAGS) $(CXX) -o viz1090 viz1090.o AppData.o AircraftList.o Aircraft.o Label.o AircraftLabel.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o $(LIBS) $(LDFLAGS)
clean: clean:
rm -f *.o viz1090 rm -f *.o viz1090

View file

@ -342,7 +342,7 @@ Map::Map() {
} }
// std::cout << "[" << x << "," << y << "] " << assemble << "\n"; // std::cout << "[" << x << "," << y << "] " << assemble << "\n";
Label *label = new Label(lon,lat,assemble); MapLabel *label = new MapLabel(lon,lat,assemble);
mapnames.push_back(label); mapnames.push_back(label);
} }
@ -371,7 +371,7 @@ Map::Map() {
} }
// std::cout << "[" << x << "," << y << "] " << assemble << "\n"; // std::cout << "[" << x << "," << y << "] " << assemble << "\n";
Label *label = new Label(lon,lat,assemble); MapLabel *label = new MapLabel(lon,lat,assemble);
airportnames.push_back(label); airportnames.push_back(label);
} }

10
Map.h
View file

@ -40,16 +40,16 @@ typedef struct Point{
float lon; float lon;
} Point; } Point;
typedef struct Label{ typedef struct MapLabel{
Point location; Point location;
std::string text; std::string text;
Label(float lon, float lat, std::string text) { MapLabel(float lon, float lat, std::string text) {
this->location.lon = lon; this->location.lon = lon;
this->location.lat = lat; this->location.lat = lat;
this->text = text; this->text = text;
} }
} Label; } MapLabel;
typedef struct Line{ typedef struct Line{
float lat_min; float lat_min;
@ -125,8 +125,8 @@ public:
std::vector<Line*> getLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max); std::vector<Line*> getLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max);
std::vector<Line*> getLines(float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max); std::vector<Line*> getLines(float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max);
std::vector<Label*> mapnames; std::vector<MapLabel*> mapnames;
std::vector<Label*> airportnames; std::vector<MapLabel*> airportnames;
Map(); Map();

94
Style.h Normal file
View file

@ -0,0 +1,94 @@
#ifndef STYLE_H
#define STYLE_H
#include "SDL2/SDL.h"
//
// This should go to a full theming class
//
typedef struct Style {
SDL_Color backgroundColor;
SDL_Color selectedColor;
SDL_Color planeColor;
SDL_Color planeGoneColor;
SDL_Color trailColor;
SDL_Color geoColor;
SDL_Color airportColor;
SDL_Color labelColor;
SDL_Color labelLineColor;
SDL_Color subLabelColor;
SDL_Color labelBackground;
SDL_Color scaleBarColor;
SDL_Color buttonColor;
SDL_Color buttonBackground;
SDL_Color buttonOutline;
SDL_Color clickColor;
SDL_Color black;
SDL_Color white;
SDL_Color red;
SDL_Color green;
SDL_Color blue;
//
// todo separate style stuff
//
Style() {
SDL_Color pink = {249,38,114,255};
SDL_Color purple = {85, 0, 255,255};
SDL_Color purple_dark = {33, 0, 122,255};
SDL_Color blue = {102,217,239,255};
SDL_Color blue_dark = {102,217,239,255};
SDL_Color green = {0,255,234,255};
SDL_Color green_dark = {24,100,110,255};
SDL_Color yellow = {216,255,0,255};
SDL_Color yellow_dark = {90,133,50,255};
SDL_Color orange = {253,151,31,255};
SDL_Color grey_light = {196,196,196,255};
SDL_Color grey = {127,127,127,255};
SDL_Color grey_dark = {64,64,64,255};
black = {0,0,0,255};
white = {255,255,255,255};
red = {255,0,0,255};
green = {0,255,0,255};
blue = {0,0,255,255};
backgroundColor = black;
selectedColor = pink;
planeColor = yellow;
planeGoneColor = grey;
trailColor = yellow_dark;
geoColor = purple_dark;
airportColor = purple;
labelColor = white;
labelLineColor = grey_dark;
subLabelColor = grey;
labelBackground = black;
scaleBarColor = grey_light;
buttonColor = grey_light;
buttonBackground = black;
buttonOutline = grey_light;
clickColor = grey;
}
} Style;
#endif

73
Text.cpp Normal file
View file

@ -0,0 +1,73 @@
#include "SDL2/SDL2_gfxPrimitives.h"
#include "Text.h"
SDL_Rect Text::drawString(std::string text, int x, int y, TTF_Font *font, SDL_Color color)
{
SDL_Rect dest = {0,0,0,0};
if(!text.length()) {
return dest;
}
SDL_Surface *surface;
surface = TTF_RenderUTF8_Solid(font, text.c_str(), color);
if (surface == NULL)
{
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
return dest;
}
dest.x = x;
dest.y = y;
dest.w = surface->w;
dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
return dest;
}
SDL_Rect Text::drawStringBG(std::string text, int x, int y, TTF_Font *font, SDL_Color color, SDL_Color bgColor) {
SDL_Rect dest = {0,0,0,0};
if(!text.length()) {
return dest;
}
SDL_Surface *surface;
surface = TTF_RenderUTF8_Shaded(font, text.c_str(), color, bgColor);
if (surface == NULL)
{
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
return dest;
}
dest.x = x;
dest.y = y;
dest.w = surface->w;
dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
return dest;
}
// check if text has changed and surface exists
// redraw existing surface
// or make new surface
// for BG, draw bg size of surface
// draw surface

604
View.cpp
View file

@ -37,6 +37,8 @@
#include "View.h" #include "View.h"
#include "AircraftLabel.h"
#include <iostream> #include <iostream>
#include <thread> #include <thread>
@ -55,10 +57,6 @@ static float elapsed_s(std::chrono::high_resolution_clock::time_point ref) {
return (fseconds { now() - ref}).count(); return (fseconds { now() - ref}).count();
} }
static float sign(float x) {
return (x > 0) - (x < 0);
}
static float clamp(float in, float min, float max) { static float clamp(float in, float min, float max) {
float out = in; float out = in;
@ -225,9 +223,6 @@ int View::outOfBounds(int x, int y, int left, int top, int right, int bottom) {
} }
} }
//
// Font stuff
//
TTF_Font* View::loadFont(const char *name, int size) TTF_Font* View::loadFont(const char *name, int size)
{ {
@ -251,6 +246,28 @@ void View::closeFont(TTF_Font *font)
} }
} }
void View::font_init() {
mapFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * screen_uiscale);
mapBoldFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
listFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * screen_uiscale);
messageFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
labelFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
mapFontWidth = 5 * screen_uiscale;
mapFontHeight = 12 * screen_uiscale;
messageFontWidth = 6 * screen_uiscale;
messageFontHeight = 12 * screen_uiscale;
labelFontWidth = 6 * screen_uiscale;
labelFontHeight = 12 * screen_uiscale;
}
// //
// SDL Utils // SDL Utils
// //
@ -300,90 +317,9 @@ void View::SDL_init() {
} }
} }
void View::font_init() {
mapFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * screen_uiscale);
mapBoldFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
listFont = loadFont("font/TerminusTTF-4.46.0.ttf", 12 * screen_uiscale);
messageFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
labelFont = loadFont("font/TerminusTTF-Bold-4.46.0.ttf", 12 * screen_uiscale);
mapFontWidth = 5 * screen_uiscale;
mapFontHeight = 12 * screen_uiscale;
messageFontWidth = 6 * screen_uiscale;
messageFontHeight = 12 * screen_uiscale;
labelFontWidth = 6 * screen_uiscale;
labelFontHeight = 12 * screen_uiscale;
}
SDL_Rect View::drawString(std::string text, int x, int y, TTF_Font *font, SDL_Color color)
{
SDL_Rect dest = {0,0,0,0};
if(!text.length()) {
return dest;
}
SDL_Surface *surface;
surface = TTF_RenderUTF8_Solid(font, text.c_str(), color);
if (surface == NULL)
{
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
return dest;
}
dest.x = x;
dest.y = y;
dest.w = surface->w;
dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
return dest;
}
SDL_Rect View::drawStringBG(std::string text, int x, int y, TTF_Font *font, SDL_Color color, SDL_Color bgColor) {
SDL_Rect dest = {0,0,0,0};
if(!text.length()) {
return dest;
}
SDL_Surface *surface;
surface = TTF_RenderUTF8_Shaded(font, text.c_str(), color, bgColor);
if (surface == NULL)
{
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
return dest;
}
dest.x = x;
dest.y = y;
dest.w = surface->w;
dest.h = surface->h;
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_RenderCopy(renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
return dest;
}
// //
// Status boxes // Status boxes -> move to separate class
// //
void View::drawStatusBox(int *left, int *top, std::string label, std::string message, SDL_Color color) { void View::drawStatusBox(int *left, int *top, std::string label, std::string message, SDL_Color color) {
@ -410,10 +346,18 @@ void View::drawStatusBox(int *left, int *top, std::string label, std::string mes
roundedRectangleRGBA(renderer, *left, *top, *left + labelWidth + messageWidth, *top + messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE); roundedRectangleRGBA(renderer, *left, *top, *left + labelWidth + messageWidth, *top + messageFontHeight, ROUND_RADIUS,color.r, color.g, color.b, SDL_ALPHA_OPAQUE);
} }
drawString(label, *left + labelFontWidth/2, *top, labelFont, style.buttonBackground); Label currentLabel;
currentLabel.setFont(labelFont);
currentLabel.setFGColor(style.buttonBackground);
currentLabel.setPosition(*left + labelFontWidth/2, *top);
currentLabel.setText(label);
currentLabel.draw(renderer);
//message currentLabel.setFont(messageFont);
drawString(message, *left + labelWidth + messageFontWidth/2, *top, messageFont, color); currentLabel.setFGColor(color);
currentLabel.setPosition(*left + labelWidth + messageFontWidth/2, *top);
currentLabel.setText(message);
currentLabel.draw(renderer);
*left = *left + labelWidth + messageWidth + PAD; *left = *left + labelWidth + messageWidth + PAD;
} }
@ -635,7 +579,12 @@ void View::drawScaleBars()
snprintf(scaleLabel,13,"%dmi", (int)pow(10,scalePower)); snprintf(scaleLabel,13,"%dmi", (int)pow(10,scalePower));
} }
drawString(scaleLabel, 10+scaleBarDist, 15*screen_uiscale, mapFont, style.scaleBarColor); Label currentLabel;
currentLabel.setFont(mapFont);
currentLabel.setFGColor(style.scaleBarColor);
currentLabel.setPosition(10+scaleBarDist, 15*screen_uiscale);
currentLabel.setText(scaleLabel);
currentLabel.draw(renderer);
scalePower++; scalePower++;
scaleBarDist = screenDist((float)pow(10,scalePower)); scaleBarDist = screenDist((float)pow(10,scalePower));
@ -740,7 +689,11 @@ void View::drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen
void View::drawPlaceNames() { void View::drawPlaceNames() {
for(std::vector<Label*>::iterator label = map.mapnames.begin(); label != map.mapnames.end(); ++label) { Label currentLabel;
currentLabel.setFont(mapFont);
currentLabel.setFGColor(style.geoColor);
for(std::vector<MapLabel*>::iterator label = map.mapnames.begin(); label != map.mapnames.end(); ++label) {
float dx, dy; float dx, dy;
int x,y; int x,y;
@ -751,10 +704,12 @@ void View::drawPlaceNames() {
continue; continue;
} }
drawString((*label)->text, x, y, mapFont, style.geoColor); currentLabel.setText((*label)->text);
currentLabel.setPosition(x,y);
currentLabel.draw(renderer);
} }
for(std::vector<Label*>::iterator label = map.airportnames.begin(); label != map.airportnames.end(); ++label) { for(std::vector<MapLabel*>::iterator label = map.airportnames.begin(); label != map.airportnames.end(); ++label) {
float dx, dy; float dx, dy;
int x,y; int x,y;
@ -765,7 +720,9 @@ void View::drawPlaceNames() {
continue; continue;
} }
drawString((*label)->text, x, y, listFont, style.airportColor); currentLabel.setText((*label)->text);
currentLabel.setPosition(x,y);
currentLabel.draw(renderer);
} }
} }
@ -879,429 +836,45 @@ void View::drawSignalMarks(Aircraft *p, int x, int y) {
void View::drawPlaneText(Aircraft *p) { void View::drawPlaneText(Aircraft *p) {
if(!p->label) {
//don't draw first time p->label = new AircraftLabel(p,metric,screen_width, screen_height, mapFont);
if(p->x == 0 || p->y == 0) {
return;
} }
int charCount; p->label->update();
int totalWidth = 0; p->label->draw(renderer);
int totalHeight = 0;
int margin = 4 * screen_uiscale;
SDL_Rect outRect;
if(p->opacity == 0 && p->labelLevel < 2) {
p->target_opacity = 1.0f;
}
if(p->opacity > 0 && p->labelLevel >= 2) {
p->target_opacity = 0.0f;
}
p->opacity += 0.25f * (p->target_opacity - p->opacity);
if(p->opacity < 0.05f) {
p->opacity = 0;
}
if(p->w != 0) {
SDL_Color drawColor = style.labelLineColor;
drawColor.a = (int) (255.0f * p->opacity);
if(p == selectedAircraft) {
drawColor = style.selectedColor;
}
int tick = 4;
int anchor_x, anchor_y, exit_x, exit_y;
if(p->x + p->w / 2 > p->cx) {
anchor_x = p->x;
} else {
anchor_x = p->x + p->w;
}
if(p->y + p->h / 2 > p->cy) {
anchor_y = p->y - margin;
} else {
anchor_y = p->y + p->h + margin;
}
if(abs(anchor_x - p->cx) > abs(anchor_y - p->cy)) {
exit_x = (anchor_x + p->cx) / 2;
exit_y = anchor_y;
} else {
exit_x = anchor_x;
exit_y = (anchor_y + p->cy) / 2;
}
Sint16 vx[3] = {
static_cast<Sint16>(p->cx),
static_cast<Sint16>(exit_x),
static_cast<Sint16>(anchor_x)};
Sint16 vy[3] = {
static_cast<Sint16>(p->cy),
static_cast<Sint16>(exit_y),
static_cast<Sint16>(anchor_y)};
boxRGBA(renderer, p->x, p->y, p->x + p->w, p->y + p->h, 0, 0, 0, 255);
bezierRGBA(renderer, vx, vy, 3, 2, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
//lineRGBA(renderer, p->x,p->y - margin, p->x + tick, p->y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x,p->y - margin, p->x + p->w, p->y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x,p->y - margin, p->x, p->y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
// lineRGBA(renderer, p->x + p->w, p->y - margin, p->x + p->w - tick, p->y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x + p->w, p->y - margin, p->x + p->w, p->y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
//lineRGBA(renderer, p->x, p->y + p->h + margin, p->x + tick, p->y + p->h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x, p->y + p->h + margin, p->x + p->w, p->y + p->h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x, p->y + p->h + margin, p->x, p->y + p->h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
// lineRGBA(renderer, p->x + p->w, p->y + p->h + margin,p->x + p->w - tick, p->y + p->h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
lineRGBA(renderer, p->x + p->w, p->y + p->h + margin,p->x + p->w, p->y + p->h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
}
if(p->labelLevel < 2 || p == selectedAircraft) {
// drawSignalMarks(p, p->x, p->y);
SDL_Color drawColor = style.labelColor;
drawColor.a = (int) (255.0f * p->opacity);
char flight[10] = "";
charCount = snprintf(flight,10," %s", p->flight);
if(charCount > 1) {
outRect = drawString(flight, p->x, p->y, mapBoldFont, drawColor);
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
}
}
if(p->labelLevel < 1 || p == selectedAircraft) {
SDL_Color drawColor = style.subLabelColor;
drawColor.a = (int) (255.0f * p->opacity);
char alt[10] = "";
if (metric) {
charCount = snprintf(alt,10," %dm", (int) (p->altitude / 3.2828));
} else {
charCount = snprintf(alt,10," %d'", p->altitude);
}
if(charCount > 1) {
// drawStringBG(alt, p->x, p->y + currentLine * mapFontHeight, mapFont, style.subLabelColor, style.labelBackground);
outRect = drawString(alt, p->x, p->y + totalHeight, mapFont, drawColor);
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
}
char speed[10] = "";
if (metric) {
charCount = snprintf(speed,10," %dkm/h", (int) (p->speed * 1.852));
} else {
charCount = snprintf(speed,10," %dmph", p->speed);
}
if(charCount > 1) {
// drawStringBG(speed, p->x, p->y + currentLine * mapFontHeight, mapFont, style.subLabelColor, style.labelBackground);
outRect = drawString(speed, p->x, p->y + totalHeight, mapFont, drawColor);
totalWidth = std::max(totalWidth,outRect.w);
totalHeight += outRect.h;
}
}
//label debug
// char debug[25] = "";
// snprintf(debug,25,"%1.2f", p->labelLevel);
// drawString(debug, p->x, p->y + totalHeight, mapFont, style.red);
// if(maxCharCount > 1) {
// Sint16 vx[4] = {
// static_cast<Sint16>(p->cx),
// static_cast<Sint16>(p->cx + (p->x - p->cx) / 2),
// static_cast<Sint16>(p->x),
// static_cast<Sint16>(p->x)};
// Sint16 vy[4] = {
// static_cast<Sint16>(p->cy),
// static_cast<Sint16>(p->cy + (p->y - p->cy) / 2),
// static_cast<Sint16>(p->y - mapFontHeight),
// static_cast<Sint16>(p->y)};
// if(p->cy > p->y + currentLine * mapFontHeight) {
// vy[2] = p->y + currentLine * mapFontHeight + mapFontHeight;
// vy[3] = p->y + currentLine * mapFontHeight;
// }
// bezierRGBA(renderer,vx,vy,4,2,style.labelLineColor.r,style.labelLineColor.g,style.labelLineColor.b,SDL_ALPHA_OPAQUE);
// lineRGBA(renderer,p->x,p->y,p->x,p->y+currentLine*mapFontHeight,style.labelLineColor.r,style.labelLineColor.g,style.labelLineColor.b,SDL_ALPHA_OPAQUE);
// }
p->target_w = totalWidth;
p->target_h = totalHeight;
p->w += 0.25f * (p->target_w - p->w);
p->h += 0.25f * (p->target_h - p->h);
if(p->w < 0.05f) {
p->w = 0;
}
if(p->h < 0.05f) {
p->h = 0;
}
} }
float View::resolveLabelConflicts() { float View::resolveLabelConflicts() {
float label_force = 0.001f;
float label_dist = 2.0f;
float density_force = 0.05f;
float attachment_force = 0.0015f;
float attachment_dist = 10.0f;
float icon_force = 0.001f;
float icon_dist = 15.0f;
float boundary_force = 0.01f;
float damping_force = 0.85f;
float velocity_limit = 2.0f;
float edge_margin = 15.0f;
float maxV = 0.0f; float maxV = 0.0f;
Aircraft *p = appData->aircraftList.head; Aircraft *p = appData->aircraftList.head;
while(p) { while(p) {
p->ddox = 0; if(p->label) {
p->ddoy = 0; p->label->clearAcceleration();
}
p = p->next; p = p->next;
} }
p = appData->aircraftList.head; p = appData->aircraftList.head;
while(p) { while(p) {
//don't update on first run if(p->label) {
if(p->x == 0) { p->label->calculateForces(appData->aircraftList.head);
p = p->next;
continue;
}
Aircraft *check_p = appData->aircraftList.head;
int p_left = p->x;
int p_right = p->x + p->w;
int p_top = p->y;
int p_bottom = p->y + p->h;
float boxmid_x = (float)(p_left + p_right) / 2.0f;
float boxmid_y = (float)(p_top + p_bottom) / 2.0f;
float offset_x = boxmid_x - p->cx;
float offset_y = boxmid_y - p->cy;
float target_length_x = attachment_dist + p->w / 2.0f;
float target_length_y = attachment_dist + p->h / 2.0f;
// stay icon_dist away from own icon
p->ddox -= sign(offset_x) * attachment_force * (fabs(offset_x) - target_length_x);
p->ddoy -= sign(offset_y) * attachment_force * (fabs(offset_y) - target_length_y);
// // //screen edge
if(p_left < edge_margin) {
p->ddox += boundary_force * (float)(edge_margin - p_left);
}
if(p_right > screen_width - edge_margin) {
p->ddox += boundary_force * (float)(screen_width - edge_margin - p_right);
}
if(p_top < edge_margin) {
p->ddoy += boundary_force * (float)(edge_margin - p_top);
}
if(p_bottom > screen_height - edge_margin) {
p->ddoy += boundary_force * (float)(screen_height - edge_margin - p_bottom);
}
float all_x = 0;
float all_y = 0;
int count = 0;
//check against other labels
float density_max = 0;
while(check_p) {
if(check_p->addr == p->addr) {
check_p = check_p -> next;
continue;
}
//calculate density for label display level (inversely proportional to area of smallest box connecting this to neighbor)
float density = 1.0 / (0.001f + fabs(p->x - check_p->x) * fabs (p->x - check_p->y));
if(density > density_max) {
density_max = density;
}
density = 1.0 / (0.001f + fabs(p->x - check_p->cx) * fabs(p->x - check_p->cy));
if(density > density_max) {
density_max = density;
}
int check_left = check_p->x;
int check_right = check_p->x + check_p->w;
int check_top = check_p->y;
int check_bottom = check_p->y + check_p->h;
float icon_x = (float)check_p->cx;
float icon_y = (float)check_p->cy;
float checkboxmid_x = (float)(check_left + check_right) / 2.0f;
float checkboxmid_y = (float)(check_top + check_bottom) / 2.0f;
float offset_x = boxmid_x - checkboxmid_x;
float offset_y = boxmid_y - checkboxmid_y;
float target_length_x = label_dist + (float)(check_p->w + p->w) / 2.0f;
float target_length_y = label_dist + (float)(check_p->h + p->h) / 2.0f;
float x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
float y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
// stay at least label_dist away from other icons
if(x_mag > 0 && y_mag > 0) {
p->ddox += sign(offset_x) * label_force * x_mag;
p->ddoy += sign(offset_y) * label_force * y_mag;
}
// stay at least icon_dist away from other icons
offset_x = boxmid_x - check_p->cx;
offset_y = boxmid_y - check_p->cy;
target_length_x = icon_dist + (float)check_p->w / 2.0f;
target_length_y = icon_dist + (float)check_p->h / 2.0f;
x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
if(x_mag > 0 && y_mag > 0) {
p->ddox += sign(offset_x) * icon_force * x_mag;
p->ddoy += sign(offset_y) * icon_force * y_mag;
}
all_x += sign(boxmid_x - checkboxmid_x);
all_y += sign(boxmid_y - checkboxmid_y);
count++;
check_p = check_p -> next;
}
// move away from others
p->ddox += density_force * all_x / count;
p->ddoy += density_force * all_y / count;
// label drawlevel hysteresis
float density_mult = 100.0f;
float level_rate = 0.0005f;
if(p->labelLevel < -1.25f + density_mult * density_max) {
p->labelLevel += level_rate;
} else if (p->labelLevel > 0.5f + density_mult * density_max) {
p->labelLevel -= level_rate;
} }
p = p->next; p = p->next;
} }
//update
p = appData->aircraftList.head; p = appData->aircraftList.head;
while(p) { while(p) {
// if this is the first update don't update based on physics if(p->label) {
if(p->x == 0) { p->label->applyForces();
p->x = p->cx;
p->y = p->cy + 20*screen_uiscale;
p = p->next;
continue;
} }
//add noise to acceleration to help with resonance and stuck labels
// float noise_x = ((float) rand() / (float) RAND_MAX) - 0.5f;
// float noise_y = ((float) rand() / (float) RAND_MAX) - 0.5f;
p->dox += p->ddox;// + 0.001f;// * noise_x;
p->doy += p->ddoy;// + 0.001f;//. * noise_y;
p->dox *= damping_force;
p->doy *= damping_force;
if(fabs(p->dox) > velocity_limit) {
p->dox = sign(p->dox) * velocity_limit;
}
if(fabs(p->doy) > velocity_limit) {
p->doy = sign(p->doy) * velocity_limit;
}
if(fabs(p->dox) < 0.01f) {
p->dox = 0;
}
if(fabs(p->doy) < 0.01f) {
p->doy = 0;
}
p->ox += p->dox;
p->oy += p->doy;
p->x = p->cx + (int)round(p->ox);
p->y = p->cy + (int)round(p->oy);
if(fabs(p->dox) > maxV) {
maxV = fabs(p->dox);
}
if(fabs(p->doy) > maxV) {
maxV = fabs(p->doy);
}
//debug box
// rectangleRGBA(renderer, p->x, p->y, p->x + p->w, p->y + p->h, 255,0,0, SDL_ALPHA_OPAQUE);
// lineRGBA(renderer, p->cx, p->cy, p->x, p->y, 0,255,0, SDL_ALPHA_OPAQUE);
// lineRGBA(renderer,p->x, p->y, p->x + p->ddox, p->y+p->ddoy, 255,0,255,255);
// lineRGBA(renderer,p->x, p->y, p->x + p->dox, p->y+p->doy, 0,255,255,255);
p = p->next; p = p->next;
} }
@ -1372,7 +945,7 @@ void View::drawPlanes() {
// float predx = x + float(elapsed(p->msSeenLatLon)) * velx; // float predx = x + float(elapsed(p->msSeenLatLon)) * velx;
// float predy = y + float(elapsed(p->msSeenLatLon)) * vely; // float predy = y + float(elapsed(p->msSeenLatLon)) * vely;
// circleRGBA(renderer, predx, predy, 4 * screen_uiscale, 127,127, 127, 255); // circleRGBA(renderer, predx, predy, 4 * screen_uiscale, 127,127, 127, 255);
// lineRGBA(renderer, p->cx, p->cy, predx, predy, 127,127, 127, 255); // lineRGBA(renderer, p->x, p->y, predx, predy, 127,127, 127, 255);
// } // }
planeColor = lerpColor(style.planeColor, style.planeGoneColor, float(elapsed_s(p->msSeen)) / (float) DISPLAY_ACTIVE); planeColor = lerpColor(style.planeColor, style.planeGoneColor, float(elapsed_s(p->msSeen)) / (float) DISPLAY_ACTIVE);
@ -1382,18 +955,18 @@ void View::drawPlanes() {
} }
if(outOfBounds(x,y)) { if(outOfBounds(x,y)) {
drawPlaneOffMap(x, y, &(p->cx), &(p->cy), planeColor); drawPlaneOffMap(x, y, &(p->x), &(p->y), planeColor);
} else { } else {
drawPlaneIcon(usex, usey, p->track, planeColor); drawPlaneIcon(usex, usey, p->track, planeColor);
p->cx = usex; p->x = usex;
p->cy = usey; p->y = usey;
} }
//show latlon ping //show latlon ping
if(elapsed(p->msSeenLatLon) < 500) { if(elapsed(p->msSeenLatLon) < 500) {
circleRGBA(renderer, p->cx, p->cy, elapsed(p->msSeenLatLon) * screen_width / (8192), 127,127, 127, 255 - (uint8_t)(255.0 * elapsed(p->msSeenLatLon) / 500.0)); circleRGBA(renderer, p->x, p->y, elapsed(p->msSeenLatLon) * screen_width / (8192), 127,127, 127, 255 - (uint8_t)(255.0 * elapsed(p->msSeenLatLon) / 500.0));
} }
drawPlaneText(p); drawPlaneText(p);
@ -1541,18 +1114,18 @@ void View::drawClick() {
} else { } else {
boxSize = 20; boxSize = 20;
} }
//rectangleRGBA(renderer, selectedAircraft->cx - boxSize, selectedAircraft->cy - boxSize, selectedAircraft->cx + boxSize, selectedAircraft->cy + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); //rectangleRGBA(renderer, selectedAircraft->x - boxSize, selectedAircraft->y - boxSize, selectedAircraft->x + boxSize, selectedAircraft->y + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx - boxSize, selectedAircraft->cy - boxSize, selectedAircraft->cx - boxSize/2, selectedAircraft->cy - boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x - boxSize, selectedAircraft->y - boxSize, selectedAircraft->x - boxSize/2, selectedAircraft->y - boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx - boxSize, selectedAircraft->cy - boxSize, selectedAircraft->cx - boxSize, selectedAircraft->cy - boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x - boxSize, selectedAircraft->y - boxSize, selectedAircraft->x - boxSize, selectedAircraft->y - boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx + boxSize, selectedAircraft->cy - boxSize, selectedAircraft->cx + boxSize/2, selectedAircraft->cy - boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x + boxSize, selectedAircraft->y - boxSize, selectedAircraft->x + boxSize/2, selectedAircraft->y - boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx + boxSize, selectedAircraft->cy - boxSize, selectedAircraft->cx + boxSize, selectedAircraft->cy - boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x + boxSize, selectedAircraft->y - boxSize, selectedAircraft->x + boxSize, selectedAircraft->y - boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx + boxSize, selectedAircraft->cy + boxSize, selectedAircraft->cx + boxSize/2, selectedAircraft->cy + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x + boxSize, selectedAircraft->y + boxSize, selectedAircraft->x + boxSize/2, selectedAircraft->y + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx + boxSize, selectedAircraft->cy + boxSize, selectedAircraft->cx + boxSize, selectedAircraft->cy + boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x + boxSize, selectedAircraft->y + boxSize, selectedAircraft->x + boxSize, selectedAircraft->y + boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx - boxSize, selectedAircraft->cy + boxSize, selectedAircraft->cx - boxSize/2, selectedAircraft->cy + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x - boxSize, selectedAircraft->y + boxSize, selectedAircraft->x - boxSize/2, selectedAircraft->y + boxSize, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
lineRGBA(renderer, selectedAircraft->cx - boxSize, selectedAircraft->cy + boxSize, selectedAircraft->cx - boxSize, selectedAircraft->cy + boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255); lineRGBA(renderer, selectedAircraft->x - boxSize, selectedAircraft->y + boxSize, selectedAircraft->x - boxSize, selectedAircraft->y + boxSize/2, style.selectedColor.r, style.selectedColor.g, style.selectedColor.b, 255);
} }
} }
@ -1563,10 +1136,10 @@ void View::registerClick(int tapcount, int x, int y) {
while(p) { while(p) {
if(x && y) { if(x && y) {
if((p->cx - x) * (p->cx - x) + (p->cy - y) * (p->cy - y) < 900) { if((p->x - x) * (p->x - x) + (p->y - y) * (p->y - y) < 900) {
if(selection) { if(selection) {
if((p->cx - x) * (p->cx - x) + (p->cy - y) * (p->cy - y) < if((p->x - x) * (p->x - x) + (p->y - y) * (p->y - y) <
(selection->cx - x) * (selection->cx - x) + (selection->cy - y) * (selection->cy - y)) { (selection->x - x) * (selection->x - x) + (selection->y - y) * (selection->y - y)) {
selection = p; selection = p;
} }
} else { } else {
@ -1615,9 +1188,10 @@ void View::draw() {
drawGeography(); drawGeography();
for(int i = 0; i < 8; i++) { for(int i = 0; i < 8; i++) {
if(resolveLabelConflicts() < 0.001f) { // if(resolveLabelConflicts() < 0.001f) {
break; // break;
} // }
resolveLabelConflicts();
} }
lineCount = 0; lineCount = 0;
@ -1631,7 +1205,9 @@ void View::draw() {
if(fps) { if(fps) {
char fps[60] = " "; char fps[60] = " ";
snprintf(fps,40," %d lines @ %.1ffps", lineCount, 1000.0 / elapsed(lastFrameTime)); snprintf(fps,40," %d lines @ %.1ffps", lineCount, 1000.0 / elapsed(lastFrameTime));
drawStringBG(fps, 0,0, mapFont, style.subLabelColor, style.backgroundColor);
//drawStringBG(fps, 0,0, mapFont, style.subLabelColor, style.backgroundColor);
} }
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);

92
View.h
View file

@ -34,11 +34,13 @@
#include "AppData.h" #include "AppData.h"
#include "Map.h" #include "Map.h"
#include "Style.h"
#include "SDL2/SDL.h" #include "SDL2/SDL.h"
#include "SDL2/SDL_ttf.h" #include "SDL2/SDL_ttf.h"
#include <chrono> #include <chrono>
#include <string> #include <string>
//defs - should all move to config file setup //defs - should all move to config file setup
#define ROUND_RADIUS 3 //radius of text box corners #define ROUND_RADIUS 3 //radius of text box corners
@ -58,96 +60,6 @@
#define LATLONMULT 111.195 // 6371.0 * M_PI / 180.0 #define LATLONMULT 111.195 // 6371.0 * M_PI / 180.0
//
// This should go to a full theming class
//
typedef struct Style {
SDL_Color backgroundColor;
SDL_Color selectedColor;
SDL_Color planeColor;
SDL_Color planeGoneColor;
SDL_Color trailColor;
SDL_Color geoColor;
SDL_Color airportColor;
SDL_Color labelColor;
SDL_Color labelLineColor;
SDL_Color subLabelColor;
SDL_Color labelBackground;
SDL_Color scaleBarColor;
SDL_Color buttonColor;
SDL_Color buttonBackground;
SDL_Color buttonOutline;
SDL_Color clickColor;
SDL_Color black;
SDL_Color white;
SDL_Color red;
SDL_Color green;
SDL_Color blue;
//
// todo separate style stuff
//
Style() {
SDL_Color pink = {249,38,114,255};
SDL_Color purple = {85, 0, 255,255};
SDL_Color purple_dark = {33, 0, 122,255};
SDL_Color blue = {102,217,239,255};
SDL_Color blue_dark = {102,217,239,255};
SDL_Color green = {0,255,234,255};
SDL_Color green_dark = {24,100,110,255};
SDL_Color yellow = {216,255,0,255};
SDL_Color yellow_dark = {90,133,50,255};
SDL_Color orange = {253,151,31,255};
SDL_Color grey_light = {196,196,196,255};
SDL_Color grey = {127,127,127,255};
SDL_Color grey_dark = {64,64,64,255};
black = {0,0,0,255};
white = {255,255,255,255};
red = {255,0,0,255};
green = {0,255,0,255};
blue = {0,0,255,255};
backgroundColor = black;
selectedColor = pink;
planeColor = yellow;
planeGoneColor = grey;
trailColor = yellow_dark;
geoColor = purple_dark;
airportColor = purple;
labelColor = white;
labelLineColor = grey_dark;
subLabelColor = grey;
labelBackground = black;
scaleBarColor = grey_light;
buttonColor = grey_light;
buttonBackground = black;
buttonOutline = grey_light;
clickColor = grey;
}
} Style;
class View { class View {
private: private: