Made debug builds the default, fixed a bug that made the menu bug out on
[ne.git] / src / ui / menu.cpp
blobf915a84da0dc2d0ddfd2492463ed596517c7e9a5
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 "menu.h"
19 #include "backend/video.h"
20 #include "backend/input.h"
21 #include "backend/shapes.h"
22 #include <stdlib.h>
23 #include <SDL/SDL.h>
24 #include <GL/gl.h>
25 #include <GL/glu.h>
26 #include <iostream>
28 Menu::Menu(std::string name, Menu::MENU_MODE m)
29 : Element(name), m_background(0), m_selected(0)
31 m_keyrep.setDelay(150);
32 m_keyrep.setTime(500);
33 setMode(m);
34 setDefaults();
37 Menu::~Menu()
39 delete m_background;
42 void Menu::setDefaults()
44 m_entry_spacing = 2.0; // units step per entry
45 m_entry_padding = 3.0; // units of padding around the entry
46 m_entry_distance = -9.0; // z distance from camera
47 m_rot_target = 0.0;
48 m_rot_accel = 0.05;
49 m_rot_vel = 0.0;
50 m_rot_friction = 1.0 - 0.2;
51 m_rot_curr = 0.0;
54 void Menu::addChild(Element *e)
56 m_children.push_back(e);
59 int Menu::run()
61 if (m_mode == OVERLAY) {
62 // take snapshot of background to render later
63 if (m_background)
64 delete m_background;
66 m_background = Texture::Screenshot();
68 else {
72 init_perspective();
74 int ret = 0;
75 bool done = false;
76 while (!done) {
77 int result = handleInput();
78 if (result == -1) {
79 ret = -1;
80 done = true;
82 else if (result == 1) {
83 ret = m_children[m_selected]->run();
84 i_clear();
85 break;
88 simulate();
89 draw();
90 v_flip();
91 SDL_Delay(10);
94 return ret;
97 int Menu::handleInput()
99 i_pump();
100 keysym_t *key = i_keystate();
102 if (key[K_ESCAPE]) {
103 return -1;
105 else if (key[K_UP]) {
106 if (m_selected != 0 && m_keyrep.repeat()) {
107 m_selected--;
110 else if (key[K_DOWN]) {
111 if (m_selected+1 < m_children.size() && m_keyrep.repeat()) {
112 m_selected++;
115 else if (key[K_RETURN]) {
116 if (m_keyrep.repeat()) {
117 return 1;
120 else {
121 m_keyrep.clear();
124 return 0;
127 void Menu::draw()
129 static float brightness = 0.4;
130 static float bg_col[] = { 0, 0, 0 };
131 static int bg_last = rand()%3;
132 static int bg_curr = -1;
133 //bg_col[bg_last] = 1;
135 if (m_mode == BACKGROUND) {
136 if (bg_curr == -1) {
137 bg_curr = bg_last;
138 while (bg_last == bg_curr) bg_curr = rand()%3;
140 if (bg_col[bg_curr] >= 1) {
141 bg_last = bg_curr;
142 bg_curr = -1;
143 } else {
144 bg_col[bg_curr] += 0.01;
145 bg_col[bg_last] -= 0.01;
147 glClearColor(bg_col[0]*brightness, bg_col[1]*brightness, bg_col[2]*brightness, 0);
150 int draw_start = m_selected-m_entry_padding;
151 int draw_end = m_selected+m_entry_padding+1;
152 int upper_bound = 0;
153 int lower_bound = m_children.size()-1;
155 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
157 if (m_mode == OVERLAY) {
158 // draw snapshot
159 glDisable(GL_DEPTH_TEST);
160 glMatrixMode(GL_MODELVIEW);
161 glLoadIdentity();
162 glMatrixMode(GL_PROJECTION);
163 glPushMatrix();
164 glLoadIdentity();
165 m_background->apply();
166 glScalef(2.0, 2.0, 1.0);
167 draw_quad();
168 glPopMatrix();
169 glMatrixMode(GL_MODELVIEW);
170 glPopMatrix();
173 glMatrixMode(GL_MODELVIEW);
174 glLoadIdentity();
175 glTranslatef(0,0,-10);
177 for (int i=draw_start; i!=draw_end; i++) {
178 //float r = m_rot_curr - m_entry_spacing*i;
179 float r = m_rot_curr - i * m_entry_spacing;
181 glPushMatrix();
182 glRotatef(r*10,1,0,0);
183 glTranslatef(0,0,m_entry_distance);
185 glColor3f(1,1,1);
186 glBegin(GL_QUADS);
187 //glColor4f(1,1,1,1);
188 glVertex2f(0,0);
189 glVertex2f(0,10);
190 //glColor4f(1,1,1,0);
191 glVertex2f(10,10);
192 glVertex2f(10,0);
193 glEnd();
195 if (i >= upper_bound && i <= lower_bound)
196 m_children[i]->draw();
197 glPopMatrix();
201 void Menu::simulate()
203 m_rot_target = m_selected*m_entry_spacing;
205 // smoothly scroll the list
206 float delta = m_rot_target-m_rot_curr;
208 #ifdef DEBUG
209 int err = 0;
210 if (delta > 10.0) {
211 printf("***DEBUG***\n");
212 printf("large delta detected between current position and target (%.2f)\n", delta);
213 printf("current rot is %.2f and target rot is %.2f\n", m_rot_curr, m_rot_target);
214 err = 1;
216 if (m_rot_vel > 1.0) {
217 printf("***DEBUG***\n");
218 printf("large vel detected (%.2f); target is %.2f and curr is %d\n",
219 m_rot_vel, m_rot_target, m_rot_curr);
220 printf("selected %.2f and spacing %d\n", m_selected, m_entry_spacing);
221 err = 1;
223 if (m_rot_friction > 1.0 || m_rot_friction < 0.0) {
224 printf("***DEBUG***\n");
225 printf("friction value of %.2f doesn't make sense\n", m_rot_friction);
226 err = 1;
228 if (err) exit(err);
229 #endif
231 m_rot_vel += m_rot_accel * delta;
232 m_rot_curr += m_rot_vel;
234 // apply friction
235 m_rot_vel *= m_rot_friction;
238 void Menu::init_perspective()
240 glMatrixMode(GL_PROJECTION);
241 glLoadIdentity();
243 double w = v_info()->width, h = v_info()->height;
244 double aspect = w/h;
246 gluPerspective(45,aspect,1,1001);
248 glEnable(GL_DEPTH_TEST);
249 glClearDepth(1);
251 glEnable(GL_CULL_FACE);
252 glFrontFace(GL_CCW);
254 glShadeModel(GL_SMOOTH);
256 glEnable(GL_TEXTURE_2D);
257 glEnable(GL_BLEND);
258 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);