]> Dogcows Code - chaz/yoink/blob - src/Main.cc
further implementing runloop support
[chaz/yoink] / src / Main.cc
1
2 /*] Copyright (c) 2009-2010, Charles McGarvey [**************************
3 **] All rights reserved.
4 *
5 * vi:ts=4 sw=4 tw=75
6 *
7 * Distributable under the terms and conditions of the 2-clause BSD license;
8 * see the file COPYING for a complete text of the license.
9 *
10 **************************************************************************/
11
12 #include "config.h"
13
14 #include <cstdlib> // atexit
15 #include <exception>
16 #include <functional>
17 #include <iostream>
18 #include <string>
19
20 #if !defined(__WIN32)
21 #include <termios.h>
22 #else
23 inline int isatty(int dummy) { return 0; }
24 #endif
25
26 #include <stlplus/portability/file_system.hpp>
27 #include <stlplus/portability/subprocesses.hpp>
28
29 #include <moof/image.hh>
30 #include <moof/log.hh>
31 #include <moof/modal_dialog.hh>
32 #include <moof/opengl.hh>
33 #include <moof/resource.hh>
34 #include <moof/settings.hh>
35 #include <moof/string.hh>
36 #include <moof/video.hh>
37
38 #include "Main.hh"
39 #include "version.h"
40
41
42 Main::Main(moof::settings& settings) :
43 moof::application(settings)
44 {
45 moof::dispatcher& dispatcher = moof::dispatcher::global();
46 video_reloaded_ = dispatcher.add_target("video.newcontext",
47 boost::bind(&Main::setup_opengl));
48 setup_opengl();
49
50 #if ENABLE_HOTLOADING
51 hotload_timer_.init(boost::bind(&moof::resource::reload_as_needed),
52 SCALAR(0.25),
53 moof::timer::repeat);
54 #endif
55 }
56
57
58 void Main::update(moof::scalar t, moof::scalar dt)
59 {
60 yoink.update(t, dt);
61 }
62
63 void Main::draw(moof::scalar alpha) const
64 {
65 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
66
67 glMatrixMode(GL_PROJECTION);
68 glLoadIdentity();
69
70 glMatrixMode(GL_MODELVIEW);
71 glLoadIdentity();
72
73 yoink.draw(alpha);
74 }
75
76 void Main::handle_event(const moof::event& event)
77 {
78 if (yoink.handle_event(event)) return;
79
80 switch (event.type)
81 {
82 case SDL_KEYUP:
83
84 if (event.key.keysym.sym == SDLK_f)
85 {
86 moof::video::current()->toggle_fullscreen();
87 }
88 else if (event.key.keysym.sym == SDLK_l)
89 {
90 moof::video::current()->toggle_cursor_captured();
91 moof::video::current()->toggle_cursor_visible();
92 }
93 else if (event.key.keysym.sym == SDLK_ESCAPE)
94 {
95 stop();
96 }
97 break;
98
99 case SDL_VIDEORESIZE:
100
101 glViewport(0, 0, event.resize.w, event.resize.h);
102 break;
103
104 case SDL_QUIT:
105
106 stop();
107 }
108 }
109
110
111 std::string Main::search_paths()
112 {
113 // Add search paths; they should be searched in this order:
114 // 1. YOINK_DATADIR (environment)
115 // 2. YOINK_DATADIR (configure)
116
117 std::string path;
118 std::string datadir = stlplus::env_vector()["YOINK_DATADIR"];
119 if (!datadir.empty())
120 {
121 path += datadir;
122 path += ":";
123 }
124 path += YOINK_DATADIR;
125
126 return path;
127 }
128
129 std::string Main::config_paths()
130 {
131 // Build the list of config files to search for, in this order:
132 // 1. YOINK_DATADIR/yoinkrc
133 // 2. /etc/yoinkrc (not for Windows)
134 // 3. $HOME/.yoinkrc
135 // 4. YOINKRC (environment)
136
137 std::string path = moof::resource::find_file("yoinkrc");
138
139 #if !defined(_WIN32)
140 path += ":/etc/yoinkrc";
141 #endif
142 path += ":$HOME/.yoinkrc";
143
144 std::string rc_file = stlplus::env_vector()["YOINKRC"];
145 if (!rc_file.empty())
146 {
147 path += ":";
148 path += rc_file;
149 }
150
151 return path;
152 }
153
154
155 void Main::setup_opengl()
156 {
157 glEnable(GL_TEXTURE_2D);
158 glEnable(GL_DEPTH_TEST);
159 //glEnable(GL_CULL_FACE);
160
161 glEnable(GL_POINT_SMOOTH);
162 glEnable(GL_LINE_SMOOTH);
163 glEnable(GL_POLYGON_SMOOTH);
164 glShadeModel(GL_SMOOTH);
165
166 //glEnable(GL_BLEND);
167 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
168 glEnable(GL_ALPHA_TEST);
169 glAlphaFunc(GL_GREATER, 0.0);
170
171 glClearColor(1.0, 0.0, 0.0, 1.0);
172
173 //glEnable(GL_LIGHTING);
174 glEnable(GL_LIGHT0);
175
176 glEnable(GL_COLOR_MATERIAL);
177 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
178
179 float amb[] = {0.1f, 0.1f, 0.1f, 1.0f};
180 float dif[] = {0.6f, 0.6f, 0.6f, 1.0f};
181 //glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light);
182 glLightfv(GL_LIGHT0, GL_AMBIENT, amb);
183 glLightfv(GL_LIGHT0, GL_DIFFUSE, dif);
184
185 float spec[] = {1.0f, 1.0f, 1.0f, 1.0f};
186 glLightfv(GL_LIGHT0, GL_SPECULAR, spec);
187 }
188
189
190 void Main::print_usage()
191 {
192 std::cout << "Usage: "
193 << PACKAGE" [-h|--help] [-i|--info] [OPTION=VALUE]..."
194 << std::endl
195 << "The alien-smashing action game." << std::endl
196 << std::endl
197 << "Options:" << std::endl
198 << " -h, --help" << std::endl
199 << " show this help and exit" << std::endl
200 << " -i, --info" << std::endl
201 << " show version and build information" << std::endl
202 << " detail=1|2|3" << std::endl
203 << " the level of detail of game scenes" << std::endl
204 << " fullscreen=true|false" << std::endl
205 << " if true, uses the entire display" << std::endl
206 << " framerate=num" << std::endl
207 << " number of frames to draw per second" << std::endl
208 << std::endl
209 << "See documentation for more options." << std::endl;
210 }
211
212
213 void Main::print_info(int argc, char* argv[])
214 {
215 bool color = (isatty(1) == 1);
216
217 stlplus::env_vector environment;
218
219 std::string assets;
220 assets.assign(YOINK_DATADIR);
221 if (!stlplus::file_readable(assets))
222 {
223 assets += " ";
224 if (color) assets += "\033[1;91m";
225 assets += "(no access)";
226 if (color) assets += "\033[0m";
227 }
228
229 std::string datadir = environment["YOINK_DATADIR"];
230 if (!datadir.empty())
231 {
232 if (!stlplus::folder_readable(datadir))
233 {
234 datadir += " ";
235 if (color) datadir += "\033[1;91m";
236 datadir += "(no access)";
237 if (color) datadir += "\033[0m";
238 }
239 }
240
241 std::string rc_file = environment["YOINKRC"];
242 if (!rc_file.empty())
243 {
244 if (!stlplus::file_readable(rc_file)) rc_file += " (no access)";
245 }
246
247 std::cout << " Executable: " << argv[0] << std::endl
248 #ifdef YOINK_GITHEAD
249 << " Commit: "YOINK_GITHEAD << std::endl
250 #endif
251 << " Version: " << PACKAGE_VERSION << std::endl
252 << " Built: " << COMPILE_TIME << std::endl
253 << " Compiler: " << COMPILER_STRING << std::endl
254 << " Assets: " << assets << std::endl
255 << "Build options: ";
256
257 #if ENABLE_CLOCK_GETTIME
258 print_option("clock_gettime", true);
259 #else
260 print_option("clock_gettime", false);
261 #endif
262 #if DEBUG
263 print_option("debug", true);
264 #else
265 print_option("debug", false);
266 #endif
267 #if ENABLE_DOUBLE_PRECISION
268 print_option("double", true);
269 #else
270 print_option("double", false);
271 #endif
272 #if WITH_GTK
273 print_option("gtk", true);
274 #else
275 print_option("gtk", false);
276 #endif
277 #if ENABLE_HOTLOADING
278 print_option("hotload", true);
279 #else
280 print_option("hotload", false);
281 #endif
282 #if ENABLE_PROFILING
283 print_option("profile", true);
284 #else
285 print_option("profile", false);
286 #endif
287 #if WITH_QT4
288 print_option("qt4", true);
289 #else
290 print_option("qt4", false);
291 #endif
292 #if ENABLE_THREADS
293 print_option("threads", true);
294 #else
295 print_option("threads", false);
296 #endif
297 std::cout << std::endl;
298 std::cout << " YOINKRC: " << rc_file << std::endl
299 << "YOINK_DATADIR: " << datadir << std::endl;
300 }
301
302 void Main::print_option(const std::string& option, bool enabled)
303 {
304 if (isatty(1) == 1)
305 {
306 if (enabled) std::cout << "\033[1;94m";
307 else std::cout << "\033[1m";
308 }
309 if (!enabled) std::cout << "-";
310 std::cout << option;
311 if (isatty(1) == 1) std::cout << "\033[0m";
312 std::cout << " ";
313 }
314
315
316 void hello()
317 {
318 if (isatty(1) == 1) std::cout << "\033[94m";
319 std::cout << std::endl << PACKAGE_STRING << std::endl
320 << "Compiled " << __TIME__ " " __DATE__ << std::endl
321 << "Send patches and bug reports to <"
322 PACKAGE_BUGREPORT << ">." << std::endl << moof::log::endl;
323 }
324
325 void goodbye()
326 {
327 if (isatty(1) == 1) std::cout << "\033[94m";
328 std::cout << std::endl << "Goodbye." << std::endl << moof::log::endl;
329 }
330
331
332 int main(int argc, char* argv[])
333 {
334 moof::backend backend;
335
336 if (argc > 1)
337 {
338 std::string arg(argv[1]);
339 if (arg == "-h" || arg == "--help")
340 {
341 Main::print_usage();
342 return 0;
343 }
344 else if (arg == "-i" || arg == "--info")
345 {
346 Main::print_info(argc, argv);
347 return 0;
348 }
349 }
350
351 hello();
352 atexit(goodbye);
353
354 moof::resource::set_search_paths(Main::search_paths());
355
356 moof::settings settings(argc, argv, Main::config_paths());
357
358 enum moof::log::level logLevel = moof::log::info;
359 settings.get("loglevel", logLevel);
360 moof::log::level(logLevel);
361
362 try
363 {
364 moof::image_handle icon(PACKAGE, "png");
365 if (icon) icon->set_as_icon();
366 else moof::log_error("no icon loaded");
367 icon.unload();
368
369 class moof::video::attributes attributes(settings);
370 moof::video video(PACKAGE_STRING, attributes);
371 video.show_fps(true);
372
373 Main app(settings);
374 return app.run();
375 }
376 catch (const std::exception& e)
377 {
378 moof::modal_dialog dialog(moof::modal_dialog::error,
379 PACKAGE_STRING, "unhandled exception",
380 e.what());
381 dialog.run();
382 }
383 catch (const char* e)
384 {
385 moof::modal_dialog dialog(moof::modal_dialog::error,
386 PACKAGE_STRING, "unhandled exception",
387 e);
388 dialog.run();
389 }
390
391 return 1;
392 }
393
This page took 0.048636 seconds and 4 git commands to generate.