dunger now saves player start position and cell size
[vrlugburz] / tools / dunger / src / lview.c
1 #include <GL/gl.h>
2 #include <drawtext.h>
3 #include "lview.h"
4 #include "app.h"
5
6 static struct level *lvl;
7 static struct cell *sel;
8 static int vpx, vpy, vpw, vph;
9 static float panx, pany, zoom;
10 static float cellsz;    /* derived from zoom and level properties */
11
12 int init_lview(struct level *l)
13 {
14         lvl = l;
15         sel = 0;
16         panx = 0;
17         pany = -12;
18         zoom = 1;
19         zoom_lview(0);
20         return 0;
21 }
22
23 void destroy_lview(void)
24 {
25 }
26
27 void lview_viewport(int x, int y, int xsz, int ysz)
28 {
29         vpx = x;
30         vpy = y;
31         vpw = xsz;
32         vph = ysz;
33         zoom_lview(0);  /* recalc cell size */
34 }
35
36 void pan_lview(float dx, float dy)
37 {
38         panx += dx;
39         pany += dy;
40 }
41
42 void zoom_lview(float dz)
43 {
44         float xsz, ysz;
45
46         zoom += dz;
47         xsz = zoom * vpw / lvl->width;
48         ysz = zoom * vph / lvl->height;
49         cellsz = xsz > ysz ? ysz : xsz;
50 }
51
52 static int bnstate[8];
53
54 void lview_mbutton(int bn, int press, int x, int y)
55 {
56         int cx, cy;
57         float hsz = cellsz / 2.0f;
58         sel = pos_to_cell(x + hsz - vpx, vph - y + hsz - vpy, 0, 0);
59         bnstate[bn] = press;
60
61         if(press) {
62                 if(!sel) return;
63
64                 switch(tool) {
65                 case TOOL_DRAW:
66                         if(bn == 0) {
67                                 sel->type = CELL_WALK;
68                         } else if(bn == 2) {
69                                 sel->type = CELL_SOLID;
70                         }
71                         break;
72
73                 case TOOL_PSTART:
74                         cell_coords(sel, &cx, &cy);
75                         if(bn == 0) {
76                                 if(sel->type == CELL_WALK) {
77                                         lvl->px = cx;
78                                         lvl->py = cy;
79                                 }
80                         } else if(bn == 2) {
81                                 if(lvl->px == cx && lvl->py == cy) {
82                                         lvl->px = lvl->py = -1;
83                                 }
84                         }
85                         break;
86                 }
87         }
88 }
89
90 void lview_mouse(int x, int y)
91 {
92         float hsz = cellsz / 2.0f;
93         if(!(sel = pos_to_cell(x + hsz - vpx, vph - y + hsz - vpy, 0, 0))) {
94                 return;
95         }
96
97         switch(tool) {
98         case TOOL_DRAW:
99                 if(bnstate[0]) {
100                         sel->type = CELL_WALK;
101                 } else if(bnstate[2]) {
102                         sel->type = CELL_SOLID;
103                 }
104                 break;
105         }
106 }
107
108 #define LTHICK  0.5f
109 static void draw_cell(struct cell *cell)
110 {
111         int row, col;
112         float x, y, hsz;
113         static const float colors[][3] = {{0, 0, 0}, {0.6, 0.6, 0.6}, {0.4, 0.2, 0.1}};
114
115         hsz = cellsz * 0.5f;
116
117         cell_coords(cell, &col, &row);
118         cell_to_pos(col, row, &x, &y);
119
120         if(sel == cell) {
121                 glColor3f(1, 1, 1);
122         } else {
123                 if(col == lvl->px && row == lvl->py) {
124                         glColor3f(0, 1, 0);
125                 } else {
126                         glColor3f(0.5f, 0.5f, 0.5f);
127                 }
128         }
129         glVertex2f(x - hsz, y - hsz);
130         glVertex2f(x + hsz, y - hsz);
131         glVertex2f(x + hsz, y + hsz);
132         glVertex2f(x - hsz, y + hsz);
133
134         x += LTHICK / 2.0f;
135         y += LTHICK / 2.0f;
136         hsz -= LTHICK * 2.0f;
137
138         glColor3fv(colors[cell->type]);
139         glVertex2f(x - hsz, y - hsz);
140         glVertex2f(x + hsz, y - hsz);
141         glVertex2f(x + hsz, y + hsz);
142         glVertex2f(x - hsz, y + hsz);
143 }
144
145
146 void draw_lview(void)
147 {
148         int i, j, row, col;
149         struct cell *cell;
150
151         glBegin(GL_QUADS);
152         cell = lvl->cells;
153         for(i=0; i<lvl->height; i++) {
154                 for(j=0; j<lvl->width; j++) {
155                         draw_cell(cell++);
156                 }
157         }
158         glEnd();
159
160         if(sel) {
161                 cell_coords(sel, &col, &row);
162
163                 glMatrixMode(GL_MODELVIEW);
164                 glPushMatrix();
165                 glTranslatef(10, 10, 0);
166
167                 glColor3f(1, 1, 1);
168                 dtx_printf("(%d, %d)", col, row);
169                 dtx_flush();
170
171                 glPopMatrix();
172         }
173 }
174
175 void cell_to_pos(int cx, int cy, float *px, float *py)
176 {
177         if(px) *px = (cx - lvl->width / 2.0f) * cellsz - panx + vpw / 2.0f;
178         if(py) *py = (cy - lvl->height / 2.0f) * cellsz - pany + vph / 2.0f;
179 }
180
181 struct cell *pos_to_cell(float px, float py, int *cx, int *cy)
182 {
183         int col, row;
184
185         col = (px + panx - vpw / 2.0f) / cellsz + lvl->width / 2.0f;
186         row = (py + pany - vph / 2.0f) / cellsz + lvl->height / 2.0f;
187
188         if(cx) *cx = col;
189         if(cy) *cy = row;
190
191         if(col >= 0 && col < lvl->width && row >= 0 && row < lvl->height) {
192                 return lvl->cells + row * lvl->width + col;
193         }
194         return 0;
195 }
196
197 void cell_coords(struct cell *cell, int *col, int *row)
198 {
199         int cidx = cell - lvl->cells;
200         *row = cidx / lvl->width;
201         *col = cidx % lvl->width;
202 }