Merge tag 'upstream/0.38'
Upstream version 0.38
Andrew Caudwell
12 years ago
0 | 0.38: | |
1 | * New high quality sprites. | |
2 | * Fullscreen toggle with alt + enter. | |
3 | * Window is now resizable. -WIDTHxHEIGHT! creates a non-resizable window. | |
4 | * Lowered minimum zoom distance. | |
5 | * Use AM_CPPFLAGS in Makefile.am to allow passing custom CPPFLAGS. | |
6 | * Don't add files that match the path of a known directory. | |
7 | * Fixed divide by zero in text shader causing artifacts on some video cards. | |
8 | * Recursively search for repository directory when log-format not specified | |
9 | (thanks to Jörg Bachmann for original concept / prototype). | |
10 | * New dependency on Boost Filesystem. | |
11 | * Doubled the maximum zoom out distance. | |
12 | * Allow negative timestamps before 1970 in custom log (artzub). | |
13 | * Fix for UTF8-CPP checked.h compilation issue (vszakats). | |
14 | * Fixed bug causing missing characters in text. | |
15 | * Fixed --highlight-users option not using highlight-colour. | |
16 | * highlight-colour default changed to white. | |
17 | * Added --selection-colour option (applied to selected users and files). | |
18 | * Added --dir-colour option (applied to directories). | |
19 | ||
0 | 20 | 0.37: |
1 | 21 | * Made SVN log GMT timestamp conversion fix portable. |
2 | 22 |
9 | 9 | 1. Dependencies |
10 | 10 | =============== |
11 | 11 | |
12 | Gource requires the following libraries to compile: | |
12 | Gource requires the following libraries to compile (package names may vary): | |
13 | 13 | |
14 | 14 | SDL 1.2 (libsdl1.2-dev) |
15 | 15 | SDL Image 1.2 (libsdl-image1.2-dev) |
16 | 16 | PCRE3 (libpcre3-dev) |
17 | 17 | Freetype 2 (libfreetype6-dev) |
18 | 18 | GLEW (libglew-dev) |
19 | GLM (libglm-dev) >= 0.9.3 | |
20 | Boost Filesystem >= 1.46 (libboost-filesystem-dev) | |
19 | 21 | |
20 | 22 | Optional: |
21 | 23 | |
22 | 24 | TinyXML (libtinyxml-dev) |
23 | 25 | |
24 | Note: SDL Image needs to have been built with support PNG and JPEG images. | |
26 | SDL Image needs to have been built with support PNG and JPEG images. | |
27 | ||
28 | GLM is a header only library that you can get from http://glm.g-truc.net/ if your distribution does not include it. | |
25 | 29 | |
26 | 30 | 2. Building |
27 | 31 | =========== |
36 | 40 | git submodule init |
37 | 41 | git submodule update |
38 | 42 | |
39 | Building on Linux/Mac OS: | |
43 | Generic build instructions for Linux/Mac OS: | |
40 | 44 | |
41 | 45 | ./configure |
42 | 46 | make |
48 | 52 | for the Code Blocks IDE (www.codeblocks.org). |
49 | 53 | |
50 | 54 | A pre-built version for Windows is normally available from the homepage. |
55 | ||
56 | Gource expects SDL to have been built with the NO_STDIO_REDIRECT flag. | |
51 | 57 | |
52 | 58 | 3. Configure Options |
53 | 59 | ==================== |
3 | 3 | |
4 | 4 | gource_SOURCES = \ |
5 | 5 | src/action.cpp src/action.h \ |
6 | src/apache.cpp src/apache.h \ | |
7 | src/bloom.cpp src/bloom.h \ | |
8 | src/bzr.cpp src/bzr.h \ | |
9 | src/commitlog.cpp src/commitlog.h \ | |
6 | src/bloom.cpp src/bloom.h \ | |
10 | 7 | src/core/bounds.h \ |
11 | src/core/camera.cpp src/core/camera.h \ | |
12 | 8 | src/core/conffile.cpp src/core/conffile.h \ |
13 | 9 | src/core/display.cpp src/core/display.h \ |
14 | 10 | src/core/frustum.cpp src/core/frustum.h \ |
33 | 29 | src/core/utf8/unchecked.h \ |
34 | 30 | src/core/utf8/utf8.h \ |
35 | 31 | src/core/vbo.cpp src/core/vbo.h \ |
36 | src/core/vectors.h \ | |
37 | src/custom.cpp src/custom.h \ | |
38 | src/cvs-exp.cpp src/cvs-exp.h \ | |
39 | src/cvs2cl.cpp src/cvs2cl.h \ | |
32 | src/core/vectors.cpp src/core/vectors.h \ | |
40 | 33 | src/dirnode.cpp src/dirnode.h \ |
41 | 34 | src/file.cpp src/file.h \ |
42 | src/git.cpp src/git.h \ | |
43 | src/gitraw.cpp src/gitraw.h \ | |
35 | src/formats/apache.cpp src/formats/apache.h \ | |
36 | src/formats/bzr.cpp src/formats/bzr.h \ | |
37 | src/formats/commitlog.cpp src/formats/commitlog.h \ | |
38 | src/formats/custom.cpp src/formats/custom.h \ | |
39 | src/formats/cvs-exp.cpp src/formats/cvs-exp.h \ | |
40 | src/formats/cvs2cl.cpp src/formats/cvs2cl.h \ | |
41 | src/formats/git.cpp src/formats/git.h \ | |
42 | src/formats/gitraw.cpp src/formats/gitraw.h \ | |
43 | src/formats/hg.cpp src/formats/hg.h \ | |
44 | src/formats/svn.cpp src/formats/svn.h \ | |
44 | 45 | src/gource.cpp src/gource.h \ |
45 | 46 | src/gource_shell.cpp src/gource_shell.h \ |
46 | 47 | src/gource_settings.cpp src/gource_settings.h \ |
47 | src/hg.cpp src/hg.h \ | |
48 | 48 | src/key.cpp src/key.h \ |
49 | src/logmill.cpp src/logmill.h \ | |
49 | 50 | src/main.cpp src/main.h \ |
50 | 51 | src/pawn.cpp src/pawn.h \ |
51 | 52 | src/slider.cpp src/slider.h \ |
52 | 53 | src/spline.cpp src/spline.h \ |
53 | src/svn.cpp src/svn.h \ | |
54 | 54 | src/textbox.cpp src/textbox.h \ |
55 | 55 | src/user.cpp src/user.h \ |
56 | 56 | src/zoomcamera.cpp src/zoomcamera.h |
57 | 57 | |
58 | CPPFLAGS = -DSDLAPP_RESOURCE_DIR=\"$(pkgdatadir)\" | |
58 | AM_CPPFLAGS = -DSDLAPP_RESOURCE_DIR=\"$(pkgdatadir)\" | |
59 | 59 | |
60 | dist_pkgdata_DATA = data/beam.png data/bloom.tga data/bloom_alpha.tga data/cursor.png data/file.png data/no_photo.png data/gource.style | |
60 | dist_pkgdata_DATA = data/beam.png data/bloom.tga data/bloom_alpha.tga data/file.png data/user.png data/gource.style | |
61 | 61 | |
62 | 62 | shadersdir = $(pkgdatadir)/shaders |
63 | 63 | dist_shaders_DATA = data/shaders/shadow.vert data/shaders/shadow.frag data/shaders/bloom.vert data/shaders/bloom.frag data/shaders/text.vert data/shaders/text.frag |
79 | 79 | endif |
80 | 80 | |
81 | 81 | if FONTDIR |
82 | CPPFLAGS += -DSDLAPP_FONT_DIR=\"$(gourcefontdir)\" | |
82 | AM_CPPFLAGS += -DSDLAPP_FONT_DIR=\"$(gourcefontdir)\" | |
83 | 83 | else |
84 | 84 | fontsdir = $(pkgdatadir)/fonts |
85 | 85 | dist_fonts_DATA = data/fonts/README data/fonts/FreeSans.ttf |
53 | 53 | $(top_srcdir)/m4/ax_check_glu.m4 \ |
54 | 54 | $(top_srcdir)/m4/ax_lang_compiler_ms.m4 \ |
55 | 55 | $(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/freetype2.m4 \ |
56 | $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac | |
56 | $(top_srcdir)/m4/m4_ax_boost_base.m4 \ | |
57 | $(top_srcdir)/m4/m4_ax_boost_filesystem.m4 \ | |
58 | $(top_srcdir)/m4/m4_ax_boost_system.m4 $(top_srcdir)/m4/sdl.m4 \ | |
59 | $(top_srcdir)/configure.ac | |
57 | 60 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
58 | 61 | $(ACLOCAL_M4) |
59 | 62 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ |
64 | 67 | am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(fontsdir)" \ |
65 | 68 | "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(shadersdir)" |
66 | 69 | PROGRAMS = $(bin_PROGRAMS) |
67 | am__gource_SOURCES_DIST = src/action.cpp src/action.h src/apache.cpp \ | |
68 | src/apache.h src/bloom.cpp src/bloom.h src/bzr.cpp src/bzr.h \ | |
69 | src/commitlog.cpp src/commitlog.h src/core/bounds.h \ | |
70 | src/core/camera.cpp src/core/camera.h src/core/conffile.cpp \ | |
70 | am__gource_SOURCES_DIST = src/action.cpp src/action.h src/bloom.cpp \ | |
71 | src/bloom.h src/core/bounds.h src/core/conffile.cpp \ | |
71 | 72 | src/core/conffile.h src/core/display.cpp src/core/display.h \ |
72 | 73 | src/core/frustum.cpp src/core/frustum.h src/core/fxfont.cpp \ |
73 | 74 | src/core/fxfont.h src/core/gl.h src/core/logger.cpp \ |
82 | 83 | src/core/stringhash.h src/core/texture.cpp src/core/texture.h \ |
83 | 84 | src/core/utf8/checked.h src/core/utf8/core.h \ |
84 | 85 | src/core/utf8/unchecked.h src/core/utf8/utf8.h \ |
85 | src/core/vbo.cpp src/core/vbo.h src/core/vectors.h \ | |
86 | src/custom.cpp src/custom.h src/cvs-exp.cpp src/cvs-exp.h \ | |
87 | src/cvs2cl.cpp src/cvs2cl.h src/dirnode.cpp src/dirnode.h \ | |
88 | src/file.cpp src/file.h src/git.cpp src/git.h src/gitraw.cpp \ | |
89 | src/gitraw.h src/gource.cpp src/gource.h src/gource_shell.cpp \ | |
90 | src/gource_shell.h src/gource_settings.cpp \ | |
91 | src/gource_settings.h src/hg.cpp src/hg.h src/key.cpp \ | |
92 | src/key.h src/main.cpp src/main.h src/pawn.cpp src/pawn.h \ | |
93 | src/slider.cpp src/slider.h src/spline.cpp src/spline.h \ | |
94 | src/svn.cpp src/svn.h src/textbox.cpp src/textbox.h \ | |
86 | src/core/vbo.cpp src/core/vbo.h src/core/vectors.cpp \ | |
87 | src/core/vectors.h src/dirnode.cpp src/dirnode.h src/file.cpp \ | |
88 | src/file.h src/formats/apache.cpp src/formats/apache.h \ | |
89 | src/formats/bzr.cpp src/formats/bzr.h \ | |
90 | src/formats/commitlog.cpp src/formats/commitlog.h \ | |
91 | src/formats/custom.cpp src/formats/custom.h \ | |
92 | src/formats/cvs-exp.cpp src/formats/cvs-exp.h \ | |
93 | src/formats/cvs2cl.cpp src/formats/cvs2cl.h \ | |
94 | src/formats/git.cpp src/formats/git.h src/formats/gitraw.cpp \ | |
95 | src/formats/gitraw.h src/formats/hg.cpp src/formats/hg.h \ | |
96 | src/formats/svn.cpp src/formats/svn.h src/gource.cpp \ | |
97 | src/gource.h src/gource_shell.cpp src/gource_shell.h \ | |
98 | src/gource_settings.cpp src/gource_settings.h src/key.cpp \ | |
99 | src/key.h src/logmill.cpp src/logmill.h src/main.cpp \ | |
100 | src/main.h src/pawn.cpp src/pawn.h src/slider.cpp src/slider.h \ | |
101 | src/spline.cpp src/spline.h src/textbox.cpp src/textbox.h \ | |
95 | 102 | src/user.cpp src/user.h src/zoomcamera.cpp src/zoomcamera.h \ |
96 | 103 | src/tinyxml/tinyxmlerror.cpp src/tinyxml/tinystr.cpp \ |
97 | 104 | src/tinyxml/tinystr.h src/tinyxml/tinyxml.cpp \ |
103 | 110 | @USE_BUNDLED_TINYXML_TRUE@ src/tinyxml/tinystr.$(OBJEXT) \ |
104 | 111 | @USE_BUNDLED_TINYXML_TRUE@ src/tinyxml/tinyxml.$(OBJEXT) \ |
105 | 112 | @USE_BUNDLED_TINYXML_TRUE@ src/tinyxml/tinyxmlparser.$(OBJEXT) |
106 | am_gource_OBJECTS = src/action.$(OBJEXT) src/apache.$(OBJEXT) \ | |
107 | src/bloom.$(OBJEXT) src/bzr.$(OBJEXT) src/commitlog.$(OBJEXT) \ | |
108 | src/core/camera.$(OBJEXT) src/core/conffile.$(OBJEXT) \ | |
109 | src/core/display.$(OBJEXT) src/core/frustum.$(OBJEXT) \ | |
110 | src/core/fxfont.$(OBJEXT) src/core/logger.$(OBJEXT) \ | |
111 | src/core/mousecursor.$(OBJEXT) src/core/plane.$(OBJEXT) \ | |
112 | src/core/ppm.$(OBJEXT) src/core/quadtree.$(OBJEXT) \ | |
113 | src/core/regex.$(OBJEXT) src/core/resource.$(OBJEXT) \ | |
114 | src/core/sdlapp.$(OBJEXT) src/core/seeklog.$(OBJEXT) \ | |
115 | src/core/settings.$(OBJEXT) src/core/shader.$(OBJEXT) \ | |
116 | src/core/stringhash.$(OBJEXT) src/core/texture.$(OBJEXT) \ | |
117 | src/core/vbo.$(OBJEXT) src/custom.$(OBJEXT) \ | |
118 | src/cvs-exp.$(OBJEXT) src/cvs2cl.$(OBJEXT) \ | |
119 | src/dirnode.$(OBJEXT) src/file.$(OBJEXT) src/git.$(OBJEXT) \ | |
120 | src/gitraw.$(OBJEXT) src/gource.$(OBJEXT) \ | |
113 | am_gource_OBJECTS = src/action.$(OBJEXT) src/bloom.$(OBJEXT) \ | |
114 | src/core/conffile.$(OBJEXT) src/core/display.$(OBJEXT) \ | |
115 | src/core/frustum.$(OBJEXT) src/core/fxfont.$(OBJEXT) \ | |
116 | src/core/logger.$(OBJEXT) src/core/mousecursor.$(OBJEXT) \ | |
117 | src/core/plane.$(OBJEXT) src/core/ppm.$(OBJEXT) \ | |
118 | src/core/quadtree.$(OBJEXT) src/core/regex.$(OBJEXT) \ | |
119 | src/core/resource.$(OBJEXT) src/core/sdlapp.$(OBJEXT) \ | |
120 | src/core/seeklog.$(OBJEXT) src/core/settings.$(OBJEXT) \ | |
121 | src/core/shader.$(OBJEXT) src/core/stringhash.$(OBJEXT) \ | |
122 | src/core/texture.$(OBJEXT) src/core/vbo.$(OBJEXT) \ | |
123 | src/core/vectors.$(OBJEXT) src/dirnode.$(OBJEXT) \ | |
124 | src/file.$(OBJEXT) src/formats/apache.$(OBJEXT) \ | |
125 | src/formats/bzr.$(OBJEXT) src/formats/commitlog.$(OBJEXT) \ | |
126 | src/formats/custom.$(OBJEXT) src/formats/cvs-exp.$(OBJEXT) \ | |
127 | src/formats/cvs2cl.$(OBJEXT) src/formats/git.$(OBJEXT) \ | |
128 | src/formats/gitraw.$(OBJEXT) src/formats/hg.$(OBJEXT) \ | |
129 | src/formats/svn.$(OBJEXT) src/gource.$(OBJEXT) \ | |
121 | 130 | src/gource_shell.$(OBJEXT) src/gource_settings.$(OBJEXT) \ |
122 | src/hg.$(OBJEXT) src/key.$(OBJEXT) src/main.$(OBJEXT) \ | |
131 | src/key.$(OBJEXT) src/logmill.$(OBJEXT) src/main.$(OBJEXT) \ | |
123 | 132 | src/pawn.$(OBJEXT) src/slider.$(OBJEXT) src/spline.$(OBJEXT) \ |
124 | src/svn.$(OBJEXT) src/textbox.$(OBJEXT) src/user.$(OBJEXT) \ | |
133 | src/textbox.$(OBJEXT) src/user.$(OBJEXT) \ | |
125 | 134 | src/zoomcamera.$(OBJEXT) $(am__objects_1) |
126 | 135 | gource_OBJECTS = $(am_gource_OBJECTS) |
127 | 136 | gource_LDADD = $(LDADD) |
182 | 191 | AUTOHEADER = @AUTOHEADER@ |
183 | 192 | AUTOMAKE = @AUTOMAKE@ |
184 | 193 | AWK = @AWK@ |
194 | BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ | |
195 | BOOST_FILESYSTEM_LIB = @BOOST_FILESYSTEM_LIB@ | |
196 | BOOST_LDFLAGS = @BOOST_LDFLAGS@ | |
197 | BOOST_SYSTEM_LIB = @BOOST_SYSTEM_LIB@ | |
185 | 198 | CC = @CC@ |
186 | 199 | CCDEPMODE = @CCDEPMODE@ |
187 | 200 | CFLAGS = @CFLAGS@ |
188 | 201 | CPP = @CPP@ |
189 | CPPFLAGS = -DSDLAPP_RESOURCE_DIR=\"$(pkgdatadir)\" $(am__append_2) | |
202 | CPPFLAGS = @CPPFLAGS@ | |
190 | 203 | CXX = @CXX@ |
191 | 204 | CXXCPP = @CXXCPP@ |
192 | 205 | CXXDEPMODE = @CXXDEPMODE@ |
295 | 308 | top_builddir = @top_builddir@ |
296 | 309 | top_srcdir = @top_srcdir@ |
297 | 310 | ACLOCAL_AMFLAGS = -I m4 |
298 | gource_SOURCES = src/action.cpp src/action.h src/apache.cpp \ | |
299 | src/apache.h src/bloom.cpp src/bloom.h src/bzr.cpp src/bzr.h \ | |
300 | src/commitlog.cpp src/commitlog.h src/core/bounds.h \ | |
301 | src/core/camera.cpp src/core/camera.h src/core/conffile.cpp \ | |
302 | src/core/conffile.h src/core/display.cpp src/core/display.h \ | |
303 | src/core/frustum.cpp src/core/frustum.h src/core/fxfont.cpp \ | |
304 | src/core/fxfont.h src/core/gl.h src/core/logger.cpp \ | |
305 | src/core/logger.h src/core/mousecursor.cpp \ | |
306 | src/core/mousecursor.h src/core/pi.h src/core/plane.cpp \ | |
307 | src/core/plane.h src/core/ppm.cpp src/core/ppm.h \ | |
308 | src/core/quadtree.cpp src/core/quadtree.h src/core/regex.cpp \ | |
309 | src/core/regex.h src/core/resource.cpp src/core/resource.h \ | |
310 | src/core/sdlapp.cpp src/core/sdlapp.h src/core/seeklog.cpp \ | |
311 | src/core/seeklog.h src/core/settings.cpp src/core/settings.h \ | |
312 | src/core/shader.cpp src/core/shader.h src/core/stringhash.cpp \ | |
313 | src/core/stringhash.h src/core/texture.cpp src/core/texture.h \ | |
311 | gource_SOURCES = src/action.cpp src/action.h src/bloom.cpp src/bloom.h \ | |
312 | src/core/bounds.h src/core/conffile.cpp src/core/conffile.h \ | |
313 | src/core/display.cpp src/core/display.h src/core/frustum.cpp \ | |
314 | src/core/frustum.h src/core/fxfont.cpp src/core/fxfont.h \ | |
315 | src/core/gl.h src/core/logger.cpp src/core/logger.h \ | |
316 | src/core/mousecursor.cpp src/core/mousecursor.h src/core/pi.h \ | |
317 | src/core/plane.cpp src/core/plane.h src/core/ppm.cpp \ | |
318 | src/core/ppm.h src/core/quadtree.cpp src/core/quadtree.h \ | |
319 | src/core/regex.cpp src/core/regex.h src/core/resource.cpp \ | |
320 | src/core/resource.h src/core/sdlapp.cpp src/core/sdlapp.h \ | |
321 | src/core/seeklog.cpp src/core/seeklog.h src/core/settings.cpp \ | |
322 | src/core/settings.h src/core/shader.cpp src/core/shader.h \ | |
323 | src/core/stringhash.cpp src/core/stringhash.h \ | |
324 | src/core/texture.cpp src/core/texture.h \ | |
314 | 325 | src/core/utf8/checked.h src/core/utf8/core.h \ |
315 | 326 | src/core/utf8/unchecked.h src/core/utf8/utf8.h \ |
316 | src/core/vbo.cpp src/core/vbo.h src/core/vectors.h \ | |
317 | src/custom.cpp src/custom.h src/cvs-exp.cpp src/cvs-exp.h \ | |
318 | src/cvs2cl.cpp src/cvs2cl.h src/dirnode.cpp src/dirnode.h \ | |
319 | src/file.cpp src/file.h src/git.cpp src/git.h src/gitraw.cpp \ | |
320 | src/gitraw.h src/gource.cpp src/gource.h src/gource_shell.cpp \ | |
321 | src/gource_shell.h src/gource_settings.cpp \ | |
322 | src/gource_settings.h src/hg.cpp src/hg.h src/key.cpp \ | |
323 | src/key.h src/main.cpp src/main.h src/pawn.cpp src/pawn.h \ | |
324 | src/slider.cpp src/slider.h src/spline.cpp src/spline.h \ | |
325 | src/svn.cpp src/svn.h src/textbox.cpp src/textbox.h \ | |
327 | src/core/vbo.cpp src/core/vbo.h src/core/vectors.cpp \ | |
328 | src/core/vectors.h src/dirnode.cpp src/dirnode.h src/file.cpp \ | |
329 | src/file.h src/formats/apache.cpp src/formats/apache.h \ | |
330 | src/formats/bzr.cpp src/formats/bzr.h \ | |
331 | src/formats/commitlog.cpp src/formats/commitlog.h \ | |
332 | src/formats/custom.cpp src/formats/custom.h \ | |
333 | src/formats/cvs-exp.cpp src/formats/cvs-exp.h \ | |
334 | src/formats/cvs2cl.cpp src/formats/cvs2cl.h \ | |
335 | src/formats/git.cpp src/formats/git.h src/formats/gitraw.cpp \ | |
336 | src/formats/gitraw.h src/formats/hg.cpp src/formats/hg.h \ | |
337 | src/formats/svn.cpp src/formats/svn.h src/gource.cpp \ | |
338 | src/gource.h src/gource_shell.cpp src/gource_shell.h \ | |
339 | src/gource_settings.cpp src/gource_settings.h src/key.cpp \ | |
340 | src/key.h src/logmill.cpp src/logmill.h src/main.cpp \ | |
341 | src/main.h src/pawn.cpp src/pawn.h src/slider.cpp src/slider.h \ | |
342 | src/spline.cpp src/spline.h src/textbox.cpp src/textbox.h \ | |
326 | 343 | src/user.cpp src/user.h src/zoomcamera.cpp src/zoomcamera.h \ |
327 | 344 | $(am__append_1) |
328 | dist_pkgdata_DATA = data/beam.png data/bloom.tga data/bloom_alpha.tga data/cursor.png data/file.png data/no_photo.png data/gource.style | |
345 | AM_CPPFLAGS = -DSDLAPP_RESOURCE_DIR=\"$(pkgdatadir)\" $(am__append_2) | |
346 | dist_pkgdata_DATA = data/beam.png data/bloom.tga data/bloom_alpha.tga data/file.png data/user.png data/gource.style | |
329 | 347 | shadersdir = $(pkgdatadir)/shaders |
330 | 348 | dist_shaders_DATA = data/shaders/shadow.vert data/shaders/shadow.frag data/shaders/bloom.vert data/shaders/bloom.frag data/shaders/text.vert data/shaders/text.frag |
331 | 349 | @FONTDIR_FALSE@fontsdir = $(pkgdatadir)/fonts |
413 | 431 | @: > src/$(DEPDIR)/$(am__dirstamp) |
414 | 432 | src/action.$(OBJEXT): src/$(am__dirstamp) \ |
415 | 433 | src/$(DEPDIR)/$(am__dirstamp) |
416 | src/apache.$(OBJEXT): src/$(am__dirstamp) \ | |
417 | src/$(DEPDIR)/$(am__dirstamp) | |
418 | 434 | src/bloom.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
419 | src/bzr.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) | |
420 | src/commitlog.$(OBJEXT): src/$(am__dirstamp) \ | |
421 | src/$(DEPDIR)/$(am__dirstamp) | |
422 | 435 | src/core/$(am__dirstamp): |
423 | 436 | @$(MKDIR_P) src/core |
424 | 437 | @: > src/core/$(am__dirstamp) |
425 | 438 | src/core/$(DEPDIR)/$(am__dirstamp): |
426 | 439 | @$(MKDIR_P) src/core/$(DEPDIR) |
427 | 440 | @: > src/core/$(DEPDIR)/$(am__dirstamp) |
428 | src/core/camera.$(OBJEXT): src/core/$(am__dirstamp) \ | |
429 | src/core/$(DEPDIR)/$(am__dirstamp) | |
430 | 441 | src/core/conffile.$(OBJEXT): src/core/$(am__dirstamp) \ |
431 | 442 | src/core/$(DEPDIR)/$(am__dirstamp) |
432 | 443 | src/core/display.$(OBJEXT): src/core/$(am__dirstamp) \ |
463 | 474 | src/core/$(DEPDIR)/$(am__dirstamp) |
464 | 475 | src/core/vbo.$(OBJEXT): src/core/$(am__dirstamp) \ |
465 | 476 | src/core/$(DEPDIR)/$(am__dirstamp) |
466 | src/custom.$(OBJEXT): src/$(am__dirstamp) \ | |
467 | src/$(DEPDIR)/$(am__dirstamp) | |
468 | src/cvs-exp.$(OBJEXT): src/$(am__dirstamp) \ | |
469 | src/$(DEPDIR)/$(am__dirstamp) | |
470 | src/cvs2cl.$(OBJEXT): src/$(am__dirstamp) \ | |
471 | src/$(DEPDIR)/$(am__dirstamp) | |
477 | src/core/vectors.$(OBJEXT): src/core/$(am__dirstamp) \ | |
478 | src/core/$(DEPDIR)/$(am__dirstamp) | |
472 | 479 | src/dirnode.$(OBJEXT): src/$(am__dirstamp) \ |
473 | 480 | src/$(DEPDIR)/$(am__dirstamp) |
474 | 481 | src/file.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
475 | src/git.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) | |
476 | src/gitraw.$(OBJEXT): src/$(am__dirstamp) \ | |
477 | src/$(DEPDIR)/$(am__dirstamp) | |
482 | src/formats/$(am__dirstamp): | |
483 | @$(MKDIR_P) src/formats | |
484 | @: > src/formats/$(am__dirstamp) | |
485 | src/formats/$(DEPDIR)/$(am__dirstamp): | |
486 | @$(MKDIR_P) src/formats/$(DEPDIR) | |
487 | @: > src/formats/$(DEPDIR)/$(am__dirstamp) | |
488 | src/formats/apache.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
489 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
490 | src/formats/bzr.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
491 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
492 | src/formats/commitlog.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
493 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
494 | src/formats/custom.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
495 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
496 | src/formats/cvs-exp.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
497 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
498 | src/formats/cvs2cl.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
499 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
500 | src/formats/git.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
501 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
502 | src/formats/gitraw.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
503 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
504 | src/formats/hg.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
505 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
506 | src/formats/svn.$(OBJEXT): src/formats/$(am__dirstamp) \ | |
507 | src/formats/$(DEPDIR)/$(am__dirstamp) | |
478 | 508 | src/gource.$(OBJEXT): src/$(am__dirstamp) \ |
479 | 509 | src/$(DEPDIR)/$(am__dirstamp) |
480 | 510 | src/gource_shell.$(OBJEXT): src/$(am__dirstamp) \ |
481 | 511 | src/$(DEPDIR)/$(am__dirstamp) |
482 | 512 | src/gource_settings.$(OBJEXT): src/$(am__dirstamp) \ |
483 | 513 | src/$(DEPDIR)/$(am__dirstamp) |
484 | src/hg.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) | |
485 | 514 | src/key.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
515 | src/logmill.$(OBJEXT): src/$(am__dirstamp) \ | |
516 | src/$(DEPDIR)/$(am__dirstamp) | |
486 | 517 | src/main.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
487 | 518 | src/pawn.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
488 | 519 | src/slider.$(OBJEXT): src/$(am__dirstamp) \ |
489 | 520 | src/$(DEPDIR)/$(am__dirstamp) |
490 | 521 | src/spline.$(OBJEXT): src/$(am__dirstamp) \ |
491 | 522 | src/$(DEPDIR)/$(am__dirstamp) |
492 | src/svn.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) | |
493 | 523 | src/textbox.$(OBJEXT): src/$(am__dirstamp) \ |
494 | 524 | src/$(DEPDIR)/$(am__dirstamp) |
495 | 525 | src/user.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) |
516 | 546 | mostlyclean-compile: |
517 | 547 | -rm -f *.$(OBJEXT) |
518 | 548 | -rm -f src/action.$(OBJEXT) |
519 | -rm -f src/apache.$(OBJEXT) | |
520 | 549 | -rm -f src/bloom.$(OBJEXT) |
521 | -rm -f src/bzr.$(OBJEXT) | |
522 | -rm -f src/commitlog.$(OBJEXT) | |
523 | -rm -f src/core/camera.$(OBJEXT) | |
524 | 550 | -rm -f src/core/conffile.$(OBJEXT) |
525 | 551 | -rm -f src/core/display.$(OBJEXT) |
526 | 552 | -rm -f src/core/frustum.$(OBJEXT) |
539 | 565 | -rm -f src/core/stringhash.$(OBJEXT) |
540 | 566 | -rm -f src/core/texture.$(OBJEXT) |
541 | 567 | -rm -f src/core/vbo.$(OBJEXT) |
542 | -rm -f src/custom.$(OBJEXT) | |
543 | -rm -f src/cvs-exp.$(OBJEXT) | |
544 | -rm -f src/cvs2cl.$(OBJEXT) | |
568 | -rm -f src/core/vectors.$(OBJEXT) | |
545 | 569 | -rm -f src/dirnode.$(OBJEXT) |
546 | 570 | -rm -f src/file.$(OBJEXT) |
547 | -rm -f src/git.$(OBJEXT) | |
548 | -rm -f src/gitraw.$(OBJEXT) | |
571 | -rm -f src/formats/apache.$(OBJEXT) | |
572 | -rm -f src/formats/bzr.$(OBJEXT) | |
573 | -rm -f src/formats/commitlog.$(OBJEXT) | |
574 | -rm -f src/formats/custom.$(OBJEXT) | |
575 | -rm -f src/formats/cvs-exp.$(OBJEXT) | |
576 | -rm -f src/formats/cvs2cl.$(OBJEXT) | |
577 | -rm -f src/formats/git.$(OBJEXT) | |
578 | -rm -f src/formats/gitraw.$(OBJEXT) | |
579 | -rm -f src/formats/hg.$(OBJEXT) | |
580 | -rm -f src/formats/svn.$(OBJEXT) | |
549 | 581 | -rm -f src/gource.$(OBJEXT) |
550 | 582 | -rm -f src/gource_settings.$(OBJEXT) |
551 | 583 | -rm -f src/gource_shell.$(OBJEXT) |
552 | -rm -f src/hg.$(OBJEXT) | |
553 | 584 | -rm -f src/key.$(OBJEXT) |
585 | -rm -f src/logmill.$(OBJEXT) | |
554 | 586 | -rm -f src/main.$(OBJEXT) |
555 | 587 | -rm -f src/pawn.$(OBJEXT) |
556 | 588 | -rm -f src/slider.$(OBJEXT) |
557 | 589 | -rm -f src/spline.$(OBJEXT) |
558 | -rm -f src/svn.$(OBJEXT) | |
559 | 590 | -rm -f src/textbox.$(OBJEXT) |
560 | 591 | -rm -f src/tinyxml/tinystr.$(OBJEXT) |
561 | 592 | -rm -f src/tinyxml/tinyxml.$(OBJEXT) |
568 | 599 | -rm -f *.tab.c |
569 | 600 | |
570 | 601 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/action.Po@am__quote@ |
571 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/apache.Po@am__quote@ | |
572 | 602 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bloom.Po@am__quote@ |
573 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bzr.Po@am__quote@ | |
574 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/commitlog.Po@am__quote@ | |
575 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/custom.Po@am__quote@ | |
576 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cvs-exp.Po@am__quote@ | |
577 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/cvs2cl.Po@am__quote@ | |
578 | 603 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/dirnode.Po@am__quote@ |
579 | 604 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/file.Po@am__quote@ |
580 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/git.Po@am__quote@ | |
581 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/gitraw.Po@am__quote@ | |
582 | 605 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/gource.Po@am__quote@ |
583 | 606 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/gource_settings.Po@am__quote@ |
584 | 607 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/gource_shell.Po@am__quote@ |
585 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/hg.Po@am__quote@ | |
586 | 608 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/key.Po@am__quote@ |
609 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logmill.Po@am__quote@ | |
587 | 610 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/main.Po@am__quote@ |
588 | 611 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/pawn.Po@am__quote@ |
589 | 612 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/slider.Po@am__quote@ |
590 | 613 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/spline.Po@am__quote@ |
591 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/svn.Po@am__quote@ | |
592 | 614 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/textbox.Po@am__quote@ |
593 | 615 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/user.Po@am__quote@ |
594 | 616 | @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/zoomcamera.Po@am__quote@ |
595 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/camera.Po@am__quote@ | |
596 | 617 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/conffile.Po@am__quote@ |
597 | 618 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/display.Po@am__quote@ |
598 | 619 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/frustum.Po@am__quote@ |
611 | 632 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/stringhash.Po@am__quote@ |
612 | 633 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/texture.Po@am__quote@ |
613 | 634 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/vbo.Po@am__quote@ |
635 | @AMDEP_TRUE@@am__include@ @am__quote@src/core/$(DEPDIR)/vectors.Po@am__quote@ | |
636 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/apache.Po@am__quote@ | |
637 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/bzr.Po@am__quote@ | |
638 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/commitlog.Po@am__quote@ | |
639 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/custom.Po@am__quote@ | |
640 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/cvs-exp.Po@am__quote@ | |
641 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/cvs2cl.Po@am__quote@ | |
642 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/git.Po@am__quote@ | |
643 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/gitraw.Po@am__quote@ | |
644 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/hg.Po@am__quote@ | |
645 | @AMDEP_TRUE@@am__include@ @am__quote@src/formats/$(DEPDIR)/svn.Po@am__quote@ | |
614 | 646 | @AMDEP_TRUE@@am__include@ @am__quote@src/tinyxml/$(DEPDIR)/tinystr.Po@am__quote@ |
615 | 647 | @AMDEP_TRUE@@am__include@ @am__quote@src/tinyxml/$(DEPDIR)/tinyxml.Po@am__quote@ |
616 | 648 | @AMDEP_TRUE@@am__include@ @am__quote@src/tinyxml/$(DEPDIR)/tinyxmlerror.Po@am__quote@ |
923 | 955 | -rm -f src/$(am__dirstamp) |
924 | 956 | -rm -f src/core/$(DEPDIR)/$(am__dirstamp) |
925 | 957 | -rm -f src/core/$(am__dirstamp) |
958 | -rm -f src/formats/$(DEPDIR)/$(am__dirstamp) | |
959 | -rm -f src/formats/$(am__dirstamp) | |
926 | 960 | -rm -f src/tinyxml/$(DEPDIR)/$(am__dirstamp) |
927 | 961 | -rm -f src/tinyxml/$(am__dirstamp) |
928 | 962 | |
935 | 969 | |
936 | 970 | distclean: distclean-am |
937 | 971 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) |
938 | -rm -rf src/$(DEPDIR) src/core/$(DEPDIR) src/tinyxml/$(DEPDIR) | |
972 | -rm -rf src/$(DEPDIR) src/core/$(DEPDIR) src/formats/$(DEPDIR) src/tinyxml/$(DEPDIR) | |
939 | 973 | -rm -f Makefile |
940 | 974 | distclean-am: clean-am distclean-compile distclean-generic \ |
941 | 975 | distclean-tags |
985 | 1019 | maintainer-clean: maintainer-clean-am |
986 | 1020 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) |
987 | 1021 | -rm -rf $(top_srcdir)/autom4te.cache |
988 | -rm -rf src/$(DEPDIR) src/core/$(DEPDIR) src/tinyxml/$(DEPDIR) | |
1022 | -rm -rf src/$(DEPDIR) src/core/$(DEPDIR) src/formats/$(DEPDIR) src/tinyxml/$(DEPDIR) | |
989 | 1023 | -rm -f Makefile |
990 | 1024 | maintainer-clean-am: distclean-am maintainer-clean-generic |
991 | 1025 |
42 | 42 | |
43 | 43 | -WIDTHxHEIGHT, --viewport WIDTHxHEIGHT |
44 | 44 | Set the viewport size. If -f is also supplied, will attempt to set |
45 | the video mode to this also. | |
45 | the video mode to this also. Add ! to make the window non-resizable. | |
46 | 46 | |
47 | 47 | -f, --fullscreen |
48 | 48 | Fullscreen. |
88 | 88 | Elasticity of nodes. |
89 | 89 | |
90 | 90 | -b, --background-colour FFFFFF |
91 | Background colour in hex. | |
91 | Background colour in hex. | |
92 | 92 | |
93 | 93 | --background-image IMAGE |
94 | Set a background image. | |
94 | Set a background image. | |
95 | 95 | |
96 | 96 | --logo IMAGE |
97 | Logo to display in the foreground. | |
97 | Logo to display in the foreground. | |
98 | 98 | |
99 | 99 | --logo-offset XxY |
100 | Offset position of the logo. | |
100 | Offset position of the logo. | |
101 | 101 | |
102 | 102 | --title TITLE |
103 | Set a title. | |
103 | Set a title. | |
104 | 104 | |
105 | 105 | --font-size SIZE |
106 | Font size. | |
106 | Font size used by the date and title. | |
107 | 107 | |
108 | 108 | --font-colour FFFFFF |
109 | Font colour in hex. | |
109 | Font colour used by the date and title in hex. | |
110 | 110 | |
111 | 111 | --key |
112 | Show file extension key. | |
112 | Show file extension key. | |
113 | 113 | |
114 | 114 | --date-format FORMAT |
115 | 115 | Specify display date string (strftime format). |
128 | 128 | --follow-user USER |
129 | 129 | Have the camera automatically follow a particular user. |
130 | 130 | |
131 | --highlight-dirs | |
132 | Highlight the names of all directories. | |
133 | ||
131 | 134 | --highlight-user USER |
132 | 135 | Highlight the names of a particular user. |
133 | 136 | |
134 | 137 | --highlight-users |
135 | 138 | Highlight the names of all users. |
136 | 139 | |
137 | --highlight-dirs | |
138 | Highlight the names of all directories. | |
139 | ||
140 | 140 | --highlight-colour FFFFFF |
141 | Highlighted text colour in hex. | |
141 | Font colour for highlighted users in hex. | |
142 | ||
143 | --selection-colour FFFFFF | |
144 | Font colour for selected users and files. | |
145 | ||
146 | --dir-colour FFFFFF | |
147 | Font colour for directories. | |
142 | 148 | |
143 | 149 | --file-filter REGEX |
144 | 150 | Filter out any files matching a specified regular expression. |
171 | 177 | --no-vsync |
172 | 178 | Disable vsync. |
173 | 179 | |
174 | --bloom-multiplier FLOAT | |
180 | --bloom-multiplier FLOAT | |
175 | 181 | Adjust the amount of bloom. |
176 | 182 | |
177 | 183 | --bloom-intensity FLOAT |
191 | 197 | Max speed users can travel per second. |
192 | 198 | |
193 | 199 | --user-friction SECONDS |
194 | Time users come to a complete hault. | |
200 | Time users take to come to a halt. | |
195 | 201 | |
196 | 202 | --user-scale SCALE |
197 | 203 | Change scale of users. |
246 | 252 | file (see log commands or the custom log format), a Gource conf |
247 | 253 | file or '-' to read STDIN. |
248 | 254 | |
249 | If path is ommited, gource will attempt to read a log from the | |
255 | If path is omitted, gource will attempt to read a log from the | |
250 | 256 | current directory. |
251 | 257 | |
252 | 258 | Git, Bazaar, Mercurial and SVN Examples: |
253 | 259 | |
254 | View the log of the respository in the current path: | |
260 | View the log of the repository in the current path: | |
255 | 261 | |
256 | 262 | gource |
257 | 263 | |
313 | 319 | log entry read and is incremented according to the simulation speed |
314 | 320 | (--seconds-per-day). |
315 | 321 | |
316 | Pressing SPACE at any time will pause/unpause the simulation. While paused you | |
322 | Pressing SPACE at any time will pause/resume the simulation. While paused you | |
317 | 323 | may use the mouse to inspect the detail of individual files and users. |
318 | 324 | |
319 | 325 | TAB cycles through selecting the current visible users. |
335 | 341 | (+-) Adjust simulation speed. |
336 | 342 | (<>) Adjust time scale. |
337 | 343 | (TAB) Cycle through visible users |
344 | ||
345 | (Alt+Enter) Toggle Fullscreen | |
346 | ||
338 | 347 | (ESC) Quit |
339 | 348 | |
340 | 349 | 4. Copyright |
953 | 953 | m4_include([m4/ax_lang_compiler_ms.m4]) |
954 | 954 | m4_include([m4/ax_pthread.m4]) |
955 | 955 | m4_include([m4/freetype2.m4]) |
956 | m4_include([m4/m4_ax_boost_base.m4]) | |
957 | m4_include([m4/m4_ax_boost_filesystem.m4]) | |
958 | m4_include([m4/m4_ax_boost_system.m4]) | |
956 | 959 | m4_include([m4/sdl.m4]) |
0 | 0 | #! /bin/sh |
1 | 1 | # Guess values for system-dependent variables and create Makefiles. |
2 | # Generated by GNU Autoconf 2.68 for Gource 0.37. | |
2 | # Generated by GNU Autoconf 2.68 for Gource 0.38. | |
3 | 3 | # |
4 | 4 | # Report bugs to <acaudwell@gmail.com>. |
5 | 5 | # |
559 | 559 | # Identity of this package. |
560 | 560 | PACKAGE_NAME='Gource' |
561 | 561 | PACKAGE_TARNAME='gource' |
562 | PACKAGE_VERSION='0.37' | |
563 | PACKAGE_STRING='Gource 0.37' | |
562 | PACKAGE_VERSION='0.38' | |
563 | PACKAGE_STRING='Gource 0.38' | |
564 | 564 | PACKAGE_BUGREPORT='acaudwell@gmail.com' |
565 | 565 | PACKAGE_URL='' |
566 | 566 | |
610 | 610 | gourcefontdir |
611 | 611 | FONTDIR_FALSE |
612 | 612 | FONTDIR_TRUE |
613 | BOOST_FILESYSTEM_LIB | |
614 | BOOST_SYSTEM_LIB | |
615 | BOOST_LDFLAGS | |
616 | BOOST_CPPFLAGS | |
613 | 617 | FT2_LIBS |
614 | 618 | FT2_CFLAGS |
615 | 619 | FT2_CONFIG |
734 | 738 | with_ft_prefix |
735 | 739 | with_ft_exec_prefix |
736 | 740 | enable_freetypetest |
741 | with_boost | |
742 | with_boost_libdir | |
743 | with_boost_system | |
744 | with_boost_filesystem | |
737 | 745 | enable_ttf_font_dir |
738 | 746 | with_tinyxml |
739 | 747 | ' |
1293 | 1301 | # Omit some internal or obsolete options to make the list less imposing. |
1294 | 1302 | # This message is too long to be a string in the A/UX 3.1 sh. |
1295 | 1303 | cat <<_ACEOF |
1296 | \`configure' configures Gource 0.37 to adapt to many kinds of systems. | |
1304 | \`configure' configures Gource 0.38 to adapt to many kinds of systems. | |
1297 | 1305 | |
1298 | 1306 | Usage: $0 [OPTION]... [VAR=VALUE]... |
1299 | 1307 | |
1367 | 1375 | |
1368 | 1376 | if test -n "$ac_init_help"; then |
1369 | 1377 | case $ac_init_help in |
1370 | short | recursive ) echo "Configuration of Gource 0.37:";; | |
1378 | short | recursive ) echo "Configuration of Gource 0.38:";; | |
1371 | 1379 | esac |
1372 | 1380 | cat <<\_ACEOF |
1373 | 1381 | |
1392 | 1400 | --with-ft-prefix=PREFIX Prefix where FreeType is installed (optional) |
1393 | 1401 | --with-ft-exec-prefix=PREFIX |
1394 | 1402 | Exec prefix where FreeType is installed (optional) |
1403 | --with-boost[=ARG] use Boost library from a standard location | |
1404 | (ARG=yes), from the specified location (ARG=<path>), | |
1405 | or disable it (ARG=no) [ARG=yes] | |
1406 | --with-boost-libdir=LIB_DIR | |
1407 | Force given directory for boost libraries. Note that | |
1408 | this will override library path detection, so use | |
1409 | this parameter only if default library detection | |
1410 | fails and you know exactly where your boost | |
1411 | libraries are located. | |
1412 | --with-boost-system[=special-lib] | |
1413 | use the System library from boost - it is possible | |
1414 | to specify a certain library for the linker e.g. | |
1415 | --with-boost-system=boost_system-gcc-mt | |
1416 | --with-boost-filesystem[=special-lib] | |
1417 | use the Filesystem library from boost - it is | |
1418 | possible to specify a certain library for the linker | |
1419 | e.g. --with-boost-filesystem=boost_filesystem-gcc-mt | |
1395 | 1420 | --with-tinyxml Use system installed TinyXML library |
1396 | 1421 | |
1397 | 1422 | Some influential environment variables: |
1474 | 1499 | test -n "$ac_init_help" && exit $ac_status |
1475 | 1500 | if $ac_init_version; then |
1476 | 1501 | cat <<\_ACEOF |
1477 | Gource configure 0.37 | |
1502 | Gource configure 0.38 | |
1478 | 1503 | generated by GNU Autoconf 2.68 |
1479 | 1504 | |
1480 | 1505 | Copyright (C) 2010 Free Software Foundation, Inc. |
2128 | 2153 | This file contains any messages produced by compilers while |
2129 | 2154 | running configure, to aid debugging if configure makes a mistake. |
2130 | 2155 | |
2131 | It was created by Gource $as_me 0.37, which was | |
2156 | It was created by Gource $as_me 0.38, which was | |
2132 | 2157 | generated by GNU Autoconf 2.68. Invocation command line was |
2133 | 2158 | |
2134 | 2159 | $ $0 $@ |
2945 | 2970 | |
2946 | 2971 | # Define the identity of the package. |
2947 | 2972 | PACKAGE='gource' |
2948 | VERSION='0.37' | |
2973 | VERSION='0.38' | |
2949 | 2974 | |
2950 | 2975 | |
2951 | 2976 | cat >>confdefs.h <<_ACEOF |
6798 | 6823 | if test "x$ac_cv_lib_GLEW_glewInit" = xyes; then : |
6799 | 6824 | LIBS="$LIBS -lGLEW" |
6800 | 6825 | else |
6801 | as_fn_error $? "GLEW required. Please see INSTALL" "$LINENO" 5 | |
6802 | fi | |
6826 | as_fn_error $? "GLEW is required. Please see INSTALL" "$LINENO" 5 | |
6827 | fi | |
6828 | ||
6829 | ||
6830 | #BOOST | |
6831 | ||
6832 | ||
6833 | # Check whether --with-boost was given. | |
6834 | if test "${with_boost+set}" = set; then : | |
6835 | withval=$with_boost; | |
6836 | if test "$withval" = "no"; then | |
6837 | want_boost="no" | |
6838 | elif test "$withval" = "yes"; then | |
6839 | want_boost="yes" | |
6840 | ac_boost_path="" | |
6841 | else | |
6842 | want_boost="yes" | |
6843 | ac_boost_path="$withval" | |
6844 | fi | |
6845 | ||
6846 | else | |
6847 | want_boost="yes" | |
6848 | fi | |
6849 | ||
6850 | ||
6851 | ||
6852 | ||
6853 | # Check whether --with-boost-libdir was given. | |
6854 | if test "${with_boost_libdir+set}" = set; then : | |
6855 | withval=$with_boost_libdir; | |
6856 | if test -d "$withval" | |
6857 | then | |
6858 | ac_boost_lib_path="$withval" | |
6859 | else | |
6860 | as_fn_error $? "--with-boost-libdir expected directory name" "$LINENO" 5 | |
6861 | fi | |
6862 | ||
6863 | else | |
6864 | ac_boost_lib_path="" | |
6865 | ||
6866 | fi | |
6867 | ||
6868 | ||
6869 | if test "x$want_boost" = "xyes"; then | |
6870 | boost_lib_version_req=1.46 | |
6871 | boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([0-9]*\.[0-9]*\)'` | |
6872 | boost_lib_version_req_major=`expr $boost_lib_version_req : '\([0-9]*\)'` | |
6873 | boost_lib_version_req_minor=`expr $boost_lib_version_req : '[0-9]*\.\([0-9]*\)'` | |
6874 | boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[0-9]*\.[0-9]*\.\([0-9]*\)'` | |
6875 | if test "x$boost_lib_version_req_sub_minor" = "x" ; then | |
6876 | boost_lib_version_req_sub_minor="0" | |
6877 | fi | |
6878 | WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` | |
6879 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for boostlib >= $boost_lib_version_req" >&5 | |
6880 | $as_echo_n "checking for boostlib >= $boost_lib_version_req... " >&6; } | |
6881 | succeeded=no | |
6882 | ||
6883 | libsubdirs="lib" | |
6884 | ax_arch=`uname -m` | |
6885 | if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = s390x -o $ax_arch = sparc64; then | |
6886 | libsubdirs="lib64 lib lib64" | |
6887 | fi | |
6888 | ||
6889 | if test "$ac_boost_path" != ""; then | |
6890 | BOOST_CPPFLAGS="-I$ac_boost_path/include" | |
6891 | for ac_boost_path_tmp in $libsubdirs; do | |
6892 | if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then | |
6893 | BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" | |
6894 | break | |
6895 | fi | |
6896 | done | |
6897 | elif test "$cross_compiling" != yes; then | |
6898 | for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do | |
6899 | if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then | |
6900 | for libsubdir in $libsubdirs ; do | |
6901 | if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
6902 | done | |
6903 | BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" | |
6904 | BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" | |
6905 | break; | |
6906 | fi | |
6907 | done | |
6908 | fi | |
6909 | ||
6910 | if test "$ac_boost_lib_path" != ""; then | |
6911 | BOOST_LDFLAGS="-L$ac_boost_lib_path" | |
6912 | fi | |
6913 | ||
6914 | CPPFLAGS_SAVED="$CPPFLAGS" | |
6915 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
6916 | export CPPFLAGS | |
6917 | ||
6918 | LDFLAGS_SAVED="$LDFLAGS" | |
6919 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
6920 | export LDFLAGS | |
6921 | ||
6922 | ||
6923 | ac_ext=cpp | |
6924 | ac_cpp='$CXXCPP $CPPFLAGS' | |
6925 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
6926 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
6927 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
6928 | ||
6929 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
6930 | /* end confdefs.h. */ | |
6931 | ||
6932 | #include <boost/version.hpp> | |
6933 | ||
6934 | int | |
6935 | main () | |
6936 | { | |
6937 | ||
6938 | #if BOOST_VERSION >= $WANT_BOOST_VERSION | |
6939 | // Everything is okay | |
6940 | #else | |
6941 | # error Boost version is too old | |
6942 | #endif | |
6943 | ||
6944 | ; | |
6945 | return 0; | |
6946 | } | |
6947 | _ACEOF | |
6948 | if ac_fn_cxx_try_compile "$LINENO"; then : | |
6949 | ||
6950 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
6951 | $as_echo "yes" >&6; } | |
6952 | succeeded=yes | |
6953 | found_system=yes | |
6954 | ||
6955 | fi | |
6956 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
6957 | ac_ext=cpp | |
6958 | ac_cpp='$CXXCPP $CPPFLAGS' | |
6959 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
6960 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
6961 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
6962 | ||
6963 | ||
6964 | ||
6965 | ||
6966 | if test "x$succeeded" != "xyes"; then | |
6967 | _version=0 | |
6968 | if test "$ac_boost_path" != ""; then | |
6969 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then | |
6970 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do | |
6971 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` | |
6972 | V_CHECK=`expr $_version_tmp \> $_version` | |
6973 | if test "$V_CHECK" = "1" ; then | |
6974 | _version=$_version_tmp | |
6975 | fi | |
6976 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` | |
6977 | BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" | |
6978 | done | |
6979 | fi | |
6980 | else | |
6981 | if test "$cross_compiling" != yes; then | |
6982 | for ac_boost_path in /usr /usr/local /opt /opt/local ; do | |
6983 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then | |
6984 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do | |
6985 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` | |
6986 | V_CHECK=`expr $_version_tmp \> $_version` | |
6987 | if test "$V_CHECK" = "1" ; then | |
6988 | _version=$_version_tmp | |
6989 | best_path=$ac_boost_path | |
6990 | fi | |
6991 | done | |
6992 | fi | |
6993 | done | |
6994 | ||
6995 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` | |
6996 | BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" | |
6997 | if test "$ac_boost_lib_path" = ""; then | |
6998 | for libsubdir in $libsubdirs ; do | |
6999 | if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
7000 | done | |
7001 | BOOST_LDFLAGS="-L$best_path/$libsubdir" | |
7002 | fi | |
7003 | fi | |
7004 | ||
7005 | if test "x$BOOST_ROOT" != "x"; then | |
7006 | for libsubdir in $libsubdirs ; do | |
7007 | if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
7008 | done | |
7009 | if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then | |
7010 | version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` | |
7011 | stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` | |
7012 | stage_version_shorten=`expr $stage_version : '\([0-9]*\.[0-9]*\)'` | |
7013 | V_CHECK=`expr $stage_version_shorten \>\= $_version` | |
7014 | if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then | |
7015 | { $as_echo "$as_me:${as_lineno-$LINENO}: We will use a staged boost library from $BOOST_ROOT" >&5 | |
7016 | $as_echo "$as_me: We will use a staged boost library from $BOOST_ROOT" >&6;} | |
7017 | BOOST_CPPFLAGS="-I$BOOST_ROOT" | |
7018 | BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" | |
7019 | fi | |
7020 | fi | |
7021 | fi | |
7022 | fi | |
7023 | ||
7024 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
7025 | export CPPFLAGS | |
7026 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
7027 | export LDFLAGS | |
7028 | ||
7029 | ac_ext=cpp | |
7030 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7031 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7032 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7033 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7034 | ||
7035 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7036 | /* end confdefs.h. */ | |
7037 | ||
7038 | #include <boost/version.hpp> | |
7039 | ||
7040 | int | |
7041 | main () | |
7042 | { | |
7043 | ||
7044 | #if BOOST_VERSION >= $WANT_BOOST_VERSION | |
7045 | // Everything is okay | |
7046 | #else | |
7047 | # error Boost version is too old | |
7048 | #endif | |
7049 | ||
7050 | ; | |
7051 | return 0; | |
7052 | } | |
7053 | _ACEOF | |
7054 | if ac_fn_cxx_try_compile "$LINENO"; then : | |
7055 | ||
7056 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 | |
7057 | $as_echo "yes" >&6; } | |
7058 | succeeded=yes | |
7059 | found_system=yes | |
7060 | ||
7061 | fi | |
7062 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
7063 | ac_ext=cpp | |
7064 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7065 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7066 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7067 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7068 | ||
7069 | fi | |
7070 | ||
7071 | if test "$succeeded" != "yes" ; then | |
7072 | if test "$_version" = "0" ; then | |
7073 | { $as_echo "$as_me:${as_lineno-$LINENO}: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation." >&5 | |
7074 | $as_echo "$as_me: We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation." >&6;} | |
7075 | else | |
7076 | { $as_echo "$as_me:${as_lineno-$LINENO}: Your boost libraries seems to old (version $_version)." >&5 | |
7077 | $as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;} | |
7078 | fi | |
7079 | # execute ACTION-IF-NOT-FOUND (if present): | |
7080 | as_fn_error $? "Boost Filesystem >= 1.46 is required. Please see INSTALL" "$LINENO" 5 | |
7081 | else | |
7082 | ||
7083 | ||
7084 | ||
7085 | $as_echo "#define HAVE_BOOST /**/" >>confdefs.h | |
7086 | ||
7087 | # execute ACTION-IF-FOUND (if present): | |
7088 | : | |
7089 | fi | |
7090 | ||
7091 | CPPFLAGS="$CPPFLAGS_SAVED" | |
7092 | LDFLAGS="$LDFLAGS_SAVED" | |
7093 | fi | |
7094 | ||
7095 | ||
7096 | ||
7097 | ||
7098 | # Check whether --with-boost-system was given. | |
7099 | if test "${with_boost_system+set}" = set; then : | |
7100 | withval=$with_boost_system; | |
7101 | if test "$withval" = "no"; then | |
7102 | want_boost="no" | |
7103 | elif test "$withval" = "yes"; then | |
7104 | want_boost="yes" | |
7105 | ax_boost_user_system_lib="" | |
7106 | else | |
7107 | want_boost="yes" | |
7108 | ax_boost_user_system_lib="$withval" | |
7109 | fi | |
7110 | ||
7111 | else | |
7112 | want_boost="yes" | |
7113 | ||
7114 | fi | |
7115 | ||
7116 | ||
7117 | if test "x$want_boost" = "xyes"; then | |
7118 | ||
7119 | ||
7120 | CPPFLAGS_SAVED="$CPPFLAGS" | |
7121 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
7122 | export CPPFLAGS | |
7123 | ||
7124 | LDFLAGS_SAVED="$LDFLAGS" | |
7125 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
7126 | export LDFLAGS | |
7127 | ||
7128 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::System library is available" >&5 | |
7129 | $as_echo_n "checking whether the Boost::System library is available... " >&6; } | |
7130 | if ${ax_cv_boost_system+:} false; then : | |
7131 | $as_echo_n "(cached) " >&6 | |
7132 | else | |
7133 | ac_ext=cpp | |
7134 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7135 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7136 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7137 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7138 | ||
7139 | CXXFLAGS_SAVE=$CXXFLAGS | |
7140 | ||
7141 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7142 | /* end confdefs.h. */ | |
7143 | #include <boost/system/error_code.hpp> | |
7144 | int | |
7145 | main () | |
7146 | { | |
7147 | boost::system::system_category | |
7148 | ; | |
7149 | return 0; | |
7150 | } | |
7151 | _ACEOF | |
7152 | if ac_fn_cxx_try_compile "$LINENO"; then : | |
7153 | ax_cv_boost_system=yes | |
7154 | else | |
7155 | ax_cv_boost_system=no | |
7156 | fi | |
7157 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
7158 | CXXFLAGS=$CXXFLAGS_SAVE | |
7159 | ac_ext=cpp | |
7160 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7161 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7162 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7163 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7164 | ||
7165 | ||
7166 | fi | |
7167 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_system" >&5 | |
7168 | $as_echo "$ax_cv_boost_system" >&6; } | |
7169 | if test "x$ax_cv_boost_system" = "xyes"; then | |
7170 | ||
7171 | ||
7172 | ||
7173 | $as_echo "#define HAVE_BOOST_SYSTEM /**/" >>confdefs.h | |
7174 | ||
7175 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` | |
7176 | ||
7177 | LDFLAGS_SAVE=$LDFLAGS | |
7178 | if test "x$ax_boost_user_system_lib" = "x"; then | |
7179 | for libextension in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.a*$;\1;'` ; do | |
7180 | ax_lib=${libextension} | |
7181 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7182 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7183 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7184 | if eval \${$as_ac_Lib+:} false; then : | |
7185 | $as_echo_n "(cached) " >&6 | |
7186 | else | |
7187 | ac_check_lib_save_LIBS=$LIBS | |
7188 | LIBS="-l$ax_lib $LIBS" | |
7189 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7190 | /* end confdefs.h. */ | |
7191 | ||
7192 | /* Override any GCC internal prototype to avoid an error. | |
7193 | Use char because int might match the return type of a GCC | |
7194 | builtin and then its argument prototype would still apply. */ | |
7195 | #ifdef __cplusplus | |
7196 | extern "C" | |
7197 | #endif | |
7198 | char exit (); | |
7199 | int | |
7200 | main () | |
7201 | { | |
7202 | return exit (); | |
7203 | ; | |
7204 | return 0; | |
7205 | } | |
7206 | _ACEOF | |
7207 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7208 | eval "$as_ac_Lib=yes" | |
7209 | else | |
7210 | eval "$as_ac_Lib=no" | |
7211 | fi | |
7212 | rm -f core conftest.err conftest.$ac_objext \ | |
7213 | conftest$ac_exeext conftest.$ac_ext | |
7214 | LIBS=$ac_check_lib_save_LIBS | |
7215 | fi | |
7216 | eval ac_res=\$$as_ac_Lib | |
7217 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7218 | $as_echo "$ac_res" >&6; } | |
7219 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7220 | BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break | |
7221 | else | |
7222 | link_system="no" | |
7223 | fi | |
7224 | ||
7225 | done | |
7226 | if test "x$link_system" != "xyes"; then | |
7227 | for libextension in `ls $BOOSTLIBDIR/boost_system*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_system.*\)\.dll.*$;\1;' -e 's;^\(boost_system.*\)\.a*$;\1;'` ; do | |
7228 | ax_lib=${libextension} | |
7229 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7230 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7231 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7232 | if eval \${$as_ac_Lib+:} false; then : | |
7233 | $as_echo_n "(cached) " >&6 | |
7234 | else | |
7235 | ac_check_lib_save_LIBS=$LIBS | |
7236 | LIBS="-l$ax_lib $LIBS" | |
7237 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7238 | /* end confdefs.h. */ | |
7239 | ||
7240 | /* Override any GCC internal prototype to avoid an error. | |
7241 | Use char because int might match the return type of a GCC | |
7242 | builtin and then its argument prototype would still apply. */ | |
7243 | #ifdef __cplusplus | |
7244 | extern "C" | |
7245 | #endif | |
7246 | char exit (); | |
7247 | int | |
7248 | main () | |
7249 | { | |
7250 | return exit (); | |
7251 | ; | |
7252 | return 0; | |
7253 | } | |
7254 | _ACEOF | |
7255 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7256 | eval "$as_ac_Lib=yes" | |
7257 | else | |
7258 | eval "$as_ac_Lib=no" | |
7259 | fi | |
7260 | rm -f core conftest.err conftest.$ac_objext \ | |
7261 | conftest$ac_exeext conftest.$ac_ext | |
7262 | LIBS=$ac_check_lib_save_LIBS | |
7263 | fi | |
7264 | eval ac_res=\$$as_ac_Lib | |
7265 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7266 | $as_echo "$ac_res" >&6; } | |
7267 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7268 | BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break | |
7269 | else | |
7270 | link_system="no" | |
7271 | fi | |
7272 | ||
7273 | done | |
7274 | fi | |
7275 | ||
7276 | else | |
7277 | for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do | |
7278 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7279 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7280 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7281 | if eval \${$as_ac_Lib+:} false; then : | |
7282 | $as_echo_n "(cached) " >&6 | |
7283 | else | |
7284 | ac_check_lib_save_LIBS=$LIBS | |
7285 | LIBS="-l$ax_lib $LIBS" | |
7286 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7287 | /* end confdefs.h. */ | |
7288 | ||
7289 | /* Override any GCC internal prototype to avoid an error. | |
7290 | Use char because int might match the return type of a GCC | |
7291 | builtin and then its argument prototype would still apply. */ | |
7292 | #ifdef __cplusplus | |
7293 | extern "C" | |
7294 | #endif | |
7295 | char exit (); | |
7296 | int | |
7297 | main () | |
7298 | { | |
7299 | return exit (); | |
7300 | ; | |
7301 | return 0; | |
7302 | } | |
7303 | _ACEOF | |
7304 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7305 | eval "$as_ac_Lib=yes" | |
7306 | else | |
7307 | eval "$as_ac_Lib=no" | |
7308 | fi | |
7309 | rm -f core conftest.err conftest.$ac_objext \ | |
7310 | conftest$ac_exeext conftest.$ac_ext | |
7311 | LIBS=$ac_check_lib_save_LIBS | |
7312 | fi | |
7313 | eval ac_res=\$$as_ac_Lib | |
7314 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7315 | $as_echo "$ac_res" >&6; } | |
7316 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7317 | BOOST_SYSTEM_LIB="-l$ax_lib"; link_system="yes"; break | |
7318 | else | |
7319 | link_system="no" | |
7320 | fi | |
7321 | ||
7322 | done | |
7323 | ||
7324 | fi | |
7325 | if test "x$ax_lib" = "x"; then | |
7326 | as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 | |
7327 | fi | |
7328 | if test "x$link_system" = "xno"; then | |
7329 | as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 | |
7330 | fi | |
7331 | fi | |
7332 | ||
7333 | CPPFLAGS="$CPPFLAGS_SAVED" | |
7334 | LDFLAGS="$LDFLAGS_SAVED" | |
7335 | fi | |
7336 | ||
7337 | ||
7338 | ||
7339 | # Check whether --with-boost-filesystem was given. | |
7340 | if test "${with_boost_filesystem+set}" = set; then : | |
7341 | withval=$with_boost_filesystem; | |
7342 | if test "$withval" = "no"; then | |
7343 | want_boost="no" | |
7344 | elif test "$withval" = "yes"; then | |
7345 | want_boost="yes" | |
7346 | ax_boost_user_filesystem_lib="" | |
7347 | else | |
7348 | want_boost="yes" | |
7349 | ax_boost_user_filesystem_lib="$withval" | |
7350 | fi | |
7351 | ||
7352 | else | |
7353 | want_boost="yes" | |
7354 | ||
7355 | fi | |
7356 | ||
7357 | ||
7358 | if test "x$want_boost" = "xyes"; then | |
7359 | ||
7360 | CPPFLAGS_SAVED="$CPPFLAGS" | |
7361 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
7362 | export CPPFLAGS | |
7363 | ||
7364 | LDFLAGS_SAVED="$LDFLAGS" | |
7365 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
7366 | export LDFLAGS | |
7367 | ||
7368 | LIBS_SAVED=$LIBS | |
7369 | LIBS="$LIBS $BOOST_SYSTEM_LIB" | |
7370 | export LIBS | |
7371 | ||
7372 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the Boost::Filesystem library is available" >&5 | |
7373 | $as_echo_n "checking whether the Boost::Filesystem library is available... " >&6; } | |
7374 | if ${ax_cv_boost_filesystem+:} false; then : | |
7375 | $as_echo_n "(cached) " >&6 | |
7376 | else | |
7377 | ac_ext=cpp | |
7378 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7379 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7380 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7381 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7382 | ||
7383 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7384 | /* end confdefs.h. */ | |
7385 | #include <boost/filesystem/path.hpp> | |
7386 | int | |
7387 | main () | |
7388 | { | |
7389 | using namespace boost::filesystem; | |
7390 | path my_path( "foo/bar/data.txt" ); | |
7391 | return 0; | |
7392 | ; | |
7393 | return 0; | |
7394 | } | |
7395 | _ACEOF | |
7396 | if ac_fn_cxx_try_compile "$LINENO"; then : | |
7397 | ax_cv_boost_filesystem=yes | |
7398 | else | |
7399 | ax_cv_boost_filesystem=no | |
7400 | fi | |
7401 | rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext | |
7402 | ac_ext=cpp | |
7403 | ac_cpp='$CXXCPP $CPPFLAGS' | |
7404 | ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' | |
7405 | ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' | |
7406 | ac_compiler_gnu=$ac_cv_cxx_compiler_gnu | |
7407 | ||
7408 | ||
7409 | fi | |
7410 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_boost_filesystem" >&5 | |
7411 | $as_echo "$ax_cv_boost_filesystem" >&6; } | |
7412 | if test "x$ax_cv_boost_filesystem" = "xyes"; then | |
7413 | ||
7414 | $as_echo "#define HAVE_BOOST_FILESYSTEM /**/" >>confdefs.h | |
7415 | ||
7416 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/[^\/]*//'` | |
7417 | if test "x$ax_boost_user_filesystem_lib" = "x"; then | |
7418 | for libextension in `ls $BOOSTLIBDIR/libboost_filesystem*.so* $BOOSTLIBDIR/libboost_filesystem*.dylib* $BOOSTLIBDIR/libboost_filesystem*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_filesystem.*\)\.so.*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.a*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.dylib$;\1;'` ; do | |
7419 | ax_lib=${libextension} | |
7420 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7421 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7422 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7423 | if eval \${$as_ac_Lib+:} false; then : | |
7424 | $as_echo_n "(cached) " >&6 | |
7425 | else | |
7426 | ac_check_lib_save_LIBS=$LIBS | |
7427 | LIBS="-l$ax_lib $LIBS" | |
7428 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7429 | /* end confdefs.h. */ | |
7430 | ||
7431 | /* Override any GCC internal prototype to avoid an error. | |
7432 | Use char because int might match the return type of a GCC | |
7433 | builtin and then its argument prototype would still apply. */ | |
7434 | #ifdef __cplusplus | |
7435 | extern "C" | |
7436 | #endif | |
7437 | char exit (); | |
7438 | int | |
7439 | main () | |
7440 | { | |
7441 | return exit (); | |
7442 | ; | |
7443 | return 0; | |
7444 | } | |
7445 | _ACEOF | |
7446 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7447 | eval "$as_ac_Lib=yes" | |
7448 | else | |
7449 | eval "$as_ac_Lib=no" | |
7450 | fi | |
7451 | rm -f core conftest.err conftest.$ac_objext \ | |
7452 | conftest$ac_exeext conftest.$ac_ext | |
7453 | LIBS=$ac_check_lib_save_LIBS | |
7454 | fi | |
7455 | eval ac_res=\$$as_ac_Lib | |
7456 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7457 | $as_echo "$ac_res" >&6; } | |
7458 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7459 | BOOST_FILESYSTEM_LIB="-l$ax_lib"; link_filesystem="yes"; break | |
7460 | else | |
7461 | link_filesystem="no" | |
7462 | fi | |
7463 | ||
7464 | done | |
7465 | if test "x$link_filesystem" != "xyes"; then | |
7466 | for libextension in `ls $BOOSTLIBDIR/boost_filesystem*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_filesystem.*\)\.dll.*$;\1;' -e 's;^\(boost_filesystem.*\)\.a*$;\1;'` ; do | |
7467 | ax_lib=${libextension} | |
7468 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7469 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7470 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7471 | if eval \${$as_ac_Lib+:} false; then : | |
7472 | $as_echo_n "(cached) " >&6 | |
7473 | else | |
7474 | ac_check_lib_save_LIBS=$LIBS | |
7475 | LIBS="-l$ax_lib $LIBS" | |
7476 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7477 | /* end confdefs.h. */ | |
7478 | ||
7479 | /* Override any GCC internal prototype to avoid an error. | |
7480 | Use char because int might match the return type of a GCC | |
7481 | builtin and then its argument prototype would still apply. */ | |
7482 | #ifdef __cplusplus | |
7483 | extern "C" | |
7484 | #endif | |
7485 | char exit (); | |
7486 | int | |
7487 | main () | |
7488 | { | |
7489 | return exit (); | |
7490 | ; | |
7491 | return 0; | |
7492 | } | |
7493 | _ACEOF | |
7494 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7495 | eval "$as_ac_Lib=yes" | |
7496 | else | |
7497 | eval "$as_ac_Lib=no" | |
7498 | fi | |
7499 | rm -f core conftest.err conftest.$ac_objext \ | |
7500 | conftest$ac_exeext conftest.$ac_ext | |
7501 | LIBS=$ac_check_lib_save_LIBS | |
7502 | fi | |
7503 | eval ac_res=\$$as_ac_Lib | |
7504 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7505 | $as_echo "$ac_res" >&6; } | |
7506 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7507 | BOOST_FILESYSTEM_LIB="-l$ax_lib"; link_filesystem="yes"; break | |
7508 | else | |
7509 | link_filesystem="no" | |
7510 | fi | |
7511 | ||
7512 | done | |
7513 | fi | |
7514 | else | |
7515 | for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do | |
7516 | as_ac_Lib=`$as_echo "ac_cv_lib_$ax_lib''_exit" | $as_tr_sh` | |
7517 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking for exit in -l$ax_lib" >&5 | |
7518 | $as_echo_n "checking for exit in -l$ax_lib... " >&6; } | |
7519 | if eval \${$as_ac_Lib+:} false; then : | |
7520 | $as_echo_n "(cached) " >&6 | |
7521 | else | |
7522 | ac_check_lib_save_LIBS=$LIBS | |
7523 | LIBS="-l$ax_lib $LIBS" | |
7524 | cat confdefs.h - <<_ACEOF >conftest.$ac_ext | |
7525 | /* end confdefs.h. */ | |
7526 | ||
7527 | /* Override any GCC internal prototype to avoid an error. | |
7528 | Use char because int might match the return type of a GCC | |
7529 | builtin and then its argument prototype would still apply. */ | |
7530 | #ifdef __cplusplus | |
7531 | extern "C" | |
7532 | #endif | |
7533 | char exit (); | |
7534 | int | |
7535 | main () | |
7536 | { | |
7537 | return exit (); | |
7538 | ; | |
7539 | return 0; | |
7540 | } | |
7541 | _ACEOF | |
7542 | if ac_fn_cxx_try_link "$LINENO"; then : | |
7543 | eval "$as_ac_Lib=yes" | |
7544 | else | |
7545 | eval "$as_ac_Lib=no" | |
7546 | fi | |
7547 | rm -f core conftest.err conftest.$ac_objext \ | |
7548 | conftest$ac_exeext conftest.$ac_ext | |
7549 | LIBS=$ac_check_lib_save_LIBS | |
7550 | fi | |
7551 | eval ac_res=\$$as_ac_Lib | |
7552 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 | |
7553 | $as_echo "$ac_res" >&6; } | |
7554 | if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : | |
7555 | BOOST_FILESYSTEM_LIB="-l$ax_lib"; link_filesystem="yes"; break | |
7556 | else | |
7557 | link_filesystem="no" | |
7558 | fi | |
7559 | ||
7560 | done | |
7561 | ||
7562 | fi | |
7563 | if test "x$ax_lib" = "x"; then | |
7564 | as_fn_error $? "Could not find a version of the library!" "$LINENO" 5 | |
7565 | fi | |
7566 | if test "x$link_filesystem" != "xyes"; then | |
7567 | as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5 | |
7568 | fi | |
7569 | fi | |
7570 | ||
7571 | CPPFLAGS="$CPPFLAGS_SAVED" | |
7572 | LDFLAGS="$LDFLAGS_SAVED" | |
7573 | LIBS="$LIBS_SAVED" | |
7574 | fi | |
7575 | ||
7576 | ||
7577 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
7578 | LIBS="$LIBS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" | |
7579 | ||
7580 | #GLM | |
7581 | ac_fn_cxx_check_header_mongrel "$LINENO" "glm/glm.hpp" "ac_cv_header_glm_glm_hpp" "$ac_includes_default" | |
7582 | if test "x$ac_cv_header_glm_glm_hpp" = xyes; then : | |
7583 | ||
7584 | else | |
7585 | as_fn_error $? "GLM headers are required. Please see INSTALL" "$LINENO" 5 | |
7586 | fi | |
7587 | ||
6803 | 7588 | |
6804 | 7589 | |
6805 | 7590 | #Check for required headers |
6807 | 7592 | if test "x$ac_cv_header_SDL_h" = xyes; then : |
6808 | 7593 | |
6809 | 7594 | else |
6810 | as_fn_error $? "SDL.h is required. Please see INSTALL" "$LINENO" 5 | |
7595 | as_fn_error $? "SDL headers are required. Please see INSTALL" "$LINENO" 5 | |
6811 | 7596 | fi |
6812 | 7597 | |
6813 | 7598 | |
6815 | 7600 | if test "x$ac_cv_header_SDL_image_h" = xyes; then : |
6816 | 7601 | |
6817 | 7602 | else |
6818 | as_fn_error $? "SDL_image.h is required. Please see INSTALL" "$LINENO" 5 | |
7603 | as_fn_error $? "SDL_image headers are required. Please see INSTALL" "$LINENO" 5 | |
6819 | 7604 | fi |
6820 | 7605 | |
6821 | 7606 | |
6823 | 7608 | if test "x$ac_cv_header_pcre_h" = xyes; then : |
6824 | 7609 | |
6825 | 7610 | else |
6826 | as_fn_error $? "pcre.h is required. Please see INSTALL" "$LINENO" 5 | |
7611 | as_fn_error $? "PCRE headers are required. Please see INSTALL" "$LINENO" 5 | |
6827 | 7612 | fi |
6828 | 7613 | |
6829 | 7614 | |
6831 | 7616 | if test "x$ac_cv_header_GL_glew_h" = xyes; then : |
6832 | 7617 | |
6833 | 7618 | else |
6834 | as_fn_error $? "glew.h is required. Please see INSTALL" "$LINENO" 5 | |
7619 | as_fn_error $? "GLEW headers are required. Please see INSTALL" "$LINENO" 5 | |
6835 | 7620 | fi |
6836 | 7621 | |
6837 | 7622 | |
7500 | 8285 | # report actual input values of CONFIG_FILES etc. instead of their |
7501 | 8286 | # values after options handling. |
7502 | 8287 | ac_log=" |
7503 | This file was extended by Gource $as_me 0.37, which was | |
8288 | This file was extended by Gource $as_me 0.38, which was | |
7504 | 8289 | generated by GNU Autoconf 2.68. Invocation command line was |
7505 | 8290 | |
7506 | 8291 | CONFIG_FILES = $CONFIG_FILES |
7557 | 8342 | cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 |
7558 | 8343 | ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" |
7559 | 8344 | ac_cs_version="\\ |
7560 | Gource config.status 0.37 | |
8345 | Gource config.status 0.38 | |
7561 | 8346 | configured by $0, generated by GNU Autoconf 2.68, |
7562 | 8347 | with options \\"\$ac_cs_config\\" |
7563 | 8348 |
2 | 2 | |
3 | 3 | AC_PREREQ(2.61) |
4 | 4 | |
5 | AC_INIT(Gource, 0.37, [acaudwell@gmail.com]) | |
5 | AC_INIT(Gource, 0.38, [acaudwell@gmail.com]) | |
6 | 6 | AC_CONFIG_SRCDIR([src/main.h]) |
7 | 7 | |
8 | 8 | AM_INIT_AUTOMAKE([dist-bzip2 foreign subdir-objects]) |
63 | 63 | AC_CHECK_LIB([pcre], [pcre_compile],, AC_MSG_ERROR(PCRE is required. Please see INSTALL)) |
64 | 64 | |
65 | 65 | #GLEW |
66 | AC_CHECK_LIB(GLEW, glewInit, LIBS="$LIBS -lGLEW", AC_MSG_ERROR([GLEW required. Please see INSTALL])) | |
66 | AC_CHECK_LIB(GLEW, glewInit, LIBS="$LIBS -lGLEW", AC_MSG_ERROR([GLEW is required. Please see INSTALL])) | |
67 | ||
68 | #BOOST | |
69 | AX_BOOST_BASE([1.46], , AC_MSG_ERROR(Boost Filesystem >= 1.46 is required. Please see INSTALL)) | |
70 | AX_BOOST_SYSTEM | |
71 | AX_BOOST_FILESYSTEM | |
72 | ||
73 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
74 | LIBS="$LIBS $BOOST_SYSTEM_LIB $BOOST_FILESYSTEM_LIB" | |
75 | ||
76 | #GLM | |
77 | AC_CHECK_HEADER([glm/glm.hpp],, AC_MSG_ERROR(GLM headers are required. Please see INSTALL)) | |
67 | 78 | |
68 | 79 | #Check for required headers |
69 | AC_CHECK_HEADER([SDL.h],, AC_MSG_ERROR(SDL.h is required. Please see INSTALL)) | |
70 | AC_CHECK_HEADER([SDL_image.h],, AC_MSG_ERROR(SDL_image.h is required. Please see INSTALL)) | |
71 | AC_CHECK_HEADER([pcre.h],, AC_MSG_ERROR(pcre.h is required. Please see INSTALL)) | |
72 | AC_CHECK_HEADER([GL/glew.h],, AC_MSG_ERROR(glew.h is required. Please see INSTALL)) | |
80 | AC_CHECK_HEADER([SDL.h],, AC_MSG_ERROR(SDL headers are required. Please see INSTALL)) | |
81 | AC_CHECK_HEADER([SDL_image.h],, AC_MSG_ERROR(SDL_image headers are required. Please see INSTALL)) | |
82 | AC_CHECK_HEADER([pcre.h],, AC_MSG_ERROR(PCRE headers are required. Please see INSTALL)) | |
83 | AC_CHECK_HEADER([GL/glew.h],, AC_MSG_ERROR(GLEW headers are required. Please see INSTALL)) | |
73 | 84 | |
74 | 85 | #see if ttf-font-dir option is enabled |
75 | 86 | AC_ARG_ENABLE(ttf-font-dir,[AS_HELP_STRING([--enable-ttf-font-dir=DIR],[directory containing GNU FreeFont TTF fonts])],[gourcefontdir="$enableval"],[gourcefontdir=""]) |
Binary diff not shown
Binary diff not shown
62 | 62 | |
63 | 63 | Free UCS scalable fonts is free software; you can redistribute it and/or |
64 | 64 | modify it under the terms of the GNU General Public License as published |
65 | by the Free Software Foundation; either version 2 of the License, or | |
65 | by the Free Software Foundation; either version 3 of the License, or | |
66 | 66 | (at your option) any later version. |
67 | 67 | |
68 | 68 | The fonts are distributed in the hope that they will be useful, but |
104 | 104 | Steve White <stevan.white@googlemail.com> |
105 | 105 | |
106 | 106 | Free UCS scalable fonts: http://savannah.gnu.org/projects/freefont/ |
107 | $Id: README,v 1.6 2008/12/25 12:51:41 Stevan_White Exp $ | |
107 | $Id: README,v 1.7 2009/01/13 08:43:23 Stevan_White Exp $ |
16 | 16 | Help ('\fB-H\fR' for extended help). |
17 | 17 | .TP |
18 | 18 | \fB\-WIDTHxHEIGHT, \-\-viewport WIDTHxHEIGHT\fR |
19 | Set the viewport size. If \-f is also supplied, will attempt to set the video mode to this also. | |
19 | Set the viewport size. If \-f is also supplied, will attempt to set the video mode to this also. Add ! to make the window non-resizable. | |
20 | 20 | .TP |
21 | 21 | \fB\-f\fR |
22 | 22 | Fullscreen |
70 | 70 | Set a title |
71 | 71 | .TP |
72 | 72 | \fB\-\-font\-size SIZE\fR |
73 | Font size. | |
73 | Font size used by the date and title. | |
74 | 74 | .TP |
75 | 75 | \fB\-\-font\-colour FFFFFF\fR |
76 | Font colour in hex. | |
76 | Font colour used by the date and title in hex. | |
77 | 77 | .TP |
78 | 78 | \fB\-\-key\fR |
79 | 79 | Show file extension key. |
99 | 99 | \fB\-\-follow\-user USER\fR |
100 | 100 | Have the camera automatically follow a particular user. |
101 | 101 | .TP |
102 | \fB\-\-highlight\-dirs\fR | |
103 | Highlight the names of all directories. | |
104 | .TP | |
102 | 105 | \fB\-\-highlight\-user USER\fR |
103 | 106 | Highlight the names of a particular user. |
104 | 107 | .TP |
105 | 108 | \fB\-\-highlight\-users\fR |
106 | 109 | Highlight the names of all users. |
107 | 110 | .TP |
108 | \fB\-\-highlight\-dirs\fR | |
109 | Highlight the names of all directories. | |
110 | .TP | |
111 | 111 | \fB\-\-highlight\-colour FFFFFF\fR |
112 | Highlighted text colour in hex. | |
112 | Font colour for highlighted users in hex. | |
113 | .TP | |
114 | \fB\-\-selection\-colour FFFFFF\fR | |
115 | Font colour for selected users and files. | |
116 | .TP | |
117 | \fB\-\-dir\-colour FFFFFF\fR | |
118 | Font colour for directories. | |
113 | 119 | .TP |
114 | 120 | \fB\-\-file\-extensions\fR |
115 | 121 | Show filename extensions only. |
157 | 163 | Max speed users can travel per second. |
158 | 164 | .TP |
159 | 165 | \fB\-\-user\-friction SECONDS\fR |
160 | Time users come to a complete hault. | |
166 | Time users take to come to a halt. | |
161 | 167 | .TP |
162 | 168 | \fB\-\-user\-scale SCALE\fR |
163 | 169 | Change scale of users. |
212 | 218 | \fBpath\fR |
213 | 219 | Either a supported version control directory, a pre-generated log file (see log commands or the custom log format), a Gource conf file or '-' to read STDIN. |
214 | 220 | |
215 | If path is ommited, gource will attempt to read a log from the current directory. | |
221 | If path is omitted, gource will attempt to read a log from the current directory. | |
216 | 222 | |
217 | 223 | .SH GIT, BAZAAR, MERCURIAL AND SVN EXAMPLES |
218 | 224 | |
219 | View the log of the respository in the current path: | |
225 | View the log of the repository in the current path: | |
220 | 226 | |
221 | 227 | .ti 10 |
222 | 228 | \fIgource\fR |
285 | 291 | .SH INTERFACE |
286 | 292 | The time shown in the top left of the screen is set initially from the first log entry read and is incremented according to the simulation speed (\-\-seconds\-per\-day). |
287 | 293 | |
288 | Pressing SPACE at any time will pause/unpause the simulation. While paused you may use the mouse to inspect the detail of individual files and users. | |
294 | Pressing SPACE at any time will pause/resume the simulation. While paused you may use the mouse to inspect the detail of individual files and users. | |
289 | 295 | |
290 | 296 | TAB cycles through selecting the current visible users. |
291 | 297 |
8 | 8 | |
9 | 9 | float combined_alpha = 1.0 - (1.0-shadow_alpha)*(1.0-colour_alpha); |
10 | 10 | |
11 | gl_FragColor = gl_Color * vec4(vec3(colour_alpha / combined_alpha), combined_alpha); | |
11 | if(combined_alpha > 0.0) colour_alpha /= combined_alpha; | |
12 | ||
13 | gl_FragColor = gl_Color * vec4(vec3(colour_alpha), combined_alpha); | |
12 | 14 | } |
Binary diff not shown
31 | 31 | <Add library="glu32" /> |
32 | 32 | <Add library="glew32" /> |
33 | 33 | <Add library="freetype" /> |
34 | <Add library="boost_filesystem-mgw46-mt-1_48" /> | |
35 | <Add library="libboost_system-mgw46-mt-1_48" /> | |
34 | 36 | </Linker> |
35 | 37 | <Unit filename="data\shaders\bloom.frag" /> |
36 | 38 | <Unit filename="data\shaders\bloom.vert" /> |
40 | 42 | <Unit filename="data\shaders\text.vert" /> |
41 | 43 | <Unit filename="src\action.cpp" /> |
42 | 44 | <Unit filename="src\action.h" /> |
43 | <Unit filename="src\apache.cpp" /> | |
44 | <Unit filename="src\apache.h" /> | |
45 | 45 | <Unit filename="src\bloom.cpp" /> |
46 | 46 | <Unit filename="src\bloom.h" /> |
47 | <Unit filename="src\bzr.cpp" /> | |
48 | <Unit filename="src\bzr.h" /> | |
49 | <Unit filename="src\commitlog.cpp" /> | |
50 | <Unit filename="src\commitlog.h" /> | |
51 | 47 | <Unit filename="src\core\bounds.h" /> |
52 | <Unit filename="src\core\camera.cpp" /> | |
53 | <Unit filename="src\core\camera.h" /> | |
54 | 48 | <Unit filename="src\core\conffile.cpp" /> |
55 | 49 | <Unit filename="src\core\conffile.h" /> |
56 | 50 | <Unit filename="src\core\display.cpp" /> |
89 | 83 | <Unit filename="src\core\texture.h" /> |
90 | 84 | <Unit filename="src\core\vbo.cpp" /> |
91 | 85 | <Unit filename="src\core\vbo.h" /> |
86 | <Unit filename="src\core\vectors.cpp" /> | |
92 | 87 | <Unit filename="src\core\vectors.h" /> |
93 | <Unit filename="src\custom.cpp" /> | |
94 | <Unit filename="src\custom.h" /> | |
95 | <Unit filename="src\cvs-exp.cpp" /> | |
96 | <Unit filename="src\cvs-exp.h" /> | |
97 | <Unit filename="src\cvs2cl.cpp" /> | |
98 | <Unit filename="src\cvs2cl.h" /> | |
99 | 88 | <Unit filename="src\dirnode.cpp" /> |
100 | 89 | <Unit filename="src\dirnode.h" /> |
101 | 90 | <Unit filename="src\file.cpp" /> |
102 | 91 | <Unit filename="src\file.h" /> |
103 | <Unit filename="src\git.cpp" /> | |
104 | <Unit filename="src\git.h" /> | |
105 | <Unit filename="src\gitraw.cpp" /> | |
106 | <Unit filename="src\gitraw.h" /> | |
92 | <Unit filename="src\formats\apache.cpp" /> | |
93 | <Unit filename="src\formats\apache.h" /> | |
94 | <Unit filename="src\formats\bzr.cpp" /> | |
95 | <Unit filename="src\formats\bzr.h" /> | |
96 | <Unit filename="src\formats\commitlog.cpp" /> | |
97 | <Unit filename="src\formats\commitlog.h" /> | |
98 | <Unit filename="src\formats\custom.cpp" /> | |
99 | <Unit filename="src\formats\custom.h" /> | |
100 | <Unit filename="src\formats\cvs-exp.cpp" /> | |
101 | <Unit filename="src\formats\cvs-exp.h" /> | |
102 | <Unit filename="src\formats\cvs2cl.cpp" /> | |
103 | <Unit filename="src\formats\cvs2cl.h" /> | |
104 | <Unit filename="src\formats\git.cpp" /> | |
105 | <Unit filename="src\formats\git.h" /> | |
106 | <Unit filename="src\formats\gitraw.cpp" /> | |
107 | <Unit filename="src\formats\gitraw.h" /> | |
108 | <Unit filename="src\formats\hg.cpp" /> | |
109 | <Unit filename="src\formats\hg.h" /> | |
110 | <Unit filename="src\formats\svn.cpp" /> | |
111 | <Unit filename="src\formats\svn.h" /> | |
107 | 112 | <Unit filename="src\gource.cpp" /> |
108 | 113 | <Unit filename="src\gource.h" /> |
109 | 114 | <Unit filename="src\gource_settings.cpp" /> |
110 | 115 | <Unit filename="src\gource_settings.h" /> |
111 | 116 | <Unit filename="src\gource_shell.cpp" /> |
112 | 117 | <Unit filename="src\gource_shell.h" /> |
113 | <Unit filename="src\hg.cpp" /> | |
114 | <Unit filename="src\hg.h" /> | |
115 | 118 | <Unit filename="src\key.cpp" /> |
116 | 119 | <Unit filename="src\key.h" /> |
120 | <Unit filename="src\logmill.cpp" /> | |
121 | <Unit filename="src\logmill.h" /> | |
117 | 122 | <Unit filename="src\main.cpp" /> |
118 | 123 | <Unit filename="src\main.h" /> |
119 | 124 | <Unit filename="src\pawn.cpp" /> |
122 | 127 | <Unit filename="src\slider.h" /> |
123 | 128 | <Unit filename="src\spline.cpp" /> |
124 | 129 | <Unit filename="src\spline.h" /> |
125 | <Unit filename="src\svn.cpp" /> | |
126 | <Unit filename="src\svn.h" /> | |
127 | 130 | <Unit filename="src\textbox.cpp" /> |
128 | 131 | <Unit filename="src\textbox.h" /> |
129 | 132 | <Unit filename="src\tinyxml\tinystr.cpp" /> |
0 | # =========================================================================== | |
1 | # http://www.gnu.org/software/autoconf-archive/ax_boost_base.html | |
2 | # =========================================================================== | |
3 | # | |
4 | # SYNOPSIS | |
5 | # | |
6 | # AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) | |
7 | # | |
8 | # DESCRIPTION | |
9 | # | |
10 | # Test for the Boost C++ libraries of a particular version (or newer) | |
11 | # | |
12 | # If no path to the installed boost library is given the macro searchs | |
13 | # under /usr, /usr/local, /opt and /opt/local and evaluates the | |
14 | # $BOOST_ROOT environment variable. Further documentation is available at | |
15 | # <http://randspringer.de/boost/index.html>. | |
16 | # | |
17 | # This macro calls: | |
18 | # | |
19 | # AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS) | |
20 | # | |
21 | # And sets: | |
22 | # | |
23 | # HAVE_BOOST | |
24 | # | |
25 | # LICENSE | |
26 | # | |
27 | # Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de> | |
28 | # Copyright (c) 2009 Peter Adolphs | |
29 | # | |
30 | # Copying and distribution of this file, with or without modification, are | |
31 | # permitted in any medium without royalty provided the copyright notice | |
32 | # and this notice are preserved. This file is offered as-is, without any | |
33 | # warranty. | |
34 | ||
35 | #serial 20 | |
36 | ||
37 | AC_DEFUN([AX_BOOST_BASE], | |
38 | [ | |
39 | AC_ARG_WITH([boost], | |
40 | [AS_HELP_STRING([--with-boost@<:@=ARG@:>@], | |
41 | [use Boost library from a standard location (ARG=yes), | |
42 | from the specified location (ARG=<path>), | |
43 | or disable it (ARG=no) | |
44 | @<:@ARG=yes@:>@ ])], | |
45 | [ | |
46 | if test "$withval" = "no"; then | |
47 | want_boost="no" | |
48 | elif test "$withval" = "yes"; then | |
49 | want_boost="yes" | |
50 | ac_boost_path="" | |
51 | else | |
52 | want_boost="yes" | |
53 | ac_boost_path="$withval" | |
54 | fi | |
55 | ], | |
56 | [want_boost="yes"]) | |
57 | ||
58 | ||
59 | AC_ARG_WITH([boost-libdir], | |
60 | AS_HELP_STRING([--with-boost-libdir=LIB_DIR], | |
61 | [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), | |
62 | [ | |
63 | if test -d "$withval" | |
64 | then | |
65 | ac_boost_lib_path="$withval" | |
66 | else | |
67 | AC_MSG_ERROR(--with-boost-libdir expected directory name) | |
68 | fi | |
69 | ], | |
70 | [ac_boost_lib_path=""] | |
71 | ) | |
72 | ||
73 | if test "x$want_boost" = "xyes"; then | |
74 | boost_lib_version_req=ifelse([$1], ,1.20.0,$1) | |
75 | boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` | |
76 | boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` | |
77 | boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` | |
78 | boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` | |
79 | if test "x$boost_lib_version_req_sub_minor" = "x" ; then | |
80 | boost_lib_version_req_sub_minor="0" | |
81 | fi | |
82 | WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` | |
83 | AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) | |
84 | succeeded=no | |
85 | ||
86 | dnl On 64-bit systems check for system libraries in both lib64 and lib. | |
87 | dnl The former is specified by FHS, but e.g. Debian does not adhere to | |
88 | dnl this (as it rises problems for generic multi-arch support). | |
89 | dnl The last entry in the list is chosen by default when no libraries | |
90 | dnl are found, e.g. when only header-only libraries are installed! | |
91 | libsubdirs="lib" | |
92 | ax_arch=`uname -m` | |
93 | if test $ax_arch = x86_64 -o $ax_arch = ppc64 -o $ax_arch = s390x -o $ax_arch = sparc64; then | |
94 | libsubdirs="lib64 lib lib64" | |
95 | fi | |
96 | ||
97 | dnl first we check the system location for boost libraries | |
98 | dnl this location ist chosen if boost libraries are installed with the --layout=system option | |
99 | dnl or if you install boost with RPM | |
100 | if test "$ac_boost_path" != ""; then | |
101 | BOOST_CPPFLAGS="-I$ac_boost_path/include" | |
102 | for ac_boost_path_tmp in $libsubdirs; do | |
103 | if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then | |
104 | BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" | |
105 | break | |
106 | fi | |
107 | done | |
108 | elif test "$cross_compiling" != yes; then | |
109 | for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do | |
110 | if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then | |
111 | for libsubdir in $libsubdirs ; do | |
112 | if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
113 | done | |
114 | BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" | |
115 | BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" | |
116 | break; | |
117 | fi | |
118 | done | |
119 | fi | |
120 | ||
121 | dnl overwrite ld flags if we have required special directory with | |
122 | dnl --with-boost-libdir parameter | |
123 | if test "$ac_boost_lib_path" != ""; then | |
124 | BOOST_LDFLAGS="-L$ac_boost_lib_path" | |
125 | fi | |
126 | ||
127 | CPPFLAGS_SAVED="$CPPFLAGS" | |
128 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
129 | export CPPFLAGS | |
130 | ||
131 | LDFLAGS_SAVED="$LDFLAGS" | |
132 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
133 | export LDFLAGS | |
134 | ||
135 | AC_REQUIRE([AC_PROG_CXX]) | |
136 | AC_LANG_PUSH(C++) | |
137 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | |
138 | @%:@include <boost/version.hpp> | |
139 | ]], [[ | |
140 | #if BOOST_VERSION >= $WANT_BOOST_VERSION | |
141 | // Everything is okay | |
142 | #else | |
143 | # error Boost version is too old | |
144 | #endif | |
145 | ]])],[ | |
146 | AC_MSG_RESULT(yes) | |
147 | succeeded=yes | |
148 | found_system=yes | |
149 | ],[ | |
150 | ]) | |
151 | AC_LANG_POP([C++]) | |
152 | ||
153 | ||
154 | ||
155 | dnl if we found no boost with system layout we search for boost libraries | |
156 | dnl built and installed without the --layout=system option or for a staged(not installed) version | |
157 | if test "x$succeeded" != "xyes"; then | |
158 | _version=0 | |
159 | if test "$ac_boost_path" != ""; then | |
160 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then | |
161 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do | |
162 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` | |
163 | V_CHECK=`expr $_version_tmp \> $_version` | |
164 | if test "$V_CHECK" = "1" ; then | |
165 | _version=$_version_tmp | |
166 | fi | |
167 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` | |
168 | BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" | |
169 | done | |
170 | fi | |
171 | else | |
172 | if test "$cross_compiling" != yes; then | |
173 | for ac_boost_path in /usr /usr/local /opt /opt/local ; do | |
174 | if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then | |
175 | for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do | |
176 | _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` | |
177 | V_CHECK=`expr $_version_tmp \> $_version` | |
178 | if test "$V_CHECK" = "1" ; then | |
179 | _version=$_version_tmp | |
180 | best_path=$ac_boost_path | |
181 | fi | |
182 | done | |
183 | fi | |
184 | done | |
185 | ||
186 | VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` | |
187 | BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" | |
188 | if test "$ac_boost_lib_path" = ""; then | |
189 | for libsubdir in $libsubdirs ; do | |
190 | if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
191 | done | |
192 | BOOST_LDFLAGS="-L$best_path/$libsubdir" | |
193 | fi | |
194 | fi | |
195 | ||
196 | if test "x$BOOST_ROOT" != "x"; then | |
197 | for libsubdir in $libsubdirs ; do | |
198 | if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi | |
199 | done | |
200 | if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then | |
201 | version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'` | |
202 | stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` | |
203 | stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` | |
204 | V_CHECK=`expr $stage_version_shorten \>\= $_version` | |
205 | if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then | |
206 | AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) | |
207 | BOOST_CPPFLAGS="-I$BOOST_ROOT" | |
208 | BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" | |
209 | fi | |
210 | fi | |
211 | fi | |
212 | fi | |
213 | ||
214 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
215 | export CPPFLAGS | |
216 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
217 | export LDFLAGS | |
218 | ||
219 | AC_LANG_PUSH(C++) | |
220 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ | |
221 | @%:@include <boost/version.hpp> | |
222 | ]], [[ | |
223 | #if BOOST_VERSION >= $WANT_BOOST_VERSION | |
224 | // Everything is okay | |
225 | #else | |
226 | # error Boost version is too old | |
227 | #endif | |
228 | ]])],[ | |
229 | AC_MSG_RESULT(yes) | |
230 | succeeded=yes | |
231 | found_system=yes | |
232 | ],[ | |
233 | ]) | |
234 | AC_LANG_POP([C++]) | |
235 | fi | |
236 | ||
237 | if test "$succeeded" != "yes" ; then | |
238 | if test "$_version" = "0" ; then | |
239 | AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]]) | |
240 | else | |
241 | AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) | |
242 | fi | |
243 | # execute ACTION-IF-NOT-FOUND (if present): | |
244 | ifelse([$3], , :, [$3]) | |
245 | else | |
246 | AC_SUBST(BOOST_CPPFLAGS) | |
247 | AC_SUBST(BOOST_LDFLAGS) | |
248 | AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) | |
249 | # execute ACTION-IF-FOUND (if present): | |
250 | ifelse([$2], , :, [$2]) | |
251 | fi | |
252 | ||
253 | CPPFLAGS="$CPPFLAGS_SAVED" | |
254 | LDFLAGS="$LDFLAGS_SAVED" | |
255 | fi | |
256 | ||
257 | ]) |
0 | # =========================================================================== | |
1 | # http://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html | |
2 | # =========================================================================== | |
3 | # | |
4 | # SYNOPSIS | |
5 | # | |
6 | # AX_BOOST_FILESYSTEM | |
7 | # | |
8 | # DESCRIPTION | |
9 | # | |
10 | # Test for Filesystem library from the Boost C++ libraries. The macro | |
11 | # requires a preceding call to AX_BOOST_BASE. Further documentation is | |
12 | # available at <http://randspringer.de/boost/index.html>. | |
13 | # | |
14 | # This macro calls: | |
15 | # | |
16 | # AC_SUBST(BOOST_FILESYSTEM_LIB) | |
17 | # | |
18 | # And sets: | |
19 | # | |
20 | # HAVE_BOOST_FILESYSTEM | |
21 | # | |
22 | # LICENSE | |
23 | # | |
24 | # Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de> | |
25 | # Copyright (c) 2009 Michael Tindal | |
26 | # Copyright (c) 2009 Roman Rybalko <libtorrent@romanr.info> | |
27 | # | |
28 | # Copying and distribution of this file, with or without modification, are | |
29 | # permitted in any medium without royalty provided the copyright notice | |
30 | # and this notice are preserved. This file is offered as-is, without any | |
31 | # warranty. | |
32 | ||
33 | #serial 22 | |
34 | ||
35 | AC_DEFUN([AX_BOOST_FILESYSTEM], | |
36 | [ | |
37 | AC_ARG_WITH([boost-filesystem], | |
38 | AS_HELP_STRING([--with-boost-filesystem@<:@=special-lib@:>@], | |
39 | [use the Filesystem library from boost - it is possible to specify a certain library for the linker | |
40 | e.g. --with-boost-filesystem=boost_filesystem-gcc-mt ]), | |
41 | [ | |
42 | if test "$withval" = "no"; then | |
43 | want_boost="no" | |
44 | elif test "$withval" = "yes"; then | |
45 | want_boost="yes" | |
46 | ax_boost_user_filesystem_lib="" | |
47 | else | |
48 | want_boost="yes" | |
49 | ax_boost_user_filesystem_lib="$withval" | |
50 | fi | |
51 | ], | |
52 | [want_boost="yes"] | |
53 | ) | |
54 | ||
55 | if test "x$want_boost" = "xyes"; then | |
56 | AC_REQUIRE([AC_PROG_CC]) | |
57 | CPPFLAGS_SAVED="$CPPFLAGS" | |
58 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
59 | export CPPFLAGS | |
60 | ||
61 | LDFLAGS_SAVED="$LDFLAGS" | |
62 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
63 | export LDFLAGS | |
64 | ||
65 | LIBS_SAVED=$LIBS | |
66 | LIBS="$LIBS $BOOST_SYSTEM_LIB" | |
67 | export LIBS | |
68 | ||
69 | AC_CACHE_CHECK(whether the Boost::Filesystem library is available, | |
70 | ax_cv_boost_filesystem, | |
71 | [AC_LANG_PUSH([C++]) | |
72 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/filesystem/path.hpp>]], | |
73 | [[using namespace boost::filesystem; | |
74 | path my_path( "foo/bar/data.txt" ); | |
75 | return 0;]])], | |
76 | ax_cv_boost_filesystem=yes, ax_cv_boost_filesystem=no) | |
77 | AC_LANG_POP([C++]) | |
78 | ]) | |
79 | if test "x$ax_cv_boost_filesystem" = "xyes"; then | |
80 | AC_DEFINE(HAVE_BOOST_FILESYSTEM,,[define if the Boost::Filesystem library is available]) | |
81 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` | |
82 | if test "x$ax_boost_user_filesystem_lib" = "x"; then | |
83 | for libextension in `ls $BOOSTLIBDIR/libboost_filesystem*.so* $BOOSTLIBDIR/libboost_filesystem*.dylib* $BOOSTLIBDIR/libboost_filesystem*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_filesystem.*\)\.so.*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.a*$;\1;' -e 's;^lib\(boost_filesystem.*\)\.dylib$;\1;'` ; do | |
84 | ax_lib=${libextension} | |
85 | AC_CHECK_LIB($ax_lib, exit, | |
86 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], | |
87 | [link_filesystem="no"]) | |
88 | done | |
89 | if test "x$link_filesystem" != "xyes"; then | |
90 | for libextension in `ls $BOOSTLIBDIR/boost_filesystem*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_filesystem.*\)\.dll.*$;\1;' -e 's;^\(boost_filesystem.*\)\.a*$;\1;'` ; do | |
91 | ax_lib=${libextension} | |
92 | AC_CHECK_LIB($ax_lib, exit, | |
93 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], | |
94 | [link_filesystem="no"]) | |
95 | done | |
96 | fi | |
97 | else | |
98 | for ax_lib in $ax_boost_user_filesystem_lib boost_filesystem-$ax_boost_user_filesystem_lib; do | |
99 | AC_CHECK_LIB($ax_lib, exit, | |
100 | [BOOST_FILESYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_FILESYSTEM_LIB) link_filesystem="yes"; break], | |
101 | [link_filesystem="no"]) | |
102 | done | |
103 | ||
104 | fi | |
105 | if test "x$ax_lib" = "x"; then | |
106 | AC_MSG_ERROR(Could not find a version of the library!) | |
107 | fi | |
108 | if test "x$link_filesystem" != "xyes"; then | |
109 | AC_MSG_ERROR(Could not link against $ax_lib !) | |
110 | fi | |
111 | fi | |
112 | ||
113 | CPPFLAGS="$CPPFLAGS_SAVED" | |
114 | LDFLAGS="$LDFLAGS_SAVED" | |
115 | LIBS="$LIBS_SAVED" | |
116 | fi | |
117 | ]) |
0 | # =========================================================================== | |
1 | # http://www.gnu.org/software/autoconf-archive/ax_boost_system.html | |
2 | # =========================================================================== | |
3 | # | |
4 | # SYNOPSIS | |
5 | # | |
6 | # AX_BOOST_SYSTEM | |
7 | # | |
8 | # DESCRIPTION | |
9 | # | |
10 | # Test for System library from the Boost C++ libraries. The macro requires | |
11 | # a preceding call to AX_BOOST_BASE. Further documentation is available at | |
12 | # <http://randspringer.de/boost/index.html>. | |
13 | # | |
14 | # This macro calls: | |
15 | # | |
16 | # AC_SUBST(BOOST_SYSTEM_LIB) | |
17 | # | |
18 | # And sets: | |
19 | # | |
20 | # HAVE_BOOST_SYSTEM | |
21 | # | |
22 | # LICENSE | |
23 | # | |
24 | # Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de> | |
25 | # Copyright (c) 2008 Michael Tindal | |
26 | # Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com> | |
27 | # | |
28 | # Copying and distribution of this file, with or without modification, are | |
29 | # permitted in any medium without royalty provided the copyright notice | |
30 | # and this notice are preserved. This file is offered as-is, without any | |
31 | # warranty. | |
32 | ||
33 | #serial 14 | |
34 | ||
35 | AC_DEFUN([AX_BOOST_SYSTEM], | |
36 | [ | |
37 | AC_ARG_WITH([boost-system], | |
38 | AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@], | |
39 | [use the System library from boost - it is possible to specify a certain library for the linker | |
40 | e.g. --with-boost-system=boost_system-gcc-mt ]), | |
41 | [ | |
42 | if test "$withval" = "no"; then | |
43 | want_boost="no" | |
44 | elif test "$withval" = "yes"; then | |
45 | want_boost="yes" | |
46 | ax_boost_user_system_lib="" | |
47 | else | |
48 | want_boost="yes" | |
49 | ax_boost_user_system_lib="$withval" | |
50 | fi | |
51 | ], | |
52 | [want_boost="yes"] | |
53 | ) | |
54 | ||
55 | if test "x$want_boost" = "xyes"; then | |
56 | AC_REQUIRE([AC_PROG_CC]) | |
57 | AC_REQUIRE([AC_CANONICAL_BUILD]) | |
58 | CPPFLAGS_SAVED="$CPPFLAGS" | |
59 | CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" | |
60 | export CPPFLAGS | |
61 | ||
62 | LDFLAGS_SAVED="$LDFLAGS" | |
63 | LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" | |
64 | export LDFLAGS | |
65 | ||
66 | AC_CACHE_CHECK(whether the Boost::System library is available, | |
67 | ax_cv_boost_system, | |
68 | [AC_LANG_PUSH([C++]) | |
69 | CXXFLAGS_SAVE=$CXXFLAGS | |
70 | ||
71 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]], | |
72 | [[boost::system::system_category]])], | |
73 | ax_cv_boost_system=yes, ax_cv_boost_system=no) | |
74 | CXXFLAGS=$CXXFLAGS_SAVE | |
75 | AC_LANG_POP([C++]) | |
76 | ]) | |
77 | if test "x$ax_cv_boost_system" = "xyes"; then | |
78 | AC_SUBST(BOOST_CPPFLAGS) | |
79 | ||
80 | AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available]) | |
81 | BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` | |
82 | ||
83 | LDFLAGS_SAVE=$LDFLAGS | |
84 | if test "x$ax_boost_user_system_lib" = "x"; then | |
85 | for libextension in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.a*$;\1;'` ; do | |
86 | ax_lib=${libextension} | |
87 | AC_CHECK_LIB($ax_lib, exit, | |
88 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], | |
89 | [link_system="no"]) | |
90 | done | |
91 | if test "x$link_system" != "xyes"; then | |
92 | for libextension in `ls $BOOSTLIBDIR/boost_system*.{dll,a}* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_system.*\)\.dll.*$;\1;' -e 's;^\(boost_system.*\)\.a*$;\1;'` ; do | |
93 | ax_lib=${libextension} | |
94 | AC_CHECK_LIB($ax_lib, exit, | |
95 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], | |
96 | [link_system="no"]) | |
97 | done | |
98 | fi | |
99 | ||
100 | else | |
101 | for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do | |
102 | AC_CHECK_LIB($ax_lib, exit, | |
103 | [BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break], | |
104 | [link_system="no"]) | |
105 | done | |
106 | ||
107 | fi | |
108 | if test "x$ax_lib" = "x"; then | |
109 | AC_MSG_ERROR(Could not find a version of the library!) | |
110 | fi | |
111 | if test "x$link_system" = "xno"; then | |
112 | AC_MSG_ERROR(Could not link against $ax_lib !) | |
113 | fi | |
114 | fi | |
115 | ||
116 | CPPFLAGS="$CPPFLAGS_SAVED" | |
117 | LDFLAGS="$LDFLAGS_SAVED" | |
118 | fi | |
119 | ]) |
41 | 41 | void RAction::drawToVBO(quadbuf& buffer) const { |
42 | 42 | if(isFinished()) return; |
43 | 43 | |
44 | vec2f src = source->getPos(); | |
45 | vec2f dest = target->getAbsolutePos(); | |
44 | vec2 src = source->getPos(); | |
45 | vec2 dest = target->getAbsolutePos(); | |
46 | 46 | |
47 | vec2f offset = (dest - src).normal().perpendicular() * target->getSize() * 0.5; | |
48 | vec2f offset_src = offset * 0.3f; | |
47 | //TODO: could use glm::perp | |
48 | ||
49 | vec2 n = normalise(dest - src); | |
50 | vec2 perp = vec2(-n.y, n.x); | |
51 | ||
52 | vec2 offset = perp * target->getSize() * 0.5f; | |
53 | vec2 offset_src = offset * 0.3f; | |
49 | 54 | |
50 | 55 | float alpha = 1.0 - progress; |
51 | 56 | float alpha2 = alpha * 0.1; |
52 | 57 | |
53 | vec4f col1 = vec4f(colour, alpha); | |
54 | vec4f col2 = vec4f(colour, alpha2); | |
58 | vec4 col1 = vec4(colour, alpha); | |
59 | vec4 col2 = vec4(colour, alpha2); | |
55 | 60 | |
56 | quadbuf_vertex v1(src - offset_src, col2, vec2f(0.0f, 0.0f)); | |
57 | quadbuf_vertex v2(src + offset_src, col2, vec2f(0.0f, 1.0f)); | |
58 | quadbuf_vertex v3(dest + offset, col1, vec2f(1.0f, 1.0f)); | |
59 | quadbuf_vertex v4(dest - offset, col1, vec2f(1.0f, 0.0f)); | |
61 | quadbuf_vertex v1(src - offset_src, col2, vec2(0.0f, 0.0f)); | |
62 | quadbuf_vertex v2(src + offset_src, col2, vec2(0.0f, 1.0f)); | |
63 | quadbuf_vertex v3(dest + offset, col1, vec2(1.0f, 1.0f)); | |
64 | quadbuf_vertex v4(dest - offset, col1, vec2(1.0f, 0.0f)); | |
60 | 65 | |
61 | 66 | buffer.add(0, v1, v2, v3, v4); |
62 | 67 | } |
64 | 69 | void RAction::draw(float dt) { |
65 | 70 | if(isFinished()) return; |
66 | 71 | |
67 | vec2f src = source->getPos(); | |
68 | vec2f dest = target->getAbsolutePos(); | |
72 | vec2 src = source->getPos(); | |
73 | vec2 dest = target->getAbsolutePos(); | |
69 | 74 | |
70 | vec2f offset = (dest - src).normal().perpendicular() * target->getSize() * 0.5; | |
71 | vec2f offset_src = offset * 0.3f; | |
75 | vec2 n = normalise(dest - src); | |
76 | vec2 perp = vec2(-n.y, n.x); | |
77 | ||
78 | vec2 offset = perp * target->getSize() * 0.5f; | |
79 | vec2 offset_src = offset * 0.3f; | |
72 | 80 | |
73 | 81 | float alpha = 1.0 - progress; |
74 | 82 | float alpha2 = alpha * 0.1; |
75 | 83 | |
76 | vec4f col1 = vec4f(colour, alpha); | |
77 | vec4f col2 = vec4f(colour, alpha2); | |
84 | vec4 col1 = vec4(colour, alpha); | |
85 | vec4 col2 = vec4(colour, alpha2); | |
78 | 86 | |
79 | 87 | glBegin(GL_QUADS); |
80 | glColor4fv(col2); | |
88 | glColor4fv(glm::value_ptr(col2)); | |
81 | 89 | glTexCoord2f(0.0,0.0); |
82 | 90 | glVertex2f(src.x - offset_src.x, src.y - offset_src.y); |
83 | 91 | glTexCoord2f(0.0,1.0); |
84 | 92 | glVertex2f(src.x + offset_src.x, src.y + offset_src.y); |
85 | 93 | |
86 | glColor4fv(col1); | |
94 | glColor4fv(glm::value_ptr(col1)); | |
87 | 95 | glTexCoord2f(1.0,1.0); |
88 | 96 | glVertex2f(dest.x + offset.x, dest.y + offset.y); |
89 | 97 | glTexCoord2f(1.0,0.0); |
92 | 100 | } |
93 | 101 | |
94 | 102 | CreateAction::CreateAction(RUser* source, RFile* target, float addedtime) : RAction(source, target, addedtime) { |
95 | colour = vec3f(0.0, 1.0, 0.0); | |
103 | colour = vec3(0.0, 1.0, 0.0); | |
96 | 104 | } |
97 | 105 | |
98 | 106 | RemoveAction::RemoveAction(RUser* source, RFile* target, float addedtime): RAction(source, target, addedtime) { |
99 | colour = vec3f(1.0, 0.0, 0.0); | |
107 | colour = vec3(1.0, 0.0, 0.0); | |
100 | 108 | } |
101 | 109 | |
102 | 110 | void RemoveAction::logic(float dt) { |
110 | 118 | } |
111 | 119 | |
112 | 120 | ModifyAction::ModifyAction(RUser* source, RFile* target, float addedtime) : RAction(source, target, addedtime) { |
113 | colour = vec3f(1.0, 0.7, 0.3); | |
121 | colour = vec3(1.0, 0.7, 0.3); | |
114 | 122 | } |
25 | 25 | |
26 | 26 | class RAction { |
27 | 27 | protected: |
28 | vec3f colour; | |
28 | vec3 colour; | |
29 | 29 | public: |
30 | 30 | RUser* source; |
31 | 31 | RFile* target; |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "apache.h" | |
18 | ||
19 | const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug" , "Sep", "Oct", "Nov", "Dec" }; | |
20 | Regex apache_entry_start("^(?:[^ ]+ )?([^ ]+) +[^ ]+ +([^ ]+) +\\[(.*?)\\] +(.*)$"); | |
21 | Regex apache_entry_date("(\\d+)/([A-Za-z]+)/(\\d+):(\\d+):(\\d+):(\\d+) ([+-])(\\d+)"); | |
22 | Regex apache_entry_request("\"([^ ]+) +([^ ]+) +([^ ]+)\" +([^ ]+) +([^\\s+]+)(.*)"); | |
23 | Regex apache_entry_agent(" +\"([^\"]+)\" +\"([^\"]+)\" +\"([^\"]+)\""); | |
24 | Regex apache_hostname_parts("([^.]+)(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?$"); | |
25 | ||
26 | ApacheCombinedLog::ApacheCombinedLog(const std::string& logfile) : RCommitLog(logfile) { | |
27 | } | |
28 | ||
29 | //parse apache access.log entry into components | |
30 | bool ApacheCombinedLog::parseCommit(RCommit& commit) { | |
31 | ||
32 | std::string line; | |
33 | std::vector<std::string> matches; | |
34 | ||
35 | if(!logf->getNextLine(line)) return false; | |
36 | ||
37 | apache_entry_start.match(line, &matches); | |
38 | ||
39 | if(matches.size()!=4) { | |
40 | return 0; | |
41 | } | |
42 | ||
43 | //get details | |
44 | commit.username = matches[0]; | |
45 | //std::string user = matches[1]; | |
46 | ||
47 | //parse timestamp | |
48 | struct tm time_str; | |
49 | ||
50 | std::string request_str = matches[3]; | |
51 | std::string datestr = matches[2]; | |
52 | ||
53 | apache_entry_date.match(datestr, &matches); | |
54 | ||
55 | if(matches.size()!=8) { | |
56 | return 0; | |
57 | } | |
58 | ||
59 | int day = atoi(matches[0].c_str()); | |
60 | int year = atoi(matches[2].c_str()); | |
61 | int hour = atoi(matches[3].c_str()); | |
62 | int minute = atoi(matches[4].c_str()); | |
63 | int second = atoi(matches[5].c_str()); | |
64 | ||
65 | // int zone = atoi(matches[7].c_str()); | |
66 | //negative timezone | |
67 | // if(strcmp(matches[6].c_str(), "-")==0) { | |
68 | // zone = -zone; | |
69 | // } | |
70 | ||
71 | int month=0; | |
72 | ||
73 | for(int i=0;i<12;i++) { | |
74 | if(matches[1] == months[i]) { | |
75 | month=i; | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | time_str.tm_year = year - 1900; | |
81 | time_str.tm_mon = month; | |
82 | time_str.tm_mday = day; | |
83 | time_str.tm_hour = hour; | |
84 | time_str.tm_min = minute; | |
85 | time_str.tm_sec = second; | |
86 | time_str.tm_isdst = -1; | |
87 | ||
88 | commit.timestamp = mktime(&time_str); | |
89 | ||
90 | matches.clear(); | |
91 | apache_entry_request.match(request_str, &matches); | |
92 | ||
93 | if(matches.size() < 5) { | |
94 | return false; | |
95 | } | |
96 | ||
97 | std::string rtype = matches[0]; | |
98 | std::string file = matches[1]; | |
99 | std::string proto = matches[2]; | |
100 | ||
101 | int code = atoi(matches[3].c_str()); | |
102 | int bytes = atol(matches[4].c_str()); | |
103 | ||
104 | //remove args from url | |
105 | size_t argpos = file.rfind("?"); | |
106 | if(argpos != std::string::npos) { | |
107 | file = file.substr(0,argpos); | |
108 | } | |
109 | ||
110 | if(file.size()==0) file = "/"; | |
111 | ||
112 | //name index pages | |
113 | if(file[file.size()-1] == '/') { | |
114 | file += "index.html"; | |
115 | } | |
116 | ||
117 | std::string action = "A"; | |
118 | commit.addFile(file, action); | |
119 | ||
120 | std::string refer; | |
121 | std::string agent; | |
122 | ||
123 | if(matches.size() > 5) { | |
124 | std::string agentstr = matches[5]; | |
125 | matches.clear(); | |
126 | apache_entry_agent.match(agentstr, &matches); | |
127 | ||
128 | if(matches.size()>1) { | |
129 | refer = matches[0]; | |
130 | agent = matches[1]; | |
131 | } | |
132 | } | |
133 | ||
134 | return true; | |
135 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GOURCE_APACHE_H | |
18 | #define GOURCE_APACHE_H | |
19 | ||
20 | #include <string> | |
21 | #include <string.h> | |
22 | ||
23 | #include <vector> | |
24 | #include <time.h> | |
25 | ||
26 | #include "commitlog.h" | |
27 | ||
28 | class ApacheCombinedLog : public RCommitLog { | |
29 | protected: | |
30 | bool parseCommit(RCommit& commit); | |
31 | BaseLog* generateLog(const std::string& dir); | |
32 | public: | |
33 | ApacheCombinedLog(const std::string& logfile); | |
34 | }; | |
35 | ||
36 | #endif |
52 | 52 | vertex_count = 0; |
53 | 53 | } |
54 | 54 | |
55 | void bloombuf::unload() { | |
56 | if(bufferid !=0) glDeleteBuffers(1, &bufferid); | |
57 | bufferid = 0; | |
58 | buffer_size = 0; | |
59 | } | |
60 | ||
55 | 61 | size_t bloombuf::vertices() { |
56 | 62 | return vertex_count; |
57 | 63 | } |
60 | 66 | return data_size; |
61 | 67 | } |
62 | 68 | |
63 | void bloombuf::add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour, const vec4f& texcoord) { | |
69 | void bloombuf::add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour, const vec4& texcoord) { | |
64 | 70 | |
65 | 71 | bloom_vertex v1(pos, colour, texcoord); |
66 | bloom_vertex v2(pos + vec2f(dims.x, 0.0f), colour, texcoord); | |
72 | bloom_vertex v2(pos + vec2(dims.x, 0.0f), colour, texcoord); | |
67 | 73 | bloom_vertex v3(pos + dims, colour, texcoord); |
68 | bloom_vertex v4(pos + vec2f(0.0f, dims.y), colour, texcoord); | |
74 | bloom_vertex v4(pos + vec2(0.0f, dims.y), colour, texcoord); | |
69 | 75 | |
70 | 76 | int i = vertex_count; |
71 | 77 |
27 | 27 | class bloom_vertex { |
28 | 28 | public: |
29 | 29 | bloom_vertex() {}; |
30 | bloom_vertex(const vec2f& pos, const vec4f& colour, const vec4f& texcoord) : | |
30 | bloom_vertex(const vec2& pos, const vec4& colour, const vec4& texcoord) : | |
31 | 31 | pos(pos), colour(colour), texcoord(texcoord) {}; |
32 | 32 | |
33 | vec2f pos; | |
34 | vec4f colour; | |
35 | vec4f texcoord; | |
33 | vec2 pos; | |
34 | vec4 colour; | |
35 | vec4 texcoord; | |
36 | 36 | char padding[24]; |
37 | 37 | }; |
38 | 38 | |
51 | 51 | bloombuf(int data_size = 0); |
52 | 52 | ~bloombuf(); |
53 | 53 | |
54 | void unload(); | |
54 | 55 | void reset(); |
55 | 56 | |
56 | 57 | size_t vertices(); |
57 | 58 | size_t capacity(); |
58 | 59 | |
59 | void add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour, const vec4f& texcoord); | |
60 | void add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour, const vec4& texcoord); | |
60 | 61 | |
61 | 62 | void update(); |
62 | 63 | void draw(); |
0 | /* | |
1 | Copyright (C) 2010 John Arbash Meinel <john@arbash-meinel.com> | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "bzr.h" | |
18 | ||
19 | Regex bzr_commit_regex("^ *([\\d.]+) (.+)\t(\\d{4})-(\\d+)-(\\d+)(?: \\{[^}]+})?(?: \\[merge\\])?$"); | |
20 | Regex bzr_file_regex("^ *([AMDR]) (.*[^/])$"); | |
21 | ||
22 | // parse Bazaar log entries (using the gource.style template) | |
23 | ||
24 | std::string gGourceBzrLogCommand() { | |
25 | return std::string("bzr log --verbose -r 1..-1 --short -n0 --forward"); | |
26 | } | |
27 | ||
28 | BazaarLog::BazaarLog(const std::string& logfile) : RCommitLog(logfile) { | |
29 | ||
30 | log_command = gGourceBzrLogCommand(); | |
31 | ||
32 | //can generate log from directory | |
33 | if(!logf && is_dir) { | |
34 | logf = generateLog(logfile); | |
35 | ||
36 | if(logf) { | |
37 | success = true; | |
38 | seekable = true; | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | BaseLog* BazaarLog::generateLog(const std::string& dir) { | |
44 | ||
45 | //does directory have a .bzr ? | |
46 | std::string bzrdir = dir + std::string("/.bzr"); | |
47 | struct stat dirinfo; | |
48 | int stat_rc = stat(bzrdir.c_str(), &dirinfo); | |
49 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
50 | return 0; | |
51 | } | |
52 | ||
53 | std::string command = getLogCommand(); | |
54 | ||
55 | createTempLog(); | |
56 | ||
57 | if(temp_file.size()==0) return 0; | |
58 | ||
59 | char cmd_buff[2048]; | |
60 | sprintf(cmd_buff, "%s %s > %s", command.c_str(), dir.c_str(), temp_file.c_str()); | |
61 | ||
62 | int command_rc = system(cmd_buff); | |
63 | ||
64 | if(command_rc != 0) { | |
65 | return 0; | |
66 | } | |
67 | ||
68 | BaseLog* seeklog = new SeekLog(temp_file); | |
69 | ||
70 | return seeklog; | |
71 | } | |
72 | ||
73 | bool BazaarLog::parseCommit(RCommit& commit) { | |
74 | ||
75 | std::string line; | |
76 | std::vector<std::string> entries; | |
77 | int year, month, day; | |
78 | ||
79 | if(!logf->getNextLine(line)) return false; | |
80 | ||
81 | debugLog("read %s\n", line.c_str()); | |
82 | if (!bzr_commit_regex.match(line, &entries)) { | |
83 | debugLog("regex failed\n"); | |
84 | return false; | |
85 | } | |
86 | commit.username = entries[1]; | |
87 | ||
88 | year = atoi(entries[2].c_str()); | |
89 | month = atoi(entries[3].c_str()); | |
90 | day = atoi(entries[4].c_str()); | |
91 | ||
92 | struct tm time_str; | |
93 | ||
94 | time_str.tm_year = year - 1900; | |
95 | time_str.tm_mon = month - 1; | |
96 | time_str.tm_mday = day; | |
97 | time_str.tm_hour = 0; | |
98 | time_str.tm_min = 0; | |
99 | time_str.tm_sec = 0; | |
100 | time_str.tm_isdst = -1; | |
101 | ||
102 | commit.timestamp = mktime(&time_str); | |
103 | ||
104 | while(logf->getNextLine(line) && line.size()) { | |
105 | if (!bzr_file_regex.match(line, &entries)) continue; | |
106 | commit.addFile(entries[1], entries[0]); | |
107 | } | |
108 | ||
109 | return true; | |
110 | } |
0 | /* | |
1 | Copyright (C) 2010 John Arbash Meinel <john@arbash-meinel.com> | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef BAZAARLOG_H | |
18 | #define BAZAARLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | std::string gGourceBzrLogCommand(); | |
23 | ||
24 | class BazaarLog : public RCommitLog { | |
25 | protected: | |
26 | bool parseCommit(RCommit& commit); | |
27 | BaseLog* generateLog(const std::string& dir); | |
28 | public: | |
29 | BazaarLog(const std::string& logfile); | |
30 | }; | |
31 | ||
32 | #endif | |
33 |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "commitlog.h" | |
18 | ||
19 | std::string munge_utf8(const std::string& str) { | |
20 | ||
21 | std::string munged; | |
22 | try { | |
23 | utf8::replace_invalid(str.begin(), str.end(), back_inserter(munged), '?'); | |
24 | } | |
25 | catch(...) { | |
26 | munged = "???"; | |
27 | } | |
28 | ||
29 | return munged; | |
30 | } | |
31 | ||
32 | //RCommitLog | |
33 | ||
34 | RCommitLog::RCommitLog(const std::string& logfile, int firstChar) { | |
35 | ||
36 | logf = 0; | |
37 | seekable = false; | |
38 | success = false; | |
39 | is_dir = false; | |
40 | buffered = false; | |
41 | ||
42 | if(logfile == "-") { | |
43 | ||
44 | //check first char | |
45 | if(checkFirstChar(firstChar, std::cin)) { | |
46 | logf = new StreamLog(); | |
47 | is_dir = false; | |
48 | seekable = false; | |
49 | success = true; | |
50 | } | |
51 | ||
52 | return; | |
53 | } | |
54 | ||
55 | struct stat fileinfo; | |
56 | int rc = stat(logfile.c_str(), &fileinfo); | |
57 | ||
58 | if(rc==0) { | |
59 | is_dir = (fileinfo.st_mode & S_IFDIR) ? true : false; | |
60 | ||
61 | if(!is_dir) { | |
62 | ||
63 | //check first char | |
64 | std::ifstream testf(logfile.c_str()); | |
65 | ||
66 | bool firstOK = checkFirstChar(firstChar, testf); | |
67 | ||
68 | testf.close(); | |
69 | ||
70 | if(firstOK) { | |
71 | logf = new SeekLog(logfile); | |
72 | seekable = true; | |
73 | success = true; | |
74 | } | |
75 | } | |
76 | } | |
77 | } | |
78 | ||
79 | RCommitLog::~RCommitLog() { | |
80 | if(logf!=0) delete logf; | |
81 | ||
82 | if(!temp_file.empty()) { | |
83 | remove(temp_file.c_str()); | |
84 | } | |
85 | } | |
86 | ||
87 | //check firstChar of stream is as expected. if no firstChar defined just returns true. | |
88 | bool RCommitLog::checkFirstChar(int firstChar, std::istream& stream) { | |
89 | ||
90 | //cant check this | |
91 | if(firstChar == -1) return true; | |
92 | ||
93 | int c = stream.peek(); | |
94 | ||
95 | if(firstChar == c) return true; | |
96 | ||
97 | return false; | |
98 | } | |
99 | ||
100 | bool RCommitLog::checkFormat() { | |
101 | ||
102 | if(!success) return false; | |
103 | ||
104 | //read a commit to see if the log is in the correct format | |
105 | if(nextCommit(lastCommit)) { | |
106 | ||
107 | if(seekable) { | |
108 | //if the log is seekable, go back to the start | |
109 | ((SeekLog*)logf)->seekTo(0.0); | |
110 | } else { | |
111 | //otherwise set the buffered flag as we have bufferd one commit | |
112 | buffered = true; | |
113 | } | |
114 | ||
115 | return true; | |
116 | } | |
117 | ||
118 | return false; | |
119 | } | |
120 | ||
121 | std::string RCommitLog::getLogCommand() { | |
122 | return log_command; | |
123 | } | |
124 | ||
125 | bool RCommitLog::isSeekable() { | |
126 | return seekable; | |
127 | } | |
128 | ||
129 | bool RCommitLog::getCommitAt(float percent, RCommit& commit) { | |
130 | if(!seekable) return false; | |
131 | ||
132 | SeekLog* seeklog = ((SeekLog*)logf); | |
133 | ||
134 | //save settings | |
135 | long currpointer = seeklog->getPointer(); | |
136 | std::string currlastline = lastline; | |
137 | ||
138 | seekTo(percent); | |
139 | bool success = findNextCommit(commit,500); | |
140 | ||
141 | //restore settings | |
142 | seeklog->setPointer(currpointer); | |
143 | lastline = currlastline; | |
144 | ||
145 | return success; | |
146 | } | |
147 | ||
148 | bool RCommitLog::getNextLine(std::string& line) { | |
149 | if(!lastline.empty()) { | |
150 | line = lastline; | |
151 | lastline = std::string(""); | |
152 | return true; | |
153 | } | |
154 | ||
155 | return logf->getNextLine(line); | |
156 | } | |
157 | ||
158 | ||
159 | void RCommitLog::seekTo(float percent) { | |
160 | if(!seekable) return; | |
161 | ||
162 | lastline = ""; | |
163 | ||
164 | ((SeekLog*)logf)->seekTo(percent); | |
165 | } | |
166 | ||
167 | float RCommitLog::getPercent() { | |
168 | if(seekable) return ((SeekLog*)logf)->getPercent(); | |
169 | ||
170 | return 0.0; | |
171 | } | |
172 | ||
173 | bool RCommitLog::findNextCommit(RCommit& commit, int attempts) { | |
174 | ||
175 | for(int i=0;i<attempts;i++) { | |
176 | RCommit c; | |
177 | ||
178 | if(nextCommit(c)) { | |
179 | commit = c; | |
180 | return true; | |
181 | } | |
182 | } | |
183 | ||
184 | return false; | |
185 | } | |
186 | ||
187 | bool RCommitLog::nextCommit(RCommit& commit) { | |
188 | ||
189 | if(buffered) { | |
190 | commit = lastCommit; | |
191 | buffered = false; | |
192 | return true; | |
193 | } | |
194 | ||
195 | bool success = parseCommit(commit); | |
196 | ||
197 | if(!success) return false; | |
198 | ||
199 | return commit.isValid(); | |
200 | } | |
201 | ||
202 | bool RCommitLog::isFinished() { | |
203 | if(seekable && logf->isFinished()) return true; | |
204 | ||
205 | return false; | |
206 | } | |
207 | ||
208 | //create temp file | |
209 | void RCommitLog::createTempLog() { | |
210 | ||
211 | std::string tempdir; | |
212 | ||
213 | #ifdef _WIN32 | |
214 | DWORD tmplen = GetTempPath(0, ""); | |
215 | ||
216 | if(tmplen == 0) return; | |
217 | ||
218 | std::vector<TCHAR> temp(tmplen+1); | |
219 | ||
220 | tmplen = GetTempPath(static_cast<DWORD>(temp.size()), &temp[0]); | |
221 | ||
222 | if(tmplen == 0 || tmplen >= temp.size()) return; | |
223 | ||
224 | tempdir = std::string(temp.begin(), temp.begin() + static_cast<std::size_t>(tmplen)); | |
225 | tempdir += "\\"; | |
226 | #else | |
227 | tempdir = "/tmp/"; | |
228 | #endif | |
229 | ||
230 | char tmplate[1024]; | |
231 | snprintf(tmplate, 1024, "%sgource-XXXXXX", tempdir.c_str()); | |
232 | ||
233 | #ifdef _WIN32 | |
234 | if(mktemp(tmplate) < 0) return; | |
235 | #else | |
236 | if(mkstemp(tmplate) < 0) return; | |
237 | #endif | |
238 | ||
239 | temp_file = std::string(tmplate); | |
240 | } | |
241 | ||
242 | // RCommitFile | |
243 | ||
244 | RCommitFile::RCommitFile(const std::string& filename, const std::string& action, vec3f colour) { | |
245 | ||
246 | this->filename = munge_utf8(filename); | |
247 | ||
248 | //prepend a root slash | |
249 | if(this->filename[0] != '/') { | |
250 | this->filename.insert(0, 1, '/'); | |
251 | } | |
252 | ||
253 | this->action = action; | |
254 | this->colour = colour; | |
255 | } | |
256 | ||
257 | RCommit::RCommit() { | |
258 | timestamp = 0; | |
259 | } | |
260 | ||
261 | vec3f RCommit::fileColour(const std::string& filename) { | |
262 | ||
263 | size_t slash = filename.rfind('/'); | |
264 | size_t dot = filename.rfind('.'); | |
265 | ||
266 | if(dot != std::string::npos && dot+1<filename.size() && (slash == std::string::npos || slash < dot)) { | |
267 | std::string file_ext = filename.substr(dot+1); | |
268 | ||
269 | return colourHash(file_ext); | |
270 | } else { | |
271 | return vec3f(1.0, 1.0, 1.0); | |
272 | } | |
273 | } | |
274 | ||
275 | void RCommit::addFile(const std::string& filename, const std::string& action) { | |
276 | files.push_back(RCommitFile(filename, action, fileColour(filename))); | |
277 | } | |
278 | ||
279 | void RCommit::addFile(const std::string& filename, const std::string& action, vec3f colour) { | |
280 | files.push_back(RCommitFile(filename, action, colour)); | |
281 | } | |
282 | ||
283 | bool RCommit::isValid() { | |
284 | ||
285 | username = munge_utf8(username); | |
286 | ||
287 | return true; | |
288 | } | |
289 | ||
290 | void RCommit::debug() { | |
291 | debugLog("files:\n"); | |
292 | ||
293 | for(std::list<RCommitFile>::iterator it = files.begin(); it != files.end(); it++) { | |
294 | RCommitFile f = *it; | |
295 | debugLog("%s %s\n", f.action.c_str(), f.filename.c_str()); | |
296 | } | |
297 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef RCOMMIT_LOG_H | |
18 | #define RCOMMIT_LOG_H | |
19 | ||
20 | ||
21 | #include "core/seeklog.h" | |
22 | #include "core/display.h" | |
23 | #include "core/regex.h" | |
24 | #include "core/stringhash.h" | |
25 | #include "core/utf8/utf8.h" | |
26 | ||
27 | #include <time.h> | |
28 | #include <string> | |
29 | #include <list> | |
30 | ||
31 | #include "sys/stat.h" | |
32 | ||
33 | class RCommitFile { | |
34 | public: | |
35 | std::string filename; | |
36 | std::string action; | |
37 | vec3f colour; | |
38 | ||
39 | RCommitFile(const std::string& filename, const std::string& action, vec3f colour); | |
40 | }; | |
41 | ||
42 | class RCommit { | |
43 | vec3f fileColour(const std::string& filename); | |
44 | public: | |
45 | time_t timestamp; | |
46 | std::string username; | |
47 | ||
48 | std::list<RCommitFile> files; | |
49 | ||
50 | bool isValid(); | |
51 | ||
52 | void addFile(const std::string& filename, const std::string& action); | |
53 | void addFile(const std::string& filename, const std::string& action, vec3f colour); | |
54 | ||
55 | RCommit(); | |
56 | void debug(); | |
57 | virtual bool parse(BaseLog* logf) { return false; }; | |
58 | }; | |
59 | ||
60 | class RCommitLog { | |
61 | protected: | |
62 | BaseLog* logf; | |
63 | ||
64 | std::string temp_file; | |
65 | std::string log_command; | |
66 | ||
67 | std::string lastline; | |
68 | ||
69 | bool is_dir; | |
70 | bool success; | |
71 | bool seekable; | |
72 | ||
73 | RCommit lastCommit; | |
74 | bool buffered; | |
75 | ||
76 | bool checkFirstChar(int firstChar, std::istream& stream); | |
77 | ||
78 | void createTempLog(); | |
79 | ||
80 | bool getNextLine(std::string& line); | |
81 | ||
82 | virtual bool parseCommit(RCommit& commit) { return false; }; | |
83 | public: | |
84 | RCommitLog(const std::string& logfile, int firstChar = -1); | |
85 | ~RCommitLog(); | |
86 | ||
87 | void seekTo(float percent); | |
88 | ||
89 | bool checkFormat(); | |
90 | ||
91 | std::string getLogCommand(); | |
92 | ||
93 | bool getCommitAt(float percent, RCommit& commit); | |
94 | bool findNextCommit(RCommit& commit, int attempts); | |
95 | bool nextCommit(RCommit& commit); | |
96 | bool isFinished(); | |
97 | bool isSeekable(); | |
98 | float getPercent(); | |
99 | }; | |
100 | ||
101 | #endif |
32 | 32 | |
33 | 33 | class Bounds2D { |
34 | 34 | public: |
35 | vec2f min; | |
36 | vec2f max; | |
35 | vec2 min; | |
36 | vec2 max; | |
37 | 37 | bool first; |
38 | 38 | |
39 | vec2f centre() const { | |
39 | vec2 centre() const { | |
40 | 40 | return min + (max - min) * 0.5f; |
41 | 41 | } |
42 | 42 | |
53 | 53 | } |
54 | 54 | |
55 | 55 | void reset() { |
56 | min = vec2f(0.0, 0.0); | |
57 | max = vec2f(0.0, 0.0); | |
56 | min = vec2(0.0, 0.0); | |
57 | max = vec2(0.0, 0.0); | |
58 | 58 | first = true; |
59 | 59 | } |
60 | 60 | |
62 | 62 | reset(); |
63 | 63 | } |
64 | 64 | |
65 | Bounds2D(const vec2f& min, const vec2f& max) { | |
65 | Bounds2D(const vec2& min, const vec2& max) { | |
66 | 66 | reset(); |
67 | 67 | update(min); |
68 | 68 | update(max); |
79 | 79 | update(bounds); |
80 | 80 | } |
81 | 81 | |
82 | void set(vec2f point) { | |
82 | void set(vec2 point) { | |
83 | 83 | reset(); |
84 | 84 | update(point); |
85 | 85 | } |
86 | 86 | |
87 | void set(const vec2f& a, const vec2f& b) { | |
87 | void set(const vec2& a, const vec2& b) { | |
88 | 88 | reset(); |
89 | 89 | update(a); |
90 | 90 | update(b); |
91 | 91 | } |
92 | 92 | |
93 | void update(const vec2f& point) { | |
93 | void update(const vec2& point) { | |
94 | 94 | if(first) { |
95 | 95 | min = point; |
96 | 96 | max = point; |
104 | 104 | if(max.y < point.y) max.y = point.y; |
105 | 105 | } |
106 | 106 | |
107 | bool contains(const vec2f& point) const { | |
107 | bool contains(const vec2& point) const { | |
108 | 108 | if(first) return false; |
109 | 109 | |
110 | 110 | if(min.x<=point.x && min.y<=point.y && max.x >= point.x && max.y >= point.y) |
125 | 125 | |
126 | 126 | void draw() const{ |
127 | 127 | glBegin(GL_LINE_STRIP); |
128 | glVertex2fv(min); | |
128 | glVertex2fv(glm::value_ptr(min)); | |
129 | 129 | glVertex2f(max.x, min.y); |
130 | glVertex2fv(max); | |
130 | glVertex2fv(glm::value_ptr(max)); | |
131 | 131 | glVertex2f(min.x, max.y); |
132 | glVertex2fv(min); | |
132 | glVertex2fv(glm::value_ptr(min)); | |
133 | 133 | glEnd(); |
134 | 134 | } |
135 | 135 | }; |
136 | 136 | |
137 | 137 | class Bounds3D { |
138 | 138 | public: |
139 | vec3f min; | |
140 | vec3f max; | |
139 | vec3 min; | |
140 | vec3 max; | |
141 | 141 | bool first; |
142 | 142 | |
143 | 143 | void reset() { |
144 | min = vec3f(0.0, 0.0, 0.0); | |
145 | max = vec3f(0.0, 0.0, 0.0); | |
144 | min = vec3(0.0, 0.0, 0.0); | |
145 | max = vec3(0.0, 0.0, 0.0); | |
146 | 146 | first = true; |
147 | 147 | } |
148 | 148 | |
150 | 150 | reset(); |
151 | 151 | } |
152 | 152 | |
153 | Bounds3D(vec3f min, vec3f max) { | |
153 | Bounds3D(vec3 min, vec3 max) { | |
154 | 154 | reset(); |
155 | 155 | update(min); |
156 | 156 | update(max); |
172 | 172 | return width() * height() * depth(); |
173 | 173 | } |
174 | 174 | |
175 | vec3f centre() { | |
176 | return min + ((max-min) * 0.5); | |
177 | } | |
178 | ||
179 | void update(vec3f point) { | |
175 | vec3 centre() { | |
176 | return min + ((max-min) * 0.5f); | |
177 | } | |
178 | ||
179 | void update(vec3 point) { | |
180 | 180 | if(first) { |
181 | 181 | min = point; |
182 | 182 | max = point; |
192 | 192 | if(max.z < point.z) max.z = point.z; |
193 | 193 | } |
194 | 194 | |
195 | bool contains(vec3f& point) { | |
195 | bool contains(vec3& point) { | |
196 | 196 | if(first) return false; |
197 | 197 | |
198 | 198 | if(min.x<=point.x && min.y<=point.y && min.z<=point.z && max.x >= point.x && max.y >= point.y && max.z >= point.z) |
204 | 204 | void draw() { |
205 | 205 | glColor4f(1.0f, 1.0f, 1.0f, 1.0f); |
206 | 206 | glBegin(GL_LINES); |
207 | glVertex3fv(min); | |
208 | glVertex3fv(max); | |
207 | glVertex3fv(glm::value_ptr(min)); | |
208 | glVertex3fv(glm::value_ptr(max)); | |
209 | 209 | glEnd(); |
210 | 210 | } |
211 | 211 |
0 | /* | |
1 | Copyright (c) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | All rights reserved. | |
3 | ||
4 | Redistribution and use in source and binary forms, with or without | |
5 | modification, are permitted provided that the following conditions | |
6 | are met: | |
7 | 1. Redistributions of source code must retain the above copyright | |
8 | notice, this list of conditions and the following disclaimer. | |
9 | 2. Redistributions in binary form must reproduce the above copyright | |
10 | notice, this list of conditions and the following disclaimer in the | |
11 | documentation and/or other materials provided with the distribution. | |
12 | 3. The name of the author may not be used to endorse or promote products | |
13 | derived from this software without specific prior written permission. | |
14 | ||
15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
16 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | |
26 | ||
27 | #include "camera.h" | |
28 | ||
29 | //Light | |
30 | ||
31 | Light::Light() { | |
32 | } | |
33 | ||
34 | Light::Light(vec3f pos) { | |
35 | this->pos = pos; | |
36 | } | |
37 | ||
38 | void Light::lookAt(vec3f target) { | |
39 | gluLookAt( pos.x, pos.y, pos.z, | |
40 | target.x, target.y, target.z, | |
41 | 0.0f, 1.0f, 0.0f); | |
42 | } | |
43 | ||
44 | void Light::setPos(vec3f pos) { | |
45 | this->pos = pos; | |
46 | } | |
47 | ||
48 | vec3f Light::getPos() { | |
49 | return pos; | |
50 | } | |
51 | ||
52 | //Camera | |
53 | ||
54 | Camera::Camera() { | |
55 | } | |
56 | ||
57 | Camera::Camera(vec3f pos, vec3f target) { | |
58 | fov = 90.0f; | |
59 | znear = 0.1f; | |
60 | zfar = 1000.0f; | |
61 | ||
62 | up = vec3f(0.0, 1.0, 0.0); | |
63 | ||
64 | this->_pos=pos; | |
65 | this->_target=target; | |
66 | reset(); | |
67 | } | |
68 | ||
69 | void Camera::focus() { | |
70 | display.mode3D(fov, znear, zfar); | |
71 | look(); | |
72 | } | |
73 | ||
74 | void Camera::focusOn(vec3f p) { | |
75 | display.mode3D(fov, znear, zfar); | |
76 | lookAt(p); | |
77 | } | |
78 | ||
79 | ||
80 | void Camera::look() { | |
81 | lookAt(target); | |
82 | } | |
83 | ||
84 | void Camera::lookAt(vec3f target) { | |
85 | gluLookAt( pos.x, pos.y, pos.z, | |
86 | target.x, target.y, target.z, | |
87 | up.x, up.y, up.z); | |
88 | } | |
89 | ||
90 | vec3f Camera::getUp() { | |
91 | return up; | |
92 | } | |
93 | ||
94 | float Camera::getZNear() { | |
95 | return znear; | |
96 | } | |
97 | ||
98 | float Camera::getZFar() { | |
99 | return zfar; | |
100 | } | |
101 | ||
102 | float Camera::getFov() { | |
103 | return fov; | |
104 | } | |
105 | ||
106 | void Camera::setUp(vec3f up) { | |
107 | this->up = up; | |
108 | } | |
109 | ||
110 | void Camera::setFov(float fov) { | |
111 | this->fov = fov; | |
112 | } | |
113 | ||
114 | void Camera::setZNear(float znear) { | |
115 | this->znear = znear; | |
116 | } | |
117 | ||
118 | void Camera::setZFar(float zfar) { | |
119 | this->zfar = zfar; | |
120 | } | |
121 | ||
122 | void Camera::setPos(vec3f pos, bool keepangle) { | |
123 | if(keepangle) { | |
124 | vec3f dir = target - this->pos; | |
125 | this->pos = pos; | |
126 | this->target = pos + dir; | |
127 | } else { | |
128 | this->pos = pos; | |
129 | } | |
130 | } | |
131 | ||
132 | void Camera::setTarget(vec3f target) { | |
133 | this->target = target; | |
134 | } | |
135 | ||
136 | vec3f Camera::getPos() { | |
137 | return pos; | |
138 | } | |
139 | ||
140 | vec3f Camera::getTarget() { | |
141 | return target; | |
142 | } | |
143 | ||
144 | void Camera::reset() { | |
145 | pos = _pos; | |
146 | target = _target; | |
147 | } | |
148 | ||
149 | // CameraEvent | |
150 | CameraEvent::CameraEvent() { | |
151 | finished=false; | |
152 | } | |
153 | ||
154 | bool CameraEvent::isFinished() { | |
155 | return finished; | |
156 | } | |
157 | ||
158 | // CameraMoveEvent | |
159 | ||
160 | CameraMoveEvent::CameraMoveEvent(float fov, vec3f pos, vec3f target, float duration) : CameraEvent() { | |
161 | this->fov = fov; | |
162 | this->pos = pos; | |
163 | this->target = target; | |
164 | this->duration = duration; | |
165 | this->elapsed = 0.0; | |
166 | } | |
167 | ||
168 | void CameraMoveEvent::prepare(Camera* cam) { | |
169 | this->elapsed = 0.0; | |
170 | this->finished = false; | |
171 | this->old_fov = cam->getFov(); | |
172 | this->old_pos = cam->getPos(); | |
173 | this->old_target = cam->getTarget(); | |
174 | } | |
175 | ||
176 | void CameraMoveEvent::logic(float dt, Camera* cam) { | |
177 | elapsed += dt; | |
178 | ||
179 | if(duration <= 0.0 || elapsed >= duration) { | |
180 | cam->setFov(fov); | |
181 | cam->setPos(pos); | |
182 | cam->setTarget(target); | |
183 | finished=true; | |
184 | return; | |
185 | } | |
186 | ||
187 | float pc = elapsed/duration; | |
188 | ||
189 | float f = old_fov * (1.0 - pc) + fov * pc; | |
190 | vec3f p = old_pos * (1.0 - pc) + pos * pc; | |
191 | vec3f t = old_target * (1.0 - pc) + target * pc; | |
192 | ||
193 | cam->setFov(f); | |
194 | cam->setPos(p); | |
195 | cam->setTarget(t); | |
196 | } | |
197 | ||
198 | // Camera Event Path | |
199 | ||
200 | CameraPath::CameraPath(Camera* cam, bool loop) { | |
201 | this->cam = cam; | |
202 | current = 0; | |
203 | current_index = -1; | |
204 | this->loop = loop; | |
205 | finished=false; | |
206 | } | |
207 | ||
208 | CameraPath::~CameraPath() { | |
209 | clear(); | |
210 | } | |
211 | ||
212 | bool CameraPath::isFinished() { | |
213 | return finished; | |
214 | } | |
215 | ||
216 | void CameraPath::reset() { | |
217 | finished=false; | |
218 | current_index = -1; | |
219 | current = 0; | |
220 | } | |
221 | ||
222 | void CameraPath::clear() { | |
223 | for(std::vector<CameraEvent*>::iterator it = events.begin(); it != events.end(); it++) { | |
224 | delete *it; | |
225 | } | |
226 | events.clear(); | |
227 | } | |
228 | ||
229 | void CameraPath::addEvent(CameraEvent* ce) { | |
230 | events.push_back(ce); | |
231 | } | |
232 | ||
233 | void CameraPath::logic(float dt) { | |
234 | if(finished || events.size() == 0 && current==0) return; | |
235 | ||
236 | if(current == 0) { | |
237 | if(loop) { | |
238 | current_index = (current_index + 1) % events.size(); | |
239 | } else { | |
240 | current_index++; | |
241 | ||
242 | if(current_index >= events.size()) { | |
243 | finished=true; | |
244 | return; | |
245 | } | |
246 | } | |
247 | ||
248 | current = events[current_index]; | |
249 | ||
250 | current->prepare(cam); | |
251 | } | |
252 | ||
253 | current->logic(dt, cam); | |
254 | ||
255 | if(current->isFinished()) { | |
256 | current = 0; | |
257 | } | |
258 | } |
0 | /* | |
1 | Copyright (c) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | All rights reserved. | |
3 | ||
4 | Redistribution and use in source and binary forms, with or without | |
5 | modification, are permitted provided that the following conditions | |
6 | are met: | |
7 | 1. Redistributions of source code must retain the above copyright | |
8 | notice, this list of conditions and the following disclaimer. | |
9 | 2. Redistributions in binary form must reproduce the above copyright | |
10 | notice, this list of conditions and the following disclaimer in the | |
11 | documentation and/or other materials provided with the distribution. | |
12 | 3. The name of the author may not be used to endorse or promote products | |
13 | derived from this software without specific prior written permission. | |
14 | ||
15 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
16 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
17 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
18 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
19 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
20 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
24 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
25 | */ | |
26 | ||
27 | #ifndef CAMERA_H | |
28 | #define CAMERA_H | |
29 | ||
30 | #include "display.h" | |
31 | ||
32 | #include <vector> | |
33 | ||
34 | class Frustum; | |
35 | ||
36 | class Light { | |
37 | vec3f pos; | |
38 | public: | |
39 | Light(); | |
40 | Light(vec3f pos); | |
41 | void lookAt(vec3f target); | |
42 | ||
43 | void setPos(vec3f pos); | |
44 | vec3f getPos(); | |
45 | }; | |
46 | ||
47 | class Camera { | |
48 | protected: | |
49 | vec3f _pos; | |
50 | vec3f _target; | |
51 | vec3f pos; | |
52 | vec3f target; | |
53 | ||
54 | vec3f up; | |
55 | ||
56 | float fov; | |
57 | float znear; | |
58 | float zfar; | |
59 | ||
60 | public: | |
61 | Camera(); | |
62 | Camera(vec3f pos, vec3f target = vec3f(0,0,0)); | |
63 | ||
64 | void setPos(vec3f pos, bool keepangle = false); | |
65 | ||
66 | void setUp(vec3f up); | |
67 | void setFov(float fov); | |
68 | void setZNear(float znear); | |
69 | void setZFar(float zfar); | |
70 | ||
71 | void setTarget(vec3f target); | |
72 | ||
73 | vec3f getTarget(); | |
74 | vec3f getPos(); | |
75 | ||
76 | vec3f getUp(); | |
77 | float getFov(); | |
78 | float getZNear(); | |
79 | float getZFar(); | |
80 | ||
81 | ||
82 | void reset(); | |
83 | void look(); | |
84 | void lookAt(vec3f target); | |
85 | ||
86 | void focus(); | |
87 | void focusOn(vec3f p); | |
88 | }; | |
89 | ||
90 | class CameraEvent { | |
91 | protected: | |
92 | bool finished; | |
93 | public: | |
94 | CameraEvent(); | |
95 | bool isFinished(); | |
96 | virtual void prepare(Camera* cam) {}; | |
97 | virtual void logic(float dt, Camera* cam) {}; | |
98 | }; | |
99 | ||
100 | class CameraMoveEvent : public CameraEvent { | |
101 | ||
102 | float duration; | |
103 | float elapsed; | |
104 | ||
105 | float fov; | |
106 | vec3f pos; | |
107 | vec3f target; | |
108 | float old_fov; | |
109 | vec3f old_pos; | |
110 | vec3f old_target; | |
111 | ||
112 | public: | |
113 | CameraMoveEvent(float fov, vec3f pos, vec3f target, float duration = 0.0); | |
114 | void prepare(Camera* cam); | |
115 | void logic(float dt, Camera* cam); | |
116 | }; | |
117 | ||
118 | class CameraPath { | |
119 | Camera* cam; | |
120 | CameraEvent* current; | |
121 | int current_index; | |
122 | ||
123 | bool loop; | |
124 | bool finished; | |
125 | ||
126 | std::vector<CameraEvent*> events; | |
127 | public: | |
128 | CameraPath(Camera* cam, bool loop = true); | |
129 | ~CameraPath(); | |
130 | void addEvent(CameraEvent* ce); | |
131 | void clear(); | |
132 | void logic(float dt); | |
133 | void reset(); | |
134 | bool isFinished(); | |
135 | }; | |
136 | ||
137 | #endif |
25 | 25 | // parse key value pair, seperated by an equals sign, removing white space on key and front of the value |
26 | 26 | Regex ConfFile_key_value("^\\s*([^=\\s]+)\\s*=\\s*([^\\s].*)?$"); |
27 | 27 | |
28 | // vec2f, vec3f, or vec4f with liberal allowance for whitespace | |
28 | // vec2, vec3, or vec4 with liberal allowance for whitespace | |
29 | 29 | Regex ConfFile_vec2_value("^\\s*vec2\\(\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*\\)\\s*$"); |
30 | 30 | Regex ConfFile_vec3_value("^\\s*vec3\\(\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*\\)\\s*$"); |
31 | 31 | Regex ConfFile_vec4_value("^\\s*vec4\\(\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*,\\s*(-?[0-9.]+)\\s*\\)\\s*$"); |
58 | 58 | setFloat(value); |
59 | 59 | } |
60 | 60 | |
61 | ConfEntry::ConfEntry(const std::string& name, vec2f value) { | |
61 | ConfEntry::ConfEntry(const std::string& name, vec2 value) { | |
62 | 62 | this->name = name; |
63 | 63 | setVec2(value); |
64 | 64 | } |
65 | 65 | |
66 | ConfEntry::ConfEntry(const std::string& name, vec3f value) { | |
66 | ConfEntry::ConfEntry(const std::string& name, vec3 value) { | |
67 | 67 | this->name = name; |
68 | 68 | setVec3(value); |
69 | 69 | } |
70 | 70 | |
71 | ConfEntry::ConfEntry(const std::string& name, vec4f value) { | |
71 | ConfEntry::ConfEntry(const std::string& name, vec4 value) { | |
72 | 72 | this->name = name; |
73 | 73 | setVec4(value); |
74 | 74 | } |
99 | 99 | this->value = std::string(value ? "yes" : "no"); |
100 | 100 | } |
101 | 101 | |
102 | void ConfEntry::setVec2(vec2f value) { | |
102 | void ConfEntry::setVec2(vec2 value) { | |
103 | 103 | char vectostr[256]; |
104 | 104 | sprintf(vectostr, "vec2(%.5f, %.5f)", value.x, value.y); |
105 | 105 | |
106 | 106 | this->value = std::string(vectostr); |
107 | 107 | } |
108 | 108 | |
109 | void ConfEntry::setVec3(vec3f value) { | |
109 | void ConfEntry::setVec3(vec3 value) { | |
110 | 110 | char vectostr[256]; |
111 | 111 | sprintf(vectostr, "vec3(%.5f, %.5f, %.5f)", value.x, value.y, value.z); |
112 | 112 | |
113 | 113 | this->value = std::string(vectostr); |
114 | 114 | } |
115 | 115 | |
116 | void ConfEntry::setVec4(vec4f value) { | |
116 | void ConfEntry::setVec4(vec4 value) { | |
117 | 117 | char vectostr[256]; |
118 | 118 | sprintf(vectostr, "vec4(%.5f, %.5f, %.5f, %.5f)", value.x, value.y, value.z, value.w); |
119 | 119 | |
176 | 176 | return false; |
177 | 177 | } |
178 | 178 | |
179 | vec2f ConfEntry::getVec2() { | |
179 | vec2 ConfEntry::getVec2() { | |
180 | 180 | |
181 | 181 | std::vector<std::string> matches; |
182 | 182 | |
183 | 183 | if(ConfFile_vec2_value.match(value, &matches)) { |
184 | return vec2f(atof(matches[0].c_str()), atof(matches[1].c_str())); | |
185 | } | |
186 | ||
187 | return vec2f(0.0, 0.0); | |
184 | return vec2(atof(matches[0].c_str()), atof(matches[1].c_str())); | |
185 | } | |
186 | ||
187 | return vec2(0.0, 0.0); | |
188 | 188 | } |
189 | 189 | |
190 | 190 | bool ConfEntry::isVec3() { |
192 | 192 | return false; |
193 | 193 | } |
194 | 194 | |
195 | vec3f ConfEntry::getVec3() { | |
195 | vec3 ConfEntry::getVec3() { | |
196 | 196 | |
197 | 197 | std::vector<std::string> matches; |
198 | 198 | |
199 | 199 | if(ConfFile_vec3_value.match(value, &matches)) { |
200 | return vec3f(atof(matches[0].c_str()), atof(matches[1].c_str()), atof(matches[2].c_str())); | |
201 | } | |
202 | ||
203 | return vec3f(0.0, 0.0, 0.0); | |
200 | return vec3(atof(matches[0].c_str()), atof(matches[1].c_str()), atof(matches[2].c_str())); | |
201 | } | |
202 | ||
203 | return vec3(0.0, 0.0, 0.0); | |
204 | 204 | } |
205 | 205 | |
206 | 206 | bool ConfEntry::isVec4() { |
208 | 208 | return false; |
209 | 209 | } |
210 | 210 | |
211 | vec4f ConfEntry::getVec4() { | |
211 | vec4 ConfEntry::getVec4() { | |
212 | 212 | |
213 | 213 | std::vector<std::string> matches; |
214 | 214 | |
215 | 215 | if(ConfFile_vec4_value.match(value, &matches)) { |
216 | return vec4f(atof(matches[0].c_str()), atof(matches[1].c_str()), atof(matches[2].c_str()), atof(matches[3].c_str()) ); | |
217 | } | |
218 | ||
219 | return vec4f(0.0, 0.0, 0.0, 0.0); | |
216 | return vec4(atof(matches[0].c_str()), atof(matches[1].c_str()), atof(matches[2].c_str()), atof(matches[3].c_str()) ); | |
217 | } | |
218 | ||
219 | return vec4(0.0, 0.0, 0.0, 0.0); | |
220 | 220 | } |
221 | 221 | |
222 | 222 | //ConfSection |
373 | 373 | return false; |
374 | 374 | } |
375 | 375 | |
376 | vec3f ConfSection::getVec3(const std::string& key) { | |
376 | vec3 ConfSection::getVec3(const std::string& key) { | |
377 | 377 | ConfEntry* entry = getEntry(key); |
378 | 378 | |
379 | 379 | if(entry) return entry->getVec3(); |
380 | 380 | |
381 | return vec3f(0.0, 0.0, 0.0); | |
382 | } | |
383 | ||
384 | vec4f ConfSection::getVec4(const std::string& key) { | |
381 | return vec3(0.0, 0.0, 0.0); | |
382 | } | |
383 | ||
384 | vec4 ConfSection::getVec4(const std::string& key) { | |
385 | 385 | ConfEntry* entry = getEntry(key); |
386 | 386 | |
387 | 387 | if(entry) return entry->getVec4(); |
388 | 388 | |
389 | return vec4f(0.0, 0.0, 0.0, 0.0); | |
389 | return vec4(0.0, 0.0, 0.0, 0.0); | |
390 | 390 | } |
391 | 391 | |
392 | 392 | void ConfSection::print(std::ostream& out) { |
730 | 730 | return false; |
731 | 731 | } |
732 | 732 | |
733 | vec3f ConfFile::getVec3(const std::string& section, const std::string& key) { | |
733 | vec3 ConfFile::getVec3(const std::string& section, const std::string& key) { | |
734 | 734 | ConfEntry* entry = getEntry(section, key); |
735 | 735 | |
736 | 736 | if(entry) return entry->getVec3(); |
737 | 737 | |
738 | return vec3f(0.0, 0.0, 0.0); | |
739 | } | |
740 | ||
741 | vec4f ConfFile::getVec4(const std::string& section, const std::string& key) { | |
738 | return vec3(0.0, 0.0, 0.0); | |
739 | } | |
740 | ||
741 | vec4 ConfFile::getVec4(const std::string& section, const std::string& key) { | |
742 | 742 | ConfEntry* entry = getEntry(section, key); |
743 | 743 | |
744 | 744 | if(entry) return entry->getVec4(); |
745 | 745 | |
746 | return vec4f(0.0, 0.0, 0.0, 0.0); | |
746 | return vec4(0.0, 0.0, 0.0, 0.0); | |
747 | 747 | } |
748 | 748 | |
749 | 749 | void ConfFile::unknownOptionException(ConfEntry* entry) { |
51 | 51 | ConfEntry(const std::string& name, int value); |
52 | 52 | ConfEntry(const std::string& name, float value); |
53 | 53 | ConfEntry(const std::string& name, bool value); |
54 | ConfEntry(const std::string& name, vec2f value); | |
55 | ConfEntry(const std::string& name, vec3f value); | |
56 | ConfEntry(const std::string& name, vec4f value); | |
54 | ConfEntry(const std::string& name, vec2 value); | |
55 | ConfEntry(const std::string& name, vec3 value); | |
56 | ConfEntry(const std::string& name, vec4 value); | |
57 | 57 | |
58 | 58 | void setName(const std::string& name); |
59 | 59 | |
61 | 61 | void setFloat(float value); |
62 | 62 | void setInt(int value); |
63 | 63 | void setBool(bool value); |
64 | void setVec2(vec2f value); | |
65 | void setVec3(vec3f value); | |
66 | void setVec4(vec4f value); | |
64 | void setVec2(vec2 value); | |
65 | void setVec3(vec3 value); | |
66 | void setVec4(vec4 value); | |
67 | 67 | |
68 | 68 | bool hasValue(); |
69 | 69 | |
74 | 74 | int getInt(); |
75 | 75 | float getFloat(); |
76 | 76 | bool getBool(); |
77 | vec2f getVec2(); | |
78 | vec3f getVec3(); | |
79 | vec4f getVec4(); | |
77 | vec2 getVec2(); | |
78 | vec3 getVec3(); | |
79 | vec4 getVec4(); | |
80 | 80 | |
81 | 81 | bool isFloat(); |
82 | 82 | bool isInt(); |
120 | 120 | int getInt(const std::string& key); |
121 | 121 | float getFloat(const std::string& key); |
122 | 122 | bool getBool(const std::string& key); |
123 | vec3f getVec3(const std::string& key); | |
124 | vec4f getVec4(const std::string& key); | |
123 | vec3 getVec3(const std::string& key); | |
124 | vec4 getVec4(const std::string& key); | |
125 | 125 | |
126 | 126 | void print(std::ostream& out); |
127 | 127 | |
175 | 175 | int getInt(const std::string& section, const std::string& key); |
176 | 176 | float getFloat(const std::string& section, const std::string& key); |
177 | 177 | bool getBool(const std::string& section, const std::string& key); |
178 | vec3f getVec3(const std::string& section, const std::string& key); | |
179 | vec4f getVec4(const std::string& section, const std::string& key); | |
178 | vec3 getVec3(const std::string& section, const std::string& key); | |
179 | vec4 getVec4(const std::string& section, const std::string& key); | |
180 | 180 | |
181 | 181 | static void trim(std::string& value); |
182 | 182 |
32 | 32 | SDLAppDisplay display; |
33 | 33 | |
34 | 34 | SDLAppDisplay::SDLAppDisplay() { |
35 | clearColour = vec4f(0.0f,0.0f,0.0f,1.0f); | |
35 | clearColour = vec4(0.0f,0.0f,0.0f,1.0f); | |
36 | 36 | enable_shaders=false; |
37 | 37 | enable_alpha=false; |
38 | 38 | vsync=false; |
39 | resizable=false; | |
40 | frameless=false; | |
39 | 41 | multi_sample = 0; |
42 | width = 0; | |
43 | height = 0; | |
44 | desktop_width = 0; | |
45 | desktop_height = 0; | |
46 | windowed_width = 0; | |
47 | windowed_height = 0; | |
48 | #if SDL_VERSION_ATLEAST(1,3,0) | |
49 | sdl_window = 0; | |
50 | gl_context = 0; | |
51 | #else | |
52 | surface = 0; | |
53 | #endif | |
54 | ||
40 | 55 | } |
41 | 56 | |
42 | 57 | SDLAppDisplay::~SDLAppDisplay() { |
43 | 58 | } |
44 | 59 | |
45 | void SDLAppDisplay::setClearColour(vec3f colour) { | |
46 | setClearColour(vec4f(colour, enable_alpha ? 0.0f : 1.0f)); | |
47 | } | |
48 | ||
49 | void SDLAppDisplay::setClearColour(vec4f colour) { | |
60 | void SDLAppDisplay::setClearColour(vec3 colour) { | |
61 | setClearColour(vec4(colour, enable_alpha ? 0.0f : 1.0f)); | |
62 | } | |
63 | ||
64 | void SDLAppDisplay::setClearColour(vec4 colour) { | |
50 | 65 | clearColour = colour; |
51 | 66 | } |
52 | 67 | |
53 | 68 | int SDLAppDisplay::SDLFlags(bool fullscreen) { |
54 | 69 | int flags = SDL_OPENGL | SDL_HWSURFACE | SDL_ANYFORMAT | SDL_DOUBLEBUF; |
70 | if (frameless) flags |= SDL_NOFRAME; | |
71 | if (resizable && !fullscreen) flags |= SDL_RESIZABLE; | |
55 | 72 | if (fullscreen) flags |= SDL_FULLSCREEN; |
73 | ||
74 | //SDL 1.3 vsync | |
75 | #ifdef SDL_RENDERER_PRESENTVSYNC | |
76 | if (!vsync) flags |= SDL_RENDERER_PRESENTVSYNC; | |
77 | #endif | |
78 | ||
56 | 79 | return flags; |
57 | 80 | } |
58 | 81 | |
62 | 85 | |
63 | 86 | void SDLAppDisplay::enableShaders(bool enable) { |
64 | 87 | enable_shaders = enable; |
88 | } | |
89 | ||
90 | void SDLAppDisplay::enableResize(bool resizable) { | |
91 | this->resizable = resizable; | |
65 | 92 | } |
66 | 93 | |
67 | 94 | void SDLAppDisplay::enableAlpha(bool enable) { |
91 | 118 | return value==1; |
92 | 119 | } |
93 | 120 | |
94 | ||
95 | void SDLAppDisplay::init(std::string window_title, int width, int height, bool fullscreen) { | |
96 | ||
97 | this->fullscreen = fullscreen; | |
121 | void SDLAppDisplay::setVideoMode(int width, int height, bool fullscreen) { | |
122 | #if SDL_VERSION_ATLEAST(1,3,0) | |
123 | ||
124 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
125 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); | |
126 | ||
127 | Uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; | |
128 | if(resizable && !fullscreen) flags |= SDL_WINDOW_RESIZABLE; | |
129 | if(fullscreen) flags |= SDL_WINDOW_FULLSCREEN; | |
130 | ||
131 | if(gl_context != 0) SDL_GL_DeleteContext(gl_context); | |
132 | if(sdl_window != 0) SDL_DestroyWindow(sdl_window); | |
133 | ||
134 | sdl_window = SDL_CreateWindow( | |
135 | gSDLAppTitle.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, | |
136 | width, height, flags); | |
137 | ||
138 | ||
139 | if (!sdl_window) { | |
140 | std::string sdlerr(SDL_GetError()); | |
141 | throw SDLInitException(sdlerr); | |
142 | } | |
143 | ||
144 | gl_context = SDL_GL_CreateContext(sdl_window); | |
145 | ||
146 | if(vsync) SDL_GL_SetSwapInterval(1); | |
147 | #else | |
148 | int depth = 32; | |
98 | 149 | |
99 | 150 | int flags = SDLFlags(fullscreen); |
100 | int depth = 32; | |
101 | ||
102 | if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) { | |
103 | throw SDLInitException(SDL_GetError()); | |
104 | } | |
105 | ||
106 | atexit(SDL_Quit); | |
107 | ||
108 | SDL_EnableUNICODE(1); | |
109 | ||
110 | //vsync | |
151 | ||
111 | 152 | if(vsync) SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1); |
112 | 153 | else SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0); |
113 | 154 | |
152 | 193 | throw SDLInitException(sdlerr); |
153 | 194 | } |
154 | 195 | } |
196 | #endif | |
197 | ||
198 | setupExtensions(); | |
199 | } | |
200 | ||
201 | void SDLAppDisplay::toggleFullscreen() { | |
202 | ||
203 | int width = this->width; | |
204 | int height = this->height; | |
205 | ||
206 | if(!fullscreen) { | |
207 | ||
208 | //save windowed width and height | |
209 | windowed_width = width; | |
210 | windowed_height = height; | |
211 | ||
212 | int fullscreen_width = desktop_width; | |
213 | int fullscreen_height = desktop_height; | |
214 | ||
215 | float aspect_ratio = fullscreen_width / (float) fullscreen_height; | |
216 | ||
217 | // if the aspect ratio suggests the person is using multiple monitors | |
218 | // find a supported resolution with a lower aspect ratio with the same | |
219 | // fullscreen height | |
220 | ||
221 | #if SDL_VERSION_ATLEAST(1,3,0) | |
222 | // TODO: do something with the 1.3 API here | |
223 | #else | |
224 | if(aspect_ratio >= 2.5) { | |
225 | ||
226 | SDL_Rect** modes = SDL_ListModes(0, SDLFlags(true)); | |
227 | ||
228 | if(modes != (SDL_Rect**)0 && modes != (SDL_Rect**)-1) { | |
229 | ||
230 | for (int i=0; modes[i]; i++) { | |
231 | if(modes[i]->h == fullscreen_height && (modes[i]->w/(float)modes[i]->h) < 2.5) { | |
232 | fullscreen_width = modes[i]->w; | |
233 | break; | |
234 | } | |
235 | } | |
236 | } | |
237 | } | |
238 | #endif | |
239 | ||
240 | width = fullscreen_width; | |
241 | height = fullscreen_height; | |
242 | ||
243 | } else { | |
244 | //switch back to window dimensions, if known | |
245 | if(windowed_width != 0) { | |
246 | width = windowed_width; | |
247 | height = windowed_height; | |
248 | } | |
249 | } | |
250 | ||
251 | fullscreen = !fullscreen; | |
252 | ||
253 | setVideoMode(width, height, fullscreen); | |
254 | ||
255 | int resized_width, resized_height; | |
256 | ||
257 | #if SDL_VERSION_ATLEAST(1,3,0) | |
258 | SDL_GetWindowSize(sdl_window, &resized_width, &resized_height); | |
259 | #else | |
260 | const SDL_VideoInfo* display_info = SDL_GetVideoInfo(); | |
261 | ||
262 | resized_width = display_info->current_w; | |
263 | resized_height = display_info->current_h; | |
264 | #endif | |
265 | ||
266 | //set viewport to match what we ended up on | |
267 | glViewport(0, 0, resized_width, resized_height); | |
268 | ||
269 | this->width = resized_width; | |
270 | this->height = resized_height; | |
271 | } | |
272 | ||
273 | void SDLAppDisplay::resize(int width, int height) { | |
274 | ||
275 | int resized_width, resized_height; | |
276 | ||
277 | #if SDL_VERSION_ATLEAST(1,3,0) | |
278 | SDL_GetWindowSize(sdl_window, &resized_width, &resized_height); | |
279 | #else | |
280 | setVideoMode(width, height, fullscreen); | |
281 | ||
282 | const SDL_VideoInfo* display_info = SDL_GetVideoInfo(); | |
283 | ||
284 | resized_width = display_info->current_w; | |
285 | resized_height = display_info->current_h; | |
286 | #endif | |
287 | ||
288 | //set viewport to match what we ended up on | |
289 | glViewport(0, 0, resized_width, resized_height); | |
290 | ||
291 | this->width = resized_width; | |
292 | this->height = resized_height; | |
293 | } | |
294 | ||
295 | void SDLAppDisplay::init(std::string window_title, int width, int height, bool fullscreen) { | |
296 | ||
297 | if(SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) { | |
298 | throw SDLInitException(SDL_GetError()); | |
299 | } | |
300 | ||
301 | const SDL_VideoInfo* display_info = SDL_GetVideoInfo(); | |
302 | ||
303 | //save the desktop resolution | |
304 | desktop_width = display_info->current_w; | |
305 | desktop_height = display_info->current_h; | |
306 | ||
307 | atexit(SDL_Quit); | |
308 | ||
309 | SDL_EnableUNICODE(1); | |
310 | ||
311 | #if SDL_VERSION_ATLEAST(1,3,0) | |
312 | #else | |
313 | SDL_WM_SetCaption(window_title.c_str(),0); | |
314 | #endif | |
315 | ||
316 | setVideoMode(width, height, fullscreen); | |
155 | 317 | |
156 | 318 | //get actual opengl viewport |
157 | 319 | GLint viewport[4]; |
158 | 320 | glGetIntegerv( GL_VIEWPORT, viewport ); |
159 | 321 | |
160 | this->width = viewport[2]; | |
161 | this->height = viewport[3]; | |
162 | ||
163 | setupExtensions(); | |
164 | ||
165 | SDL_WM_SetCaption(window_title.c_str(),0); | |
322 | this->width = viewport[2]; | |
323 | this->height = viewport[3]; | |
324 | this->fullscreen = fullscreen; | |
166 | 325 | } |
167 | 326 | |
168 | 327 | void SDLAppDisplay::quit() { |
328 | ||
329 | #if SDL_VERSION_ATLEAST(1,3,0) | |
330 | if(gl_context != 0) SDL_GL_DeleteContext(gl_context); | |
331 | if(sdl_window != 0) SDL_DestroyWindow(sdl_window); | |
332 | #endif | |
333 | ||
169 | 334 | texturemanager.purge(); |
170 | 335 | shadermanager.purge(); |
171 | 336 | fontmanager.purge(); |
173 | 338 | } |
174 | 339 | |
175 | 340 | void SDLAppDisplay::update() { |
341 | #if SDL_VERSION_ATLEAST(1,3,0) | |
342 | SDL_GL_SwapWindow(sdl_window); | |
343 | #else | |
176 | 344 | SDL_GL_SwapBuffers(); |
345 | #endif | |
177 | 346 | } |
178 | 347 | |
179 | 348 | void SDLAppDisplay::clear() { |
215 | 384 | glPopMatrix(); |
216 | 385 | } |
217 | 386 | |
218 | vec4f SDLAppDisplay::currentColour() { | |
219 | vec4f colour; | |
220 | glGetFloatv(GL_CURRENT_COLOR, colour); | |
221 | return colour; | |
222 | } | |
223 | ||
224 | void SDLAppDisplay::checkGLErrors() { | |
225 | //TODO | |
226 | } | |
227 | ||
228 | void SDLAppDisplay::fullScreenQuad(bool coord_flip) { | |
229 | ||
230 | int y1 = coord_flip ? 0 : 1; | |
231 | int y2 = coord_flip ? 1 : 0; | |
232 | ||
233 | glBegin(GL_QUADS); | |
234 | glTexCoord2i(0,y1); | |
235 | glVertex2f(0, 0); | |
236 | ||
237 | glTexCoord2i(1,y1); | |
238 | glVertex2i(display.width, 0); | |
239 | ||
240 | glTexCoord2i(1,y2); | |
241 | glVertex2i(display.width, display.height); | |
242 | ||
243 | glTexCoord2i(0,y2); | |
244 | glVertex2i(0, display.height); | |
245 | glEnd(); | |
246 | } | |
247 | ||
248 | void SDLAppDisplay::renderToTexture(GLuint target, int width, int height, GLenum format) { | |
249 | glEnable(GL_TEXTURE_2D); | |
250 | glBindTexture(GL_TEXTURE_2D, target); | |
251 | glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, width, height, 0); | |
252 | } | |
253 | ||
254 | GLuint SDLAppDisplay::emptyTexture(int width, int height, GLenum format) { | |
255 | GLuint textureid; | |
256 | ||
257 | glEnable(GL_TEXTURE_2D); | |
258 | ||
259 | glGenTextures(1, &textureid); | |
260 | glBindTexture(GL_TEXTURE_2D, textureid); | |
261 | ||
262 | glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, | |
263 | GL_RGBA, GL_UNSIGNED_BYTE, 0); | |
264 | ||
265 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); | |
266 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); | |
267 | ||
268 | return textureid; | |
269 | } | |
270 | ||
271 | GLuint SDLAppDisplay::createTexture(int width, int height, bool mipmaps, bool clamp, bool trilinear, GLenum format, unsigned int* data) { | |
272 | ||
273 | GLuint textureid; | |
274 | ||
275 | glGenTextures(1, &textureid); | |
276 | glBindTexture(GL_TEXTURE_2D, textureid); | |
277 | ||
278 | if(mipmaps) { | |
279 | gluBuild2DMipmaps(GL_TEXTURE_2D, 4, width, height, format, GL_UNSIGNED_BYTE, data); | |
280 | } else { | |
281 | glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, format, GL_UNSIGNED_BYTE, data); | |
282 | } | |
283 | ||
284 | //GL_LINEAR_MIPMAP_LINEAR - Trilinear | |
285 | //GL_LINEAR_MIPMAP_NEAREST - Bilinear | |
286 | ||
287 | if(trilinear) { | |
288 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); | |
289 | } else { | |
290 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST); | |
291 | } | |
292 | ||
293 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST_MIPMAP_NEAREST); | |
294 | ||
295 | if(clamp) { | |
296 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
297 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
298 | } | |
299 | ||
300 | return textureid; | |
301 | } | |
302 | ||
303 | vec3f SDLAppDisplay::project(vec3f pos) { | |
387 | vec4 SDLAppDisplay::currentColour() { | |
388 | vec4 colour; | |
389 | glGetFloatv(GL_CURRENT_COLOR, glm::value_ptr(colour)); | |
390 | return colour; | |
391 | } | |
392 | ||
393 | vec3 SDLAppDisplay::project(vec3 pos) { | |
304 | 394 | GLint viewport[4]; |
305 | 395 | GLdouble modelview[16]; |
306 | 396 | GLdouble projection[16]; |
314 | 404 | |
315 | 405 | winY = (float)viewport[3] - winY; |
316 | 406 | |
317 | return vec3f((float) winX, (float) winY, (float) winZ); | |
318 | } | |
319 | ||
320 | vec3f SDLAppDisplay::unproject(vec2f pos) { | |
407 | return vec3((float) winX, (float) winY, (float) winZ); | |
408 | } | |
409 | ||
410 | vec3 SDLAppDisplay::unproject(vec2 pos) { | |
321 | 411 | GLint viewport[4]; |
322 | 412 | GLdouble modelview[16]; |
323 | 413 | GLdouble projection[16]; |
333 | 423 | glReadPixels( int(winX), int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ ); |
334 | 424 | gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ); |
335 | 425 | |
336 | return vec3f((float) posX, (float) posY, (float) posZ); | |
337 | } | |
426 | return vec3((float) posX, (float) posY, (float) posZ); | |
427 | } |
54 | 54 | }; |
55 | 55 | |
56 | 56 | class SDLAppDisplay { |
57 | SDL_Surface *surface; | |
58 | 57 | |
59 | 58 | bool enable_shaders; |
60 | 59 | bool enable_alpha; |
60 | bool resizable; | |
61 | bool frameless; | |
61 | 62 | bool vsync; |
62 | 63 | |
63 | 64 | int multi_sample; |
66 | 67 | void setupExtensions(); |
67 | 68 | public: |
68 | 69 | int width, height; |
70 | int desktop_width, desktop_height; | |
71 | int windowed_width, windowed_height; | |
72 | ||
73 | #if SDL_VERSION_ATLEAST(1,3,0) | |
74 | SDL_Window* sdl_window; | |
75 | SDL_GLContext gl_context; | |
76 | #else | |
77 | SDL_Surface *surface; | |
78 | #endif | |
79 | ||
69 | 80 | bool fullscreen; |
70 | vec4f clearColour; | |
81 | vec4 clearColour; | |
71 | 82 | |
72 | 83 | SDLAppDisplay(); |
73 | 84 | ~SDLAppDisplay(); |
74 | 85 | |
75 | void init(std::string window_title, int xres, int yres, bool fullscreen); | |
86 | void toggleFullscreen(); | |
87 | void resize(int width, int height); | |
88 | ||
89 | void init(std::string window_title, int width, int height, bool fullscreen); | |
90 | void setVideoMode(int width, int height, bool fullscreen); | |
76 | 91 | |
77 | 92 | bool multiSamplingEnabled(); |
78 | 93 | |
80 | 95 | |
81 | 96 | void update(); |
82 | 97 | void clear(); |
83 | void enableVsync(bool vsync); | |
84 | void setClearColour(vec3f colour); | |
85 | void setClearColour(vec4f colour); | |
98 | ||
99 | void setClearColour(vec3 colour); | |
100 | void setClearColour(vec4 colour); | |
101 | ||
86 | 102 | |
87 | 103 | void enableShaders(bool enable); |
104 | void enableVsync(bool vsync); | |
105 | void enableAlpha(bool enable); | |
106 | void enableResize(bool resizable); | |
107 | void enableFrameless(bool frameless); | |
88 | 108 | |
89 | void enableAlpha(bool enable); | |
90 | 109 | void multiSample(int sample); |
91 | 110 | |
92 | 111 | void mode3D(float fov, float znear, float zfar); |
95 | 114 | void push2D(); |
96 | 115 | void pop2D(); |
97 | 116 | |
98 | vec4f currentColour(); | |
117 | vec4 currentColour(); | |
99 | 118 | |
100 | void fullScreenQuad(bool coord_flip); | |
101 | ||
102 | void renderToTexture(GLuint target, int width, int height, GLenum format); | |
103 | GLuint emptyTexture(int width, int height, GLenum format); | |
104 | GLuint createTexture(int width, int height, bool mipmaps, bool clamp, bool trilinear, GLenum format, unsigned int* data); | |
105 | ||
106 | vec3f project(vec3f pos); | |
107 | vec3f unproject(vec2f pos); | |
108 | ||
109 | void checkGLErrors(); | |
119 | vec3 project(vec3 pos); | |
120 | vec3 unproject(vec2 pos); | |
110 | 121 | }; |
111 | 122 | |
112 | 123 | extern SDLAppDisplay display; |
32 | 32 | Frustum::Frustum() { |
33 | 33 | } |
34 | 34 | |
35 | Frustum::Frustum(Camera& camera) { | |
36 | update(camera); | |
35 | Frustum::Frustum(const vec3& source, const vec3& target, const vec3& up, float fov, float near_distance, float far_distance) { | |
36 | update(source, target, up, fov, near_distance, far_distance); | |
37 | 37 | } |
38 | 38 | |
39 | void Frustum::update(Camera& camera) { | |
40 | updatePerspective(camera); | |
41 | updateView(camera); | |
39 | void Frustum::update(const vec3& source, const vec3& target, const vec3& up, float fov, float near_distance, float far_distance) { | |
40 | updatePerspective(fov, near_distance, far_distance); | |
41 | updateView(source, target, up); | |
42 | 42 | } |
43 | 43 | |
44 | void Frustum::updatePerspective(Camera& camera) { | |
44 | void Frustum::updatePerspective(float fov, float near_distance, float far_distance) { | |
45 | ||
46 | this->near_distance = near_distance; | |
47 | this->far_distance = far_distance; | |
48 | ||
45 | 49 | view_ratio = (float) display.width / (float) display.height; |
46 | fov = camera.getFov(); | |
47 | near_distance = camera.getZNear(); | |
48 | far_distance = camera.getZFar(); | |
49 | 50 | |
50 | 51 | float toa = (float) tan(fov * 0.5 * DEGREES_TO_RADIANS); |
51 | 52 | |
55 | 56 | far_half_width = far_half_height * view_ratio; |
56 | 57 | } |
57 | 58 | |
58 | void Frustum::updateView(Camera& camera) { | |
59 | vec3f source = camera.getPos(); | |
60 | vec3f target = camera.getTarget(); | |
61 | vec3f up = camera.getUp(); | |
59 | void Frustum::updateView(const vec3& source, const vec3& target, const vec3& up) { | |
62 | 60 | |
63 | vec3f view_ray = target - source; | |
64 | view_ray.normalize(); | |
61 | vec3 view_ray = normalise(target - source); | |
65 | 62 | |
66 | vec3f horiz_normal = view_ray.cross(up); | |
67 | horiz_normal.normalize(); | |
63 | vec3 horiz_normal = normalise(glm::cross(view_ray,up)); | |
68 | 64 | |
69 | vec3f vert_normal = horiz_normal.cross(view_ray); | |
65 | vec3 vert_normal = glm::cross(horiz_normal, view_ray); | |
70 | 66 | |
71 | 67 | //calculate the positions of the 8 points that make up |
72 | 68 | //the viewing frustum and then use them to create the 6 planes |
73 | 69 | |
74 | vec3f near_centre = source + view_ray * near_distance; | |
75 | vec3f far_centre = source + view_ray * far_distance; | |
70 | vec3 near_centre = source + view_ray * near_distance; | |
71 | vec3 far_centre = source + view_ray * far_distance; | |
76 | 72 | |
77 | vec3f near_horiz_offset = horiz_normal * near_half_width; | |
78 | vec3f near_vert_offset = vert_normal * near_half_height; | |
73 | vec3 near_horiz_offset = horiz_normal * near_half_width; | |
74 | vec3 near_vert_offset = vert_normal * near_half_height; | |
79 | 75 | |
80 | 76 | near_top_left = near_centre + near_vert_offset - near_horiz_offset; |
81 | 77 | near_top_right = near_centre + near_vert_offset + near_horiz_offset; |
82 | 78 | near_bottom_left = near_centre - near_vert_offset - near_horiz_offset; |
83 | 79 | near_bottom_right = near_centre - near_vert_offset + near_horiz_offset; |
84 | 80 | |
85 | vec3f far_horiz_offset = horiz_normal * far_half_width; | |
86 | vec3f far_vert_offset = vert_normal * far_half_height; | |
81 | vec3 far_horiz_offset = horiz_normal * far_half_width; | |
82 | vec3 far_vert_offset = vert_normal * far_half_height; | |
87 | 83 | |
88 | 84 | far_top_left = far_centre + far_vert_offset - far_horiz_offset; |
89 | 85 | far_top_right = far_centre + far_vert_offset + far_horiz_offset; |
109 | 105 | planes[5] = Plane(far_top_right, far_top_left, far_bottom_left); |
110 | 106 | } |
111 | 107 | |
112 | bool Frustum::contains(const vec3f& p) const { | |
108 | bool Frustum::contains(const vec3& p) const { | |
113 | 109 | |
114 | 110 | for(int i=0; i < 6; i++) { |
115 | 111 | float dist = planes[i].distance(p); |
122 | 118 | |
123 | 119 | bool Frustum::intersects(const Bounds3D& bounds) const { |
124 | 120 | |
125 | vec3f corner; | |
121 | vec3 corner; | |
126 | 122 | |
127 | 123 | for(int i=0; i<6; i++) { |
128 | 124 | |
139 | 135 | |
140 | 136 | bool Frustum::intersects(const Bounds2D& bounds, float z) const { |
141 | 137 | |
142 | vec3f corner; | |
138 | vec3 corner; | |
143 | 139 | |
144 | 140 | for(int i=0; i<6; i++) { |
145 | 141 |
27 | 27 | #ifndef FRUSTUM_H |
28 | 28 | #define FRUSTUM_H |
29 | 29 | |
30 | #include "vectors.h" | |
31 | #include "camera.h" | |
30 | #include "gl.h" | |
32 | 31 | #include "plane.h" |
33 | 32 | #include "pi.h" |
34 | 33 | #include "bounds.h" |
35 | ||
36 | class Camera; | |
37 | 34 | |
38 | 35 | class Frustum { |
39 | 36 | |
46 | 43 | float far_half_width; |
47 | 44 | float far_half_height; |
48 | 45 | |
49 | vec3f near_top_left, near_top_right; | |
50 | vec3f near_bottom_left, near_bottom_right; | |
51 | vec3f far_top_left, far_top_right; | |
52 | vec3f far_bottom_left, far_bottom_right; | |
46 | vec3 near_top_left, near_top_right; | |
47 | vec3 near_bottom_left, near_bottom_right; | |
48 | vec3 far_top_left, far_top_right; | |
49 | vec3 far_bottom_left, far_bottom_right; | |
53 | 50 | |
54 | 51 | Plane planes[6]; |
55 | 52 | public: |
56 | 53 | Frustum(); |
57 | Frustum(Camera& camera); | |
58 | void update(Camera& camera); | |
59 | void updatePerspective(Camera& camera); | |
60 | void updateView(Camera& camera); | |
54 | Frustum(const vec3& source, const vec3& target, const vec3& up, float fov, float near_distance, float far_distance); | |
61 | 55 | |
62 | bool contains(const vec3f& p) const; | |
56 | void update(const vec3& source, const vec3& target, const vec3& up, float fov, float near_distance, float far_distance); | |
57 | ||
58 | void updatePerspective(float fov, float near_distance, float far_distance); | |
59 | void updateView(const vec3& source, const vec3& target, const vec3& up); | |
60 | ||
61 | bool contains(const vec3& p) const; | |
63 | 62 | |
64 | 63 | bool intersects(const Bounds3D& bounds) const; |
65 | 64 | bool intersects(const Bounds2D& bounds, float z = 0.0) const; |
63 | 63 | |
64 | 64 | FT_Face ftface = set->getFTFace(); |
65 | 65 | |
66 | if(FT_Load_Glyph( ftface, FT_Get_Char_Index( ftface, chr ), FT_LOAD_DEFAULT )) | |
66 | FT_UInt index = FT_Get_Char_Index( ftface, chr ); | |
67 | ||
68 | //debugLog("FXGlyph %x %d %d", chr, chr, index); | |
69 | ||
70 | if(FT_Load_Glyph( ftface, index, FT_LOAD_DEFAULT )) | |
67 | 71 | throw FXFontException(ftface->family_name); |
68 | 72 | |
69 | 73 | FT_Glyph ftglyph; |
75 | 79 | |
76 | 80 | glyph_bitmap = (FT_BitmapGlyph)ftglyph; |
77 | 81 | |
78 | dims = vec2f( glyph_bitmap->bitmap.width, glyph_bitmap->bitmap.rows) + vec2f(2.0f, 2.0f); | |
79 | corner = vec2f( glyph_bitmap->left, -glyph_bitmap->top) + vec2f(0.5, -0.5); | |
80 | advance = vec2f( ftface->glyph->advance.x >> 6, ftface->glyph->advance.y >> 6); | |
81 | ||
82 | vertex_positions[0] = vec2f(0.0f, 0.0f); | |
83 | vertex_positions[1] = vec2f(dims.x, 0.0f); | |
82 | dims = vec2( glyph_bitmap->bitmap.width, glyph_bitmap->bitmap.rows) + vec2(2.0f, 2.0f); | |
83 | corner = vec2( glyph_bitmap->left, -glyph_bitmap->top) + vec2(0.5, -0.5); | |
84 | advance = vec2( ftface->glyph->advance.x >> 6, ftface->glyph->advance.y >> 6); | |
85 | ||
86 | vertex_positions[0] = vec2(0.0f, 0.0f); | |
87 | vertex_positions[1] = vec2(dims.x, 0.0f); | |
84 | 88 | vertex_positions[2] = dims; |
85 | vertex_positions[3] = vec2f(0.0f, dims.y); | |
89 | vertex_positions[3] = vec2(0.0f, dims.y); | |
86 | 90 | |
87 | 91 | //call_list = 0; |
88 | 92 | page = 0; |
89 | 93 | } |
90 | 94 | |
91 | void FXGlyph::setPage(FXGlyphPage* page, const vec4f& texcoords) { | |
95 | void FXGlyph::setPage(FXGlyphPage* page, const vec4& texcoords) { | |
92 | 96 | this->page = page; |
93 | 97 | this->texcoords = texcoords; |
94 | 98 | |
95 | vertex_texcoords[0] = vec2f(texcoords.x, texcoords.y); | |
96 | vertex_texcoords[1] = vec2f(texcoords.z, texcoords.y); | |
97 | vertex_texcoords[2] = vec2f(texcoords.z, texcoords.w); | |
98 | vertex_texcoords[3] = vec2f(texcoords.x, texcoords.w); | |
99 | } | |
100 | ||
101 | void FXGlyph::drawToVBO(quadbuf& buffer, const vec2f& pos, const vec4f& colour) const { | |
102 | buffer.add(page->textureid, pos + corner, dims, colour, texcoords); | |
103 | } | |
104 | ||
105 | void FXGlyph::draw(const vec2f& pos) const { | |
99 | vertex_texcoords[0] = vec2(texcoords.x, texcoords.y); | |
100 | vertex_texcoords[1] = vec2(texcoords.z, texcoords.y); | |
101 | vertex_texcoords[2] = vec2(texcoords.z, texcoords.w); | |
102 | vertex_texcoords[3] = vec2(texcoords.x, texcoords.w); | |
103 | } | |
104 | ||
105 | void FXGlyph::drawToVBO(quadbuf& buffer, const vec2& pos, const vec4& colour) const { | |
106 | buffer.add(page->texture->textureid, pos + corner, dims, colour, texcoords); | |
107 | } | |
108 | ||
109 | void FXGlyph::draw(const vec2& pos) const { | |
106 | 110 | for(int i=0;i<4;i++) { |
107 | glTexCoord2fv(vertex_texcoords[i]); | |
108 | glVertex2fv(vertex_positions[i] + pos + corner); | |
111 | vec2 pos_offset = vertex_positions[i] + pos + corner; | |
112 | ||
113 | glTexCoord2fv(glm::value_ptr(vertex_texcoords[i])); | |
114 | glVertex2fv(glm::value_ptr(pos_offset)); | |
115 | ||
109 | 116 | } |
110 | 117 | } |
111 | 118 | |
120 | 127 | memset(texture_data, 0, page_width * page_height); |
121 | 128 | |
122 | 129 | needs_update = false; |
123 | textureid = 0; | |
124 | glGenTextures(1, &textureid); | |
130 | texture = 0; | |
125 | 131 | |
126 | 132 | max_glyph_height = cursor_x = cursor_y = 1; |
127 | 133 | } |
161 | 167 | |
162 | 168 | //fprintf(stderr, "corner_x = %d, corner_y = %d\n", corner_x, corner_y); |
163 | 169 | |
164 | vec4f texcoords = vec4f( (((float)corner_x)-0.5f) / (float) page_width, | |
170 | vec4 texcoords = vec4( (((float)corner_x)-0.5f) / (float) page_width, | |
165 | 171 | (((float)corner_y)-0.5f) / (float) page_height, |
166 | 172 | (((float)corner_x+bitmap->bitmap.width)+1.5f) / (float) page_width, |
167 | 173 | (((float)corner_y+bitmap->bitmap.rows)+1.5f) / (float) page_height ); |
180 | 186 | void FXGlyphPage::updateTexture() { |
181 | 187 | if(!needs_update) return; |
182 | 188 | |
183 | glBindTexture( GL_TEXTURE_2D, textureid); | |
184 | ||
185 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); | |
186 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); | |
187 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); | |
188 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); | |
189 | ||
190 | glTexImage2D( GL_TEXTURE_2D, 0, GL_ALPHA, page_width, page_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, texture_data ); | |
189 | if(!texture) { | |
190 | texture = texturemanager.create(page_width, page_height, false, GL_CLAMP_TO_EDGE, GL_ALPHA, texture_data); | |
191 | } else { | |
192 | texture->reload(); | |
193 | } | |
191 | 194 | |
192 | 195 | needs_update = false; |
193 | 196 | } |
235 | 238 | //add to bitmap without updating textures until the end |
236 | 239 | pre_caching = true; |
237 | 240 | |
238 | while (chr = *precache_glyphs++) { | |
241 | while (*precache_glyphs) { | |
242 | chr = *precache_glyphs++; | |
239 | 243 | getGlyph(chr); |
240 | 244 | } |
241 | 245 | |
312 | 316 | return width; |
313 | 317 | } |
314 | 318 | |
315 | void FXGlyphSet::drawToVBO(vec2f& cursor, const std::string& text, const vec4f& colour) { | |
319 | void FXGlyphSet::drawToVBO(vec2& cursor, const std::string& text, const vec4& colour) { | |
316 | 320 | FTUnicodeStringItr<unsigned char> unicode_text((const unsigned char*)text.c_str()); |
317 | 321 | |
318 | 322 | unsigned int chr; |
334 | 338 | |
335 | 339 | unsigned int chr; |
336 | 340 | |
337 | vec2f pos; | |
341 | vec2 pos; | |
338 | 342 | |
339 | 343 | while (*unicode_text) { |
340 | 344 | chr = *unicode_text++; |
341 | 345 | |
342 | 346 | FXGlyph* glyph = getGlyph(chr); |
343 | 347 | |
344 | if(glyph->page->textureid != textureid) { | |
348 | if(glyph->page->texture->textureid != textureid) { | |
345 | 349 | if(textureid != -1) glEnd(); |
346 | textureid = glyph->page->textureid; | |
350 | textureid = glyph->page->texture->textureid; | |
347 | 351 | glBindTexture(GL_TEXTURE_2D, textureid); |
348 | 352 | glBegin(GL_QUADS); |
349 | 353 | } |
355 | 359 | if(textureid != -1) glEnd(); |
356 | 360 | } |
357 | 361 | |
362 | void FXGlyphSet::drawPages() { | |
363 | vec2 corner = vec2(0.0f); | |
364 | ||
365 | glPushMatrix(); | |
366 | ||
367 | for(std::vector<FXGlyphPage*>::iterator it = pages.begin(); it != pages.end(); it++) { | |
368 | FXGlyphPage* page = *it; | |
369 | page->texture->bind(); | |
370 | ||
371 | glBegin(GL_QUADS); | |
372 | glTexCoord2f(0.0f, 0.0f); | |
373 | glVertex2f(0.0f, 0.0f); | |
374 | ||
375 | glTexCoord2f(1.0f, 0.0f); | |
376 | glVertex2f(page->texture->w, 0.0f); | |
377 | ||
378 | glTexCoord2f(1.0f, 1.0f); | |
379 | glVertex2f(page->texture->w, page->texture->h); | |
380 | ||
381 | glTexCoord2f(0.0f, 1.0f); | |
382 | glVertex2f(0.0f, page->texture->h); | |
383 | glEnd(); | |
384 | ||
385 | glTranslatef(page->texture->w, 0.0f, 0.0f); | |
386 | } | |
387 | ||
388 | glPopMatrix(); | |
389 | } | |
390 | ||
358 | 391 | //FXFont |
359 | 392 | |
360 | 393 | FXFont::FXFont() { |
369 | 402 | void FXFont::init() { |
370 | 403 | shadow = false; |
371 | 404 | shadow_strength = 0.7; |
372 | shadow_offset = vec2f(1.0, 1.0); | |
405 | shadow_offset = vec2(1.0, 1.0); | |
373 | 406 | round = false; |
374 | 407 | align_right = false; |
375 | 408 | align_top = true; |
376 | 409 | |
377 | colour = vec4f(1.0f, 1.0f, 1.0f, 1.0f); | |
378 | shadow_colour = vec4f(0.0f, 0.0f, 0.0f, shadow_strength); | |
410 | colour = vec4(1.0f, 1.0f, 1.0f, 1.0f); | |
411 | shadow_colour = vec4(0.0f, 0.0f, 0.0f, shadow_strength); | |
379 | 412 | } |
380 | 413 | |
381 | 414 | void FXFont::roundCoordinates(bool round) { |
395 | 428 | shadow_colour.w = colour.w * shadow_strength; |
396 | 429 | } |
397 | 430 | |
398 | void FXFont::setColour(const vec4f& colour) { | |
431 | void FXFont::setColour(const vec4& colour) { | |
399 | 432 | this->colour = colour; |
400 | 433 | shadow_colour.w = colour.w * shadow_strength; |
401 | 434 | } |
406 | 439 | } |
407 | 440 | |
408 | 441 | void FXFont::shadowOffset(float x, float y) { |
409 | shadow_offset = vec2f(x,y); | |
442 | shadow_offset = vec2(x,y); | |
410 | 443 | } |
411 | 444 | |
412 | 445 | void FXFont::dropShadow(bool shadow) { |
433 | 466 | return glyphset->getWidth(text); |
434 | 467 | } |
435 | 468 | |
436 | void FXFont::render(float x, float y, const std::string& text, const vec4f& colour) const{ | |
469 | void FXFont::render(float x, float y, const std::string& text, const vec4& colour) const{ | |
437 | 470 | |
438 | 471 | if(fontmanager.use_vbo) { |
439 | vec2f cursor_start(x,y); | |
472 | vec2 cursor_start(x,y); | |
440 | 473 | glyphset->drawToVBO(cursor_start, text, colour); |
441 | 474 | return; |
442 | 475 | } |
443 | 476 | |
444 | glColor4fv(colour); | |
477 | glColor4fv(glm::value_ptr(colour)); | |
445 | 478 | |
446 | 479 | glPushMatrix(); |
447 | 480 | |
488 | 521 | } |
489 | 522 | |
490 | 523 | render(x, y, text, colour); |
524 | } | |
525 | ||
526 | void FXFont::drawGlyphes() { | |
527 | if(glyphset) glyphset->drawPages(); | |
491 | 528 | } |
492 | 529 | |
493 | 530 | // FXFontManager |
501 | 538 | use_vbo = false; |
502 | 539 | } |
503 | 540 | |
541 | void FXFontManager::unload() { | |
542 | font_vbo.unload(); | |
543 | } | |
544 | ||
545 | void FXFontManager::reload() { | |
546 | } | |
547 | ||
504 | 548 | void FXFontManager::startBuffer() { |
505 | 549 | font_vbo.reset(); |
506 | 550 | use_vbo = true; |
538 | 582 | } |
539 | 583 | |
540 | 584 | FXFont FXFontManager::grab(std::string font_file, int size, int dpi) { |
541 | ||
542 | char buf[256]; | |
543 | 585 | |
544 | 586 | if(font_dir.size()>0 && font_file[0] != '/') { |
545 | 587 | font_file = font_dir + font_file; |
57 | 57 | #include "vectors.h" |
58 | 58 | #include "logger.h" |
59 | 59 | #include "resource.h" |
60 | #include "texture.h" | |
60 | 61 | #include "vbo.h" |
61 | 62 | |
62 | 63 | #include <string> |
63 | 64 | #include <vector> |
64 | 65 | #include <map> |
65 | ||
66 | #include <ft2build.h> | |
67 | #include FT_FREETYPE_H | |
68 | #include FT_GLYPH_H | |
69 | ||
70 | #include "ftgl/FTUnicode.h" | |
71 | 66 | |
72 | 67 | class FXFontException : public ResourceException { |
73 | 68 | public: |
84 | 79 | int page_width; |
85 | 80 | int page_height; |
86 | 81 | public: |
82 | TextureResource* texture; | |
83 | ||
87 | 84 | FXGlyphPage(int page_width, int page_height); |
88 | 85 | ~FXGlyphPage(); |
89 | 86 | |
91 | 88 | |
92 | 89 | void updateTexture(); |
93 | 90 | |
94 | GLuint textureid; | |
95 | ||
96 | 91 | int cursor_x, cursor_y; |
97 | 92 | int max_glyph_height; |
98 | 93 | }; |
100 | 95 | class FXGlyph { |
101 | 96 | unsigned int chr; |
102 | 97 | |
103 | vec2f dims; | |
104 | vec2f corner; | |
105 | vec2f advance; | |
106 | public: | |
107 | vec2f vertex_positions[4]; | |
108 | vec2f vertex_texcoords[4]; | |
98 | vec2 dims; | |
99 | vec2 corner; | |
100 | vec2 advance; | |
101 | public: | |
102 | vec2 vertex_positions[4]; | |
103 | vec2 vertex_texcoords[4]; | |
109 | 104 | |
110 | 105 | FXGlyphPage* page; |
111 | vec4f texcoords; | |
106 | vec4 texcoords; | |
112 | 107 | FXGlyphSet* set; |
113 | 108 | FT_BitmapGlyph glyph_bitmap; |
114 | 109 | |
115 | 110 | FXGlyph(FXGlyphSet* set, unsigned int chr); |
116 | 111 | |
117 | const vec2f& getAdvance() const { return advance; }; | |
118 | const vec2f& getCorner() const { return corner; }; | |
119 | const vec2f& getDimensions() const { return dims; }; | |
120 | ||
121 | void setPage(FXGlyphPage* page, const vec4f& texcoords); | |
122 | ||
123 | void drawToVBO(quadbuf& buffer, const vec2f& offset, const vec4f& colour) const; | |
124 | void draw(const vec2f& pos) const; | |
112 | const vec2& getAdvance() const { return advance; }; | |
113 | const vec2& getCorner() const { return corner; }; | |
114 | const vec2& getDimensions() const { return dims; }; | |
115 | ||
116 | void setPage(FXGlyphPage* page, const vec4& texcoords); | |
117 | ||
118 | void drawToVBO(quadbuf& buffer, const vec2& offset, const vec4& colour) const; | |
119 | void draw(const vec2& pos) const; | |
125 | 120 | }; |
126 | 121 | |
127 | 122 | class FXGlyphSet { |
156 | 151 | |
157 | 152 | int getSize() const { return size; }; |
158 | 153 | |
159 | void drawToVBO(vec2f& cursor, const std::string& text, const vec4f& colour); | |
154 | void drawToVBO(vec2& cursor, const std::string& text, const vec4& colour); | |
160 | 155 | void draw(const std::string& text); |
156 | ||
157 | void drawPages(); | |
161 | 158 | }; |
162 | 159 | |
163 | 160 | class FXFont { |
169 | 166 | bool round; |
170 | 167 | |
171 | 168 | float shadow_strength; |
172 | vec2f shadow_offset; | |
173 | vec4f shadow_colour; | |
174 | vec4f colour; | |
169 | vec2 shadow_offset; | |
170 | vec4 shadow_colour; | |
171 | vec4 colour; | |
175 | 172 | |
176 | 173 | bool align_right, align_top; |
177 | 174 | |
178 | void render(float x, float y, const std::string& text, const vec4f& colour) const; | |
175 | void render(float x, float y, const std::string& text, const vec4& colour) const; | |
179 | 176 | void init(); |
180 | 177 | public: |
181 | 178 | FXFont(); |
206 | 203 | void shadowStrength(float s); |
207 | 204 | void shadowOffset(float x, float y); |
208 | 205 | |
209 | void setColour(const vec4f& colour); | |
206 | void setColour(const vec4& colour); | |
210 | 207 | void setAlpha(float alpha); |
208 | ||
209 | void drawGlyphes(); | |
211 | 210 | }; |
212 | 211 | |
213 | 212 | typedef std::map<int,FXGlyphSet*> fontSizeMap; |
226 | 225 | |
227 | 226 | void setDir(std::string font_dir); |
228 | 227 | void init(); |
228 | ||
229 | void unload(); | |
230 | void reload(); | |
231 | ||
229 | 232 | void destroy(); |
230 | 233 | void purge(); |
231 | 234 |
5 | 5 | #define NO_SDL_GLEXT |
6 | 6 | #include "SDL.h" |
7 | 7 | #include "SDL_opengl.h" |
8 | #endif | |
8 | 9 | |
10 | #define PRINT_GL_ERRORS | |
11 | ||
12 | #ifdef PRINT_GL_ERRORS | |
13 | #define glCheckError() { \ | |
14 | int gl_error = glGetError(); \ | |
15 | if(gl_error != GL_NO_ERROR) fprintf(stderr, "GL error %s at %s:%d\n", gluErrorString(gl_error), __FILE__, __LINE__); \ | |
16 | } | |
17 | #else | |
18 | #define glCheckError() | |
9 | 19 | #endif |
20 | ||
21 | #include <ft2build.h> | |
22 | #include FT_FREETYPE_H | |
23 | #include FT_GLYPH_H | |
24 | #include "ftgl/FTUnicode.h" | |
25 | ||
26 | #include "vectors.h" | |
27 | ||
28 |
24 | 24 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 | 25 | */ |
26 | 26 | |
27 | //#define SDLAPP_DEBUG_LOG "debug.log" | |
28 | ||
29 | 27 | #include "logger.h" |
30 | 28 | |
31 | bool firstEntry = true; | |
29 | std::map<int,std::string> log_levels = boost::assign::map_list_of | |
30 | (LOG_LEVEL_WARN, " WARN" ) | |
31 | (LOG_LEVEL_DEBUG, "DEBUG" ) | |
32 | (LOG_LEVEL_INFO, " INFO" ) | |
33 | (LOG_LEVEL_ERROR, "ERROR" ) | |
34 | (LOG_LEVEL_INFINITY, "????" ); | |
32 | 35 | |
33 | void debugLog(const char *str, ...) { | |
34 | #ifdef SDLAPP_DEBUG_LOG | |
36 | // LoggerMessage | |
35 | 37 | |
36 | FILE *log; | |
38 | LoggerMessage::LoggerMessage(int level, const std::string& message) | |
39 | : level(level), message(message) { | |
40 | } | |
37 | 41 | |
38 | if (firstEntry) { | |
42 | // Logger | |
39 | 43 | |
40 | log = fopen(SDLAPP_DEBUG_LOG, "w"); | |
44 | Logger::Logger(int level, FILE* stream, int hist_capacity) { | |
45 | init(level, stream, hist_capacity); | |
46 | } | |
41 | 47 | |
42 | if(log==0) { | |
43 | fprintf(stderr, "could not create %s\n", SDLAPP_DEBUG_LOG); | |
44 | exit(1); | |
45 | } | |
48 | void Logger::init(int level, FILE* stream, int hist_capacity) { | |
49 | this->level = level; | |
50 | this->stream = stream; | |
51 | this->hist_capacity = hist_capacity; | |
52 | } | |
46 | 53 | |
47 | firstEntry=false; | |
48 | } else { | |
54 | void Logger::message(int level, const std::string& message) { | |
49 | 55 | |
50 | log = fopen(SDLAPP_DEBUG_LOG, "a"); | |
56 | if(this->level > level) return; | |
51 | 57 | |
52 | if(log==0) { | |
53 | fprintf(stderr, "could not append to %s\n", SDLAPP_DEBUG_LOG); | |
54 | exit(1); | |
55 | } | |
58 | if(stream != 0) { | |
59 | fprintf(stderr, "%s: %s\n", log_levels[level].c_str(), message.c_str()); | |
56 | 60 | } |
61 | ||
62 | if(!hist_capacity) return; | |
63 | ||
64 | while(history.size() >= hist_capacity) { | |
65 | history.pop_front(); | |
66 | } | |
67 | ||
68 | history.push_back(LoggerMessage(level, message)); | |
69 | } | |
70 | ||
71 | void warnLog(const char *str, ...) { | |
72 | ||
73 | if(!logger || logger->getLevel() > LOG_LEVEL_WARN) return; | |
74 | ||
75 | char msgbuff[65536]; | |
57 | 76 | |
58 | 77 | va_list vl; |
59 | 78 | |
60 | 79 | va_start(vl, str); |
61 | vfprintf(log, str, vl); | |
80 | vsnprintf(msgbuff, 65536, str, vl); | |
62 | 81 | va_end(vl); |
63 | 82 | |
64 | fclose(log); | |
83 | logger->message( LOG_LEVEL_WARN, msgbuff ); | |
84 | } | |
65 | 85 | |
66 | #endif | |
86 | void debugLog(const char *str, ...) { | |
87 | ||
88 | if(!logger || logger->getLevel() > LOG_LEVEL_DEBUG) return; | |
89 | ||
90 | char msgbuff[65536]; | |
91 | ||
92 | va_list vl; | |
93 | ||
94 | va_start(vl, str); | |
95 | vsnprintf(msgbuff, 65536, str, vl); | |
96 | va_end(vl); | |
97 | ||
98 | logger->message( LOG_LEVEL_DEBUG, msgbuff ); | |
67 | 99 | } |
100 | ||
101 | void infoLog(const char *str, ...) { | |
102 | ||
103 | if(!logger || logger->getLevel() > LOG_LEVEL_INFO) return; | |
104 | ||
105 | char msgbuff[65536]; | |
106 | ||
107 | va_list vl; | |
108 | ||
109 | va_start(vl, str); | |
110 | vsnprintf(msgbuff, 65536, str, vl); | |
111 | va_end(vl); | |
112 | ||
113 | logger->message( LOG_LEVEL_INFO, msgbuff ); | |
114 | } | |
115 | ||
116 | void errorLog(const char *str, ...) { | |
117 | ||
118 | if(!logger || logger->getLevel() > LOG_LEVEL_ERROR) return; | |
119 | ||
120 | char msgbuff[65536]; | |
121 | ||
122 | va_list vl; | |
123 | ||
124 | va_start(vl, str); | |
125 | vsnprintf(msgbuff, 65536, str, vl); | |
126 | va_end(vl); | |
127 | ||
128 | logger->message( LOG_LEVEL_ERROR, msgbuff ); | |
129 | } | |
130 | ||
131 | Logger* logger = new Logger(LOG_LEVEL_ERROR, stderr, 0); |
26 | 26 | |
27 | 27 | #ifndef LOGGER_H |
28 | 28 | #define LOGGER_H |
29 | ||
29 | ||
30 | #include "gl.h" | |
31 | ||
32 | #include <map> | |
33 | #include <deque> | |
34 | #include <string> | |
35 | ||
36 | #include <boost/assign/list_of.hpp> | |
37 | ||
30 | 38 | #include <stdio.h> |
31 | 39 | #include <stdarg.h> |
32 | 40 | #include <stdlib.h> |
33 | 41 | |
42 | enum logger_level { LOG_LEVEL_PEDANTIC, LOG_LEVEL_WARN, LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_ERROR, LOG_LEVEL_INFINITY }; | |
43 | ||
44 | class LoggerMessage { | |
45 | ||
46 | public: | |
47 | LoggerMessage(int level, const std::string& message); | |
48 | ||
49 | int level; | |
50 | std::string message; | |
51 | }; | |
52 | ||
53 | class Logger { | |
54 | protected: | |
55 | std::deque<LoggerMessage> history; | |
56 | int hist_capacity; | |
57 | FILE* stream; | |
58 | int level; | |
59 | public: | |
60 | ||
61 | void setLevel(int level) { this->level = level; }; | |
62 | int getLevel() const { return level; } | |
63 | ||
64 | Logger(); | |
65 | Logger(int level, FILE* stream, int history_capacity = 0); | |
66 | ||
67 | void init(int level, FILE* stream, int history_capacity); | |
68 | ||
69 | void message(int level, const std::string& message); | |
70 | }; | |
71 | ||
72 | void warnLog(const char *args, ...); | |
34 | 73 | void debugLog(const char *args, ...); |
74 | void infoLog(const char *args, ...); | |
75 | void errorLog(const char *args, ...); | |
76 | ||
77 | extern Logger* logger; | |
35 | 78 | |
36 | 79 | #endif |
32 | 32 | hidden = false; |
33 | 33 | timeout = 3.0f; |
34 | 34 | idle = timeout; |
35 | ||
36 | sdl_default_cursor = SDL_GetCursor(); | |
37 | ||
38 | ||
39 | Uint8 data[4*32]; | |
40 | Uint8 mask[4*32]; | |
41 | ||
42 | memset(data, 0, sizeof(data)); | |
43 | memset(mask, 0, sizeof(mask)); | |
44 | ||
45 | sdl_hidden_cursor = SDL_CreateCursor(data, mask, 32, 32, 0, 0); | |
46 | } | |
47 | ||
48 | MouseCursor::~MouseCursor() { | |
49 | SDL_SetCursor(sdl_default_cursor); | |
50 | SDL_FreeCursor(sdl_hidden_cursor); | |
35 | 51 | } |
36 | 52 | |
37 | 53 | void MouseCursor::useSystemCursor(bool system_cursor) { |
38 | 54 | this->system_cursor = system_cursor; |
39 | 55 | |
40 | 56 | if(!hidden) { |
41 | if(system_cursor) SDL_ShowCursor(true); | |
42 | else SDL_ShowCursor(false); | |
57 | if(system_cursor) SDL_SetCursor(sdl_default_cursor); | |
58 | else SDL_SetCursor(sdl_hidden_cursor); | |
43 | 59 | } else { |
44 | SDL_ShowCursor(false); | |
60 | SDL_SetCursor(sdl_hidden_cursor); | |
45 | 61 | } |
46 | 62 | } |
47 | 63 | |
52 | 68 | if(show) idle = 0.0; |
53 | 69 | |
54 | 70 | if(system_cursor) { |
55 | if(show) SDL_ShowCursor(true); | |
56 | else SDL_ShowCursor(false); | |
71 | if(show) SDL_SetCursor(sdl_default_cursor); | |
72 | else SDL_SetCursor(sdl_hidden_cursor); | |
57 | 73 | } |
58 | 74 | } |
59 | 75 | |
90 | 106 | } |
91 | 107 | |
92 | 108 | bool MouseCursor::hasFocus() const { |
109 | #if SDL_VERSION_ATLEAST(1,3,0) | |
110 | return (SDL_GetMouseFocus() == display.sdl_window); | |
111 | #else | |
93 | 112 | return (SDL_GetAppState() & SDL_APPMOUSEFOCUS); |
113 | #endif | |
94 | 114 | } |
95 | 115 | |
96 | 116 | void MouseCursor::setCursorTexture(TextureResource* texture) { |
97 | 117 | cursortex = texture; |
98 | 118 | } |
99 | 119 | |
100 | void MouseCursor::updatePos(const vec2f& pos) { | |
120 | void MouseCursor::updatePos(const vec2& pos) { | |
101 | 121 | mousepos = pos; |
102 | 122 | idle = 0.0f; |
103 | 123 | } |
115 | 135 | glEnable(GL_TEXTURE_2D); |
116 | 136 | glEnable(GL_BLEND); |
117 | 137 | |
118 | glBindTexture(GL_TEXTURE_2D, cursortex->textureid); | |
138 | cursortex->bind(); | |
119 | 139 | |
120 | 140 | glTranslatef(mousepos.x, mousepos.y, 0.0f); |
121 | 141 |
31 | 31 | |
32 | 32 | class MouseCursor { |
33 | 33 | |
34 | vec2f mousepos; | |
34 | vec2 mousepos; | |
35 | 35 | |
36 | 36 | bool hidden; |
37 | 37 | bool system_cursor; |
38 | 38 | |
39 | 39 | float idle; |
40 | 40 | float timeout; |
41 | ||
42 | SDL_Cursor* sdl_default_cursor; | |
43 | SDL_Cursor* sdl_hidden_cursor; | |
41 | 44 | |
42 | 45 | TextureResource* cursortex; |
43 | 46 | public: |
44 | 47 | MouseCursor(); |
45 | ||
46 | vec2f getPos() const { return mousepos; } | |
48 | ~MouseCursor(); | |
49 | ||
50 | vec2 getPos() const { return mousepos; } | |
47 | 51 | |
48 | 52 | bool leftButtonPressed() const; |
49 | 53 | bool rightButtonPressed() const; |
55 | 59 | bool isVisible() const; |
56 | 60 | bool hasFocus() const; |
57 | 61 | |
58 | void updatePos(const vec2f& pos); | |
62 | void updatePos(const vec2& pos); | |
59 | 63 | |
60 | 64 | void showCursor(bool show); |
61 | 65 | void useSystemCursor(bool system_cursor); |
30 | 30 | d = 0.0f; |
31 | 31 | } |
32 | 32 | |
33 | Plane::Plane(const vec3f & v1, const vec3f & v2, const vec3f & v3) { | |
34 | vec3f edge1 = v1 - v2; | |
35 | vec3f edge2 = v3 - v2; | |
33 | Plane::Plane(const vec3 & v1, const vec3 & v2, const vec3 & v3) { | |
34 | vec3 edge1 = v1 - v2; | |
35 | vec3 edge2 = v3 - v2; | |
36 | 36 | |
37 | normal = edge2.cross(edge1); | |
38 | normal.normalize(); | |
37 | normal = normalise(glm::cross(edge2, edge1)); | |
39 | 38 | |
40 | 39 | point = v2; |
41 | 40 | |
42 | d = -(normal.dot(point)); | |
41 | d = -(glm::dot(normal, point)); | |
43 | 42 | } |
44 | 43 | |
45 | float Plane::distance(const vec3f & p) const{ | |
46 | return (d + normal.dot(p)); | |
44 | float Plane::distance(const vec3 & p) const{ | |
45 | return d + glm::dot(normal, p); | |
47 | 46 | } |
48 | 47 |
32 | 32 | |
33 | 33 | class Plane { |
34 | 34 | public: |
35 | vec3f normal, point; | |
35 | vec3 normal, point; | |
36 | 36 | float d; |
37 | 37 | |
38 | 38 | Plane(); |
39 | Plane(const vec3f & v1, const vec3f & v2, const vec3f & v3); | |
39 | Plane(const vec3 & v1, const vec3 & v2, const vec3 & v3); | |
40 | 40 | |
41 | float distance(const vec3f & p) const; | |
41 | float distance(const vec3 & p) const; | |
42 | 42 | }; |
43 | 43 | |
44 | 44 | #endif |
46 | 46 | |
47 | 47 | cond = SDL_CreateCond(); |
48 | 48 | mutex = SDL_CreateMutex(); |
49 | ||
50 | #if SDL_VERSION_ATLEAST(1,3,0) | |
51 | thread = SDL_CreateThread( dumper_thread, "frame_exporter", this ); | |
52 | #else | |
49 | 53 | thread = SDL_CreateThread( dumper_thread, this ); |
54 | #endif | |
50 | 55 | } |
51 | 56 | |
52 | 57 | FrameExporter::~FrameExporter() { |
53 | stopDumpThr(); | |
58 | stop(); | |
54 | 59 | |
55 | 60 | SDL_KillThread(thread); |
56 | 61 | SDL_DestroyCond(cond); |
63 | 68 | delete[] pixels_out; |
64 | 69 | } |
65 | 70 | |
66 | void FrameExporter::stopDumpThr() { | |
67 | if(dumper_thread_state == FRAME_EXPORTER_STOPPED) return; | |
71 | void FrameExporter::stop() { | |
72 | if(dumper_thread_state == FRAME_EXPORTER_STOPPED || dumper_thread_state == FRAME_EXPORTER_EXIT) return; | |
68 | 73 | |
69 | 74 | SDL_mutexP(mutex); |
70 | 75 | |
160 | 165 | } |
161 | 166 | |
162 | 167 | PPMExporter::~PPMExporter() { |
163 | stopDumpThr(); | |
168 | stop(); | |
164 | 169 | |
165 | 170 | if(filename.size()>0) |
166 | 171 | ((std::fstream*)output)->close(); |
49 | 49 | SDL_cond* cond; |
50 | 50 | int dumper_thread_state; |
51 | 51 | |
52 | void stopDumpThr(); | |
53 | 52 | public: |
54 | 53 | FrameExporter(); |
55 | 54 | virtual ~FrameExporter(); |
55 | void stop(); | |
56 | 56 | void dump(); |
57 | 57 | void dumpThr(); |
58 | 58 | virtual void dumpImpl() {}; |
53 | 53 | return; |
54 | 54 | } |
55 | 55 | |
56 | vec2f average = bounds.centre(); | |
57 | ||
58 | vec2f middle = average - bounds.min; | |
59 | ||
60 | vec2f relmax = bounds.max-bounds.min; | |
56 | vec2 average = bounds.centre(); | |
57 | ||
58 | vec2 middle = average - bounds.min; | |
59 | ||
60 | vec2 relmax = bounds.max-bounds.min; | |
61 | 61 | |
62 | 62 | Bounds2D newbounds; |
63 | 63 | |
64 | 64 | children.reserve(4); |
65 | 65 | |
66 | 66 | //top left |
67 | newbounds = Bounds2D( bounds.min + vec2f(0.0, 0.0), bounds.min + middle ); | |
67 | newbounds = Bounds2D( bounds.min + vec2(0.0, 0.0), bounds.min + middle ); | |
68 | 68 | children.push_back(new QuadNode(tree, this, newbounds, depth)); |
69 | 69 | |
70 | 70 | //top right |
71 | newbounds = Bounds2D( bounds.min + vec2f(middle.x, 0.0), bounds.min + vec2f(relmax.x,middle.y) ); | |
71 | newbounds = Bounds2D( bounds.min + vec2(middle.x, 0.0), bounds.min + vec2(relmax.x,middle.y) ); | |
72 | 72 | children.push_back(new QuadNode(tree, this, newbounds, depth)); |
73 | 73 | |
74 | 74 | //bottom left |
75 | newbounds = Bounds2D( bounds.min + vec2f(0.0, middle.y), bounds.min + vec2f(middle.x,relmax.y) ); | |
75 | newbounds = Bounds2D( bounds.min + vec2(0.0, middle.y), bounds.min + vec2(middle.x,relmax.y) ); | |
76 | 76 | children.push_back(new QuadNode(tree, this, newbounds, depth)); |
77 | 77 | |
78 | 78 | //bottom right |
184 | 184 | |
185 | 185 | |
186 | 186 | |
187 | int QuadNode::getItemsAt(std::set<QuadItem*>& itemset, vec2f pos) { | |
187 | int QuadNode::getItemsAt(std::set<QuadItem*>& itemset, vec2 pos) { | |
188 | 188 | |
189 | 189 | if(!items.empty()) { |
190 | 190 | int items_added = 0; |
262 | 262 | |
263 | 263 | } |
264 | 264 | |
265 | void QuadNode::visitItemsAt(const vec2f & pos, VisitFunctor<QuadItem> & visit){ | |
265 | void QuadNode::visitItemsAt(const vec2 & pos, VisitFunctor<QuadItem> & visit){ | |
266 | 266 | |
267 | 267 | if(!items.empty()){ |
268 | 268 | |
283 | 283 | } |
284 | 284 | |
285 | 285 | |
286 | int QuadNode::getChildIndex(const vec2f & pos) const{ | |
286 | int QuadNode::getChildIndex(const vec2 & pos) const{ | |
287 | 287 | |
288 | 288 | if(children.empty()) return -1; |
289 | 289 | |
451 | 451 | } |
452 | 452 | |
453 | 453 | |
454 | int QuadTree::getItemsAt(std::set<QuadItem*>& itemset, vec2f pos) { | |
454 | int QuadTree::getItemsAt(std::set<QuadItem*>& itemset, vec2 pos) { | |
455 | 455 | int return_count = root->getItemsAt(itemset, pos); |
456 | 456 | |
457 | 457 | return return_count; |
472 | 472 | } |
473 | 473 | |
474 | 474 | |
475 | void QuadTree::visitItemsAt(const vec2f & pos, VisitFunctor<QuadItem> & visit){ | |
475 | void QuadTree::visitItemsAt(const vec2 & pos, VisitFunctor<QuadItem> & visit){ | |
476 | 476 | return root->visitItemsAt(pos, visit); |
477 | 477 | } |
478 | 478 |
30 | 30 | #include <set> |
31 | 31 | #include <list> |
32 | 32 | |
33 | #include "vectors.h" | |
33 | #include "gl.h" | |
34 | 34 | #include "bounds.h" |
35 | 35 | #include "frustum.h" |
36 | 36 | |
61 | 61 | |
62 | 62 | QuadTree* tree; |
63 | 63 | |
64 | int getChildIndex(const vec2f & pos) const; | |
64 | int getChildIndex(const vec2 & pos) const; | |
65 | 65 | void addToChild(QuadItem* item); |
66 | 66 | |
67 | 67 | int depth; |
76 | 76 | |
77 | 77 | void addItem(QuadItem* item); //if not subdivided, subdivide, add to correct subdivided node. |
78 | 78 | |
79 | int getItemsAt(std::set<QuadItem*>& itemset, vec2f pos); | |
79 | int getItemsAt(std::set<QuadItem*>& itemset, vec2 pos); | |
80 | 80 | void getLeavesInFrustum(std::set<QuadNode*>& nodeset, Frustum& frustum); |
81 | 81 | int getItemsInFrustum(std::set<QuadItem*>& itemset, Frustum& frustum); |
82 | 82 | int getItemsInBounds(std::set<QuadItem*>& itemset, Bounds2D& bounds) const; |
83 | 83 | |
84 | 84 | void visitItemsInFrustum(const Frustum & frustum, VisitFunctor<QuadItem> & visit); |
85 | 85 | void visitItemsInBounds(const Bounds2D & bounds, VisitFunctor<QuadItem> & visit); |
86 | void visitItemsAt(const vec2f & pos, VisitFunctor<QuadItem> & visit); | |
86 | void visitItemsAt(const vec2 & pos, VisitFunctor<QuadItem> & visit); | |
87 | 87 | void visitLeavesInFrustum(const Frustum & frustum, VisitFunctor<QuadNode> & visit); |
88 | 88 | |
89 | 89 | bool empty(); |
104 | 104 | int max_node_depth; |
105 | 105 | int max_node_items; |
106 | 106 | |
107 | int getItemsAt(std::set<QuadItem*>& itemset, vec2f pos); | |
107 | int getItemsAt(std::set<QuadItem*>& itemset, vec2 pos); | |
108 | 108 | void getLeavesInFrustum(std::set<QuadNode*>& nodeset, Frustum& frustum); |
109 | 109 | int getItemsInFrustum(std::set<QuadItem*>& itemset, Frustum& frustum); |
110 | 110 | int getItemsInBounds(std::set<QuadItem*>& itemset, Bounds2D& bounds) const; |
111 | 111 | |
112 | void visitItemsAt(const vec2f & pos, VisitFunctor<QuadItem> & visit); | |
112 | void visitItemsAt(const vec2 & pos, VisitFunctor<QuadItem> & visit); | |
113 | 113 | void visitLeavesInFrustum(const Frustum & frustum, VisitFunctor<QuadNode> & visit); |
114 | 114 | void visitItemsInFrustum(const Frustum & frustum, VisitFunctor<QuadItem> & visit); |
115 | 115 | void visitItemsInBounds(const Bounds2D & bounds, VisitFunctor<QuadItem> & visit); |
33 | 33 | return resource_dir; |
34 | 34 | } |
35 | 35 | |
36 | void ResourceManager::setDir(std::string resource_dir) { | |
36 | void ResourceManager::setDir(const std::string& resource_dir) { | |
37 | 37 | this->resource_dir = resource_dir; |
38 | 38 | } |
39 | 39 | |
49 | 49 | ResourceManager::~ResourceManager() { |
50 | 50 | } |
51 | 51 | |
52 | Resource* ResourceManager::grab(std::string name) { | |
52 | Resource* ResourceManager::grab(const std::string& name) { | |
53 | 53 | //debugLog("grabing %s\n", name.c_str()); |
54 | 54 | Resource* r = resources[name]; |
55 | 55 | |
63 | 63 | } |
64 | 64 | |
65 | 65 | void ResourceManager::release(Resource* resource) { |
66 | Resource* r = resources[resource->name]; | |
66 | Resource* r = resources[resource->resource_name]; | |
67 | 67 | |
68 | 68 | if(r==0) return; |
69 | 69 | |
72 | 72 | |
73 | 73 | if(r->refcount()<=0) { |
74 | 74 | //debugLog("no refs to %s, deleting\n", name.c_str()); |
75 | resources.erase(r->name); //sufficient? | |
75 | resources.erase(r->resource_name); //sufficient? | |
76 | 76 | delete r; |
77 | 77 | } |
78 | 78 | } |
32 | 32 | #include <cstring> |
33 | 33 | #include <stdexcept> |
34 | 34 | |
35 | #ifdef _WIN32 | |
36 | #include "windows.h" | |
37 | #endif | |
38 | ||
39 | 35 | class ResourceException : public std::exception { |
40 | 36 | protected: |
41 | 37 | std::string resource; |
49 | 45 | class Resource { |
50 | 46 | int refs; |
51 | 47 | public: |
52 | std::string name; | |
53 | Resource(std::string name) { this->name = name; refs=0; }; | |
48 | std::string resource_name; | |
49 | Resource() { refs =0; }; | |
50 | Resource(const std::string& resource_name) : resource_name(resource_name), refs(0) {}; | |
51 | ||
52 | void setResourceName(const std::string& resource_name) { | |
53 | if(this->resource_name.empty()) this->resource_name = resource_name; | |
54 | }; | |
55 | ||
54 | 56 | int refcount() { return refs; }; |
55 | 57 | void addref() { refs++; }; |
56 | 58 | void deref() { refs--; }; |
63 | 65 | std::string resource_dir; |
64 | 66 | public: |
65 | 67 | |
66 | void setDir(std::string resource_dir); | |
68 | void setDir(const std::string& resource_dir); | |
67 | 69 | std::string getDir(); |
68 | 70 | |
69 | 71 | ResourceManager(); |
72 | 74 | void purge(); |
73 | 75 | |
74 | 76 | void release(Resource* resource); |
75 | Resource* grab(std::string name); | |
76 | virtual Resource* create(std::string name) { return 0; }; | |
77 | Resource* grab(const std::string& resource_name); | |
78 | virtual Resource* create(const std::string& name) { return 0; }; | |
77 | 79 | }; |
78 | 80 | |
79 | 81 | #endif |
40 | 40 | |
41 | 41 | #ifdef _WIN32 |
42 | 42 | HWND gSDLAppConsoleWindow = 0; |
43 | bool using_parent_console = false; | |
44 | ||
45 | bool SDLAppAttachToConsole() { | |
46 | if(using_parent_console) return true; | |
47 | if(gSDLAppConsoleWindow != 0) return false; | |
48 | ||
49 | // if TERM is set to msys, try and attach to console | |
50 | // could possibly add other supported TERMs here if there are any | |
51 | ||
52 | char* term = getenv("TERM"); | |
53 | if(!term || strcmp(term, "msys")!=0) return false; | |
54 | ||
55 | if(AttachConsole(ATTACH_PARENT_PROCESS)) { | |
56 | ||
57 | // send stdout to console unless already redirected | |
58 | if (_fileno(stdout) == -1 || _get_osfhandle(fileno(stdout)) == -1) { | |
59 | freopen("conout$","w", stdout); | |
60 | } | |
61 | ||
62 | // send stderr to console unless already redirected | |
63 | if (_fileno(stderr) == -1 || _get_osfhandle(fileno(stderr)) == -1) { | |
64 | freopen("conout$","w", stderr); | |
65 | } | |
66 | ||
67 | using_parent_console = true; | |
68 | } | |
69 | ||
70 | return using_parent_console; | |
71 | } | |
43 | 72 | |
44 | 73 | void SDLAppCreateWindowsConsole() { |
45 | if(gSDLAppConsoleWindow !=0) return; | |
74 | if(using_parent_console || gSDLAppConsoleWindow != 0) return; | |
75 | ||
76 | //try to attach to the available console if there is one | |
77 | ||
78 | if(SDLAppAttachToConsole()) return; | |
46 | 79 | |
47 | 80 | //create a console on Windows so users can see messages |
48 | ||
49 | 81 | //find an available name for our window |
82 | ||
83 | char consoleTitle[512]; | |
50 | 84 | int console_suffix = 0; |
51 | char consoleTitle[512]; | |
52 | 85 | sprintf(consoleTitle, "%s Console", gSDLAppTitle.c_str()); |
53 | 86 | |
54 | 87 | while(FindWindow(0, consoleTitle)) { |
71 | 104 | SDL_Delay(100); |
72 | 105 | } |
73 | 106 | |
74 | //disable the close button so the user cant crash gource | |
107 | //disable the close button so the user cant crash the application | |
75 | 108 | HMENU hm = GetSystemMenu(gSDLAppConsoleWindow, false); |
76 | 109 | DeleteMenu(hm, SC_CLOSE, MF_BYCOMMAND); |
77 | 110 | } |
112 | 145 | printf("%s\n", msg.c_str()); |
113 | 146 | |
114 | 147 | #ifdef _WIN32 |
115 | printf("\nPress Enter\n"); | |
116 | getchar(); | |
148 | if(gSDLAppConsoleWindow) { | |
149 | printf("\nPress Enter\n"); | |
150 | getchar(); | |
151 | } | |
117 | 152 | #endif |
118 | 153 | |
119 | 154 | exit(0); |
131 | 166 | fprintf(stderr, "Try '%s --help' for more information.\n\n", gSDLAppExec.c_str()); |
132 | 167 | |
133 | 168 | #ifdef _WIN32 |
134 | fprintf(stderr, "Press Enter\n"); | |
135 | getchar(); | |
169 | if(gSDLAppConsoleWindow) { | |
170 | fprintf(stderr, "Press Enter\n"); | |
171 | getchar(); | |
172 | } | |
136 | 173 | #endif |
137 | 174 | |
138 | 175 | exit(1); |
263 | 300 | fps=0; |
264 | 301 | return_code=0; |
265 | 302 | appFinished=false; |
303 | min_delta_msec = 8; | |
266 | 304 | } |
267 | 305 | |
268 | 306 | void SDLApp::updateFramerate() { |
308 | 346 | |
309 | 347 | // cant have delta ticks be less than 8ms |
310 | 348 | buffer_msec += delta_msec; |
311 | if(buffer_msec < 8) { | |
349 | if(buffer_msec < min_delta_msec) { | |
312 | 350 | SDL_Delay(1); |
313 | 351 | continue; |
314 | 352 | } |
335 | 373 | |
336 | 374 | switch(event.type) { |
337 | 375 | case SDL_QUIT: |
338 | appFinished=true; | |
376 | quit(); | |
339 | 377 | break; |
340 | 378 | |
341 | 379 | case SDL_MOUSEMOTION: |
342 | 380 | mouseMove(&event.motion); |
343 | 381 | break; |
382 | ||
383 | #if SDL_VERSION_ATLEAST(1,3,0) | |
384 | case SDL_MOUSEWHEEL: | |
385 | mouseWheel(&event.wheel); | |
386 | break; | |
387 | ||
388 | case SDL_WINDOWEVENT: | |
389 | if(event.window.event == SDL_WINDOWEVENT_RESIZED) { | |
390 | resize(event.window.data1, event.window.data2); | |
391 | } | |
392 | break; | |
393 | #else | |
394 | case SDL_VIDEORESIZE: | |
395 | resize(event.resize.w, event.resize.h); | |
396 | break; | |
397 | #endif | |
344 | 398 | |
345 | 399 | case SDL_MOUSEBUTTONDOWN: |
346 | 400 | mouseClick(&event.button); |
27 | 27 | #ifndef SDLAPP_H |
28 | 28 | #define SDLAPP_H |
29 | 29 | |
30 | #ifdef _WIN32 | |
31 | ||
32 | #ifdef _WIN32_WINNT | |
33 | #undef _WIN32_WINNT | |
34 | #endif | |
35 | ||
36 | #define _WIN32_WINNT 0x0501 | |
37 | #include "windows.h" | |
38 | #endif | |
39 | ||
30 | 40 | #include "display.h" |
31 | 41 | #include "logger.h" |
32 | 42 | |
41 | 51 | extern std::string gSDLAppExec; |
42 | 52 | |
43 | 53 | #ifdef _WIN32 |
54 | extern HWND gSDLAppConsoleWindow; | |
55 | ||
56 | bool SDLAppAttachToConsole(); | |
44 | 57 | void SDLAppCreateWindowsConsole(); |
45 | 58 | void SDLAppResizeWindowsConsole(int height); |
46 | 59 | #endif |
62 | 75 | SDLAppException(const char* str, ...) : showhelp(false) { |
63 | 76 | |
64 | 77 | va_list vl; |
65 | char msg[1024]; | |
78 | char msg[4096]; | |
66 | 79 | |
67 | 80 | va_start(vl, str); |
68 | vsnprintf(msg, 1024, str, vl); | |
81 | vsnprintf(msg, 4096, str, vl); | |
69 | 82 | va_end(vl); |
70 | 83 | |
71 | 84 | message = std::string(msg); |
86 | 99 | int fps_updater; |
87 | 100 | int return_code; |
88 | 101 | |
89 | ||
90 | 102 | void updateFramerate(); |
91 | 103 | protected: |
104 | int min_delta_msec; | |
92 | 105 | bool appFinished; |
93 | 106 | void stop(int return_code); |
94 | 107 | public: |
99 | 112 | |
100 | 113 | int run(); |
101 | 114 | |
115 | virtual void resize(int width, int height) {}; | |
116 | ||
102 | 117 | virtual void update(float t, float dt) {}; |
103 | 118 | virtual void init() {}; |
104 | 119 | |
105 | 120 | virtual void logic(float t, float dt) {}; |
106 | 121 | virtual void draw(float t, float dt) {}; |
107 | 122 | |
123 | virtual void quit() { appFinished = true; }; | |
124 | ||
108 | 125 | virtual void mouseMove(SDL_MouseMotionEvent *e) {}; |
109 | 126 | virtual void mouseClick(SDL_MouseButtonEvent *e) {}; |
110 | 127 | virtual void keyPress(SDL_KeyboardEvent *e) {}; |
128 | ||
129 | #if SDL_VERSION_ATLEAST(1,3,0) | |
130 | virtual void mouseWheel(SDL_MouseWheelEvent *e) {}; | |
131 | #endif | |
111 | 132 | |
112 | 133 | int returnCode(); |
113 | 134 | bool isFinished(); |
41 | 41 | int ret = fcntl(STDIN_FILENO, F_GETFL, 0); |
42 | 42 | |
43 | 43 | if (fcntl (STDIN_FILENO, F_SETFL, ret | O_NONBLOCK) < 0) { |
44 | debugLog("fcntl(stdin) failed\n"); | |
44 | debugLog("fcntl(stdin) failed"); | |
45 | 45 | fcntl_fail = true; |
46 | 46 | } |
47 | 47 | #endif |
213 | 213 | bool finished = false; |
214 | 214 | |
215 | 215 | if(stream->fail() || stream->eof()) { |
216 | debugLog("stream is finished\n"); | |
216 | //debugLog("stream is finished"); | |
217 | 217 | finished=true; |
218 | 218 | } |
219 | 219 |
17 | 17 | #include "settings.h" |
18 | 18 | |
19 | 19 | Regex SDLAppSettings_rect_regex("^([0-9.]+)x([0-9.]+)$"); |
20 | Regex SDLAppSettings_viewport_regex("^([0-9.]+)x([0-9.]+)(!)?$"); | |
20 | 21 | |
21 | 22 | SDLAppSettings::SDLAppSettings() { |
22 | 23 | setDisplayDefaults(); |
53 | 54 | |
54 | 55 | void SDLAppSettings::setDisplayDefaults() { |
55 | 56 | display_width = 1024; |
57 | #ifdef __APPLE__ | |
58 | display_height = 640; | |
59 | #else | |
56 | 60 | display_height = 768; |
61 | #endif | |
57 | 62 | fullscreen = false; |
58 | 63 | multisample = false; |
59 | 64 | transparent = false; |
65 | resizable = true; | |
60 | 66 | vsync = true; |
61 | 67 | |
62 | 68 | output_ppm_filename = ""; |
68 | 74 | ConfSection* section = new ConfSection("display"); |
69 | 75 | |
70 | 76 | char viewportbuff[256]; |
71 | snprintf(viewportbuff, 256, "%dx%d", display_width, display_height); | |
77 | snprintf(viewportbuff, 256, "%dx%d%s", display_width, display_height, resizable ? "" : "!" ); | |
72 | 78 | |
73 | 79 | std::string viewport = std::string(viewportbuff); |
74 | 80 | |
81 | 87 | section->setEntry(new ConfEntry("multi-sampling", multisample)); |
82 | 88 | |
83 | 89 | if(!vsync) { |
84 | section->setEntry(new ConfEntry("no-vsync", vsync)); | |
85 | } | |
86 | ||
90 | section->setEntry(new ConfEntry("no-vsync", true)); | |
91 | } | |
92 | ||
87 | 93 | conf.setSection(section); |
88 | 94 | } |
89 | 95 | |
90 | bool SDLAppSettings::parseRectangle(const std::string& value, int* x, int* y) { | |
96 | bool SDLAppSettings::parseRectangle(const std::string& value, int& x, int& y) { | |
91 | 97 | |
92 | 98 | std::vector<std::string> matches; |
93 | 99 | |
94 | 100 | if(SDLAppSettings_rect_regex.match(value, &matches)) { |
95 | if(x!=0) *x = atoi(matches[0].c_str()); | |
96 | if(y!=0) *y = atoi(matches[1].c_str()); | |
101 | ||
102 | x = atoi(matches[0].c_str()); | |
103 | y = atoi(matches[1].c_str()); | |
104 | ||
97 | 105 | return true; |
98 | 106 | } |
99 | 107 | |
100 | 108 | return false; |
101 | 109 | } |
110 | ||
111 | bool SDLAppSettings::parseViewport(const std::string& value, int& x, int& y, bool& no_resize) { | |
112 | ||
113 | std::vector<std::string> matches; | |
114 | ||
115 | if(SDLAppSettings_viewport_regex.match(value, &matches)) { | |
116 | x = atoi(matches[0].c_str()); | |
117 | y = atoi(matches[1].c_str()); | |
118 | ||
119 | if(matches.size()>2) no_resize = true; | |
120 | ||
121 | if(x>0 && y>0) return true; | |
122 | } | |
123 | ||
124 | return false; | |
125 | } | |
126 | ||
102 | 127 | |
103 | 128 | void SDLAppSettings::parseArgs(int argc, char *argv[], ConfFile& conffile, std::vector<std::string>* files) { |
104 | 129 | |
148 | 173 | |
149 | 174 | int width = 0; |
150 | 175 | int height = 0; |
151 | ||
152 | if(parseRectangle(displayarg, &width, &height)) { | |
176 | bool no_resize = false; | |
177 | ||
178 | if(parseViewport(displayarg, width, height, no_resize)) { | |
153 | 179 | if(width>0 && height>0) { |
154 | 180 | |
155 | 181 | ConfSection* display_settings = conffile.getSection("display"); |
158 | 184 | display_settings = conffile.addSection("display"); |
159 | 185 | } |
160 | 186 | |
161 | display_settings->setEntry("viewport", args); | |
187 | display_settings->setEntry("viewport", displayarg); | |
188 | ||
162 | 189 | continue; |
163 | 190 | } |
164 | 191 | } |
230 | 257 | |
231 | 258 | std::string viewport = entry->getString(); |
232 | 259 | |
260 | ||
261 | ||
233 | 262 | int width = 0; |
234 | 263 | int height = 0; |
235 | ||
236 | size_t x = viewport.rfind("x"); | |
237 | ||
238 | if(x != std::string::npos && x != 0 && x != viewport.size()-1) { | |
239 | std::string widthstr = viewport.substr(0, x); | |
240 | std::string heightstr = viewport.substr(x+1); | |
241 | ||
242 | width = atoi(widthstr.c_str()); | |
243 | height = atoi(heightstr.c_str()); | |
244 | } | |
245 | ||
246 | if(width>0 && height>0) { | |
247 | display_width = width; | |
248 | display_height = height; | |
264 | bool no_resize = false; | |
265 | ||
266 | if(parseViewport(viewport, width, height, no_resize)) { | |
267 | display_width = width; | |
268 | display_height = height; | |
269 | if(no_resize) resizable = false; | |
249 | 270 | } else { |
250 | 271 | conffile.invalidValueException(entry); |
251 | 272 | } |
270 | 291 | if(display_settings->getBool("no-vsync")) { |
271 | 292 | vsync = false; |
272 | 293 | } |
273 | ||
294 | ||
274 | 295 | if((entry = display_settings->getEntry("output-ppm-stream")) != 0) { |
275 | 296 | |
276 | 297 | if(!entry->hasValue()) { |
31 | 31 | |
32 | 32 | virtual void commandLineOption(const std::string& name, const std::string& value) {} |
33 | 33 | |
34 | bool parseRectangle(const std::string& value, int* x=0, int* y=0); | |
34 | bool parseRectangle(const std::string& value, int& x, int& y); | |
35 | bool parseViewport(const std::string& value, int& x, int& y, bool& no_resize); | |
36 | ||
35 | 37 | public: |
36 | 38 | int display_width; |
37 | 39 | int display_height; |
38 | 40 | bool multisample; |
39 | 41 | bool fullscreen; |
40 | 42 | bool transparent; |
43 | bool resizable; | |
41 | 44 | bool vsync; |
42 | ||
45 | ||
43 | 46 | std::string output_ppm_filename; |
44 | 47 | int output_framerate; |
45 | 48 |
30 | 30 | |
31 | 31 | //ShaderManager |
32 | 32 | |
33 | Regex Shader_pre_include("\\s*#include\\s*\"([^\"]+)\""); | |
33 | ShaderManager::ShaderManager() { | |
34 | warnings = false; | |
35 | } | |
36 | ||
37 | void ShaderManager::enableWarnings(bool warnings) { | |
38 | this->warnings = warnings; | |
39 | } | |
40 | ||
41 | Regex Shader_pre_version("^\\s*#version\\s*(\\d+)\\s*$"); | |
42 | Regex Shader_pre_extension("^\\s*#extension\\s*([a-zA-Z0-9_]+)\\s+:\\s+(enable|require|warn|disable)\\s*$"); | |
43 | Regex Shader_pre_include("^\\s*#include\\s*\"([^\"]+)\""); | |
44 | Regex Shader_uniform_def("^\\s*uniform\\s+(\\w+)\\s+(\\w+)(?:\\[(\\d+)\\])?\\s*;\\s*$"); | |
45 | Regex Shader_error_line("\\b\\d*\\((\\d+)\\) : error "); | |
46 | Regex Shader_error2_line("\\bERROR: \\d+:(\\d+):"); | |
47 | Regex Shader_warning_line("\\b\\d*\\((\\d+)\\) : warning "); | |
34 | 48 | |
35 | 49 | Shader* ShaderManager::grab(const std::string& shader_prefix) { |
36 | 50 | Resource* s = resources[shader_prefix]; |
45 | 59 | return (Shader*) s; |
46 | 60 | } |
47 | 61 | |
48 | //Shader | |
49 | Shader::Shader(const std::string& prefix) : Resource(prefix) { | |
50 | ||
51 | std::string shader_dir = shadermanager.getDir(); | |
52 | ||
53 | std::string vertexSrc = shader_dir + prefix + std::string(".vert"); | |
54 | std::string fragmentSrc = shader_dir + prefix + std::string(".frag"); | |
55 | ||
56 | vertexShader = load(vertexSrc, GL_VERTEX_SHADER); | |
57 | fragmentShader = load(fragmentSrc, GL_FRAGMENT_SHADER); | |
58 | ||
59 | makeProgram(); | |
60 | } | |
61 | ||
62 | Shader::~Shader() { | |
63 | glDeleteShader(vertexShader); | |
64 | glDeleteShader(fragmentShader); | |
65 | glDeleteProgram(shaderProg); | |
66 | } | |
67 | ||
68 | void Shader::makeProgram() { | |
69 | shaderProg = glCreateProgram(); | |
70 | glAttachShader(shaderProg,fragmentShader); | |
71 | glAttachShader(shaderProg,vertexShader); | |
72 | glLinkProgram(shaderProg); | |
73 | } | |
74 | ||
75 | void Shader::checkError(const std::string& filename, GLenum shaderRef) { | |
76 | ||
77 | GLint compile_success; | |
78 | glGetShaderiv(shaderRef, GL_COMPILE_STATUS, &compile_success); | |
62 | void ShaderManager::manage(Shader* shader) { | |
63 | ||
64 | if(shader->resource_name.empty()) { | |
65 | throw SDLAppException("Cannot manage shader with no resource name"); | |
66 | } | |
67 | ||
68 | if(resources[shader->resource_name] != 0) { | |
69 | throw SDLAppException("A shader resource already exists under the name '%s'", shader->resource_name.c_str()); | |
70 | } | |
71 | ||
72 | resources[shader->resource_name] = shader; | |
73 | ||
74 | shader->addref(); | |
75 | } | |
76 | ||
77 | void ShaderManager::unload() { | |
78 | for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) { | |
79 | ((Shader*)it->second)->unload(); | |
80 | } | |
81 | } | |
82 | ||
83 | void ShaderManager::reload() { | |
84 | for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) { | |
85 | ((Shader*)it->second)->load(); | |
86 | } | |
87 | } | |
88 | ||
89 | //ShaderUniform | |
90 | ||
91 | ShaderUniform::ShaderUniform(Shader* shader, const std::string& name, int uniform_type, const std::string& type_name) | |
92 | : shader(shader), name(name), location(-1), initialized(false), modified(false), baked(false), uniform_type(uniform_type), type_name(type_name) { | |
93 | } | |
94 | ||
95 | void ShaderUniform::unload() { | |
96 | location = -1; | |
97 | } | |
98 | ||
99 | const std::string& ShaderUniform::getName() const { | |
100 | return name; | |
101 | } | |
102 | ||
103 | GLint ShaderUniform::getLocation() { | |
104 | ||
105 | // TODO: (re-)compiling the shader should break the uniform location caching. | |
106 | ||
107 | if(location != -1) return location; | |
108 | ||
109 | location = glGetUniformLocation( shader->getProgram(), name.c_str() ); | |
110 | ||
111 | return location; | |
112 | } | |
113 | ||
114 | void ShaderUniform::setBaked(bool baked) { | |
115 | if(this->baked == baked) return; | |
116 | this->baked = baked; | |
117 | modified = true; | |
118 | } | |
119 | ||
120 | ||
121 | //FloatShaderUniform | |
122 | ||
123 | FloatShaderUniform::FloatShaderUniform(Shader* shader, const std::string& name, float value) : | |
124 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_FLOAT, "float") { | |
125 | } | |
126 | ||
127 | void FloatShaderUniform::setValue(float value) { | |
128 | if(baked && this->value == value) return; | |
129 | ||
130 | this->value = value; | |
131 | modified = true; | |
132 | initialized = true; | |
133 | } | |
134 | ||
135 | void FloatShaderUniform::apply() { | |
136 | glUniform1f(getLocation(), value); | |
137 | } | |
138 | ||
139 | float FloatShaderUniform::getValue() const { | |
140 | return value; | |
141 | } | |
142 | ||
143 | void FloatShaderUniform::write(std::string& content) const { | |
144 | ||
145 | char buff[256]; | |
146 | ||
147 | if(baked) { | |
148 | // snprintf(buff, 256, "const %s %s = %e;\n", type_name.c_str(), name.c_str(), value); | |
149 | snprintf(buff, 256, "#define %s %e\n", name.c_str(), value); | |
150 | } else { | |
151 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
152 | } | |
153 | ||
154 | content += buff; | |
155 | } | |
156 | ||
157 | //IntShaderUniform | |
158 | ||
159 | IntShaderUniform::IntShaderUniform(Shader* shader, const std::string& name, int value) : | |
160 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_INT, "int") { | |
161 | } | |
162 | ||
163 | void IntShaderUniform::setValue(int value) { | |
164 | if(baked && this->value == value) return; | |
165 | ||
166 | this->value = value; | |
167 | modified = true; | |
168 | initialized = true; | |
169 | } | |
170 | ||
171 | void IntShaderUniform::apply() { | |
172 | glUniform1i(getLocation(), value); | |
173 | } | |
174 | ||
175 | float IntShaderUniform::getValue() const { | |
176 | return value; | |
177 | } | |
178 | ||
179 | void IntShaderUniform::write(std::string& content) const { | |
180 | ||
181 | char buff[256]; | |
182 | ||
183 | if(baked) { | |
184 | snprintf(buff, 256, "#define %s %d\n", name.c_str(), value); | |
185 | } else { | |
186 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
187 | } | |
188 | ||
189 | content += buff; | |
190 | } | |
191 | ||
192 | //BoolShaderUniform | |
193 | ||
194 | BoolShaderUniform::BoolShaderUniform(Shader* shader, const std::string& name, bool value) : | |
195 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_BOOL, "bool") { | |
196 | } | |
197 | ||
198 | void BoolShaderUniform::setValue(bool value) { | |
199 | if(baked && this->value == value) return; | |
200 | ||
201 | this->value = value; | |
202 | modified = true; | |
203 | initialized = true; | |
204 | } | |
205 | ||
206 | void BoolShaderUniform::apply() { | |
207 | glUniform1i(getLocation(), value); | |
208 | } | |
209 | ||
210 | float BoolShaderUniform::getValue() const { | |
211 | return value; | |
212 | } | |
213 | ||
214 | void BoolShaderUniform::write(std::string& content) const { | |
215 | ||
216 | char buff[256]; | |
217 | ||
218 | if(baked) { | |
219 | snprintf(buff, 256, "#define %s %s\n", name.c_str(), value ? "true" : "false"); | |
220 | } else { | |
221 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
222 | } | |
223 | ||
224 | content += buff; | |
225 | } | |
226 | ||
227 | //Sampler1DShaderUniform | |
228 | ||
229 | Sampler1DShaderUniform::Sampler1DShaderUniform(Shader* shader, const std::string& name, int value) : | |
230 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_1D, "sampler1D") { | |
231 | } | |
232 | ||
233 | void Sampler1DShaderUniform::setValue(int value) { | |
234 | if(baked && this->value == value) return; | |
235 | ||
236 | this->value = value; | |
237 | modified = true; | |
238 | initialized = true; | |
239 | } | |
240 | ||
241 | void Sampler1DShaderUniform::setBaked(bool baked) { | |
242 | } | |
243 | ||
244 | void Sampler1DShaderUniform::write(std::string& content) const { | |
245 | char buff[256]; | |
246 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
247 | content += buff; | |
248 | } | |
249 | ||
250 | void Sampler1DShaderUniform::apply() { | |
251 | glUniform1i(getLocation(), value); | |
252 | } | |
253 | ||
254 | float Sampler1DShaderUniform::getValue() const { | |
255 | return value; | |
256 | } | |
257 | ||
258 | //Sampler2DShaderUniform | |
259 | ||
260 | Sampler2DShaderUniform::Sampler2DShaderUniform(Shader* shader, const std::string& name, int value) : | |
261 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_SAMPLER_2D, "sampler2D") { | |
262 | } | |
263 | ||
264 | void Sampler2DShaderUniform::setValue(int value) { | |
265 | if(baked && this->value == value) return; | |
266 | ||
267 | this->value = value; | |
268 | modified = true; | |
269 | initialized = true; | |
270 | } | |
271 | ||
272 | void Sampler2DShaderUniform::apply() { | |
273 | glUniform1i(getLocation(), value); | |
274 | } | |
275 | ||
276 | float Sampler2DShaderUniform::getValue() const { | |
277 | return value; | |
278 | } | |
279 | ||
280 | //cant be baked | |
281 | void Sampler2DShaderUniform::setBaked(bool baked) { | |
282 | } | |
283 | ||
284 | void Sampler2DShaderUniform::write(std::string& content) const { | |
285 | char buff[256]; | |
286 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
287 | content += buff; | |
288 | } | |
289 | ||
290 | ||
291 | //Vec2ShaderUniform | |
292 | ||
293 | Vec2ShaderUniform::Vec2ShaderUniform(Shader* shader, const std::string& name, const vec2& value) : | |
294 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC2, "vec2") { | |
295 | } | |
296 | ||
297 | void Vec2ShaderUniform::setValue(const vec2& value) { | |
298 | if(baked && this->value == value) return; | |
299 | ||
300 | this->value = value; | |
301 | modified = true; | |
302 | initialized = true; | |
303 | } | |
304 | ||
305 | void Vec2ShaderUniform::apply() { | |
306 | glUniform2fv(getLocation(), 1, glm::value_ptr(value)); | |
307 | } | |
308 | ||
309 | const vec2& Vec2ShaderUniform::getValue() const { | |
310 | return value; | |
311 | } | |
312 | ||
313 | void Vec2ShaderUniform::write(std::string& content) const { | |
314 | ||
315 | char buff[256]; | |
316 | ||
317 | if(baked) { | |
318 | snprintf(buff, 256, "#define %s vec2(%e, %e)\n", name.c_str(), value.x, value.y); | |
319 | } else { | |
320 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
321 | } | |
322 | ||
323 | content += buff; | |
324 | } | |
325 | ||
326 | //Vec3ShaderUniform | |
327 | ||
328 | Vec3ShaderUniform::Vec3ShaderUniform(Shader* shader, const std::string& name, const vec3& value) : | |
329 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC3, "vec3") { | |
330 | } | |
331 | ||
332 | ||
333 | void Vec3ShaderUniform::setValue(const vec3& value) { | |
334 | if(baked && this->value == value) return; | |
335 | ||
336 | this->value = value; | |
337 | modified = true; | |
338 | initialized = true; | |
339 | } | |
340 | ||
341 | void Vec3ShaderUniform::apply() { | |
342 | glUniform3fv(getLocation(), 1, glm::value_ptr(value)); | |
343 | } | |
344 | ||
345 | ||
346 | const vec3& Vec3ShaderUniform::getValue() const { | |
347 | return value; | |
348 | } | |
349 | ||
350 | void Vec3ShaderUniform::write(std::string& content) const { | |
351 | ||
352 | char buff[256]; | |
353 | ||
354 | if(baked) { | |
355 | snprintf(buff, 256, "#define %s vec3(%e, %e, %e)\n", name.c_str(), value.x, value.y, value.z); | |
356 | } else { | |
357 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
358 | } | |
359 | ||
360 | content += buff; | |
361 | } | |
362 | ||
363 | //Vec4ShaderUniform | |
364 | ||
365 | Vec4ShaderUniform::Vec4ShaderUniform(Shader* shader, const std::string& name, const vec4& value) : | |
366 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_VEC4, "vec4") { | |
367 | } | |
368 | ||
369 | void Vec4ShaderUniform::setValue(const vec4& value) { | |
370 | if(baked && this->value == value) return; | |
371 | ||
372 | this->value = value; | |
373 | modified = true; | |
374 | initialized = true; | |
375 | } | |
376 | ||
377 | void Vec4ShaderUniform::apply() { | |
378 | glUniform4fv(getLocation(), 1, glm::value_ptr(value)); | |
379 | } | |
380 | ||
381 | const vec4& Vec4ShaderUniform::getValue() const { | |
382 | return value; | |
383 | } | |
384 | ||
385 | void Vec4ShaderUniform::write(std::string& content) const { | |
386 | ||
387 | char buff[256]; | |
388 | ||
389 | if(baked) { | |
390 | snprintf(buff, 256, "#define %s vec4(%e, %e, %e, %e)\n", name.c_str(), value.x, value.y, value.z, value.w); | |
391 | } else { | |
392 | snprintf(buff, 256, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
393 | } | |
394 | ||
395 | content += buff; | |
396 | } | |
397 | ||
398 | //Mat3ShaderUniform | |
399 | ||
400 | Mat3ShaderUniform::Mat3ShaderUniform(Shader* shader, const std::string& name, const mat3& value) : | |
401 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT3, "mat3") { | |
402 | } | |
403 | ||
404 | void Mat3ShaderUniform::setValue(const mat3& value) { | |
405 | if(baked && this->value == value) return; | |
406 | ||
407 | this->value = value; | |
408 | modified = true; | |
409 | initialized = true; | |
410 | } | |
411 | ||
412 | void Mat3ShaderUniform::apply() { | |
413 | glUniformMatrix3fv(getLocation(), 1, 0, glm::value_ptr(value)); | |
414 | } | |
415 | ||
416 | const mat3& Mat3ShaderUniform::getValue() const { | |
417 | return value; | |
418 | } | |
419 | ||
420 | void Mat3ShaderUniform::write(std::string& content) const { | |
421 | ||
422 | char buff[1024]; | |
423 | ||
424 | if(baked) { | |
425 | snprintf(buff, 1024, "#define %s mat3(%e, %e, %e, %e, %e, %e, %e, %e, %e)\n", name.c_str(), | |
426 | value[0][0], value[0][1], value[0][2], | |
427 | value[1][0], value[1][1], value[1][2], | |
428 | value[2][0], value[2][1], value[2][2]); | |
429 | ||
430 | } else { | |
431 | snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
432 | } | |
433 | ||
434 | content += buff; | |
435 | } | |
436 | ||
437 | //Mat4ShaderUniform | |
438 | ||
439 | Mat4ShaderUniform::Mat4ShaderUniform(Shader* shader, const std::string& name, const mat4& value) : | |
440 | value(value), ShaderUniform(shader, name, SHADER_UNIFORM_MAT4, "mat4") { | |
441 | } | |
442 | ||
443 | void Mat4ShaderUniform::setValue(const mat4& value) { | |
444 | if(baked && this->value == value) return; | |
445 | ||
446 | this->value = value; | |
447 | modified = true; | |
448 | initialized = true; | |
449 | } | |
450 | ||
451 | void Mat4ShaderUniform::apply() { | |
452 | glUniformMatrix4fv(getLocation(), 1, 0, glm::value_ptr(value)); | |
453 | } | |
454 | ||
455 | const mat4& Mat4ShaderUniform::getValue() const { | |
456 | return value; | |
457 | } | |
458 | ||
459 | void Mat4ShaderUniform::write(std::string& content) const { | |
460 | ||
461 | char buff[1024]; | |
462 | ||
463 | if(baked) { | |
464 | snprintf(buff, 1024, "#define %s mat4(%e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e, %e)\n", name.c_str(), | |
465 | value[0][0], value[0][1], value[0][2], value[0][3], | |
466 | value[1][0], value[1][1], value[1][2], value[1][3], | |
467 | value[2][0], value[2][1], value[2][2], value[2][3], | |
468 | value[3][0], value[3][1], value[3][2], value[3][3]); | |
469 | } else { | |
470 | snprintf(buff, 1024, "uniform %s %s;\n", type_name.c_str(), name.c_str()); | |
471 | } | |
472 | ||
473 | content += buff; | |
474 | } | |
475 | ||
476 | ||
477 | //Vec2ArrayShaderUniform | |
478 | ||
479 | Vec2ArrayShaderUniform::Vec2ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec2* value) : | |
480 | length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC2_ARRAY, "vec2") { | |
481 | this->value = new vec2[length]; | |
482 | if(value != 0) copyValue(value); | |
483 | } | |
484 | ||
485 | Vec2ArrayShaderUniform::~Vec2ArrayShaderUniform() { | |
486 | if(value) delete[] value; | |
487 | } | |
488 | ||
489 | const vec2* Vec2ArrayShaderUniform::getValue() const { | |
490 | return value; | |
491 | } | |
492 | ||
493 | void Vec2ArrayShaderUniform::copyValue(const vec2* value) { | |
494 | for(size_t i=0; i<length; i++) { | |
495 | this->value[i] = value[i]; | |
496 | } | |
497 | } | |
498 | ||
499 | void Vec2ArrayShaderUniform::copyValue(const std::vector<vec2>& value) { | |
500 | for(size_t i=0; i<length; i++) { | |
501 | this->value[i] = value[i]; | |
502 | } | |
503 | } | |
504 | ||
505 | void Vec2ArrayShaderUniform::setValue(const vec2* value) { | |
506 | if(baked) { | |
507 | bool match = true; | |
508 | ||
509 | for(size_t i=0;i<length;i++) { | |
510 | if(value[i] != this->value[i]) { | |
511 | match = false; | |
512 | break; | |
513 | } | |
514 | } | |
515 | ||
516 | if(match) return; | |
517 | } | |
518 | ||
519 | copyValue(value); | |
520 | ||
521 | modified = true; | |
522 | initialized = true; | |
523 | } | |
524 | ||
525 | void Vec2ArrayShaderUniform::setValue(const std::vector<vec2>& value) { | |
526 | if(baked) { | |
527 | bool match = true; | |
528 | ||
529 | for(size_t i=0;i<length;i++) { | |
530 | if(value[i] != this->value[i]) { | |
531 | match = false; | |
532 | break; | |
533 | } | |
534 | } | |
535 | ||
536 | if(match) return; | |
537 | } | |
538 | ||
539 | copyValue(value); | |
540 | ||
541 | modified = true; | |
542 | initialized = true; | |
543 | } | |
544 | ||
545 | void Vec2ArrayShaderUniform::apply() { | |
546 | glUniform2fv(getLocation(), length, glm::value_ptr(value[0])); | |
547 | } | |
548 | ||
549 | void Vec2ArrayShaderUniform::write(std::string& content) const { | |
550 | ||
551 | char buff[1024]; | |
552 | ||
553 | if(baked) { | |
554 | snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str()); | |
555 | ||
556 | content += buff; | |
557 | ||
558 | for(size_t i=0; i<length; i++) { | |
559 | snprintf(buff, 1024, " %s(%e, %e)", type_name.c_str(), value[i].x, value[i].y); | |
560 | content += buff; | |
561 | if(i<length-1) content += ",\n"; | |
562 | else content += "\n);\n"; | |
563 | } | |
564 | ||
565 | } else { | |
566 | snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length); | |
567 | content += buff; | |
568 | } | |
569 | } | |
570 | ||
571 | //Vec3ArrayShaderUniform | |
572 | ||
573 | Vec3ArrayShaderUniform::Vec3ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec3* value) : | |
574 | length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC3_ARRAY, "vec3") { | |
575 | this->value = new vec3[length]; | |
576 | if(value != 0) copyValue(value); | |
577 | } | |
578 | ||
579 | Vec3ArrayShaderUniform::~Vec3ArrayShaderUniform() { | |
580 | if(value) delete[] value; | |
581 | } | |
582 | ||
583 | const vec3* Vec3ArrayShaderUniform::getValue() const { | |
584 | return value; | |
585 | } | |
586 | ||
587 | void Vec3ArrayShaderUniform::copyValue(const vec3* value) { | |
588 | for(size_t i=0; i<length; i++) { | |
589 | this->value[i] = value[i]; | |
590 | } | |
591 | } | |
592 | ||
593 | void Vec3ArrayShaderUniform::copyValue(const std::vector<vec3>& value) { | |
594 | for(size_t i=0; i<length; i++) { | |
595 | this->value[i] = value[i]; | |
596 | } | |
597 | } | |
598 | ||
599 | void Vec3ArrayShaderUniform::setValue(const vec3* value) { | |
600 | if(baked) { | |
601 | bool match = true; | |
602 | ||
603 | for(size_t i=0;i<length;i++) { | |
604 | if(value[i] != this->value[i]) { | |
605 | match = false; | |
606 | break; | |
607 | } | |
608 | } | |
609 | ||
610 | if(match) return; | |
611 | } | |
612 | ||
613 | copyValue(value); | |
614 | ||
615 | modified = true; | |
616 | initialized = true; | |
617 | } | |
618 | ||
619 | void Vec3ArrayShaderUniform::setValue(const std::vector<vec3>& value) { | |
620 | if(baked) { | |
621 | bool match = true; | |
622 | ||
623 | for(size_t i=0;i<length;i++) { | |
624 | if(value[i] != this->value[i]) { | |
625 | match = false; | |
626 | break; | |
627 | } | |
628 | } | |
629 | ||
630 | if(match) return; | |
631 | } | |
632 | ||
633 | copyValue(value); | |
634 | ||
635 | modified = true; | |
636 | initialized = true; | |
637 | } | |
638 | ||
639 | void Vec3ArrayShaderUniform::apply() { | |
640 | glUniform3fv(getLocation(), length, glm::value_ptr(value[0])); | |
641 | } | |
642 | ||
643 | void Vec3ArrayShaderUniform::write(std::string& content) const { | |
644 | ||
645 | char buff[1024]; | |
646 | ||
647 | if(baked) { | |
648 | snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str()); | |
649 | ||
650 | content += buff; | |
651 | ||
652 | for(size_t i=0; i<length; i++) { | |
653 | snprintf(buff, 1024, " %s(%e, %e, %e)", type_name.c_str(), value[i].x, value[i].y, value[i].z); | |
654 | content += buff; | |
655 | if(i<length-1) content += ",\n"; | |
656 | else content += "\n);\n"; | |
657 | } | |
658 | ||
659 | } else { | |
660 | snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length); | |
661 | content += buff; | |
662 | } | |
663 | } | |
664 | ||
665 | //Vec4ArrayShaderUniform | |
666 | ||
667 | Vec4ArrayShaderUniform::Vec4ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec4* value) : | |
668 | length(length), ShaderUniform(shader, name, SHADER_UNIFORM_VEC4_ARRAY, "vec4") { | |
669 | this->value = new vec4[length]; | |
670 | if(value != 0) copyValue(value); | |
671 | } | |
672 | ||
673 | Vec4ArrayShaderUniform::~Vec4ArrayShaderUniform() { | |
674 | if(value) delete[] value; | |
675 | } | |
676 | ||
677 | const vec4* Vec4ArrayShaderUniform::getValue() const { | |
678 | return value; | |
679 | } | |
680 | ||
681 | void Vec4ArrayShaderUniform::copyValue(const std::vector<vec4>& value) { | |
682 | for(size_t i=0; i<length; i++) { | |
683 | this->value[i] = value[i]; | |
684 | } | |
685 | } | |
686 | ||
687 | void Vec4ArrayShaderUniform::copyValue(const vec4* value) { | |
688 | for(size_t i=0; i<length; i++) { | |
689 | this->value[i] = value[i]; | |
690 | } | |
691 | } | |
692 | ||
693 | void Vec4ArrayShaderUniform::setValue(const vec4* value) { | |
694 | if(baked) { | |
695 | bool match = true; | |
696 | ||
697 | for(size_t i=0;i<length;i++) { | |
698 | if(value[i] != this->value[i]) { | |
699 | match = false; | |
700 | break; | |
701 | } | |
702 | } | |
703 | ||
704 | if(match) return; | |
705 | } | |
706 | ||
707 | copyValue(value); | |
708 | ||
709 | modified = true; | |
710 | initialized = true; | |
711 | } | |
712 | ||
713 | void Vec4ArrayShaderUniform::setValue(const std::vector<vec4>& value) { | |
714 | if(baked) { | |
715 | bool match = true; | |
716 | ||
717 | for(size_t i=0;i<length;i++) { | |
718 | if(value[i] != this->value[i]) { | |
719 | match = false; | |
720 | break; | |
721 | } | |
722 | } | |
723 | ||
724 | if(match) return; | |
725 | } | |
726 | ||
727 | copyValue(value); | |
728 | ||
729 | modified = true; | |
730 | initialized = true; | |
731 | } | |
732 | ||
733 | void Vec4ArrayShaderUniform::apply() { | |
734 | glUniform4fv(getLocation(), length, glm::value_ptr(value[0])); | |
735 | } | |
736 | ||
737 | void Vec4ArrayShaderUniform::write(std::string& content) const { | |
738 | ||
739 | char buff[1024]; | |
740 | ||
741 | if(baked) { | |
742 | snprintf(buff, 1024, "%s[%ld] %s = %s[] (\n", type_name.c_str(), length, name.c_str(), type_name.c_str()); | |
743 | ||
744 | content += buff; | |
745 | ||
746 | for(size_t i=0; i<length; i++) { | |
747 | snprintf(buff, 1024, " %s(%e, %e, %e, %e)", type_name.c_str(), value[i].x, value[i].y, value[i].z, value[i].w); | |
748 | content += buff; | |
749 | if(i<length-1) content += ",\n"; | |
750 | else content += "\n);\n"; | |
751 | } | |
752 | ||
753 | } else { | |
754 | snprintf(buff, 1024, "uniform %s %s[%ld];\n", type_name.c_str(), name.c_str(), length); | |
755 | content += buff; | |
756 | } | |
757 | ||
758 | } | |
759 | ||
760 | //ShaderPass | |
761 | ||
762 | ShaderPass::ShaderPass(Shader* parent, GLint shader_object_type, const std::string& shader_object_desc) : parent(parent), shader_object_type(shader_object_type), shader_object_desc(shader_object_desc) { | |
763 | shader_object = 0; | |
764 | version = 0; | |
765 | } | |
766 | ||
767 | ShaderPass::~ShaderPass() { | |
768 | unload(); | |
769 | } | |
770 | ||
771 | void ShaderPass::unload() { | |
772 | if(shader_object!=0) glDeleteShader(shader_object); | |
773 | shader_object = 0; | |
774 | } | |
775 | ||
776 | void ShaderPass::attachTo(GLenum program) { | |
777 | glAttachShader(program, shader_object); | |
778 | } | |
779 | ||
780 | bool ShaderPass::errorContext(const char* log_message, std::string& context) { | |
781 | ||
782 | std::vector<std::string> matches; | |
783 | ||
784 | if( !Shader_error_line.match(log_message, &matches) | |
785 | && !Shader_error2_line.match(log_message, &matches) | |
786 | && !(shadermanager.warnings && Shader_warning_line.match(log_message, &matches))) | |
787 | return false; | |
788 | ||
789 | int line_no = atoi(matches[0].c_str()); | |
790 | ||
791 | std::stringstream in(shader_object_source); | |
792 | ||
793 | int i = 1; | |
794 | int amount = 3; | |
795 | ||
796 | char line_detail[1024]; | |
797 | ||
798 | std::string line; | |
799 | while( std::getline(in,line) ) { | |
800 | ||
801 | if(i==line_no || i<line_no && i+amount>=line_no || i>line_no && i-amount<=line_no) { | |
802 | snprintf(line_detail, 1024, "%s%4d | %s\n", (i==line_no ? "-> ": " "), i, line.c_str()); | |
803 | context += line_detail; | |
804 | } | |
805 | i++; | |
806 | } | |
807 | ||
808 | return true; | |
809 | } | |
810 | ||
811 | void ShaderPass::checkError() { | |
812 | if(!shader_object) return; | |
813 | ||
814 | GLint compile_success; | |
815 | glGetShaderiv(shader_object, GL_COMPILE_STATUS, &compile_success); | |
79 | 816 | |
80 | 817 | GLint info_log_length; |
81 | glGetShaderiv(shaderRef, GL_INFO_LOG_LENGTH, &info_log_length); | |
818 | glGetShaderiv(shader_object, GL_INFO_LOG_LENGTH, &info_log_length); | |
819 | ||
820 | const char* resource_desc = !parent->resource_name.empty() ? parent->resource_name.c_str() : "???"; | |
82 | 821 | |
83 | 822 | if(info_log_length > 1) { |
84 | 823 | char info_log[info_log_length]; |
85 | 824 | |
86 | glGetShaderInfoLog(shaderRef, info_log_length, &info_log_length, info_log); | |
825 | glGetShaderInfoLog(shader_object, info_log_length, &info_log_length, info_log); | |
826 | ||
827 | std::string context; | |
828 | errorContext(info_log, context); | |
87 | 829 | |
88 | 830 | if(!compile_success) { |
89 | throw SDLAppException("shader '%s' failed to compile: %s", filename.c_str(), info_log); | |
90 | } | |
91 | ||
92 | if(shadermanager.debug) { | |
93 | fprintf(stderr, "%s: %s\n", filename.c_str(), info_log); | |
831 | throw SDLAppException("%s shader '%s' failed to compile:\n%s\n%s", | |
832 | shader_object_desc.c_str(), | |
833 | resource_desc, | |
834 | info_log, | |
835 | context.c_str()); | |
836 | ||
837 | ||
838 | ||
839 | } | |
840 | ||
841 | if(shadermanager.warnings) { | |
842 | warnLog("%s shader '%s':\n%s\n%s", | |
843 | shader_object_desc.c_str(), | |
844 | resource_desc, | |
845 | info_log, | |
846 | context.c_str()); | |
847 | ||
94 | 848 | } |
95 | 849 | |
96 | 850 | return; |
97 | 851 | } |
98 | ||
852 | ||
99 | 853 | if(!compile_success) { |
100 | throw SDLAppException("shader '%s' failed to compile", filename.c_str()); | |
101 | } | |
102 | } | |
103 | ||
104 | GLenum Shader::load(const std::string& filename, GLenum shaderType) { | |
105 | ||
106 | std::string source; | |
107 | readSource(filename, source); | |
108 | ||
109 | if(source.empty()) { | |
110 | throw SDLAppException("could not read shader '%s'", filename.c_str()); | |
111 | } | |
112 | ||
113 | GLenum shaderRef = glCreateShader(shaderType); | |
114 | ||
115 | const char* source_ptr = source.c_str(); | |
116 | int source_len = source.size(); | |
117 | ||
118 | glShaderSource(shaderRef, 1, (const GLchar**) &source_ptr, &source_len); | |
119 | ||
120 | glCompileShader(shaderRef); | |
121 | ||
122 | checkError(filename, shaderRef); | |
123 | ||
124 | return shaderRef; | |
125 | } | |
126 | ||
127 | ||
128 | bool Shader::preprocess(const std::string& line, std::string& output) { | |
854 | throw SDLAppException("%s shader '%s' failed to compile", | |
855 | shader_object_desc.c_str(), | |
856 | resource_desc); | |
857 | } | |
858 | } | |
859 | ||
860 | void ShaderPass::toString(std::string& out) { | |
861 | if(version!=0) { | |
862 | out.append(str(boost::format("#version %d\n") % version)); | |
863 | } | |
864 | ||
865 | for(std::map<std::string, std::string>::iterator it = extensions.begin(); it != extensions.end(); it++) { | |
866 | out.append(str(boost::format("#extension %s : %s\n") % it->first % it->second)); | |
867 | } | |
868 | ||
869 | foreach(ShaderUniform* u, uniforms) { | |
870 | u->write(out); | |
871 | } | |
872 | ||
873 | out.append(source); | |
874 | } | |
875 | ||
876 | void ShaderPass::compile() { | |
877 | ||
878 | if(!shader_object) shader_object = glCreateShader(shader_object_type); | |
879 | ||
880 | if(source.empty()) return; | |
881 | ||
882 | shader_object_source.clear(); | |
883 | ||
884 | toString(shader_object_source); | |
885 | ||
886 | // apply subsitutions | |
887 | parent->applySubstitutions(shader_object_source); | |
888 | ||
889 | foreach(ShaderUniform* u, uniforms) { | |
890 | u->setModified(false); | |
891 | } | |
892 | ||
893 | //fprintf(stderr, "src:\n%s", shader_object_source.c_str()); | |
894 | ||
895 | const char* source_ptr = shader_object_source.c_str(); | |
896 | int source_len = shader_object_source.size(); | |
897 | ||
898 | glShaderSource(shader_object, 1, (const GLchar**) &source_ptr, &source_len); | |
899 | glCompileShader(shader_object); | |
900 | ||
901 | checkError(); | |
902 | } | |
903 | ||
904 | //add uniform, unless parent Shader has this in which case link to it | |
905 | ShaderUniform* ShaderPass::addArrayUniform(const std::string& name, const std::string& type, size_t length) { | |
906 | ||
907 | ShaderUniform* uniform = 0; | |
908 | ||
909 | if((uniform = parent->getUniform(name)) == 0) { | |
910 | ||
911 | if(type == "vec2") { | |
912 | uniform = new Vec2ArrayShaderUniform(parent, name, length); | |
913 | } else if(type == "vec3") { | |
914 | uniform = new Vec3ArrayShaderUniform(parent, name, length); | |
915 | } else if(type == "vec4") { | |
916 | uniform = new Vec4ArrayShaderUniform(parent, name, length); | |
917 | } else { | |
918 | throw SDLAppException("shader uniform arrays for type '%s' not implemented", type.c_str()); | |
919 | } | |
920 | ||
921 | uniform->setInitialized(false); | |
922 | ||
923 | parent->addUniform(uniform); | |
924 | } | |
925 | ||
926 | uniforms.push_back(uniform); | |
927 | ||
928 | return uniform; | |
929 | } | |
930 | ||
931 | ShaderUniform* ShaderPass::addUniform(const std::string& name, const std::string& type) { | |
932 | ||
933 | ShaderUniform* uniform = 0; | |
934 | ||
935 | if((uniform = parent->getUniform(name)) == 0) { | |
936 | ||
937 | if(type == "float") { | |
938 | uniform = new FloatShaderUniform(parent, name); | |
939 | } else if(type == "int") { | |
940 | uniform = new IntShaderUniform(parent, name); | |
941 | } else if(type == "bool") { | |
942 | uniform = new BoolShaderUniform(parent, name); | |
943 | } else if(type == "sampler1D") { | |
944 | uniform = new Sampler1DShaderUniform(parent, name); | |
945 | } else if(type == "sampler2D") { | |
946 | uniform = new Sampler2DShaderUniform(parent, name); | |
947 | } else if(type == "vec2") { | |
948 | uniform = new Vec2ShaderUniform(parent, name); | |
949 | } else if(type == "vec3") { | |
950 | uniform = new Vec3ShaderUniform(parent, name); | |
951 | } else if(type == "vec4") { | |
952 | uniform = new Vec4ShaderUniform(parent, name); | |
953 | } else if(type == "mat3") { | |
954 | uniform = new Mat3ShaderUniform(parent, name); | |
955 | } else if(type == "mat4") { | |
956 | uniform = new Mat4ShaderUniform(parent, name); | |
957 | } else { | |
958 | throw SDLAppException("unsupported shader uniform type '%s'", type.c_str()); | |
959 | } | |
960 | ||
961 | uniform->setInitialized(false); | |
962 | ||
963 | parent->addUniform(uniform); | |
964 | } | |
965 | ||
966 | uniforms.push_back(uniform); | |
967 | ||
968 | return uniform; | |
969 | } | |
970 | ||
971 | bool ShaderPass::preprocess(const std::string& line) { | |
129 | 972 | |
130 | 973 | std::vector<std::string> matches; |
131 | 974 | |
975 | if(Shader_pre_version.match(line, &matches)) { | |
976 | version = atoi(matches[0].c_str()); | |
977 | return true; | |
978 | } | |
979 | ||
980 | if(Shader_pre_extension.match(line, &matches)) { | |
981 | extensions[matches[0]] = matches[1]; | |
982 | return true; | |
983 | } | |
984 | ||
132 | 985 | if(Shader_pre_include.match(line, &matches)) { |
133 | 986 | |
134 | 987 | std::string include_file = shadermanager.getDir() + matches[0]; |
135 | 988 | |
136 | readSource(include_file, output); | |
989 | includeFile(include_file); | |
137 | 990 | |
138 | 991 | return true; |
139 | 992 | } |
140 | 993 | |
994 | if(Shader_uniform_def.match(line, &matches)) { | |
995 | std::string uniform_type = matches[0]; | |
996 | std::string uniform_name = matches[1]; | |
997 | ||
998 | if(matches.size() > 2) { | |
999 | size_t uniform_length = atoi(matches[2].c_str()); | |
1000 | addArrayUniform(uniform_name, uniform_type, uniform_length); | |
1001 | } else { | |
1002 | addUniform(uniform_name, uniform_type); | |
1003 | } | |
1004 | ||
1005 | return true; | |
1006 | } | |
1007 | ||
141 | 1008 | return false; |
142 | ||
143 | } | |
144 | ||
145 | bool Shader::readSource(const std::string& file, std::string& output) { | |
1009 | } | |
1010 | ||
1011 | void ShaderPass::includeFile(const std::string& filename) { | |
146 | 1012 | |
147 | 1013 | // get length |
148 | std::ifstream in(file.c_str()); | |
1014 | std::ifstream in(filename.c_str()); | |
149 | 1015 | |
150 | 1016 | if(!in.is_open()) { |
151 | throw SDLAppException("could not open '%s'", file.c_str()); | |
1017 | throw SDLAppException("could not open '%s'", filename.c_str()); | |
152 | 1018 | } |
153 | 1019 | |
154 | 1020 | std::string line; |
155 | 1021 | while( std::getline(in,line) ) { |
156 | if(!preprocess(line, output)) { | |
157 | output += line; | |
158 | output += "\n"; | |
1022 | if(!preprocess(line)) { | |
1023 | source += line; | |
1024 | source += "\n"; | |
159 | 1025 | } |
160 | 1026 | } |
161 | 1027 | |
162 | 1028 | in.close(); |
163 | ||
164 | return true; | |
1029 | } | |
1030 | ||
1031 | void ShaderPass::includeSource(const std::string& string) { | |
1032 | ||
1033 | std::stringstream in(string); | |
1034 | ||
1035 | std::string line; | |
1036 | while( std::getline(in,line) ) { | |
1037 | if(!preprocess(line)) { | |
1038 | source += line; | |
1039 | source += "\n"; | |
1040 | } | |
1041 | } | |
1042 | } | |
1043 | ||
1044 | VertexShader::VertexShader(Shader* parent) : ShaderPass(parent, GL_VERTEX_SHADER, "vertex") { | |
1045 | } | |
1046 | ||
1047 | FragmentShader::FragmentShader(Shader* parent) : ShaderPass(parent, GL_FRAGMENT_SHADER, "fragment") { | |
1048 | } | |
1049 | ||
1050 | GeometryShader::GeometryShader(Shader* parent) : ShaderPass(parent, GL_GEOMETRY_SHADER_ARB, "geometry") { | |
1051 | } | |
1052 | ||
1053 | void GeometryShader::attachTo(GLenum program) { | |
1054 | ShaderPass::attachTo(program); | |
1055 | } | |
1056 | ||
1057 | //Shader | |
1058 | ||
1059 | Shader::Shader(const std::string& prefix) : Resource(prefix) { | |
1060 | ||
1061 | setDefaults(); | |
1062 | ||
1063 | std::string shader_dir = shadermanager.getDir(); | |
1064 | ||
1065 | std::string vertex_file = shader_dir + prefix + std::string(".vert"); | |
1066 | std::string fragment_file = shader_dir + prefix + std::string(".frag"); | |
1067 | ||
1068 | vertex_shader = new VertexShader(this); | |
1069 | vertex_shader->includeFile(vertex_file); | |
1070 | ||
1071 | fragment_shader = new FragmentShader(this); | |
1072 | fragment_shader->includeFile(fragment_file); | |
1073 | ||
1074 | load(); | |
1075 | } | |
1076 | ||
1077 | Shader::Shader() { | |
1078 | setDefaults(); | |
1079 | } | |
1080 | ||
1081 | void Shader::setDynamicCompile(bool dynamic_compile) { | |
1082 | this->dynamic_compile = dynamic_compile; | |
1083 | } | |
1084 | ||
1085 | void Shader::setDefaults() { | |
1086 | vertex_shader = 0; | |
1087 | fragment_shader = 0; | |
1088 | geometry_shader = 0; | |
1089 | program = 0; | |
1090 | dynamic_compile = false; | |
1091 | } | |
1092 | ||
1093 | Shader::~Shader() { | |
1094 | clear(); | |
1095 | } | |
1096 | ||
1097 | void Shader::clear() { | |
1098 | unload(); | |
1099 | ||
1100 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1101 | delete it->second; | |
1102 | } | |
1103 | uniforms.clear(); | |
1104 | ||
1105 | if(vertex_shader != 0) delete vertex_shader; | |
1106 | if(geometry_shader != 0) delete geometry_shader; | |
1107 | if(fragment_shader != 0) delete fragment_shader; | |
1108 | ||
1109 | vertex_shader = 0; | |
1110 | geometry_shader = 0; | |
1111 | fragment_shader = 0; | |
1112 | } | |
1113 | ||
1114 | void Shader::unload() { | |
1115 | if(program != 0) glDeleteProgram(program); | |
1116 | program = 0; | |
1117 | ||
1118 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1119 | it->second->unload(); | |
1120 | } | |
1121 | } | |
1122 | ||
1123 | void Shader::load() { | |
1124 | //fprintf(stderr, "load\n"); | |
1125 | ||
1126 | if(program !=0) unload(); | |
1127 | ||
1128 | if(vertex_shader != 0) vertex_shader->compile(); | |
1129 | if(geometry_shader != 0) geometry_shader->compile(); | |
1130 | if(fragment_shader != 0) fragment_shader->compile(); | |
1131 | ||
1132 | program = glCreateProgram(); | |
1133 | ||
1134 | if(vertex_shader!=0) vertex_shader->attachTo(program); | |
1135 | if(geometry_shader!=0) geometry_shader->attachTo(program); | |
1136 | if(fragment_shader!=0) fragment_shader->attachTo(program); | |
1137 | ||
1138 | glLinkProgram(program); | |
1139 | ||
1140 | checkProgramError(); | |
1141 | ||
1142 | if(vertex_shader != 0) vertex_shader->unload(); | |
1143 | if(geometry_shader != 0) geometry_shader->unload(); | |
1144 | if(fragment_shader != 0) fragment_shader->unload(); | |
1145 | } | |
1146 | ||
1147 | void Shader::checkProgramError() { | |
1148 | ||
1149 | GLint link_success; | |
1150 | glGetProgramiv(program, GL_LINK_STATUS, &link_success); | |
1151 | ||
1152 | GLint info_log_length; | |
1153 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length); | |
1154 | ||
1155 | const char* resource_desc = !resource_name.empty() ? resource_name.c_str() : "???"; | |
1156 | ||
1157 | if(info_log_length > 1) { | |
1158 | char info_log[info_log_length]; | |
1159 | ||
1160 | glGetProgramInfoLog(program, info_log_length, &info_log_length, info_log); | |
1161 | ||
1162 | if(!link_success) { | |
1163 | throw SDLAppException("shader '%s' failed to link:\n%s", | |
1164 | resource_desc, | |
1165 | info_log); | |
1166 | } | |
1167 | ||
1168 | if(shadermanager.warnings) { | |
1169 | warnLog("shader '%s':\n%s", | |
1170 | resource_desc, | |
1171 | info_log); | |
1172 | } | |
1173 | ||
1174 | return; | |
1175 | } | |
1176 | ||
1177 | if(!link_success) { | |
1178 | throw SDLAppException("shader '%s' failed to link", | |
1179 | resource_desc); | |
1180 | } | |
1181 | } | |
1182 | ||
1183 | void Shader::bind() { | |
1184 | glUseProgram(program); | |
1185 | } | |
1186 | ||
1187 | void Shader::unbind() { | |
1188 | glUseProgram(0); | |
165 | 1189 | } |
166 | 1190 | |
167 | 1191 | void Shader::use() { |
168 | glUseProgram(shaderProg); | |
1192 | ||
1193 | if(shadermanager.warnings) { | |
1194 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1195 | ShaderUniform* u = it->second; | |
1196 | ||
1197 | if(!u->isInitialized()) warnLog("shader '%s': uniform '%s' was never initialized", (!resource_name.empty() ? resource_name.c_str() : "???"), u->getName().c_str()); | |
1198 | } | |
1199 | } | |
1200 | ||
1201 | if(dynamic_compile && needsCompile()) { | |
1202 | unbind(); | |
1203 | load(); | |
1204 | infoLog("shader '%s' recompiled", resource_name.c_str()); | |
1205 | } | |
1206 | ||
1207 | bind(); | |
1208 | ||
1209 | applyUniforms(); | |
169 | 1210 | } |
170 | 1211 | |
171 | 1212 | GLenum Shader::getProgram() { |
172 | return shaderProg; | |
173 | } | |
174 | ||
175 | GLenum Shader::getVertexShader() { | |
176 | return vertexShader; | |
177 | } | |
178 | ||
179 | GLenum Shader::getFragmentShader() { | |
180 | return fragmentShader; | |
181 | } | |
182 | ||
183 | GLint Shader::getVarLocation(const std::string& name) { | |
184 | ||
185 | GLint loc = varMap[name] - 1; | |
186 | ||
187 | if(loc != -1) return loc; | |
188 | ||
189 | loc = glGetUniformLocation( shaderProg, name.c_str() ); | |
190 | ||
191 | varMap[name] = loc + 1; | |
192 | ||
193 | return loc; | |
1213 | return program; | |
1214 | } | |
1215 | ||
1216 | void Shader::addUniform(ShaderUniform* uniform) { | |
1217 | ||
1218 | if(getUniform(uniform->getName()) != 0) { | |
1219 | throw SDLAppException("shader already has a uniform named '%s'", uniform->getName().c_str() ); | |
1220 | } | |
1221 | ||
1222 | uniforms[uniform->getName()] = uniform; | |
1223 | } | |
1224 | ||
1225 | ShaderUniform* Shader::getUniform(const std::string& name) { | |
1226 | std::map<std::string, ShaderUniform*>::iterator it = uniforms.find(name); | |
1227 | ||
1228 | if(it != uniforms.end()) { | |
1229 | return it->second; | |
1230 | } | |
1231 | return 0; | |
1232 | } | |
1233 | ||
1234 | ShaderPass* Shader::grabShaderPass(GLenum shader_object_type) { | |
1235 | ||
1236 | ShaderPass* shader_pass = 0; | |
1237 | ||
1238 | switch(shader_object_type) { | |
1239 | case GL_VERTEX_SHADER: | |
1240 | if(!vertex_shader) vertex_shader = new VertexShader(this); | |
1241 | shader_pass = vertex_shader; | |
1242 | break; | |
1243 | case GL_GEOMETRY_SHADER_ARB: | |
1244 | if(!geometry_shader) geometry_shader = new GeometryShader(this); | |
1245 | shader_pass = geometry_shader; | |
1246 | break; | |
1247 | case GL_FRAGMENT_SHADER: | |
1248 | if(!fragment_shader) fragment_shader = new FragmentShader(this); | |
1249 | shader_pass = fragment_shader; | |
1250 | break; | |
1251 | } | |
1252 | ||
1253 | return shader_pass; | |
1254 | } | |
1255 | ||
1256 | ||
1257 | void Shader::includeSource(GLenum shader_object_type, const std::string& source) { | |
1258 | ||
1259 | ShaderPass* pass = grabShaderPass(shader_object_type); | |
1260 | ||
1261 | pass->includeSource(source); | |
1262 | } | |
1263 | ||
1264 | void Shader::includeFile(GLenum shader_object_type, const std::string& filename) { | |
1265 | ||
1266 | ShaderPass* pass = grabShaderPass(shader_object_type); | |
1267 | ||
1268 | pass->includeFile(filename); | |
1269 | } | |
1270 | ||
1271 | void Shader::addSubstitute(const std::string& name, const char *value, ...) { | |
1272 | ||
1273 | va_list vl; | |
1274 | char sub[4096]; | |
1275 | ||
1276 | va_start(vl, value); | |
1277 | vsnprintf(sub, 4096, value, vl); | |
1278 | va_end(vl); | |
1279 | ||
1280 | substitutions[name] = sub; | |
1281 | } | |
1282 | ||
1283 | void Shader::substitute(std::string& source, const std::string& name, const std::string& value) { | |
1284 | ||
1285 | std::string::size_type next_match; | |
1286 | ||
1287 | for(next_match = source.find(name); | |
1288 | next_match != std::string::npos; | |
1289 | next_match = source.find(name, next_match)) { | |
1290 | source.replace(next_match, name.length(), value); | |
1291 | next_match += value.length(); | |
1292 | } | |
1293 | } | |
1294 | ||
1295 | void Shader::applySubstitutions(std::string& source) { | |
1296 | ||
1297 | for(std::map<std::string, std::string>::iterator it = substitutions.begin(); it != substitutions.end(); it++) { | |
1298 | substitute(source, it->first, it->second); | |
1299 | } | |
1300 | } | |
1301 | ||
1302 | void Shader::setBool (const std::string& name, bool value) { | |
1303 | ShaderUniform* uniform = getUniform(name); | |
1304 | ||
1305 | if(!uniform || uniform->getType() != SHADER_UNIFORM_BOOL) return; | |
1306 | ||
1307 | ((BoolShaderUniform*)uniform)->setValue(value); | |
1308 | } | |
1309 | ||
1310 | void Shader::setInteger (const std::string& name, int value) { | |
1311 | ShaderUniform* uniform = getUniform(name); | |
1312 | ||
1313 | if(!uniform || uniform->getType() != SHADER_UNIFORM_INT) return; | |
1314 | ||
1315 | ((IntShaderUniform*)uniform)->setValue(value); | |
1316 | } | |
1317 | ||
1318 | void Shader::setSampler1D (const std::string& name, int value) { | |
1319 | ShaderUniform* uniform = getUniform(name); | |
1320 | ||
1321 | if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_1D) return; | |
1322 | ||
1323 | ((Sampler1DShaderUniform*)uniform)->setValue(value); | |
1324 | } | |
1325 | ||
1326 | void Shader::setSampler2D (const std::string& name, int value) { | |
1327 | ShaderUniform* uniform = getUniform(name); | |
1328 | ||
1329 | if(!uniform || uniform->getType() != SHADER_UNIFORM_SAMPLER_2D) return; | |
1330 | ||
1331 | ((Sampler2DShaderUniform*)uniform)->setValue(value); | |
194 | 1332 | } |
195 | 1333 | |
196 | 1334 | void Shader::setFloat(const std::string& name, float value) { |
197 | GLint loc = getVarLocation(name); | |
198 | glUniform1f(loc, value); | |
199 | } | |
200 | ||
201 | void Shader::setVec2 (const std::string& name, const vec2f& value) { | |
202 | GLint loc = getVarLocation(name); | |
203 | glUniform2fv(loc, 1, value); | |
204 | } | |
205 | ||
206 | void Shader::setVec3 (const std::string& name, const vec3f& value) { | |
207 | GLint loc = getVarLocation(name); | |
208 | glUniform3fv(loc, 1, value); | |
209 | } | |
210 | ||
211 | void Shader::setVec4 (const std::string& name, const vec4f& value) { | |
212 | GLint loc = getVarLocation(name); | |
213 | glUniform4fv(loc, 1, value); | |
214 | } | |
215 | ||
216 | void Shader::setInteger (const std::string& name, int value) { | |
217 | GLint loc = getVarLocation(name); | |
218 | glUniform1i(loc, value); | |
219 | } | |
220 | ||
221 | ||
222 | ||
1335 | ShaderUniform* uniform = getUniform(name); | |
1336 | ||
1337 | if(!uniform || uniform->getType() != SHADER_UNIFORM_FLOAT) return; | |
1338 | ||
1339 | ((FloatShaderUniform*)uniform)->setValue(value); | |
1340 | } | |
1341 | ||
1342 | void Shader::setVec2 (const std::string& name, const vec2& value) { | |
1343 | ShaderUniform* uniform = getUniform(name); | |
1344 | ||
1345 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2) return; | |
1346 | ||
1347 | ((Vec2ShaderUniform*)uniform)->setValue(value); | |
1348 | } | |
1349 | ||
1350 | void Shader::setVec3 (const std::string& name, const vec3& value) { | |
1351 | ShaderUniform* uniform = getUniform(name); | |
1352 | ||
1353 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3) return; | |
1354 | ||
1355 | ((Vec3ShaderUniform*)uniform)->setValue(value); | |
1356 | } | |
1357 | ||
1358 | void Shader::setVec2Array (const std::string& name, vec2* value) { | |
1359 | ShaderUniform* uniform = getUniform(name); | |
1360 | ||
1361 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return; | |
1362 | ||
1363 | ((Vec2ArrayShaderUniform*)uniform)->setValue(value); | |
1364 | } | |
1365 | ||
1366 | void Shader::setVec2Array (const std::string& name, std::vector<vec2>& value) { | |
1367 | ShaderUniform* uniform = getUniform(name); | |
1368 | ||
1369 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC2_ARRAY) return; | |
1370 | ||
1371 | ((Vec2ArrayShaderUniform*)uniform)->setValue(value); | |
1372 | } | |
1373 | ||
1374 | void Shader::setVec3Array (const std::string& name, vec3* value) { | |
1375 | ShaderUniform* uniform = getUniform(name); | |
1376 | ||
1377 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return; | |
1378 | ||
1379 | ((Vec3ArrayShaderUniform*)uniform)->setValue(value); | |
1380 | } | |
1381 | ||
1382 | void Shader::setVec3Array (const std::string& name, std::vector<vec3>& value) { | |
1383 | ShaderUniform* uniform = getUniform(name); | |
1384 | ||
1385 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC3_ARRAY) return; | |
1386 | ||
1387 | ((Vec3ArrayShaderUniform*)uniform)->setValue(value); | |
1388 | } | |
1389 | ||
1390 | void Shader::setVec4Array (const std::string& name, vec4* value) { | |
1391 | ShaderUniform* uniform = getUniform(name); | |
1392 | ||
1393 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return; | |
1394 | ||
1395 | ((Vec4ArrayShaderUniform*)uniform)->setValue(value); | |
1396 | } | |
1397 | ||
1398 | void Shader::setVec4Array (const std::string& name, std::vector<vec4>& value) { | |
1399 | ShaderUniform* uniform = getUniform(name); | |
1400 | ||
1401 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4_ARRAY) return; | |
1402 | ||
1403 | ((Vec4ArrayShaderUniform*)uniform)->setValue(value); | |
1404 | } | |
1405 | ||
1406 | void Shader::setVec4 (const std::string& name, const vec4& value) { | |
1407 | ShaderUniform* uniform = getUniform(name); | |
1408 | ||
1409 | if(!uniform || uniform->getType() != SHADER_UNIFORM_VEC4) return; | |
1410 | ||
1411 | ((Vec4ShaderUniform*)uniform)->setValue(value); | |
1412 | } | |
1413 | ||
1414 | void Shader::setMat3 (const std::string& name, const mat3& value) { | |
1415 | ShaderUniform* uniform = getUniform(name); | |
1416 | ||
1417 | if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT3) return; | |
1418 | ||
1419 | ((Mat3ShaderUniform*)uniform)->setValue(value); | |
1420 | } | |
1421 | ||
1422 | void Shader::setMat4 (const std::string& name, const mat4& value) { | |
1423 | ShaderUniform* uniform = getUniform(name); | |
1424 | ||
1425 | if(!uniform || uniform->getType() != SHADER_UNIFORM_MAT4) return; | |
1426 | ||
1427 | ((Mat4ShaderUniform*)uniform)->setValue(value); | |
1428 | } | |
1429 | ||
1430 | void Shader::setBaked(const std::string& name, bool baked) { | |
1431 | ShaderUniform* uniform = getUniform(name); | |
1432 | ||
1433 | if(!uniform) return; | |
1434 | ||
1435 | uniform->setBaked(baked); | |
1436 | } | |
1437 | ||
1438 | void Shader::setBakedUniforms(bool baked) { | |
1439 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1440 | it->second->setBaked(baked); | |
1441 | } | |
1442 | } | |
1443 | ||
1444 | ||
1445 | void Shader::applyUniforms() { | |
1446 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1447 | if(!it->second->isBaked()) it->second->apply(); | |
1448 | } | |
1449 | } | |
1450 | ||
1451 | bool Shader::needsCompile() { | |
1452 | ||
1453 | for(std::map<std::string, ShaderUniform*>::iterator it= uniforms.begin(); it!=uniforms.end();it++) { | |
1454 | ShaderUniform* u = it->second; | |
1455 | ||
1456 | if(u->isBaked() && u->isModified()) { | |
1457 | //infoLog("baked uniform %s needs update", u->getName().c_str()); | |
1458 | return true; | |
1459 | } | |
1460 | } | |
1461 | ||
1462 | return false; | |
1463 | } |
33 | 33 | #include "display.h" |
34 | 34 | #include "sdlapp.h" |
35 | 35 | #include "regex.h" |
36 | ||
36 | #include "util.h" | |
37 | ||
38 | #include <boost/format.hpp> | |
39 | #include <list> | |
37 | 40 | #include <map> |
38 | 41 | #include <string> |
39 | 42 | #include <fstream> |
43 | #include <sstream> | |
44 | ||
45 | enum { SHADER_UNIFORM_FLOAT, | |
46 | SHADER_UNIFORM_BOOL, | |
47 | SHADER_UNIFORM_SAMPLER_1D, | |
48 | SHADER_UNIFORM_SAMPLER_2D, | |
49 | SHADER_UNIFORM_INT, | |
50 | SHADER_UNIFORM_VEC2, | |
51 | SHADER_UNIFORM_VEC3, | |
52 | SHADER_UNIFORM_VEC4, | |
53 | SHADER_UNIFORM_MAT3, | |
54 | SHADER_UNIFORM_MAT4, | |
55 | SHADER_UNIFORM_VEC2_ARRAY, | |
56 | SHADER_UNIFORM_VEC3_ARRAY, | |
57 | SHADER_UNIFORM_VEC4_ARRAY | |
58 | }; | |
59 | ||
60 | class Shader; | |
61 | ||
62 | class ShaderUniform { | |
63 | protected: | |
64 | std::string name; | |
65 | GLint location; | |
66 | Shader* shader; | |
67 | int uniform_type; | |
68 | std::string type_name; | |
69 | bool modified; | |
70 | bool initialized; | |
71 | bool baked; | |
72 | public: | |
73 | ||
74 | ShaderUniform(Shader* shader, const std::string& name, int uniform_type, const std::string& type_name); | |
75 | ||
76 | virtual void unload(); | |
77 | ||
78 | int getType() { return uniform_type; }; | |
79 | ||
80 | virtual void write(std::string& content) const {}; | |
81 | ||
82 | const std::string& getName() const; | |
83 | bool isInitialized() const { return initialized; }; | |
84 | GLint getLocation(); | |
85 | ||
86 | bool isBaked() const { return baked; }; | |
87 | bool isModified() const { return modified; }; | |
88 | ||
89 | void setInitialized(bool initialized) { this->initialized = initialized; }; | |
90 | ||
91 | virtual void apply() {}; | |
92 | ||
93 | virtual void setBaked(bool baked); | |
94 | virtual void setModified(bool modified) { this->modified = modified; }; | |
95 | }; | |
96 | ||
97 | class FloatShaderUniform : public ShaderUniform { | |
98 | float value; | |
99 | public: | |
100 | FloatShaderUniform(Shader* shader, const std::string& name, float value = 0.0f); | |
101 | ||
102 | void write(std::string& content) const; | |
103 | ||
104 | void apply(); | |
105 | void setValue(float value); | |
106 | float getValue() const; | |
107 | }; | |
108 | ||
109 | class IntShaderUniform : public ShaderUniform { | |
110 | int value; | |
111 | public: | |
112 | IntShaderUniform(Shader* shader, const std::string& name, int value = 0); | |
113 | ||
114 | void write(std::string& content) const; | |
115 | ||
116 | void apply(); | |
117 | void setValue(int value); | |
118 | float getValue() const; | |
119 | }; | |
120 | ||
121 | class BoolShaderUniform : public ShaderUniform { | |
122 | bool value; | |
123 | public: | |
124 | BoolShaderUniform(Shader* shader, const std::string& name, bool value = false); | |
125 | ||
126 | void write(std::string& content) const; | |
127 | ||
128 | void apply(); | |
129 | void setValue(bool value); | |
130 | float getValue() const; | |
131 | }; | |
132 | ||
133 | class Sampler1DShaderUniform : public ShaderUniform { | |
134 | int value; | |
135 | public: | |
136 | Sampler1DShaderUniform(Shader* shader, const std::string& name, int value = 0); | |
137 | ||
138 | void write(std::string& content) const; | |
139 | ||
140 | void setBaked(bool baked); | |
141 | ||
142 | void apply(); | |
143 | void setValue(int value); | |
144 | float getValue() const; | |
145 | }; | |
146 | ||
147 | class Sampler2DShaderUniform : public ShaderUniform { | |
148 | int value; | |
149 | public: | |
150 | Sampler2DShaderUniform(Shader* shader, const std::string& name, int value = 0); | |
151 | ||
152 | void write(std::string& content) const; | |
153 | ||
154 | void setBaked(bool baked); | |
155 | ||
156 | void apply(); | |
157 | void setValue(int value); | |
158 | float getValue() const; | |
159 | }; | |
160 | ||
161 | class Vec2ShaderUniform : public ShaderUniform { | |
162 | vec2 value; | |
163 | public: | |
164 | Vec2ShaderUniform(Shader* shader, const std::string& name, const vec2& value = vec2(0.0f)) ; | |
165 | ||
166 | void write(std::string& content) const; | |
167 | ||
168 | void apply(); | |
169 | void setValue(const vec2& value); | |
170 | const vec2& getValue() const; | |
171 | }; | |
172 | ||
173 | class Vec3ShaderUniform : public ShaderUniform { | |
174 | vec3 value; | |
175 | public: | |
176 | Vec3ShaderUniform(Shader* shader, const std::string& name, const vec3& value = vec3(0.0f)); | |
177 | ||
178 | void write(std::string& content) const; | |
179 | ||
180 | void apply(); | |
181 | void setValue(const vec3& value); | |
182 | const vec3& getValue() const; | |
183 | }; | |
184 | ||
185 | class Vec4ShaderUniform : public ShaderUniform { | |
186 | vec4 value; | |
187 | public: | |
188 | Vec4ShaderUniform(Shader* shader, const std::string& name, const vec4& value = vec4(0.0f)); | |
189 | ||
190 | void write(std::string& content) const; | |
191 | ||
192 | void apply(); | |
193 | void setValue(const vec4& value); | |
194 | const vec4& getValue() const; | |
195 | }; | |
196 | ||
197 | class Mat3ShaderUniform : public ShaderUniform { | |
198 | mat3 value; | |
199 | public: | |
200 | Mat3ShaderUniform(Shader* shader, const std::string& name, const mat3& value = mat3(1.0f)); | |
201 | ||
202 | void write(std::string& content) const; | |
203 | ||
204 | void apply(); | |
205 | void setValue(const mat3& value); | |
206 | const mat3& getValue() const; | |
207 | }; | |
208 | ||
209 | class Mat4ShaderUniform : public ShaderUniform { | |
210 | mat4 value; | |
211 | public: | |
212 | Mat4ShaderUniform(Shader* shader, const std::string& name, const mat4& value = mat4(1.0f)); | |
213 | ||
214 | void write(std::string& content) const; | |
215 | ||
216 | void apply(); | |
217 | void setValue(const mat4& value); | |
218 | const mat4& getValue() const; | |
219 | }; | |
220 | ||
221 | class Vec2ArrayShaderUniform : public ShaderUniform { | |
222 | vec2* value; | |
223 | size_t length; | |
224 | ||
225 | void copyValue(const vec2* value); | |
226 | void copyValue(const std::vector<vec2>& value); | |
227 | public: | |
228 | Vec2ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec2* value = 0); | |
229 | ~Vec2ArrayShaderUniform(); | |
230 | ||
231 | void write(std::string& content) const; | |
232 | ||
233 | void apply(); | |
234 | ||
235 | void setValue(const vec2* value); | |
236 | void setValue(const std::vector<vec2>& value); | |
237 | ||
238 | const vec2* getValue() const; | |
239 | }; | |
240 | ||
241 | class Vec3ArrayShaderUniform : public ShaderUniform { | |
242 | vec3* value; | |
243 | size_t length; | |
244 | ||
245 | void copyValue(const vec3* value); | |
246 | void copyValue(const std::vector<vec3>& value); | |
247 | public: | |
248 | Vec3ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec3* value = 0); | |
249 | ~Vec3ArrayShaderUniform(); | |
250 | ||
251 | void write(std::string& content) const; | |
252 | ||
253 | void apply(); | |
254 | ||
255 | void setValue(const vec3* value); | |
256 | void setValue(const std::vector<vec3>& value); | |
257 | ||
258 | const vec3* getValue() const; | |
259 | }; | |
260 | ||
261 | class Vec4ArrayShaderUniform : public ShaderUniform { | |
262 | vec4* value; | |
263 | size_t length; | |
264 | ||
265 | void copyValue(const vec4* value); | |
266 | void copyValue(const std::vector<vec4>& value); | |
267 | public: | |
268 | Vec4ArrayShaderUniform(Shader* shader, const std::string& name, size_t length, const vec4* value = 0); | |
269 | ~Vec4ArrayShaderUniform(); | |
270 | ||
271 | void write(std::string& content) const; | |
272 | ||
273 | void apply(); | |
274 | ||
275 | void setValue(const vec4* value); | |
276 | void setValue(const std::vector<vec4>& value); | |
277 | ||
278 | const vec4* getValue() const; | |
279 | }; | |
280 | ||
281 | class ShaderPass { | |
282 | GLint shader_object_type; | |
283 | std::string shader_object_desc; | |
284 | GLenum shader_object; | |
285 | ||
286 | int version; | |
287 | std::map<std::string,std::string> extensions; | |
288 | ||
289 | Shader* parent; | |
290 | ||
291 | std::string source; | |
292 | std::string shader_object_source; | |
293 | ||
294 | std::list<ShaderUniform*> uniforms; | |
295 | ||
296 | bool errorContext(const char* log_message, std::string& context); | |
297 | ||
298 | bool preprocess(const std::string& line); | |
299 | public: | |
300 | ShaderPass(Shader* parent, GLint shader_object_type, const std::string& shader_object_desc); | |
301 | virtual ~ShaderPass(); | |
302 | ||
303 | GLint getType() { return shader_object_type; }; | |
304 | ||
305 | void toString(std::string& out); | |
306 | ||
307 | void unload(); | |
308 | void compile(); | |
309 | ||
310 | void checkError(); | |
311 | ||
312 | ShaderUniform* addArrayUniform(const std::string& name, const std::string& type, size_t length); | |
313 | ShaderUniform* addUniform(const std::string& name, const std::string& type); | |
314 | ||
315 | virtual void attachTo(GLenum program); | |
316 | ||
317 | void includeSource(const std::string& source); | |
318 | void includeFile(const std::string& filename); | |
319 | }; | |
320 | ||
321 | class VertexShader : public ShaderPass { | |
322 | public: | |
323 | VertexShader(Shader* parent); | |
324 | }; | |
325 | ||
326 | class FragmentShader : public ShaderPass { | |
327 | public: | |
328 | FragmentShader(Shader* parent); | |
329 | }; | |
330 | ||
331 | class GeometryShader : public ShaderPass { | |
332 | public: | |
333 | GeometryShader(Shader* parent); | |
334 | ||
335 | void attachTo(GLenum program); | |
336 | }; | |
40 | 337 | |
41 | 338 | class Shader : public Resource { |
42 | 339 | |
43 | std::map<std::string, GLint> varMap; | |
44 | ||
45 | GLenum shaderProg; | |
46 | GLenum vertexShader; | |
47 | GLenum fragmentShader; | |
48 | ||
49 | GLint getVarLocation(const std::string& name); | |
50 | ||
51 | bool preprocess(const std::string& line, std::string& output); | |
52 | bool readSource(const std::string& filename, std::string& output); | |
53 | GLenum load(const std::string& filename, GLenum shaderType); | |
54 | void makeProgram(); | |
55 | ||
56 | void checkError(const std::string& filename, GLenum shaderRef); | |
57 | public: | |
340 | std::map<std::string, ShaderUniform*> uniforms; | |
341 | std::map<std::string,std::string> substitutions; | |
342 | ||
343 | GLenum program; | |
344 | bool dynamic_compile; | |
345 | ||
346 | void checkProgramError(); | |
347 | ||
348 | void setDefaults(); | |
349 | public: | |
350 | VertexShader* vertex_shader; | |
351 | GeometryShader* geometry_shader; | |
352 | FragmentShader* fragment_shader; | |
353 | ||
354 | Shader(); | |
58 | 355 | Shader(const std::string& prefix); |
59 | 356 | ~Shader(); |
60 | 357 | |
61 | 358 | GLenum getProgram(); |
62 | GLenum getVertexShader(); | |
63 | GLenum getFragmentShader(); | |
64 | ||
359 | ||
360 | void clear(); | |
361 | ||
362 | void load(); | |
363 | void unload(); | |
364 | ||
365 | ShaderPass* grabShaderPass(GLenum shader_object_type); | |
366 | ||
367 | void includeSource(GLenum shader_object_type, const std::string& source); | |
368 | void includeFile(GLenum shader_object_type, const std::string& filename); | |
369 | ||
370 | static void substitute(std::string& source, const std::string& name, const std::string& value); | |
371 | ||
372 | void addSubstitute(const std::string& name, const char *value, ...); | |
373 | void applySubstitutions(std::string& source); | |
374 | ||
375 | void addUniform(ShaderUniform* uniform); | |
376 | ShaderUniform* getUniform(const std::string& name); | |
377 | ||
378 | void setDynamicCompile(bool dynamic_compile); | |
379 | bool needsCompile(); | |
380 | ||
381 | void applyUniforms(); | |
382 | ||
383 | void setBool(const std::string& name, bool value); | |
65 | 384 | void setInteger (const std::string& name, int value); |
385 | void setSampler1D(const std::string& name, int value); | |
386 | void setSampler2D(const std::string& name, int value); | |
66 | 387 | void setFloat(const std::string& name, float value); |
67 | void setVec2 (const std::string& name, const vec2f& value); | |
68 | void setVec3 (const std::string& name, const vec3f& value); | |
69 | void setVec4 (const std::string& name, const vec4f& value); | |
388 | void setVec2 (const std::string& name, const vec2& value); | |
389 | void setVec3 (const std::string& name, const vec3& value); | |
390 | void setVec4 (const std::string& name, const vec4& value); | |
391 | void setMat3 (const std::string& name, const mat3& value); | |
392 | void setMat4 (const std::string& name, const mat4& value); | |
393 | ||
394 | void setVec2Array(const std::string& name, vec2* value); | |
395 | void setVec2Array(const std::string& name, std::vector<vec2>& value); | |
396 | ||
397 | void setVec3Array(const std::string& name, vec3* value); | |
398 | void setVec3Array(const std::string& name, std::vector<vec3>& value); | |
399 | ||
400 | void setVec4Array(const std::string& name, vec4* value); | |
401 | void setVec4Array(const std::string& name, std::vector<vec4>& value); | |
402 | ||
403 | void setBaked(const std::string& name, bool baked); | |
404 | void setBakedUniforms(bool baked); | |
405 | ||
406 | void bind(); | |
407 | void unbind(); | |
70 | 408 | |
71 | 409 | void use(); |
72 | 410 | }; |
73 | 411 | |
74 | 412 | class ShaderManager : public ResourceManager { |
75 | 413 | public: |
76 | bool debug; | |
77 | ShaderManager() { | |
78 | debug = false; | |
79 | } | |
414 | bool warnings; | |
415 | ||
416 | ShaderManager(); | |
80 | 417 | Shader* grab(const std::string& shader_prefix); |
418 | ||
419 | void enableWarnings(bool warnings); | |
420 | ||
421 | void manage(Shader* shader); | |
422 | ||
423 | void unload(); | |
424 | void reload(); | |
81 | 425 | }; |
82 | 426 | |
83 | 427 | extern ShaderManager shadermanager; |
44 | 44 | return val; |
45 | 45 | } |
46 | 46 | |
47 | vec2f vec2Hash(std::string& str) { | |
47 | vec2 vec2Hash(std::string& str) { | |
48 | 48 | int hash = stringHash(str); |
49 | 49 | |
50 | 50 | int x = ((hash/7) % 255) - 127; |
51 | 51 | int y = ((hash/3) % 255) - 127; |
52 | 52 | |
53 | vec2f v = vec2f(x, y); | |
54 | v.normalize(); | |
53 | vec2 v = normalise(vec2(x, y)); | |
55 | 54 | |
56 | 55 | return v; |
57 | 56 | } |
58 | 57 | |
59 | vec3f vec3Hash(std::string& str) { | |
58 | vec3 vec3Hash(std::string& str) { | |
60 | 59 | int hash = stringHash(str); |
61 | 60 | |
62 | 61 | int x = ((hash/7) % 255) - 127; |
63 | 62 | int y = ((hash/3) % 255) - 127; |
64 | 63 | int z = hash % 255; |
65 | 64 | |
66 | vec3f v = vec3f(x, y, z); | |
67 | v.normalize(); | |
65 | vec3 v = normalise(vec3(x, y, z)); | |
68 | 66 | |
69 | 67 | return v; |
70 | 68 | } |
71 | 69 | |
72 | vec3f colourHash(std::string& str) { | |
70 | vec3 colourHash(std::string& str) { | |
73 | 71 | int hash = stringHash(str); |
74 | 72 | |
75 | 73 | int r = (hash/7) % 255; |
78 | 76 | if(g<0) g=0; |
79 | 77 | int b = hash % 255; |
80 | 78 | |
81 | vec3f colour = vec3f(r, g, b); | |
82 | colour.normalize(); | |
79 | vec3 colour = normalise(vec3(r, g, b)); | |
83 | 80 | |
84 | 81 | return colour; |
85 | 82 | } |
33 | 33 | |
34 | 34 | //basic string hash algorithm |
35 | 35 | int stringHash(std::string& str); |
36 | vec2f vec2Hash(std::string& str); | |
37 | vec3f vec3Hash(std::string& str); | |
38 | vec3f colourHash(std::string& str); | |
39 | vec3f stylizedColourHash(std::string& str); | |
36 | vec2 vec2Hash(std::string& str); | |
37 | vec3 vec3Hash(std::string& str); | |
38 | vec3 colourHash(std::string& str); | |
39 | vec3 stylizedColourHash(std::string& str); | |
40 | 40 | |
41 | 41 | extern int gStringHashSeed; |
42 | 42 |
25 | 25 | */ |
26 | 26 | |
27 | 27 | #include "texture.h" |
28 | #include "display.h" | |
28 | 29 | |
29 | 30 | TextureManager texturemanager; |
30 | 31 | |
31 | 32 | // texture manager |
32 | 33 | |
33 | 34 | TextureManager::TextureManager() : ResourceManager() { |
34 | } | |
35 | ||
36 | TextureResource* TextureManager::grabFile(std::string name, bool mipmaps, bool clamp, bool trilinear) { | |
37 | return grab(name, mipmaps, clamp, trilinear, true); | |
38 | } | |
39 | ||
40 | TextureResource* TextureManager::grab(std::string name, bool mipmaps, bool clamp, bool trilinear, bool external_file) { | |
41 | ||
42 | Resource* r = resources[name]; | |
43 | ||
44 | if(r==0) { | |
45 | r = new TextureResource(name, mipmaps, clamp, trilinear, external_file); | |
46 | ||
47 | resources[name] = r; | |
48 | } | |
35 | resource_seq = 0; | |
36 | trilinear = true; | |
37 | } | |
38 | ||
39 | TextureResource* TextureManager::grabFile(const std::string& filename, bool mipmaps, GLint wrap) { | |
40 | return grab(filename, mipmaps, wrap, true); | |
41 | } | |
42 | ||
43 | TextureResource* TextureManager::grab(const std::string& filename, bool mipmaps, GLint wrap, bool external) { | |
44 | ||
45 | TextureResource* r = 0; | |
46 | ||
47 | //look up this resource | |
48 | if((r = (TextureResource*) resources[filename]) != 0) { | |
49 | r->addref(); | |
50 | return r; | |
51 | } | |
52 | ||
53 | r = new TextureResource(filename, mipmaps, wrap, external); | |
54 | r->load(); | |
55 | ||
56 | addResource(r); | |
57 | ||
58 | return r; | |
59 | } | |
60 | ||
61 | void TextureManager::addResource(TextureResource* r) { | |
62 | ||
63 | if(r->resource_name.empty()) { | |
64 | char res_name[256]; | |
65 | snprintf(res_name, 256, "__texture_resource_%d", ++resource_seq); | |
66 | ||
67 | std::string resource_name(res_name); | |
68 | ||
69 | r->setResourceName(resource_name); | |
70 | } | |
71 | ||
72 | resources[r->resource_name] = r; | |
49 | 73 | r->addref(); |
74 | } | |
75 | ||
76 | TextureResource* TextureManager::create(GLenum target) { | |
77 | ||
78 | TextureResource* r = new TextureResource(); | |
79 | r->target = target; | |
80 | ||
81 | r->load(); | |
82 | ||
83 | addResource(r); | |
50 | 84 | |
51 | 85 | return (TextureResource*)r; |
52 | } | |
53 | ||
54 | // texture resource | |
55 | ||
56 | TextureResource::TextureResource(std::string file, bool mipmaps, bool clamp, bool trilinear, bool external_file) : Resource(file) { | |
86 | ||
87 | } | |
88 | ||
89 | TextureResource* TextureManager::create(int width, int height, bool mipmaps, GLint wrap, GLenum format, GLubyte* data) { | |
90 | ||
91 | TextureResource* r = new TextureResource(width, height, mipmaps, wrap, format, data); | |
92 | r->load(); | |
93 | ||
94 | addResource(r); | |
95 | ||
96 | return (TextureResource*)r; | |
97 | ||
98 | ||
99 | } | |
100 | ||
101 | void TextureManager::unload() { | |
102 | for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) { | |
103 | ((TextureResource*)it->second)->unload(); | |
104 | } | |
105 | } | |
106 | ||
107 | void TextureManager::reload() { | |
108 | for(std::map<std::string, Resource*>::iterator it= resources.begin(); it!=resources.end();it++) { | |
109 | ((TextureResource*)it->second)->load(); | |
110 | } | |
111 | } | |
112 | ||
113 | // TextureResource | |
114 | ||
115 | TextureResource::TextureResource() { | |
116 | textureid = 0; | |
117 | w = 0; | |
118 | h = 0; | |
119 | format = 0; | |
120 | data = 0; | |
121 | wrap = GL_CLAMP_TO_EDGE; | |
122 | target = GL_TEXTURE_2D; | |
123 | mipmaps = false; | |
124 | ||
125 | setDefaultFiltering(); | |
126 | } | |
127 | ||
128 | TextureResource::TextureResource(const std::string& filename, bool mipmaps, GLint wrap, bool external) : Resource(filename) { | |
129 | ||
130 | this->mipmaps = mipmaps; | |
131 | this->wrap = wrap; | |
132 | ||
133 | data = 0; | |
134 | format = 0; | |
135 | textureid = 0; | |
136 | target = GL_TEXTURE_2D; | |
57 | 137 | |
58 | 138 | //if doesnt have an absolute path, look in resource dir |
59 | if(!external_file && !(file.size() > 2 && file[1] == ':') && !(file.size() > 1 && file[0] == '/')) { | |
60 | file = texturemanager.getDir() + file; | |
61 | } | |
62 | ||
63 | debugLog("creating texture from %s\n", file.c_str()); | |
64 | ||
65 | SDL_Surface *surface = IMG_Load(file.c_str()); | |
66 | ||
67 | if(surface==0) throw TextureException(file); | |
68 | ||
69 | w = surface->w; | |
70 | h = surface->h; | |
71 | ||
72 | //figure out image colour order | |
73 | int format = colourFormat(surface); | |
74 | ||
75 | if(format==0) throw TextureException(file); | |
76 | ||
77 | textureid = display.createTexture(w, h, mipmaps, clamp, trilinear, format, (unsigned int*) surface->pixels); | |
78 | ||
79 | SDL_FreeSurface(surface); | |
80 | } | |
81 | ||
82 | int TextureResource::colourFormat(SDL_Surface* surface) { | |
139 | if(!external && !(filename.size() > 2 && filename[1] == ':') && !(filename.size() > 1 && filename[0] == '/')) { | |
140 | this->filename = texturemanager.getDir() + filename; | |
141 | } else { | |
142 | this->filename = filename; | |
143 | } | |
144 | ||
145 | setDefaultFiltering(); | |
146 | } | |
147 | ||
148 | TextureResource::TextureResource(int width, int height, bool mipmaps, GLint wrap, GLenum format, GLubyte* data) { | |
149 | this->w = width; | |
150 | this->h = height; | |
151 | this->data = data; | |
152 | this->format = format; | |
153 | this->mipmaps = mipmaps; | |
154 | this->wrap = wrap; | |
155 | this->target = GL_TEXTURE_2D; | |
156 | ||
157 | textureid = 0; | |
158 | ||
159 | setDefaultFiltering(); | |
160 | } | |
161 | ||
162 | TextureResource::~TextureResource() { | |
163 | unload(); | |
164 | } | |
165 | ||
166 | void TextureResource::setDefaultFiltering() { | |
167 | ||
168 | if(mipmaps) { | |
169 | ||
170 | if(texturemanager.trilinear) { | |
171 | min_filter = GL_LINEAR_MIPMAP_LINEAR; | |
172 | } else { | |
173 | min_filter = GL_LINEAR_MIPMAP_NEAREST; | |
174 | } | |
175 | ||
176 | mag_filter = GL_LINEAR; | |
177 | ||
178 | } else { | |
179 | min_filter = GL_LINEAR; | |
180 | mag_filter = GL_LINEAR; | |
181 | } | |
182 | ||
183 | } | |
184 | ||
185 | void TextureResource::setFiltering(GLint min_filter, GLint mag_filter) { | |
186 | ||
187 | this->min_filter = min_filter; | |
188 | this->mag_filter = mag_filter; | |
189 | ||
190 | glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter); | |
191 | glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mag_filter); | |
192 | } | |
193 | ||
194 | void TextureResource::setWrapStyle(GLint wrap) { | |
195 | ||
196 | this->wrap = wrap; | |
197 | ||
198 | glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap); | |
199 | glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap); | |
200 | } | |
201 | ||
202 | ||
203 | void TextureResource::unload() { | |
204 | if(textureid!=0) glDeleteTextures(1, &textureid); | |
205 | textureid=0; | |
206 | } | |
207 | ||
208 | void TextureResource::createTexture() { | |
209 | ||
210 | if(!textureid) glGenTextures(1, &textureid); | |
211 | ||
212 | glBindTexture(target, textureid); | |
213 | ||
214 | if(w != 0 && format != 0) { | |
215 | ||
216 | GLint internalFormat = 0; | |
217 | ||
218 | switch(format) { | |
219 | case GL_ALPHA: | |
220 | internalFormat = GL_ALPHA; | |
221 | break; | |
222 | case GL_LUMINANCE: | |
223 | internalFormat = GL_LUMINANCE; | |
224 | break; | |
225 | default: | |
226 | internalFormat = GL_RGBA; | |
227 | break; | |
228 | } | |
229 | ||
230 | if(mipmaps) { | |
231 | gluBuild2DMipmaps(target, internalFormat, w, h, format, GL_UNSIGNED_BYTE, data); | |
232 | } else { | |
233 | glTexImage2D(target, 0, internalFormat, w, h, 0, format, GL_UNSIGNED_BYTE, data); | |
234 | } | |
235 | } | |
236 | ||
237 | setFiltering(min_filter, mag_filter); | |
238 | setWrapStyle(wrap); | |
239 | } | |
240 | ||
241 | void TextureResource::reload() { | |
242 | load(true); | |
243 | } | |
244 | ||
245 | void TextureResource::load(bool reload) { | |
246 | ||
247 | if(textureid != 0) { | |
248 | if(!reload) return; | |
249 | debugLog("texture %d is being reloaded", textureid); | |
250 | } | |
251 | ||
252 | SDL_Surface *surface = 0; | |
253 | ||
254 | if(!filename.empty()) { | |
255 | debugLog("creating texture from %s", filename.c_str()); | |
256 | ||
257 | surface = IMG_Load(filename.c_str()); | |
258 | ||
259 | if(surface==0) throw TextureException(filename); | |
260 | ||
261 | w = surface->w; | |
262 | h = surface->h; | |
263 | ||
264 | //figure out image colour order | |
265 | format = colourFormat(surface); | |
266 | ||
267 | data = (GLubyte*) surface->pixels; | |
268 | ||
269 | if(format==0) throw TextureException(filename); | |
270 | } | |
271 | ||
272 | createTexture(); | |
273 | ||
274 | if(surface != 0) { | |
275 | SDL_FreeSurface(surface); | |
276 | data = 0; | |
277 | } | |
278 | } | |
279 | ||
280 | GLenum TextureResource::colourFormat(SDL_Surface* surface) { | |
83 | 281 | |
84 | 282 | int colours = surface->format->BytesPerPixel; |
85 | 283 | int format = 0; |
100 | 298 | return format; |
101 | 299 | } |
102 | 300 | |
103 | TextureResource::~TextureResource() { | |
104 | if(textureid!=0) glDeleteTextures(1, &textureid); | |
105 | } | |
301 | void TextureResource::bind() { | |
302 | ||
303 | if(!textureid) load(); | |
304 | glBindTexture(target, textureid); | |
305 | } |
30 | 30 | #include "SDL_image.h" |
31 | 31 | |
32 | 32 | #include "resource.h" |
33 | #include "display.h" | |
33 | #include "gl.h" | |
34 | 34 | |
35 | 35 | class TextureException : public ResourceException { |
36 | 36 | public: |
38 | 38 | }; |
39 | 39 | |
40 | 40 | class TextureResource : public Resource { |
41 | int colourFormat(SDL_Surface* surface); | |
42 | void loadTexture(std::string file, bool mipmaps, bool clamp, bool trilinear, bool external_file); | |
41 | bool mipmaps; | |
42 | GLint wrap; | |
43 | GLint min_filter; | |
44 | GLint mag_filter; | |
45 | std::string filename; | |
46 | ||
47 | GLenum colourFormat(SDL_Surface* surface); | |
43 | 48 | public: |
44 | int w, h; | |
49 | int w, h; | |
50 | GLenum target; | |
51 | GLenum format; | |
45 | 52 | GLuint textureid; |
46 | TextureResource(std::string name, bool mipmaps, bool clamp, bool trilinear, bool external_file); | |
53 | GLubyte* data; | |
54 | ||
55 | TextureResource(); | |
56 | TextureResource(int width, int height, bool mipmaps, GLint wrap, GLenum format, GLubyte* data = 0); | |
57 | TextureResource(const std::string& filename, bool mipmaps, GLint wrap, bool external); | |
58 | ||
59 | void setWrapStyle(GLint wrap); | |
60 | ||
61 | void setFiltering(GLint min_filter, GLint mag_filter); | |
62 | void setDefaultFiltering(); | |
63 | ||
64 | void bind(); | |
65 | ||
66 | void createTexture(); | |
67 | ||
68 | void reload(); | |
69 | ||
70 | void load(bool reload = false); | |
71 | ||
72 | void unload(); | |
73 | ||
47 | 74 | ~TextureResource(); |
48 | 75 | }; |
49 | 76 | |
50 | 77 | class TextureManager : public ResourceManager { |
78 | int resource_seq; | |
79 | ||
80 | void addResource(TextureResource* r); | |
51 | 81 | public: |
82 | bool trilinear; | |
83 | ||
52 | 84 | TextureManager(); |
53 | TextureResource* grabFile(std::string name, bool mipmaps=true, bool clamp=true, bool trilinear=false); | |
54 | TextureResource* grab(std::string file, bool mipmaps=true, bool clamp=true, bool trilinear=false, bool external_file = false); | |
85 | ||
86 | TextureResource* grabFile(const std::string& filename, bool mipmaps = true, GLint wrap = GL_CLAMP_TO_EDGE); | |
87 | TextureResource* grab(const std::string& filename, bool mipmaps = true, GLint wrap = GL_CLAMP_TO_EDGE, bool external_file = false); | |
88 | ||
89 | TextureResource* create(int width, int height, bool mipmaps, GLint wrap, GLenum format, GLubyte* data = 0); | |
90 | TextureResource* create(GLenum target = GL_TEXTURE_2D); | |
91 | ||
92 | void unload(); | |
93 | void reload(); | |
55 | 94 | }; |
56 | 95 | |
57 | 96 | extern TextureManager texturemanager; |
63 | 63 | }; |
64 | 64 | |
65 | 65 | /// The library API - functions intended to be called by the users |
66 | ||
67 | template <typename octet_iterator> | |
68 | octet_iterator append(uint32_t cp, octet_iterator result) | |
69 | { | |
70 | if (!internal::is_code_point_valid(cp)) | |
71 | throw invalid_code_point(cp); | |
72 | ||
73 | if (cp < 0x80) // one octet | |
74 | *(result++) = static_cast<uint8_t>(cp); | |
75 | else if (cp < 0x800) { // two octets | |
76 | *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); | |
77 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
78 | } | |
79 | else if (cp < 0x10000) { // three octets | |
80 | *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); | |
81 | *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); | |
82 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
83 | } | |
84 | else if (cp <= internal::CODE_POINT_MAX) { // four octets | |
85 | *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); | |
86 | *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80); | |
87 | *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); | |
88 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
89 | } | |
90 | else | |
91 | throw invalid_code_point(cp); | |
92 | ||
93 | return result; | |
94 | } | |
66 | 95 | |
67 | 96 | template <typename octet_iterator, typename output_iterator> |
68 | 97 | output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, uint32_t replacement) |
103 | 132 | } |
104 | 133 | |
105 | 134 | template <typename octet_iterator> |
106 | octet_iterator append(uint32_t cp, octet_iterator result) | |
107 | { | |
108 | if (!internal::is_code_point_valid(cp)) | |
109 | throw invalid_code_point(cp); | |
110 | ||
111 | if (cp < 0x80) // one octet | |
112 | *(result++) = static_cast<uint8_t>(cp); | |
113 | else if (cp < 0x800) { // two octets | |
114 | *(result++) = static_cast<uint8_t>((cp >> 6) | 0xc0); | |
115 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
116 | } | |
117 | else if (cp < 0x10000) { // three octets | |
118 | *(result++) = static_cast<uint8_t>((cp >> 12) | 0xe0); | |
119 | *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); | |
120 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
121 | } | |
122 | else if (cp <= internal::CODE_POINT_MAX) { // four octets | |
123 | *(result++) = static_cast<uint8_t>((cp >> 18) | 0xf0); | |
124 | *(result++) = static_cast<uint8_t>(((cp >> 12) & 0x3f) | 0x80); | |
125 | *(result++) = static_cast<uint8_t>(((cp >> 6) & 0x3f) | 0x80); | |
126 | *(result++) = static_cast<uint8_t>((cp & 0x3f) | 0x80); | |
127 | } | |
128 | else | |
129 | throw invalid_code_point(cp); | |
130 | ||
131 | return result; | |
132 | } | |
133 | ||
134 | template <typename octet_iterator> | |
135 | 135 | uint32_t next(octet_iterator& it, octet_iterator end) |
136 | 136 | { |
137 | 137 | uint32_t cp = 0; |
0 | #ifndef CORE_UTIL_H | |
1 | #define CORE_UTIL_H | |
2 | ||
3 | #include <boost/foreach.hpp> | |
4 | ||
5 | #define foreach BOOST_FOREACH | |
6 | ||
7 | #endif |
28 | 28 | |
29 | 29 | //quadbuf |
30 | 30 | |
31 | quadbuf::quadbuf(int data_size) : data_size(data_size) { | |
31 | quadbuf::quadbuf(int vertex_capacity) : vertex_capacity(vertex_capacity) { | |
32 | 32 | vertex_count = 0; |
33 | curr_buffer =-1; | |
34 | 33 | |
35 | buffers.resize(1); | |
36 | ||
37 | data = data_size > 0 ? new quadbuf_vertex[data_size] : 0; | |
34 | data = vertex_capacity > 0 ? new quadbuf_vertex[vertex_capacity] : 0; | |
38 | 35 | |
39 | 36 | //fprintf(stderr, "size of quadbuf_vertex = %d\n", sizeof(quadbuf_vertex)); |
40 | 37 | } |
43 | 40 | if(data!=0) delete[] data; |
44 | 41 | } |
45 | 42 | |
43 | void quadbuf::unload() { | |
44 | buf.unload(); | |
45 | } | |
46 | ||
46 | 47 | void quadbuf::resize(int new_size) { |
47 | 48 | |
48 | 49 | quadbuf_vertex* _data = data; |
49 | 50 | |
50 | 51 | data = new quadbuf_vertex[new_size]; |
51 | 52 | |
52 | for(int i=0;i<data_size;i++) { | |
53 | for(int i=0;i<vertex_capacity;i++) { | |
53 | 54 | data[i] = _data[i]; |
54 | 55 | } |
55 | 56 | |
56 | data_size = new_size; | |
57 | vertex_capacity = new_size; | |
57 | 58 | |
58 | 59 | if(_data != 0) delete[] _data; |
59 | 60 | } |
68 | 69 | } |
69 | 70 | |
70 | 71 | size_t quadbuf::capacity() { |
71 | return data_size; | |
72 | return vertex_capacity; | |
72 | 73 | } |
73 | 74 | |
74 | 75 | size_t quadbuf::texture_changes() { |
75 | 76 | return textures.size(); |
76 | 77 | } |
77 | 78 | |
78 | vec4f quadbuf_default_texcoord(0.0f, 0.0f, 1.0f, 1.0f); | |
79 | vec4 quadbuf_default_texcoord(0.0f, 0.0f, 1.0f, 1.0f); | |
79 | 80 | |
80 | void quadbuf::add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour) { | |
81 | void quadbuf::add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour) { | |
81 | 82 | add(textureid, pos, dims, colour, quadbuf_default_texcoord); |
82 | 83 | } |
83 | 84 | |
84 | void quadbuf::add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour, const vec4f& texcoord) { | |
85 | void quadbuf::add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour, const vec4& texcoord) { | |
85 | 86 | //debugLog("%d: %.2f, %.2f, %.2f, %.2f\n", i, pos.x, pos.y, dims.x, dims.y); |
86 | 87 | |
87 | quadbuf_vertex v1(pos, colour, vec2f(texcoord.x, texcoord.y)); | |
88 | quadbuf_vertex v2(pos + vec2f(dims.x, 0.0f), colour, vec2f(texcoord.z, texcoord.y)); | |
89 | quadbuf_vertex v3(pos + dims, colour, vec2f(texcoord.z, texcoord.w)); | |
90 | quadbuf_vertex v4(pos + vec2f(0.0f, dims.y), colour, vec2f(texcoord.x, texcoord.w)); | |
88 | quadbuf_vertex v1(pos, colour, vec2(texcoord.x, texcoord.y)); | |
89 | quadbuf_vertex v2(pos + vec2(dims.x, 0.0f), colour, vec2(texcoord.z, texcoord.y)); | |
90 | quadbuf_vertex v3(pos + dims, colour, vec2(texcoord.z, texcoord.w)); | |
91 | quadbuf_vertex v4(pos + vec2(0.0f, dims.y), colour, vec2(texcoord.x, texcoord.w)); | |
91 | 92 | |
92 | 93 | int i = vertex_count; |
93 | 94 | |
94 | 95 | vertex_count += 4; |
95 | 96 | |
96 | if(vertex_count > data_size) { | |
97 | if(vertex_count > vertex_capacity) { | |
97 | 98 | resize(vertex_count*2); |
98 | 99 | } |
99 | 100 | |
113 | 114 | |
114 | 115 | vertex_count += 4; |
115 | 116 | |
116 | if(vertex_count > data_size) { | |
117 | if(vertex_count > vertex_capacity) { | |
117 | 118 | resize(vertex_count*2); |
118 | 119 | } |
119 | 120 | |
130 | 131 | void quadbuf::update() { |
131 | 132 | if(vertex_count==0) return; |
132 | 133 | |
133 | curr_buffer = (curr_buffer + 1) % buffers.size(); | |
134 | ||
135 | quadbuf_buffer* buf = &(buffers[curr_buffer]); | |
136 | ||
137 | if(!buf->id) { | |
138 | glGenBuffers(1, &(buf->id)); | |
139 | } | |
140 | ||
141 | glBindBuffer(GL_ARRAY_BUFFER, buf->id); | |
134 | buf.bind(); | |
142 | 135 | |
143 | 136 | //recreate buffer if less than the vertex_count |
144 | if(buf->size < vertex_count) { | |
145 | buf->size = data_size; | |
146 | glBufferData(GL_ARRAY_BUFFER, buf->size*sizeof(quadbuf_vertex), &(data[0].pos.x), GL_DYNAMIC_DRAW); | |
147 | } else { | |
148 | glBufferSubData(GL_ARRAY_BUFFER, 0, vertex_count*sizeof(quadbuf_vertex), &(data[0].pos.x)); | |
149 | } | |
150 | ||
151 | glBindBuffer(GL_ARRAY_BUFFER, 0); | |
137 | buf.buffer( vertex_count, sizeof(quadbuf_vertex), vertex_capacity, &(data[0].pos.x), GL_DYNAMIC_DRAW ); | |
138 | ||
139 | buf.unbind(); | |
152 | 140 | } |
153 | 141 | |
154 | 142 | void quadbuf::draw() { |
155 | if(vertex_count==0 || curr_buffer==-1) return; | |
156 | ||
157 | glBindBuffer(GL_ARRAY_BUFFER, buffers[curr_buffer].id); | |
143 | if(vertex_count==0) return; | |
144 | ||
145 | buf.bind(); | |
158 | 146 | |
159 | 147 | glEnableClientState(GL_VERTEX_ARRAY); |
160 | 148 | glEnableClientState(GL_COLOR_ARRAY); |
195 | 183 | glDisableClientState(GL_COLOR_ARRAY); |
196 | 184 | glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
197 | 185 | |
198 | glBindBuffer(GL_ARRAY_BUFFER, 0); | |
186 | buf.unbind(); | |
199 | 187 | } |
39 | 39 | class quadbuf_vertex { |
40 | 40 | public: |
41 | 41 | quadbuf_vertex() {}; |
42 | quadbuf_vertex(const vec2f& pos, const vec4f& colour, const vec2f& texcoord) : pos(pos), colour(colour), texcoord(texcoord) {}; | |
42 | quadbuf_vertex(const vec2& pos, const vec4& colour, const vec2& texcoord) : pos(pos), colour(colour), texcoord(texcoord) {}; | |
43 | 43 | |
44 | vec2f pos; | |
45 | vec4f colour; | |
46 | vec2f texcoord; | |
44 | vec2 pos; | |
45 | vec4 colour; | |
46 | vec2 texcoord; | |
47 | 47 | }; |
48 | 48 | |
49 | 49 | //maintain ranges corresponding to each texture |
57 | 57 | |
58 | 58 | class quadbuf_buffer { |
59 | 59 | public: |
60 | GLuint id; | |
61 | int capacity; | |
62 | ||
60 | 63 | quadbuf_buffer() { |
61 | 64 | id = 0; |
62 | size = 0; | |
65 | capacity = 0; | |
63 | 66 | } |
64 | 67 | ~quadbuf_buffer() { |
65 | if(id !=0) glDeleteBuffers(1, &id); | |
68 | unload(); | |
66 | 69 | } |
67 | 70 | |
68 | GLuint id; | |
69 | int size; | |
71 | void init() { | |
72 | if(!id) glGenBuffers(1, &id); | |
73 | } | |
74 | ||
75 | void unload() { | |
76 | capacity = 0; | |
77 | if(id != 0) { | |
78 | glDeleteBuffers(1, &id); | |
79 | id = 0; | |
80 | } | |
81 | } | |
82 | ||
83 | void bind() { | |
84 | if(!id) init(); | |
85 | glBindBuffer(GL_ARRAY_BUFFER, id); | |
86 | } | |
87 | ||
88 | void buffer(int item_count, int item_size, int item_capacity, GLvoid* data, GLenum usage) { | |
89 | ||
90 | if(capacity < item_count) { | |
91 | capacity = item_capacity; | |
92 | glBufferData(GL_ARRAY_BUFFER, capacity * item_size, data, usage); | |
93 | } else { | |
94 | glBufferSubData(GL_ARRAY_BUFFER, 0, item_count * item_size, data); | |
95 | } | |
96 | } | |
97 | ||
98 | void unbind() { | |
99 | glBindBuffer(GL_ARRAY_BUFFER, 0); | |
100 | } | |
70 | 101 | }; |
71 | 102 | |
72 | 103 | class quadbuf { |
73 | 104 | |
74 | 105 | quadbuf_vertex* data; |
75 | int data_size; | |
106 | int vertex_capacity; | |
76 | 107 | |
77 | 108 | std::vector<quadbuf_tex> textures; |
78 | 109 | |
79 | std::vector<quadbuf_buffer> buffers; | |
80 | int curr_buffer; | |
110 | quadbuf_buffer buf; | |
81 | 111 | |
82 | 112 | int vertex_count; |
83 | 113 | |
86 | 116 | quadbuf(int data_size = 0); |
87 | 117 | ~quadbuf(); |
88 | 118 | |
119 | void unload(); | |
89 | 120 | void reset(); |
90 | 121 | |
91 | 122 | size_t vertices(); |
92 | 123 | size_t capacity(); |
93 | 124 | size_t texture_changes(); |
94 | 125 | |
95 | void add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour); | |
96 | void add(GLuint textureid, const vec2f& pos, const vec2f& dims, const vec4f& colour, const vec4f& texcoord); | |
126 | void add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour); | |
127 | void add(GLuint textureid, const vec2& pos, const vec2& dims, const vec4& colour, const vec4& texcoord); | |
97 | 128 | void add(GLuint textureid, const quadbuf_vertex& v1, const quadbuf_vertex& v2, const quadbuf_vertex& v3, const quadbuf_vertex& v4); |
98 | 129 | |
99 | 130 | void update(); |
0 | #include "vectors.h" | |
1 | ||
2 | vec2 rotate_vec2(const vec2& v, float s, float c) { | |
3 | return vec2( v.x * c - v.y * s, v.x * s + v.y * c ); | |
4 | } | |
5 | ||
6 | vec2 normalise(const vec2& v) { | |
7 | float l = glm::length(v); | |
8 | if(l > 0.0) return v / l; | |
9 | return v; | |
10 | } | |
11 | ||
12 | vec3 normalise(const vec3& v) { | |
13 | float l = glm::length(v); | |
14 | if(l > 0.0) return v / l; | |
15 | return v; | |
16 | } | |
17 | ||
18 | vec4 normalise(const vec4& v) { | |
19 | float l = glm::length(v); | |
20 | if(l > 0.0) return v / l; | |
21 | return v; | |
22 | } |
27 | 27 | #ifndef VECTORS_H |
28 | 28 | #define VECTORS_H |
29 | 29 | |
30 | #include <cmath> | |
30 | #include <glm/glm.hpp> | |
31 | #include <glm/gtc/type_ptr.hpp> | |
32 | #include <glm/gtc/matrix_transform.hpp> | |
33 | #include <glm/gtc/matrix_access.hpp> | |
34 | #include <glm/gtx/norm.hpp> | |
31 | 35 | |
32 | template<class T> class vec2 { | |
36 | using glm::vec2; | |
37 | using glm::vec3; | |
38 | using glm::vec4; | |
39 | using glm::mat3; | |
40 | using glm::mat4; | |
41 | ||
42 | vec2 rotate_vec2(const vec2& v, float s, float c); | |
43 | ||
44 | vec2 normalise(const vec2& v); | |
45 | vec3 normalise(const vec3& v); | |
46 | vec4 normalise(const vec4& v); | |
47 | ||
48 | class lerp2 : public glm::vec2 { | |
33 | 49 | public: |
34 | T x; | |
35 | T y; | |
50 | vec2 p; | |
51 | vec2 l; | |
36 | 52 | |
37 | vec2(const vec2<T>& vec) { | |
38 | this->x = vec.x; | |
39 | this->y = vec.y; | |
53 | lerp2() : vec2(), p(), l() { | |
40 | 54 | } |
41 | 55 | |
42 | vec2(T x = 0, T y = 0) { | |
43 | this->x = x; | |
44 | this->y = y; | |
45 | } | |
46 | ||
47 | vec2<T> perpendicular() const { | |
48 | return vec2<T>(y * -1.0f, x); | |
49 | } | |
50 | ||
51 | ||
52 | T dot(const vec2<T> &vec) const { | |
53 | return x*vec.x + y*vec.y; | |
54 | } | |
55 | ||
56 | T operator* (const vec2<T> &vec) const { | |
57 | return x*vec.x + y*vec.y; | |
58 | } | |
59 | ||
60 | vec2<T> operator+ (const vec2<T> &vec) const { | |
61 | return vec2<T>(x+vec.x, y+vec.y); | |
62 | } | |
63 | ||
64 | vec2<T> operator- (const vec2<T> &vec) const { | |
65 | return vec2<T>(x-vec.x, y-vec.y); | |
66 | } | |
67 | ||
68 | vec2<T> operator* (const T n) const { | |
69 | return vec2<T>(x*n, y*n); | |
70 | } | |
71 | ||
72 | vec2<T> operator/ (const T n) const { | |
73 | return vec2<T>(x/n, y/n); | |
74 | } | |
75 | ||
76 | friend vec2<T> operator* (T n, const vec2<T>& vec) { | |
77 | return vec2<T>(vec.x*n, vec.y*n); | |
78 | } | |
79 | ||
80 | bool operator== (const vec2<T> &vec) const { | |
81 | return (vec.x==x && vec.y==y); | |
82 | } | |
83 | ||
84 | bool operator!= (const vec2<T> &vec) const { | |
85 | return (vec.x!=x || vec.y!=y); | |
86 | } | |
87 | ||
88 | T length2() const { | |
89 | return x*x + y*y; | |
90 | } | |
91 | ||
92 | T length() const { | |
93 | return sqrt(x*x + y*y); | |
94 | } | |
95 | ||
96 | void normalize() { | |
97 | T len = length(); | |
98 | if(len == 0) return; | |
99 | ||
100 | *this *= (1.0/len); | |
101 | } | |
102 | ||
103 | vec2<T> normal() const { | |
104 | vec2<T> v(x,y); | |
105 | v.normalize(); | |
106 | return v; | |
107 | } | |
108 | ||
109 | vec2<T> rotate(float angle) const { | |
110 | ||
111 | float s = sinf(angle); | |
112 | float c = cosf(angle); | |
113 | ||
114 | return vec2<T>( x * c - y * s, x * s + y * c ); | |
115 | } | |
116 | ||
117 | vec2<T> rotate(float s, float c) const { | |
118 | return vec2<T>( x * c - y * s, x * s + y * c ); | |
119 | } | |
120 | ||
121 | vec2<T> rotate(const vec2<T> ¢re, float angle) const { | |
122 | vec2<T> v = *this - centre; | |
123 | ||
124 | float s = sinf(angle); | |
125 | float c = cosf(angle); | |
126 | ||
127 | v = vec2<T>( v.x * c - v.y * s, v.x * s + v.y * c ); | |
128 | ||
129 | return v + centre; | |
130 | } | |
131 | ||
132 | vec2<T> rotate(const vec2<T> ¢re, float s, float c) const { | |
133 | vec2<T> v = *this - centre; | |
134 | ||
135 | v = vec2<T>( v.x * c - v.y * s, v.x * s + v.y * c ); | |
136 | ||
137 | return v + centre; | |
138 | } | |
139 | ||
140 | ||
141 | operator T*() const { | |
142 | return (T*) &x; | |
143 | } | |
144 | ||
145 | vec2<T>& operator= (const vec2<T> &vec) { | |
146 | x = vec.x; | |
147 | y = vec.y; | |
56 | const lerp2& snap() { | |
57 | p = *this; | |
148 | 58 | return *this; |
149 | 59 | } |
150 | 60 | |
151 | void operator+= (const vec2<T> &vec) { | |
152 | x += vec.x; | |
153 | y += vec.y; | |
61 | static vec2 lerp(const vec2& a, const vec2& b, float n) { | |
62 | return a + (b - a) * n; | |
154 | 63 | } |
155 | 64 | |
156 | void operator-= (const vec2<T> &vec) { | |
157 | x -= vec.x; | |
158 | y -= vec.y; | |
65 | const vec2& lerp(float n) { | |
66 | l = p + (*this - p) * n; | |
67 | return l; | |
159 | 68 | } |
160 | ||
161 | void operator*= (T n) { | |
162 | x *= n; | |
163 | y *= n; | |
164 | } | |
165 | ||
166 | void operator/= (T n) { | |
167 | x /= n; | |
168 | y /= n; | |
69 | ||
70 | const lerp2& operator= (const vec2& vec) { | |
71 | this->x = vec.x; | |
72 | this->y = vec.y; | |
73 | return *this; | |
169 | 74 | } |
170 | 75 | }; |
171 | 76 | |
172 | template<class T> class vec3 { | |
77 | class lerp3 : public vec3 { | |
173 | 78 | public: |
174 | T x; | |
175 | T y; | |
176 | T z; | |
79 | vec3 p; | |
80 | vec3 l; | |
177 | 81 | |
178 | vec3(const vec3<T>& vec) { | |
82 | lerp3() : vec3(), p(), l() { | |
83 | } | |
84 | ||
85 | const lerp3& snap() { | |
86 | p = *this; | |
87 | return *this; | |
88 | } | |
89 | ||
90 | static vec3 lerp(const vec3& a, const vec3& b, float n) { | |
91 | return a + (b - a) * n; | |
92 | } | |
93 | ||
94 | const vec3& lerp(float n) { | |
95 | l = p + (*this - p) * n; | |
96 | return l; | |
97 | } | |
98 | ||
99 | const lerp3& operator= (const vec3& vec) { | |
179 | 100 | this->x = vec.x; |
180 | 101 | this->y = vec.y; |
181 | 102 | this->z = vec.z; |
182 | } | |
183 | ||
184 | vec3(const vec2<T>& vec, float z) { | |
185 | this->x = vec.x; | |
186 | this->y = vec.y; | |
187 | this->z = z; | |
188 | } | |
189 | ||
190 | vec3(T x = 0, T y = 0, T z = 0) { | |
191 | this->x = x; | |
192 | this->y = y; | |
193 | this->z = z; | |
194 | } | |
195 | ||
196 | vec3<T> cross(const vec3<T>& vec) const { | |
197 | return vec3<T>(y*vec.z-z*vec.y, z*vec.x-x*vec.z, x*vec.y-y*vec.x); | |
198 | } | |
199 | ||
200 | T dot(const vec3<T>& vec) const { | |
201 | return x*vec.x + y*vec.y + z*vec.z; | |
202 | } | |
203 | ||
204 | T operator* (const vec3<T> &vec) const { | |
205 | return x*vec.x + y*vec.y + z*vec.z; | |
206 | } | |
207 | ||
208 | vec3<T> operator+ (const vec3<T> &vec) const { | |
209 | return vec3<T>(x+vec.x,y+vec.y,z+vec.z); | |
210 | } | |
211 | ||
212 | vec3<T> operator- (const vec3<T> &vec) const { | |
213 | return vec3<T>(x-vec.x,y-vec.y,z-vec.z); | |
214 | } | |
215 | ||
216 | vec3<T> operator* (T n) const { | |
217 | return vec3<T>(x*n,y*n,z*n); | |
218 | } | |
219 | ||
220 | vec3<T> operator/ (const T n) const { | |
221 | return vec3<T>(x/n, y/n, z/n); | |
222 | } | |
223 | ||
224 | friend vec3<T> operator* (T n, const vec3<T>& vec) { | |
225 | return vec3<T>(vec.x*n,vec.y*n,vec.z*n); | |
226 | } | |
227 | ||
228 | bool operator== (vec3<T> &vec) const { | |
229 | return (vec.x==x && vec.y==y && vec.z==z); | |
230 | } | |
231 | ||
232 | bool operator!= (vec3<T> &vec) const { | |
233 | return (vec.x!=x || vec.y!=y || vec.z!=z); | |
234 | } | |
235 | ||
236 | T length2() const { | |
237 | return x*x + y*y + z*z; | |
238 | } | |
239 | ||
240 | T length() const { | |
241 | return sqrt(x*x + y*y + z*z); | |
242 | } | |
243 | ||
244 | void normalize() { | |
245 | T len = length(); | |
246 | if(len == 0) return; | |
247 | ||
248 | *this *= (1.0/len); | |
249 | } | |
250 | ||
251 | vec3<T> normal() const { | |
252 | vec3<T> v(x,y,z); | |
253 | v.normalize(); | |
254 | return v; | |
255 | } | |
256 | ||
257 | vec2<T> truncate() const { | |
258 | return vec2<T>(x, y); | |
259 | } | |
260 | ||
261 | operator T*() const { | |
262 | return (T*) &x; | |
263 | } | |
264 | ||
265 | vec3<T>& operator= (const vec3<T> &vec) { | |
266 | x = vec.x; | |
267 | y = vec.y; | |
268 | z = vec.z; | |
269 | 103 | return *this; |
270 | } | |
271 | ||
272 | void operator+= (const vec3<T> &vec) { | |
273 | x += vec.x; | |
274 | y += vec.y; | |
275 | z += vec.z; | |
276 | } | |
277 | ||
278 | void operator-= (const vec3<T> &vec) { | |
279 | x -= vec.x; | |
280 | y -= vec.y; | |
281 | z -= vec.z; | |
282 | } | |
283 | ||
284 | void operator*= (T n) { | |
285 | x *= n; | |
286 | y *= n; | |
287 | z *= n; | |
288 | } | |
289 | ||
290 | void operator/= (T n) { | |
291 | x /= n; | |
292 | y /= n; | |
293 | z /= n; | |
294 | 104 | } |
295 | 105 | }; |
296 | 106 | |
297 | template<class T> class lerp3 : public vec3<T> { | |
298 | public: | |
299 | vec3<T> p; | |
300 | vec3<T> l; | |
301 | ||
302 | lerp3() : vec3<T>(), p(), l() { | |
303 | } | |
304 | ||
305 | lerp3(const vec3<T>& vec) : vec3<T>(vec) { | |
306 | } | |
307 | ||
308 | void snap() { | |
309 | p = (vec3<T>) *this; | |
310 | } | |
311 | ||
312 | const vec3<T>& lerp(T n) { | |
313 | l = p * n + *this * (1.0-n); | |
314 | return l; | |
315 | } | |
316 | }; | |
317 | ||
318 | template<class T> class vec4 { | |
319 | public: | |
320 | T x; | |
321 | T y; | |
322 | T z; | |
323 | T w; | |
324 | ||
325 | vec4(T x = 0, T y = 0, T z = 0, T w = 0) { | |
326 | this->x = x; | |
327 | this->y = y; | |
328 | this->z = z; | |
329 | this->w = w; | |
330 | } | |
331 | ||
332 | vec4(const vec4<T>& vec) { | |
333 | this->x = vec.x; | |
334 | this->y = vec.y; | |
335 | this->z = vec.z; | |
336 | this->w = vec.w; | |
337 | } | |
338 | ||
339 | vec4(const vec3<T>& vec, T w) { | |
340 | this->x = vec.x; | |
341 | this->y = vec.y; | |
342 | this->z = vec.z; | |
343 | this->w = w; | |
344 | } | |
345 | ||
346 | vec4<T>& operator= (const vec4<T> &vec) { | |
347 | x = vec.x; | |
348 | y = vec.y; | |
349 | z = vec.z; | |
350 | w = vec.w; | |
351 | return *this; | |
352 | } | |
353 | ||
354 | T dot(const vec4<T>& vec) const { | |
355 | return x*vec.x + y*vec.y + z*vec.z + w*vec.w; | |
356 | } | |
357 | ||
358 | vec4<T> operator+ (const vec4<T> &vec) const { | |
359 | return vec4<T>(x+vec.x, y+vec.y, z+vec.z, w+vec.w); | |
360 | } | |
361 | ||
362 | vec4<T> operator- (const vec4<T> &vec) const { | |
363 | return vec4<T>(x-vec.x, y-vec.y, z-vec.z, w-vec.w); | |
364 | } | |
365 | ||
366 | vec4<T> operator* (T n) const { | |
367 | return vec4<T>(x*n, y*n, z*n, w*n); | |
368 | } | |
369 | ||
370 | vec4<T> operator/ (const T n) const { | |
371 | return vec4<T>(x/n, y/n, z/n, w/n); | |
372 | } | |
373 | ||
374 | T operator* (const vec4<T> &vec) const { | |
375 | return x*vec.x + y*vec.y + z*vec.z + w*vec.w; | |
376 | } | |
377 | ||
378 | friend vec4<T> operator* (T n, const vec4<T>& vec) { | |
379 | return vec4<T>(vec.x*n, vec.y*n, vec.z*n, vec.w*n); | |
380 | } | |
381 | ||
382 | bool operator== (const vec4<T> &vec) const { | |
383 | return (vec.x==x && vec.y==y && vec.z==z && vec.w==w); | |
384 | } | |
385 | ||
386 | bool operator!= (const vec4<T> &vec) const { | |
387 | return (vec.x!=x || vec.y!=y || vec.z!=z || vec.w!=w); | |
388 | } | |
389 | ||
390 | T length2() const { | |
391 | return x*x + y*y + z*z + w*w; | |
392 | } | |
393 | ||
394 | T length() const { | |
395 | return sqrt(x*x + y*y + z*z + w*w); | |
396 | } | |
397 | ||
398 | void normalize() { | |
399 | T len = length(); | |
400 | if(len == 0) return; | |
401 | ||
402 | *this *= (1.0/len); | |
403 | } | |
404 | ||
405 | vec4<T> normal() const { | |
406 | vec4<T> v(x,y,z,w); | |
407 | v.normalize(); | |
408 | return v; | |
409 | } | |
410 | ||
411 | vec3<T> truncate() const { | |
412 | return vec3<T>(x, y, z); | |
413 | } | |
414 | ||
415 | operator T*() const { | |
416 | return (T*) &x; | |
417 | } | |
418 | ||
419 | void operator+= (const vec4<T> &vec) { | |
420 | x += vec.x; | |
421 | y += vec.y; | |
422 | z += vec.z; | |
423 | w += vec.w; | |
424 | } | |
425 | ||
426 | void operator-= (const vec4<T> &vec) { | |
427 | x -= vec.x; | |
428 | y -= vec.y; | |
429 | z -= vec.z; | |
430 | w -= vec.w; | |
431 | } | |
432 | ||
433 | void operator*= (T n) { | |
434 | x *= n; | |
435 | y *= n; | |
436 | z *= n; | |
437 | w *= n; | |
438 | } | |
439 | ||
440 | void operator/= (T n) { | |
441 | x /= n; | |
442 | y /= n; | |
443 | z /= n; | |
444 | w /= n; | |
445 | } | |
446 | }; | |
447 | ||
448 | typedef vec2<float> vec2f; | |
449 | typedef vec3<float> vec3f; | |
450 | typedef vec4<float> vec4f; | |
451 | ||
452 | typedef lerp3<float> lerp3f; | |
453 | ||
454 | typedef vec2<int> vec2i; | |
455 | typedef vec3<int> vec3i; | |
456 | typedef vec4<int> vec4i; | |
457 | ||
458 | 107 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "custom.h" | |
18 | ||
19 | Regex custom_regex("^([0-9]+)\\|([^|]*)\\|([ADM]?)\\|([^|]+)(?:\\|#?([A-F0-9]{6}))?"); | |
20 | ||
21 | CustomLog::CustomLog(const std::string& logfile) : RCommitLog(logfile) { | |
22 | } | |
23 | ||
24 | vec3f CustomLog::parseColour(const std::string& cstr) { | |
25 | debugLog("parseColour\n"); | |
26 | vec3f colour; | |
27 | int r,g,b; | |
28 | ||
29 | if(sscanf(cstr.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { | |
30 | ||
31 | colour = vec3f( r, g, b ); | |
32 | colour /= 255.0f; | |
33 | ||
34 | debugLog("colour %.2f %.2f %.2f\n", colour.x,colour.y,colour.z); | |
35 | } | |
36 | ||
37 | return colour; | |
38 | } | |
39 | ||
40 | // parse modified cvs format log entries | |
41 | ||
42 | bool CustomLog::parseCommit(RCommit& commit) { | |
43 | ||
44 | while(parseCommitEntry(commit)); | |
45 | ||
46 | return !commit.files.empty(); | |
47 | } | |
48 | ||
49 | bool CustomLog::parseCommitEntry(RCommit& commit) { | |
50 | ||
51 | std::string line; | |
52 | std::vector<std::string> entries; | |
53 | ||
54 | if(!getNextLine(line)) return false; | |
55 | ||
56 | //custom line | |
57 | if(!custom_regex.match(line, &entries)) return false; | |
58 | ||
59 | long timestamp = atol(entries[0].c_str()); | |
60 | ||
61 | std::string username = (entries[1].size()>0) ? entries[1] : "Unknown"; | |
62 | std::string action = (entries[2].size()>0) ? entries[2] : "A"; | |
63 | ||
64 | //if this file is for the same person and timestamp | |
65 | //we add to the commit, else we save the lastline | |
66 | //and return false | |
67 | if(commit.files.empty()) { | |
68 | commit.timestamp = timestamp; | |
69 | commit.username = username; | |
70 | } else { | |
71 | if(commit.timestamp != timestamp || commit.username != username) { | |
72 | lastline = line; | |
73 | return false; | |
74 | } | |
75 | } | |
76 | ||
77 | bool has_colour = false; | |
78 | vec3f colour; | |
79 | ||
80 | if(entries.size()>=5 && entries[4].size()>0) { | |
81 | has_colour = true; | |
82 | colour = parseColour(entries[4]); | |
83 | } | |
84 | ||
85 | if(has_colour) { | |
86 | commit.addFile(entries[3], action, colour); | |
87 | } else { | |
88 | commit.addFile(entries[3], action); | |
89 | } | |
90 | ||
91 | return true; | |
92 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CUSTOMLOG_H | |
18 | #define CUSTOMLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | class CustomLog : public RCommitLog { | |
23 | protected: | |
24 | bool parseCommit(RCommit& commit); | |
25 | bool parseCommitEntry(RCommit& commit); | |
26 | vec3f parseColour(const std::string& cstr); | |
27 | public: | |
28 | CustomLog(const std::string& logfile); | |
29 | }; | |
30 | ||
31 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "cvs-exp.h" | |
18 | ||
19 | Regex cvsexp_commitno_regex("^([0-9]{6}):"); | |
20 | Regex cvsexp_branch_regex("^BRANCH \\[(.+)\\]$"); | |
21 | Regex cvsexp_date_regex("^\\(date: ([0-9]{4})[-/]([0-9]{2})[-/]([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(?: [+-][0-9]{4})?;(.+)$"); | |
22 | Regex cvsexp_detail_regex("author: ([^;]+); state: ([^;]+);(.+)$"); | |
23 | //Regex cvsexp_lines_regex("lines: \\+([0-9]+) -([0-9]+)"); | |
24 | Regex cvsexp_entry_regex("\\| (.+),v:([0-9.]+),?"); | |
25 | Regex cvsexp_end_regex("^(=+)$"); | |
26 | ||
27 | std::string gGourceCvsExpLogCommand = "cvs-exp.pl -notree"; | |
28 | ||
29 | CVSEXPCommitLog::CVSEXPCommitLog(const std::string& logfile) : RCommitLog(logfile) { | |
30 | } | |
31 | ||
32 | // parse modified cvs format log entries | |
33 | ||
34 | bool CVSEXPCommitLog::parseCommit(RCommit& commit) { | |
35 | ||
36 | std::string line; | |
37 | std::vector<std::string> entries; | |
38 | ||
39 | if(!logf->getNextLine(line)) return false; | |
40 | ||
41 | //skip empty line if there is one | |
42 | if(line.size() == 0) { | |
43 | if(!logf->getNextLine(line)) return false; | |
44 | } | |
45 | ||
46 | //read commit no | |
47 | if(!cvsexp_commitno_regex.match(line, &entries)) return false; | |
48 | ||
49 | //int commitno = atoi(entries[0].c_str()); | |
50 | //debugLog("commitno matched\n"); | |
51 | ||
52 | if(!logf->getNextLine(line)) return false; | |
53 | ||
54 | //should be a branch | |
55 | if(cvsexp_branch_regex.match(line, &entries)) { | |
56 | ||
57 | //read next blank line | |
58 | if(!logf->getNextLine(line)) return false; | |
59 | if(line.size()) return false; | |
60 | if(!logf->getNextLine(line)) return false; | |
61 | } | |
62 | ||
63 | //parse date | |
64 | if(!cvsexp_date_regex.match(line, &entries)) return false; | |
65 | ||
66 | //debugLog("date matched\n"); | |
67 | ||
68 | struct tm time_str; | |
69 | ||
70 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
71 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
72 | time_str.tm_mday = atoi(entries[2].c_str()); | |
73 | time_str.tm_hour = atoi(entries[3].c_str()); | |
74 | time_str.tm_min = atoi(entries[4].c_str()); | |
75 | time_str.tm_sec = atoi(entries[5].c_str()); | |
76 | time_str.tm_isdst = -1; | |
77 | ||
78 | commit.timestamp = mktime(&time_str); | |
79 | ||
80 | //parse author,state | |
81 | std::string rest = entries[6]; | |
82 | if(!cvsexp_detail_regex.match(rest, &entries)) return false; | |
83 | ||
84 | //debugLog("author/state matched\n"); | |
85 | ||
86 | commit.username = entries[0]; | |
87 | ||
88 | std::string commit_state = entries[1]; | |
89 | ||
90 | /* not used | |
91 | //if rest is not ')' parse lines | |
92 | rest = entries[2]; | |
93 | ||
94 | // need to parse lines | |
95 | if(rest.size() > 2) { | |
96 | if(!cvsexp_lines_regex.match(rest, &entries)) return false; | |
97 | } | |
98 | */ | |
99 | ||
100 | if(!logf->getNextLine(line)) return false; | |
101 | ||
102 | std::string commit_action = (commit_state == "dead") ? "D" : "M"; | |
103 | ||
104 | while(cvsexp_entry_regex.match(line, &entries)) { | |
105 | ||
106 | //ignore files in Attic - previously deleted file | |
107 | if(entries[0].find("/Attic/") == std::string::npos) { | |
108 | commit.addFile(entries[0], commit_action); | |
109 | } | |
110 | ||
111 | if(!logf->getNextLine(line)) return false; | |
112 | } | |
113 | ||
114 | //read blank line | |
115 | if(!logf->getNextLine(line)) return false; | |
116 | ||
117 | //std::string message; | |
118 | ||
119 | //read commit message | |
120 | while(logf->getNextLine(line) && line.size()) { | |
121 | //if(message.size()) message += std::string("\n"); | |
122 | //message += line; | |
123 | } | |
124 | ||
125 | //read until end of commit or eof | |
126 | while(logf->getNextLine(line)) { | |
127 | if(cvsexp_end_regex.match(line,&entries)) { | |
128 | //debugLog("read end of commit %s\n", entries[0].c_str()); | |
129 | break; | |
130 | } | |
131 | } | |
132 | ||
133 | return true; | |
134 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CVSLOG_EXP_H | |
18 | #define CVSLOG_EXP_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | class CVSEXPCommitLog : public RCommitLog { | |
23 | protected: | |
24 | bool parseCommit(RCommit& commit); | |
25 | public: | |
26 | CVSEXPCommitLog(const std::string& logfile); | |
27 | }; | |
28 | ||
29 | extern std::string gGourceCvsExpLogCommand; | |
30 | ||
31 | #endif |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "cvs2cl.h" | |
18 | ||
19 | Regex cvs2cl_xml_tag("^<\\??xml"); | |
20 | Regex cvs2cl_logentry_start("^<entry"); | |
21 | Regex cvs2cl_logentry_end("^</entry>"); | |
22 | Regex cvs2cl_logentry_timestamp("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})Z"); | |
23 | ||
24 | std::string gGourceCVS2CLLogCommand = "cvs2cl --chrono --stdout --xml -g-q"; | |
25 | ||
26 | CVS2CLCommitLog::CVS2CLCommitLog(const std::string& logfile) : RCommitLog(logfile, '<') { | |
27 | } | |
28 | ||
29 | bool CVS2CLCommitLog::parseCommit(RCommit& commit) { | |
30 | ||
31 | //fprintf(stderr,"parsing cvs2cl log\n"); | |
32 | ||
33 | std::string line; | |
34 | ||
35 | if(!getNextLine(line)) return false; | |
36 | ||
37 | //start of log entry | |
38 | if(!cvs2cl_logentry_start.match(line)) { | |
39 | ||
40 | //is this the start of the document | |
41 | if(!cvs2cl_xml_tag.match(line)) return false; | |
42 | ||
43 | //fprintf(stderr,"found xml tag\n"); | |
44 | ||
45 | //if so find the first logentry tag | |
46 | ||
47 | bool found_logentry = false; | |
48 | ||
49 | while(getNextLine(line)) { | |
50 | if(cvs2cl_logentry_start.match(line)) { | |
51 | found_logentry = true; | |
52 | break; | |
53 | } | |
54 | } | |
55 | ||
56 | if(!found_logentry) return false; | |
57 | } | |
58 | ||
59 | //fprintf(stderr,"found logentry\n"); | |
60 | ||
61 | logentry.clear(); | |
62 | ||
63 | logentry.append(line); | |
64 | logentry.append("\n"); | |
65 | ||
66 | //fprintf(stderr,"found opening tag\n"); | |
67 | ||
68 | bool endfound = false; | |
69 | ||
70 | while(getNextLine(line)) { | |
71 | logentry.append(line); | |
72 | logentry.append("\n"); | |
73 | if(cvs2cl_logentry_end.match(line)) { | |
74 | //fprintf(stderr,"found closing tag\n"); | |
75 | endfound=true; | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | //incomplete commit | |
81 | if(!endfound) return false; | |
82 | ||
83 | //fprintf(stderr,"read logentry\n"); | |
84 | ||
85 | TiXmlDocument doc; | |
86 | ||
87 | if(!doc.Parse(logentry.c_str())) return false; | |
88 | ||
89 | //fprintf(stderr,"try to parse logentry: %s\n", logentry.c_str()); | |
90 | ||
91 | TiXmlElement* leE = doc.FirstChildElement( "entry" ); | |
92 | ||
93 | std::vector<std::string> entries; | |
94 | ||
95 | if(!leE) return false; | |
96 | ||
97 | //parse date | |
98 | TiXmlElement* dateE = leE->FirstChildElement( "isoDate" ); | |
99 | ||
100 | if(!dateE) return false; | |
101 | ||
102 | std::string timestamp_str(dateE->GetText()); | |
103 | ||
104 | if(!cvs2cl_logentry_timestamp.match(timestamp_str, &entries)) | |
105 | return false; | |
106 | ||
107 | struct tm time_str; | |
108 | ||
109 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
110 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
111 | time_str.tm_mday = atoi(entries[2].c_str()); | |
112 | time_str.tm_hour = atoi(entries[3].c_str()); | |
113 | time_str.tm_min = atoi(entries[4].c_str()); | |
114 | time_str.tm_sec = atoi(entries[5].c_str()); | |
115 | time_str.tm_isdst = -1; | |
116 | ||
117 | commit.timestamp = mktime(&time_str); | |
118 | ||
119 | //parse author | |
120 | TiXmlElement* authorE = leE->FirstChildElement("author"); | |
121 | ||
122 | if(authorE != 0) { | |
123 | ||
124 | std::string author(authorE->GetText()); | |
125 | ||
126 | if(author.empty()) author = "Unknown"; | |
127 | ||
128 | commit.username = author; | |
129 | } | |
130 | ||
131 | //parse changes | |
132 | ||
133 | for(TiXmlElement* fileE = leE->FirstChildElement("file"); fileE != 0; fileE = fileE->NextSiblingElement()) { | |
134 | ||
135 | TiXmlElement* state = fileE->FirstChildElement("cvsstate"); | |
136 | TiXmlElement* name = fileE->FirstChildElement("name"); | |
137 | ||
138 | //check for state | |
139 | if(name == 0 || state == 0) continue; | |
140 | ||
141 | std::string status = strcmp(state->GetText(), "dead") == 0 ? "D" : "M"; | |
142 | std::string file(name->GetText()); | |
143 | ||
144 | if(file.empty()) continue; | |
145 | ||
146 | commit.addFile(file, status); | |
147 | } | |
148 | ||
149 | //fprintf(stderr,"parsed logentry\n"); | |
150 | ||
151 | //read files | |
152 | ||
153 | return true; | |
154 | } |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CVS2CL_H | |
18 | #define CVS2CL_H | |
19 | ||
20 | #include "gource_settings.h" | |
21 | ||
22 | #include "commitlog.h" | |
23 | ||
24 | #include <sstream> | |
25 | ||
26 | #ifdef HAVE_LIBTINYXML | |
27 | #include <tinyxml.h> | |
28 | #else | |
29 | #include "tinyxml/tinyxml.h" | |
30 | #endif | |
31 | ||
32 | ||
33 | #include <unistd.h> | |
34 | ||
35 | extern std::string gGourceCVS2CLLogCommand; | |
36 | ||
37 | class CVS2CLCommitLog : public RCommitLog { | |
38 | protected: | |
39 | bool parseCommit(RCommit& commit); | |
40 | ||
41 | std::string logentry; | |
42 | public: | |
43 | CVS2CLCommitLog(const std::string& logfile); | |
44 | }; | |
45 | ||
46 | #endif |
37 | 37 | parent = 0; |
38 | 38 | setParent(parent); |
39 | 39 | |
40 | accel = spos = prev_accel = vel = vec2(0.0f); | |
41 | ||
42 | //NOTE: parent is always being set to 0 so this never gets called ... | |
43 | ||
40 | 44 | //figure out starting position |
41 | 45 | if(parent !=0) { |
42 | vec2f parentPos = parent->getPos(); | |
43 | vec2f offset; | |
46 | vec2 parentPos = parent->getPos(); | |
47 | vec2 offset; | |
44 | 48 | |
45 | 49 | RDirNode* parentP = parent->getParent(); |
46 | 50 | |
47 | 51 | pos = parentPos; |
48 | 52 | } else { |
49 | pos = vec2f(0.0f, 0.0f); | |
53 | pos = vec2(0.0f, 0.0f); | |
50 | 54 | } |
51 | 55 | |
52 | 56 | float padded_file_radius = gGourceFileDiameter * 0.5; |
113 | 117 | void RDirNode::rotate(float s, float c) { |
114 | 118 | |
115 | 119 | if(parent != 0) { |
116 | pos = pos.rotate(s, c); | |
117 | spos = spos.rotate(s, c); | |
120 | pos = rotate_vec2(pos, s, c); | |
121 | spos = rotate_vec2(spos, s, c); | |
118 | 122 | } |
119 | 123 | |
120 | 124 | for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { |
123 | 127 | } |
124 | 128 | } |
125 | 129 | |
126 | void RDirNode::setPos(const vec2f & pos) { | |
130 | void RDirNode::setPos(const vec2 & pos) { | |
127 | 131 | this->pos = pos; |
128 | 132 | } |
129 | 133 | |
145 | 149 | return parent; |
146 | 150 | } |
147 | 151 | |
152 | ||
153 | bool RDirNode::isDir(const std::string& path) const { | |
154 | ||
155 | if(prefixedBy(path)) return true; | |
156 | ||
157 | if(path.find(abspath) != 0) return false; | |
158 | ||
159 | for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) { | |
160 | if((*it)->isDir(path)) return true; | |
161 | } | |
162 | ||
163 | return false; | |
164 | } | |
148 | 165 | |
149 | 166 | //finds directories closest to the root directory prefixed by path (eg foo/ may match just foo/ or could also match foo/bar1, foo/bar2, ... if foo/ doesn't exist). |
150 | 167 | void RDirNode::findDirs(const std::string& path, std::list<RDirNode*>& dirs) { |
368 | 385 | //simply change path of node and add this to it |
369 | 386 | if( parent==0 && abspath == "/" |
370 | 387 | && f->path.compare(abspath) != 0 && noFiles() && noDirs()) { |
371 | debugLog("modifying root path to %s\n", f->path.c_str()); | |
388 | debugLog("modifying root path to %s", f->path.c_str()); | |
372 | 389 | changePath(f->path); |
373 | 390 | } |
374 | 391 | |
401 | 418 | //do we have a file in this directory thats fullpath is a prefix of this file, if so |
402 | 419 | //that file is actually a directory - the file should be removed, and a directory with that path added |
403 | 420 | //if this is the root node we do this regardless of if the file was added to a child node |
421 | ||
404 | 422 | for(std::list<RFile*>::const_iterator it = files.begin(); it != files.end(); it++) { |
405 | 423 | RFile* file = (*it); |
406 | ||
424 | ||
407 | 425 | if(f->path.find(file->fullpath) == 0) { |
408 | 426 | //fprintf(stderr, "removing %s as is actually the directory of %s\n", file->fullpath.c_str(), f->fullpath.c_str()); |
409 | 427 | file->remove(true); |
425 | 443 | // if so create another node, and move those nodes there |
426 | 444 | |
427 | 445 | std::string commonpath; |
428 | vec2f commonPos; | |
446 | vec2 commonPos; | |
429 | 447 | for(std::list<RDirNode*>::iterator it = children.begin(); it != children.end(); it++) { |
430 | 448 | RDirNode* child = (*it); |
431 | 449 | |
475 | 493 | return dir_radius_sqrt; |
476 | 494 | } |
477 | 495 | |
478 | vec3f RDirNode::averageFileColour() const{ | |
479 | ||
480 | vec3f av; | |
496 | vec3 RDirNode::averageFileColour() const{ | |
497 | ||
498 | vec3 av; | |
481 | 499 | int count = 0; |
482 | 500 | |
483 | 501 | for(std::list<RFile*>::const_iterator it = files.begin(); it != files.end(); it++) { |
506 | 524 | return av; |
507 | 525 | } |
508 | 526 | |
509 | const vec4f & RDirNode::getColour() const{ | |
527 | const vec4 & RDirNode::getColour() const{ | |
510 | 528 | return col; |
511 | 529 | } |
512 | 530 | |
515 | 533 | // make branch brighter if recently accessed |
516 | 534 | float brightness = std::max(0.6f, 1.0f - std::min(1.0f, since_last_node_change / 3.0f)); |
517 | 535 | |
518 | col = vec4f(brightness, brightness, brightness, 1.0); | |
536 | col = vec4(brightness, brightness, brightness, 1.0); | |
519 | 537 | |
520 | 538 | int fcount = 0; |
521 | 539 | |
524 | 542 | |
525 | 543 | if(file->isHidden()) continue;; |
526 | 544 | |
527 | vec3f filecol = file->getColour() * brightness; | |
545 | vec3 filecol = file->getColour() * brightness; | |
528 | 546 | float a = file->getAlpha(); |
529 | 547 | |
530 | col += vec4f(filecol.x, filecol.y, filecol.z, a); | |
548 | col += vec4(filecol.x, filecol.y, filecol.z, a); | |
531 | 549 | |
532 | 550 | fcount++; |
533 | 551 | } |
563 | 581 | |
564 | 582 | float RDirNode::distanceToParent() const{ |
565 | 583 | |
566 | float posd = (parent->getPos() - pos).length(); | |
584 | float posd = glm::length(parent->getPos() - pos); | |
567 | 585 | float distance = posd - (dir_radius + parent->getParentRadius()); |
568 | ||
586 | ||
569 | 587 | return distance; |
570 | 588 | } |
571 | 589 | |
572 | 590 | void RDirNode::applyForceDir(RDirNode* node) { |
573 | 591 | if(node == this) return; |
574 | 592 | |
575 | vec2f dir = node->getPos() - pos; | |
576 | ||
577 | float posd2 = dir.length2(); | |
593 | vec2 dir = node->getPos() - pos; | |
594 | ||
595 | float posd2 = glm::length2(dir); | |
578 | 596 | float myradius = getRadius(); |
579 | 597 | float your_radius = node->getRadius(); |
580 | ||
598 | ||
581 | 599 | float sumradius = (myradius + your_radius); |
582 | 600 | |
583 | 601 | float distance2 = posd2 - sumradius*sumradius; |
590 | 608 | |
591 | 609 | //resolve overlap |
592 | 610 | if(posd < 0.00001) { |
593 | accel += vec2f( (rand() % 100) - 50, (rand() % 100) - 50).normal(); | |
611 | accel += normalise(vec2( (rand() % 100) - 50, (rand() % 100) - 50)); | |
594 | 612 | return; |
595 | 613 | } |
596 | 614 | |
597 | accel += distance * dir.normal(); | |
598 | } | |
599 | ||
600 | const vec2f & RDirNode::getPos() const{ | |
615 | accel += distance * normalise(dir); | |
616 | } | |
617 | ||
618 | const vec2 & RDirNode::getPos() const{ | |
601 | 619 | return pos; |
602 | 620 | } |
603 | 621 | |
636 | 654 | // * dirs should attract to sit on the radius of the parent dir ie: |
637 | 655 | // should attract to distance_to_parent * normal_to_parent |
638 | 656 | |
639 | accel += gGourceForceGravity * parent_dist * (parent->getPos() - pos).normal(); | |
640 | ||
657 | ||
658 | ||
659 | accel += gGourceForceGravity * parent_dist * normalise(parent->getPos() - pos); | |
660 | ||
641 | 661 | // * dirs should be pushed along the parent_parent to parent normal by a force smaller than the parent radius force |
642 | 662 | RDirNode* pparent = parent->getParent(); |
643 | 663 | |
644 | 664 | if(pparent != 0) { |
645 | vec2f parent_edge = (parent->getPos() - pparent->getPos()); | |
646 | vec2f parent_edge_normal = parent_edge.normal(); | |
647 | ||
648 | vec2f dest = (parent->getPos() + (parent->getRadius() + getRadius()) * parent_edge_normal) - pos; | |
665 | vec2 parent_edge = (parent->getPos() - pparent->getPos()); | |
666 | vec2 parent_edge_normal = normalise(parent_edge); | |
667 | ||
668 | vec2 dest = (parent->getPos() + (parent->getRadius() + getRadius()) * parent_edge_normal) - pos; | |
649 | 669 | |
650 | 670 | accel += dest; |
651 | 671 | } |
653 | 673 | // * dirs should repulse from other dirs of this parent |
654 | 674 | const std::list<RDirNode*> & siblings = parent->getChildren(); |
655 | 675 | if(!siblings.empty()) { |
656 | vec2f sib_accel; | |
676 | vec2 sib_accel; | |
657 | 677 | |
658 | 678 | int visible = 1; |
659 | 679 | |
665 | 685 | |
666 | 686 | visible++; |
667 | 687 | |
668 | sib_accel -= (node->getPos() - pos).normal(); | |
688 | sib_accel -= normalise(node->getPos() - pos); | |
669 | 689 | } |
670 | 690 | |
671 | 691 | //parent circumfrence divided by the number of visible child nodes |
683 | 703 | std::string indentstr; |
684 | 704 | while(indentstr.size() < indent) indentstr += " "; |
685 | 705 | |
686 | debugLog("%s%s\n", indentstr.c_str(), abspath.c_str()); | |
706 | debugLog("%s%s", indentstr.c_str(), abspath.c_str()); | |
687 | 707 | |
688 | 708 | for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) { |
689 | 709 | RDirNode* node = (*it); |
729 | 749 | if(parent == 0) return; |
730 | 750 | |
731 | 751 | //update the spline point |
732 | vec2f td = (parent->getPos() - pos) * 0.5; | |
733 | ||
734 | vec2f mid = pos + td;// - td.perpendicular() * pos.normal();// * 10.0; | |
735 | ||
736 | vec2f delta = (mid - spos); | |
752 | vec2 td = (parent->getPos() - pos) * 0.5f; | |
753 | ||
754 | vec2 mid = pos + td;// - td.perpendicular() * pos.normal();// * 10.0; | |
755 | ||
756 | vec2 delta = (mid - spos); | |
737 | 757 | |
738 | 758 | //dont let spos get more than half the length of the distance behind |
739 | if(delta.length2() > td.length2()) { | |
740 | spos += delta.normal() * (delta.length() - td.length()); | |
741 | } | |
742 | ||
743 | spos += delta * std::min(1.0, dt * 2.0); | |
759 | if(glm::length2(delta) > glm::length2(td)) { | |
760 | spos += normalise(delta) * (glm::length(delta) - glm::length(td)); | |
761 | } | |
762 | ||
763 | spos += delta * std::min(1.0f, dt * 2.0f); | |
744 | 764 | } |
745 | 765 | |
746 | 766 | void RDirNode::setInitialPosition() { |
750 | 770 | |
751 | 771 | //offset position by some pseudo-randomness |
752 | 772 | if(parentP != 0) { |
753 | pos += ((parent->getPos() - parentP->getPos()).normal() * 2.0 + vec2Hash(abspath)).normal(); | |
773 | //pos += ((parent->getPos() - parentP->getPos()).normal() * 2.0 + vec2Hash(abspath)).normal(); | |
774 | pos += normalise(normalise(parent->getPos() - parentP->getPos()) * 2.0f + vec2Hash(abspath)); | |
775 | ||
754 | 776 | } else { |
755 | 777 | pos += vec2Hash(abspath); |
756 | 778 | } |
757 | ||
779 | ||
758 | 780 | //the spline point |
759 | spos = pos - (parent->getPos() - pos) * 0.5; | |
781 | spos = pos - (parent->getPos() - pos) * 0.5f; | |
760 | 782 | position_initialized=true; |
761 | 783 | } |
762 | 784 | |
764 | 786 | |
765 | 787 | //the root node is the centre of the world |
766 | 788 | if(parent == 0) { |
767 | pos = vec2f(0.0, 0.0); | |
789 | pos = vec2(0.0f); | |
768 | 790 | return; |
769 | 791 | } |
770 | 792 | |
776 | 798 | pos += accel * dt; |
777 | 799 | |
778 | 800 | if(gGourceSettings.elasticity>0.0) { |
779 | vec2f diff = (accel - prev_accel); | |
801 | vec2 diff = (accel - prev_accel); | |
780 | 802 | |
781 | 803 | float m = dt * gGourceSettings.elasticity; |
782 | 804 | |
783 | vec2f accel3 = prev_accel * (1.0-m) + diff * m; | |
805 | vec2 accel3 = prev_accel * (1.0f-m) + diff * m; | |
784 | 806 | pos += accel3; |
785 | 807 | prev_accel = accel3; |
786 | 808 | } |
787 | 809 | |
788 | 810 | //accel = accel * std::max(0.0f, (1.0f - dt*10.0f)); |
789 | accel = vec2f(0.0, 0.0); | |
790 | } | |
791 | ||
792 | const vec2f & RDirNode::getNodeNormal() const{ | |
811 | accel = vec2(0.0, 0.0); | |
812 | } | |
813 | ||
814 | const vec2 & RDirNode::getNodeNormal() const{ | |
793 | 815 | return node_normal; |
794 | 816 | } |
795 | 817 | |
796 | vec2f RDirNode::calcFileDest(int max_files, int file_no) { | |
818 | vec2 RDirNode::calcFileDest(int max_files, int file_no) { | |
797 | 819 | |
798 | 820 | float arc = 1.0/(float)max_files; |
799 | 821 | |
800 | 822 | float frac = arc * 0.5 + arc * file_no; |
801 | 823 | |
802 | vec2f dest = vec2f(sinf(frac*PI*2.0), cosf(frac*PI*2.0)); | |
824 | vec2 dest = vec2(sinf(frac*PI*2.0), cosf(frac*PI*2.0)); | |
803 | 825 | |
804 | 826 | return dest; |
805 | 827 | } |
817 | 839 | RFile* f = *it; |
818 | 840 | |
819 | 841 | if(f->isHidden()) { |
820 | f->setDest(vec2f(0.0,0.0)); | |
842 | f->setDest(vec2(0.0,0.0)); | |
821 | 843 | f->setDistance(0.0f); |
822 | 844 | continue; |
823 | 845 | } |
824 | 846 | |
825 | vec2f dest = calcFileDest(max_files, file_no); | |
847 | vec2 dest = calcFileDest(max_files, file_no); | |
826 | 848 | |
827 | 849 | f->setDest(dest); |
828 | 850 | f->setDistance(d); |
865 | 887 | |
866 | 888 | //update node normal |
867 | 889 | if(parent != 0) { |
868 | node_normal = (pos - parent->getPos()).normal(); | |
890 | node_normal = normalise(pos - parent->getPos()); | |
869 | 891 | } |
870 | 892 | |
871 | 893 | //update files |
900 | 922 | |
901 | 923 | float alpha = gGourceSettings.highlight_dirs ? 1.0 : std::max(0.0f, 5.0f - since_last_node_change) / 5.0f; |
902 | 924 | |
903 | vec2f mid = spline.getMidPoint(); | |
925 | vec2 mid = spline.getMidPoint(); | |
904 | 926 | |
905 | 927 | dirfont.setAlpha(alpha); |
906 | 928 | dirfont.draw(mid.x, mid.y, path_token); |
920 | 942 | projected_spos.x = screen_x; |
921 | 943 | projected_spos.y = screen_y; |
922 | 944 | |
923 | static vec2f selected_offset(5.5f, -2.0f); | |
924 | static vec2f unselected_offset(5.5f, -1.0f); | |
945 | static vec2 selected_offset(5.5f, -2.0f); | |
946 | static vec2 unselected_offset(5.5f, -1.0f); | |
925 | 947 | |
926 | 948 | if(!gGourceSettings.hide_filenames) { |
927 | 949 | |
1004 | 1026 | |
1005 | 1027 | if(f->isHidden()) continue; |
1006 | 1028 | |
1007 | vec3f col = f->getColour(); | |
1029 | vec3 col = f->getColour(); | |
1008 | 1030 | float alpha = f->getAlpha(); |
1009 | 1031 | |
1010 | buffer.add(f->graphic->textureid, f->getAbsolutePos() - f->dims*0.5f, f->dims, vec4f(col.x, col.y, col.z, alpha)); | |
1032 | buffer.add(f->graphic->textureid, f->getAbsolutePos() - f->dims*0.5f, f->dims, vec4(col.x, col.y, col.z, alpha)); | |
1011 | 1033 | } |
1012 | 1034 | } |
1013 | 1035 | |
1023 | 1045 | |
1024 | 1046 | float bloom_radius = dir_radius * 2.0 * gGourceSettings.bloom_multiplier; |
1025 | 1047 | float bloom_diameter = bloom_radius * 2.0; |
1026 | vec4f bloom_col = col * gGourceSettings.bloom_intensity; | |
1027 | ||
1028 | vec4f bloom_texcoords(bloom_radius, pos.x, pos.y, 0.0f); | |
1029 | ||
1030 | vec2f bloom_dims(bloom_diameter, bloom_diameter); | |
1031 | ||
1032 | buffer.add(0, pos - bloom_dims*0.5f,bloom_dims, vec4f(bloom_col.x, bloom_col.y, bloom_col.z, 1.0f), bloom_texcoords); | |
1048 | vec4 bloom_col = col * gGourceSettings.bloom_intensity; | |
1049 | ||
1050 | vec4 bloom_texcoords(bloom_radius, pos.x, pos.y, 0.0f); | |
1051 | ||
1052 | vec2 bloom_dims(bloom_diameter, bloom_diameter); | |
1053 | ||
1054 | buffer.add(0, pos - bloom_dims*0.5f,bloom_dims, vec4(bloom_col.x, bloom_col.y, bloom_col.z, 1.0f), bloom_texcoords); | |
1033 | 1055 | } |
1034 | 1056 | |
1035 | 1057 | for(std::list<RDirNode*>::const_iterator it = children.begin(); it != children.end(); it++) { |
1042 | 1064 | |
1043 | 1065 | if(in_frustum) { |
1044 | 1066 | |
1045 | vec4f col = getColour(); | |
1067 | vec4 col = getColour(); | |
1046 | 1068 | |
1047 | 1069 | glPushMatrix(); |
1048 | 1070 | glTranslatef(pos.x, pos.y, 0.0); |
1065 | 1087 | } |
1066 | 1088 | } |
1067 | 1089 | |
1068 | const vec2f & RDirNode::getSPos() const{ | |
1090 | const vec2 & RDirNode::getSPos() const{ | |
1069 | 1091 | return projected_spos; |
1070 | 1092 | } |
1071 | 1093 | |
1072 | const vec2f & RDirNode::getProjectedPos() const{ | |
1094 | const vec2 & RDirNode::getProjectedPos() const{ | |
1073 | 1095 | return projected_pos; |
1074 | 1096 | } |
1075 | 1097 | |
1120 | 1142 | |
1121 | 1143 | float bloom_radius = dir_radius * 2.0 * gGourceSettings.bloom_multiplier; |
1122 | 1144 | |
1123 | vec4f bloom_col = col * gGourceSettings.bloom_intensity; | |
1145 | vec4 bloom_col = col * gGourceSettings.bloom_intensity; | |
1124 | 1146 | |
1125 | 1147 | glColor4f(bloom_col.x, bloom_col.y, bloom_col.z, 1.0); |
1126 | 1148 | |
1149 | 1171 | void RDirNode::updateQuadItemBounds() { |
1150 | 1172 | float radius = getRadius(); |
1151 | 1173 | |
1152 | vec2f radoffset(radius, radius); | |
1174 | vec2 radoffset(radius, radius); | |
1153 | 1175 | |
1154 | 1176 | //set bounds |
1155 | 1177 | quadItemBounds.set(pos - radoffset, pos + radoffset); |
46 | 46 | |
47 | 47 | SplineEdge spline; |
48 | 48 | |
49 | vec4f col; | |
50 | ||
51 | vec2f spos; | |
52 | ||
53 | vec2f projected_pos; | |
54 | vec2f projected_spos; | |
55 | ||
56 | vec2f pos; | |
57 | vec2f vel; | |
58 | vec2f accel, prev_accel; | |
49 | vec4 col; | |
50 | ||
51 | vec2 spos; | |
52 | ||
53 | vec2 projected_pos; | |
54 | vec2 projected_spos; | |
55 | ||
56 | vec2 pos; | |
57 | vec2 vel; | |
58 | vec2 accel, prev_accel; | |
59 | 59 | |
60 | 60 | float dir_area; |
61 | 61 | |
76 | 76 | |
77 | 77 | int visible_count; |
78 | 78 | |
79 | vec3f screenpos; | |
80 | vec2f node_normal; | |
79 | vec3 screenpos; | |
80 | vec2 node_normal; | |
81 | 81 | |
82 | 82 | void calcRadius(); |
83 | 83 | void calcColour(); |
92 | 92 | void updateSplinePoint(float dt); |
93 | 93 | void move(float dt); |
94 | 94 | |
95 | vec2f calcFileDest(int layer_no, int file_no); | |
95 | vec2 calcFileDest(int layer_no, int file_no); | |
96 | 96 | void updateFilePositions(); |
97 | 97 | |
98 | 98 | void adjustPath(); |
132 | 132 | |
133 | 133 | const std::string & getPath() const; |
134 | 134 | |
135 | const vec2f & getNodeNormal() const; | |
135 | const vec2 & getNodeNormal() const; | |
136 | 136 | |
137 | 137 | bool isParent(RDirNode* node) const; |
138 | 138 | |
152 | 152 | const std::list<RFile*>* getFiles() const { return &files; }; |
153 | 153 | void getFilesRecursive(std::list<RFile*>& files) const; |
154 | 154 | |
155 | vec3f averageFileColour() const; | |
156 | ||
157 | const vec4f & getColour() const; | |
155 | vec3 averageFileColour() const; | |
156 | ||
157 | const vec4 & getColour() const; | |
158 | 158 | |
159 | 159 | RDirNode* getParent() const; |
160 | 160 | |
161 | bool isDir(const std::string& path) const; | |
161 | 162 | void findDirs(const std::string& path, std::list<RDirNode*>& dirs); |
162 | 163 | |
163 | const vec2f & getPos() const; | |
164 | const vec2 & getPos() const; | |
164 | 165 | |
165 | 166 | void calcEdges(); |
166 | 167 | |
167 | const vec2f & getProjectedPos() const; | |
168 | const vec2f & getSPos() const; | |
169 | ||
170 | void setPos(const vec2f & pos); | |
168 | const vec2 & getProjectedPos() const; | |
169 | const vec2 & getSPos() const; | |
170 | ||
171 | void setPos(const vec2 & pos); | |
171 | 172 | |
172 | 173 | void rotate(float s, float c); |
173 | 174 |
23 | 23 | FXFont file_selected_font; |
24 | 24 | FXFont file_font; |
25 | 25 | |
26 | RFile::RFile(const std::string & name, const vec3f & colour, const vec2f & pos, int tagid) : Pawn(name,pos,tagid) { | |
26 | RFile::RFile(const std::string & name, const vec3 & colour, const vec2 & pos, int tagid) : Pawn(name,pos,tagid) { | |
27 | 27 | hidden = true; |
28 | size = gGourceFileDiameter; | |
28 | size = gGourceFileDiameter * 1.05; | |
29 | 29 | radius = size * 0.5; |
30 | 30 | |
31 | 31 | setGraphic(gGourceSettings.file_graphic); |
34 | 34 | nametime = 4.0; |
35 | 35 | name_interval = nametime; |
36 | 36 | |
37 | namecol = vec3f(1.0, 1.0, 1.0); | |
37 | namecol = vec3(1.0, 1.0, 1.0); | |
38 | 38 | file_colour = colour; |
39 | 39 | |
40 | 40 | last_action = 0.0; |
51 | 51 | file_selected_font = fontmanager.grab("FreeSans.ttf", 18); |
52 | 52 | file_selected_font.dropShadow(true); |
53 | 53 | file_selected_font.roundCoordinates(false); |
54 | file_selected_font.setColour(vec4f(1.0f, 1.0f, 0.0f, 1.0f)); | |
54 | file_selected_font.setColour(vec4(gGourceSettings.selection_colour, 1.0f)); | |
55 | 55 | } |
56 | 56 | |
57 | 57 | if(!file_font.initialized()) { |
58 | 58 | file_font = fontmanager.grab("FreeSans.ttf", 14); |
59 | 59 | file_font.dropShadow(true); |
60 | 60 | file_font.roundCoordinates(false); |
61 | file_font.setColour(vec4f(1.0f, 1.0f, 1.0f, 1.0f)); | |
61 | file_font.setColour(vec4(1.0f, 1.0f, 1.0f, 1.0f)); | |
62 | 62 | } |
63 | 63 | |
64 | 64 | //namelist = glGenLists(1); |
85 | 85 | return dir; |
86 | 86 | } |
87 | 87 | |
88 | vec2f RFile::getAbsolutePos() const{ | |
88 | vec2 RFile::getAbsolutePos() const{ | |
89 | 89 | return pos + dir->getPos(); |
90 | 90 | } |
91 | 91 | |
92 | bool RFile::overlaps(const vec2f& pos) const { | |
93 | ||
94 | vec2f abs_pos = getAbsolutePos(); | |
92 | bool RFile::overlaps(const vec2& pos) const { | |
93 | ||
94 | vec2 abs_pos = getAbsolutePos(); | |
95 | 95 | |
96 | 96 | float halfsize_x = size * 0.5f; |
97 | vec2f halfsize ( halfsize_x, halfsize_x * graphic_ratio ); | |
97 | vec2 halfsize ( halfsize_x, halfsize_x * graphic_ratio ); | |
98 | 98 | |
99 | 99 | Bounds2D file_bounds(abs_pos - halfsize, abs_pos + halfsize); |
100 | 100 | |
153 | 153 | } |
154 | 154 | |
155 | 155 | void RFile::colourize() { |
156 | file_colour = ext.size() ? colourHash(ext) : vec3f(1.0f, 1.0f, 1.0f); | |
157 | } | |
158 | ||
159 | const vec3f& RFile::getNameColour() const{ | |
160 | return selected ? selectedcol : namecol; | |
161 | } | |
162 | ||
163 | const vec3f & RFile::getFileColour() const{ | |
156 | file_colour = ext.size() ? colourHash(ext) : vec3(1.0f, 1.0f, 1.0f); | |
157 | } | |
158 | ||
159 | const vec3& RFile::getNameColour() const{ | |
160 | return selected ? gGourceSettings.selection_colour : namecol; | |
161 | } | |
162 | ||
163 | const vec3 & RFile::getFileColour() const{ | |
164 | 164 | return file_colour; |
165 | 165 | } |
166 | 166 | |
167 | vec3f RFile::getColour() const{ | |
168 | if(selected) return vec3f(1.0, 1.0, 1.0); | |
167 | vec3 RFile::getColour() const{ | |
168 | if(selected) return vec3(1.0f); | |
169 | 169 | |
170 | 170 | float lc = elapsed - last_action; |
171 | 171 | |
172 | if(lc<1.0) { | |
173 | return touch_colour * (1.0-lc) + file_colour * lc; | |
172 | if(lc<1.0f) { | |
173 | return touch_colour * (1.0f-lc) + file_colour * lc; | |
174 | 174 | } |
175 | 175 | |
176 | 176 | return file_colour; |
190 | 190 | void RFile::logic(float dt) { |
191 | 191 | Pawn::logic(dt); |
192 | 192 | |
193 | vec2f dest_pos = dest; | |
193 | vec2 dest_pos = dest; | |
194 | 194 | /* |
195 | 195 | if(dir->getParent() != 0 && dir->noDirs()) { |
196 | vec2f dirnorm = dir->getNodeNormal(); | |
196 | vec2 dirnorm = dir->getNodeNormal(); | |
197 | 197 | dest_pos = dirnorm + dest; |
198 | 198 | }*/ |
199 | 199 | |
204 | 204 | accel = dest_pos - pos; |
205 | 205 | |
206 | 206 | // apply accel |
207 | vec2f accel2 = accel * speed * dt; | |
208 | ||
209 | if(accel2.length2() > accel.length2()) { | |
207 | vec2 accel2 = accel * speed * dt; | |
208 | ||
209 | if(glm::length2(accel2) > glm::length2(accel)) { | |
210 | 210 | accel2 = accel; |
211 | 211 | } |
212 | 212 | |
213 | 213 | pos += accel2; |
214 | 214 | |
215 | 215 | //files have no momentum |
216 | accel = vec2f(0.0f, 0.0f); | |
216 | accel = vec2(0.0f, 0.0f); | |
217 | 217 | |
218 | 218 | // has completely faded out |
219 | 219 | if(!expiring && elapsed - last_action >= gGourceSettings.file_idle_time + 1.0) { |
238 | 238 | if(isHidden() && !removing) elapsed = 0.0; |
239 | 239 | } |
240 | 240 | |
241 | void RFile::touch(const vec3f & colour) { | |
241 | void RFile::touch(const vec3 & colour) { | |
242 | 242 | if(removing) return; |
243 | 243 | |
244 | 244 | //fprintf(stderr, "touch %s\n", fullpath.c_str()); |
275 | 275 | |
276 | 276 | static GLdouble screen_x, screen_y, screen_z; |
277 | 277 | |
278 | vec2f text_pos = getAbsolutePos(); | |
278 | vec2 text_pos = getAbsolutePos(); | |
279 | 279 | text_pos.x += 5.5f; |
280 | 280 | |
281 | 281 | if(selected) |
17 | 17 | #ifndef RFILE_H |
18 | 18 | #define RFILE_H |
19 | 19 | |
20 | #include "core/stringhash.h" | |
21 | ||
22 | 20 | #include "pawn.h" |
23 | 21 | #include "dirnode.h" |
22 | #include "core/stringhash.h" | |
24 | 23 | |
25 | 24 | class RDirNode; |
26 | 25 | |
27 | 26 | class RFile : public Pawn { |
28 | vec3f file_colour; | |
29 | vec3f touch_colour; | |
27 | vec3 file_colour; | |
28 | vec3 touch_colour; | |
30 | 29 | |
31 | 30 | RDirNode* dir; |
32 | 31 | |
37 | 36 | |
38 | 37 | float radius; |
39 | 38 | |
40 | vec2f dest; | |
39 | vec2 dest; | |
41 | 40 | float distance; |
42 | 41 | |
43 | 42 | // FXLabel* label; |
46 | 45 | |
47 | 46 | void setFilename(const std::string& abs_file_path); |
48 | 47 | |
49 | const vec3f& getNameColour() const; | |
48 | const vec3& getNameColour() const; | |
50 | 49 | void drawNameText(float alpha); |
51 | 50 | public: |
52 | 51 | std::string path; |
53 | 52 | std::string fullpath; |
54 | 53 | std::string ext; |
55 | 54 | |
56 | RFile(const std::string & name, const vec3f & colour, const vec2f & pos, int tagid); | |
55 | RFile(const std::string & name, const vec3 & colour, const vec2 & pos, int tagid); | |
57 | 56 | ~RFile(); |
58 | 57 | |
59 | 58 | bool isExpiring() const { return expiring; } |
60 | 59 | bool isRemoving() const { return removing; } |
61 | 60 | |
62 | bool overlaps(const vec2f& pos) const; | |
61 | bool overlaps(const vec2& pos) const; | |
63 | 62 | |
64 | const vec3f & getFileColour() const; | |
65 | vec3f getColour() const; | |
63 | const vec3 & getFileColour() const; | |
64 | vec3 getColour() const; | |
66 | 65 | void colourize(); |
67 | 66 | |
68 | 67 | float getAlpha() const; |
69 | 68 | |
70 | void touch(const vec3f & colour); | |
69 | void touch(const vec3 & colour); | |
71 | 70 | |
72 | 71 | void setSelected(bool selected); |
73 | 72 | |
75 | 74 | |
76 | 75 | void setHidden(bool hidden); |
77 | 76 | |
78 | void setDest(const vec2f & dest){ this->dest = dest; } | |
77 | void setDest(const vec2 & dest){ this->dest = dest; } | |
79 | 78 | void setDistance(float distance){ this->distance = distance; } |
80 | 79 | |
81 | 80 | void calcScreenPos(GLint* viewport, GLdouble* modelview, GLdouble* projection); |
85 | 84 | |
86 | 85 | void remove(bool force=false); |
87 | 86 | |
88 | vec2f getAbsolutePos() const; | |
87 | vec2 getAbsolutePos() const; | |
89 | 88 | |
90 | 89 | RDirNode* getDir() const; |
91 | 90 | void setDir(RDirNode* dir); |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "apache.h" | |
18 | ||
19 | const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug" , "Sep", "Oct", "Nov", "Dec" }; | |
20 | Regex apache_entry_start("^(?:[^ ]+ )?([^ ]+) +[^ ]+ +([^ ]+) +\\[(.*?)\\] +(.*)$"); | |
21 | Regex apache_entry_date("(\\d+)/([A-Za-z]+)/(\\d+):(\\d+):(\\d+):(\\d+) ([+-])(\\d+)"); | |
22 | Regex apache_entry_request("\"([^ ]+) +([^ ]+) +([^ ]+)\" +([^ ]+) +([^\\s+]+)(.*)"); | |
23 | Regex apache_entry_agent(" +\"([^\"]+)\" +\"([^\"]+)\" +\"([^\"]+)\""); | |
24 | Regex apache_hostname_parts("([^.]+)(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?(?:\\.([^.]+))?$"); | |
25 | ||
26 | ApacheCombinedLog::ApacheCombinedLog(const std::string& logfile) : RCommitLog(logfile) { | |
27 | } | |
28 | ||
29 | //parse apache access.log entry into components | |
30 | bool ApacheCombinedLog::parseCommit(RCommit& commit) { | |
31 | ||
32 | std::string line; | |
33 | std::vector<std::string> matches; | |
34 | ||
35 | if(!logf->getNextLine(line)) return false; | |
36 | ||
37 | apache_entry_start.match(line, &matches); | |
38 | ||
39 | if(matches.size()!=4) { | |
40 | return 0; | |
41 | } | |
42 | ||
43 | //get details | |
44 | commit.username = matches[0]; | |
45 | //std::string user = matches[1]; | |
46 | ||
47 | //parse timestamp | |
48 | struct tm time_str; | |
49 | ||
50 | std::string request_str = matches[3]; | |
51 | std::string datestr = matches[2]; | |
52 | ||
53 | apache_entry_date.match(datestr, &matches); | |
54 | ||
55 | if(matches.size()!=8) { | |
56 | return 0; | |
57 | } | |
58 | ||
59 | int day = atoi(matches[0].c_str()); | |
60 | int year = atoi(matches[2].c_str()); | |
61 | int hour = atoi(matches[3].c_str()); | |
62 | int minute = atoi(matches[4].c_str()); | |
63 | int second = atoi(matches[5].c_str()); | |
64 | ||
65 | // int zone = atoi(matches[7].c_str()); | |
66 | //negative timezone | |
67 | // if(strcmp(matches[6].c_str(), "-")==0) { | |
68 | // zone = -zone; | |
69 | // } | |
70 | ||
71 | int month=0; | |
72 | ||
73 | for(int i=0;i<12;i++) { | |
74 | if(matches[1] == months[i]) { | |
75 | month=i; | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | time_str.tm_year = year - 1900; | |
81 | time_str.tm_mon = month; | |
82 | time_str.tm_mday = day; | |
83 | time_str.tm_hour = hour; | |
84 | time_str.tm_min = minute; | |
85 | time_str.tm_sec = second; | |
86 | time_str.tm_isdst = -1; | |
87 | ||
88 | commit.timestamp = mktime(&time_str); | |
89 | ||
90 | matches.clear(); | |
91 | apache_entry_request.match(request_str, &matches); | |
92 | ||
93 | if(matches.size() < 5) { | |
94 | return false; | |
95 | } | |
96 | ||
97 | std::string rtype = matches[0]; | |
98 | std::string file = matches[1]; | |
99 | std::string proto = matches[2]; | |
100 | ||
101 | int code = atoi(matches[3].c_str()); | |
102 | int bytes = atol(matches[4].c_str()); | |
103 | ||
104 | //remove args from url | |
105 | size_t argpos = file.rfind("?"); | |
106 | if(argpos != std::string::npos) { | |
107 | file = file.substr(0,argpos); | |
108 | } | |
109 | ||
110 | if(file.size()==0) file = "/"; | |
111 | ||
112 | //name index pages | |
113 | if(file[file.size()-1] == '/') { | |
114 | file += "index.html"; | |
115 | } | |
116 | ||
117 | std::string action = "A"; | |
118 | commit.addFile(file, action); | |
119 | ||
120 | std::string refer; | |
121 | std::string agent; | |
122 | ||
123 | if(matches.size() > 5) { | |
124 | std::string agentstr = matches[5]; | |
125 | matches.clear(); | |
126 | apache_entry_agent.match(agentstr, &matches); | |
127 | ||
128 | if(matches.size()>1) { | |
129 | refer = matches[0]; | |
130 | agent = matches[1]; | |
131 | } | |
132 | } | |
133 | ||
134 | return true; | |
135 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GOURCE_APACHE_H | |
18 | #define GOURCE_APACHE_H | |
19 | ||
20 | #include <string> | |
21 | #include <string.h> | |
22 | ||
23 | #include <vector> | |
24 | #include <time.h> | |
25 | ||
26 | #include "commitlog.h" | |
27 | ||
28 | class ApacheCombinedLog : public RCommitLog { | |
29 | protected: | |
30 | bool parseCommit(RCommit& commit); | |
31 | BaseLog* generateLog(const std::string& dir); | |
32 | public: | |
33 | ApacheCombinedLog(const std::string& logfile); | |
34 | }; | |
35 | ||
36 | #endif |
0 | /* | |
1 | Copyright (C) 2010 John Arbash Meinel <john@arbash-meinel.com> | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "bzr.h" | |
18 | ||
19 | Regex bzr_commit_regex("^ *([\\d.]+) (.+)\t(\\d{4})-(\\d+)-(\\d+)(?: \\{[^}]+})?(?: \\[merge\\])?$"); | |
20 | Regex bzr_file_regex("^ *([AMDR]) (.*[^/])$"); | |
21 | ||
22 | // parse Bazaar log entries (using the gource.style template) | |
23 | ||
24 | std::string gGourceBzrLogCommand() { | |
25 | return std::string("bzr log --verbose -r 1..-1 --short -n0 --forward"); | |
26 | } | |
27 | ||
28 | BazaarLog::BazaarLog(const std::string& logfile) : RCommitLog(logfile) { | |
29 | ||
30 | log_command = gGourceBzrLogCommand(); | |
31 | ||
32 | //can generate log from directory | |
33 | if(!logf && is_dir) { | |
34 | logf = generateLog(logfile); | |
35 | ||
36 | if(logf) { | |
37 | success = true; | |
38 | seekable = true; | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | BaseLog* BazaarLog::generateLog(const std::string& dir) { | |
44 | ||
45 | //does directory have a .bzr ? | |
46 | std::string bzrdir = dir + std::string("/.bzr"); | |
47 | struct stat dirinfo; | |
48 | int stat_rc = stat(bzrdir.c_str(), &dirinfo); | |
49 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
50 | return 0; | |
51 | } | |
52 | ||
53 | std::string command = getLogCommand(); | |
54 | ||
55 | // do we have this client installed | |
56 | requireExecutable("bzr"); | |
57 | ||
58 | createTempLog(); | |
59 | ||
60 | if(temp_file.size()==0) return 0; | |
61 | ||
62 | char cmd_buff[2048]; | |
63 | sprintf(cmd_buff, "%s %s > %s", command.c_str(), dir.c_str(), temp_file.c_str()); | |
64 | ||
65 | int command_rc = systemCommand(cmd_buff); | |
66 | ||
67 | if(command_rc != 0) { | |
68 | return 0; | |
69 | } | |
70 | ||
71 | BaseLog* seeklog = new SeekLog(temp_file); | |
72 | ||
73 | return seeklog; | |
74 | } | |
75 | ||
76 | bool BazaarLog::parseCommit(RCommit& commit) { | |
77 | ||
78 | std::string line; | |
79 | std::vector<std::string> entries; | |
80 | int year, month, day; | |
81 | ||
82 | if(!logf->getNextLine(line)) return false; | |
83 | ||
84 | debugLog("read %s\n", line.c_str()); | |
85 | if (!bzr_commit_regex.match(line, &entries)) { | |
86 | debugLog("regex failed\n"); | |
87 | return false; | |
88 | } | |
89 | commit.username = entries[1]; | |
90 | ||
91 | year = atoi(entries[2].c_str()); | |
92 | month = atoi(entries[3].c_str()); | |
93 | day = atoi(entries[4].c_str()); | |
94 | ||
95 | struct tm time_str; | |
96 | ||
97 | time_str.tm_year = year - 1900; | |
98 | time_str.tm_mon = month - 1; | |
99 | time_str.tm_mday = day; | |
100 | time_str.tm_hour = 0; | |
101 | time_str.tm_min = 0; | |
102 | time_str.tm_sec = 0; | |
103 | time_str.tm_isdst = -1; | |
104 | ||
105 | commit.timestamp = mktime(&time_str); | |
106 | ||
107 | while(logf->getNextLine(line) && line.size()) { | |
108 | if (!bzr_file_regex.match(line, &entries)) continue; | |
109 | commit.addFile(entries[1], entries[0]); | |
110 | } | |
111 | ||
112 | return true; | |
113 | } |
0 | /* | |
1 | Copyright (C) 2010 John Arbash Meinel <john@arbash-meinel.com> | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef BAZAARLOG_H | |
18 | #define BAZAARLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | std::string gGourceBzrLogCommand(); | |
23 | ||
24 | class BazaarLog : public RCommitLog { | |
25 | protected: | |
26 | bool parseCommit(RCommit& commit); | |
27 | BaseLog* generateLog(const std::string& dir); | |
28 | public: | |
29 | BazaarLog(const std::string& logfile); | |
30 | }; | |
31 | ||
32 | #endif | |
33 |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "commitlog.h" | |
18 | #include "../gource_settings.h" | |
19 | ||
20 | std::string munge_utf8(const std::string& str) { | |
21 | ||
22 | std::string munged; | |
23 | try { | |
24 | utf8::replace_invalid(str.begin(), str.end(), back_inserter(munged), '?'); | |
25 | } | |
26 | catch(...) { | |
27 | munged = "???"; | |
28 | } | |
29 | ||
30 | return munged; | |
31 | } | |
32 | ||
33 | //RCommitLog | |
34 | ||
35 | RCommitLog::RCommitLog(const std::string& logfile, int firstChar) { | |
36 | ||
37 | logf = 0; | |
38 | seekable = false; | |
39 | success = false; | |
40 | is_dir = false; | |
41 | buffered = false; | |
42 | ||
43 | if(logfile == "-") { | |
44 | ||
45 | //check first char | |
46 | if(checkFirstChar(firstChar, std::cin)) { | |
47 | logf = new StreamLog(); | |
48 | is_dir = false; | |
49 | seekable = false; | |
50 | success = true; | |
51 | } | |
52 | ||
53 | return; | |
54 | } | |
55 | ||
56 | struct stat fileinfo; | |
57 | int rc = stat(logfile.c_str(), &fileinfo); | |
58 | ||
59 | if(rc==0) { | |
60 | is_dir = (fileinfo.st_mode & S_IFDIR) ? true : false; | |
61 | ||
62 | if(!is_dir) { | |
63 | ||
64 | //check first char | |
65 | std::ifstream testf(logfile.c_str()); | |
66 | ||
67 | bool firstOK = checkFirstChar(firstChar, testf); | |
68 | ||
69 | testf.close(); | |
70 | ||
71 | if(firstOK) { | |
72 | logf = new SeekLog(logfile); | |
73 | seekable = true; | |
74 | success = true; | |
75 | } | |
76 | } | |
77 | } | |
78 | } | |
79 | ||
80 | RCommitLog::~RCommitLog() { | |
81 | if(logf!=0) delete logf; | |
82 | ||
83 | if(!temp_file.empty()) { | |
84 | remove(temp_file.c_str()); | |
85 | } | |
86 | } | |
87 | ||
88 | int RCommitLog::systemCommand(const std::string& command) { | |
89 | #ifdef _WIN32 | |
90 | SDLAppCreateWindowsConsole(); | |
91 | #endif | |
92 | return system(command.c_str()); | |
93 | } | |
94 | ||
95 | // TODO: implement check for 'nix OSs | |
96 | void RCommitLog::requireExecutable(const std::string& exename) { | |
97 | ||
98 | #ifdef _WIN32 | |
99 | TCHAR exePath[MAX_PATH]; | |
100 | DWORD result = SearchPath(0, exename.c_str(), ".exe", MAX_PATH, exePath, 0); | |
101 | ||
102 | if(result) return; | |
103 | ||
104 | throw SDLAppException("unable to find %s.exe", exename.c_str()); | |
105 | #endif | |
106 | } | |
107 | ||
108 | //check firstChar of stream is as expected. if no firstChar defined just returns true. | |
109 | bool RCommitLog::checkFirstChar(int firstChar, std::istream& stream) { | |
110 | ||
111 | //cant check this | |
112 | if(firstChar == -1) return true; | |
113 | ||
114 | int c = stream.peek(); | |
115 | ||
116 | if(firstChar == c) return true; | |
117 | ||
118 | return false; | |
119 | } | |
120 | ||
121 | bool RCommitLog::checkFormat() { | |
122 | ||
123 | if(!success) return false; | |
124 | ||
125 | //read a commit to see if the log is in the correct format | |
126 | if(nextCommit(lastCommit, false)) { | |
127 | ||
128 | if(seekable) { | |
129 | //if the log is seekable, go back to the start | |
130 | ((SeekLog*)logf)->seekTo(0.0); | |
131 | } else { | |
132 | //otherwise set the buffered flag as we have bufferd one commit | |
133 | buffered = true; | |
134 | } | |
135 | ||
136 | return true; | |
137 | } | |
138 | ||
139 | return false; | |
140 | } | |
141 | ||
142 | std::string RCommitLog::getLogCommand() { | |
143 | return log_command; | |
144 | } | |
145 | ||
146 | bool RCommitLog::isSeekable() { | |
147 | return seekable; | |
148 | } | |
149 | ||
150 | bool RCommitLog::getCommitAt(float percent, RCommit& commit) { | |
151 | if(!seekable) return false; | |
152 | ||
153 | SeekLog* seeklog = ((SeekLog*)logf); | |
154 | ||
155 | //save settings | |
156 | long currpointer = seeklog->getPointer(); | |
157 | std::string currlastline = lastline; | |
158 | ||
159 | seekTo(percent); | |
160 | bool success = findNextCommit(commit,500); | |
161 | ||
162 | //restore settings | |
163 | seeklog->setPointer(currpointer); | |
164 | lastline = currlastline; | |
165 | ||
166 | return success; | |
167 | } | |
168 | ||
169 | bool RCommitLog::getNextLine(std::string& line) { | |
170 | if(!lastline.empty()) { | |
171 | line = lastline; | |
172 | lastline = std::string(""); | |
173 | return true; | |
174 | } | |
175 | ||
176 | return logf->getNextLine(line); | |
177 | } | |
178 | ||
179 | ||
180 | void RCommitLog::seekTo(float percent) { | |
181 | if(!seekable) return; | |
182 | ||
183 | lastline = ""; | |
184 | ||
185 | ((SeekLog*)logf)->seekTo(percent); | |
186 | } | |
187 | ||
188 | float RCommitLog::getPercent() { | |
189 | if(seekable) return ((SeekLog*)logf)->getPercent(); | |
190 | ||
191 | return 0.0; | |
192 | } | |
193 | ||
194 | bool RCommitLog::findNextCommit(RCommit& commit, int attempts) { | |
195 | ||
196 | for(int i=0;i<attempts;i++) { | |
197 | RCommit c; | |
198 | ||
199 | if(nextCommit(c)) { | |
200 | commit = c; | |
201 | return true; | |
202 | } | |
203 | } | |
204 | ||
205 | return false; | |
206 | } | |
207 | ||
208 | bool RCommitLog::nextCommit(RCommit& commit, bool validate) { | |
209 | ||
210 | if(buffered) { | |
211 | commit = lastCommit; | |
212 | buffered = false; | |
213 | return true; | |
214 | } | |
215 | ||
216 | bool success = parseCommit(commit); | |
217 | ||
218 | if(!success) return false; | |
219 | ||
220 | commit.postprocess(); | |
221 | ||
222 | if(validate) return commit.isValid(); | |
223 | ||
224 | return true; | |
225 | } | |
226 | ||
227 | bool RCommitLog::isFinished() { | |
228 | if(seekable && logf->isFinished()) return true; | |
229 | ||
230 | return false; | |
231 | } | |
232 | ||
233 | //create temp file | |
234 | void RCommitLog::createTempLog() { | |
235 | ||
236 | std::string tempdir; | |
237 | ||
238 | #ifdef _WIN32 | |
239 | DWORD tmplen = GetTempPath(0, ""); | |
240 | ||
241 | if(tmplen == 0) return; | |
242 | ||
243 | std::vector<TCHAR> temp(tmplen+1); | |
244 | ||
245 | tmplen = GetTempPath(static_cast<DWORD>(temp.size()), &temp[0]); | |
246 | ||
247 | if(tmplen == 0 || tmplen >= temp.size()) return; | |
248 | ||
249 | tempdir = std::string(temp.begin(), temp.begin() + static_cast<std::size_t>(tmplen)); | |
250 | tempdir += "\\"; | |
251 | #else | |
252 | tempdir = "/tmp/"; | |
253 | #endif | |
254 | ||
255 | char tmplate[1024]; | |
256 | snprintf(tmplate, 1024, "%sgource-XXXXXX", tempdir.c_str()); | |
257 | ||
258 | #ifdef _WIN32 | |
259 | if(mktemp(tmplate) < 0) return; | |
260 | #else | |
261 | if(mkstemp(tmplate) < 0) return; | |
262 | #endif | |
263 | ||
264 | temp_file = std::string(tmplate); | |
265 | } | |
266 | ||
267 | // RCommitFile | |
268 | ||
269 | RCommitFile::RCommitFile(const std::string& filename, const std::string& action, vec3 colour) { | |
270 | ||
271 | this->filename = munge_utf8(filename); | |
272 | ||
273 | //prepend a root slash | |
274 | if(this->filename[0] != '/') { | |
275 | this->filename.insert(0, 1, '/'); | |
276 | } | |
277 | ||
278 | this->action = action; | |
279 | this->colour = colour; | |
280 | } | |
281 | ||
282 | RCommit::RCommit() { | |
283 | timestamp = 0; | |
284 | } | |
285 | ||
286 | vec3 RCommit::fileColour(const std::string& filename) { | |
287 | ||
288 | size_t slash = filename.rfind('/'); | |
289 | size_t dot = filename.rfind('.'); | |
290 | ||
291 | if(dot != std::string::npos && dot+1<filename.size() && (slash == std::string::npos || slash < dot)) { | |
292 | std::string file_ext = filename.substr(dot+1); | |
293 | ||
294 | return colourHash(file_ext); | |
295 | } else { | |
296 | return vec3(1.0, 1.0, 1.0); | |
297 | } | |
298 | } | |
299 | ||
300 | void RCommit::addFile(const std::string& filename, const std::string& action) { | |
301 | addFile(filename, action, fileColour(filename)); | |
302 | } | |
303 | ||
304 | void RCommit::addFile(const std::string& filename, const std::string& action, const vec3& colour) { | |
305 | //check filename against filters | |
306 | if(!gGourceSettings.file_filters.empty()) { | |
307 | ||
308 | for(std::vector<Regex*>::iterator ri = gGourceSettings.file_filters.begin(); ri != gGourceSettings.file_filters.end(); ri++) { | |
309 | Regex* r = *ri; | |
310 | ||
311 | if(r->match(filename)) { | |
312 | return; | |
313 | } | |
314 | } | |
315 | } | |
316 | ||
317 | files.push_back(RCommitFile(filename, action, colour)); | |
318 | } | |
319 | ||
320 | void RCommit::postprocess() { | |
321 | username = munge_utf8(username); | |
322 | } | |
323 | ||
324 | bool RCommit::isValid() { | |
325 | ||
326 | //check user against filters, if found, discard commit | |
327 | if(!gGourceSettings.user_filters.empty()) { | |
328 | for(std::vector<Regex*>::iterator ri = gGourceSettings.user_filters.begin(); ri != gGourceSettings.user_filters.end(); ri++) { | |
329 | Regex* r = *ri; | |
330 | ||
331 | if(r->match(username)) { | |
332 | return false; | |
333 | } | |
334 | } | |
335 | } | |
336 | ||
337 | return !files.empty(); | |
338 | } | |
339 | ||
340 | void RCommit::debug() { | |
341 | debugLog("files:\n"); | |
342 | ||
343 | for(std::list<RCommitFile>::iterator it = files.begin(); it != files.end(); it++) { | |
344 | RCommitFile f = *it; | |
345 | debugLog("%s %s\n", f.action.c_str(), f.filename.c_str()); | |
346 | } | |
347 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef RCOMMIT_LOG_H | |
18 | #define RCOMMIT_LOG_H | |
19 | ||
20 | ||
21 | #include "../core/seeklog.h" | |
22 | #include "../core/display.h" | |
23 | #include "../core/regex.h" | |
24 | #include "../core/stringhash.h" | |
25 | #include "../core/utf8/utf8.h" | |
26 | ||
27 | #include <time.h> | |
28 | #include <string> | |
29 | #include <list> | |
30 | ||
31 | #include "sys/stat.h" | |
32 | ||
33 | class RCommitFile { | |
34 | public: | |
35 | std::string filename; | |
36 | std::string action; | |
37 | vec3 colour; | |
38 | ||
39 | RCommitFile(const std::string& filename, const std::string& action, vec3 colour); | |
40 | }; | |
41 | ||
42 | class RCommit { | |
43 | vec3 fileColour(const std::string& filename); | |
44 | public: | |
45 | time_t timestamp; | |
46 | std::string username; | |
47 | ||
48 | std::list<RCommitFile> files; | |
49 | ||
50 | void postprocess(); | |
51 | bool isValid(); | |
52 | ||
53 | void addFile(const std::string& filename, const std::string& action); | |
54 | void addFile(const std::string& filename, const std::string& action, const vec3& colour); | |
55 | ||
56 | RCommit(); | |
57 | void debug(); | |
58 | virtual bool parse(BaseLog* logf) { return false; }; | |
59 | }; | |
60 | ||
61 | class RCommitLog { | |
62 | protected: | |
63 | BaseLog* logf; | |
64 | ||
65 | std::string temp_file; | |
66 | std::string log_command; | |
67 | ||
68 | std::string lastline; | |
69 | ||
70 | bool is_dir; | |
71 | bool success; | |
72 | bool seekable; | |
73 | ||
74 | RCommit lastCommit; | |
75 | bool buffered; | |
76 | ||
77 | bool checkFirstChar(int firstChar, std::istream& stream); | |
78 | ||
79 | void createTempLog(); | |
80 | ||
81 | bool getNextLine(std::string& line); | |
82 | ||
83 | virtual bool parseCommit(RCommit& commit) { return false; }; | |
84 | public: | |
85 | RCommitLog(const std::string& logfile, int firstChar = -1); | |
86 | ~RCommitLog(); | |
87 | ||
88 | void seekTo(float percent); | |
89 | ||
90 | bool checkFormat(); | |
91 | ||
92 | std::string getLogCommand(); | |
93 | ||
94 | int systemCommand(const std::string& command); | |
95 | void requireExecutable(const std::string& exename); | |
96 | ||
97 | bool getCommitAt(float percent, RCommit& commit); | |
98 | bool findNextCommit(RCommit& commit, int attempts); | |
99 | bool nextCommit(RCommit& commit, bool validate = true); | |
100 | bool isFinished(); | |
101 | bool isSeekable(); | |
102 | float getPercent(); | |
103 | }; | |
104 | ||
105 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "custom.h" | |
18 | ||
19 | Regex custom_regex("^(-?[0-9]+)\\|([^|]*)\\|([ADM]?)\\|([^|]+)(?:\\|#?([A-F0-9]{6}))?"); | |
20 | ||
21 | CustomLog::CustomLog(const std::string& logfile) : RCommitLog(logfile) { | |
22 | } | |
23 | ||
24 | vec3 CustomLog::parseColour(const std::string& cstr) { | |
25 | debugLog("parseColour\n"); | |
26 | vec3 colour; | |
27 | int r,g,b; | |
28 | ||
29 | if(sscanf(cstr.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { | |
30 | ||
31 | colour = vec3( r, g, b ); | |
32 | colour /= 255.0f; | |
33 | ||
34 | debugLog("colour %.2f %.2f %.2f\n", colour.x,colour.y,colour.z); | |
35 | } | |
36 | ||
37 | return colour; | |
38 | } | |
39 | ||
40 | // parse modified cvs format log entries | |
41 | ||
42 | bool CustomLog::parseCommit(RCommit& commit) { | |
43 | ||
44 | while(parseCommitEntry(commit)); | |
45 | ||
46 | return !commit.files.empty(); | |
47 | } | |
48 | ||
49 | bool CustomLog::parseCommitEntry(RCommit& commit) { | |
50 | ||
51 | std::string line; | |
52 | std::vector<std::string> entries; | |
53 | ||
54 | if(!getNextLine(line)) return false; | |
55 | ||
56 | //custom line | |
57 | if(!custom_regex.match(line, &entries)) return false; | |
58 | ||
59 | long timestamp = atol(entries[0].c_str()); | |
60 | ||
61 | std::string username = (entries[1].size()>0) ? entries[1] : "Unknown"; | |
62 | std::string action = (entries[2].size()>0) ? entries[2] : "A"; | |
63 | ||
64 | //if this file is for the same person and timestamp | |
65 | //we add to the commit, else we save the lastline | |
66 | //and return false | |
67 | if(commit.files.empty()) { | |
68 | commit.timestamp = timestamp; | |
69 | commit.username = username; | |
70 | } else { | |
71 | if(commit.timestamp != timestamp || commit.username != username) { | |
72 | lastline = line; | |
73 | return false; | |
74 | } | |
75 | } | |
76 | ||
77 | bool has_colour = false; | |
78 | vec3 colour; | |
79 | ||
80 | if(entries.size()>=5 && entries[4].size()>0) { | |
81 | has_colour = true; | |
82 | colour = parseColour(entries[4]); | |
83 | } | |
84 | ||
85 | if(has_colour) { | |
86 | commit.addFile(entries[3], action, colour); | |
87 | } else { | |
88 | commit.addFile(entries[3], action); | |
89 | } | |
90 | ||
91 | return true; | |
92 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CUSTOMLOG_H | |
18 | #define CUSTOMLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | class CustomLog : public RCommitLog { | |
23 | protected: | |
24 | bool parseCommit(RCommit& commit); | |
25 | bool parseCommitEntry(RCommit& commit); | |
26 | vec3 parseColour(const std::string& cstr); | |
27 | public: | |
28 | CustomLog(const std::string& logfile); | |
29 | }; | |
30 | ||
31 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "cvs-exp.h" | |
18 | ||
19 | Regex cvsexp_commitno_regex("^([0-9]{6}):"); | |
20 | Regex cvsexp_branch_regex("^BRANCH \\[(.+)\\]$"); | |
21 | Regex cvsexp_date_regex("^\\(date: ([0-9]{4})[-/]([0-9]{2})[-/]([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})(?: [+-][0-9]{4})?;(.+)$"); | |
22 | Regex cvsexp_detail_regex("author: ([^;]+); state: ([^;]+);(.+)$"); | |
23 | //Regex cvsexp_lines_regex("lines: \\+([0-9]+) -([0-9]+)"); | |
24 | Regex cvsexp_entry_regex("\\| (.+),v:([0-9.]+),?"); | |
25 | Regex cvsexp_end_regex("^(=+)$"); | |
26 | ||
27 | std::string gGourceCvsExpLogCommand = "cvs-exp.pl -notree"; | |
28 | ||
29 | CVSEXPCommitLog::CVSEXPCommitLog(const std::string& logfile) : RCommitLog(logfile) { | |
30 | } | |
31 | ||
32 | // parse modified cvs format log entries | |
33 | ||
34 | bool CVSEXPCommitLog::parseCommit(RCommit& commit) { | |
35 | ||
36 | std::string line; | |
37 | std::vector<std::string> entries; | |
38 | ||
39 | if(!logf->getNextLine(line)) return false; | |
40 | ||
41 | //skip empty line if there is one | |
42 | if(line.size() == 0) { | |
43 | if(!logf->getNextLine(line)) return false; | |
44 | } | |
45 | ||
46 | //read commit no | |
47 | if(!cvsexp_commitno_regex.match(line, &entries)) return false; | |
48 | ||
49 | //int commitno = atoi(entries[0].c_str()); | |
50 | //debugLog("commitno matched\n"); | |
51 | ||
52 | if(!logf->getNextLine(line)) return false; | |
53 | ||
54 | //should be a branch | |
55 | if(cvsexp_branch_regex.match(line, &entries)) { | |
56 | ||
57 | //read next blank line | |
58 | if(!logf->getNextLine(line)) return false; | |
59 | if(line.size()) return false; | |
60 | if(!logf->getNextLine(line)) return false; | |
61 | } | |
62 | ||
63 | //parse date | |
64 | if(!cvsexp_date_regex.match(line, &entries)) return false; | |
65 | ||
66 | //debugLog("date matched\n"); | |
67 | ||
68 | struct tm time_str; | |
69 | ||
70 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
71 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
72 | time_str.tm_mday = atoi(entries[2].c_str()); | |
73 | time_str.tm_hour = atoi(entries[3].c_str()); | |
74 | time_str.tm_min = atoi(entries[4].c_str()); | |
75 | time_str.tm_sec = atoi(entries[5].c_str()); | |
76 | time_str.tm_isdst = -1; | |
77 | ||
78 | commit.timestamp = mktime(&time_str); | |
79 | ||
80 | //parse author,state | |
81 | std::string rest = entries[6]; | |
82 | if(!cvsexp_detail_regex.match(rest, &entries)) return false; | |
83 | ||
84 | //debugLog("author/state matched\n"); | |
85 | ||
86 | commit.username = entries[0]; | |
87 | ||
88 | std::string commit_state = entries[1]; | |
89 | ||
90 | /* not used | |
91 | //if rest is not ')' parse lines | |
92 | rest = entries[2]; | |
93 | ||
94 | // need to parse lines | |
95 | if(rest.size() > 2) { | |
96 | if(!cvsexp_lines_regex.match(rest, &entries)) return false; | |
97 | } | |
98 | */ | |
99 | ||
100 | if(!logf->getNextLine(line)) return false; | |
101 | ||
102 | std::string commit_action = (commit_state == "dead") ? "D" : "M"; | |
103 | ||
104 | while(cvsexp_entry_regex.match(line, &entries)) { | |
105 | ||
106 | //ignore files in Attic - previously deleted file | |
107 | if(entries[0].find("/Attic/") == std::string::npos) { | |
108 | commit.addFile(entries[0], commit_action); | |
109 | } | |
110 | ||
111 | if(!logf->getNextLine(line)) return false; | |
112 | } | |
113 | ||
114 | //read blank line | |
115 | if(!logf->getNextLine(line)) return false; | |
116 | ||
117 | //std::string message; | |
118 | ||
119 | //read commit message | |
120 | while(logf->getNextLine(line) && line.size()) { | |
121 | //if(message.size()) message += std::string("\n"); | |
122 | //message += line; | |
123 | } | |
124 | ||
125 | //read until end of commit or eof | |
126 | while(logf->getNextLine(line)) { | |
127 | if(cvsexp_end_regex.match(line,&entries)) { | |
128 | //debugLog("read end of commit %s\n", entries[0].c_str()); | |
129 | break; | |
130 | } | |
131 | } | |
132 | ||
133 | return true; | |
134 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CVSLOG_EXP_H | |
18 | #define CVSLOG_EXP_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | class CVSEXPCommitLog : public RCommitLog { | |
23 | protected: | |
24 | bool parseCommit(RCommit& commit); | |
25 | public: | |
26 | CVSEXPCommitLog(const std::string& logfile); | |
27 | }; | |
28 | ||
29 | extern std::string gGourceCvsExpLogCommand; | |
30 | ||
31 | #endif |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "cvs2cl.h" | |
18 | ||
19 | Regex cvs2cl_xml_tag("^<\\??xml"); | |
20 | Regex cvs2cl_logentry_start("^<entry"); | |
21 | Regex cvs2cl_logentry_end("^</entry>"); | |
22 | Regex cvs2cl_logentry_timestamp("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})Z"); | |
23 | ||
24 | std::string gGourceCVS2CLLogCommand = "cvs2cl --chrono --stdout --xml -g-q"; | |
25 | ||
26 | CVS2CLCommitLog::CVS2CLCommitLog(const std::string& logfile) : RCommitLog(logfile, '<') { | |
27 | } | |
28 | ||
29 | bool CVS2CLCommitLog::parseCommit(RCommit& commit) { | |
30 | ||
31 | //fprintf(stderr,"parsing cvs2cl log\n"); | |
32 | ||
33 | std::string line; | |
34 | ||
35 | if(!getNextLine(line)) return false; | |
36 | ||
37 | //start of log entry | |
38 | if(!cvs2cl_logentry_start.match(line)) { | |
39 | ||
40 | //is this the start of the document | |
41 | if(!cvs2cl_xml_tag.match(line)) return false; | |
42 | ||
43 | //fprintf(stderr,"found xml tag\n"); | |
44 | ||
45 | //if so find the first logentry tag | |
46 | ||
47 | bool found_logentry = false; | |
48 | ||
49 | while(getNextLine(line)) { | |
50 | if(cvs2cl_logentry_start.match(line)) { | |
51 | found_logentry = true; | |
52 | break; | |
53 | } | |
54 | } | |
55 | ||
56 | if(!found_logentry) return false; | |
57 | } | |
58 | ||
59 | //fprintf(stderr,"found logentry\n"); | |
60 | ||
61 | logentry.clear(); | |
62 | ||
63 | logentry.append(line); | |
64 | logentry.append("\n"); | |
65 | ||
66 | //fprintf(stderr,"found opening tag\n"); | |
67 | ||
68 | bool endfound = false; | |
69 | ||
70 | while(getNextLine(line)) { | |
71 | logentry.append(line); | |
72 | logentry.append("\n"); | |
73 | if(cvs2cl_logentry_end.match(line)) { | |
74 | //fprintf(stderr,"found closing tag\n"); | |
75 | endfound=true; | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | //incomplete commit | |
81 | if(!endfound) return false; | |
82 | ||
83 | //fprintf(stderr,"read logentry\n"); | |
84 | ||
85 | TiXmlDocument doc; | |
86 | ||
87 | if(!doc.Parse(logentry.c_str())) return false; | |
88 | ||
89 | //fprintf(stderr,"try to parse logentry: %s\n", logentry.c_str()); | |
90 | ||
91 | TiXmlElement* leE = doc.FirstChildElement( "entry" ); | |
92 | ||
93 | std::vector<std::string> entries; | |
94 | ||
95 | if(!leE) return false; | |
96 | ||
97 | //parse date | |
98 | TiXmlElement* dateE = leE->FirstChildElement( "isoDate" ); | |
99 | ||
100 | if(!dateE) return false; | |
101 | ||
102 | std::string timestamp_str(dateE->GetText()); | |
103 | ||
104 | if(!cvs2cl_logentry_timestamp.match(timestamp_str, &entries)) | |
105 | return false; | |
106 | ||
107 | struct tm time_str; | |
108 | ||
109 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
110 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
111 | time_str.tm_mday = atoi(entries[2].c_str()); | |
112 | time_str.tm_hour = atoi(entries[3].c_str()); | |
113 | time_str.tm_min = atoi(entries[4].c_str()); | |
114 | time_str.tm_sec = atoi(entries[5].c_str()); | |
115 | time_str.tm_isdst = -1; | |
116 | ||
117 | commit.timestamp = mktime(&time_str); | |
118 | ||
119 | //parse author | |
120 | TiXmlElement* authorE = leE->FirstChildElement("author"); | |
121 | ||
122 | if(authorE != 0) { | |
123 | ||
124 | std::string author(authorE->GetText()); | |
125 | ||
126 | if(author.empty()) author = "Unknown"; | |
127 | ||
128 | commit.username = author; | |
129 | } | |
130 | ||
131 | //parse changes | |
132 | ||
133 | for(TiXmlElement* fileE = leE->FirstChildElement("file"); fileE != 0; fileE = fileE->NextSiblingElement()) { | |
134 | ||
135 | TiXmlElement* state = fileE->FirstChildElement("cvsstate"); | |
136 | TiXmlElement* name = fileE->FirstChildElement("name"); | |
137 | ||
138 | //check for state | |
139 | if(name == 0 || state == 0) continue; | |
140 | ||
141 | std::string status = strcmp(state->GetText(), "dead") == 0 ? "D" : "M"; | |
142 | std::string file(name->GetText()); | |
143 | ||
144 | if(file.empty()) continue; | |
145 | ||
146 | commit.addFile(file, status); | |
147 | } | |
148 | ||
149 | //fprintf(stderr,"parsed logentry\n"); | |
150 | ||
151 | //read files | |
152 | ||
153 | return true; | |
154 | } |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef CVS2CL_H | |
18 | #define CVS2CL_H | |
19 | ||
20 | #include "../gource_settings.h" | |
21 | #include "commitlog.h" | |
22 | ||
23 | #include <sstream> | |
24 | ||
25 | #ifdef HAVE_LIBTINYXML | |
26 | #include <tinyxml.h> | |
27 | #else | |
28 | #include "../tinyxml/tinyxml.h" | |
29 | #endif | |
30 | ||
31 | ||
32 | #include <unistd.h> | |
33 | ||
34 | extern std::string gGourceCVS2CLLogCommand; | |
35 | ||
36 | class CVS2CLCommitLog : public RCommitLog { | |
37 | protected: | |
38 | bool parseCommit(RCommit& commit); | |
39 | ||
40 | std::string logentry; | |
41 | public: | |
42 | CVS2CLCommitLog(const std::string& logfile); | |
43 | }; | |
44 | ||
45 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "git.h" | |
18 | ||
19 | // parse git log entries | |
20 | ||
21 | //git-log command notes: | |
22 | // - no single quotes on WIN32 as system call treats them differently | |
23 | // - 'user:' prefix allows us to quickly tell if the log is the wrong format | |
24 | // and try a different format (eg cvs-exp) | |
25 | ||
26 | std::string gGourceGitLogCommand = "git log " | |
27 | "--pretty=format:user:%aN%n%ct " | |
28 | "--reverse --raw --encoding=UTF-8 " | |
29 | "--no-renames"; | |
30 | ||
31 | GitCommitLog::GitCommitLog(const std::string& logfile) : RCommitLog(logfile, 'u') { | |
32 | ||
33 | log_command = gGourceGitLogCommand; | |
34 | ||
35 | if(gGourceSettings.git_branch.size()>0) { | |
36 | log_command += " "; | |
37 | log_command += gGourceSettings.git_branch; | |
38 | } | |
39 | ||
40 | //can generate log from directory | |
41 | if(!logf && is_dir) { | |
42 | logf = generateLog(logfile); | |
43 | ||
44 | if(logf) { | |
45 | success = true; | |
46 | seekable = true; | |
47 | } | |
48 | } | |
49 | } | |
50 | ||
51 | BaseLog* GitCommitLog::generateLog(const std::string& dir) { | |
52 | //get working directory | |
53 | char cwd_buff[1024]; | |
54 | ||
55 | if(getcwd(cwd_buff, 1024) != cwd_buff) { | |
56 | return 0; | |
57 | } | |
58 | ||
59 | //does directory have a .git ? | |
60 | std::string gitdir = dir + std::string("/.git"); | |
61 | struct stat dirinfo; | |
62 | int stat_rc = stat(gitdir.c_str(), &dirinfo); | |
63 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
64 | return 0; | |
65 | } | |
66 | ||
67 | // do we have this client installed | |
68 | requireExecutable("git"); | |
69 | ||
70 | std::string command = getLogCommand(); | |
71 | ||
72 | //create temp file | |
73 | createTempLog(); | |
74 | ||
75 | if(temp_file.size()==0) return 0; | |
76 | ||
77 | if(chdir(dir.c_str()) != 0) { | |
78 | return 0; | |
79 | } | |
80 | ||
81 | char cmd_buff[2048]; | |
82 | sprintf(cmd_buff, "%s > %s", command.c_str(), temp_file.c_str()); | |
83 | ||
84 | int command_rc = systemCommand(cmd_buff); | |
85 | ||
86 | if(command_rc != 0) { | |
87 | chdir(cwd_buff); | |
88 | return 0; | |
89 | } | |
90 | ||
91 | // check for new-enough Git version | |
92 | // if %aN does not appear to be supported try %an | |
93 | std::ifstream in(temp_file.c_str()); | |
94 | char firstBytes[9]; | |
95 | in.read(firstBytes, 8); | |
96 | in.close(); | |
97 | firstBytes[8] = '\0'; | |
98 | if(!strcmp(firstBytes, "user:%aN")) { | |
99 | char *pos = strstr(cmd_buff, "%aN"); | |
100 | pos[2] = 'n'; | |
101 | command_rc = systemCommand(cmd_buff); | |
102 | } | |
103 | ||
104 | //change back to original directoy | |
105 | chdir(cwd_buff); | |
106 | ||
107 | if(command_rc != 0) { | |
108 | return 0; | |
109 | } | |
110 | ||
111 | BaseLog* seeklog = new SeekLog(temp_file); | |
112 | ||
113 | return seeklog; | |
114 | } | |
115 | ||
116 | // parse modified git format log entries | |
117 | ||
118 | bool GitCommitLog::parseCommit(RCommit& commit) { | |
119 | ||
120 | std::string line; | |
121 | ||
122 | commit.username = ""; | |
123 | ||
124 | while(logf->getNextLine(line) && line.size()) { | |
125 | ||
126 | if(line.find("user:") == 0) { | |
127 | ||
128 | //username follows user prefix | |
129 | commit.username = line.substr(5); | |
130 | ||
131 | if(!logf->getNextLine(line)) return false; | |
132 | ||
133 | commit.timestamp = atol(line.c_str()); | |
134 | ||
135 | //this isnt a commit we are parsing, abort | |
136 | if(commit.timestamp == 0) return false; | |
137 | ||
138 | continue; | |
139 | } | |
140 | ||
141 | //should see username before files | |
142 | if(commit.username.empty()) return false; | |
143 | ||
144 | size_t tab = line.find('\t'); | |
145 | ||
146 | //incorrect log format | |
147 | if(tab == std::string::npos || tab == 0 || tab == line.size()-1) continue; | |
148 | ||
149 | std::string status = line.substr(tab - 1, 1); | |
150 | std::string file = line.substr(tab + 1); | |
151 | ||
152 | if(file.empty()) continue; | |
153 | ||
154 | //check for and remove double quotes | |
155 | if(file.find('"') == 0 && file.rfind('"') == file.size()-1) { | |
156 | if(file.size()<=2) continue; | |
157 | ||
158 | file = file.substr(1,file.size()-2); | |
159 | } | |
160 | ||
161 | commit.addFile(file, status); | |
162 | } | |
163 | ||
164 | //check we at least got a username | |
165 | if(commit.username.empty()) return false; | |
166 | ||
167 | return true; | |
168 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GITLOG_H | |
18 | #define GITLOG_H | |
19 | ||
20 | #include "../gource_settings.h" | |
21 | #include "commitlog.h" | |
22 | ||
23 | #include <unistd.h> | |
24 | ||
25 | extern std::string gGourceGitLogCommand; | |
26 | ||
27 | class GitCommitLog : public RCommitLog { | |
28 | protected: | |
29 | bool parseCommit(RCommit& commit); | |
30 | BaseLog* generateLog(const std::string& dir); | |
31 | public: | |
32 | GitCommitLog(const std::string& logfile); | |
33 | }; | |
34 | ||
35 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "gitraw.h" | |
18 | ||
19 | Regex git_raw_commit("^commit ([0-9a-z]+)"); | |
20 | Regex git_raw_tree("^tree ([0-9a-z]+)"); | |
21 | Regex git_raw_parent("^parent ([0-9a-z]+)"); | |
22 | Regex git_raw_author("^author (.+) <([^@>]+)@?([^>]*)> (\\d+) ([-+]\\d+)"); | |
23 | Regex git_raw_committer("^committer (.+) <([^@>]+)@?([^>]*)> (\\d+) ([-+]\\d+)"); | |
24 | Regex git_raw_file("^:[0-9]+ [0-9]+ [0-9a-z]+\\.* ([0-9a-z]+)\\.* ([A-Z])[ \\t]+(.+)"); | |
25 | ||
26 | // parse git log entries | |
27 | ||
28 | std::string gGourceGitRawLogCommand = "git log --reverse --raw --pretty=raw"; | |
29 | ||
30 | GitRawCommitLog::GitRawCommitLog(const std::string& logfile) : RCommitLog(logfile, 'c') { | |
31 | ||
32 | log_command = gGourceGitRawLogCommand; | |
33 | } | |
34 | ||
35 | // parse modified cvs format log entries | |
36 | ||
37 | bool GitRawCommitLog::parseCommit(RCommit& commit) { | |
38 | ||
39 | std::string line; | |
40 | std::vector<std::string> entries; | |
41 | ||
42 | //read commit ref/ branch | |
43 | if(!logf->getNextLine(line)) return false; | |
44 | ||
45 | //commit | |
46 | if(!git_raw_commit.match(line, &entries)) return false; | |
47 | ||
48 | if(!logf->getNextLine(line)) return false; | |
49 | ||
50 | //tree | |
51 | if(!git_raw_tree.match(line, &entries)) return false; | |
52 | ||
53 | if(!logf->getNextLine(line)) return false; | |
54 | ||
55 | //0 or more parents | |
56 | while(git_raw_parent.match(line, &entries)) { | |
57 | if(!logf->getNextLine(line)) return false; | |
58 | } | |
59 | ||
60 | //author - used for display name | |
61 | if(!git_raw_author.match(line, &entries)) return false; | |
62 | ||
63 | commit.username = entries[0]; | |
64 | ||
65 | if(!logf->getNextLine(line)) return false; | |
66 | ||
67 | //committer - used for time (most likely cronological) | |
68 | if(!git_raw_committer.match(line, &entries)) return false; | |
69 | ||
70 | commit.timestamp = atol(entries[3].c_str()); | |
71 | ||
72 | //blank line before message | |
73 | if(!logf->getNextLine(line)) return false; | |
74 | ||
75 | //read commit message | |
76 | while(logf->getNextLine(line) && line.size()) { | |
77 | } | |
78 | ||
79 | //read files | |
80 | while(logf->getNextLine(line) && line.size()) { | |
81 | //debugLog("file??? %s\n", line.c_str()); | |
82 | ||
83 | if(git_raw_file.match(line, &entries)) { | |
84 | commit.addFile(entries[2], entries[1]); | |
85 | } | |
86 | } | |
87 | ||
88 | // commit.debug(); | |
89 | ||
90 | return true; | |
91 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GITLOG_RAW_H | |
18 | #define GITLOG_RAW_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | #include <unistd.h> | |
23 | ||
24 | extern std::string gGourceGitRawLogCommand; | |
25 | ||
26 | class GitRawCommitLog : public RCommitLog { | |
27 | protected: | |
28 | bool parseCommit(RCommit& commit); | |
29 | public: | |
30 | GitRawCommitLog(const std::string& logfile); | |
31 | }; | |
32 | ||
33 | #endif | |
34 |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "hg.h" | |
18 | ||
19 | Regex hg_regex("^([0-9]+) -?[0-9]+\\|([^|]+)\\|([ADM]?)\\|(.+)$"); | |
20 | ||
21 | // parse Mercurial log entries (using the gource.style template) | |
22 | ||
23 | std::string gGourceMercurialCommand() { | |
24 | ||
25 | std::string gource_style_path = gSDLAppResourceDir + std::string("gource.style"); | |
26 | ||
27 | return std::string("hg log -r 0:tip --style \"") + gource_style_path + std::string("\""); | |
28 | } | |
29 | ||
30 | MercurialLog::MercurialLog(const std::string& logfile) : RCommitLog(logfile) { | |
31 | ||
32 | log_command = gGourceMercurialCommand(); | |
33 | ||
34 | //can generate log from directory | |
35 | if(!logf && is_dir) { | |
36 | logf = generateLog(logfile); | |
37 | ||
38 | if(logf) { | |
39 | success = true; | |
40 | seekable = true; | |
41 | } | |
42 | } | |
43 | } | |
44 | ||
45 | BaseLog* MercurialLog::generateLog(const std::string& dir) { | |
46 | ||
47 | //does directory have a .hg ? | |
48 | std::string hgdir = dir + std::string("/.hg"); | |
49 | struct stat dirinfo; | |
50 | int stat_rc = stat(hgdir.c_str(), &dirinfo); | |
51 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
52 | return 0; | |
53 | } | |
54 | ||
55 | // do we have this client installed | |
56 | requireExecutable("hg"); | |
57 | ||
58 | std::string command = getLogCommand(); | |
59 | ||
60 | createTempLog(); | |
61 | ||
62 | if(temp_file.size()==0) return 0; | |
63 | ||
64 | char cmd_buff[2048]; | |
65 | sprintf(cmd_buff, "%s -R \"%s\" > %s", command.c_str(), dir.c_str(), temp_file.c_str()); | |
66 | ||
67 | int command_rc = systemCommand(cmd_buff); | |
68 | ||
69 | if(command_rc != 0) { | |
70 | return 0; | |
71 | } | |
72 | ||
73 | BaseLog* seeklog = new SeekLog(temp_file); | |
74 | ||
75 | return seeklog; | |
76 | } | |
77 | ||
78 | ||
79 | bool MercurialLog::parseCommit(RCommit& commit) { | |
80 | ||
81 | while(parseCommitEntry(commit)); | |
82 | ||
83 | return !commit.files.empty(); | |
84 | } | |
85 | ||
86 | bool MercurialLog::parseCommitEntry(RCommit& commit) { | |
87 | ||
88 | std::string line; | |
89 | std::vector<std::string> entries; | |
90 | ||
91 | if(!logf->getNextLine(line)) return false; | |
92 | ||
93 | //custom line | |
94 | if(!hg_regex.match(line, &entries)) return false; | |
95 | ||
96 | time_t timestamp = atol(entries[0].c_str()); | |
97 | std::string username = entries[1]; | |
98 | ||
99 | //if this file is for the same person and timestamp | |
100 | //we add to the commit, else we save the lastline | |
101 | //and return false | |
102 | if(commit.files.empty()) { | |
103 | commit.timestamp = timestamp; | |
104 | commit.username = username; | |
105 | } else { | |
106 | if(commit.timestamp != timestamp || commit.username != username) { | |
107 | lastline = line; | |
108 | return false; | |
109 | } | |
110 | } | |
111 | ||
112 | std::string action = "A"; | |
113 | ||
114 | if(!entries[2].empty()) { | |
115 | action = entries[2]; | |
116 | } | |
117 | ||
118 | commit.addFile(entries[3], action); | |
119 | ||
120 | //commit.debug(); | |
121 | ||
122 | return true; | |
123 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef MERCURIALLOG_H | |
18 | #define MERCURIALLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | std::string gGourceMercurialCommand(); | |
23 | ||
24 | class MercurialLog : public RCommitLog { | |
25 | protected: | |
26 | bool parseCommit(RCommit& commit); | |
27 | bool parseCommitEntry(RCommit& commit); | |
28 | BaseLog* generateLog(const std::string& dir); | |
29 | public: | |
30 | MercurialLog(const std::string& logfile); | |
31 | }; | |
32 | ||
33 | #endif⏎ |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "svn.h" | |
18 | ||
19 | Regex svn_xml_tag("^<\\??xml"); | |
20 | Regex svn_logentry_start("^<logentry"); | |
21 | Regex svn_logentry_end("^</logentry>"); | |
22 | Regex svn_logentry_timestamp("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})"); | |
23 | ||
24 | std::string gGourceSVNLogCommand = "svn log -r 1:HEAD --xml --verbose --quiet"; | |
25 | ||
26 | SVNCommitLog::SVNCommitLog(const std::string& logfile) : RCommitLog(logfile, '<') { | |
27 | ||
28 | log_command = gGourceSVNLogCommand; | |
29 | ||
30 | //can generate log from directory | |
31 | if(!logf && is_dir) { | |
32 | logf = generateLog(logfile); | |
33 | ||
34 | if(logf) { | |
35 | success = true; | |
36 | seekable = true; | |
37 | } | |
38 | } | |
39 | ||
40 | logentry.reserve(1024); | |
41 | } | |
42 | ||
43 | ||
44 | BaseLog* SVNCommitLog::generateLog(const std::string& dir) { | |
45 | //get working directory | |
46 | char cwd_buff[1024]; | |
47 | ||
48 | if(getcwd(cwd_buff, 1024) != cwd_buff) { | |
49 | return 0; | |
50 | } | |
51 | ||
52 | //does directory have a .svn ? | |
53 | std::string gitdir = dir + std::string("/.svn"); | |
54 | struct stat dirinfo; | |
55 | int stat_rc = stat(gitdir.c_str(), &dirinfo); | |
56 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
57 | return 0; | |
58 | } | |
59 | ||
60 | // do we have this client installed | |
61 | requireExecutable("svn"); | |
62 | ||
63 | std::string command = getLogCommand(); | |
64 | ||
65 | //create temp file | |
66 | createTempLog(); | |
67 | ||
68 | if(temp_file.size()==0) return 0; | |
69 | ||
70 | if(chdir(dir.c_str()) != 0) { | |
71 | return 0; | |
72 | } | |
73 | ||
74 | char cmd_buff[2048]; | |
75 | sprintf(cmd_buff, "%s > %s", command.c_str(), temp_file.c_str()); | |
76 | ||
77 | int command_rc = systemCommand(cmd_buff); | |
78 | ||
79 | chdir(cwd_buff); | |
80 | ||
81 | if(command_rc != 0) { | |
82 | return 0; | |
83 | } | |
84 | ||
85 | BaseLog* seeklog = new SeekLog(temp_file); | |
86 | ||
87 | return seeklog; | |
88 | } | |
89 | ||
90 | #ifndef HAVE_TIMEGM | |
91 | ||
92 | std::string system_tz; | |
93 | bool system_tz_init = false; | |
94 | ||
95 | time_t __timegm_hack(struct tm* tm) { | |
96 | ||
97 | if(!system_tz_init) { | |
98 | char* current_tz_env = getenv("TZ"); | |
99 | ||
100 | if(current_tz_env != 0) { | |
101 | system_tz = std::string("TZ=") + current_tz_env; | |
102 | } | |
103 | ||
104 | system_tz_init = true; | |
105 | } | |
106 | ||
107 | putenv((char*)"TZ=UTC"); | |
108 | tzset(); | |
109 | ||
110 | time_t timestamp = mktime(tm); | |
111 | ||
112 | if(!system_tz.empty()) { | |
113 | putenv((char*)system_tz.c_str()); | |
114 | } else { | |
115 | #ifdef HAVE_UNSETENV | |
116 | unsetenv("TZ"); | |
117 | #else | |
118 | putenv((char*)"TZ="); | |
119 | #endif | |
120 | } | |
121 | tzset(); | |
122 | ||
123 | return timestamp; | |
124 | } | |
125 | #endif | |
126 | ||
127 | bool SVNCommitLog::parseCommit(RCommit& commit) { | |
128 | ||
129 | //fprintf(stderr,"parsing svn log\n"); | |
130 | ||
131 | std::string line; | |
132 | ||
133 | if(!getNextLine(line)) return false; | |
134 | ||
135 | //start of log entry | |
136 | if(!svn_logentry_start.match(line)) { | |
137 | ||
138 | //is this the start of the document | |
139 | if(!svn_xml_tag.match(line)) return false; | |
140 | ||
141 | //fprintf(stderr,"found xml tag\n"); | |
142 | ||
143 | //if so find the first logentry tag | |
144 | ||
145 | bool found_logentry = false; | |
146 | ||
147 | while(getNextLine(line)) { | |
148 | if(svn_logentry_start.match(line)) { | |
149 | found_logentry = true; | |
150 | break; | |
151 | } | |
152 | } | |
153 | ||
154 | if(!found_logentry) return false; | |
155 | } | |
156 | ||
157 | //fprintf(stderr,"found logentry\n"); | |
158 | ||
159 | logentry.clear(); | |
160 | ||
161 | logentry.append(line); | |
162 | logentry.append("\n"); | |
163 | ||
164 | //fprintf(stderr,"found opening tag\n"); | |
165 | ||
166 | bool endfound = false; | |
167 | ||
168 | while(getNextLine(line)) { | |
169 | logentry.append(line); | |
170 | logentry.append("\n"); | |
171 | if(svn_logentry_end.match(line)) { | |
172 | //fprintf(stderr,"found closing tag\n"); | |
173 | endfound=true; | |
174 | break; | |
175 | } | |
176 | } | |
177 | ||
178 | //incomplete commit | |
179 | if(!endfound) return false; | |
180 | ||
181 | //fprintf(stderr,"read logentry\n"); | |
182 | ||
183 | TiXmlDocument doc; | |
184 | ||
185 | if(!doc.Parse(logentry.c_str())) return false; | |
186 | ||
187 | //fprintf(stderr,"try to parse logentry: %s\n", logentry.c_str()); | |
188 | ||
189 | TiXmlElement* leE = doc.FirstChildElement( "logentry" ); | |
190 | ||
191 | std::vector<std::string> entries; | |
192 | ||
193 | if(!leE) return false; | |
194 | ||
195 | //parse date | |
196 | TiXmlElement* dateE = leE->FirstChildElement( "date" ); | |
197 | ||
198 | if(!dateE) return false; | |
199 | ||
200 | std::string timestamp_str(dateE->GetText()); | |
201 | ||
202 | if(!svn_logentry_timestamp.match(timestamp_str, &entries)) | |
203 | return false; | |
204 | ||
205 | struct tm time_str; | |
206 | ||
207 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
208 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
209 | time_str.tm_mday = atoi(entries[2].c_str()); | |
210 | time_str.tm_hour = atoi(entries[3].c_str()); | |
211 | time_str.tm_min = atoi(entries[4].c_str()); | |
212 | time_str.tm_sec = atoi(entries[5].c_str()); | |
213 | time_str.tm_isdst = -1; | |
214 | ||
215 | #ifdef HAVE_TIMEGM | |
216 | commit.timestamp = timegm(&time_str); | |
217 | #else | |
218 | commit.timestamp = __timegm_hack(&time_str); | |
219 | #endif | |
220 | ||
221 | //parse author | |
222 | TiXmlElement* authorE = leE->FirstChildElement("author"); | |
223 | ||
224 | if(authorE != 0) { | |
225 | ||
226 | std::string author(authorE->GetText()); | |
227 | ||
228 | if(author.empty()) author = "Unknown"; | |
229 | ||
230 | commit.username = author; | |
231 | } | |
232 | ||
233 | TiXmlElement* pathsE = leE->FirstChildElement( "paths" ); | |
234 | ||
235 | //log entries sometimes dont have any paths | |
236 | if(!pathsE) return true; | |
237 | ||
238 | //parse changes | |
239 | ||
240 | for(TiXmlElement* pathE = pathsE->FirstChildElement("path"); pathE != 0; pathE = pathE->NextSiblingElement()) { | |
241 | //parse path | |
242 | ||
243 | const char* kind = pathE->Attribute("kind"); | |
244 | const char* action = pathE->Attribute("action"); | |
245 | ||
246 | //check for action | |
247 | if(action == 0) continue; | |
248 | ||
249 | bool is_dir = false; | |
250 | ||
251 | //if has the 'kind' attribute (old versions of svn dont have this), check if it is a dir | |
252 | if(kind != 0 && strcmp(kind,"dir") == 0) { | |
253 | ||
254 | //accept only deletes for directories | |
255 | if(strcmp(action, "D") != 0) continue; | |
256 | ||
257 | is_dir = true; | |
258 | } | |
259 | ||
260 | std::string file(pathE->GetText()); | |
261 | std::string status(action); | |
262 | ||
263 | if(file.empty()) continue; | |
264 | if(status.empty()) continue; | |
265 | ||
266 | //append trailing slash if is directory | |
267 | if(is_dir && file[file.size()-1] != '/') { | |
268 | file = file + std::string("/"); | |
269 | } | |
270 | ||
271 | commit.addFile(file, status); | |
272 | } | |
273 | ||
274 | //fprintf(stderr,"parsed logentry\n"); | |
275 | ||
276 | //read files | |
277 | ||
278 | return true; | |
279 | } |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef SVNLOG_H | |
18 | #define SVNLOG_H | |
19 | ||
20 | #include "../gource_settings.h" | |
21 | ||
22 | #include "commitlog.h" | |
23 | ||
24 | #include <sstream> | |
25 | ||
26 | #ifdef HAVE_LIBTINYXML | |
27 | #include <tinyxml.h> | |
28 | #else | |
29 | #include "../tinyxml/tinyxml.h" | |
30 | #endif | |
31 | ||
32 | #include <unistd.h> | |
33 | ||
34 | extern std::string gGourceSVNLogCommand; | |
35 | ||
36 | class SVNCommitLog : public RCommitLog { | |
37 | protected: | |
38 | bool parseCommit(RCommit& commit); | |
39 | BaseLog* generateLog(const std::string& dir); | |
40 | ||
41 | std::string logentry; | |
42 | public: | |
43 | SVNCommitLog(const std::string& logfile); | |
44 | }; | |
45 | ||
46 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "git.h" | |
18 | ||
19 | // parse git log entries | |
20 | ||
21 | //git-log command notes: | |
22 | // - no single quotes on WIN32 as system call treats them differently | |
23 | // - 'user:' prefix allows us to quickly tell if the log is the wrong format | |
24 | // and try a different format (eg cvs-exp) | |
25 | ||
26 | std::string gGourceGitLogCommand = "git log " | |
27 | "--pretty=format:user:%aN%n%ct " | |
28 | "--reverse --raw --encoding=UTF-8 " | |
29 | "--no-renames"; | |
30 | ||
31 | GitCommitLog::GitCommitLog(const std::string& logfile) : RCommitLog(logfile, 'u') { | |
32 | ||
33 | log_command = gGourceGitLogCommand; | |
34 | ||
35 | if(gGourceSettings.git_branch.size()>0) { | |
36 | log_command += " "; | |
37 | log_command += gGourceSettings.git_branch; | |
38 | } | |
39 | ||
40 | //can generate log from directory | |
41 | if(!logf && is_dir) { | |
42 | logf = generateLog(logfile); | |
43 | ||
44 | if(logf) { | |
45 | success = true; | |
46 | seekable = true; | |
47 | } | |
48 | } | |
49 | } | |
50 | ||
51 | BaseLog* GitCommitLog::generateLog(const std::string& dir) { | |
52 | //get working directory | |
53 | char cwd_buff[1024]; | |
54 | ||
55 | if(getcwd(cwd_buff, 1024) != cwd_buff) { | |
56 | return 0; | |
57 | } | |
58 | ||
59 | //does directory have a .git ? | |
60 | std::string gitdir = dir + std::string("/.git"); | |
61 | struct stat dirinfo; | |
62 | int stat_rc = stat(gitdir.c_str(), &dirinfo); | |
63 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
64 | return 0; | |
65 | } | |
66 | ||
67 | std::string command = getLogCommand(); | |
68 | ||
69 | //create temp file | |
70 | createTempLog(); | |
71 | ||
72 | if(temp_file.size()==0) return 0; | |
73 | ||
74 | if(chdir(dir.c_str()) != 0) { | |
75 | return 0; | |
76 | } | |
77 | ||
78 | char cmd_buff[2048]; | |
79 | sprintf(cmd_buff, "%s > %s", command.c_str(), temp_file.c_str()); | |
80 | ||
81 | int command_rc = system(cmd_buff); | |
82 | ||
83 | if(command_rc != 0) { | |
84 | chdir(cwd_buff); | |
85 | return 0; | |
86 | } | |
87 | ||
88 | // check for new-enough Git version | |
89 | // if %aN does not appear to be supported try %an | |
90 | std::ifstream in(temp_file.c_str()); | |
91 | char firstBytes[9]; | |
92 | in.read(firstBytes, 8); | |
93 | in.close(); | |
94 | firstBytes[8] = '\0'; | |
95 | if(!strcmp(firstBytes, "user:%aN")) { | |
96 | char *pos = strstr(cmd_buff, "%aN"); | |
97 | pos[2] = 'n'; | |
98 | command_rc = system(cmd_buff); | |
99 | } | |
100 | ||
101 | //change back to original directoy | |
102 | chdir(cwd_buff); | |
103 | ||
104 | if(command_rc != 0) { | |
105 | return 0; | |
106 | } | |
107 | ||
108 | BaseLog* seeklog = new SeekLog(temp_file); | |
109 | ||
110 | return seeklog; | |
111 | } | |
112 | ||
113 | // parse modified git format log entries | |
114 | ||
115 | bool GitCommitLog::parseCommit(RCommit& commit) { | |
116 | ||
117 | std::string line; | |
118 | ||
119 | commit.username = ""; | |
120 | ||
121 | while(logf->getNextLine(line) && line.size()) { | |
122 | ||
123 | if(line.find("user:") == 0) { | |
124 | ||
125 | //username follows user prefix | |
126 | commit.username = line.substr(5); | |
127 | ||
128 | if(!logf->getNextLine(line)) return false; | |
129 | ||
130 | commit.timestamp = atol(line.c_str()); | |
131 | ||
132 | //this isnt a commit we are parsing, abort | |
133 | if(commit.timestamp == 0) return false; | |
134 | ||
135 | continue; | |
136 | } | |
137 | ||
138 | //should see username before files | |
139 | if(commit.username.size() == 0) return false; | |
140 | ||
141 | size_t tab = line.find('\t'); | |
142 | ||
143 | //incorrect log format | |
144 | if(tab == std::string::npos || tab == 0 || tab == line.size()-1) continue; | |
145 | ||
146 | std::string status = line.substr(tab - 1, 1); | |
147 | std::string file = line.substr(tab + 1); | |
148 | ||
149 | if(file.empty()) continue; | |
150 | ||
151 | //check for and remove double quotes | |
152 | if(file.find('"') == 0 && file.rfind('"') == file.size()-1) { | |
153 | if(file.size()<=2) continue; | |
154 | ||
155 | file = file.substr(1,file.size()-2); | |
156 | } | |
157 | ||
158 | commit.addFile(file, status); | |
159 | } | |
160 | ||
161 | //check we at least got a username | |
162 | if(commit.username.size()==0) return false; | |
163 | ||
164 | return true; | |
165 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GITLOG_H | |
18 | #define GITLOG_H | |
19 | ||
20 | #include "gource_settings.h" | |
21 | ||
22 | #include "commitlog.h" | |
23 | ||
24 | #include <unistd.h> | |
25 | ||
26 | extern std::string gGourceGitLogCommand; | |
27 | ||
28 | class GitCommitLog : public RCommitLog { | |
29 | protected: | |
30 | bool parseCommit(RCommit& commit); | |
31 | BaseLog* generateLog(const std::string& dir); | |
32 | public: | |
33 | GitCommitLog(const std::string& logfile); | |
34 | }; | |
35 | ||
36 | #endif |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "gitraw.h" | |
18 | ||
19 | Regex git_raw_commit("^commit ([0-9a-z]+)"); | |
20 | Regex git_raw_tree("^tree ([0-9a-z]+)"); | |
21 | Regex git_raw_parent("^parent ([0-9a-z]+)"); | |
22 | Regex git_raw_author("^author (.+) <([^@>]+)@?([^>]*)> (\\d+) ([-+]\\d+)"); | |
23 | Regex git_raw_committer("^committer (.+) <([^@>]+)@?([^>]*)> (\\d+) ([-+]\\d+)"); | |
24 | Regex git_raw_file("^:[0-9]+ [0-9]+ [0-9a-z]+\\.* ([0-9a-z]+)\\.* ([A-Z])[ \\t]+(.+)"); | |
25 | ||
26 | // parse git log entries | |
27 | ||
28 | std::string gGourceGitRawLogCommand = "git log --reverse --raw --pretty=raw"; | |
29 | ||
30 | GitRawCommitLog::GitRawCommitLog(const std::string& logfile) : RCommitLog(logfile, 'c') { | |
31 | ||
32 | log_command = gGourceGitRawLogCommand; | |
33 | } | |
34 | ||
35 | // parse modified cvs format log entries | |
36 | ||
37 | bool GitRawCommitLog::parseCommit(RCommit& commit) { | |
38 | ||
39 | std::string line; | |
40 | std::vector<std::string> entries; | |
41 | ||
42 | //read commit ref/ branch | |
43 | if(!logf->getNextLine(line)) return false; | |
44 | ||
45 | //commit | |
46 | if(!git_raw_commit.match(line, &entries)) return false; | |
47 | ||
48 | if(!logf->getNextLine(line)) return false; | |
49 | ||
50 | //tree | |
51 | if(!git_raw_tree.match(line, &entries)) return false; | |
52 | ||
53 | if(!logf->getNextLine(line)) return false; | |
54 | ||
55 | //0 or more parents | |
56 | while(git_raw_parent.match(line, &entries)) { | |
57 | if(!logf->getNextLine(line)) return false; | |
58 | } | |
59 | ||
60 | //author - used for display name | |
61 | if(!git_raw_author.match(line, &entries)) return false; | |
62 | ||
63 | commit.username = entries[0]; | |
64 | ||
65 | if(!logf->getNextLine(line)) return false; | |
66 | ||
67 | //committer - used for time (most likely cronological) | |
68 | if(!git_raw_committer.match(line, &entries)) return false; | |
69 | ||
70 | commit.timestamp = atol(entries[3].c_str()); | |
71 | ||
72 | //blank line before message | |
73 | if(!logf->getNextLine(line)) return false; | |
74 | ||
75 | //read commit message | |
76 | while(logf->getNextLine(line) && line.size()) { | |
77 | } | |
78 | ||
79 | //read files | |
80 | while(logf->getNextLine(line) && line.size()) { | |
81 | //debugLog("file??? %s\n", line.c_str()); | |
82 | ||
83 | if(git_raw_file.match(line, &entries)) { | |
84 | commit.addFile(entries[2], entries[1]); | |
85 | } | |
86 | } | |
87 | ||
88 | // commit.debug(); | |
89 | ||
90 | return true; | |
91 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef GITLOG_RAW_H | |
18 | #define GITLOG_RAW_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | #include <unistd.h> | |
23 | ||
24 | extern std::string gGourceGitRawLogCommand; | |
25 | ||
26 | class GitRawCommitLog : public RCommitLog { | |
27 | protected: | |
28 | bool parseCommit(RCommit& commit); | |
29 | public: | |
30 | GitRawCommitLog(const std::string& logfile); | |
31 | }; | |
32 | ||
33 | #endif | |
34 |
31 | 31 | if(!GLEW_VERSION_2_0) gGourceSettings.ffp = true; |
32 | 32 | |
33 | 33 | if(!gGourceSettings.file_graphic) { |
34 | gGourceSettings.file_graphic = texturemanager.grab("file.png"); | |
34 | gGourceSettings.file_graphic = texturemanager.grab("file.png", true, GL_CLAMP_TO_EDGE); | |
35 | 35 | } |
36 | 36 | |
37 | 37 | fontlarge = fontmanager.grab("FreeSans.ttf", 42); |
51 | 51 | |
52 | 52 | bloomtex = texturemanager.grab(bloom_tga); |
53 | 53 | beamtex = texturemanager.grab("beam.png"); |
54 | usertex = texturemanager.grab("no_photo.png"); | |
54 | usertex = texturemanager.grab("user.png", true, GL_CLAMP_TO_EDGE); | |
55 | 55 | |
56 | 56 | shadow_shader = text_shader = bloom_shader = 0; |
57 | 57 | |
83 | 83 | |
84 | 84 | paused = false; |
85 | 85 | first_read = true; |
86 | draw_loading = true; | |
87 | 86 | |
88 | 87 | grab_mouse = false; |
89 | 88 | mousemoved = false; |
90 | 89 | mousedragged = false; |
91 | 90 | mouseclicked = false; |
92 | 91 | |
93 | cursor.setCursorTexture(texturemanager.grab("cursor.png")); | |
94 | cursor.useSystemCursor(false); | |
95 | ||
96 | 92 | if(gGourceSettings.hide_mouse) { |
97 | 93 | cursor.showCursor(false); |
98 | 94 | } |
120 | 116 | |
121 | 117 | file_key = FileKey(1.0f); |
122 | 118 | |
123 | camera = ZoomCamera(vec3f(0,0, -300), vec3f(0.0, 0.0, 0.0), 250.0, 5000.0); | |
119 | camera = ZoomCamera(vec3(0,0, -300), vec3(0.0, 0.0, 0.0), gGourceSettings.camera_zoom_default, gGourceSettings.camera_zoom_max); | |
124 | 120 | camera.setPadding(gGourceSettings.padding); |
125 | 121 | |
126 | 122 | setCameraMode(gGourceSettings.camera_mode); |
135 | 131 | |
136 | 132 | reset(); |
137 | 133 | |
134 | logmill = new RLogMill(logfile); | |
135 | ||
136 | shutdown = false; | |
137 | ||
138 | 138 | if(exporter!=0) setFrameExporter(exporter, gGourceSettings.output_framerate); |
139 | 139 | |
140 | 140 | //if recording a video or in demo mode, or multiple repos, the slider is initially hidden |
142 | 142 | } |
143 | 143 | |
144 | 144 | void Gource::writeCustomLog(const std::string& logfile, const std::string& output_file) { |
145 | RCommitLog* commitlog = determineFormat(logfile); | |
146 | ||
147 | if(!commitlog) return; | |
145 | ||
146 | RLogMill logmill(logfile); | |
147 | RCommitLog* commitlog = logmill.getLog(); | |
148 | ||
149 | // TODO: exception handling | |
150 | ||
151 | if(!commitlog) { | |
152 | std::string error = logmill.getError(); | |
153 | if(!error.empty()) SDLAppQuit(error); | |
154 | return; | |
155 | } | |
148 | 156 | |
149 | 157 | RCommit commit; |
150 | 158 | |
178 | 186 | if(output_file != "-") fclose(fh); |
179 | 187 | } |
180 | 188 | |
181 | RCommitLog* Gource::determineFormat(const std::string& logfile) { | |
182 | debugLog("determineFormat(%s)\n", logfile.c_str()); | |
183 | ||
184 | RCommitLog* clog = 0; | |
185 | ||
186 | //we've been told what format to use | |
187 | if(gGourceSettings.log_format.size() > 0) { | |
188 | debugLog("--log-format = %s\n", gGourceSettings.log_format.c_str()); | |
189 | ||
190 | if(gGourceSettings.log_format == "git") { | |
191 | clog = new GitCommitLog(logfile); | |
192 | if(clog->checkFormat()) return clog; | |
193 | delete clog; | |
194 | ||
195 | clog = new GitRawCommitLog(logfile); | |
196 | if(clog->checkFormat()) return clog; | |
197 | delete clog; | |
198 | } | |
199 | ||
200 | if(gGourceSettings.log_format == "hg") { | |
201 | clog = new MercurialLog(logfile); | |
202 | if(clog->checkFormat()) return clog; | |
203 | delete clog; | |
204 | } | |
205 | if(gGourceSettings.log_format == "bzr") { | |
206 | clog = new BazaarLog(logfile); | |
207 | if(clog->checkFormat()) return clog; | |
208 | delete clog; | |
209 | } | |
210 | ||
211 | if(gGourceSettings.log_format == "cvs") { | |
212 | clog = new CVSEXPCommitLog(logfile); | |
213 | if(clog->checkFormat()) return clog; | |
214 | delete clog; | |
215 | } | |
216 | ||
217 | if(gGourceSettings.log_format == "custom") { | |
218 | clog = new CustomLog(logfile); | |
219 | if(clog->checkFormat()) return clog; | |
220 | delete clog; | |
221 | } | |
222 | ||
223 | if(gGourceSettings.log_format == "apache") { | |
224 | clog = new ApacheCombinedLog(logfile); | |
225 | if(clog->checkFormat()) return clog; | |
226 | delete clog; | |
227 | } | |
228 | ||
229 | if(gGourceSettings.log_format == "svn") { | |
230 | clog = new SVNCommitLog(logfile); | |
231 | if(clog->checkFormat()) return clog; | |
232 | delete clog; | |
233 | } | |
234 | ||
235 | if(gGourceSettings.log_format == "cvs2cl") { | |
236 | clog = new CVS2CLCommitLog(logfile); | |
237 | if(clog->checkFormat()) return clog; | |
238 | delete clog; | |
239 | } | |
240 | ||
241 | return 0; | |
242 | } | |
243 | ||
244 | //git | |
245 | debugLog("trying git...\n"); | |
246 | clog = new GitCommitLog(logfile); | |
247 | if(clog->checkFormat()) return clog; | |
248 | ||
249 | delete clog; | |
250 | ||
251 | //mercurial | |
252 | debugLog("trying mercurial...\n"); | |
253 | clog = new MercurialLog(logfile); | |
254 | if(clog->checkFormat()) return clog; | |
255 | ||
256 | delete clog; | |
257 | ||
258 | //bzr | |
259 | debugLog("trying bzr...\n"); | |
260 | clog = new BazaarLog(logfile); | |
261 | if(clog->checkFormat()) return clog; | |
262 | ||
263 | delete clog; | |
264 | ||
265 | //git raw | |
266 | debugLog("trying git raw...\n"); | |
267 | clog = new GitRawCommitLog(logfile); | |
268 | if(clog->checkFormat()) return clog; | |
269 | ||
270 | delete clog; | |
271 | ||
272 | //cvs exp | |
273 | debugLog("trying cvs-exp...\n"); | |
274 | clog = new CVSEXPCommitLog(logfile); | |
275 | if(clog->checkFormat()) return clog; | |
276 | ||
277 | delete clog; | |
278 | ||
279 | //svn | |
280 | debugLog("trying svn...\n"); | |
281 | clog = new SVNCommitLog(logfile); | |
282 | if(clog->checkFormat()) return clog; | |
283 | ||
284 | delete clog; | |
285 | ||
286 | //cvs2cl | |
287 | debugLog("trying cvs2cl...\n"); | |
288 | clog = new CVS2CLCommitLog(logfile); | |
289 | if(clog->checkFormat()) return clog; | |
290 | ||
291 | delete clog; | |
292 | ||
293 | //custom | |
294 | debugLog("trying custom...\n"); | |
295 | clog = new CustomLog(logfile); | |
296 | if(clog->checkFormat()) return clog; | |
297 | ||
298 | delete clog; | |
299 | ||
300 | //apache | |
301 | debugLog("trying apache combined...\n"); | |
302 | clog = new ApacheCombinedLog(logfile); | |
303 | if(clog->checkFormat()) return clog; | |
304 | ||
305 | delete clog; | |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
310 | 189 | Gource::~Gource() { |
311 | 190 | reset(); |
312 | 191 | |
313 | if(commitlog!=0) delete commitlog; | |
314 | if(root!=0) delete root; | |
192 | if(logmill!=0) delete logmill; | |
193 | if(root!=0) delete root; | |
315 | 194 | |
316 | 195 | //reset settings |
317 | 196 | gGourceSettings.setGourceDefaults(); |
318 | 197 | } |
319 | 198 | |
320 | 199 | void Gource::init() { |
200 | } | |
201 | ||
202 | void Gource::unload() { | |
203 | ||
204 | file_vbo.unload(); | |
205 | user_vbo.unload(); | |
206 | edge_vbo.unload(); | |
207 | action_vbo.unload(); | |
208 | bloom_vbo.unload(); | |
209 | ||
210 | } | |
211 | ||
212 | void Gource::reload() { | |
213 | ||
214 | slider.resize(); | |
215 | } | |
216 | ||
217 | void Gource::quit() { | |
218 | shutdown = true; | |
321 | 219 | } |
322 | 220 | |
323 | 221 | void Gource::update(float t, float dt) { |
346 | 244 | draw(runtime, scaled_dt); |
347 | 245 | |
348 | 246 | //extract frames based on frameskip setting if frameExporter defined |
349 | if(frameExporter != 0) { | |
247 | if(frameExporter != 0 && commitlog && !shutdown) { | |
350 | 248 | if(framecount % (frameskip+1) == 0) { |
351 | 249 | frameExporter->dump(); |
352 | 250 | } |
387 | 285 | |
388 | 286 | bool rightmouse = cursor.rightButtonPressed(); |
389 | 287 | |
288 | #if not SDL_VERSION_ATLEAST(1,3,0) | |
390 | 289 | if(grab_mouse) { |
391 | 290 | int warp_x = display.width/2; |
392 | 291 | int warp_y = display.height/2; |
396 | 295 | |
397 | 296 | SDL_WarpMouse(warp_x, warp_y); |
398 | 297 | } |
298 | #endif | |
399 | 299 | |
400 | 300 | //move camera in direction the user dragged the mouse |
401 | 301 | if(mousedragged || rightmouse) { |
402 | vec2f mag( e->xrel, e->yrel ); | |
302 | vec2 mag( e->xrel, e->yrel ); | |
403 | 303 | |
404 | 304 | //if right mouse button is held while dragging, rotate tree instead of |
405 | 305 | //moving camera |
424 | 324 | |
425 | 325 | if(grab_mouse) return; |
426 | 326 | |
427 | mousepos = vec2f(e->x, e->y); | |
327 | mousepos = vec2(e->x, e->y); | |
428 | 328 | mousemoved=true; |
429 | 329 | |
430 | 330 | cursor.updatePos(mousepos); |
449 | 349 | if(zoomin) { |
450 | 350 | distance /= zoom_multi; |
451 | 351 | |
452 | if(distance < 100.0f) distance = 100.0f; | |
352 | if(distance < gGourceSettings.camera_zoom_min) distance = gGourceSettings.camera_zoom_min; | |
453 | 353 | } else { |
454 | 354 | distance *= zoom_multi; |
455 | 355 | |
456 | if(distance > 4999.0f) distance = 4999.0f; | |
356 | if(distance > gGourceSettings.camera_zoom_max) distance = gGourceSettings.camera_zoom_max; | |
457 | 357 | } |
458 | 358 | |
459 | 359 | camera.setDistance(distance); |
460 | 360 | } |
361 | ||
362 | #if SDL_VERSION_ATLEAST(1,3,0) | |
363 | void Gource::mouseWheel(SDL_MouseWheelEvent *e) { | |
364 | ||
365 | int mouse_x, mouse_y; | |
366 | SDL_GetMouseState(&mouse_x, &mouse_y); | |
367 | ||
368 | vec2 mousepos(mouse_x, mouse_y); | |
369 | ||
370 | if(e->y > 0) { | |
371 | zoom(true); | |
372 | } | |
373 | ||
374 | if(e->y < 0) { | |
375 | zoom(false); | |
376 | } | |
377 | } | |
378 | ||
379 | #endif | |
461 | 380 | |
462 | 381 | void Gource::mouseClick(SDL_MouseButtonEvent *e) { |
463 | 382 | if(commitlog==0) return; |
476 | 395 | |
477 | 396 | if(e->button == SDL_BUTTON_LEFT || e->button == SDL_BUTTON_RIGHT) { |
478 | 397 | if(!cursor.buttonPressed()) { |
398 | grab_mouse=false; | |
399 | #if SDL_VERSION_ATLEAST(1,3,0) | |
400 | SDL_SetRelativeMouseMode(SDL_FALSE); | |
401 | SDL_WarpMouseInWindow(display.sdl_window, mousepos.x, mousepos.y); | |
402 | #else | |
403 | SDL_WarpMouse(mousepos.x, mousepos.y); | |
404 | #endif | |
479 | 405 | cursor.showCursor(true); |
480 | grab_mouse=false; | |
481 | SDL_WarpMouse(mousepos.x, mousepos.y); | |
482 | 406 | } |
483 | 407 | } |
484 | 408 | } |
506 | 430 | if(e->button == SDL_BUTTON_RIGHT) { |
507 | 431 | cursor.showCursor(false); |
508 | 432 | grab_mouse=true; |
433 | #if SDL_VERSION_ATLEAST(1,3,0) | |
434 | SDL_SetRelativeMouseMode(SDL_TRUE); | |
435 | #endif | |
509 | 436 | return; |
510 | 437 | } |
511 | 438 | |
512 | 439 | if(e->button == SDL_BUTTON_LEFT) { |
513 | 440 | |
514 | //mousepos = vec2f(e->x, e->y); | |
441 | //mousepos = vec2(e->x, e->y); | |
515 | 442 | mouseclicked=true; |
516 | 443 | |
517 | 444 | if(canSeek()) { |
681 | 608 | if (e->type == SDL_KEYUP) return; |
682 | 609 | |
683 | 610 | if (e->type == SDL_KEYDOWN) { |
684 | if (e->keysym.unicode == SDLK_ESCAPE) { | |
685 | appFinished=true; | |
611 | ||
612 | #if SDL_VERSION_ATLEAST(1,3,0) | |
613 | bool key_escape = e->keysym.scancode == SDL_SCANCODE_ESCAPE; | |
614 | bool key_tab = e->keysym.scancode == SDL_SCANCODE_TAB; | |
615 | bool key_space = e->keysym.scancode == SDL_SCANCODE_SPACE; | |
616 | bool key_plus = e->keysym.scancode == SDL_SCANCODE_EQUALS; | |
617 | bool key_equals = e->keysym.scancode == SDL_SCANCODE_EQUALS; | |
618 | bool key_minus = e->keysym.scancode == SDL_SCANCODE_MINUS; | |
619 | bool key_leftbracket = e->keysym.scancode == SDL_SCANCODE_LEFTBRACKET; | |
620 | bool key_rightbracket = e->keysym.scancode == SDL_SCANCODE_RIGHTBRACKET; | |
621 | bool key_comma = e->keysym.scancode == SDL_SCANCODE_COMMA; | |
622 | bool key_period = e->keysym.scancode == SDL_SCANCODE_PERIOD; | |
623 | bool key_slash = e->keysym.scancode == SDL_SCANCODE_SLASH; | |
624 | #else | |
625 | bool key_escape = e->keysym.unicode == SDLK_ESCAPE; | |
626 | bool key_tab = e->keysym.unicode == SDLK_TAB; | |
627 | bool key_space = e->keysym.unicode == SDLK_SPACE; | |
628 | bool key_plus = e->keysym.unicode == SDLK_PLUS; | |
629 | bool key_equals = e->keysym.unicode == SDLK_EQUALS; | |
630 | bool key_minus = e->keysym.unicode == SDLK_MINUS; | |
631 | bool key_leftbracket = e->keysym.unicode == SDLK_LEFTBRACKET; | |
632 | bool key_rightbracket = e->keysym.unicode == SDLK_RIGHTBRACKET; | |
633 | bool key_comma = e->keysym.unicode == SDLK_COMMA; | |
634 | bool key_period = e->keysym.unicode == SDLK_PERIOD; | |
635 | bool key_slash = e->keysym.unicode == SDLK_SLASH; | |
636 | #endif | |
637 | ||
638 | if (key_escape) { | |
639 | quit(); | |
686 | 640 | } |
687 | 641 | |
688 | 642 | if(commitlog==0) return; |
808 | 762 | recolour=true; |
809 | 763 | } |
810 | 764 | |
811 | if(e->keysym.unicode == SDLK_TAB) { | |
765 | if(key_tab) { | |
812 | 766 | selectNextUser(); |
813 | 767 | } |
814 | 768 | |
815 | if (e->keysym.unicode == SDLK_SPACE) { | |
769 | if (key_space) { | |
816 | 770 | paused = !paused; |
817 | 771 | } |
818 | 772 | |
819 | if (e->keysym.unicode == SDLK_EQUALS || e->keysym.unicode == SDLK_PLUS) { | |
773 | if (key_equals || key_plus) { | |
820 | 774 | if(gGourceSettings.days_per_second>=1.0) { |
821 | 775 | gGourceSettings.days_per_second = std::min(30.0f, floorf(gGourceSettings.days_per_second) + 1.0f); |
822 | 776 | } else { |
824 | 778 | } |
825 | 779 | } |
826 | 780 | |
827 | if (e->keysym.unicode == SDLK_MINUS) { | |
781 | if (key_minus) { | |
828 | 782 | if(gGourceSettings.days_per_second>1.0) { |
829 | 783 | gGourceSettings.days_per_second = std::max(0.0f, floorf(gGourceSettings.days_per_second) - 1.0f); |
830 | 784 | } else { |
840 | 794 | zoom(false); |
841 | 795 | } |
842 | 796 | |
843 | if(e->keysym.unicode == SDLK_LEFTBRACKET) { | |
797 | if(key_leftbracket) { | |
844 | 798 | gGourceForceGravity /= 1.1; |
845 | 799 | } |
846 | 800 | |
847 | if(e->keysym.unicode == SDLK_RIGHTBRACKET) { | |
801 | if(key_rightbracket) { | |
848 | 802 | gGourceForceGravity *= 1.1; |
849 | 803 | } |
850 | 804 | |
851 | if(e->keysym.unicode == SDLK_PERIOD) { | |
805 | if(key_period) { | |
852 | 806 | |
853 | 807 | if(gGourceSettings.time_scale>=1.0) { |
854 | 808 | gGourceSettings.time_scale = std::min(4.0f, floorf(gGourceSettings.time_scale) + 1.0f); |
857 | 811 | } |
858 | 812 | } |
859 | 813 | |
860 | if(e->keysym.unicode == SDLK_COMMA) { | |
814 | if(key_comma) { | |
861 | 815 | |
862 | 816 | if(gGourceSettings.time_scale>1.0) { |
863 | 817 | gGourceSettings.time_scale = std::max(0.0f, floorf(gGourceSettings.time_scale) - 1.0f); |
866 | 820 | } |
867 | 821 | } |
868 | 822 | |
869 | if(e->keysym.unicode == SDLK_SLASH) { | |
823 | if(key_slash) { | |
870 | 824 | gGourceSettings.time_scale = 1.0f; |
871 | 825 | } |
872 | 826 | } |
903 | 857 | |
904 | 858 | message_timer = 0.0f; |
905 | 859 | |
906 | cursor_move = vec2f(0.0f, 0.0f); | |
860 | cursor_move = vec2(0.0f, 0.0f); | |
907 | 861 | |
908 | 862 | selectedUser = 0; |
909 | 863 | hoverUser = 0; |
915 | 869 | mouseclicked=false; |
916 | 870 | mousemoved=false; |
917 | 871 | mousedragged = false; |
872 | ||
873 | commitqueue_max_size = 100; | |
918 | 874 | |
919 | 875 | rotate_angle = 0.0f; |
920 | 876 | |
979 | 935 | |
980 | 936 | RFile* Gource::addFile(const RCommitFile& cf) { |
981 | 937 | |
938 | //if we already have max files in circulation | |
939 | //we cant add any more | |
940 | if(gGourceSettings.max_files > 0 && files.size() >= gGourceSettings.max_files) return 0; | |
941 | ||
942 | //see if this is a directory | |
943 | std::string file_as_dir = cf.filename; | |
944 | if(file_as_dir[file_as_dir.size()-1] != '/') file_as_dir.append("/"); | |
945 | ||
946 | if(root->isDir(file_as_dir)) return 0; | |
947 | ||
982 | 948 | int tagid = tag_seq++; |
983 | 949 | |
984 | RFile* file = new RFile(cf.filename, cf.colour, vec2f(0.0,0.0), tagid); | |
950 | RFile* file = new RFile(cf.filename, cf.colour, vec2(0.0,0.0), tagid); | |
985 | 951 | |
986 | 952 | files[cf.filename] = file; |
987 | 953 | tagfilemap[tagid] = file; |
991 | 957 | file_key.inc(file); |
992 | 958 | |
993 | 959 | while(root->getParent() != 0) { |
994 | debugLog("parent changed to %s\n", root->getPath().c_str()); | |
960 | debugLog("parent changed to %s", root->getPath().c_str()); | |
995 | 961 | root = root->getParent(); |
996 | 962 | } |
997 | 963 | |
1000 | 966 | |
1001 | 967 | RUser* Gource::addUser(const std::string& username) { |
1002 | 968 | |
1003 | vec2f pos; | |
969 | vec2 pos; | |
1004 | 970 | |
1005 | 971 | if(dir_bounds.area() > 0) { |
1006 | 972 | pos = dir_bounds.centre(); |
1007 | 973 | } else { |
1008 | pos = vec2f(0,0); | |
974 | pos = vec2(0,0); | |
1009 | 975 | } |
1010 | 976 | |
1011 | 977 | int tagid = tag_seq++; |
1062 | 1028 | |
1063 | 1029 | //debugLog("readLog()\n"); |
1064 | 1030 | |
1065 | while(!commitlog->isFinished() && commitqueue.size() < 1) { | |
1031 | // read commits until either we are ahead of currtime | |
1032 | while(!commitlog->isFinished() && (commitqueue.empty() || commitqueue.back().timestamp <= currtime && commitqueue.size() < commitqueue_max_size)) { | |
1066 | 1033 | |
1067 | 1034 | RCommit commit; |
1068 | 1035 | |
1073 | 1040 | continue; |
1074 | 1041 | } |
1075 | 1042 | |
1076 | //ignore blank commits | |
1077 | if(commit.files.size() > 0) { | |
1078 | commitqueue.push_back(commit); | |
1079 | } | |
1080 | } | |
1081 | ||
1082 | if(first_read && commitqueue.size()==0) { | |
1043 | commitqueue.push_back(commit); | |
1044 | } | |
1045 | ||
1046 | if(first_read && commitqueue.empty()) { | |
1047 | fprintf(stderr, "no files on first read\n"); | |
1083 | 1048 | throw SDLAppException("no commits found"); |
1084 | 1049 | } |
1085 | 1050 | |
1103 | 1068 | |
1104 | 1069 | void Gource::processCommit(RCommit& commit, float t) { |
1105 | 1070 | |
1106 | //check user against filters, if found, discard commit | |
1107 | if(!gGourceSettings.user_filters.empty()) { | |
1108 | for(std::vector<Regex*>::iterator ri = gGourceSettings.user_filters.begin(); ri != gGourceSettings.user_filters.end(); ri++) { | |
1109 | Regex* r = *ri; | |
1110 | ||
1111 | if(r->match(commit.username)) { | |
1112 | return; | |
1113 | } | |
1114 | } | |
1115 | } | |
1116 | ||
1117 | 1071 | //find files of this commit or create it |
1118 | 1072 | for(std::list<RCommitFile>::iterator it = commit.files.begin(); it != commit.files.end(); it++) { |
1119 | 1073 | |
1120 | 1074 | RCommitFile& cf = *it; |
1121 | 1075 | RFile* file = 0; |
1122 | 1076 | |
1123 | //check filename against filters | |
1124 | if(!gGourceSettings.file_filters.empty()) { | |
1125 | ||
1126 | bool filtered_filename = false; | |
1127 | ||
1128 | for(std::vector<Regex*>::iterator ri = gGourceSettings.file_filters.begin(); ri != gGourceSettings.file_filters.end(); ri++) { | |
1129 | Regex* r = *ri; | |
1130 | ||
1131 | if(r->match(cf.filename)) { | |
1132 | filtered_filename = true; | |
1133 | break; | |
1134 | } | |
1135 | } | |
1136 | ||
1137 | if(filtered_filename) continue; | |
1138 | } | |
1139 | ||
1140 | 1077 | //is this a directory (ends in slash) |
1141 | 1078 | //deleting a directory - find directory: then for each file, remove each file |
1142 | 1079 | |
1154 | 1091 | for(std::list<RDirNode*>::iterator it = dirs.begin(); it != dirs.end(); it++) { |
1155 | 1092 | |
1156 | 1093 | RDirNode* dir = (*it); |
1157 | ||
1094 | ||
1158 | 1095 | //fprintf(stderr, "deleting everything under %s because of %s\n", dir->getPath().c_str(), cf.filename.c_str()); |
1159 | 1096 | |
1160 | 1097 | //foreach dir files |
1168 | 1105 | addFileAction(commit.username, cf.action, file, t); |
1169 | 1106 | } |
1170 | 1107 | } |
1171 | ||
1108 | ||
1172 | 1109 | return; |
1173 | 1110 | } |
1174 | 1111 | |
1177 | 1114 | |
1178 | 1115 | if(file == 0) { |
1179 | 1116 | |
1180 | //if we already have max files in circulation | |
1181 | //we cant add any more | |
1182 | if(gGourceSettings.max_files > 0 && files.size() >= gGourceSettings.max_files) | |
1183 | continue; | |
1184 | ||
1185 | 1117 | file = addFile(cf); |
1118 | ||
1119 | if(!file) continue; | |
1186 | 1120 | } |
1187 | 1121 | |
1188 | 1122 | addFileAction(commit.username, cf.action, file, t); |
1203 | 1137 | if(user == 0) { |
1204 | 1138 | user = addUser(username); |
1205 | 1139 | |
1206 | // set the highlighted flag if name matches a highlighted user | |
1207 | for(std::vector<std::string>::iterator hi = gGourceSettings.highlight_users.begin(); hi != gGourceSettings.highlight_users.end(); hi++) { | |
1208 | std::string highlight = *hi; | |
1209 | ||
1210 | if(highlight.size() && user->getName() == highlight) { | |
1211 | user->setHighlighted(true); | |
1212 | break; | |
1140 | if(gGourceSettings.highlight_all_users) user->setHighlighted(true); | |
1141 | else { | |
1142 | ||
1143 | // set the highlighted flag if name matches a highlighted user | |
1144 | for(std::vector<std::string>::iterator hi = gGourceSettings.highlight_users.begin(); hi != gGourceSettings.highlight_users.end(); hi++) { | |
1145 | std::string highlight = *hi; | |
1146 | ||
1147 | if(!highlight.empty() && user->getName() == highlight) { | |
1148 | user->setHighlighted(true); | |
1149 | break; | |
1150 | } | |
1213 | 1151 | } |
1214 | 1152 | } |
1215 | 1153 | } |
1239 | 1177 | // update quad tree |
1240 | 1178 | Bounds2D quadtreebounds = user_bounds; |
1241 | 1179 | |
1242 | quadtreebounds.min -= vec2f(1.0f, 1.0f); | |
1243 | quadtreebounds.max += vec2f(1.0f, 1.0f); | |
1180 | quadtreebounds.min -= vec2(1.0f, 1.0f); | |
1181 | quadtreebounds.max += vec2(1.0f, 1.0f); | |
1244 | 1182 | |
1245 | 1183 | update_user_tree_time = SDL_GetTicks(); |
1246 | 1184 | |
1364 | 1302 | // update quad tree |
1365 | 1303 | Bounds2D quadtreebounds = dir_bounds; |
1366 | 1304 | |
1367 | quadtreebounds.min -= vec2f(1.0f, 1.0f); | |
1368 | quadtreebounds.max += vec2f(1.0f, 1.0f); | |
1305 | quadtreebounds.min -= vec2(1.0f, 1.0f); | |
1306 | quadtreebounds.max += vec2(1.0f, 1.0f); | |
1369 | 1307 | |
1370 | 1308 | update_dir_tree_time = SDL_GetTicks(); |
1371 | 1309 | |
1426 | 1364 | |
1427 | 1365 | if(manual_camera) { |
1428 | 1366 | |
1429 | if(cursor_move.length2() > 0.0f) { | |
1367 | if(glm::length2(cursor_move) > 0.0f) { | |
1430 | 1368 | |
1431 | 1369 | float cam_rate = ( -camera.getPos().z ) / ( 5000.0f ); |
1432 | 1370 | |
1433 | vec3f cam_pos = camera.getPos(); | |
1434 | ||
1435 | vec2f cursor_delta = cursor_move * cam_rate * 400.0f * dt; | |
1371 | vec3 cam_pos = camera.getPos(); | |
1372 | ||
1373 | vec2 cursor_delta = cursor_move * cam_rate * 400.0f * dt; | |
1436 | 1374 | |
1437 | 1375 | cam_pos.x += cursor_delta.x; |
1438 | 1376 | cam_pos.y += cursor_delta.y; |
1442 | 1380 | |
1443 | 1381 | auto_rotate = false; |
1444 | 1382 | |
1445 | cursor_move = vec2f(0.0f, 0.0f); | |
1383 | cursor_move = vec2(0.0f, 0.0f); | |
1446 | 1384 | } |
1447 | 1385 | |
1448 | 1386 | } else { |
1452 | 1390 | if(track_users && (selectedFile !=0 || selectedUser !=0)) { |
1453 | 1391 | Bounds2D focusbounds; |
1454 | 1392 | |
1455 | vec3f camerapos = camera.getPos(); | |
1393 | vec3 camerapos = camera.getPos(); | |
1456 | 1394 | |
1457 | 1395 | if(selectedUser !=0) focusbounds.update(selectedUser->getPos()); |
1458 | 1396 | if(selectedFile !=0) focusbounds.update(selectedFile->getAbsolutePos()); |
1483 | 1421 | |
1484 | 1422 | } else if(!cursor.rightButtonPressed() && dir_bounds.area() > 10000.0f) { |
1485 | 1423 | |
1486 | float ratio = dir_bounds.width() / dir_bounds.height(); | |
1487 | ||
1488 | if(ratio < 0.67f) { | |
1424 | float aspect_ratio = display.width / (float) display.height; | |
1425 | ||
1426 | float bounds_ratio = (aspect_ratio > 1.0f) ? dir_bounds.width() / dir_bounds.height() : dir_bounds.height() / dir_bounds.width(); | |
1427 | ||
1428 | if(bounds_ratio < 0.67f) { | |
1489 | 1429 | rotation_remaining_angle = 90.0f; |
1490 | 1430 | } |
1491 | 1431 | } |
1512 | 1452 | |
1513 | 1453 | void Gource::logic(float t, float dt) { |
1514 | 1454 | |
1515 | if(draw_loading) return; | |
1516 | ||
1455 | if(shutdown && logmill->isFinished()) { | |
1456 | appFinished=true; | |
1457 | return; | |
1458 | } | |
1459 | ||
1517 | 1460 | if(message_timer>0.0f) message_timer -= dt; |
1518 | 1461 | if(splash>0.0f) splash -= dt; |
1519 | 1462 | |
1520 | 1463 | //init log file |
1521 | 1464 | if(commitlog == 0) { |
1522 | 1465 | |
1523 | try { | |
1524 | ||
1525 | commitlog = determineFormat(logfile); | |
1526 | ||
1527 | } catch(SeekLogException& exception) { | |
1528 | throw SDLAppException("unable to read log file"); | |
1529 | } | |
1530 | ||
1531 | if(commitlog == 0) { | |
1532 | //if not in a git dir and no log file, show help | |
1533 | if(logfile.size() == 0 || logfile == ".") { | |
1466 | if(!logmill->isFinished()) return; | |
1467 | ||
1468 | commitlog = logmill->getLog(); | |
1469 | ||
1470 | std::string error = logmill->getError(); | |
1471 | ||
1472 | if(!commitlog) { | |
1473 | ||
1474 | if(!error.empty()) { | |
1475 | throw SDLAppException(error); | |
1476 | } else { | |
1477 | ||
1478 | if(frameExporter!=0) frameExporter->stop(); | |
1479 | ||
1534 | 1480 | SDL_Quit(); |
1535 | 1481 | |
1536 | 1482 | SDLAppException exception(""); |
1537 | 1483 | exception.setShowHelp(true); |
1484 | ||
1538 | 1485 | throw exception; |
1539 | } else if(SDLAppDirExists(logfile)) { | |
1540 | throw SDLAppException("directory not supported"); | |
1541 | } else { | |
1542 | throw SDLAppException("unsupported log format (you may need to regenerate your log file)"); | |
1543 | 1486 | } |
1544 | 1487 | } |
1545 | 1488 | |
1552 | 1495 | |
1553 | 1496 | slider.logic(dt); |
1554 | 1497 | |
1498 | bool right = false; | |
1499 | bool left = false; | |
1500 | bool up = false; | |
1501 | bool down = false; | |
1502 | ||
1503 | #if SDL_VERSION_ATLEAST(1,3,0) | |
1504 | Uint8 *keystate = SDL_GetKeyboardState(0); | |
1505 | ||
1506 | right = keystate[SDL_SCANCODE_RIGHT]; | |
1507 | left = keystate[SDL_SCANCODE_LEFT]; | |
1508 | up = keystate[SDL_SCANCODE_UP]; | |
1509 | down = keystate[SDL_SCANCODE_DOWN]; | |
1510 | #else | |
1555 | 1511 | Uint8 *keystate = SDL_GetKeyState(0); |
1556 | 1512 | |
1557 | if(keystate[SDLK_RIGHT]) { | |
1513 | right = keystate[SDLK_RIGHT]; | |
1514 | left = keystate[SDLK_LEFT]; | |
1515 | up = keystate[SDLK_UP]; | |
1516 | down = keystate[SDLK_DOWN]; | |
1517 | #endif | |
1518 | ||
1519 | if(right) { | |
1558 | 1520 | cursor_move.x = 10.0; |
1559 | 1521 | manual_camera = true; |
1560 | 1522 | } |
1561 | 1523 | |
1562 | if(keystate[SDLK_LEFT]) { | |
1524 | if(left) { | |
1563 | 1525 | cursor_move.x = -10.0; |
1564 | 1526 | manual_camera = true; |
1565 | 1527 | } |
1566 | 1528 | |
1567 | if(keystate[SDLK_UP]) { | |
1529 | if(up) { | |
1568 | 1530 | cursor_move.y = -10.0; |
1569 | 1531 | manual_camera = true; |
1570 | 1532 | } |
1571 | 1533 | |
1572 | if(keystate[SDLK_DOWN]) { | |
1534 | if(down) { | |
1573 | 1535 | cursor_move.y = 10.0; |
1574 | 1536 | manual_camera = true; |
1575 | 1537 | } |
1585 | 1547 | for(std::map<std::string,RUser*>::iterator it = users.begin(); it!=users.end(); it++) { |
1586 | 1548 | RUser* user = it->second; |
1587 | 1549 | |
1588 | vec2f userpos = user->getPos(); | |
1589 | ||
1590 | user->setPos(userpos.rotate(s, c)); | |
1550 | vec2 userpos = user->getPos(); | |
1551 | ||
1552 | user->setPos(rotate_vec2(userpos, s, c)); | |
1591 | 1553 | } |
1592 | 1554 | |
1593 | 1555 | rotate_angle = 0.0f; |
1615 | 1577 | } |
1616 | 1578 | |
1617 | 1579 | // get more entries |
1618 | if(commitqueue.size() == 0) { | |
1580 | if(commitqueue.empty()) { | |
1619 | 1581 | readLog(); |
1620 | 1582 | } |
1621 | 1583 | |
1622 | 1584 | //loop in attempt to find commits |
1623 | if(commitqueue.size()==0 && commitlog->isSeekable() && gGourceSettings.loop) { | |
1585 | if(commitqueue.empty() && commitlog->isSeekable() && gGourceSettings.loop) { | |
1624 | 1586 | first_read=true; |
1625 | 1587 | seekTo(0.0); |
1626 | 1588 | readLog(); |
1627 | 1589 | } |
1628 | 1590 | |
1629 | if(currtime==0 && commitqueue.size()) { | |
1591 | if(currtime==0 && !commitqueue.empty()) { | |
1630 | 1592 | currtime = lasttime = commitqueue[0].timestamp; |
1631 | 1593 | subseconds = 0.0; |
1632 | 1594 | } |
1653 | 1615 | |
1654 | 1616 | |
1655 | 1617 | //add commits up until the current time |
1656 | while(commitqueue.size() > 0) { | |
1657 | ||
1658 | RCommit commit = commitqueue[0]; | |
1618 | while(!commitqueue.empty()) { | |
1619 | ||
1620 | RCommit commit = commitqueue.front(); | |
1659 | 1621 | |
1660 | 1622 | //auto skip ahead, unless stop_position_reached |
1661 | 1623 | if(gGourceSettings.auto_skip_seconds>=0.0 && idle_time >= gGourceSettings.auto_skip_seconds && !stop_position_reached) { |
1688 | 1650 | |
1689 | 1651 | updateCamera(dt); |
1690 | 1652 | |
1691 | updateTime(commitqueue.size() > 0 ? currtime : lasttime); | |
1653 | updateTime(!commitqueue.empty() ? currtime : lasttime); | |
1692 | 1654 | } |
1693 | 1655 | |
1694 | 1656 | void Gource::mousetrace(float dt) { |
1695 | 1657 | |
1696 | vec3f cam_pos = camera.getPos(); | |
1697 | ||
1698 | vec2f projected_mouse = vec2f( -(mousepos.x * 2.0f - ((float)display.width)) / ((float)display.height), | |
1658 | vec3 cam_pos = camera.getPos(); | |
1659 | ||
1660 | vec2 projected_mouse = vec2( -(mousepos.x * 2.0f - ((float)display.width)) / ((float)display.height), | |
1699 | 1661 | (1.0f - (2.0f * mousepos.y) / ((float)display.height))) |
1700 | 1662 | * cam_pos.z; |
1701 | 1663 | projected_mouse.x += cam_pos.x; |
1812 | 1774 | |
1813 | 1775 | glColor4f(1.0, 1.0, 1.0, 1.0); |
1814 | 1776 | |
1815 | std::string loading_message("Reading Log..."); | |
1816 | int width = font.getWidth(loading_message); | |
1817 | ||
1818 | font.print(display.width/2 - width/2, display.height/2 - 10, "%s", loading_message.c_str()); | |
1777 | const char* progress; | |
1778 | ||
1779 | switch(int(runtime*3.0f)%4) { | |
1780 | case 0: | |
1781 | progress = ""; | |
1782 | break; | |
1783 | case 1: | |
1784 | progress = "."; | |
1785 | break; | |
1786 | case 2: | |
1787 | progress = ".."; | |
1788 | break; | |
1789 | case 3: | |
1790 | progress = "..."; | |
1791 | break; | |
1792 | } | |
1793 | ||
1794 | const char* action = !shutdown ? "Reading Log" : "Aborting"; | |
1795 | ||
1796 | int width = font.getWidth(action); | |
1797 | font.setColour(vec4(1.0f)); | |
1798 | font.print(display.width/2 - width/2, display.height/2 - 10, "%s%s", action, progress); | |
1819 | 1799 | } |
1820 | 1800 | |
1821 | 1801 | void Gource::drawBackground(float dt) { |
1822 | 1802 | if(!gGourceDrawBackground) return; |
1823 | 1803 | |
1824 | display.setClearColour(vec4f(gGourceSettings.background_colour, gGourceSettings.transparent ? 0.0f : 1.0f)); | |
1804 | display.setClearColour(vec4(gGourceSettings.background_colour, gGourceSettings.transparent ? 0.0f : 1.0f)); | |
1825 | 1805 | display.clear(); |
1826 | 1806 | |
1827 | 1807 | if(backgroundtex!=0) { |
1865 | 1845 | |
1866 | 1846 | draw_edges_time = SDL_GetTicks() - draw_edges_time; |
1867 | 1847 | |
1868 | //draw shadows | |
1848 | //draw file shadows | |
1869 | 1849 | |
1870 | 1850 | draw_shadows_time = SDL_GetTicks(); |
1871 | 1851 | |
1852 | drawFileShadows(dt); | |
1853 | ||
1854 | draw_shadows_time = SDL_GetTicks() - draw_shadows_time; | |
1855 | ||
1856 | //draw actions | |
1857 | ||
1858 | draw_actions_time = SDL_GetTicks(); | |
1859 | ||
1860 | drawActions(dt); | |
1861 | ||
1862 | draw_actions_time = SDL_GetTicks() - draw_actions_time; | |
1863 | ||
1864 | //draw files | |
1865 | ||
1866 | draw_files_time = SDL_GetTicks(); | |
1867 | ||
1868 | drawFiles(dt); | |
1869 | ||
1870 | draw_files_time = SDL_GetTicks() - draw_files_time; | |
1871 | ||
1872 | //draw users | |
1873 | ||
1874 | draw_users_time = SDL_GetTicks(); | |
1875 | ||
1872 | 1876 | drawUserShadows(dt); |
1873 | ||
1874 | drawFileShadows(dt); | |
1875 | ||
1876 | draw_shadows_time = SDL_GetTicks() - draw_shadows_time; | |
1877 | ||
1878 | //draw actions | |
1879 | ||
1880 | draw_actions_time = SDL_GetTicks(); | |
1881 | ||
1882 | drawActions(dt); | |
1883 | ||
1884 | draw_actions_time = SDL_GetTicks() - draw_actions_time; | |
1885 | ||
1886 | //draw files | |
1887 | ||
1888 | draw_files_time = SDL_GetTicks(); | |
1889 | ||
1890 | drawFiles(dt); | |
1891 | ||
1892 | draw_files_time = SDL_GetTicks() - draw_files_time; | |
1893 | ||
1894 | //draw users | |
1895 | ||
1896 | draw_users_time = SDL_GetTicks(); | |
1897 | 1877 | |
1898 | 1878 | drawUsers(dt); |
1899 | 1879 | |
1941 | 1921 | shadow_shader->use(); |
1942 | 1922 | shadow_shader->setFloat("shadow_strength", 0.5); |
1943 | 1923 | |
1944 | vec2f shadow_offset = vec2f(2.0, 2.0); | |
1924 | vec2 shadow_offset = vec2(2.0, 2.0); | |
1945 | 1925 | |
1946 | 1926 | glPushMatrix(); |
1947 | 1927 | glTranslatef(shadow_offset.x, shadow_offset.y, 0.0f); |
2084 | 2064 | RUser* user = it->second; |
2085 | 2065 | |
2086 | 2066 | float alpha = user->getAlpha(); |
2087 | vec3f col = user->getColour(); | |
2088 | ||
2089 | user_vbo.add(user->graphic->textureid, user->getPos() - user->dims*0.5f, user->dims, vec4f(col.x, col.y, col.z, alpha)); | |
2067 | vec3 col = user->getColour(); | |
2068 | ||
2069 | user_vbo.add(user->graphic->textureid, user->getPos() - user->dims*0.5f, user->dims, vec4(col.x, col.y, col.z, alpha)); | |
2090 | 2070 | |
2091 | 2071 | //draw actions |
2092 | 2072 | user->updateActionsVBO(action_vbo); |
2146 | 2126 | shadow_shader->use(); |
2147 | 2127 | shadow_shader->setFloat("shadow_strength", 0.5); |
2148 | 2128 | |
2149 | vec2f shadow_offset = vec2f(2.0, 2.0) * gGourceSettings.user_scale; | |
2129 | vec2 shadow_offset = vec2(2.0, 2.0) * gGourceSettings.user_scale; | |
2150 | 2130 | |
2151 | 2131 | glPushMatrix(); |
2152 | 2132 | glTranslatef(shadow_offset.x, shadow_offset.y, 0.0f); |
2216 | 2196 | |
2217 | 2197 | drawBackground(dt); |
2218 | 2198 | |
2219 | if(draw_loading) { | |
2199 | if(!commitlog) { | |
2220 | 2200 | loadingScreen(); |
2221 | draw_loading = false; | |
2222 | 2201 | return; |
2223 | 2202 | } |
2224 | 2203 | |
2225 | Frustum frustum(camera); | |
2204 | Frustum frustum(camera.getPos(), camera.getTarget(), camera.getUp(), camera.getFOV(), camera.getZNear(), camera.getZFar()); | |
2226 | 2205 | |
2227 | 2206 | trace_time = SDL_GetTicks(); |
2228 | 2207 | |
2304 | 2283 | fontmanager.startBuffer(); |
2305 | 2284 | } |
2306 | 2285 | |
2307 | font.roundCoordinates(false); | |
2286 | font.roundCoordinates(false); | |
2287 | font.setColour(vec4(gGourceSettings.dir_colour, 1.0f)); | |
2308 | 2288 | |
2309 | 2289 | root->drawNames(font); |
2310 | 2290 | |
2389 | 2369 | glEnable(GL_BLEND); |
2390 | 2370 | glEnable(GL_TEXTURE_2D); |
2391 | 2371 | |
2392 | vec3f campos = camera.getPos(); | |
2372 | vec3 campos = camera.getPos(); | |
2393 | 2373 | |
2394 | 2374 | if(logotex!=0) { |
2395 | 2375 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
2400 | 2380 | |
2401 | 2381 | glBindTexture(GL_TEXTURE_2D, logotex->textureid); |
2402 | 2382 | |
2403 | vec2f logopos = vec2f(display.width, display.height) - vec2f(logotex->w, logotex->h) - gGourceSettings.logo_offset; | |
2383 | vec2 logopos = vec2(display.width, display.height) - vec2(logotex->w, logotex->h) - gGourceSettings.logo_offset; | |
2404 | 2384 | |
2405 | 2385 | glPushMatrix(); |
2406 | 2386 | |
2431 | 2411 | int cwidth = font.getWidth("Software Version Control Visualization"); |
2432 | 2412 | int awidth = font.getWidth("(C) 2009 Andrew Caudwell"); |
2433 | 2413 | |
2434 | vec2f corner(display.width/2 - logowidth/2 - 30.0f, display.height/2 - 40); | |
2414 | vec2 corner(display.width/2 - logowidth/2 - 30.0f, display.height/2 - 40); | |
2435 | 2415 | |
2436 | 2416 | glDisable(GL_TEXTURE_2D); |
2437 | 2417 | glColor4f(0.0f, 0.5f, 1.0f, splash * 0.015f); |
2444 | 2424 | |
2445 | 2425 | glEnable(GL_TEXTURE_2D); |
2446 | 2426 | |
2447 | glColor4f(1.0,1.0,1.0,1.0); | |
2427 | fontlarge.setColour(vec4(1.0f)); | |
2448 | 2428 | fontlarge.draw(display.width/2 - logowidth/2,display.height/2 - 30, "Gource"); |
2429 | ||
2430 | font.setColour(vec4(1.0f)); | |
2449 | 2431 | font.draw(display.width/2 - cwidth/2,display.height/2 + 10, "Software Version Control Visualization"); |
2450 | 2432 | font.draw(display.width/2 - awidth/2,display.height/2 + 30, "(C) 2009 Andrew Caudwell"); |
2451 | 2433 | } |
2452 | 2434 | |
2453 | 2435 | // text using the specified font goes here |
2454 | 2436 | |
2455 | fontmedium.setColour(vec4f(gGourceSettings.font_colour, 1.0f)); | |
2456 | ||
2437 | fontmedium.setColour(vec4(gGourceSettings.font_colour, 1.0f)); | |
2438 | ||
2457 | 2439 | if(!gGourceSettings.hide_date) { |
2458 | 2440 | fontmedium.draw(display.width/2 - date_x_offset, 20, displaydate); |
2459 | 2441 | } |
2501 | 2483 | //debug info |
2502 | 2484 | |
2503 | 2485 | if(debug) { |
2504 | font.setAlpha(1.0f); | |
2486 | font.setColour(vec4(1.0f)); | |
2505 | 2487 | |
2506 | 2488 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
2507 | 2489 | glEnable(GL_BLEND); |
2508 | 2490 | glEnable(GL_TEXTURE_2D); |
2509 | 2491 | |
2510 | ||
2511 | 2492 | font.print(1,20, "FPS: %.2f", fps); |
2512 | 2493 | font.print(1,40,"Days Per Second: %.2f", |
2513 | 2494 | gGourceSettings.days_per_second); |
2514 | font.print(1,60,"Time Scale: %.2f", gGourceSettings.time_scale); | |
2495 | font.print(1,60,"Commit Queue: %d", commitqueue.size()); | |
2515 | 2496 | font.print(1,80,"Users: %d", users.size()); |
2516 | 2497 | font.print(1,100,"Files: %d", files.size()); |
2517 | 2498 | font.print(1,120,"Dirs: %d", gGourceDirMap.size()); |
37 | 37 | |
38 | 38 | #include "gource_settings.h" |
39 | 39 | |
40 | #include "git.h" | |
41 | #include "hg.h" | |
42 | #include "bzr.h" | |
43 | #include "gitraw.h" | |
44 | #include "cvs2cl.h" | |
45 | #include "cvs-exp.h" | |
46 | #include "custom.h" | |
47 | #include "apache.h" | |
48 | #include "svn.h" | |
40 | #include "logmill.h" | |
49 | 41 | |
50 | 42 | #include "core/vbo.h" |
51 | 43 | #include "bloom.h" |
63 | 55 | |
64 | 56 | FrameExporter* frameExporter; |
65 | 57 | |
58 | RLogMill* logmill; | |
59 | bool shutdown; | |
60 | ||
66 | 61 | RCommitLog* commitlog; |
67 | 62 | PositionSlider slider; |
68 | 63 | ZoomCamera camera; |
84 | 79 | bool mouseclicked; |
85 | 80 | bool mousedragged; |
86 | 81 | |
87 | vec2f cursor_move; | |
82 | vec2 cursor_move; | |
88 | 83 | |
89 | 84 | bool recolour; |
90 | 85 | |
95 | 90 | |
96 | 91 | float rotate_angle; |
97 | 92 | |
98 | vec2f mousepos; | |
93 | vec2 mousepos; | |
99 | 94 | |
100 | 95 | float last_percent; |
101 | 96 | |
142 | 137 | FXFont font, fontlarge, fontmedium; |
143 | 138 | |
144 | 139 | bool first_read; |
145 | bool draw_loading; | |
146 | 140 | bool paused; |
147 | 141 | |
148 | 142 | float max_tick_rate; |
182 | 176 | Bounds2D user_bounds; |
183 | 177 | Bounds2D active_user_bounds; |
184 | 178 | |
179 | int commitqueue_max_size; | |
180 | ||
185 | 181 | std::deque<RCommit> commitqueue; |
186 | 182 | std::map<std::string, RUser*> users; |
187 | 183 | std::map<std::string, RFile*> files; |
195 | 191 | float message_timer; |
196 | 192 | |
197 | 193 | void setMessage(const char* str, ...); |
198 | ||
194 | ||
199 | 195 | void reset(); |
200 | 196 | |
201 | 197 | RUser* addUser(const std::string& username); |
211 | 207 | |
212 | 208 | void readLog(); |
213 | 209 | |
210 | void logReadingError(const std::string& error); | |
211 | ||
214 | 212 | void processCommit(RCommit& commit, float t); |
215 | 213 | void addFileAction(const std::string& username, const std::string& action, RFile* file, float t); |
216 | 214 | |
218 | 216 | |
219 | 217 | void toggleCameraMode(); |
220 | 218 | |
221 | static RCommitLog* determineFormat(const std::string& logfile); | |
222 | ||
223 | 219 | void updateCamera(float dt); |
224 | 220 | |
225 | 221 | void updateUsers(float t, float dt); |
243 | 239 | void drawBackground(float dt); |
244 | 240 | |
245 | 241 | void drawScene(float dt); |
246 | ||
242 | ||
247 | 243 | void updateVBOs(float dt); |
248 | 244 | |
249 | 245 | void updateAndDrawEdges(); |
250 | ||
246 | ||
251 | 247 | void drawFileShadows(float dt); |
252 | 248 | void drawUserShadows(float dt); |
253 | 249 | void drawActions(float dt); |
270 | 266 | |
271 | 267 | void showSplash(); |
272 | 268 | |
269 | bool isBusy(); | |
270 | ||
273 | 271 | void logic(float t, float dt); |
274 | 272 | void draw(float t, float dt); |
275 | 273 | |
276 | 274 | void init(); |
275 | ||
276 | void unload(); | |
277 | void reload(); | |
278 | ||
279 | void quit(); | |
280 | ||
277 | 281 | void update(float t, float dt); |
278 | 282 | void keyPress(SDL_KeyboardEvent *e); |
279 | 283 | void mouseMove(SDL_MouseMotionEvent *e); |
280 | 284 | void mouseClick(SDL_MouseButtonEvent *e); |
285 | #if SDL_VERSION_ATLEAST(1,3,0) | |
286 | void mouseWheel(SDL_MouseWheelEvent *e); | |
287 | #endif | |
281 | 288 | }; |
282 | 289 | |
283 | 290 | #endif |
50 | 50 | printf(" --disable-auto-skip Disable auto skip\n"); |
51 | 51 | printf(" -s, --seconds-per-day SECONDS Speed in seconds per day (default: 10)\n"); |
52 | 52 | printf(" --realtime Realtime playback speed\n"); |
53 | printf(" -c, --time-scale SCALE Change simuation time scale (default: 1.0)\n"); | |
53 | printf(" -c, --time-scale SCALE Change simulation time scale (default: 1.0)\n"); | |
54 | 54 | printf(" -e, --elasticity FLOAT Elasticity of nodes\n\n"); |
55 | 55 | |
56 | 56 | printf(" --key Show file extension key\n\n"); |
92 | 92 | |
93 | 93 | printf(" --date-format FORMAT Specify display date string (strftime format)\n\n"); |
94 | 94 | |
95 | printf(" --font-size SIZE Font size\n"); | |
96 | printf(" --font-colour FFFFFF Font colour in hex\n\n"); | |
95 | printf(" --font-size SIZE Font size used by date and title\n"); | |
96 | printf(" --font-colour FFFFFF Font colour used by date and title in hex\n\n"); | |
97 | 97 | |
98 | 98 | printf(" --file-extensions Show filename extensions only\n\n"); |
99 | 99 | |
112 | 112 | printf(" --user-filter REGEX Ignore usernames matching this regex\n"); |
113 | 113 | printf(" --file-filter REGEX Ignore files matching this regex\n\n"); |
114 | 114 | |
115 | printf(" --user-friction SECONDS Time users come to a complete hault (default: 0.67)\n"); | |
115 | printf(" --user-friction SECONDS Change the rate users slow down (default: 0.67)\n"); | |
116 | 116 | printf(" --user-scale SCALE Change scale of users (default: 1.0)\n"); |
117 | 117 | printf(" --max-user-speed UNITS Speed users can travel per second (default: 500)\n\n"); |
118 | 118 | |
119 | 119 | printf(" --follow-user USER Camera will automatically follow this user\n"); |
120 | printf(" --highlight-dirs Highlight the names of all directories\n"); | |
120 | 121 | printf(" --highlight-user USER Highlight the names of a particular user\n"); |
121 | 122 | printf(" --highlight-users Highlight the names of all users\n\n"); |
122 | printf(" --highlight-dirs Highlight the names of all directories\n"); | |
123 | printf(" --highlight-colour Font colour for highlighted text\n\n"); | |
123 | printf(" --highlight-colour Font colour for highlighted users in hex.\n"); | |
124 | printf(" --selection-colour Font colour for selected users and files.\n"); | |
125 | printf(" --dir-colour Font colour for directories.\n\n"); | |
124 | 126 | |
125 | 127 | printf(" --hash-seed SEED Change the seed of hash function\n\n"); |
126 | 128 | |
136 | 138 | } |
137 | 139 | |
138 | 140 | #ifdef _WIN32 |
139 | printf("Press Enter\n"); | |
140 | getchar(); | |
141 | if(gSDLAppConsoleWindow) { | |
142 | printf("Press Enter\n"); | |
143 | getchar(); | |
144 | } | |
141 | 145 | #endif |
142 | 146 | |
143 | 147 | exit(0); |
181 | 185 | conf_sections["load-config"] = "command-line"; |
182 | 186 | conf_sections["save-config"] = "command-line"; |
183 | 187 | conf_sections["output-custom-log"] = "command-line"; |
188 | conf_sections["log-level"] = "command-line"; | |
184 | 189 | |
185 | 190 | //boolean args |
186 | 191 | arg_types["help"] = "bool"; |
238 | 243 | arg_types["follow-user"] = "multi-value"; |
239 | 244 | arg_types["highlight-user"] = "multi-value"; |
240 | 245 | |
246 | arg_types["log-level"] = "string"; | |
241 | 247 | arg_types["background-image"] = "string"; |
242 | 248 | arg_types["logo"] = "string"; |
243 | 249 | arg_types["logo-offset"] = "string"; |
264 | 270 | arg_types["title"] = "string"; |
265 | 271 | arg_types["font-colour"] = "string"; |
266 | 272 | arg_types["highlight-colour"] = "string"; |
273 | arg_types["selection-colour"] = "string"; | |
274 | arg_types["dir-colour"] = "string"; | |
275 | ||
267 | 276 | } |
268 | 277 | |
269 | 278 | void GourceSettings::setGourceDefaults() { |
303 | 312 | loop = false; |
304 | 313 | |
305 | 314 | logo = ""; |
306 | logo_offset = vec2f(20.0f,20.0f); | |
315 | logo_offset = vec2(20.0f,20.0f); | |
307 | 316 | |
308 | 317 | colour_user_images = false; |
309 | 318 | default_user_image = ""; |
310 | 319 | user_image_dir = ""; |
311 | 320 | user_image_map.clear(); |
312 | 321 | |
322 | camera_zoom_min = 50.0f; | |
323 | camera_zoom_default = 100.0f; | |
324 | camera_zoom_max = 10000.0f; | |
325 | ||
313 | 326 | camera_mode = "overview"; |
314 | 327 | padding = 1.1f; |
315 | 328 | |
319 | 332 | bloom_multiplier = 1.0f; |
320 | 333 | bloom_intensity = 0.75f; |
321 | 334 | |
322 | background_colour = vec3f(0.1f, 0.1f, 0.1f); | |
335 | background_colour = vec3(0.1f, 0.1f, 0.1f); | |
323 | 336 | background_image = ""; |
324 | 337 | |
325 | 338 | title = ""; |
326 | 339 | |
327 | 340 | font_size = 16; |
328 | font_colour = vec3f(1.0f, 1.0f, 1.0f); | |
329 | highlight_colour = vec3f(1.0f, 1.0f, 0.3f); | |
341 | dir_colour = vec3(1.0f); | |
342 | font_colour = vec3(1.0f); | |
343 | highlight_colour = vec3(1.0f); | |
344 | selection_colour = vec3(1.0, 1.0, 0.3f); | |
330 | 345 | |
331 | 346 | elasticity = 0.0f; |
332 | 347 | |
350 | 365 | |
351 | 366 | gStringHashSeed = 31; |
352 | 367 | |
368 | log_level = LOG_LEVEL_ERROR; | |
369 | ||
353 | 370 | //delete file filters |
354 | 371 | for(std::vector<Regex*>::iterator it = file_filters.begin(); it != file_filters.end(); it++) { |
355 | 372 | delete (*it); |
422 | 439 | |
423 | 440 | if(name == "output-custom-log" && value.size() > 0) { |
424 | 441 | output_custom_filename = value; |
442 | return; | |
443 | } | |
444 | ||
445 | if(name == "log-level") { | |
446 | if(value == "warn") { | |
447 | log_level = LOG_LEVEL_WARN; | |
448 | } else if(value == "debug") { | |
449 | log_level = LOG_LEVEL_DEBUG; | |
450 | } else if(value == "info") { | |
451 | log_level = LOG_LEVEL_INFO; | |
452 | } else if(value == "error") { | |
453 | log_level = LOG_LEVEL_ERROR; | |
454 | } | |
425 | 455 | return; |
426 | 456 | } |
427 | 457 | |
717 | 747 | if(entry->isVec3()) { |
718 | 748 | font_colour = entry->getVec3(); |
719 | 749 | } else if(colstring.size()==6 && sscanf(colstring.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { |
720 | font_colour = vec3f(r,g,b); | |
750 | font_colour = vec3(r,g,b); | |
721 | 751 | font_colour /= 255.0f; |
722 | 752 | } else { |
723 | 753 | conffile.invalidValueException(entry); |
735 | 765 | if(entry->isVec3()) { |
736 | 766 | background_colour = entry->getVec3(); |
737 | 767 | } else if(colstring.size()==6 && sscanf(colstring.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { |
738 | background_colour = vec3f(r,g,b); | |
768 | background_colour = vec3(r,g,b); | |
739 | 769 | background_colour /= 255.0f; |
740 | 770 | } else { |
741 | 771 | conffile.invalidValueException(entry); |
753 | 783 | if(entry->isVec3()) { |
754 | 784 | highlight_colour = entry->getVec3(); |
755 | 785 | } else if(colstring.size()==6 && sscanf(colstring.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { |
756 | highlight_colour = vec3f(r,g,b); | |
786 | highlight_colour = vec3(r,g,b); | |
757 | 787 | highlight_colour /= 255.0f; |
758 | 788 | } else { |
759 | 789 | conffile.invalidValueException(entry); |
760 | 790 | } |
761 | 791 | } |
792 | ||
793 | if((entry = gource_settings->getEntry("selection-colour")) != 0) { | |
794 | ||
795 | if(!entry->hasValue()) conffile.entryException(entry, "specify selection colour (FFFFFF)"); | |
796 | ||
797 | int r,g,b; | |
798 | ||
799 | std::string colstring = entry->getString(); | |
800 | ||
801 | if(entry->isVec3()) { | |
802 | selection_colour = entry->getVec3(); | |
803 | } else if(colstring.size()==6 && sscanf(colstring.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { | |
804 | selection_colour = vec3(r,g,b); | |
805 | selection_colour /= 255.0f; | |
806 | } else { | |
807 | conffile.invalidValueException(entry); | |
808 | } | |
809 | } | |
810 | ||
811 | if((entry = gource_settings->getEntry("dir-colour")) != 0) { | |
812 | ||
813 | if(!entry->hasValue()) conffile.entryException(entry, "specify dir colour (FFFFFF)"); | |
814 | ||
815 | int r,g,b; | |
816 | ||
817 | std::string colstring = entry->getString(); | |
818 | ||
819 | if(entry->isVec3()) { | |
820 | dir_colour = entry->getVec3(); | |
821 | } else if(colstring.size()==6 && sscanf(colstring.c_str(), "%02x%02x%02x", &r, &g, &b) == 3) { | |
822 | dir_colour = vec3(r,g,b); | |
823 | dir_colour /= 255.0f; | |
824 | } else { | |
825 | conffile.invalidValueException(entry); | |
826 | } | |
827 | } | |
762 | 828 | |
763 | 829 | if((entry = gource_settings->getEntry("background-image")) != 0) { |
764 | 830 | |
790 | 856 | int posx = 0; |
791 | 857 | int posy = 0; |
792 | 858 | |
793 | if(parseRectangle(logo_offset_str, &posx, &posy)) { | |
794 | logo_offset = vec2f(posx, posy); | |
859 | if(parseRectangle(logo_offset_str, posx, posy)) { | |
860 | logo_offset = vec2(posx, posy); | |
795 | 861 | } else { |
796 | 862 | conffile.invalidValueException(entry); |
797 | 863 | } |
1093 | 1159 | } |
1094 | 1160 | } |
1095 | 1161 | |
1096 | ||
1097 | ||
1098 | ||
1099 | 1162 | //validate path |
1100 | 1163 | if(gource_settings->hasValue("path")) { |
1101 | 1164 | path = gource_settings->getString("path"); |
17 | 17 | #ifndef GOURCE_SETTINGS_H |
18 | 18 | #define GOURCE_SETTINGS_H |
19 | 19 | |
20 | #define GOURCE_VERSION "0.37" | |
20 | #define GOURCE_VERSION "0.38" | |
21 | 21 | |
22 | 22 | #include <dirent.h> |
23 | 23 | |
24 | #include "hg.h" | |
25 | #include "git.h" | |
26 | #include "bzr.h" | |
27 | #include "cvs-exp.h" | |
28 | #include "cvs2cl.h" | |
29 | #include "svn.h" | |
24 | #include "formats/hg.h" | |
25 | #include "formats/git.h" | |
26 | #include "formats/bzr.h" | |
27 | #include "formats/cvs-exp.h" | |
28 | #include "formats/cvs2cl.h" | |
29 | #include "formats/svn.h" | |
30 | 30 | |
31 | 31 | #include "core/settings.h" |
32 | 32 | #include "core/regex.h" |
58 | 58 | std::string path; |
59 | 59 | |
60 | 60 | std::string logo; |
61 | vec2f logo_offset; | |
61 | vec2 logo_offset; | |
62 | 62 | |
63 | 63 | float start_position; |
64 | 64 | float stop_position; |
81 | 81 | std::string user_image_dir; |
82 | 82 | std::map<std::string, std::string> user_image_map; |
83 | 83 | |
84 | float camera_zoom_min; | |
85 | float camera_zoom_max; | |
86 | float camera_zoom_default; | |
87 | ||
84 | 88 | std::string camera_mode; |
85 | 89 | float padding; |
86 | 90 | |
90 | 94 | float bloom_multiplier; |
91 | 95 | float bloom_intensity; |
92 | 96 | |
93 | vec3f background_colour; | |
97 | vec3 background_colour; | |
94 | 98 | std::string background_image; |
95 | 99 | |
96 | 100 | std::string title; |
97 | 101 | |
98 | 102 | int font_size; |
99 | vec3f font_colour; | |
103 | vec3 font_colour; | |
100 | 104 | |
101 | 105 | float elasticity; |
102 | 106 | |
116 | 120 | |
117 | 121 | bool highlight_dirs; |
118 | 122 | bool highlight_all_users; |
119 | vec3f highlight_colour; | |
120 | 123 | |
124 | vec3 dir_colour; | |
125 | vec3 highlight_colour; | |
126 | vec3 selection_colour; | |
127 | ||
121 | 128 | std::vector<std::string> highlight_users; |
122 | 129 | std::vector<std::string> follow_users; |
123 | 130 | std::vector<Regex*> file_filters; |
127 | 134 | std::string output_custom_filename; |
128 | 135 | |
129 | 136 | TextureResource* file_graphic; |
137 | ||
138 | int log_level; | |
130 | 139 | |
131 | 140 | GourceSettings(); |
132 | 141 |
16 | 16 | |
17 | 17 | #include "gource_shell.h" |
18 | 18 | |
19 | GourceShell* gGourceShell = 0; | |
20 | ||
19 | 21 | // GourceShell |
20 | 22 | |
21 | 23 | GourceShell::GourceShell(ConfFile* conf, FrameExporter* exporter) { |
23 | 25 | this->conf = conf; |
24 | 26 | this->exporter = exporter; |
25 | 27 | |
28 | min_delta_msec = 16; | |
29 | ||
26 | 30 | next = false; |
27 | 31 | |
32 | shutdown = false; | |
33 | ||
28 | 34 | gource = 0; |
29 | 35 | gource_settings = conf->getSections("gource")->begin(); |
30 | 36 | |
34 | 40 | transition_interval = 0.0f; |
35 | 41 | |
36 | 42 | if(strstr((const char *)glGetString(GL_EXTENSIONS), "GL_ARB_texture_non_power_of_two" )) { |
37 | transition_texture = display.emptyTexture(display.width, display.height, GL_RGBA); | |
38 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | |
39 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | |
43 | ||
44 | transition_texture = texturemanager.create(display.width, display.height, false, GL_CLAMP_TO_EDGE, GL_RGBA); | |
40 | 45 | } |
41 | 46 | } |
42 | 47 | |
43 | 48 | GourceShell::~GourceShell() { |
44 | 49 | if(gource!=0) delete gource; |
45 | if(transition_texture!=0) glDeleteTextures(1, &transition_texture); | |
50 | if(transition_texture!=0) texturemanager.release(transition_texture); | |
51 | } | |
52 | ||
53 | void GourceShell::toggleFullscreen() { | |
54 | ||
55 | if(exporter != 0) return; | |
56 | ||
57 | texturemanager.unload(); | |
58 | shadermanager.unload(); | |
59 | fontmanager.unload(); | |
60 | ||
61 | if(gource!=0) gource->unload(); | |
62 | ||
63 | //recreate gl context | |
64 | display.toggleFullscreen(); | |
65 | ||
66 | texturemanager.reload(); | |
67 | shadermanager.reload(); | |
68 | fontmanager.reload(); | |
69 | ||
70 | if(gource!=0) gource->reload(); | |
71 | } | |
72 | ||
73 | void GourceShell::resize(int width, int height) { | |
74 | ||
75 | texturemanager.unload(); | |
76 | shadermanager.unload(); | |
77 | fontmanager.unload(); | |
78 | ||
79 | if(gource!=0) gource->unload(); | |
80 | ||
81 | //recreate gl context | |
82 | display.resize(width, height); | |
83 | ||
84 | texturemanager.reload(); | |
85 | shadermanager.reload(); | |
86 | fontmanager.reload(); | |
87 | ||
88 | if(gource!=0) gource->reload(); | |
46 | 89 | } |
47 | 90 | |
48 | 91 | void GourceShell::keyPress(SDL_KeyboardEvent *e) { |
49 | 92 | |
50 | 93 | //Quit demo if the user presses ESC |
51 | 94 | if (e->type == SDL_KEYDOWN) { |
52 | if (e->keysym.unicode == SDLK_ESCAPE) { | |
53 | appFinished=true; | |
54 | } | |
55 | ||
56 | if (e->keysym.unicode == SDLK_RETURN) { | |
57 | if(gGourceSettings.repo_count>1) | |
58 | next = true; | |
59 | } | |
60 | ||
95 | ||
96 | #if SDL_VERSION_ATLEAST(1,3,0) | |
97 | bool key_escape = e->keysym.scancode == SDL_SCANCODE_ESCAPE; | |
98 | bool key_return = e->keysym.scancode == SDL_SCANCODE_RETURN; | |
99 | #else | |
100 | bool key_escape = e->keysym.unicode == SDLK_ESCAPE; | |
101 | bool key_return = e->keysym.unicode == SDLK_RETURN; | |
102 | #endif | |
103 | ||
104 | if (key_escape) { | |
105 | quit(); | |
106 | } | |
107 | ||
108 | if(key_return) { | |
109 | ||
110 | #if SDL_VERSION_ATLEAST(1,3,0) | |
111 | Uint8* keystate = SDL_GetKeyboardState(NULL); | |
112 | if(keystate[SDL_SCANCODE_RALT] || keystate[SDL_SCANCODE_LALT]) { | |
113 | #else | |
114 | Uint8* keystate = SDL_GetKeyState(NULL); | |
115 | if(keystate[SDLK_RALT] || keystate[SDLK_LALT]) { | |
116 | #endif | |
117 | ||
118 | toggleFullscreen(); | |
119 | ||
120 | } else { | |
121 | if(gGourceSettings.repo_count>1) | |
122 | next = true; | |
123 | } | |
124 | } | |
61 | 125 | } |
62 | 126 | |
63 | 127 | if(gource!=0) gource->keyPress(e); |
67 | 131 | if(gource!=0) gource->mouseMove(e); |
68 | 132 | } |
69 | 133 | |
134 | #if SDL_VERSION_ATLEAST(1,3,0) | |
135 | void GourceShell::mouseWheel(SDL_MouseWheelEvent *e) { | |
136 | if(gource!=0) gource->mouseWheel(e); | |
137 | } | |
138 | #endif | |
139 | ||
70 | 140 | void GourceShell::mouseClick(SDL_MouseButtonEvent *e) { |
71 | 141 | if(gource!=0) gource->mouseClick(e); |
72 | 142 | } |
73 | 143 | |
144 | void GourceShell::quit() { | |
145 | if(gource!=0) gource->quit(); | |
146 | shutdown=true; | |
147 | } | |
148 | ||
74 | 149 | Gource* GourceShell::getNext() { |
75 | 150 | |
76 | 151 | if(gource!=0) { |
77 | delete gource; | |
78 | gource = 0; | |
79 | ||
80 | 152 | transition_interval = 1.0f; |
81 | 153 | } |
82 | ||
83 | if(gource_settings == conf->getSections("gource")->end()) { | |
154 | ||
155 | if(shutdown || gource_settings == conf->getSections("gource")->end()) { | |
156 | ||
157 | // if we are done, delete gource and replace it with nothing | |
158 | if(gource != 0) { | |
159 | Gource* gource_tmp = gource; | |
160 | gource = 0; | |
161 | delete gource_tmp; | |
162 | } | |
163 | ||
84 | 164 | return 0; |
85 | 165 | } |
86 | 166 | |
111 | 191 | } |
112 | 192 | } |
113 | 193 | |
114 | Gource* gource = new Gource(exporter); | |
115 | ||
194 | // replace gource | |
195 | ||
196 | Gource* gource_tmp = gource; | |
197 | gource = new Gource(exporter); | |
198 | delete gource_tmp; | |
199 | ||
116 | 200 | next = false; |
117 | ||
201 | ||
118 | 202 | return gource; |
119 | 203 | } |
120 | 204 | |
127 | 211 | glEnable(GL_BLEND); |
128 | 212 | glEnable(GL_TEXTURE_2D); |
129 | 213 | |
130 | glBindTexture(GL_TEXTURE_2D, transition_texture); | |
214 | transition_texture->bind(); | |
131 | 215 | |
132 | 216 | glColor4f(1.0, 1.0, 1.0, transition_interval); |
133 | 217 | |
151 | 235 | void GourceShell::update(float t, float dt) { |
152 | 236 | |
153 | 237 | if(gource == 0 || gource->isFinished()) { |
154 | gource = getNext(); | |
155 | ||
156 | if(gource==0) appFinished=true; | |
238 | if(!getNext()) appFinished=true; | |
239 | ||
157 | 240 | return; |
158 | 241 | } |
159 | 242 | |
162 | 245 | |
163 | 246 | //copy last frame |
164 | 247 | if( (next|| gource->isFinished()) && transition_texture!=0) { |
165 | display.renderToTexture(transition_texture, display.width, display.height, GL_RGBA); | |
248 | ||
249 | glEnable(GL_TEXTURE_2D); | |
250 | transition_texture->bind(); | |
251 | glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, display.width, display.height, 0); | |
252 | ||
166 | 253 | } else { |
167 | 254 | //blend last frame of previous scene |
168 | 255 | blendLastFrame(dt); |
25 | 25 | |
26 | 26 | Gource* gource; |
27 | 27 | |
28 | bool shutdown; | |
28 | 29 | bool next; |
29 | 30 | |
30 | GLuint transition_texture; | |
31 | TextureResource* transition_texture; | |
31 | 32 | float transition_interval; |
32 | 33 | |
33 | 34 | FrameExporter* exporter; |
42 | 43 | |
43 | 44 | void update(float t, float dt); |
44 | 45 | |
46 | void resize(int width, int height); | |
47 | ||
48 | void toggleFullscreen(); | |
49 | ||
50 | void quit(); | |
51 | ||
45 | 52 | void keyPress(SDL_KeyboardEvent *e); |
46 | 53 | void mouseMove(SDL_MouseMotionEvent *e); |
47 | 54 | void mouseClick(SDL_MouseButtonEvent *e); |
48 | ||
55 | #if SDL_VERSION_ATLEAST(1,3,0) | |
56 | void mouseWheel(SDL_MouseWheelEvent *e); | |
57 | #endif | |
49 | 58 | }; |
50 | 59 | |
51 | 60 | #endif |
61 | ||
62 | extern GourceShell* gGourceShell; |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "hg.h" | |
18 | ||
19 | Regex hg_regex("^([0-9]+) -?[0-9]+\\|([^|]+)\\|([ADM]?)\\|(.+)$"); | |
20 | ||
21 | // parse Mercurial log entries (using the gource.style template) | |
22 | ||
23 | std::string gGourceMercurialCommand() { | |
24 | ||
25 | std::string gource_style_path = gSDLAppResourceDir + std::string("gource.style"); | |
26 | ||
27 | return std::string("hg log -r 0:tip --style \"") + gource_style_path + std::string("\""); | |
28 | } | |
29 | ||
30 | MercurialLog::MercurialLog(const std::string& logfile) : RCommitLog(logfile) { | |
31 | ||
32 | log_command = gGourceMercurialCommand(); | |
33 | ||
34 | //can generate log from directory | |
35 | if(!logf && is_dir) { | |
36 | logf = generateLog(logfile); | |
37 | ||
38 | if(logf) { | |
39 | success = true; | |
40 | seekable = true; | |
41 | } | |
42 | } | |
43 | } | |
44 | ||
45 | BaseLog* MercurialLog::generateLog(const std::string& dir) { | |
46 | ||
47 | //does directory have a .hg ? | |
48 | std::string hgdir = dir + std::string("/.hg"); | |
49 | struct stat dirinfo; | |
50 | int stat_rc = stat(hgdir.c_str(), &dirinfo); | |
51 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
52 | return 0; | |
53 | } | |
54 | ||
55 | std::string command = getLogCommand(); | |
56 | ||
57 | createTempLog(); | |
58 | ||
59 | if(temp_file.size()==0) return 0; | |
60 | ||
61 | char cmd_buff[2048]; | |
62 | sprintf(cmd_buff, "%s -R \"%s\" > %s", command.c_str(), dir.c_str(), temp_file.c_str()); | |
63 | ||
64 | int command_rc = system(cmd_buff); | |
65 | ||
66 | if(command_rc != 0) { | |
67 | return 0; | |
68 | } | |
69 | ||
70 | BaseLog* seeklog = new SeekLog(temp_file); | |
71 | ||
72 | return seeklog; | |
73 | } | |
74 | ||
75 | ||
76 | bool MercurialLog::parseCommit(RCommit& commit) { | |
77 | ||
78 | while(parseCommitEntry(commit)); | |
79 | ||
80 | return !commit.files.empty(); | |
81 | } | |
82 | ||
83 | bool MercurialLog::parseCommitEntry(RCommit& commit) { | |
84 | ||
85 | std::string line; | |
86 | std::vector<std::string> entries; | |
87 | ||
88 | if(!logf->getNextLine(line)) return false; | |
89 | ||
90 | //custom line | |
91 | if(!hg_regex.match(line, &entries)) return false; | |
92 | ||
93 | time_t timestamp = atol(entries[0].c_str()); | |
94 | std::string username = entries[1]; | |
95 | ||
96 | //if this file is for the same person and timestamp | |
97 | //we add to the commit, else we save the lastline | |
98 | //and return false | |
99 | if(commit.files.empty()) { | |
100 | commit.timestamp = timestamp; | |
101 | commit.username = username; | |
102 | } else { | |
103 | if(commit.timestamp != timestamp || commit.username != username) { | |
104 | lastline = line; | |
105 | return false; | |
106 | } | |
107 | } | |
108 | ||
109 | std::string action = "A"; | |
110 | ||
111 | if(!entries[2].empty()) { | |
112 | action = entries[2]; | |
113 | } | |
114 | ||
115 | commit.addFile(entries[3], action); | |
116 | ||
117 | //commit.debug(); | |
118 | ||
119 | return true; | |
120 | } |
0 | /* | |
1 | Copyright (C) 2009 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef MERCURIALLOG_H | |
18 | #define MERCURIALLOG_H | |
19 | ||
20 | #include "commitlog.h" | |
21 | ||
22 | std::string gGourceMercurialCommand(); | |
23 | ||
24 | class MercurialLog : public RCommitLog { | |
25 | protected: | |
26 | bool parseCommit(RCommit& commit); | |
27 | bool parseCommitEntry(RCommit& commit); | |
28 | BaseLog* generateLog(const std::string& dir); | |
29 | public: | |
30 | MercurialLog(const std::string& logfile); | |
31 | }; | |
32 | ||
33 | #endif⏎ |
3 | 3 | // File Key Entry |
4 | 4 | // a string for the file ext and a colour |
5 | 5 | |
6 | FileKeyEntry::FileKeyEntry(const FXFont& font, const std::string& ext, const vec3f& colour) { | |
6 | FileKeyEntry::FileKeyEntry(const FXFont& font, const std::string& ext, const vec3& colour) { | |
7 | 7 | this->ext = ext; |
8 | 8 | this->colour = colour; |
9 | 9 | this->pos_y = -1.0f; |
11 | 11 | this->font = font; |
12 | 12 | this->font.dropShadow(false); |
13 | 13 | |
14 | shadow = vec2f(3.0, 3.0); | |
14 | shadow = vec2(3.0, 3.0); | |
15 | 15 | |
16 | 16 | width = 90.0f; |
17 | 17 | height = 18.0f; |
27 | 27 | show = true; |
28 | 28 | |
29 | 29 | display_ext = ext; |
30 | ||
30 | ||
31 | 31 | bool truncated = false; |
32 | ||
32 | ||
33 | 33 | while(font.getWidth(display_ext) > width - 15.0f) { |
34 | 34 | display_ext.resize(display_ext.size()-1); |
35 | 35 | truncated = true; |
36 | 36 | } |
37 | ||
37 | ||
38 | 38 | if(truncated) { |
39 | 39 | display_ext += std::string("..."); |
40 | 40 | } |
41 | 41 | } |
42 | 42 | |
43 | const vec3f& FileKeyEntry::getColour() const { | |
43 | const vec3& FileKeyEntry::getColour() const { | |
44 | 44 | return colour; |
45 | 45 | } |
46 | 46 | |
57 | 57 | } |
58 | 58 | |
59 | 59 | void FileKeyEntry::colourize() { |
60 | colour = ext.empty() ? vec3f(1.0f, 1.0f, 1.0f) : colourHash(ext); | |
60 | colour = ext.empty() ? vec3(1.0f, 1.0f, 1.0f) : colourHash(ext); | |
61 | 61 | } |
62 | 62 | |
63 | 63 | void FileKeyEntry::inc() { |
106 | 106 | } |
107 | 107 | } |
108 | 108 | |
109 | pos = vec2f(alpha * left_margin, pos_y); | |
109 | pos = vec2(alpha * left_margin, pos_y); | |
110 | 110 | } |
111 | 111 | |
112 | 112 | void FileKeyEntry::draw() { |
141 | 141 | |
142 | 142 | glEnable(GL_TEXTURE_2D); |
143 | 143 | |
144 | font.setColour(vec4f(1.0f, 1.0f, 1.0f, alpha)); | |
144 | font.setColour(vec4(1.0f, 1.0f, 1.0f, alpha)); | |
145 | 145 | |
146 | 146 | font.dropShadow(false); |
147 | 147 | font.draw((int)pos.x+2, (int)pos.y+3, display_ext.c_str()); |
272 | 272 | std::sort(active_keys.begin(), active_keys.end(), file_key_entry_sort); |
273 | 273 | |
274 | 274 | //limit to entries we can put onto the screen |
275 | int max_visible_entries = (display.height - 150.0f) / 20.0f; | |
275 | int max_visible_entries = std::max(0, (int)((display.height - 150.0f) / 20.0f)); | |
276 | 276 | |
277 | 277 | if (active_keys.size() > max_visible_entries) { |
278 | 278 | active_keys.resize(max_visible_entries); |
28 | 28 | |
29 | 29 | class FileKeyEntry { |
30 | 30 | FXFont font; |
31 | vec3f colour; | |
31 | vec3 colour; | |
32 | 32 | std::string ext; |
33 | 33 | std::string display_ext; |
34 | 34 | float alpha; |
41 | 41 | float left_margin; |
42 | 42 | float width; |
43 | 43 | float height; |
44 | vec2f pos; | |
45 | vec2f shadow; | |
44 | vec2 pos; | |
45 | vec2 shadow; | |
46 | 46 | bool show; |
47 | 47 | public: |
48 | FileKeyEntry(const FXFont& font, const std::string& ext, const vec3f& colour); | |
48 | FileKeyEntry(const FXFont& font, const std::string& ext, const vec3& colour); | |
49 | 49 | |
50 | const vec3f& getColour() const; | |
50 | const vec3& getColour() const; | |
51 | 51 | const std::string& getExt() const; |
52 | 52 | |
53 | 53 | void setDestY(float dest_y); |
0 | /* | |
1 | Copyright (C) 2012 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "logmill.h" | |
18 | #include "gource_settings.h" | |
19 | ||
20 | #include "formats/git.h" | |
21 | #include "formats/gitraw.h" | |
22 | #include "formats/custom.h" | |
23 | #include "formats/hg.h" | |
24 | #include "formats/bzr.h" | |
25 | #include "formats/svn.h" | |
26 | #include "formats/apache.h" | |
27 | ||
28 | extern "C" { | |
29 | ||
30 | static int logmill_thread(void *lmill) { | |
31 | ||
32 | RLogMill *logmill = static_cast<RLogMill*> (lmill); | |
33 | logmill->run(); | |
34 | ||
35 | return 0; | |
36 | } | |
37 | ||
38 | }; | |
39 | ||
40 | RLogMill::RLogMill(const std::string& logfile) | |
41 | : logfile(logfile) { | |
42 | ||
43 | logmill_thread_state = LOGMILL_STATE_STARTUP; | |
44 | clog = 0; | |
45 | ||
46 | #if SDL_VERSION_ATLEAST(1,3,0) | |
47 | thread = SDL_CreateThread( logmill_thread, "logmill", this ); | |
48 | #else | |
49 | thread = SDL_CreateThread( logmill_thread, this ); | |
50 | #endif | |
51 | } | |
52 | ||
53 | RLogMill::~RLogMill() { | |
54 | ||
55 | abort(); | |
56 | ||
57 | if(thread) SDL_KillThread(thread); | |
58 | if(clog) delete clog; | |
59 | } | |
60 | ||
61 | void RLogMill::run() { | |
62 | logmill_thread_state = LOGMILL_STATE_FETCHING; | |
63 | ||
64 | #if defined(HAVE_PTHREAD) && !defined(_WIN32) | |
65 | sigset_t mask; | |
66 | sigemptyset(&mask); | |
67 | ||
68 | // unblock SIGINT so user can cancel | |
69 | // NOTE: assumes SDL is using pthreads | |
70 | ||
71 | sigaddset(&mask, SIGINT); | |
72 | pthread_sigmask(SIG_UNBLOCK, &mask, 0); | |
73 | #endif | |
74 | ||
75 | std::string log_format = gGourceSettings.log_format; | |
76 | ||
77 | try { | |
78 | ||
79 | clog = fetchLog(log_format); | |
80 | ||
81 | } catch(SeekLogException& exception) { | |
82 | error = "unable to read log file"; | |
83 | } catch(SDLAppException& exception) { | |
84 | error = exception.what(); | |
85 | } | |
86 | ||
87 | if(!clog && error.empty()) { | |
88 | if(SDLAppDirExists(logfile)) { | |
89 | if(!log_format.empty()) { | |
90 | error = "failed to generate log file"; | |
91 | } else { | |
92 | error = "directory not supported"; | |
93 | } | |
94 | } else { | |
95 | error = "unsupported log format (you may need to regenerate your log file)"; | |
96 | } | |
97 | } | |
98 | ||
99 | logmill_thread_state = clog ? LOGMILL_STATE_SUCCESS : LOGMILL_STATE_FAILURE; | |
100 | } | |
101 | ||
102 | void RLogMill::abort() { | |
103 | // TODO: make abort nicer by notifying the log process | |
104 | // we want to shutdown | |
105 | ||
106 | while(logmill_thread_state <= LOGMILL_STATE_FETCHING) { | |
107 | SDL_Delay(100); | |
108 | } | |
109 | } | |
110 | ||
111 | bool RLogMill::isFinished() { | |
112 | return logmill_thread_state > LOGMILL_STATE_FETCHING; | |
113 | } | |
114 | ||
115 | int RLogMill::getStatus() { | |
116 | return logmill_thread_state; | |
117 | } | |
118 | ||
119 | std::string RLogMill::getError() { | |
120 | return error; | |
121 | } | |
122 | ||
123 | ||
124 | RCommitLog* RLogMill::getLog() { | |
125 | ||
126 | while(logmill_thread_state <= LOGMILL_STATE_FETCHING) { | |
127 | SDL_Delay(100); | |
128 | } | |
129 | ||
130 | return clog; | |
131 | } | |
132 | ||
133 | bool RLogMill::findRepository(boost::filesystem::path& dir, std::string& log_format) { | |
134 | ||
135 | dir = absolute(dir); | |
136 | ||
137 | //fprintf(stderr, "find repository from initial path: %s\n", dir.string().c_str()); | |
138 | ||
139 | while(is_directory(dir)) { | |
140 | ||
141 | if(is_directory(dir / ".git")) log_format = "git"; | |
142 | else if(is_directory(dir / ".hg")) log_format = "hg"; | |
143 | else if(is_directory(dir / ".bzr")) log_format = "bzr"; | |
144 | else if(is_directory(dir / ".svn")) log_format = "svn"; | |
145 | ||
146 | if(!log_format.empty()) { | |
147 | //fprintf(stderr, "found '%s' repository at: %s\n", log_format.c_str(), dir.string().c_str()); | |
148 | return true; | |
149 | } | |
150 | ||
151 | if(!dir.has_parent_path()) return false; | |
152 | ||
153 | dir = dir.parent_path(); | |
154 | } | |
155 | ||
156 | return false; | |
157 | } | |
158 | ||
159 | ||
160 | RCommitLog* RLogMill::fetchLog(std::string& log_format) { | |
161 | ||
162 | RCommitLog* clog = 0; | |
163 | ||
164 | //if the log format is not specified and 'logfile' is a directory, recursively look for a version control repository. | |
165 | //this method allows for something strange like someone who having an svn repository inside a git repository | |
166 | //(in which case it would pick the svn directory as it would encounter that first) | |
167 | ||
168 | if(log_format.empty() && logfile != "-") { | |
169 | ||
170 | try { | |
171 | boost::filesystem::path repo_path(logfile); | |
172 | ||
173 | if(is_directory(repo_path)) { | |
174 | if(findRepository(repo_path, log_format)) { | |
175 | logfile = repo_path.string(); | |
176 | } | |
177 | } | |
178 | } catch(boost::filesystem3::filesystem_error& error) { | |
179 | } | |
180 | } | |
181 | ||
182 | //we've been told what format to use | |
183 | if(log_format.size() > 0) { | |
184 | debugLog("log-format = %s", log_format.c_str()); | |
185 | ||
186 | if(log_format == "git") { | |
187 | clog = new GitCommitLog(logfile); | |
188 | if(clog->checkFormat()) return clog; | |
189 | delete clog; | |
190 | ||
191 | clog = new GitRawCommitLog(logfile); | |
192 | if(clog->checkFormat()) return clog; | |
193 | delete clog; | |
194 | } | |
195 | ||
196 | if(log_format == "hg") { | |
197 | clog = new MercurialLog(logfile); | |
198 | if(clog->checkFormat()) return clog; | |
199 | delete clog; | |
200 | } | |
201 | ||
202 | if(log_format == "bzr") { | |
203 | clog = new BazaarLog(logfile); | |
204 | if(clog->checkFormat()) return clog; | |
205 | delete clog; | |
206 | } | |
207 | ||
208 | if(log_format == "cvs") { | |
209 | clog = new CVSEXPCommitLog(logfile); | |
210 | if(clog->checkFormat()) return clog; | |
211 | delete clog; | |
212 | } | |
213 | ||
214 | if(log_format == "custom") { | |
215 | clog = new CustomLog(logfile); | |
216 | if(clog->checkFormat()) return clog; | |
217 | delete clog; | |
218 | } | |
219 | ||
220 | if(log_format == "apache") { | |
221 | clog = new ApacheCombinedLog(logfile); | |
222 | if(clog->checkFormat()) return clog; | |
223 | delete clog; | |
224 | } | |
225 | ||
226 | if(log_format == "svn") { | |
227 | clog = new SVNCommitLog(logfile); | |
228 | if(clog->checkFormat()) return clog; | |
229 | delete clog; | |
230 | } | |
231 | ||
232 | if(log_format == "cvs2cl") { | |
233 | clog = new CVS2CLCommitLog(logfile); | |
234 | if(clog->checkFormat()) return clog; | |
235 | delete clog; | |
236 | } | |
237 | ||
238 | return 0; | |
239 | } | |
240 | ||
241 | // try different formats until one works | |
242 | ||
243 | //git | |
244 | debugLog("trying git..."); | |
245 | clog = new GitCommitLog(logfile); | |
246 | if(clog->checkFormat()) return clog; | |
247 | ||
248 | delete clog; | |
249 | ||
250 | //mercurial | |
251 | debugLog("trying mercurial..."); | |
252 | clog = new MercurialLog(logfile); | |
253 | if(clog->checkFormat()) return clog; | |
254 | ||
255 | delete clog; | |
256 | ||
257 | //bzr | |
258 | debugLog("trying bzr..."); | |
259 | clog = new BazaarLog(logfile); | |
260 | if(clog->checkFormat()) return clog; | |
261 | ||
262 | delete clog; | |
263 | ||
264 | //git raw | |
265 | debugLog("trying git raw..."); | |
266 | clog = new GitRawCommitLog(logfile); | |
267 | if(clog->checkFormat()) return clog; | |
268 | ||
269 | delete clog; | |
270 | ||
271 | //cvs exp | |
272 | debugLog("trying cvs-exp..."); | |
273 | clog = new CVSEXPCommitLog(logfile); | |
274 | if(clog->checkFormat()) return clog; | |
275 | ||
276 | delete clog; | |
277 | ||
278 | //svn | |
279 | debugLog("trying svn..."); | |
280 | clog = new SVNCommitLog(logfile); | |
281 | if(clog->checkFormat()) return clog; | |
282 | ||
283 | delete clog; | |
284 | ||
285 | //cvs2cl | |
286 | debugLog("trying cvs2cl..."); | |
287 | clog = new CVS2CLCommitLog(logfile); | |
288 | if(clog->checkFormat()) return clog; | |
289 | ||
290 | delete clog; | |
291 | ||
292 | //custom | |
293 | debugLog("trying custom..."); | |
294 | clog = new CustomLog(logfile); | |
295 | if(clog->checkFormat()) return clog; | |
296 | ||
297 | delete clog; | |
298 | ||
299 | //apache | |
300 | debugLog("trying apache combined..."); | |
301 | clog = new ApacheCombinedLog(logfile); | |
302 | if(clog->checkFormat()) return clog; | |
303 | ||
304 | delete clog; | |
305 | ||
306 | return 0; | |
307 | } |
0 | /* | |
1 | Copyright (C) 2012 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef LOGMILL_H | |
18 | #define LOGMILL_H | |
19 | ||
20 | #include <boost/filesystem.hpp> | |
21 | ||
22 | #include "SDL_thread.h" | |
23 | ||
24 | #include "core/sdlapp.h" | |
25 | #include "core/display.h" | |
26 | ||
27 | #include "formats/commitlog.h" | |
28 | ||
29 | #if defined(HAVE_PTHREAD) && !defined(_WIN32) | |
30 | #include <signal.h> | |
31 | #endif | |
32 | ||
33 | enum { | |
34 | LOGMILL_STATE_STARTUP, | |
35 | LOGMILL_STATE_FETCHING, | |
36 | LOGMILL_STATE_SUCCESS, | |
37 | LOGMILL_STATE_FAILURE | |
38 | }; | |
39 | ||
40 | class RLogMill { | |
41 | SDL_Thread* thread; | |
42 | SDL_mutex* mutex; | |
43 | SDL_cond* cond; | |
44 | ||
45 | int logmill_thread_state; | |
46 | ||
47 | std::string logfile; | |
48 | RCommitLog* clog; | |
49 | ||
50 | std::string error; | |
51 | ||
52 | bool findRepository(boost::filesystem::path& dir, std::string& log_format); | |
53 | RCommitLog* fetchLog(std::string& log_format); | |
54 | public: | |
55 | RLogMill(const std::string& logfile); | |
56 | ~RLogMill(); | |
57 | ||
58 | void run(); | |
59 | ||
60 | void abort(); | |
61 | ||
62 | std::string getError(); | |
63 | ||
64 | int getStatus(); | |
65 | bool isFinished(); | |
66 | ||
67 | RCommitLog* getLog(); | |
68 | }; | |
69 | ||
70 | #endif |
35 | 35 | for(std::vector<std::string>::iterator fit = files.begin(); fit != files.end(); fit++) { |
36 | 36 | std::string file = *fit; |
37 | 37 | |
38 | if( file.rfind(".conf") == file.size()-5 | |
39 | || file.rfind(".cfg") == file.size()-4 | |
40 | || file.rfind(".ini") == file.size()-4) { | |
38 | int file_length = file.size(); | |
39 | ||
40 | if( file.rfind(".conf") == (file_length-5) && file_length > 5 | |
41 | || file.rfind(".cfg") == (file_length-4) && file_length > 4 | |
42 | || file.rfind(".ini") == (file_length-4) && file_length > 4) { | |
41 | 43 | |
42 | 44 | bool is_conf=true; |
43 | 45 | |
56 | 58 | } |
57 | 59 | } |
58 | 60 | } |
61 | ||
62 | //set log level | |
63 | logger->setLevel(gGourceSettings.log_level); | |
59 | 64 | |
60 | 65 | //load config |
61 | 66 | if(!gGourceSettings.load_config.empty()) { |
116 | 121 | //enable vsync |
117 | 122 | display.enableVsync(gGourceSettings.vsync); |
118 | 123 | |
124 | //allow resizing window if we are not recording | |
125 | if(gGourceSettings.resizable && gGourceSettings.output_ppm_filename.empty()) { | |
126 | display.enableResize(true); | |
127 | } | |
128 | ||
119 | 129 | try { |
120 | 130 | |
121 | 131 | display.init("Gource", gGourceSettings.display_width, gGourceSettings.display_height, gGourceSettings.fullscreen); |
127 | 137 | |
128 | 138 | SDLAppQuit(errormsg); |
129 | 139 | } |
140 | ||
141 | #ifdef _WIN32 | |
142 | SDLAppAttachToConsole(); | |
143 | #endif | |
130 | 144 | |
131 | 145 | //init frame exporter |
132 | 146 | FrameExporter* exporter = 0; |
153 | 167 | GourceShell* gourcesh = 0; |
154 | 168 | |
155 | 169 | try { |
156 | gourcesh = new GourceShell(&conf, exporter); | |
170 | gourcesh = gGourceShell = new GourceShell(&conf, exporter); | |
157 | 171 | gourcesh->run(); |
158 | 172 | |
159 | 173 | } catch(ResourceException& exception) { |
170 | 184 | } else { |
171 | 185 | SDLAppQuit(exception.what()); |
172 | 186 | } |
173 | ||
174 | 187 | } |
188 | ||
189 | gGourceShell = 0; | |
175 | 190 | |
176 | 191 | if(gourcesh != 0) delete gourcesh; |
177 | 192 | if(exporter != 0) delete exporter; |
18 | 18 | |
19 | 19 | float gGourceShadowStrength = 0.5; |
20 | 20 | |
21 | Pawn::Pawn(const std::string& name, vec2f pos, int tagid) { | |
21 | Pawn::Pawn(const std::string& name, vec2 pos, int tagid) { | |
22 | 22 | this->name = name; |
23 | 23 | this->pos = pos; |
24 | 24 | this->tagid = tagid; |
32 | 32 | |
33 | 33 | namewidth = 0; |
34 | 34 | |
35 | this->shadowOffset = vec2f(2.0, 2.0); | |
35 | this->shadowOffset = vec2(2.0, 2.0); | |
36 | 36 | this->elapsed = 0.0; |
37 | 37 | this->fadetime = 1.0; |
38 | 38 | this->nametime = 5.0; |
39 | 39 | this->name_interval = 0.0; |
40 | this->namecol = vec3f(1.0, 1.0, 1.0); | |
41 | ||
42 | this->selectedcol = gGourceSettings.highlight_colour; | |
40 | this->namecol = vec3(1.0, 1.0, 1.0); | |
43 | 41 | |
44 | 42 | this->graphic = 0; |
45 | 43 | this->graphic_ratio = 1.0; |
49 | 47 | return size; |
50 | 48 | } |
51 | 49 | |
52 | void Pawn::setPos(vec2f pos) { | |
50 | void Pawn::setPos(vec2 pos) { | |
53 | 51 | this->pos = pos; |
54 | 52 | } |
55 | 53 | |
65 | 63 | |
66 | 64 | float halfsize_x = size * 0.5f; |
67 | 65 | |
68 | vec2f halfsize ( halfsize_x, halfsize_x * graphic_ratio ); | |
66 | vec2 halfsize ( halfsize_x, halfsize_x * graphic_ratio ); | |
69 | 67 | |
70 | 68 | //set bounds |
71 | 69 | quadItemBounds.set(pos - halfsize, pos + halfsize); |
88 | 86 | } |
89 | 87 | |
90 | 88 | this->graphic = graphic; |
91 | this->dims = vec2f(size, size*graphic_ratio); | |
89 | this->dims = vec2(size, size*graphic_ratio); | |
92 | 90 | } |
93 | 91 | |
94 | 92 | |
101 | 99 | this->selected = selected; |
102 | 100 | } |
103 | 101 | |
104 | const vec3f& Pawn::getNameColour() const { | |
102 | const vec3& Pawn::getNameColour() const { | |
105 | 103 | return namecol; |
106 | 104 | } |
107 | 105 | |
108 | void Pawn::calcScreenPos(const vec2f& offset) { | |
109 | screenpos = display.project(vec3f(pos.x+offset.x, pos.y+offset.y, 0.0f)); | |
106 | void Pawn::calcScreenPos(const vec2& offset) { | |
107 | screenpos = display.project(vec3(pos.x+offset.x, pos.y+offset.y, 0.0f)); | |
110 | 108 | } |
111 | 109 | |
112 | 110 | bool Pawn::nameVisible() const { |
131 | 129 | if(isHidden() || !shadow) return; |
132 | 130 | |
133 | 131 | float halfsize = size * 0.5f; |
134 | vec2f offsetpos = pos - vec2f(halfsize, halfsize*graphic_ratio) + shadowOffset; | |
132 | vec2 offsetpos = pos - vec2(halfsize, halfsize*graphic_ratio) + shadowOffset; | |
135 | 133 | |
136 | 134 | float alpha = getAlpha(); |
137 | 135 | |
162 | 160 | if(hidden) return; |
163 | 161 | |
164 | 162 | float halfsize = size * 0.5f; |
165 | vec2f offsetpos = pos - vec2f(halfsize, halfsize*graphic_ratio); | |
163 | vec2 offsetpos = pos - vec2(halfsize, halfsize*graphic_ratio); | |
166 | 164 | |
167 | 165 | float alpha = getAlpha(); |
168 | 166 | |
169 | vec3f col = getColour(); | |
167 | vec3 col = getColour(); | |
170 | 168 | |
171 | 169 | glBindTexture(GL_TEXTURE_2D, graphic->textureid); |
172 | 170 |
28 | 28 | |
29 | 29 | class Pawn : public QuadItem { |
30 | 30 | protected: |
31 | vec2f pos; | |
32 | vec2f shadowOffset; | |
31 | vec2 pos; | |
32 | vec2 shadowOffset; | |
33 | 33 | |
34 | 34 | std::string name; |
35 | 35 | float namewidth; |
36 | vec2f accel; | |
36 | vec2 accel; | |
37 | 37 | float speed; |
38 | 38 | |
39 | 39 | float elapsed; |
41 | 41 | |
42 | 42 | float nametime; |
43 | 43 | float name_interval; |
44 | vec3f namecol; | |
45 | vec3f selectedcol; | |
44 | vec3 namecol; | |
46 | 45 | |
47 | 46 | bool shadow; |
48 | 47 | |
57 | 56 | virtual bool nameVisible() const; |
58 | 57 | |
59 | 58 | virtual void drawNameText(float alpha) {}; |
60 | virtual const vec3f& getNameColour() const; | |
59 | virtual const vec3& getNameColour() const; | |
61 | 60 | protected: |
62 | 61 | bool selected; |
63 | 62 | public: |
64 | 63 | float size; |
65 | 64 | float graphic_ratio; |
66 | 65 | TextureResource* graphic; |
67 | vec3f screenpos; | |
68 | vec2f dims; | |
66 | vec3 screenpos; | |
67 | vec2 dims; | |
69 | 68 | |
70 | Pawn(const std::string& name, vec2f pos, int tagid); | |
71 | const vec2f & getPos() const { return pos; } | |
72 | void setPos(vec2f pos); | |
69 | Pawn(const std::string& name, vec2 pos, int tagid); | |
70 | const vec2 & getPos() const { return pos; } | |
71 | void setPos(vec2 pos); | |
73 | 72 | |
74 | void calcScreenPos(const vec2f& offset); | |
73 | void calcScreenPos(const vec2& offset); | |
75 | 74 | |
76 | 75 | void updateQuadItemBounds(); |
77 | 76 | |
91 | 90 | bool isHidden() const { return hidden; } |
92 | 91 | |
93 | 92 | virtual float getAlpha() const{ return std::min(elapsed/fadetime, 1.0f); } |
94 | virtual vec3f getColour() const { return vec3f(1.0, 1.0, 1.0); } | |
93 | virtual vec3 getColour() const { return vec3(1.0, 1.0, 1.0); } | |
95 | 94 | |
96 | 95 | void setGraphic(TextureResource* graphic); |
97 | 96 |
24 | 24 | font = fontmanager.grab("FreeSans.ttf", 16); |
25 | 25 | font.dropShadow(true); |
26 | 26 | |
27 | int gap = display.width / 30; | |
28 | ||
29 | bounds.update(vec2f(gap, display.height - gap*2)); | |
30 | bounds.update(vec2f(display.width - gap, display.height - gap)); | |
31 | ||
32 | slidercol = vec3f(1.0, 1.0, 1.0); | |
27 | slidercol = vec3(1.0, 1.0, 1.0); | |
33 | 28 | |
34 | 29 | mouseover = -1.0; |
35 | 30 | |
36 | 31 | mouseover_elapsed = 1.0; |
37 | 32 | fade_time = 1.0; |
38 | 33 | alpha = 0.0; |
34 | ||
35 | resize(); | |
39 | 36 | } |
40 | 37 | |
41 | void PositionSlider::setColour(vec3f col) { | |
38 | void PositionSlider::resize() { | |
39 | int gap = display.width / 30; | |
40 | ||
41 | bounds.reset(); | |
42 | bounds.update(vec2(gap, display.height - gap*2)); | |
43 | bounds.update(vec2(display.width - gap, display.height - gap)); | |
44 | } | |
45 | ||
46 | void PositionSlider::setColour(vec3 col) { | |
42 | 47 | slidercol = col; |
43 | 48 | } |
44 | 49 | |
46 | 51 | mouseover_elapsed = 0.0; |
47 | 52 | } |
48 | 53 | |
49 | bool PositionSlider::mouseOver(vec2f pos, float* percent_ptr) { | |
54 | bool PositionSlider::mouseOver(vec2 pos, float* percent_ptr) { | |
50 | 55 | if(bounds.contains(pos)) { |
51 | 56 | |
52 | 57 | mouseover_elapsed = 0; |
64 | 69 | return false; |
65 | 70 | } |
66 | 71 | |
67 | bool PositionSlider::click(vec2f pos, float* percent_ptr) { | |
72 | bool PositionSlider::click(vec2 pos, float* percent_ptr) { | |
68 | 73 | if(mouseOver(pos, &percent)) { |
69 | 74 | |
70 | 75 | if(percent_ptr != 0) { |
32 | 32 | float fade_time; |
33 | 33 | float alpha; |
34 | 34 | |
35 | vec3f slidercol; | |
35 | vec3 slidercol; | |
36 | 36 | |
37 | 37 | float capwidth; |
38 | 38 | std::string caption; |
39 | 39 | public: |
40 | 40 | PositionSlider(float percent = 0.0f); |
41 | 41 | |
42 | void setColour(vec3f col); | |
42 | void setColour(vec3 col); | |
43 | 43 | |
44 | 44 | void setCaption(const std::string& cap); |
45 | 45 | |
46 | 46 | void setPercent(float percent); |
47 | 47 | |
48 | void resize(); | |
49 | ||
48 | 50 | void show(); |
49 | 51 | |
50 | bool mouseOver(vec2f pos, float* percent_ptr); | |
51 | bool click(vec2f pos, float* percent_ptr); | |
52 | bool mouseOver(vec2 pos, float* percent_ptr); | |
53 | bool click(vec2 pos, float* percent_ptr); | |
52 | 54 | void logic(float dt); |
53 | 55 | void draw(float dt); |
54 | 56 | }; |
19 | 19 | SplineEdge::SplineEdge() { |
20 | 20 | } |
21 | 21 | |
22 | void SplineEdge::update(const vec2f& pos1, const vec4f& col1, const vec2f& pos2, const vec4f& col2, const vec2f& spos) { | |
22 | void SplineEdge::update(const vec2& pos1, const vec4& col1, const vec2& pos2, const vec4& col2, const vec2& spos) { | |
23 | 23 | |
24 | vec2f pt_last; | |
25 | vec4f col_last; | |
24 | vec2 pt_last; | |
25 | vec4 col_last; | |
26 | 26 | |
27 | vec2f mid = (pos1 - pos2) * 0.5; | |
28 | vec2f to = vec2f(pos1 - spos); | |
27 | vec2 mid = (pos1 - pos2) * 0.5f; | |
28 | vec2 to = vec2(pos1 - spos); | |
29 | 29 | |
30 | float dp = std::min(1.0f, to.normal().dot(mid.normal())); | |
30 | //TODO: not sure this makes any sense | |
31 | //float dp = std::min(1.0f, to.normal().dot(mid.normal())); | |
32 | float dp = std::min(1.0f, glm::dot(normalise(to), normalise(mid)) ); | |
31 | 33 | |
32 | 34 | float ang = acos(dp) / PI; |
33 | 35 | |
46 | 48 | float t = (float)i/edge_detail; |
47 | 49 | float tt = 1.0f-t; |
48 | 50 | |
49 | vec2f p0 = pos1 * t + spos * tt; | |
50 | vec2f p1 = spos * t + pos2 * tt; | |
51 | vec2 p0 = pos1 * t + spos * tt; | |
52 | vec2 p1 = spos * t + pos2 * tt; | |
51 | 53 | |
52 | vec2f pt = p0 * t + p1 * tt; | |
54 | vec2 pt = p0 * t + p1 * tt; | |
53 | 55 | |
54 | vec4f coln = col1 * t + col2 * tt; | |
56 | vec4 coln = col1 * t + col2 * tt; | |
55 | 57 | |
56 | 58 | spline_point.push_back(pt); |
57 | 59 | spline_colour.push_back(coln); |
58 | 60 | } |
59 | 61 | |
60 | midpoint = pos1 * 0.25 + pos2 * 0.25 + spos * 0.5; | |
62 | midpoint = pos1 * 0.25f + pos2 * 0.25f + spos * 0.5f; | |
61 | 63 | } |
62 | 64 | |
63 | const vec2f& SplineEdge::getMidPoint() const { | |
65 | const vec2& SplineEdge::getMidPoint() const { | |
64 | 66 | return midpoint; |
65 | 67 | } |
66 | 68 | |
70 | 72 | |
71 | 73 | for(int i=0; i < edges_count; i++) { |
72 | 74 | |
73 | vec2f perp = (spline_point[i] - spline_point[i+1]).perpendicular().normal() * 2.5f; | |
75 | //vec2 perp = (spline_point[i] - spline_point[i+1]).perpendicular().normal() * 2.5f; | |
74 | 76 | |
75 | quadbuf_vertex v1(spline_point[i] + perp, spline_colour[i], vec2f(1.0f, 0.0f)); | |
76 | quadbuf_vertex v2(spline_point[i] - perp, spline_colour[i], vec2f(0.0f, 0.0f)); | |
77 | quadbuf_vertex v3(spline_point[i+1] - perp, spline_colour[i+1], vec2f(0.0f, 0.0f)); | |
78 | quadbuf_vertex v4(spline_point[i+1] + perp, spline_colour[i+1], vec2f(1.0f, 0.0f)); | |
77 | vec2 perp = (spline_point[i] - spline_point[i+1]); | |
78 | perp = normalise(vec2(-perp.y, perp.x)) * 2.5f; | |
79 | ||
80 | quadbuf_vertex v1(spline_point[i] + perp, spline_colour[i], vec2(1.0f, 0.0f)); | |
81 | quadbuf_vertex v2(spline_point[i] - perp, spline_colour[i], vec2(0.0f, 0.0f)); | |
82 | quadbuf_vertex v3(spline_point[i+1] - perp, spline_colour[i+1], vec2(0.0f, 0.0f)); | |
83 | quadbuf_vertex v4(spline_point[i+1] + perp, spline_colour[i+1], vec2(1.0f, 0.0f)); | |
79 | 84 | |
80 | 85 | buffer.add(0, v1, v2, v3, v4); |
81 | 86 | } |
82 | 87 | } |
83 | 88 | |
84 | void SplineEdge::drawBeam(const vec2f & pos1, const vec4f & col1, const vec2f & pos2, const vec4f & col2, float radius, bool first) const{ | |
89 | void SplineEdge::drawBeam(const vec2 & pos1, const vec4 & col1, const vec2 & pos2, const vec4 & col2, float radius, bool first) const{ | |
85 | 90 | |
86 | vec2f perp = (pos1 - pos2).perpendicular().normal() * radius; | |
91 | //vec2 perp = (pos1 - pos2).perpendicular().normal() * radius; | |
87 | 92 | |
93 | vec2 perp = (pos1 - pos2); | |
94 | perp = normalise(vec2(-perp.y, perp.x)) * radius; | |
95 | ||
96 | ||
88 | 97 | // src point |
89 | 98 | if(first) { |
90 | glColor4fv(col1); | |
99 | glColor4fv(glm::value_ptr(col1)); | |
91 | 100 | glTexCoord2f(1.0,0.0); |
92 | 101 | glVertex2f(pos1.x + perp.x, pos1.y + perp.y); |
93 | 102 | glTexCoord2f(0.0,0.0); |
95 | 104 | } |
96 | 105 | |
97 | 106 | // dest point |
98 | glColor4fv(col2); | |
107 | glColor4fv(glm::value_ptr(col2)); | |
99 | 108 | glTexCoord2f(1.0,0.0); |
100 | 109 | glVertex2f(pos2.x + perp.x, pos2.y + perp.y); |
101 | 110 | glTexCoord2f(0.0,0.0); |
106 | 115 | |
107 | 116 | int edges_count = spline_point.size() - 1; |
108 | 117 | |
109 | vec2f offset(2.0, 2.0); | |
118 | vec2 offset(2.0, 2.0); | |
110 | 119 | |
111 | 120 | glBegin(GL_QUAD_STRIP); |
112 | 121 | |
113 | 122 | for(int i=0;i<edges_count;i++) { |
114 | drawBeam(spline_point[i] + offset, vec4f(0.0, 0.0, 0.0, gGourceShadowStrength), spline_point[i+1] + offset, vec4f(0.0, 0.0, 0.0, gGourceShadowStrength), 2.5, i==0); | |
123 | drawBeam(spline_point[i] + offset, vec4(0.0, 0.0, 0.0, gGourceShadowStrength), spline_point[i+1] + offset, vec4(0.0, 0.0, 0.0, gGourceShadowStrength), 2.5, i==0); | |
115 | 124 | } |
116 | 125 | |
117 | 126 | glEnd(); |
27 | 27 | |
28 | 28 | class SplineEdge { |
29 | 29 | |
30 | std::vector<vec2f> spline_point; | |
31 | std::vector<vec4f> spline_colour; | |
30 | std::vector<vec2> spline_point; | |
31 | std::vector<vec4> spline_colour; | |
32 | 32 | |
33 | vec2f midpoint; | |
33 | vec2 midpoint; | |
34 | 34 | |
35 | void drawBeam(const vec2f & pos1, const vec4f & col1, const vec2f & pos2, const vec4f & col2, float radius, bool first) const; | |
35 | void drawBeam(const vec2 & pos1, const vec4 & col1, const vec2 & pos2, const vec4 & col2, float radius, bool first) const; | |
36 | 36 | public: |
37 | 37 | SplineEdge(); |
38 | 38 | |
39 | const vec2f& getMidPoint() const; | |
39 | const vec2& getMidPoint() const; | |
40 | 40 | |
41 | void update(const vec2f& pos1, const vec4f& col1, const vec2f& pos2, const vec4f& col2, const vec2f& spos); | |
41 | void update(const vec2& pos1, const vec4& col1, const vec2& pos2, const vec4& col2, const vec2& spos); | |
42 | 42 | |
43 | 43 | void drawToVBO(quadbuf& buffer) const; |
44 | 44 |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #include "svn.h" | |
18 | ||
19 | Regex svn_xml_tag("^<\\??xml"); | |
20 | Regex svn_logentry_start("^<logentry"); | |
21 | Regex svn_logentry_end("^</logentry>"); | |
22 | Regex svn_logentry_timestamp("(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})"); | |
23 | ||
24 | std::string gGourceSVNLogCommand = "svn log -r 1:HEAD --xml --verbose --quiet"; | |
25 | ||
26 | SVNCommitLog::SVNCommitLog(const std::string& logfile) : RCommitLog(logfile, '<') { | |
27 | ||
28 | log_command = gGourceSVNLogCommand; | |
29 | ||
30 | //can generate log from directory | |
31 | if(!logf && is_dir) { | |
32 | logf = generateLog(logfile); | |
33 | ||
34 | if(logf) { | |
35 | success = true; | |
36 | seekable = true; | |
37 | } | |
38 | } | |
39 | ||
40 | logentry.reserve(1024); | |
41 | } | |
42 | ||
43 | ||
44 | BaseLog* SVNCommitLog::generateLog(const std::string& dir) { | |
45 | //get working directory | |
46 | char cwd_buff[1024]; | |
47 | ||
48 | if(getcwd(cwd_buff, 1024) != cwd_buff) { | |
49 | return 0; | |
50 | } | |
51 | ||
52 | //does directory have a .svn ? | |
53 | std::string gitdir = dir + std::string("/.svn"); | |
54 | struct stat dirinfo; | |
55 | int stat_rc = stat(gitdir.c_str(), &dirinfo); | |
56 | if(stat_rc!=0 || !(dirinfo.st_mode & S_IFDIR)) { | |
57 | return 0; | |
58 | } | |
59 | ||
60 | std::string command = getLogCommand(); | |
61 | ||
62 | //create temp file | |
63 | createTempLog(); | |
64 | ||
65 | if(temp_file.size()==0) return 0; | |
66 | ||
67 | if(chdir(dir.c_str()) != 0) { | |
68 | return 0; | |
69 | } | |
70 | ||
71 | char cmd_buff[2048]; | |
72 | sprintf(cmd_buff, "%s > %s", command.c_str(), temp_file.c_str()); | |
73 | ||
74 | int command_rc = system(cmd_buff); | |
75 | ||
76 | chdir(cwd_buff); | |
77 | ||
78 | if(command_rc != 0) { | |
79 | return 0; | |
80 | } | |
81 | ||
82 | BaseLog* seeklog = new SeekLog(temp_file); | |
83 | ||
84 | return seeklog; | |
85 | } | |
86 | ||
87 | #ifndef HAVE_TIMEGM | |
88 | ||
89 | std::string system_tz; | |
90 | bool system_tz_init = false; | |
91 | ||
92 | time_t __timegm_hack(struct tm* tm) { | |
93 | ||
94 | if(!system_tz_init) { | |
95 | char* current_tz_env = getenv("TZ"); | |
96 | ||
97 | if(current_tz_env != 0) { | |
98 | system_tz = std::string("TZ=") + current_tz_env; | |
99 | } | |
100 | ||
101 | system_tz_init = true; | |
102 | } | |
103 | ||
104 | putenv((char*)"TZ=UTC"); | |
105 | tzset(); | |
106 | ||
107 | time_t timestamp = mktime(tm); | |
108 | ||
109 | if(!system_tz.empty()) { | |
110 | putenv((char*)system_tz.c_str()); | |
111 | } else { | |
112 | #ifdef HAVE_UNSETENV | |
113 | unsetenv("TZ"); | |
114 | #else | |
115 | putenv((char*)"TZ="); | |
116 | #endif | |
117 | } | |
118 | tzset(); | |
119 | ||
120 | return timestamp; | |
121 | } | |
122 | #endif | |
123 | ||
124 | bool SVNCommitLog::parseCommit(RCommit& commit) { | |
125 | ||
126 | //fprintf(stderr,"parsing svn log\n"); | |
127 | ||
128 | std::string line; | |
129 | ||
130 | if(!getNextLine(line)) return false; | |
131 | ||
132 | //start of log entry | |
133 | if(!svn_logentry_start.match(line)) { | |
134 | ||
135 | //is this the start of the document | |
136 | if(!svn_xml_tag.match(line)) return false; | |
137 | ||
138 | //fprintf(stderr,"found xml tag\n"); | |
139 | ||
140 | //if so find the first logentry tag | |
141 | ||
142 | bool found_logentry = false; | |
143 | ||
144 | while(getNextLine(line)) { | |
145 | if(svn_logentry_start.match(line)) { | |
146 | found_logentry = true; | |
147 | break; | |
148 | } | |
149 | } | |
150 | ||
151 | if(!found_logentry) return false; | |
152 | } | |
153 | ||
154 | //fprintf(stderr,"found logentry\n"); | |
155 | ||
156 | logentry.clear(); | |
157 | ||
158 | logentry.append(line); | |
159 | logentry.append("\n"); | |
160 | ||
161 | //fprintf(stderr,"found opening tag\n"); | |
162 | ||
163 | bool endfound = false; | |
164 | ||
165 | while(getNextLine(line)) { | |
166 | logentry.append(line); | |
167 | logentry.append("\n"); | |
168 | if(svn_logentry_end.match(line)) { | |
169 | //fprintf(stderr,"found closing tag\n"); | |
170 | endfound=true; | |
171 | break; | |
172 | } | |
173 | } | |
174 | ||
175 | //incomplete commit | |
176 | if(!endfound) return false; | |
177 | ||
178 | //fprintf(stderr,"read logentry\n"); | |
179 | ||
180 | TiXmlDocument doc; | |
181 | ||
182 | if(!doc.Parse(logentry.c_str())) return false; | |
183 | ||
184 | //fprintf(stderr,"try to parse logentry: %s\n", logentry.c_str()); | |
185 | ||
186 | TiXmlElement* leE = doc.FirstChildElement( "logentry" ); | |
187 | ||
188 | std::vector<std::string> entries; | |
189 | ||
190 | if(!leE) return false; | |
191 | ||
192 | //parse date | |
193 | TiXmlElement* dateE = leE->FirstChildElement( "date" ); | |
194 | ||
195 | if(!dateE) return false; | |
196 | ||
197 | std::string timestamp_str(dateE->GetText()); | |
198 | ||
199 | if(!svn_logentry_timestamp.match(timestamp_str, &entries)) | |
200 | return false; | |
201 | ||
202 | struct tm time_str; | |
203 | ||
204 | time_str.tm_year = atoi(entries[0].c_str()) - 1900; | |
205 | time_str.tm_mon = atoi(entries[1].c_str()) - 1; | |
206 | time_str.tm_mday = atoi(entries[2].c_str()); | |
207 | time_str.tm_hour = atoi(entries[3].c_str()); | |
208 | time_str.tm_min = atoi(entries[4].c_str()); | |
209 | time_str.tm_sec = atoi(entries[5].c_str()); | |
210 | time_str.tm_isdst = -1; | |
211 | ||
212 | #ifdef HAVE_TIMEGM | |
213 | commit.timestamp = timegm(&time_str); | |
214 | #else | |
215 | commit.timestamp = __timegm_hack(&time_str); | |
216 | #endif | |
217 | ||
218 | //parse author | |
219 | TiXmlElement* authorE = leE->FirstChildElement("author"); | |
220 | ||
221 | if(authorE != 0) { | |
222 | ||
223 | std::string author(authorE->GetText()); | |
224 | ||
225 | if(author.empty()) author = "Unknown"; | |
226 | ||
227 | commit.username = author; | |
228 | } | |
229 | ||
230 | TiXmlElement* pathsE = leE->FirstChildElement( "paths" ); | |
231 | ||
232 | //log entries sometimes dont have any paths | |
233 | if(!pathsE) return true; | |
234 | ||
235 | //parse changes | |
236 | ||
237 | for(TiXmlElement* pathE = pathsE->FirstChildElement("path"); pathE != 0; pathE = pathE->NextSiblingElement()) { | |
238 | //parse path | |
239 | ||
240 | const char* kind = pathE->Attribute("kind"); | |
241 | const char* action = pathE->Attribute("action"); | |
242 | ||
243 | //check for action | |
244 | if(action == 0) continue; | |
245 | ||
246 | bool is_dir = false; | |
247 | ||
248 | //if has the 'kind' attribute (old versions of svn dont have this), check if it is a dir | |
249 | if(kind != 0 && strcmp(kind,"dir") == 0) { | |
250 | ||
251 | //accept only deletes for directories | |
252 | if(strcmp(action, "D") != 0) continue; | |
253 | ||
254 | is_dir = true; | |
255 | } | |
256 | ||
257 | std::string file(pathE->GetText()); | |
258 | std::string status(action); | |
259 | ||
260 | if(file.empty()) continue; | |
261 | if(status.empty()) continue; | |
262 | ||
263 | //append trailing slash if is directory | |
264 | if(is_dir && file[file.size()-1] != '/') { | |
265 | file = file + std::string("/"); | |
266 | } | |
267 | ||
268 | commit.addFile(file, status); | |
269 | } | |
270 | ||
271 | //fprintf(stderr,"parsed logentry\n"); | |
272 | ||
273 | //read files | |
274 | ||
275 | return true; | |
276 | } |
0 | /* | |
1 | Copyright (C) 2010 Andrew Caudwell (acaudwell@gmail.com) | |
2 | ||
3 | This program is free software; you can redistribute it and/or | |
4 | modify it under the terms of the GNU General Public License | |
5 | as published by the Free Software Foundation; either version | |
6 | 3 of the License, or (at your option) any later version. | |
7 | ||
8 | This program is distributed in the hope that it will be useful, | |
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | GNU General Public License for more details. | |
12 | ||
13 | You should have received a copy of the GNU General Public License | |
14 | along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
17 | #ifndef SVNLOG_H | |
18 | #define SVNLOG_H | |
19 | ||
20 | #include "gource_settings.h" | |
21 | ||
22 | #include "commitlog.h" | |
23 | ||
24 | #include <sstream> | |
25 | ||
26 | #ifdef HAVE_LIBTINYXML | |
27 | #include <tinyxml.h> | |
28 | #else | |
29 | #include "tinyxml/tinyxml.h" | |
30 | #endif | |
31 | ||
32 | #include <unistd.h> | |
33 | ||
34 | extern std::string gGourceSVNLogCommand; | |
35 | ||
36 | class SVNCommitLog : public RCommitLog { | |
37 | protected: | |
38 | bool parseCommit(RCommit& commit); | |
39 | BaseLog* generateLog(const std::string& dir); | |
40 | ||
41 | std::string logentry; | |
42 | public: | |
43 | SVNCommitLog(const std::string& logfile); | |
44 | }; | |
45 | ||
46 | #endif |
22 | 22 | TextBox::TextBox(const FXFont& font) { |
23 | 23 | this->font = font; |
24 | 24 | |
25 | shadow = vec2f(3.0f, 3.0f); | |
25 | shadow = vec2(3.0f, 3.0f); | |
26 | 26 | |
27 | colour = vec3f(0.7f, 0.7f, 0.7f); | |
28 | corner = vec2f(0.0f,0.0f); | |
27 | colour = vec3(0.7f, 0.7f, 0.7f); | |
28 | corner = vec2(0.0f,0.0f); | |
29 | 29 | alpha = 1.0f; |
30 | 30 | brightness = 1.0f; |
31 | 31 | max_width_chars = 1024; |
46 | 46 | this->brightness = brightness; |
47 | 47 | } |
48 | 48 | |
49 | void TextBox::setColour(const vec3f& colour) { | |
49 | void TextBox::setColour(const vec3& colour) { | |
50 | 50 | this->colour = colour; |
51 | 51 | } |
52 | 52 | |
91 | 91 | } |
92 | 92 | } |
93 | 93 | |
94 | void TextBox::setPos(const vec2f& pos, bool adjust) { | |
94 | void TextBox::setPos(const vec2& pos, bool adjust) { | |
95 | 95 | |
96 | 96 | corner = pos; |
97 | 97 |
27 | 27 | |
28 | 28 | std::vector<std::string> content; |
29 | 29 | |
30 | vec3f colour; | |
30 | vec3 colour; | |
31 | 31 | float alpha; |
32 | 32 | float brightness; |
33 | vec2f corner; | |
34 | vec2f shadow; | |
33 | vec2 corner; | |
34 | vec2 shadow; | |
35 | 35 | FXFont font; |
36 | 36 | int max_width_chars; |
37 | 37 | int rect_width; |
47 | 47 | |
48 | 48 | void clear(); |
49 | 49 | |
50 | void setPos(const vec2f& pos, bool adjust = false); | |
51 | void setColour(const vec3f& colour); | |
50 | void setPos(const vec2& pos, bool adjust = false); | |
51 | void setColour(const vec3& colour); | |
52 | 52 | void setAlpha(float alpha); |
53 | 53 | void setBrightness(float brightness); |
54 | 54 |
20 | 20 | float gGourceActionDist = 50.0; |
21 | 21 | float gGourcePersonalSpaceDist = 100.0; |
22 | 22 | |
23 | RUser::RUser(const std::string& name, vec2f pos, int tagid) : Pawn(name,pos,tagid) { | |
23 | RUser::RUser(const std::string& name, vec2 pos, int tagid) : Pawn(name,pos,tagid) { | |
24 | 24 | |
25 | 25 | this->name = name; |
26 | 26 | |
27 | 27 | speed = gGourceSettings.max_user_speed; |
28 | 28 | size = 20.0 * gGourceSettings.user_scale; |
29 | 29 | |
30 | shadowOffset = vec2f(2.0, 2.0) * gGourceSettings.user_scale; | |
30 | shadowOffset = vec2(2.0, 2.0) * gGourceSettings.user_scale; | |
31 | 31 | |
32 | 32 | shadow = true; |
33 | 33 | |
88 | 88 | |
89 | 89 | if(u==this) return; |
90 | 90 | |
91 | vec2f u_pos = u->getPos(); | |
92 | ||
93 | vec2f dir = u_pos - pos; | |
94 | ||
95 | float dist = dir.length(); | |
91 | vec2 u_pos = u->getPos(); | |
92 | ||
93 | vec2 dir = u_pos - pos; | |
94 | ||
95 | float dist = glm::length(dir); | |
96 | 96 | |
97 | 97 | //different repelling force depending on how busy the user is |
98 | 98 | float desired_dist = getActionCount() == 0 ? |
102 | 102 | //resolve overlap |
103 | 103 | if(dist < 0.001) { |
104 | 104 | |
105 | accel += 1.0f * vec2f( (rand() % 100) - 50, (rand() % 100) - 50).normal(); | |
105 | accel += 1.0f * normalise(vec2( (rand() % 100) - 50, (rand() % 100) - 50)); | |
106 | 106 | |
107 | 107 | return; |
108 | 108 | } |
109 | 109 | |
110 | 110 | //repelling force |
111 | 111 | if(dist < desired_dist) { |
112 | accel -= (desired_dist-dist) * dir.normal(); | |
112 | accel -= (desired_dist-dist) * normalise(dir); | |
113 | 113 | } |
114 | 114 | } |
115 | 115 | |
116 | 116 | void RUser::applyForceAction(RAction* action) { |
117 | 117 | RFile* f = action->target; |
118 | 118 | |
119 | vec2f f_pos = f->getAbsolutePos(); | |
120 | vec2f dir = f_pos - pos; | |
121 | float dist = dir.length(); | |
119 | vec2 f_pos = f->getAbsolutePos(); | |
120 | vec2 dir = f_pos - pos; | |
121 | float dist = glm::length(dir); | |
122 | 122 | |
123 | 123 | float desired_dist = gGourceActionDist; |
124 | 124 | |
125 | 125 | //resolve overlap |
126 | 126 | if(dist < 0.001) { |
127 | accel += vec2f( (rand() % 100) - 50, (rand() % 100) - 50).normal(); | |
127 | accel += normalise(vec2( (rand() % 100) - 50, (rand() % 100) - 50)); | |
128 | 128 | return; |
129 | 129 | } |
130 | 130 | |
131 | 131 | //repelling force |
132 | 132 | if(dist < desired_dist) { |
133 | accel -= (desired_dist - dist) * dir.normal(); | |
133 | accel -= (desired_dist - dist) * normalise(dir); | |
134 | 134 | return; |
135 | 135 | } |
136 | 136 | |
137 | 137 | if(dist > gGourceBeamDist) { |
138 | accel += (dist-gGourceBeamDist) * dir.normal(); | |
138 | accel += (dist-gGourceBeamDist) * normalise(dir); | |
139 | 139 | } |
140 | 140 | } |
141 | 141 | |
197 | 197 | if(findimage != gGourceSettings.user_image_map.end()) { |
198 | 198 | std::string imagefile = findimage->second; |
199 | 199 | |
200 | if(!gGourceSettings.colour_user_images) usercol = vec3f(1.0, 1.0, 1.0); | |
201 | ||
202 | graphic = texturemanager.grabFile(imagefile); | |
203 | } | |
204 | } | |
200 | if(!gGourceSettings.colour_user_images) usercol = vec3(1.0, 1.0, 1.0); | |
201 | ||
202 | graphic = texturemanager.grabFile(imagefile, true, GL_CLAMP_TO_EDGE); | |
203 | } | |
204 | } | |
205 | ||
206 | ||
207 | //TODO: trilinear probably should be an attribute of the texture | |
208 | // perhaps the mipmap option should be an enum: eg TEX_MIPMAP_TRILINEAR | |
205 | 209 | |
206 | 210 | //nope |
207 | 211 | if(!graphic) { |
208 | 212 | if(gGourceSettings.default_user_image.size() > 0) { |
209 | if(!gGourceSettings.colour_user_images) usercol = vec3f(1.0, 1.0, 1.0); | |
210 | graphic = texturemanager.grabFile(gGourceSettings.default_user_image); | |
213 | if(!gGourceSettings.colour_user_images) usercol = vec3(1.0, 1.0, 1.0); | |
214 | graphic = texturemanager.grabFile(gGourceSettings.default_user_image, true, GL_CLAMP_TO_EDGE); | |
211 | 215 | } else { |
212 | graphic = texturemanager.grab("no_photo.png"); | |
216 | graphic = texturemanager.grab("user.png", true, GL_CLAMP_TO_EDGE); | |
213 | 217 | } |
214 | 218 | } |
215 | 219 | |
216 | 220 | setGraphic(graphic); |
217 | 221 | |
218 | usercol = usercol * 0.6 + vec3f(1.0, 1.0, 1.0) * 0.4; | |
219 | usercol *= 0.9; | |
222 | usercol = usercol * 0.6f + vec3(1.0f) * 0.4f; | |
223 | usercol *= 0.9f; | |
220 | 224 | } |
221 | 225 | |
222 | 226 | int RUser::getActionCount() { |
254 | 258 | |
255 | 259 | if(!find_nearby_action) break; |
256 | 260 | |
257 | float action_dist = (action->target->getAbsolutePos() - pos).length(); | |
261 | float action_dist = glm::length(action->target->getAbsolutePos() - pos); | |
258 | 262 | |
259 | 263 | //queue first action in range |
260 | 264 | if(action_dist < gGourceBeamDist) { |
291 | 295 | it++; |
292 | 296 | } |
293 | 297 | |
294 | if(accel.length2() > speed * speed) { | |
295 | accel = accel.normal() * speed; | |
298 | if(glm::length2(accel) > speed * speed) { | |
299 | accel = normalise(accel) * speed; | |
296 | 300 | } |
297 | 301 | |
298 | 302 | pos += accel * dt; |
299 | 303 | |
300 | 304 | accel = accel * std::max(0.0f, (1.0f - gGourceSettings.user_friction*dt)); |
301 | ||
302 | //ensure characters dont crawl | |
303 | // float accel_amount = accel.length(); | |
304 | // if(!actions.empty() && accel_amount > 0.0 && accel_amount < min_units_ps) { | |
305 | // accel = accel.normal() * min_units_ps; | |
306 | // } | |
307 | ||
308 | // move(dt); | |
309 | 305 | } |
310 | 306 | |
311 | 307 | void RUser::updateFont() { |
333 | 329 | updateFont(); |
334 | 330 | } |
335 | 331 | |
336 | const vec3f& RUser::getNameColour() const { | |
337 | return (selected||highlighted) ? selectedcol : namecol; | |
338 | } | |
339 | ||
340 | vec3f RUser::getColour() const{ | |
341 | if(selected) return vec3f(1.0, 1.0, 1.0); | |
332 | const vec3& RUser::getNameColour() const { | |
333 | return selected ? gGourceSettings.selection_colour : highlighted ? gGourceSettings.highlight_colour : namecol; | |
334 | } | |
335 | ||
336 | vec3 RUser::getColour() const{ | |
337 | if(selected) return vec3(1.0, 1.0, 1.0); | |
342 | 338 | |
343 | 339 | return usercol; |
344 | 340 | } |
377 | 373 | |
378 | 374 | static GLdouble screen_x, screen_y, screen_z; |
379 | 375 | |
380 | vec2f text_pos = pos; | |
376 | vec2 text_pos = pos; | |
381 | 377 | text_pos.y -= dims.y * 0.5f; |
382 | 378 | |
383 | 379 | gluProject( text_pos.x, text_pos.y, 0.0f, modelview, projection, viewport, &screen_x, &screen_y, &screen_z); |
392 | 388 | float user_alpha = getAlpha(); |
393 | 389 | |
394 | 390 | if(gGourceSettings.highlight_all_users || highlighted || selected || alpha>0.0) { |
395 | vec3f name_col = getNameColour(); | |
391 | vec3 name_col = getNameColour(); | |
396 | 392 | float name_alpha = (selected||highlighted||gGourceSettings.highlight_all_users) ? user_alpha : alpha; |
397 | 393 | |
398 | font.setColour(vec4f(name_col.x, name_col.y, name_col.z, name_alpha)); | |
394 | font.setColour(vec4(name_col.x, name_col.y, name_col.z, name_alpha)); | |
399 | 395 | font.draw(screenpos.x, screenpos.y, name); |
400 | 396 | } |
401 | 397 | } |
47 | 47 | float min_units_ps; |
48 | 48 | |
49 | 49 | std::string name; |
50 | vec3f usercol; | |
50 | vec3 usercol; | |
51 | 51 | |
52 | 52 | bool highlighted; |
53 | 53 | |
54 | 54 | bool nameVisible() const; |
55 | 55 | |
56 | 56 | void updateFont(); |
57 | const vec3f& getNameColour() const; | |
57 | const vec3& getNameColour() const; | |
58 | 58 | void drawNameText(float alpha); |
59 | 59 | public: |
60 | RUser(const std::string& name, vec2f pos, int tagid); | |
60 | RUser(const std::string& name, vec2 pos, int tagid); | |
61 | 61 | |
62 | vec3f getColour() const; | |
62 | vec3 getColour() const; | |
63 | 63 | void colourize(); |
64 | 64 | |
65 | 65 | const std::string& getName() const; |
19 | 19 | ZoomCamera::ZoomCamera() { |
20 | 20 | } |
21 | 21 | |
22 | ZoomCamera::ZoomCamera(vec3f start, vec3f target, float min_distance, float max_distance) : Camera(start,target) { | |
23 | dest = start; | |
24 | up = vec3f(0.0f, -1.0f, 0.0f); | |
22 | ZoomCamera::ZoomCamera(vec3 pos, vec3 target, float min_distance, float max_distance) : | |
23 | pos(pos), _pos(pos), target(target), _target(target), dest(pos), fov(90.0f) { | |
24 | ||
25 | znear = 0.1; | |
26 | ||
27 | up = vec3(0.0f, -1.0f, 0.0f); | |
25 | 28 | |
26 | 29 | setMinDistance(min_distance); |
27 | 30 | setMaxDistance(max_distance); |
34 | 37 | } |
35 | 38 | |
36 | 39 | void ZoomCamera::reset() { |
37 | Camera::reset(); | |
40 | pos = _pos; | |
41 | target = _target; | |
38 | 42 | } |
39 | 43 | |
40 | 44 | float ZoomCamera::getMaxDistance() { return max_distance; } |
62 | 66 | this->lockon = lockon; |
63 | 67 | } |
64 | 68 | |
69 | void ZoomCamera::look() { | |
70 | lookAt(target); | |
71 | } | |
72 | ||
73 | void ZoomCamera::lookAt(const vec3& target) { | |
74 | gluLookAt( pos.x, pos.y, pos.z, | |
75 | target.x, target.y, target.z, | |
76 | up.x, up.y, up.z); | |
77 | } | |
78 | ||
79 | void ZoomCamera::focus() { | |
80 | display.mode3D(fov, znear, zfar); | |
81 | look(); | |
82 | } | |
83 | ||
65 | 84 | void ZoomCamera::stop() { |
66 | 85 | this->dest = pos; |
67 | 86 | } |
77 | 96 | |
78 | 97 | //center camera on bounds |
79 | 98 | |
80 | vec2f centre = bounds.centre(); | |
99 | vec2 centre = bounds.centre(); | |
81 | 100 | |
82 | 101 | //adjust by screen ratio |
83 | 102 | dest.x = centre.x; |
89 | 108 | float width = bounds.width() * padding; |
90 | 109 | float height = bounds.height() * padding; |
91 | 110 | |
92 | float dratio = display.height / (float) display.width; | |
111 | float aspect_ratio = display.width / (float) display.height; | |
93 | 112 | |
94 | if(dratio > 1.0) { | |
95 | height /= dratio; | |
96 | } else { | |
97 | width *= dratio; | |
98 | } | |
113 | if(aspect_ratio < 1.0) { | |
114 | height /= aspect_ratio; | |
115 | } else { | |
116 | width /= aspect_ratio; | |
117 | } | |
99 | 118 | |
100 | 119 | //calc visible width of the opposite wall at a distance of 1 this fov |
101 | float toa = tan( getFov() * 0.5f * DEGREES_TO_RADIANS ) * 2.0; | |
120 | float toa = tan( fov * 0.5f * DEGREES_TO_RADIANS ) * 2.0; | |
102 | 121 | |
103 | 122 | float distance; |
104 | 123 | |
107 | 126 | |
108 | 127 | //cropping: vertical, horizontal or none |
109 | 128 | if(gGourceSettings.crop_vertical) { |
110 | distance = width / toa ; | |
111 | 129 | |
130 | distance = width / toa; | |
131 | ||
132 | ||
112 | 133 | } else if (gGourceSettings.crop_horizontal) { |
113 | distance = height / toa ; | |
114 | 134 | |
135 | distance = height / toa; | |
136 | ||
115 | 137 | } else { |
116 | 138 | |
117 | if(width > height) { | |
118 | distance = width / toa ; | |
139 | if(width >= height) { | |
140 | distance = width / toa; | |
119 | 141 | } else { |
120 | distance = height / toa ; | |
142 | distance = height / toa; | |
121 | 143 | } |
122 | 144 | } |
123 | 145 | |
134 | 156 | dest.z = -distance; |
135 | 157 | } |
136 | 158 | |
159 | void ZoomCamera::setPos(const vec3& pos, bool keep_angle) { | |
160 | if(keep_angle) { | |
161 | vec3 dir = target - this->pos; | |
162 | this->pos = pos; | |
163 | this->target = pos + dir; | |
164 | } else { | |
165 | this->pos = pos; | |
166 | } | |
167 | } | |
168 | ||
137 | 169 | void ZoomCamera::logic(float dt) { |
138 | vec3f dp = (dest - pos); | |
170 | vec3 dp = (dest - pos); | |
139 | 171 | |
140 | vec3f dpt = dp * dt * speed; | |
172 | vec3 dpt = dp * dt * speed; | |
141 | 173 | |
142 | 174 | if(lockon) { |
143 | dpt = dpt * lockon_time + dp * (1.0-lockon_time); | |
175 | dpt = dpt * lockon_time + dp * (1.0f-lockon_time); | |
144 | 176 | |
145 | 177 | if(lockon_time>0.0) { |
146 | 178 | lockon_time = std::max(0.0f, lockon_time-dt*0.5f); |
147 | 179 | } |
148 | 180 | } |
149 | 181 | |
150 | if(dpt.length2() > dp.length2()) dpt = dp; | |
182 | if(glm::length2(dpt) > glm::length2(dp)) dpt = dp; | |
151 | 183 | |
152 | 184 | pos += dpt; |
153 | 185 | |
154 | target = vec3f(pos.x, pos.y, 0.0); | |
186 | target = vec3(pos.x, pos.y, 0.0); | |
155 | 187 | } |
17 | 17 | #ifndef ZOOM_CAMERA_H |
18 | 18 | #define ZOOM_CAMERA_H |
19 | 19 | |
20 | #include "core/camera.h" | |
21 | 20 | #include "core/bounds.h" |
22 | 21 | #include "core/frustum.h" |
23 | 22 | |
24 | 23 | #include "gource_settings.h" |
25 | 24 | |
26 | class ZoomCamera : public Camera { | |
27 | vec3f dest; | |
25 | class ZoomCamera { | |
26 | vec3 pos; | |
27 | vec3 dest; | |
28 | vec3 target; | |
29 | vec3 up; | |
30 | vec3 _pos; | |
31 | vec3 _target; | |
32 | ||
28 | 33 | bool lockon; |
29 | 34 | float speed; |
30 | 35 | float lockon_time; |
31 | 36 | |
32 | 37 | float padding; |
38 | ||
33 | 39 | float min_distance, max_distance; |
40 | ||
41 | float fov; | |
42 | float znear, zfar; | |
34 | 43 | public: |
35 | 44 | ZoomCamera(); |
36 | ZoomCamera(vec3f start, vec3f target, float min_distance, float max_distance); | |
45 | ZoomCamera(vec3 start, vec3 target, float min_distance, float max_distance); | |
37 | 46 | |
38 | 47 | void setSpeed(float speed); |
39 | 48 | |
40 | 49 | void lockOn(bool lockon); |
41 | 50 | |
42 | vec3f getDest() { return dest; } | |
51 | void look(); | |
52 | void lookAt(const vec3& target); | |
53 | void focus(); | |
54 | ||
55 | const vec3& getPos() const { return pos; }; | |
56 | const vec3& getUp() const { return up; }; | |
57 | const vec3& getTarget() const { return target; }; | |
58 | const vec3& getDest() const { return dest; }; | |
43 | 59 | |
60 | float getFOV() { return fov; }; | |
61 | float getZNear() { return znear; }; | |
62 | float getZFar() { return zfar; }; | |
63 | ||
64 | void setPos(const vec3& pos, bool keep_angle = false); | |
65 | ||
44 | 66 | float getMinDistance(); |
45 | 67 | float getMaxDistance(); |
46 | 68 |