summaryrefslogtreecommitdiff
path: root/cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'cursor.c')
-rw-r--r--cursor.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/cursor.c b/cursor.c
new file mode 100644
index 00000000..1f1d99e8
--- /dev/null
+++ b/cursor.c
@@ -0,0 +1,196 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <math.h>
+#include <glib.h>
+#include "coord.h"
+#include "transform.h"
+#include "graphics.h"
+#include "statusbar.h"
+#include "menu.h"
+#include "vehicle.h"
+#include "container.h"
+
+
+#include "route.h"
+
+struct cursor {
+ struct container *co;
+ struct graphics_gc *cursor_gc;
+ struct point cursor_pnt;
+};
+
+struct coord *
+cursor_pos_get(void *t)
+{
+ struct cursor *this=t;
+ return vehicle_pos_get(this->co->vehicle);
+}
+
+static void
+cursor_draw(struct cursor *this, struct point *pnt, double *speed, double *dir)
+{
+ int x=this->cursor_pnt.x;
+ int y=this->cursor_pnt.y;
+ int r=12,lw=2;
+ double dx,dy;
+ double fac1,fac2;
+ int dir_i=*dir-this->co->trans->angle;
+ struct point cpnt[3];
+ struct graphics *gra=this->co->gra;
+
+ if (pnt && x == pnt->x && y == pnt->y)
+ return;
+ cpnt[0]=this->cursor_pnt;
+ cpnt[0].x-=r+lw;
+ cpnt[0].y-=r+lw;
+ gra->draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2);
+ if (pnt) {
+ gra->draw_mode(gra, draw_mode_cursor);
+ this->cursor_pnt=*pnt;
+ x=pnt->x;
+ y=pnt->y;
+ cpnt[0].x=x;
+ cpnt[0].y=y;
+ gra->draw_circle(gra, this->cursor_gc, &cpnt[0], r*2);
+ if (*speed > 2.5) {
+ dx=sin(M_PI*dir_i/180);
+ dy=-cos(M_PI*dir_i/180);
+
+ fac1=0.7*r;
+ fac2=0.4*r;
+ cpnt[0].x=x-dx*fac1+dy*fac2;
+ cpnt[0].y=y-dy*fac1-dx*fac2;
+ cpnt[1].x=x+dx*r;
+ cpnt[1].y=y+dy*r;
+ cpnt[2].x=x-dx*fac1-dy*fac2;
+ cpnt[2].y=y-dy*fac1+dx*fac2;
+ gra->draw_lines(gra, this->cursor_gc, cpnt, 3);
+ } else {
+ cpnt[1]=cpnt[0];
+ gra->draw_lines(gra, this->cursor_gc, cpnt, 2);
+ }
+ gra->draw_mode(gra, draw_mode_end);
+ }
+}
+
+static void
+cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new)
+{
+ struct coord c_new;
+ struct transformation tr;
+ struct point pnt;
+ unsigned long scale;
+ long x,y;
+ int dir_i;
+ struct container *co=this->co;
+
+ if (dir)
+ dir_i=*dir;
+ else
+ dir_i=0;
+
+ pnt.x=co->trans->width-x_new;
+ pnt.y=co->trans->height-y_new;
+ graphics_get_view(co, &x, &y, &scale);
+ tr=*this->co->trans;
+ transform_setup(&tr, c->x, c->y, scale, dir_i);
+ transform_reverse(&tr, &pnt, &c_new);
+ printf("%lx %lx vs %lx %lx\n", c->x, c->y, c_new.x, c_new.y);
+ x=c_new.x;
+ y=c_new.y;
+ transform_set_angle(co->trans,dir_i);
+ graphics_set_view(co, &x, &y, &scale);
+}
+
+static void
+cursor_map_reposition(struct cursor *this, struct coord *c, double *dir)
+{
+ unsigned long scale;
+ long x,y;
+
+ if (this->co->flags->orient_north) {
+ graphics_set_view(this->co, &c->x, &c->y, NULL);
+ } else {
+ cursor_map_reposition_screen(this, c, dir, this->co->trans->width/2, this->co->trans->height*0.8);
+ }
+}
+
+static int
+cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir, struct point *pnt)
+{
+ struct point pnt_new;
+ struct transformation *t=this->co->trans;
+
+ pnt_new.x=-1;
+ if (pnt->x < 0.1*t->width) {
+ pnt_new.x=0.8*t->width;
+ pnt_new.y=t->height/2;
+ }
+ if (pnt->x > 0.9*t->width) {
+ pnt_new.x=0.2*t->width;
+ pnt_new.y=t->height/2;
+ }
+ if (pnt->y < (this->co->flags->orient_north ? 0.1 : 0.5)*t->height) {
+ pnt_new.x=t->width/2;
+ pnt_new.y=0.8*t->height;
+ }
+ if (pnt->y > 0.9*t->height) {
+ pnt_new.x=t->width/2;
+ pnt_new.y=0.2*t->height;
+ }
+ if (pnt_new.x != -1) {
+ if (this->co->flags->orient_north) {
+ cursor_map_reposition_screen(this, c, NULL, pnt_new.x, pnt_new.y);
+ } else {
+ cursor_map_reposition(this, c, dir);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void
+cursor_update(struct cursor *this)
+{
+ struct point pnt;
+ struct coord *pos;
+ struct vehicle *v=this->co->vehicle;
+ double *dir;
+
+ if (v) {
+ pos=vehicle_pos_get(v);
+ dir=vehicle_dir_get(v);
+ route_set_position(this->co->route, cursor_pos_get(this->co->cursor));
+ if (!transform(this->co->trans, pos, &pnt)) {
+ cursor_map_reposition(this, pos, dir);
+ transform(this->co->trans, pos, &pnt);
+ }
+ if (pnt.x < 0 || pnt.y < 0 || pnt.x >= this->co->trans->width || pnt.y >= this->co->trans->height) {
+ cursor_map_reposition(this, pos, dir);
+ transform(this->co->trans, pos, &pnt);
+ }
+ if (cursor_map_reposition_boundary(this, pos, dir, &pnt))
+ transform(this->co->trans, pos, &pnt);
+ cursor_draw(this, &pnt, vehicle_speed_get(v), vehicle_dir_get(v));
+ }
+extern void compass_draw();
+ compass_draw(this->co->compass, this->co);
+}
+
+extern void *vehicle;
+
+struct cursor *
+cursor_new(struct container *co)
+{
+ struct cursor *this=g_new(struct cursor,1);
+ this->co=co;
+ this->cursor_gc=co->gra->gc_new(co->gra);
+ co->gra->gc_set_foreground(this->cursor_gc, 0x0000, 0x0000, 0xffff);
+ co->gra->gc_set_linewidth(this->cursor_gc, 2);
+ vehicle_callback(cursor_update, this);
+ return this;
+}