]> git.jsancho.org Git - lugaru.git/blob - Source/Menu.cpp
c402c8d39f50ad9374730629579672e05e5a5d5b
[lugaru.git] / Source / Menu.cpp
1 #include <vector>
2 #include <string>
3 #include "gamegl.h"
4
5 #include "Menu.h"
6 using namespace Menu;
7
8 extern float multiplier;
9
10 struct MenuItem {
11     enum MenuItemType {NONE, LABEL, BUTTON, IMAGE, IMAGEBUTTON, MAPMARKER, MAPLINE, MAPLABEL} type;
12     int id;
13     string text;
14     Texture texture;
15     int x, y, w, h;
16     float r, g, b;
17     float effectfade;
18
19     float linestartsize;
20     float lineendsize;
21
22     void init(MenuItemType _type, int _id, const string& _text, Texture _texture,
23               int _x, int _y, int _w, int _h, float _r, float _g, float _b,
24               float _linestartsize = 1, float _lineendsize = 1) {
25         type = _type;
26         id = _id;
27         text = _text;
28         texture = _texture;
29         x = _x;
30         y = _y;
31         w = _w;
32         h = _h;
33         r = _r;
34         g = _g;
35         b = _b;
36         effectfade = 0;
37         linestartsize = _linestartsize;
38         lineendsize = _lineendsize;
39         if (type == MenuItem::BUTTON) {
40             if (w == -1)
41                 w = text.length() * 10;
42             if (h == -1)
43                 h = 20;
44         }
45     }
46 };
47
48 vector<MenuItem> items;
49
50
51
52
53 void Menu::clearMenu()
54 {
55     items.clear();
56 }
57
58 void Menu::addLabel(int id, const string& text, int x, int y, float r, float g, float b)
59 {
60     items.push_back(MenuItem());
61     items.back().init(MenuItem::LABEL, id, text, Texture(), x, y, -1, -1, r, g, b);
62 }
63 void Menu::addButton(int id, const string& text, int x, int y, float r, float g, float b)
64 {
65     items.push_back(MenuItem());
66     items.back().init(MenuItem::BUTTON, id, text, Texture(), x, y, -1, -1, r, g, b);
67 }
68 void Menu::addImage(int id, Texture texture, int x, int y, int w, int h, float r, float g, float b)
69 {
70     items.push_back(MenuItem());
71     items.back().init(MenuItem::IMAGE, id, "", texture, x, y, w, h, r, g, b);
72 }
73 void Menu::addButtonImage(int id, Texture texture, int x, int y, int w, int h, float r, float g, float b)
74 {
75     items.push_back(MenuItem());
76     items.back().init(MenuItem::IMAGEBUTTON, id, "", texture, x, y, w, h, r, g, b);
77 }
78 void Menu::addMapLine(int x, int y, int w, int h, float startsize, float endsize, float r, float g, float b)
79 {
80     items.push_back(MenuItem());
81     items.back().init(MenuItem::MAPLINE, -1, "", Texture(), x, y, w, h, r, g, b, startsize, endsize);
82 }
83 void Menu::addMapMarker(int id, Texture texture, int x, int y, int w, int h, float r, float g, float b)
84 {
85     items.push_back(MenuItem());
86     items.back().init(MenuItem::MAPMARKER, id, "", texture, x, y, w, h, r, g, b);
87 }
88 void Menu::addMapLabel(int id, const string& text, int x, int y, float r, float g, float b)
89 {
90     items.push_back(MenuItem());
91     items.back().init(MenuItem::MAPLABEL, id, text, Texture(), x, y, -1, -1, r, g, b);
92 }
93
94 void Menu::setText(int id, const string& text)
95 {
96     for (vector<MenuItem>::iterator it = items.begin(); it != items.end(); it++)
97         if (it->id == id) {
98             it->text = text;
99             it->w = it->text.length() * 10;
100             break;
101         }
102 }
103
104 void Menu::setText(int id, const string& text, int x, int y, int w, int h)
105 {
106     for (vector<MenuItem>::iterator it = items.begin(); it != items.end(); it++)
107         if (it->id == id) {
108             it->text = text;
109             it->x = x;
110             it->y = y;
111             if (w == -1)
112                 it->w = it->text.length() * 10;
113             if (h == -1)
114                 it->h = 20;
115             break;
116         }
117 }
118
119 int Menu::getSelected(int mousex, int mousey)
120 {
121     for (vector<MenuItem>::iterator it = items.begin(); it != items.end(); it++)
122         if (it->type == MenuItem::BUTTON || it->type == MenuItem::IMAGEBUTTON || it->type == MenuItem::MAPMARKER) {
123             int mx = mousex;
124             int my = mousey;
125             if (it->type == MenuItem::MAPMARKER) {
126                 mx -= 1;
127                 my += 2;
128             }
129             if (mx >= it->x && mx < it->x + it->w && my >= it->y && my < it->y + it->h)
130                 return it->id;
131         }
132     return -1;
133 }
134
135 void GUITick()
136 {
137     for (vector<MenuItem>::iterator it = items.begin(); it != items.end(); it++) {
138         if (it->id == Game::selected) {
139             it->effectfade += multiplier * 5;
140             if (it->effectfade > 1)
141                 it->effectfade = 1;
142         } else {
143             it->effectfade -= multiplier * 5;
144             if (it->effectfade < 0)
145                 it->effectfade = 0;
146         }
147     }
148 }
149
150 void Menu::drawItems()
151 {
152     GUITick();
153     glEnable(GL_TEXTURE_2D);
154     glEnable(GL_ALPHA_TEST);
155     glEnable(GL_BLEND);
156     for (vector<MenuItem>::iterator it = items.begin(); it != items.end(); it++) {
157         switch (it->type) {
158         case MenuItem::IMAGE:
159         case MenuItem::IMAGEBUTTON:
160         case MenuItem::MAPMARKER:
161             glColor4f(it->r, it->g, it->b, 1);
162             glPushMatrix();
163             if (it->type == MenuItem::MAPMARKER) {
164                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
165                 glTranslatef(2.5, -4.5, 0); //from old code
166             } else {
167                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
168             }
169             it->texture.bind();
170             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
171             glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
172             glBegin(GL_QUADS);
173             glTexCoord2f(0, 0);
174             glVertex3f(it->x, it->y, 0);
175             glTexCoord2f(1, 0);
176             glVertex3f(it->x + it->w, it->y, 0);
177             glTexCoord2f(1, 1);
178             glVertex3f(it->x + it->w, it->y + it->h, 0);
179             glTexCoord2f(0, 1);
180             glVertex3f(it->x, it->y + it->h, 0);
181             glEnd();
182             if (it->type != MenuItem::IMAGE) {
183                 //mouseover highlight
184                 for (int i = 0; i < 10; i++) {
185                     if (1 - ((float)i) / 10 - (1 - it->effectfade) > 0) {
186                         glColor4f(it->r, it->g, it->b, (1 - ((float)i) / 10 - (1 - it->effectfade))*.25);
187                         glBegin(GL_QUADS);
188                         glTexCoord2f(0, 0);
189                         glVertex3f(it->x - ((float)i) * 1 / 2, it->y - ((float)i) * 1 / 2, 0);
190                         glTexCoord2f(1, 0);
191                         glVertex3f(it->x + it->w + ((float)i) * 1 / 2, it->y - ((float)i) * 1 / 2, 0);
192                         glTexCoord2f(1, 1);
193                         glVertex3f(it->x + it->w + ((float)i) * 1 / 2, it->y + it->h + ((float)i) * 1 / 2, 0);
194                         glTexCoord2f(0, 1);
195                         glVertex3f(it->x - ((float)i) * 1 / 2, it->y + it->h + ((float)i) * 1 / 2, 0);
196                         glEnd();
197                     }
198                 }
199             }
200             glPopMatrix();
201             break;
202         case MenuItem::LABEL:
203         case MenuItem::BUTTON:
204             glColor4f(it->r, it->g, it->b, 1);
205             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
206             Game::text->glPrint(it->x, it->y, it->text.c_str(), 0, 1, 640, 480);
207             if (it->type != MenuItem::LABEL) {
208                 //mouseover highlight
209                 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
210                 for (int i = 0; i < 15; i++) {
211                     if (1 - ((float)i) / 15 - (1 - it->effectfade) > 0) {
212                         glColor4f(it->r, it->g, it->b, (1 - ((float)i) / 10 - (1 - it->effectfade))*.25);
213                         Game::text->glPrint(it->x - ((float)i), it->y, it->text.c_str(), 0, 1 + ((float)i) / 70, 640, 480);
214                     }
215                 }
216             }
217             break;
218         case MenuItem::MAPLABEL:
219             Game::text->glPrintOutlined(0.9, 0, 0, it->x, it->y, it->text.c_str(), 0, 0.6, 640, 480);
220             break;
221         case MenuItem::MAPLINE: {
222             XYZ linestart;
223             linestart.x = it->x;
224             linestart.y = it->y;
225             linestart.z = 0;
226             XYZ lineend;
227             lineend.x = it->x + it->w;
228             lineend.y = it->y + it->h;
229             lineend.z = 0;
230             XYZ offset = lineend - linestart;
231             XYZ fac = offset;
232             Normalise(&fac);
233             offset = DoRotation(offset, 0, 0, 90);
234             Normalise(&offset);
235
236             linestart += fac * 4 * it->linestartsize;
237             lineend -= fac * 4 * it->lineendsize;
238
239             glDisable(GL_TEXTURE_2D);
240             glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241             glColor4f(it->r, it->g, it->b, 1);
242             glPushMatrix();
243             glTranslatef(2, -5, 0); //from old code
244             glBegin(GL_QUADS);
245             glVertex3f(linestart.x - offset.x * it->linestartsize, linestart.y - offset.y * it->linestartsize, 0.0f);
246             glVertex3f(linestart.x + offset.x * it->linestartsize, linestart.y + offset.y * it->linestartsize, 0.0f);
247             glVertex3f(lineend.x + offset.x * it->lineendsize, lineend.y + offset.y * it->lineendsize, 0.0f);
248             glVertex3f(lineend.x - offset.x * it->lineendsize, lineend.y - offset.y * it->lineendsize, 0.0f);
249             glEnd();
250             glPopMatrix();
251             glEnable(GL_TEXTURE_2D);
252         }
253         break;
254         }
255     }
256 }
257