Rotating menu now has limits and optimized drawing.
[ne.git] / src / main.cpp
blob6c31457a5be97e67b1dc1f3a896ad3cde006985d
1 /************************************************************************
2 This file is part of NE.
4 NE is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 NE is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with NE. If not, see <http://www.gnu.org/licenses/>.
16 ************************************************************************/
18 #include "backend/video.h"
19 #include "backend/input.h"
20 #include "backend/shapes.h"
21 #include "backend/texture.h"
22 #include "mods/list.h"
24 #include <time.h>
25 #include <GL/gl.h>
26 #include <GL/glu.h>
27 #include <SDL/SDL.h>
28 #include <FTGL/FTGL.h>
29 #include <FTGL/FTFont.h>
30 #include <FTGL/FTGLExtrdFont.h>
31 #include <FTGL/FTGLPixmapFont.h>
32 #include <FTGL/FTGLTextureFont.h>
34 #include <iostream>
35 #include <sstream>
36 #include <string>
37 #include <vector>
39 static int gl_init();
41 #define FONT_SCALE 0.025
43 inline void draw_text(FTFont *f, const char *msg, float x, float y, float z)
45 FTPoint upper,lower;
46 float cx, cy;
47 float lx,ly,lz, ux,uy,uz;
49 f->BBox(msg,lx,ly,lz,ux,uy,uz);
50 cx = (ux-lx)/2;
51 cy = (uy-ly)/2;
53 cx *= FONT_SCALE;
54 cy *= FONT_SCALE;
56 glPushMatrix();
57 glTranslatef(x-cx,y-cy,z);
58 glScalef(FONT_SCALE,FONT_SCALE,FONT_SCALE);
59 f->Render(msg);
60 glPopMatrix();
63 int main(int argc, char **argv)
65 v_init();
66 i_init();
68 int width = 1024;
69 int height = 768;
70 int full = 0;
72 // parse args
74 const char *usage = "USAGE:\n\t%s [-w WIDTH] [-h HEIGHT] [-f]\n";
76 std::stringstream ss;
77 for (int i=1; i<argc; i++)
78 ss << argv[i] << " ";
80 std::string arg_s;
81 while (ss >> arg_s)
83 if (arg_s == "-w")
84 ss >> width;
85 else if (arg_s == "-h")
86 ss >> height;
87 else if (arg_s == "-f")
88 full = 1;
89 else
91 printf(usage,argv[0]);
92 return 1;
97 srand(time(0));
99 v_setup(width,height,full);
101 SDL_WM_SetCaption("NE Game Selection (Choose one!)", "NE Game Selection");
103 gl_init();
104 shapes_init();
107 Texture *tex_bg = new Texture("data/menu/bg.png");
109 const char *font = "data/fonts/freesansbold.ttf";
111 FTGLTextureFont *font_medium = new FTGLTextureFont(font);
112 font_medium->FaceSize(32);
114 FTGLTextureFont *font_small = new FTGLTextureFont(font);
115 font_small->FaceSize(16);
117 float bgcol[] = { 0, 0, 0 };
118 int bg_last = rand()%3;
119 int bg_curr = -1;
120 bgcol[bg_last] = 1;
122 // some variables to control the size and speed of the GUI
123 float entry_spacing = 2;
124 int entry_padding = 5;
125 float scroll_speed = 0.2;
127 struct mod* selected_mod = mod_list;
128 int mod_count = 0;
130 for (struct mod* curr_mod = mod_list; curr_mod->runfunc != 0; curr_mod++)
132 mod_count++;
135 std::cout << "Counted " << mod_count << " mods" << std::endl;
137 while (1)
139 if (bg_curr == -1)
141 bg_curr = bg_last;
142 while (bg_last == bg_curr) bg_curr = rand()%3;
145 if (bgcol[bg_curr] >= 1)
147 bg_last = bg_curr;
148 bg_curr = -1;
149 } else {
150 bgcol[bg_curr]+=0.01;
151 bgcol[bg_last]-=0.01;
154 glClearColor(bgcol[0],bgcol[1],bgcol[2],1);
155 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
157 glMatrixMode(GL_MODELVIEW);
158 glLoadIdentity();
160 i_pump();
162 keysym_t *key = i_keystate();
164 static int keydown = 0;
165 if (key[K_ESCAPE])
167 return 0;
169 else if (key[K_UP])
171 if (selected_mod != mod_list && !keydown)
172 selected_mod--;
173 keydown = 1;
175 else if (key[K_DOWN])
177 if ((selected_mod+1)->runfunc && !keydown)
178 selected_mod++;
179 keydown = 1;
181 else if (key[K_RETURN])
183 if (!keydown)
185 // cleanup what resources we can...
186 delete tex_bg;
187 delete font_medium;
188 delete font_small;
189 return selected_mod->runfunc();
191 keydown = 1;
193 else
195 keydown = 0;
198 // set a start and end so we don't wrap or draw too much
199 // IMPORTANT: be sure to check the bounds before anything is de-referenced!
200 struct mod* draw_start = selected_mod-entry_padding;
201 struct mod* draw_end = selected_mod+entry_padding+1;
202 struct mod* upper_bound = mod_list;
203 struct mod* lower_bound = mod_list+mod_count-1;
205 int idx = selected_mod - mod_list;
207 glPushMatrix();
208 glLoadIdentity();
209 glTranslatef(0,0,-10);
210 static float r, r_accum = 0;
211 float r_target = idx*entry_spacing;
213 // smoothly scroll the list
215 if (r_accum > r_target+scroll_speed)
216 r_accum -= scroll_speed;
217 else if ( r_accum < r_target-scroll_speed)
218 r_accum += scroll_speed;
220 // first pass, background rendering
221 glEnable(GL_LIGHT0);
222 for (struct mod* curr_mod = draw_start; curr_mod != draw_end; curr_mod++)
224 r = r_accum - entry_spacing * (idx + curr_mod-draw_start - entry_padding);
225 glPushMatrix();
226 glRotatef(r*10,1,0,0);
227 glTranslatef(0,0,-5);
229 if (curr_mod == selected_mod)
231 glDisable(GL_LIGHTING);
232 glColor3f(0,0,0);
234 else
236 glEnable(GL_LIGHTING);
239 glTranslatef(0,0,-0.1);
240 glScalef(15,3,1);
241 tex_bg->apply();
243 if (curr_mod >= upper_bound && curr_mod <= lower_bound)
244 draw_quad();
246 glPopMatrix();
249 // second pass, text rendering
250 glDisable(GL_LIGHTING);
251 for (struct mod* curr_mod = draw_start; curr_mod != draw_end; curr_mod++)
253 r = r_accum - entry_spacing * (idx + curr_mod-draw_start - entry_padding);
254 glPushMatrix();
255 glRotatef(r*10,1,0,0);
256 glTranslatef(0,0,-5);
258 if (curr_mod == selected_mod)
260 glColor3f(1,1,1);
262 else
264 glColor3f(0,0,0);
266 if (curr_mod >= upper_bound && curr_mod <= lower_bound)
268 draw_text(font_medium,curr_mod->name,0,0.5,0);
269 draw_text(font_small,curr_mod->desc,0,-0.5,0);
272 glPopMatrix();
275 glPopMatrix();
277 glColor3f(0,0,0);
278 glPushMatrix();
279 glLoadIdentity();
280 glTranslatef(0,0,-20);
281 glRotatef(90,0,0,1);
282 glDisable(GL_DEPTH_TEST);
283 draw_text(font_medium, "Select a mod to run.", 0, 10, 1);
284 glEnable(GL_DEPTH_TEST);
285 glPopMatrix();
287 SDL_Delay(10);
289 v_flip();
292 return 1;
295 int gl_init()
297 //glClearColor(0,0,0,0);
299 glMatrixMode(GL_PROJECTION);
300 glLoadIdentity();
302 double w = v_info()->width, h = v_info()->height;
303 double aspect = w/h;
305 gluPerspective(45,aspect,1,1001);
307 glEnable(GL_DEPTH_TEST);
308 glClearDepth(1);
310 glEnable(GL_CULL_FACE);
311 glFrontFace(GL_CCW);
313 glShadeModel(GL_SMOOTH);
315 glEnable(GL_TEXTURE_2D);
316 glEnable(GL_BLEND);
317 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
319 return 0;