Fixed a bug in the overlay renderer, fixed window icon
[ne.git] / src / ui / menu.cpp
blob1c8ccbb7f1b5c5e34dafe2ee55378f3a7446b00f
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 static void gl_perspective()
30 glMatrixMode(GL_PROJECTION);
31 glLoadIdentity();
33 double w = v_info()->width, h = v_info()->height;
34 double aspect = w/h;
36 gluPerspective(45,aspect,1,1001);
38 glEnable(GL_DEPTH_TEST);
39 glClearDepth(1);
41 glEnable(GL_CULL_FACE);
42 glFrontFace(GL_CCW);
44 glShadeModel(GL_SMOOTH);
46 glEnable(GL_TEXTURE_2D);
47 glEnable(GL_BLEND);
48 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
51 Menu::Menu(std::string name, Menu::MENU_MODE m)
52 : Element(name), m_background(0), m_selected(0)
54 m_keyrep.setDelay(150);
55 m_keyrep.setTime(300);
56 setMode(m);
57 setDefaults();
60 Menu::~Menu()
62 delete m_background;
65 void Menu::setDefaults()
67 m_entry_spacing = 2.0; // units step per entry
68 m_entry_padding = 3.0; // units of padding around the entry
69 m_entry_distance = -9.0; // z distance from camera
70 m_rot_target = 0.0;
71 m_rot_accel = 0.05;
72 m_rot_vel = 0.0;
73 m_rot_friction = 1.0 - 0.2;
74 m_rot_curr = 0.0;
77 void Menu::addChild(Element *e)
79 m_children.push_back(e);
82 int Menu::run()
84 v_title(m_name.c_str(), m_name.c_str());
85 v_resizecb(gl_perspective);
87 if (m_mode == OVERLAY) {
88 // take snapshot of background to render later
89 if (m_background)
90 delete m_background;
92 m_background = Texture::Screenshot();
94 else {
98 init_perspective();
100 int ret = 0;
101 bool done = false;
102 while (!done) {
103 int result = handleInput();
104 if (result == -1) {
105 ret = -1;
106 done = true;
108 else if (result == 1) {
109 v_resizecb(NULL);
110 const char *name = m_children[m_selected]->getName().c_str();
111 v_title(name, name);
112 ret = m_children[m_selected]->run();
113 i_clear();
114 break;
117 simulate();
118 draw();
119 v_flip();
120 SDL_Delay(10);
123 return ret;
126 int Menu::handleInput()
128 i_pump();
129 keysym_t *key = i_keystate();
131 if (key[K_ESCAPE]) {
132 return -1;
134 else if (key[K_UP]) {
135 if (m_selected != 0 && m_keyrep.repeat()) {
136 m_selected--;
139 else if (key[K_DOWN]) {
140 if (m_selected+1 < (int)m_children.size() && m_keyrep.repeat()) {
141 m_selected++;
144 else if (key[K_RETURN]) {
145 if (m_keyrep.repeat()) {
146 return 1;
149 else {
150 m_keyrep.clear();
153 return 0;
156 void Menu::draw()
158 static float brightness = 0.4;
159 static float bg_col[] = { 0, 0, 0 };
160 static int bg_last = rand()%3;
161 static int bg_curr = -1;
162 //bg_col[bg_last] = 1;
164 if (m_mode == BACKGROUND) {
165 if (bg_curr == -1) {
166 bg_curr = bg_last;
167 while (bg_last == bg_curr) bg_curr = rand()%3;
169 if (bg_col[bg_curr] >= 1) {
170 bg_last = bg_curr;
171 bg_curr = -1;
172 } else {
173 bg_col[bg_curr] += 0.01;
174 bg_col[bg_last] -= 0.01;
176 glClearColor(bg_col[0]*brightness, bg_col[1]*brightness, bg_col[2]*brightness, 0);
179 int draw_start = m_selected-m_entry_padding;
180 int draw_end = m_selected+m_entry_padding+1;
181 int upper_bound = 0;
182 int lower_bound = m_children.size()-1;
184 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
186 if (m_mode == OVERLAY) {
187 // draw snapshot
188 glDisable(GL_DEPTH_TEST);
189 glDisable(GL_LIGHTING);
190 glEnable(GL_TEXTURE_2D);
191 glMatrixMode(GL_MODELVIEW);
192 glLoadIdentity();
193 glMatrixMode(GL_PROJECTION);
194 glPushMatrix();
195 glLoadIdentity();
196 glColor3f(1.0, 1.0, 1.0);
197 m_background->apply();
198 glScalef(2.0, 2.0, 1.0);
199 draw_quad();
200 glPopMatrix();
201 glMatrixMode(GL_MODELVIEW);
202 glPopMatrix();
205 glMatrixMode(GL_MODELVIEW);
206 glLoadIdentity();
207 glTranslatef(0,0,-10);
209 for (int i=draw_start; i!=draw_end; i++) {
210 //float r = m_rot_curr - m_entry_spacing*i;
211 float r = m_rot_curr - i * m_entry_spacing;
213 glPushMatrix();
214 glRotatef(r*10,1,0,0);
215 glTranslatef(0,0,m_entry_distance);
217 glColor3f(1,1,1);
218 glBegin(GL_QUADS);
219 //glColor4f(1,1,1,1);
220 glVertex2f(0,0);
221 glVertex2f(0,10);
222 //glColor4f(1,1,1,0);
223 glVertex2f(10,10);
224 glVertex2f(10,0);
225 glEnd();
227 if (i >= upper_bound && i <= lower_bound)
228 m_children[i]->draw();
229 glPopMatrix();
233 void Menu::simulate()
235 m_rot_target = m_selected*m_entry_spacing;
237 // smoothly scroll the list
238 float delta = m_rot_target-m_rot_curr;
240 m_rot_vel += m_rot_accel * delta;
241 m_rot_curr += m_rot_vel;
243 // apply friction
244 m_rot_vel *= m_rot_friction;
247 void Menu::init_perspective()
249 gl_perspective();