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