From: Charles McGarvey Date: Tue, 27 Jul 2010 04:36:54 +0000 (-0600) Subject: mesh and other random adjustments X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=commitdiff_plain;h=6f1b787a10d8ab1a3117a4b8c004dd2d90599608 mesh and other random adjustments --- diff --git a/arch/gentoo/yoink.ebuild b/arch/gentoo/yoink.ebuild index 16781c7..6e167d0 100644 --- a/arch/gentoo/yoink.ebuild +++ b/arch/gentoo/yoink.ebuild @@ -4,17 +4,17 @@ EAPI=2 -inherit autotools eutils games +inherit eutils games DESCRIPTION="Alien-smashing action game" HOMEPAGE="http://www.dogcows.com/yoink/" -SRC_URI="http://www.dogcows.com/yoink/${P}.tar.bz2 +SRC_URI="http://www.dogcows.com/yoink/chrome/site/${P}.tar.bz2 http://eng.utah.edu/~mcgarvey/yoink/${P}.tar.bz2" LICENSE="BSD-2 BSD LGPL-2.1 ZLIB" SLOT="0" KEYWORDS="amd64 x86" -IUSE="debug double-precision gtk qt4 threads" +IUSE="debug double-precision gtk hotload qt4 threads" RDEPEND="dev-lang/lua media-libs/libpng @@ -22,30 +22,26 @@ RDEPEND="dev-lang/lua media-libs/libvorbis media-libs/openal virtual/glu - virtual/opengl" + virtual/opengl + gtk? ( x11-libs/gtk+:2 ) + qt4? ( !gtk? ( x11-libs/qt-core:4 ) )" DEPEND="${RDEPEND} dev-libs/boost dev-util/pkgconfig" -src_prepare() { - sed -i -e "/apps/d" -e "/pixmap/d" data/Makefile.am || die "sed failed" - sed -i -e "/man/d" Makefile.am || die "sed failed" - - eautoreconf -} - src_configure() { egamesconf \ --disable-dependency-tracking \ $(use_enable debug) \ $(use_enable double-precision) \ + $(use_enable hotload) \ $(use_enable threads) \ $(use_with gtk) \ $(use_with qt4) } src_install() { - emake DESTDIR="${D}" install || die "emake install failed" + emake DESTDIR="${D}" install_man=no install || die "emake failed" dodoc AUTHORS COPYING README TODO doman doc/yoink.6 doicon data/yoink.png diff --git a/configure b/configure index bea16f4..292639c 100755 --- a/configure +++ b/configure @@ -58,7 +58,7 @@ Program options: --enable-clock_gettime use a very accurate timing function --enable-debug compile in assertion checks and other debug helps --enable-double-precision use larger floating-point numbers - --enable-hotloading watch assets and automatically reload them + --enable-hotload automatically reload modified game assets --enable-threads use threads for concurrency where appropriate --with-gtk use the gtk2 toolkit (overrides --with-qt4) @@ -468,17 +468,16 @@ end config.USE_CLOCK_GETTIME = get_feature("clock_gettime") config.USE_DOUBLE_PRECISION = get_feature("double-precision") -config.USE_HOTLOADING = get_feature("hotloading") +config.USE_HOTLOADING = get_feature("hotload") config.USE_THREADS = get_feature("threads") -config.PROFILING_ENABLED = get_feature("profile") and add_cflag("-pg") - -if get_package("gtk") then - -- TODO +if get_feature("profile") then + config.PROFILING_ENABLED = true + add_cflag("-pg") + LDFLAGS = LDFLAGS .. "-pg" end -if get_package("qt4") then - -- TODO -end +if get_package("gtk") then config.USE_GTK = true end +if get_package("qt4") then config.USE_QT4 = true end -- diff --git a/data/models/classic.ac b/data/models/classic.ac index ef7f632..7b13176 100644 --- a/data/models/classic.ac +++ b/data/models/classic.ac @@ -15,40 +15,40 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 34 -23 1 -7 -23 0 -7 -12 0 -7 -12 1 -7 -29 1 -7 -29 0 -7 -33 0 -7 -33 1 -7 -22 0 -7 -21 0 -7 -20 0 -7 -19 0 -7 -18 0 -7 -17 0 -7 -16 0 -7 -15 0 -7 -14 0 -7 -13 0 -7 -22 1 -7 -21 1 -7 -20 1 -7 -19 1 -7 -18 1 -7 -17 1 -7 -16 1 -7 -15 1 -7 -14 1 -7 -13 1 -7 -30 1 -7 -31 1 -7 -32 1 -7 -30 0 -7 -31 0 -7 -32 0 -7 +23 1 -3 +23 0 -3 +12 0 -3 +12 1 -3 +29 1 -3 +29 0 -3 +33 0 -3 +33 1 -3 +22 0 -3 +21 0 -3 +20 0 -3 +19 0 -3 +18 0 -3 +17 0 -3 +16 0 -3 +15 0 -3 +14 0 -3 +13 0 -3 +22 1 -3 +21 1 -3 +20 1 -3 +19 1 -3 +18 1 -3 +17 1 -3 +16 1 -3 +15 1 -3 +14 1 -3 +13 1 -3 +30 1 -3 +31 1 -3 +32 1 -3 +30 0 -3 +31 0 -3 +32 0 -3 numsurf 15 SURF 0x00 mat 1 @@ -164,80 +164,80 @@ texture "Building.png" texrep 1 1 crease 30.000000 numvert 74 -18 0 -6 18 0 -2 +18 0 2 +15 0 2 15 0 -2 -15 0 -6 +18 3 2 +15 3 2 18 3 -2 15 3 -2 -18 3 -6 -15 3 -6 +18 1 2 +18 2 2 +15 1 2 +15 2 2 18 1 -2 18 2 -2 15 1 -2 15 2 -2 -18 1 -6 -18 2 -6 -15 1 -6 -15 2 -6 -17 0 -2 -16 0 -2 -17 3 -2 -16 3 -2 -16 1 -2 -17 1 -2 -16 2 -2 -17 2 -2 -18 0 -5 -18 0 -4 -18 0 -3 -18 3 -3 -18 3 -4 -18 3 -5 -18 1 -3 -18 1 -4 -18 1 -5 -18 2 -3 -18 2 -4 -18 2 -5 -15 0 -3 -15 0 -4 -15 0 -5 -15 3 -3 -15 3 -4 -15 3 -5 -15 1 -3 -15 1 -4 -15 1 -5 -15 2 -3 -15 2 -4 -15 2 -5 -15 5.499999 -4.000002 -18 5.499999 -4.000002 -16 5.499999 -4.000002 -17 5.499999 -4.000002 -15 4 -5 -15 4 -4 -15 4 -3 -18 4 -5 -18 4 -4 -18 4 -3 -18 5 -4 -18 2.8 -1.8 -15 2.8 -1.8 -15 5 -4 -17 2.8 -1.8 -16 2.8 -1.8 -18 4.266666 -3.266667 -18 3.533333 -2.533333 -17 5 -4 -16 5 -4 -15 3.533333 -2.533334 -15 4.266666 -3.266667 -16 3.533333 -2.533334 -17 3.533333 -2.533333 -16 4.266666 -3.266667 -17 4.266666 -3.266667 +17 0 2 +16 0 2 +17 3 2 +16 3 2 +16 1 2 +17 1 2 +16 2 2 +17 2 2 +18 0 -1 +18 0 0 +18 0 1 +18 3 1 +18 3 0 +18 3 -1 +18 1 1 +18 1 0 +18 1 -1 +18 2 1 +18 2 0 +18 2 -1 +15 0 1 +15 0 0 +15 0 -1 +15 3 1 +15 3 0 +15 3 -1 +15 1 1 +15 1 0 +15 1 -1 +15 2 1 +15 2 0 +15 2 -1 +15 5.499999 -2e-06 +18 5.499999 -2e-06 +16 5.499999 -2e-06 +17 5.499999 -2e-06 +15 4 -1 +15 4 0 +15 4 1 +18 4 -1 +18 4 0 +18 4 1 +18 5 0 +18 2.8 2.2 +15 2.8 2.2 +15 5 0 +17 2.8 2.2 +16 2.8 2.2 +18 4.266666 0.733333 +18 3.533333 1.466667 +17 5 0 +16 5 0 +15 3.533333 1.466666 +15 4.266666 0.733333 +16 3.533333 1.466666 +17 3.533333 1.466667 +16 4.266666 0.733333 +17 4.266666 0.733333 numsurf 57 SURF 0x00 mat 2 @@ -540,9 +540,9 @@ refs 3 SURF 0x00 mat 2 refs 3 -5 0.375 0.75 -54 0.5 0.5 -39 0.375 0.5 +5 0.499525219202 0.500041484833 +54 0.374525249004 0.750041484833 +39 0.374525249004 0.500041425228 SURF 0x00 mat 2 refs 3 @@ -553,19 +553,19 @@ SURF 0x00 mat 2 refs 3 56 0.25 0.5 -58 0.124999992549 0.5 -57 0.25 0.75 +58 0.25 0.75 +57 0.125 0.5 SURF 0x00 mat 2 refs 3 -55 0.375 0.75 -58 0.5 0.5 +55 0.5 0.5 +58 0.375 0.75 56 0.375 0.5 SURF 0x00 mat 2 refs 3 -6 0.375 0.75 -55 0.5 0.5 +6 0.5 0.5 +55 0.375 0.75 29 0.375 0.5 SURF 0x00 mat 2 @@ -637,17 +637,17 @@ data 6 L-Lawn crease 30.000000 numvert 11 +6 0 2 +2 0 4 +2 0 2 +14 0 2 +5 0 -3 +15 0 -3 6 0 -2 -2 0 0 -2 0 -2 14 0 -2 -5 0 -7 -15 0 -7 -6 0 -6 -14 0 -6 -5 0 -2 -15 0 0 -5 0 0 +5 0 2 +15 0 4 +5 0 4 numsurf 6 SURF 0x30 mat 3 @@ -699,78 +699,50 @@ texture "TowerBlock1.png" texrep 1 1 crease 30.000000 numvert 182 -12 0 -7 -5 0 -7 -5 8 -7 -12 8 -7 -3 8 -7 -12 0 -13 -12 0 -12 -12 0 -11 -12 0 -10 +12 0 -3 +5 0 -3 +5 8 -3 +12 8 -3 +3 8 -3 12 0 -9 12 0 -8 +12 0 -7 +12 0 -6 +12 0 -5 +12 0 -4 +12 8 -4 +12 8 -5 +12 8 -6 +12 8 -7 12 8 -8 12 8 -9 -12 8 -10 -12 8 -11 -12 8 -12 -12 8 -13 -3 8 -13 -3 8 -12 -3 8 -11 -3 8 -10 3 8 -9 3 8 -8 -5 1 -7 -5 2 -7 -5 3 -7 -5 4 -7 -5 5 -7 -5 6 -7 -5 7 -7 -12 1 -7 -12 2 -7 -12 3 -7 -12 4 -7 -12 5 -7 -12 6 -7 -12 7 -7 -12 1 -13 -12 2 -13 -12 3 -13 -12 4 -13 -12 5 -13 -12 6 -13 -12 7 -13 -12 7 -12 -12 6 -12 -12 5 -12 -12 4 -12 -12 3 -12 -12 2 -12 -12 1 -12 -12 7 -11 -12 6 -11 -12 5 -11 -12 4 -11 -12 3 -11 -12 2 -11 -12 1 -11 -12 1 -10 -12 2 -10 -12 3 -10 -12 4 -10 -12 5 -10 -12 6 -10 -12 7 -10 -12 7 -9 -12 6 -9 -12 5 -9 -12 4 -9 -12 3 -9 -12 2 -9 +3 8 -7 +3 8 -6 +3 8 -5 +3 8 -4 +5 1 -3 +5 2 -3 +5 3 -3 +5 4 -3 +5 5 -3 +5 6 -3 +5 7 -3 +12 1 -3 +12 2 -3 +12 3 -3 +12 4 -3 +12 5 -3 +12 6 -3 +12 7 -3 12 1 -9 +12 2 -9 +12 3 -9 +12 4 -9 +12 5 -9 +12 6 -9 +12 7 -9 12 7 -8 12 6 -8 12 5 -8 @@ -778,86 +750,82 @@ numvert 182 12 3 -8 12 2 -8 12 1 -8 -11 0 -7 -10 0 -7 -9 0 -7 -8 0 -7 -7 0 -7 -6 0 -7 -6 1 -7 -7 1 -7 -8 1 -7 -9 1 -7 -10 1 -7 -11 1 -7 -6 2 -7 -7 2 -7 -8 2 -7 -9 2 -7 -10 2 -7 -11 2 -7 -6 3 -7 -7 3 -7 -8 3 -7 -9 3 -7 -10 3 -7 -11 3 -7 -6 4 -7 -7 4 -7 -8 4 -7 -9 4 -7 -10 4 -7 -11 4 -7 -6 5 -7 -7 5 -7 -8 5 -7 -9 5 -7 -10 5 -7 -11 5 -7 -6 6 -7 -7 6 -7 -8 6 -7 -9 6 -7 -10 6 -7 -11 6 -7 -6 7 -7 -7 7 -7 -8 7 -7 -9 7 -7 -10 7 -7 -11 7 -7 -11 8 -13 -10 8 -13 -9 8 -13 -8 8 -13 -7 8 -13 -6 8 -13 -5 8 -13 -4 8 -13 -11 8 -12 -10 8 -12 -9 8 -12 -8 8 -12 -7 8 -12 -6 8 -12 -5 8 -12 -4 8 -12 -11 8 -11 -10 8 -11 -9 8 -11 -8 8 -11 -7 8 -11 -6 8 -11 -5 8 -11 -4 8 -11 -11 8 -10 -10 8 -10 -9 8 -10 -8 8 -10 -7 8 -10 -6 8 -10 -5 8 -10 -4 8 -10 +12 7 -7 +12 6 -7 +12 5 -7 +12 4 -7 +12 3 -7 +12 2 -7 +12 1 -7 +12 1 -6 +12 2 -6 +12 3 -6 +12 4 -6 +12 5 -6 +12 6 -6 +12 7 -6 +12 7 -5 +12 6 -5 +12 5 -5 +12 4 -5 +12 3 -5 +12 2 -5 +12 1 -5 +12 7 -4 +12 6 -4 +12 5 -4 +12 4 -4 +12 3 -4 +12 2 -4 +12 1 -4 +11 0 -3 +10 0 -3 +9 0 -3 +8 0 -3 +7 0 -3 +6 0 -3 +6 1 -3 +7 1 -3 +8 1 -3 +9 1 -3 +10 1 -3 +11 1 -3 +6 2 -3 +7 2 -3 +8 2 -3 +9 2 -3 +10 2 -3 +11 2 -3 +6 3 -3 +7 3 -3 +8 3 -3 +9 3 -3 +10 3 -3 +11 3 -3 +6 4 -3 +7 4 -3 +8 4 -3 +9 4 -3 +10 4 -3 +11 4 -3 +6 5 -3 +7 5 -3 +8 5 -3 +9 5 -3 +10 5 -3 +11 5 -3 +6 6 -3 +7 6 -3 +8 6 -3 +9 6 -3 +10 6 -3 +11 6 -3 +6 7 -3 +7 7 -3 +8 7 -3 +9 7 -3 +10 7 -3 +11 7 -3 11 8 -9 10 8 -9 9 8 -9 @@ -874,13 +842,45 @@ numvert 182 6 8 -8 5 8 -8 4 8 -8 -4 8 -7 11 8 -7 10 8 -7 9 8 -7 8 8 -7 7 8 -7 6 8 -7 +5 8 -7 +4 8 -7 +11 8 -6 +10 8 -6 +9 8 -6 +8 8 -6 +7 8 -6 +6 8 -6 +5 8 -6 +4 8 -6 +11 8 -5 +10 8 -5 +9 8 -5 +8 8 -5 +7 8 -5 +6 8 -5 +5 8 -5 +4 8 -5 +11 8 -4 +10 8 -4 +9 8 -4 +8 8 -4 +7 8 -4 +6 8 -4 +5 8 -4 +4 8 -4 +4 8 -3 +11 8 -3 +10 8 -3 +9 8 -3 +8 8 -3 +7 8 -3 +6 8 -3 numsurf 158 SURF 0x00 mat 4 @@ -1997,10 +1997,17 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 45 -14 0 -6 14 0 -2 +14 0 2 +6 0 2 6 0 -2 -6 0 -6 +13 0 2 +12 0 2 +11 0 2 +10 0 2 +9 0 2 +8 0 2 +7 0 2 13 0 -2 12 0 -2 11 0 -2 @@ -2008,40 +2015,33 @@ numvert 45 9 0 -2 8 0 -2 7 0 -2 -13 0 -6 -12 0 -6 -11 0 -6 -10 0 -6 -9 0 -6 -8 0 -6 -7 0 -6 -14 0 -5 -14 0 -4 -14 0 -3 -6 0 -3 -6 0 -4 -6 0 -5 -13 0 -5 -13 0 -4 -13 0 -3 -12 0 -5 -12 0 -4 -12 0 -3 -11 0 -5 -11 0 -4 -11 0 -3 -10 0 -5 -10 0 -4 -10 0 -3 -9 0 -3 -9 0 -4 -9 0 -5 -8 0 -3 -8 0 -4 -8 0 -5 -7 0 -3 -7 0 -4 -7 0 -5 +14 0 -1 +14 0 0 +14 0 1 +6 0 1 +6 0 0 +6 0 -1 +13 0 -1 +13 0 0 +13 0 1 +12 0 -1 +12 0 0 +12 0 1 +11 0 -1 +11 0 0 +11 0 1 +10 0 -1 +10 0 0 +10 0 1 +9 0 1 +9 0 0 +9 0 -1 +8 0 1 +8 0 0 +8 0 -1 +7 0 1 +7 0 0 +7 0 -1 numsurf 32 SURF 0x00 mat 1 @@ -2276,137 +2276,67 @@ texture "TowerBlock1.png" texrep 1 1 crease 30.000000 numvert 201 -5 0 -7 -5 0 -2 -0 0 -2 -0 15 -7 -0 15 -2 -5 15 -2 -5 15 -7 -0 15 -6 -0 15 -5 -0 15 -4 +5 0 -3 +5 0 2 +0 0 2 0 15 -3 +0 15 2 +5 15 2 5 15 -3 -5 15 -4 -5 15 -5 -5 15 -6 -5 0 -6 -5 0 -5 -5 0 -4 -5 0 -3 -1 15 -7 -2 15 -7 -3 15 -7 -4 15 -7 -1 15 -2 -2 15 -2 -3 15 -2 -4 15 -2 -1 0 -2 -2 0 -2 -3 0 -2 -4 0 -2 -1 15 -6 -2 15 -6 -3 15 -6 -4 15 -6 -1 15 -5 -2 15 -5 -3 15 -5 -4 15 -5 -1 15 -4 -2 15 -4 -3 15 -4 -4 15 -4 +0 15 -2 +0 15 -1 +0 15 0 +0 15 1 +5 15 1 +5 15 0 +5 15 -1 +5 15 -2 +5 0 -2 +5 0 -1 +5 0 0 +5 0 1 1 15 -3 2 15 -3 3 15 -3 4 15 -3 -0 14 -2 -0 13 -2 -0 12 -2 -0 11 -2 -0 10 -2 -0 9 -2 -0 8 -2 -0 7 -2 -0 6 -2 -0 5 -2 -0 4 -2 -0 3 -2 -0 2 -2 -0 1 -2 -5 14 -7 -5 13 -7 -5 12 -7 -5 11 -7 -5 10 -7 -5 9 -7 -5 8 -7 -5 7 -7 -5 6 -7 -5 5 -7 -5 4 -7 -5 3 -7 -5 2 -7 -5 1 -7 -5 14 -2 -5 13 -2 -5 12 -2 -5 11 -2 -5 10 -2 -5 9 -2 -5 8 -2 -5 7 -2 -5 6 -2 -5 5 -2 -5 4 -2 -5 3 -2 -5 2 -2 -5 1 -2 -5 14 -6 -5 13 -6 -5 12 -6 -5 11 -6 -5 10 -6 -5 9 -6 -5 8 -6 -5 7 -6 -5 6 -6 -5 5 -6 -5 4 -6 -5 3 -6 -5 2 -6 -5 1 -6 -5 14 -5 -5 13 -5 -5 12 -5 -5 11 -5 -5 10 -5 -5 9 -5 -5 8 -5 -5 7 -5 -5 6 -5 -5 5 -5 -5 4 -5 -5 3 -5 -5 2 -5 -5 1 -5 -5 14 -4 -5 13 -4 -5 12 -4 -5 11 -4 -5 10 -4 -5 9 -4 -5 8 -4 -5 7 -4 -5 6 -4 -5 5 -4 -5 4 -4 -5 3 -4 -5 2 -4 -5 1 -4 +1 15 2 +2 15 2 +3 15 2 +4 15 2 +1 0 2 +2 0 2 +3 0 2 +4 0 2 +1 15 -2 +2 15 -2 +3 15 -2 +4 15 -2 +1 15 -1 +2 15 -1 +3 15 -1 +4 15 -1 +1 15 0 +2 15 0 +3 15 0 +4 15 0 +1 15 1 +2 15 1 +3 15 1 +4 15 1 +0 14 2 +0 13 2 +0 12 2 +0 11 2 +0 10 2 +0 9 2 +0 8 2 +0 7 2 +0 6 2 +0 5 2 +0 4 2 +0 3 2 +0 2 2 +0 1 2 5 14 -3 5 13 -3 5 12 -3 @@ -2421,101 +2351,133 @@ numvert 201 5 3 -3 5 2 -3 5 1 -3 -4 1 -2 -4 2 -2 -4 3 -2 -4 4 -2 -4 5 -2 -4 6 -2 -4 7 -2 -4 8 -2 -4 9 -2 -4 10 -2 -4 11 -2 -4 12 -2 -4 13 -2 -4 14 -2 -3 14 -2 -3 13 -2 -3 12 -2 -3 11 -2 -3 10 -2 -3 9 -2 -3 8 -2 -3 7 -2 -3 6 -2 -3 5 -2 -3 4 -2 -3 3 -2 -3 2 -2 -3 1 -2 -2 1 -2 -2 2 -2 -2 3 -2 -2 4 -2 -2 5 -2 -2 6 -2 -2 7 -2 -2 8 -2 -2 9 -2 -2 10 -2 -2 11 -2 -2 12 -2 -2 13 -2 -2 14 -2 -1 1 -2 -1 2 -2 -1 3 -2 -1 4 -2 -1 5 -2 -1 6 -2 -1 7 -2 -1 8 -2 -1 9 -2 -1 10 -2 -1 11 -2 -1 12 -2 -1 13 -2 -1 14 -2 -numsurf 181 -SURF 0x00 -mat 4 -refs 4 -1 -1.49011611938e-08 1.0 -0 0.0 0.75 -16 0.25 0.75 -17 0.25 1.0 -SURF 0x00 -mat 4 -refs 3 -16 -1.49011611938e-08 1.0 -0 0.0 0.75 -15 0.25 0.75 -SURF 0x00 -mat 4 -refs 3 -17 -1.49011611938e-08 1.0 -18 0.0 0.75 -1 0.25 0.75 -SURF 0x00 -mat 4 -refs 4 -29 -1.49011611938e-08 1.0 -28 0.0 0.75 -2 0.25 0.75 -1 0.25 1.0 -SURF 0x00 -mat 4 -refs 3 -30 -1.49011611938e-08 1.0 -29 0.0 0.75 -1 0.25 0.75 -SURF 0x00 -mat 4 -refs 3 -28 -1.49011611938e-08 1.0 -27 0.0 0.75 -2 0.25 0.75 +5 14 2 +5 13 2 +5 12 2 +5 11 2 +5 10 2 +5 9 2 +5 8 2 +5 7 2 +5 6 2 +5 5 2 +5 4 2 +5 3 2 +5 2 2 +5 1 2 +5 14 -2 +5 13 -2 +5 12 -2 +5 11 -2 +5 10 -2 +5 9 -2 +5 8 -2 +5 7 -2 +5 6 -2 +5 5 -2 +5 4 -2 +5 3 -2 +5 2 -2 +5 1 -2 +5 14 -1 +5 13 -1 +5 12 -1 +5 11 -1 +5 10 -1 +5 9 -1 +5 8 -1 +5 7 -1 +5 6 -1 +5 5 -1 +5 4 -1 +5 3 -1 +5 2 -1 +5 1 -1 +5 14 0 +5 13 0 +5 12 0 +5 11 0 +5 10 0 +5 9 0 +5 8 0 +5 7 0 +5 6 0 +5 5 0 +5 4 0 +5 3 0 +5 2 0 +5 1 0 +5 14 1 +5 13 1 +5 12 1 +5 11 1 +5 10 1 +5 9 1 +5 8 1 +5 7 1 +5 6 1 +5 5 1 +5 4 1 +5 3 1 +5 2 1 +5 1 1 +4 1 2 +4 2 2 +4 3 2 +4 4 2 +4 5 2 +4 6 2 +4 7 2 +4 8 2 +4 9 2 +4 10 2 +4 11 2 +4 12 2 +4 13 2 +4 14 2 +3 14 2 +3 13 2 +3 12 2 +3 11 2 +3 10 2 +3 9 2 +3 8 2 +3 7 2 +3 6 2 +3 5 2 +3 4 2 +3 3 2 +3 2 2 +3 1 2 +2 1 2 +2 2 2 +2 3 2 +2 4 2 +2 5 2 +2 6 2 +2 7 2 +2 8 2 +2 9 2 +2 10 2 +2 11 2 +2 12 2 +2 13 2 +2 14 2 +1 1 2 +1 2 2 +1 3 2 +1 4 2 +1 5 2 +1 6 2 +1 7 2 +1 8 2 +1 9 2 +1 10 2 +1 11 2 +1 12 2 +1 13 2 +1 14 2 +numsurf 175 SURF 0x00 mat 4 refs 4 @@ -3750,10 +3712,10 @@ texture "Trees.png" texrep 1 1 crease 30.000000 numvert 4 -12.7 3 -6.46203 -12.7 0 -6.46203 -15.7 0 -6.46203 -15.7 3 -6.46203 +12.7 3 -2.46203 +12.7 0 -2.46203 +15.7 0 -2.46203 +15.7 3 -2.46203 numsurf 1 SURF 0x00 mat 5 @@ -3771,14 +3733,21 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 48 +14 0.5 2 14 0.5 -2 -14 0.5 -6 -6 0.5 -6 6 0.5 -2 -14 0 -6 -6 0 -6 +6 0.5 2 14 0 -2 6 0 -2 +14 0 2 +6 0 2 +13 0.5 2 +12 0.5 2 +11 0.5 2 +10 0.5 2 +9 0.5 2 +8 0.5 2 +7 0.5 2 13 0.5 -2 12 0.5 -2 11 0.5 -2 @@ -3786,13 +3755,13 @@ numvert 48 9 0.5 -2 8 0.5 -2 7 0.5 -2 -13 0.5 -6 -12 0.5 -6 -11 0.5 -6 -10 0.5 -6 -9 0.5 -6 -8 0.5 -6 -7 0.5 -6 +13 0 2 +12 0 2 +11 0 2 +10 0 2 +9 0 2 +8 0 2 +7 0 2 13 0 -2 12 0 -2 11 0 -2 @@ -3800,25 +3769,18 @@ numvert 48 9 0 -2 8 0 -2 7 0 -2 -13 0 -6 -12 0 -6 -11 0 -6 -10 0 -6 -9 0 -6 -8 0 -6 -7 0 -6 -14 0.5 -3 -14 0.5 -4 -14 0.5 -5 -6 0.5 -5 -6 0.5 -4 -6 0.5 -3 -14 0 -5 -14 0 -4 -14 0 -3 -6 0 -5 -6 0 -4 -6 0 -3 +14 0.5 1 +14 0.5 0 +14 0.5 -1 +6 0.5 -1 +6 0.5 0 +6 0.5 1 +14 0 -1 +14 0 0 +14 0 1 +6 0 -1 +6 0 0 +6 0 1 numsurf 24 SURF 0x30 mat 1 @@ -3997,96 +3959,96 @@ texture "Building.png" texrep 1 1 crease 30.000000 numvert 90 -28 0 -10 -28 0 -7 -24 0 -7 -24 0 -10 -28 4 -7 -24 4 -7 -28 4 -10 -24 4 -10 -26 6 -7 -26 6 -10 -26 6.5 -7 -26 6.5 -10 -28 0 -9 -28 0 -8 -24 0 -8 -24 0 -9 -28 4 -8 -28 4 -9 -24 4 -8 -24 4 -9 -26 6 -8 -26 6 -9 -26 6.5 -8 -26 6.5 -9 -28 1 -7 -28 2 -7 -28 3 -7 -24 1 -7 -24 2 -7 -24 3 -7 -28 1 -10 -28 2 -10 -28 3 -10 -24 1 -10 -24 2 -10 -24 3 -10 -28 1 -8 -28 2 -8 -28 3 -8 -28 3 -9 -28 2 -9 -28 1 -9 -24 1 -9 -24 2 -9 -24 3 -9 -24 1 -8 -24 2 -8 -24 3 -8 -27 0 -7 -26 0 -7 -25 0 -7 -27 4 -7 -26 4 -7 -25 4 -7 -25 1 -7 -26 1 -7 -27 1 -7 -27 2 -7 -26 2 -7 -25 2 -7 -25 3 -7 -26 3 -7 -27 3 -7 -25 5 -7 -27 5 -7 -26 5 -7 -23.878679 3.87868 -7 -23.878679 3.87868 -10 -28.121321 3.87868 -7 -28.121321 3.87868 -10 -24.585787 4.585787 -7 -25.292892 5.292893 -7 -25.292892 5.292893 -10 -24.585787 4.585787 -10 -23.878679 3.87868 -8 -23.878679 3.87868 -9 -24.585787 4.585787 -8 -25.292892 5.292893 -8 -24.585787 4.585787 -9 -25.292892 5.292893 -9 -27.414213 4.585786 -10 -26.707108 5.292893 -10 -28.121321 3.87868 -8 -28.121321 3.87868 -9 -27.414213 4.585787 -7 -26.707108 5.292893 -7 -26.707108 5.292893 -8 -27.414213 4.585786 -8 -26.707108 5.292893 -9 -27.414213 4.585786 -9 +28 0 -6 +28 0 -3 +24 0 -3 +24 0 -6 +28 4 -3 +24 4 -3 +28 4 -6 +24 4 -6 +26 6 -3 +26 6 -6 +26 6.5 -3 +26 6.5 -6 +28 0 -5 +28 0 -4 +24 0 -4 +24 0 -5 +28 4 -4 +28 4 -5 +24 4 -4 +24 4 -5 +26 6 -4 +26 6 -5 +26 6.5 -4 +26 6.5 -5 +28 1 -3 +28 2 -3 +28 3 -3 +24 1 -3 +24 2 -3 +24 3 -3 +28 1 -6 +28 2 -6 +28 3 -6 +24 1 -6 +24 2 -6 +24 3 -6 +28 1 -4 +28 2 -4 +28 3 -4 +28 3 -5 +28 2 -5 +28 1 -5 +24 1 -5 +24 2 -5 +24 3 -5 +24 1 -4 +24 2 -4 +24 3 -4 +27 0 -3 +26 0 -3 +25 0 -3 +27 4 -3 +26 4 -3 +25 4 -3 +25 1 -3 +26 1 -3 +27 1 -3 +27 2 -3 +26 2 -3 +25 2 -3 +25 3 -3 +26 3 -3 +27 3 -3 +25 5 -3 +27 5 -3 +26 5 -3 +23.878679 3.87868 -3 +23.878679 3.87868 -6 +28.121321 3.87868 -3 +28.121321 3.87868 -6 +24.585787 4.585787 -3 +25.292892 5.292893 -3 +25.292892 5.292893 -6 +24.585787 4.585787 -6 +23.878679 3.87868 -4 +23.878679 3.87868 -5 +24.585787 4.585787 -4 +25.292892 5.292893 -4 +24.585787 4.585787 -5 +25.292892 5.292893 -5 +27.414213 4.585786 -6 +26.707108 5.292893 -6 +28.121321 3.87868 -4 +28.121321 3.87868 -5 +27.414213 4.585787 -3 +26.707108 5.292893 -3 +26.707108 5.292893 -4 +27.414213 4.585786 -4 +26.707108 5.292893 -5 +27.414213 4.585786 -5 numsurf 67 SURF 0x20 mat 2 @@ -4404,9 +4366,9 @@ refs 3 SURF 0x00 mat 2 refs 3 -8 0.5 0.5 +8 0.375 0.75 65 0.375 0.5 -64 0.375 0.75 +64 0.5 0.5 SURF 0x00 mat 2 refs 4 @@ -4418,14 +4380,14 @@ SURF 0x00 mat 2 refs 4 52 0.375 0.5 -65 0.25 0.5 +65 0.375 0.75 63 0.25 0.75 -53 0.375 0.75 +53 0.25 0.5 SURF 0x00 mat 2 refs 3 -4 0.375 0.75 -64 0.5 0.5 +4 0.5 0.5 +64 0.375 0.75 51 0.375 0.5 SURF 0x00 mat 2 @@ -4560,30 +4522,30 @@ data 6 M-Lawn crease 30.000000 numvert 24 -31 0 -2 -31 0 0 -15 0 0 +31 0 2 +31 0 4 +15 0 4 +15 0 2 +23 0 -3 +23 0 -2 15 0 -2 -23 0 -7 -23 0 -6 -15 0 -6 -15 0 -7 -18 0 -6 -18 0 -5 -19 0 -5 -19 0 -6 -19 0 -4 -19 0 -2 +15 0 -3 18 0 -2 -18 0 -4 -28 0 -5 -28 0 -3 -24 0 -3 -24 0 -5 -33 0 -7 -33 0 -6 -29 0 -6 -29 0 -7 +18 0 -1 +19 0 -1 +19 0 -2 +19 0 0 +19 0 2 +18 0 2 +18 0 0 +28 0 -1 +28 0 1 +24 0 1 +24 0 -1 +33 0 -3 +33 0 -2 +29 0 -2 +29 0 -3 numsurf 6 SURF 0x00 mat 3 @@ -4636,174 +4598,174 @@ texture "TowerBlock1.png" texrep 1 1 crease 30.000000 numvert 168 -38 0 -9 -38 0 -3 +38 0 -5 +38 0 1 +33 0 1 +33 0 -5 +33 0 0 +33 0 -1 +33 0 -2 33 0 -3 -33 0 -9 33 0 -4 -33 0 -5 -33 0 -6 -33 0 -7 -33 0 -8 -33 1 -3 -33 2 -3 -33 3 -3 -33 4 -3 -33 5 -3 +33 1 1 +33 2 1 +33 3 1 +33 4 1 +33 5 1 +33 6 1 +38 1 -5 +38 2 -5 +38 3 -5 +38 4 -5 +38 5 -5 +38 6 -5 +38 1 1 +38 2 1 +38 3 1 +38 4 1 +38 5 1 +38 6 1 +33 6 -5 +33 5 -5 +33 4 -5 +33 3 -5 +33 2 -5 +33 1 -5 +33 6 0 +33 5 0 +33 4 0 +33 3 0 +33 2 0 +33 1 0 +33 6 -1 +33 5 -1 +33 4 -1 +33 3 -1 +33 2 -1 +33 1 -1 +33 6 -2 +33 5 -2 +33 4 -2 +33 3 -2 +33 2 -2 +33 1 -2 33 6 -3 -38 1 -9 -38 2 -9 -38 3 -9 -38 4 -9 -38 5 -9 -38 6 -9 -38 1 -3 -38 2 -3 -38 3 -3 -38 4 -3 -38 5 -3 -38 6 -3 -33 6 -9 -33 5 -9 -33 4 -9 -33 3 -9 -33 2 -9 -33 1 -9 +33 5 -3 +33 4 -3 +33 3 -3 +33 2 -3 +33 1 -3 33 6 -4 33 5 -4 33 4 -4 33 3 -4 33 2 -4 33 1 -4 -33 6 -5 -33 5 -5 -33 4 -5 -33 3 -5 -33 2 -5 -33 1 -5 -33 6 -6 -33 5 -6 -33 4 -6 -33 3 -6 -33 2 -6 -33 1 -6 -33 6 -7 -33 5 -7 -33 4 -7 -33 3 -7 -33 2 -7 -33 1 -7 -33 6 -8 -33 5 -8 -33 4 -8 -33 3 -8 -33 2 -8 -33 1 -8 -37 0 -3 -36 0 -3 -35 0 -3 -34 0 -3 -34 1 -3 -35 1 -3 -36 1 -3 -37 1 -3 -34 2 -3 -35 2 -3 -36 2 -3 -37 2 -3 -37 3 -3 -36 3 -3 -35 3 -3 -34 3 -3 -34 4 -3 -35 4 -3 -36 4 -3 -37 4 -3 -34 5 -3 -35 5 -3 -36 5 -3 -37 5 -3 -37 6 -3 -36 6 -3 -35 6 -3 -34 6 -3 -38 0 -8 -38 0 -7 -38 0 -6 -38 0 -5 +37 0 1 +36 0 1 +35 0 1 +34 0 1 +34 1 1 +35 1 1 +36 1 1 +37 1 1 +34 2 1 +35 2 1 +36 2 1 +37 2 1 +37 3 1 +36 3 1 +35 3 1 +34 3 1 +34 4 1 +35 4 1 +36 4 1 +37 4 1 +34 5 1 +35 5 1 +36 5 1 +37 5 1 +37 6 1 +36 6 1 +35 6 1 +34 6 1 38 0 -4 +38 0 -3 +38 0 -2 +38 0 -1 +38 0 0 +38 1 0 +38 1 -1 +38 1 -2 +38 1 -3 38 1 -4 -38 1 -5 -38 1 -6 -38 1 -7 -38 1 -8 +38 2 0 +38 2 -1 +38 2 -2 +38 2 -3 38 2 -4 -38 2 -5 -38 2 -6 -38 2 -7 -38 2 -8 +38 3 0 +38 3 -1 +38 3 -2 +38 3 -3 38 3 -4 -38 3 -5 -38 3 -6 -38 3 -7 -38 3 -8 -38 4 -8 -38 4 -7 -38 4 -6 -38 4 -5 38 4 -4 -38 5 -8 -38 5 -7 -38 5 -6 -38 5 -5 +38 4 -3 +38 4 -2 +38 4 -1 +38 4 0 38 5 -4 +38 5 -3 +38 5 -2 +38 5 -1 +38 5 0 +38 6 0 +38 6 -1 +38 6 -2 +38 6 -3 38 6 -4 -38 6 -5 -38 6 -6 -38 6 -7 -38 6 -8 -33 7 -9 -34 7 -9 -35 7 -9 -36 7 -9 -37 7 -9 -38 7 -9 -38 7 -8 -38 7 -7 -38 7 -6 +33 7 -5 +34 7 -5 +35 7 -5 +36 7 -5 +37 7 -5 38 7 -5 38 7 -4 38 7 -3 +38 7 -2 +38 7 -1 +38 7 0 +38 7 1 +33 7 1 +34 7 1 +35 7 1 +36 7 1 +37 7 1 +33 7 -4 33 7 -3 -34 7 -3 -35 7 -3 +33 7 -2 +33 7 -1 +33 7 0 36 7 -3 37 7 -3 -33 7 -8 -33 7 -7 -33 7 -6 -33 7 -5 -33 7 -4 -36 7 -7 -37 7 -7 -37 7 -8 -36 7 -8 -35 7 -7 -35 7 -8 -34 7 -7 -34 7 -8 -36 7 -6 -37 7 -6 -35 7 -6 -34 7 -6 -36 7 -5 -37 7 -5 -35 7 -5 -34 7 -5 -36 7 -4 37 7 -4 +36 7 -4 +35 7 -3 35 7 -4 +34 7 -3 34 7 -4 +36 7 -2 +37 7 -2 +35 7 -2 +34 7 -2 +36 7 -1 +37 7 -1 +35 7 -1 +34 7 -1 +36 7 0 +37 7 0 +35 7 0 +34 7 0 numsurf 149 SURF 0x00 mat 4 @@ -5857,26 +5819,79 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 87 +33 0 4 +33 0 3 +33 0 2 +33 0 1 33 0 0 33 0 -1 33 0 -2 -33 0 -3 -33 0 -4 -33 0 -5 -33 0 -6 -18 0 -4 -18 0 -5 -31 0 0 +18 0 0 +18 0 -1 +31 0 4 +32 0 4 +29 0 -3 +28 0 -3 +27 0 -3 +26 0 -3 +25 0 -3 +24 0 -3 +23 0 -3 +32 0 3 +31 0 3 +19 0 2 +20 0 2 +21 0 2 +22 0 2 +23 0 2 +24 0 2 +25 0 2 +26 0 2 +27 0 2 +28 0 2 +29 0 2 +30 0 2 +31 0 2 +32 0 2 +32 0 1 +31 0 1 +30 0 1 +29 0 1 +28 0 1 +27 0 1 +26 0 1 +25 0 1 +24 0 1 +23 0 1 +22 0 1 +21 0 1 +20 0 1 +19 0 1 32 0 0 -29 0 -7 -28 0 -7 -27 0 -7 -26 0 -7 -25 0 -7 -24 0 -7 -23 0 -7 +31 0 0 +30 0 0 +29 0 0 +28 0 0 +24 0 0 +23 0 0 +22 0 0 +21 0 0 +20 0 0 +19 0 0 32 0 -1 31 0 -1 +30 0 -1 +29 0 -1 +28 0 -1 +27 0 -1 +26 0 -1 +25 0 -1 +24 0 -1 +23 0 -1 +22 0 -1 +21 0 -1 +20 0 -1 +19 0 -1 19 0 -2 20 0 -2 21 0 -2 @@ -5891,59 +5906,6 @@ numvert 87 30 0 -2 31 0 -2 32 0 -2 -32 0 -3 -31 0 -3 -30 0 -3 -29 0 -3 -28 0 -3 -27 0 -3 -26 0 -3 -25 0 -3 -24 0 -3 -23 0 -3 -22 0 -3 -21 0 -3 -20 0 -3 -19 0 -3 -32 0 -4 -31 0 -4 -30 0 -4 -29 0 -4 -28 0 -4 -24 0 -4 -23 0 -4 -22 0 -4 -21 0 -4 -20 0 -4 -19 0 -4 -32 0 -5 -31 0 -5 -30 0 -5 -29 0 -5 -28 0 -5 -27 0 -5 -26 0 -5 -25 0 -5 -24 0 -5 -23 0 -5 -22 0 -5 -21 0 -5 -20 0 -5 -19 0 -5 -19 0 -6 -20 0 -6 -21 0 -6 -22 0 -6 -23 0 -6 -24 0 -6 -25 0 -6 -26 0 -6 -27 0 -6 -28 0 -6 -29 0 -6 -30 0 -6 -31 0 -6 -32 0 -6 numsurf 59 SURF 0x10 mat 1 @@ -6367,22 +6329,22 @@ texture "Trees.png" texrep 1 1 crease 30.000000 numvert 16 -27 3 -4.5 -27 0 -4.5 -24 0 -4.5 -24 3 -4.5 -24 3 -4.5 -24 0 -4.5 -27 0 -4.5 -27 3 -4.5 -28.299999 3 -3.46203 -28.299999 0 -3.46203 -25.299999 0 -3.46203 -25.299999 3 -3.46203 -25.299999 3 -3.46203 -25.299999 0 -3.46203 -28.299999 0 -3.46203 -28.299999 3 -3.46203 +27 3 -0.5 +27 0 -0.5 +24 0 -0.5 +24 3 -0.5 +24 3 -0.5 +24 0 -0.5 +27 0 -0.5 +27 3 -0.5 +28.299999 3 0.53797 +28.299999 0 0.53797 +25.299999 0 0.53797 +25.299999 3 0.53797 +25.299999 3 0.53797 +25.299999 0 0.53797 +28.299999 0 0.53797 +28.299999 3 0.53797 numsurf 4 SURF 0x00 mat 5 @@ -6421,94 +6383,94 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 88 -24 0.5 -4 -28 0.5 -4 -24 0.5 -5 -25 0.5 -5 -26 0.5 -5 -27 0.5 -5 -28 0.5 -5 -24 0.5 -3 -25 0.5 -3 -26 0.5 -3 -27 0.5 -3 -28 0.5 -3 -24 0 -5 -25 0 -5 -26 0 -5 -27 0 -5 -28 0 -5 -24 0 -4 -28 0 -4 -24 0 -3 -25 0 -3 -26 0 -3 -27 0 -3 -28 0 -3 -23 0.5 -7 -29 0.5 -7 -19 0.5 -3 -31 0.5 -1 -31 0.5 0 -33 0.5 -6 -32 0.5 -6 -31 0.5 -6 -30 0.5 -6 -29 0.5 -6 -23 0.5 -6 -22 0.5 -6 -21 0.5 -6 -20 0.5 -6 -19 0.5 -6 -19 0.5 -5 -18 0.5 -5 -19 0.5 -4 -18 0.5 -4 +24 0.5 0 +28 0.5 0 +24 0.5 -1 +25 0.5 -1 +26 0.5 -1 +27 0.5 -1 +28 0.5 -1 +24 0.5 1 +25 0.5 1 +26 0.5 1 +27 0.5 1 +28 0.5 1 +24 0 -1 +25 0 -1 +26 0 -1 +27 0 -1 +28 0 -1 +24 0 0 +28 0 0 +24 0 1 +25 0 1 +26 0 1 +27 0 1 +28 0 1 +23 0.5 -3 +29 0.5 -3 +19 0.5 1 +31 0.5 3 +31 0.5 4 +33 0.5 -2 +32 0.5 -2 31 0.5 -2 30 0.5 -2 29 0.5 -2 -28 0.5 -2 -27 0.5 -2 -26 0.5 -2 -25 0.5 -2 -24 0.5 -2 23 0.5 -2 22 0.5 -2 21 0.5 -2 20 0.5 -2 19 0.5 -2 -32 0 -6 -31 0 -6 -30 0 -6 -29 0 -6 -23 0 -6 -22 0 -6 -21 0 -6 -20 0 -6 -19 0 -6 -19 0 -5 -19 0 -4 -19 0 -3 +19 0.5 -1 +18 0.5 -1 +19 0.5 0 +18 0.5 0 +31 0.5 2 +30 0.5 2 +29 0.5 2 +28 0.5 2 +27 0.5 2 +26 0.5 2 +25 0.5 2 +24 0.5 2 +23 0.5 2 +22 0.5 2 +21 0.5 2 +20 0.5 2 +19 0.5 2 +32 0 -2 31 0 -2 30 0 -2 29 0 -2 -28 0 -2 -27 0 -2 -26 0 -2 -25 0 -2 -24 0 -2 23 0 -2 22 0 -2 21 0 -2 20 0 -2 19 0 -2 -31 0 -1 -23 0 -7 -29 0 -7 -31 0 0 -18 0 -5 -18 0 -4 -33 0 -6 +19 0 -1 +19 0 0 +19 0 1 +31 0 2 +30 0 2 +29 0 2 +28 0 2 +27 0 2 +26 0 2 +25 0 2 +24 0 2 +23 0 2 +22 0 2 +21 0 2 +20 0 2 +19 0 2 +31 0 3 +23 0 -3 +29 0 -3 +31 0 4 +18 0 -1 +18 0 0 +33 0 -2 numsurf 41 SURF 0x30 mat 1 @@ -6804,14 +6766,14 @@ data 6 R-Lawn crease 30.000000 numvert 8 -48 0 -2 -48 0 0 -40 0 0 -40 0 -2 -45 0 -7 -45 0 -6 -39 0 -6 -39 0 -7 +48 0 2 +48 0 4 +40 0 4 +40 0 2 +45 0 -3 +45 0 -2 +39 0 -2 +39 0 -3 numsurf 2 SURF 0x20 mat 3 @@ -6836,74 +6798,74 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 68 -33 0 0 -34 0 0 -35 0 0 -36 0 0 -37 0 0 -38 0 0 -39 0 0 -40 0 0 -38 0 -7 -39 0 -7 +33 0 4 +34 0 4 +35 0 4 +36 0 4 +37 0 4 +38 0 4 +39 0 4 +40 0 4 +38 0 -3 +39 0 -3 +44 0 2 +44 0 1 +44 0 0 +44 0 -1 44 0 -2 -44 0 -3 -44 0 -4 -44 0 -5 -44 0 -6 -33 0 -1 -33 0 -2 -33 0 -3 -34 0 -3 -34 0 -2 -34 0 -1 -35 0 -3 -35 0 -2 -35 0 -1 -36 0 -1 -36 0 -2 -36 0 -3 -37 0 -3 -37 0 -2 -37 0 -1 +33 0 3 +33 0 2 +33 0 1 +34 0 1 +34 0 2 +34 0 3 +35 0 1 +35 0 2 +35 0 3 +36 0 3 +36 0 2 +36 0 1 +37 0 1 +37 0 2 +37 0 3 +38 0 3 +38 0 2 +38 0 1 +38 0 0 38 0 -1 38 0 -2 -38 0 -3 -38 0 -4 -38 0 -5 -38 0 -6 -39 0 -6 -39 0 -5 -39 0 -4 -39 0 -3 39 0 -2 39 0 -1 -40 0 -6 -40 0 -5 -40 0 -4 -40 0 -3 +39 0 0 +39 0 1 +39 0 2 +39 0 3 40 0 -2 40 0 -1 -41 0 -6 -41 0 -5 -41 0 -4 -41 0 -3 +40 0 0 +40 0 1 +40 0 2 +40 0 3 41 0 -2 -42 0 -6 -42 0 -5 -42 0 -4 -42 0 -3 +41 0 -1 +41 0 0 +41 0 1 +41 0 2 42 0 -2 -43 0 -6 -43 0 -5 -43 0 -4 -43 0 -3 +42 0 -1 +42 0 0 +42 0 1 +42 0 2 43 0 -2 +43 0 -1 +43 0 0 +43 0 1 +43 0 2 +45 0 2 +45 0 1 +45 0 0 +45 0 -1 45 0 -2 -45 0 -3 -45 0 -4 -45 0 -5 -45 0 -6 numsurf 48 SURF 0x00 mat 1 @@ -7250,112 +7212,56 @@ texture "TowerBlock1.png" texrep 1 1 crease 30.000000 numvert 201 -50 0 -2 -45 0 -2 -45 15 -7 -45 15 -2 -50 15 -2 -45 0 -7 -45 15 -6 -45 15 -5 -45 15 -4 +50 0 2 +45 0 2 45 15 -3 +45 15 2 +50 15 2 45 0 -3 -45 0 -4 -45 0 -5 -45 0 -6 -49 0 -2 -48 0 -2 -47 0 -2 -46 0 -2 -46 15 -2 -47 15 -2 -48 15 -2 -49 15 -2 -45 1 -2 -45 2 -2 -45 3 -2 -45 4 -2 -45 5 -2 -45 6 -2 -45 7 -2 -45 8 -2 -45 9 -2 -45 10 -2 -45 11 -2 -45 12 -2 -45 13 -2 -45 14 -2 -50 1 -2 -50 2 -2 -50 3 -2 -50 4 -2 -50 5 -2 -50 6 -2 -50 7 -2 -50 8 -2 -50 9 -2 -50 10 -2 -50 11 -2 -50 12 -2 -50 13 -2 -50 14 -2 -45 14 -7 -45 13 -7 -45 12 -7 -45 11 -7 -45 10 -7 -45 9 -7 -45 8 -7 -45 7 -7 -45 6 -7 -45 5 -7 -45 4 -7 -45 3 -7 -45 2 -7 -45 1 -7 -45 14 -6 -45 13 -6 -45 12 -6 -45 11 -6 -45 10 -6 -45 9 -6 -45 8 -6 -45 7 -6 -45 6 -6 -45 5 -6 -45 4 -6 -45 3 -6 -45 2 -6 -45 1 -6 -45 14 -5 -45 13 -5 -45 12 -5 -45 11 -5 -45 10 -5 -45 9 -5 -45 8 -5 -45 7 -5 -45 6 -5 -45 5 -5 -45 4 -5 -45 3 -5 -45 2 -5 -45 1 -5 -45 14 -4 -45 13 -4 -45 12 -4 -45 11 -4 -45 10 -4 -45 9 -4 -45 8 -4 -45 7 -4 -45 6 -4 -45 5 -4 -45 4 -4 -45 3 -4 -45 2 -4 -45 1 -4 +45 15 -2 +45 15 -1 +45 15 0 +45 15 1 +45 0 1 +45 0 0 +45 0 -1 +45 0 -2 +49 0 2 +48 0 2 +47 0 2 +46 0 2 +46 15 2 +47 15 2 +48 15 2 +49 15 2 +45 1 2 +45 2 2 +45 3 2 +45 4 2 +45 5 2 +45 6 2 +45 7 2 +45 8 2 +45 9 2 +45 10 2 +45 11 2 +45 12 2 +45 13 2 +45 14 2 +50 1 2 +50 2 2 +50 3 2 +50 4 2 +50 5 2 +50 6 2 +50 7 2 +50 8 2 +50 9 2 +50 10 2 +50 11 2 +50 12 2 +50 13 2 +50 14 2 45 14 -3 45 13 -3 45 12 -3 @@ -7370,87 +7276,143 @@ numvert 201 45 3 -3 45 2 -3 45 1 -3 -49 1 -2 -49 2 -2 -49 3 -2 -49 4 -2 -49 5 -2 -49 6 -2 -49 7 -2 -49 8 -2 -49 9 -2 -49 10 -2 -49 11 -2 -49 12 -2 -49 13 -2 -49 14 -2 -48 1 -2 -48 2 -2 -48 3 -2 -48 4 -2 -48 5 -2 -48 6 -2 -48 7 -2 -48 8 -2 -48 9 -2 -48 10 -2 -48 11 -2 -48 12 -2 -48 13 -2 -48 14 -2 -47 14 -2 -47 13 -2 -47 12 -2 -47 11 -2 -47 10 -2 -47 9 -2 -47 8 -2 -47 7 -2 -47 6 -2 -47 5 -2 -47 4 -2 -47 3 -2 -47 2 -2 -47 1 -2 -46 1 -2 -46 2 -2 -46 3 -2 -46 4 -2 -46 5 -2 -46 6 -2 -46 7 -2 -46 8 -2 -46 9 -2 -46 10 -2 -46 11 -2 -46 12 -2 -46 13 -2 -46 14 -2 +45 14 -2 +45 13 -2 +45 12 -2 +45 11 -2 +45 10 -2 +45 9 -2 +45 8 -2 +45 7 -2 +45 6 -2 +45 5 -2 +45 4 -2 +45 3 -2 +45 2 -2 +45 1 -2 +45 14 -1 +45 13 -1 +45 12 -1 +45 11 -1 +45 10 -1 +45 9 -1 +45 8 -1 +45 7 -1 +45 6 -1 +45 5 -1 +45 4 -1 +45 3 -1 +45 2 -1 +45 1 -1 +45 14 0 +45 13 0 +45 12 0 +45 11 0 +45 10 0 +45 9 0 +45 8 0 +45 7 0 +45 6 0 +45 5 0 +45 4 0 +45 3 0 +45 2 0 +45 1 0 +45 14 1 +45 13 1 +45 12 1 +45 11 1 +45 10 1 +45 9 1 +45 8 1 +45 7 1 +45 6 1 +45 5 1 +45 4 1 +45 3 1 +45 2 1 +45 1 1 +49 1 2 +49 2 2 +49 3 2 +49 4 2 +49 5 2 +49 6 2 +49 7 2 +49 8 2 +49 9 2 +49 10 2 +49 11 2 +49 12 2 +49 13 2 +49 14 2 +48 1 2 +48 2 2 +48 3 2 +48 4 2 +48 5 2 +48 6 2 +48 7 2 +48 8 2 +48 9 2 +48 10 2 +48 11 2 +48 12 2 +48 13 2 +48 14 2 +47 14 2 +47 13 2 +47 12 2 +47 11 2 +47 10 2 +47 9 2 +47 8 2 +47 7 2 +47 6 2 +47 5 2 +47 4 2 +47 3 2 +47 2 2 +47 1 2 +46 1 2 +46 2 2 +46 3 2 +46 4 2 +46 5 2 +46 6 2 +46 7 2 +46 8 2 +46 9 2 +46 10 2 +46 11 2 +46 12 2 +46 13 2 +46 14 2 +46 15 1 +47 15 1 +48 15 1 +49 15 1 +50 15 1 +46 15 0 +47 15 0 +48 15 0 +49 15 0 +50 15 0 +46 15 -1 +47 15 -1 +48 15 -1 +49 15 -1 +50 15 -1 +46 15 -2 +47 15 -2 +48 15 -2 +49 15 -2 +50 15 -2 46 15 -3 47 15 -3 48 15 -3 49 15 -3 50 15 -3 -46 15 -4 -47 15 -4 -48 15 -4 -49 15 -4 -50 15 -4 -46 15 -5 -47 15 -5 -48 15 -5 -49 15 -5 -50 15 -5 -46 15 -6 -47 15 -6 -48 15 -6 -49 15 -6 -50 15 -6 -46 15 -7 -47 15 -7 -48 15 -7 -49 15 -7 -50 15 -7 numsurf 175 SURF 0x00 mat 4 @@ -8686,18 +8648,18 @@ texture "Trees.png" texrep 1 1 crease 30.000000 numvert 12 -40.900002 3 -7.4 -40.900002 0 -7.4 -43.900002 0 -7.4 -43.900002 3 -7.4 -38.800003 3 -6.76203 -38.800003 0 -6.76203 -41.800003 0 -6.76203 -41.800003 3 -6.76203 -45 3 -6.16203 -45 0 -6.16203 -42 0 -6.16203 -42 3 -6.16203 +40.900002 3 -3.4 +40.900002 0 -3.4 +43.900002 0 -3.4 +43.900002 3 -3.4 +38.800003 3 -2.76203 +38.800003 0 -2.76203 +41.800003 0 -2.76203 +41.800003 3 -2.76203 +45 3 -2.16203 +45 0 -2.16203 +42 0 -2.16203 +42 3 -2.16203 numsurf 3 SURF 0x00 mat 5 @@ -8729,38 +8691,38 @@ texture "Scenery.png" texrep 1 1 crease 30.000000 numvert 32 -44 0.5 -6 44 0.5 -2 -43 0.5 -6 +44 0.5 2 43 0.5 -2 -42 0.5 -6 +43 0.5 2 42 0.5 -2 -41 0.5 -6 +42 0.5 2 41 0.5 -2 -40 0.5 -6 -40 0.5 0 -40 0.5 -1 +41 0.5 2 40 0.5 -2 -39 0.5 -6 -39 0.5 -7 +40 0.5 4 +40 0.5 3 +40 0.5 2 +39 0.5 -2 +39 0.5 -3 +43 0 2 43 0 -2 -43 0 -6 +42 0 2 42 0 -2 -42 0 -6 +41 0 2 41 0 -2 -41 0 -6 -40 0 -1 +40 0 3 +40 0 2 40 0 -2 -40 0 -6 -39 0 -6 -44 0 -6 +39 0 -2 44 0 -2 -39 0 -7 -40 0 0 +44 0 2 +39 0 -3 +40 0 4 +45 0 2 45 0 -2 -45 0 -6 +45 0.5 2 45 0.5 -2 -45 0.5 -6 numsurf 14 SURF 0x30 mat 1 diff --git a/data/models/classic.blend b/data/models/classic.blend index 8ed0773..122fc03 100644 Binary files a/data/models/classic.blend and b/data/models/classic.blend differ diff --git a/data/scenes/Classic.lua b/data/scenes/Classic.lua index 2d00a67..8476279 100644 --- a/data/scenes/Classic.lua +++ b/data/scenes/Classic.lua @@ -23,794 +23,15 @@ LogInfo("-----", SetBounds({-5, 0, -6}, {45, 15, 4}) --- Left end tower block --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Front - -ResetTransform() -Translate(-5, 0, 2) -SetTexture("TowerBlock1") -DrawTilemap({ - width = 5, - 2, 2, 2, 2, 2, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 1, 0, 0, 1, 0, - 4, 4, 4, 4, 4}) - --- Right side - -ResetTransform() -Rotate(Y, 90) -Translate(0, 0, 2) -DrawTilemap({ - width = 5, - surface = RIGHT, - 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, - 4, 5, 5, 5, 4}) - --- Top - -ResetTransform() -Rotate(X, 90) -Translate(-5, 15, -3) -DrawTilemap({ - width = 5, - surface = TOP, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3}) - --- Leftmost background tower block --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Front - -if detail > LOW then - ResetTransform() - Translate(0, 0, -3) - DrawTilemap({ - width = 7, - 2, 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 6, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 0, 1, 0, 0, 0, 1, 0, - 4, 4, 5, 5, 5, 4, 4}) - - -- Right side - - ResetTransform() - Rotate(Y, 90) - Translate(7, 0, -3) - DrawTilemap({ - width = 6, - 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 4, 4, 4, 4, 4, 4}) - - -- Top - - ResetTransform() - Rotate(X, 90) - Translate(-2, 8, -9) - DrawTilemap({ - width = 9, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3}) -end - --- Foreground building with pitched roof --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Left wall - -ResetTransform() -Rotate(Y, -90) -Translate(10, 0, -2) -SetTexture("Building") -DrawTilemap({ - width = 4, - surface = LEFT, - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 5, 6, 4, - 3, 6, 5, 4}) - --- Right wall - -ResetTransform() -Rotate(Y, -90) -Translate(13, 0, -2) -DrawTilemap({ - width = 4, - surface = RIGHT, - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 5, 6, 4, - 3, 8, 5, 4}) - --- Front wall - -ResetTransform() -Translate(10, 0, 2) -DrawTilemap({ - width = 3, - 15, 7, 16, - 3, 5, 4, - 3, 6, 4}) - --- Pitched roof - -ResetTransform() -Rotate(X, 135) -Scale(1, 1.5, 1.5) -Translate(10, 5, 0) -DrawTilemap({ - width = 3, - 13, 13, 13, - 13, 13, 13}) - --- Finial - -ResetTransform() -Translate(10, 5, -0.00001) -DrawTilemap({ - width = 3, - 18, 18, 18}) - --- Cheaty invisible platform --- This draws nothing but creates a platform on the roof for walking. - -ResetTransform() -Rotate(X, 90) -Translate(10, 5, 0) -DrawTilemap({ - width = 3, - surface = TOP, - -1, -1, -1}) - --- The ground --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Courtyard - -ResetTransform() -Rotate(X, 90) -Translate(-3, 0, -3) -SetTexture("Scenery") -DrawTilemap({ - width = 13, - surface = TOP, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, - -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}) - --- Front grass - -if detail > MEDIUM then - ResetTransform() - Scale(8, 1, 1) - Translate(1, -0.5, 2) - DrawTile({ - 2, - u_scale = 8}) - - -- Back grass - - ResetTransform() - Scale(8, 1, 1) - Translate(1, -0.5, -2) - DrawTile({ - 2, - u_scale = 8 - }) - - -- Left grass - - ResetTransform() - Scale(4, 1, 1) - Rotate(Y, -90) - Translate(1, -0.5, -2) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Right grass - - ResetTransform() - Scale(4, 1, 1) - Rotate(Y, -90) - Translate(9, -0.5, -2) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Fence behind house - - ResetTransform() - Scale(11, 1, 1) - Translate(7, 0, -3) - DrawTile({ - 4, - u_scale = 11 - }) -end - --- Background building with pitched roof --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Front wall - -if detail > LOW then - ResetTransform() - Translate(19, 0, -3) - SetTexture("Building") - DrawTilemap({ - width = 4, - -1, 9, 11, -1, - 9, 10, 12, 11, - 15, 7, 7, 16, - 3, 6, 5, 4, - 3, 5, 6, 4, - 3, 8, 5, 4}) - - -- Left wall - - ResetTransform() - Rotate(Y, -90) - Translate(19, 0, -6) - DrawTilemap({ - width = 3, - 15, 1, 16, - 3, 7, 4, - 3, 5, 4, - 3, 0, 4}) - - -- Right wall - - ResetTransform() - Rotate(Y, -90) - Translate(23, 0, -6) - DrawTilemap({ - width = 3, - 15, 0, 16, - 3, 7, 4, - 3, 6, 4, - 3, 2, 4}) - - -- Left pitched roof - - ResetTransform() - Rotate(X, 135) - Scale(1, 1.5, 1.5) - Rotate(Y, -90) - Translate(21, 6, -6) - DrawTilemap({ - width = 3, - 13, 13, 13, - 13, 13, 13}) - - -- Right pitched roof - - ResetTransform() - Rotate(X, -135) - Scale(1, 1.5, 1.5) - Rotate(Y, -90) - Translate(21, 6, -6) - DrawTilemap({ - width = 3, - 13, 13, 13, - 13, 13, 13}) - - -- Finial - - ResetTransform() - Rotate(Y, -90) - Translate(21, 6, -6) - DrawTilemap({ - width = 3, - 18, 18, 18}) -end - --- More ground to the right --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Ground under house - -ResetTransform() -Rotate(X, 90) -Translate(10, 0, -3) -SetTexture("Scenery") -DrawTilemap({ - width = 3, - surface = TOP, - 1, 1, 1, - 1, 1, 1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - 1, 1, 1}) - --- Left part of center courtyard - -ResetTransform() -Rotate(X, 90) -Translate(13, 0, -3) -DrawTilemap({ - width = 8, - surface = TOP, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 0, 0, 0}) - --- Front grass - -if detail > MEDIUM then - ResetTransform() - Scale(12, 1, 1) - Translate(14, -0.5, 2) - DrawTile({ - 2, - u_scale = 12 - }) - - -- Back grass - - ResetTransform() - Scale(4, 1, 1) - Translate(14, -0.5, -2) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Front grass next to door - - ResetTransform() - Translate(13, -0.5, 0) - DrawTile({ - 2, - u_scale = 1 - }) - - -- Back grass next to door - - ResetTransform() - Translate(13, -0.5, -1) - DrawTile({ - 2, - u_scale = 1 - }) - - -- Left grass - - ResetTransform() - Rotate(Y, -90) - Translate(14, -0.5, -2) - DrawTilemap({ - width = 4, - 2, -1, 2, 2}) - - -- Grass left of house - - ResetTransform() - Rotate(Y, -90) - Translate(18, -0.5, -3) - DrawTile({ - 2, - u_scale = 1 - }) - - -- Grass right of house - - ResetTransform() - Rotate(Y, -90) - Translate(24, -0.5, -3) - DrawTile({ - 2, - u_scale = 1 - }) - - -- Front grass in center - - ResetTransform() - Scale(4, 1, 1) - Translate(19, -0.5, 1) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Back grass in center - - ResetTransform() - Scale(4, 1, 1) - Translate(19, -0.5, -1) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Left grass in center - - ResetTransform() - Scale(2, 1, 1) - Rotate(Y, -90) - Translate(19, -0.5, -1) - DrawTile({ - 2, - u_scale = 2 - }) - - -- Right grass in center - - ResetTransform() - Scale(2, 1, 1) - Rotate(Y, -90) - Translate(23, -0.5, -1) - DrawTile({ - 2, - u_scale = 2 - }) -end - --- Right part of center courtyard - -ResetTransform() -Rotate(X, 90) -Translate(21, 0, -3) -DrawTilemap({ - width = 7, - surface = TOP, - 1, 1, 1, 1, 1, 0, 0, - 1, 1, 1, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1}) - --- Fence to right of back house - -if detail > MEDIUM then - ResetTransform() - Scale(4, 1, 1) - Translate(24, 0, -3) - DrawTile({ - 4, - u_scale = 4 - }) - - -- Grass in front of fence - - ResetTransform() - Scale(4, 1, 1) - Translate(24, -0.5, -2) - DrawTile({ - 2, - u_scale = 4 - }) - - -- Grass to left of tower block - - ResetTransform() - Scale(2, 1, 1) - Rotate(Y, -90) - Translate(26, -0.5, 2) - DrawTile({ - 2, - u_scale = 2 - }) - - -- Grass to right of tower block - - ResetTransform() - Scale(2, 1, 1) - Rotate(Y, -90) - Translate(35, -0.5, 2) - DrawTile({ - 2, - u_scale = 2 - }) - - -- Next bit of grass - - ResetTransform() - Scale(5, 1, 1) - Translate(35, -0.5, 2) - DrawTile({ - 2, - u_scale = 5 - }) - - -- Back grass - - ResetTransform() - Scale(6, 1, 1) - Translate(34, -0.5, -2) - DrawTile({ - 2, - u_scale = 6 - }) - - -- Extra bit of back grass - - ResetTransform() - Rotate(Y, -90) - Translate(34, -0.5, -3) - DrawTile({ - 2, - u_scale = 1 - }) -end - --- Ground around tower block - -ResetTransform() -Rotate(X, 90) -Translate(28, 0, 1) -DrawTilemap({ - width = 5, - surface = TOP, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0}) - --- Rightmost ground - -ResetTransform() -Rotate(X, 90) -Translate(33, 0, -3) -DrawTilemap({ - width = 10, - surface = TOP, - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, - 0, 1, 1, 1, 1, 1, 1, -1, -1, -1}) - --- Right foreground tower block --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Front - -ResetTransform() -Translate(28, 0, 1) -SetTexture("TowerBlock1") -DrawTilemap({ - width = 5, - 2, 2, 2, 2, 2, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 6, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 6, 0, - 4, 4, 4, 4, 4}) - --- Right side - -ResetTransform() -Rotate(Y, 90) -Translate(33, 0, 1) -DrawTilemap({ - width = 6, - surface = RIGHT, - 2, 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 5, 4, 5, 5, 4, 5}) - --- Left side - -ResetTransform() -Rotate(Y, 90) -Translate(28, 0, 1) -DrawTilemap({ - width = 6, - surface = LEFT, - 2, 2, 2, 2, 2, 2, - 0, 1, 6, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 0, 1, 0, 0, 1, 0, - 5, 4, 5, 5, 4, 5}) - --- Top - -ResetTransform() -Rotate(X, 90) -Translate(28, 7, -5) -DrawTilemap({ - width = 5, - surface = TOP, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3}) - --- Right end tower block --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - --- Front - -ResetTransform() -Translate(40, 0, 2) -DrawTilemap({ - width = 5, - 2, 2, 2, 2, 2, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 6, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 6, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 0, 1, 0, 0, 1, - 4, 4, 4, 4, 4}) - --- Left side - -ResetTransform() -Rotate(Y, 90) -Translate(40, 0, 2) -DrawTilemap({ - width = 5, - surface = LEFT, - 2, 2, 2, 2, 2, - 6, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 6, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 6, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 4, 5, 5, 5, 4}) - --- Top - -ResetTransform() -Rotate(X, 90) -Translate(40, 15, -3) -DrawTilemap({ - width = 5, - surface = TOP, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3}) - --- Background --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -ResetTransform() -Translate(-0.3, -0.3, -35) -Scale(105, 52, 1) -SetTexture("BackgroundFar") -DrawTile() - -Translate(0, 0, 5) -SetTexture("BackgroundNear") -DrawTile({ - blend = detail > LOW and true or false -}) - --- Trees --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -SetTexture("Trees") - --- Left courtyard - -if detail > LOW then - ResetTransform() - Scale(3) - Translate(7.75, -0.1, -2.5) - DrawTile(1) -end - --- Center courtyard - -ResetTransform() -Scale(3) -Translate(19, -0.1, -0.5) -DrawTile(0) - -ResetTransform() -Scale(3) -Translate(20.25, -0.1, 0.5) -DrawTile(1) - --- Right courtyard - -if detail > LOW then - ResetTransform() - Scale(3) - Translate(34, -0.1, -2.75) - DrawTile(1) - - ResetTransform() - Scale(3) - Translate(36, -0.1, -3.5) - DrawTile(0) - - ResetTransform() - Scale(3) - Translate(37, -0.1, -2.25) - DrawTile(1) -end +--geometry = yoink.mesh("classic.ac") +--geometry:draw() +--geometry = yoink.mesh.fromstring([[ +--AC3Db +--OBJECT poly +--name "Hello World" +--... +--]] -- Functions: @@ -845,7 +66,37 @@ end Event = {} -function Event:Think() +do + local mysound = yoink.sound("Explosion") + local count = 0 + function Event.Think() + if count % 300 == 0 then + --mysound:play() + end + count = count + 1 + end +end + + +classic_mesh = yoink.mesh("classic") + +--drawme = {} + +--world = classic_mesh:object(1) +--for i = 1, 19 do + --local object = world:kid(i) + --if object then table.insert(drawme, object) end +--end + +--lawn = classic_mesh:object(1):kid("M-Lawn") + +--Event.Draw = function() tower:draw(false) end +Event.Draw = function() + --for i,object in ipairs(drawme) do + --object:draw() + --end + --lawn:draw() + classic_mesh:draw() end function Event:BadGuyDied(enemy) diff --git a/src/Animation.cc b/src/Animation.cc index fead5ca..a9710ce 100644 --- a/src/Animation.cc +++ b/src/Animation.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include "Animation.hh" @@ -139,11 +140,6 @@ public: moof::script script; std::string path = moof::resource::find_file("animations/"+name, "lua"); - //if (!resource::find(path)) - //{ - //throw std::runtime_error("cannot find resource " + name); - //} - script.import_base_library(); moof::log::import(script); importAnimationBindings(script); diff --git a/src/Animation.hh b/src/Animation.hh index 3875b45..97e916d 100644 --- a/src/Animation.hh +++ b/src/Animation.hh @@ -22,7 +22,6 @@ #include #include -#include class Animation; @@ -36,7 +35,7 @@ typedef boost::shared_ptr AnimationP; * about anything to whatever drawing context is used to render the frame. */ -class Animation : public moof::resource +class Animation { public: diff --git a/src/GameLayer.cc b/src/GameLayer.cc index 5e95b76..8ff3a75 100644 --- a/src/GameLayer.cc +++ b/src/GameLayer.cc @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -24,8 +25,10 @@ void GameLayer::loadSceneLoader() { - state_.script.import_standard_libraries(); + state_.script.import_safe_standard_libraries(); moof::log::import(state_.script); + moof::mesh::import(state_.script, "yoink"); + moof::sound::import(state_.script, "yoink"); std::string path = moof::resource::find_file("scenes/loader.lua"); if (path.empty()) @@ -45,7 +48,7 @@ void GameLayer::loadSceneLoader() state_.script.top().get(state_.sceneList); if (state_.sceneList.size() == 0) { - throw std::runtime_error("no variable `scenes' in script loader."); + throw std::runtime_error("no variable `scenes' in script loader"); } } @@ -73,27 +76,31 @@ void GameLayer::advanceScene(moof::settings& settings) state_.script.registry().set_field(); } state_.script.pop(); + + table = state_.script.globals().push_field("Event"); + if (table.is_table()) + { + table.push_field("Draw"); + state_.script.registry().set_field("Draw"); + } + state_.script.pop(); } } GameLayer::GameLayer() { - moof::log_info("about to load sound resource..."); - music_.sample("sounds/NightFusionIntro.ogg"); + music_.sample("NightFusionIntro.ogg"); music_.loop(true); - music_.enqueue("sounds/NightFusionLoop.ogg"); + music_.enqueue("NightFusionLoop.ogg"); music_.position(moof::vector3(10.0, 5.0, 0.0)); - mThinkTimer.init(boost::bind(&GameLayer::thinkTimer, this), - 0.1, moof::timer::repeat); + punch_sound_.sample("RobotPunch"); state_.heroine = Heroine::alloc(); state_.heroine->animation.startSequence("FlyDiagonallyUp"); state_.interp.init(0.0, 1.0, 4.0, moof::lerp_scalar::oscillate); - - sceneMesh = moof::resource::load("classic.ac"); } @@ -101,7 +108,7 @@ void GameLayer::did_add_to_view() { bool isMute = false; settings().get("nomusic", isMute); - music_.stream(); + music_.play(); loadSceneLoader(); advanceScene(settings()); // load the first scene @@ -137,16 +144,12 @@ void GameLayer::update(moof::scalar t, moof::scalar dt) mRay.point = state_.heroine->state().position; - moof::view::update(t, dt); -} - -void GameLayer::thinkTimer() -{ state_.script.registry().push_field("Think"); if (state_.script[-1].is_function()) state_.script.call(); - else state_.script.pop(); -} + else state_.script.pop(); + moof::view::update(t, dt); +} void GameLayer::rayTimer() { @@ -189,7 +192,7 @@ void GameLayer::draw(moof::scalar alpha) const state_.camera.upload_to_gl(alpha); float pos[] = {state_.heroine->state().position[0], - state_.heroine->state().position[1], 0.0f}; + state_.heroine->state().position[1], 0.0f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, pos); // DRAW THE SCENE @@ -199,7 +202,24 @@ void GameLayer::draw(moof::scalar alpha) const glEnableClientState(GL_TEXTURE_COORD_ARRAY); //state_.scene->draw_if_visible(alpha, state_.camera.frustum()); - sceneMesh->draw(alpha); + + size_t meh = 23; + state_.script.push(meh); + state_.script.pop(); + + state_.script.registry().push_field("Draw"); + if (state_.script[-1].is_function()) + { + moof::script::status result = state_.script.call(); + if (result != moof::script::success) + { + std::string str; + state_.script[-1].get(str); + throw std::runtime_error("script error: " + str); + } + } + else state_.script.pop(); + state_.heroine->draw(alpha); mRay.draw(); diff --git a/src/GameLayer.hh b/src/GameLayer.hh index 54b4996..f381443 100644 --- a/src/GameLayer.hh +++ b/src/GameLayer.hh @@ -24,7 +24,6 @@ #include #include -#include #include #include // TODO @@ -62,22 +61,16 @@ private: void loadSceneLoader(); void advanceScene(moof::settings& settings); - void thinkTimer(); - void projection(); void projection(moof::scalar width, moof::scalar height); - GameState state_; - moof::timer mThinkTimer; + mutable GameState state_; HudP mHud; - //moof::sound_stream mMusic; moof::sound punch_sound_; moof::sound music_; - moof::mesh_handle sceneMesh; - moof::ray2 mRay; moof::line2 mLine; moof::circle mCircle; diff --git a/src/Main.cc b/src/Main.cc index ae183ec..13681ee 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -17,6 +17,12 @@ #include #include +#if !defined(__WIN32) +#include +#else +int isatty(int dummy) { return 0; } +#endif + #include #include @@ -25,6 +31,7 @@ #include #include #include +#include #include #include "GameLayer.hh" @@ -37,9 +44,15 @@ Main::Main(moof::settings& settings, moof::video& video) : moof::view(settings, video) { moof::dispatcher& dispatcher = moof::dispatcher::global(); - mNewContextDispatch = dispatcher.add_target("video.newcontext", - boost::bind(&Main::setupGL)); - setupGL(); + video_reloaded_ = dispatcher.add_target("video.newcontext", + boost::bind(&Main::setup_opengl)); + setup_opengl(); + +#if USE_HOTLOADING + hotload_timer_.init(boost::bind(&moof::resource::reload_as_needed), + SCALAR(0.25), + moof::timer::repeat); +#endif } @@ -100,7 +113,7 @@ bool Main::handle_event(const moof::event& event) } -std::string Main::getSearchPath() +std::string Main::search_paths() { // Add search paths; they should be searched in this order: // 1. YOINK_DATADIR (environment) @@ -118,7 +131,7 @@ std::string Main::getSearchPath() return path; } -std::string Main::getConfigPath() +std::string Main::config_paths() { // Build the list of config files to search for, in this order: // 1. YOINK_DATADIR/yoinkrc @@ -144,17 +157,19 @@ std::string Main::getConfigPath() } -void Main::setupGL() +void Main::setup_opengl() { glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_POLYGON_SMOOTH); + //glEnable(GL_POINT_SMOOTH); + //glEnable(GL_LINE_SMOOTH); + //glEnable(GL_POLYGON_SMOOTH); glShadeModel(GL_SMOOTH); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //glEnable(GL_BLEND); + //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0.0); @@ -163,21 +178,21 @@ void Main::setupGL() //glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); - float light[] = {1.0f, 1.0f, 1.0f, 1.0f}; - glLightfv(GL_LIGHT0, GL_AMBIENT_AND_DIFFUSE, light); + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + float amb[] = {0.1f, 0.1f, 0.1f, 1.0f}; + float dif[] = {0.6f, 0.6f, 0.6f, 1.0f}; + //glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light); + glLightfv(GL_LIGHT0, GL_AMBIENT, amb); + glLightfv(GL_LIGHT0, GL_DIFFUSE, dif); - //glMatrixMode(GL_PROJECTION); - //glLoadIdentity(); - //moof::scalar ratio = moof::core.getVideo()->width() / - //moof::core.getVideo()->height(); - //gluPerspective(60.0, ratio, 1.0, 250.0); - - //glMatrixMode(GL_MODELVIEW); + float spec[] = {1.0f, 1.0f, 1.0f, 1.0f}; + glLightfv(GL_LIGHT0, GL_SPECULAR, spec); } -void Main::printUsage() +void Main::print_usage() { std::cout << "Usage: " << PACKAGE" [-h|--help] [-i|--info] [OPTION=VALUE]..." @@ -199,18 +214,33 @@ void Main::printUsage() << "See documentation for more options." << std::endl; } -void Main::printInfo(int argc, char* argv[]) + +void Main::print_info(int argc, char* argv[]) { + bool color = (isatty(1) == 1); + stlplus::env_vector environment; std::string assets; assets.assign(YOINK_DATADIR); - if (!stlplus::file_readable(assets)) assets += " (no access)"; + if (!stlplus::file_readable(assets)) + { + assets += " "; + if (color) assets += "\033[1;91m"; + assets += "(no access)"; + if (color) assets += "\033[0m"; + } std::string datadir = environment["YOINK_DATADIR"]; if (!datadir.empty()) { - if (!stlplus::folder_readable(datadir)) datadir += " (no access)"; + if (!stlplus::folder_readable(datadir)) + { + datadir += " "; + if (color) datadir += "\033[1;91m"; + datadir += "(no access)"; + if (color) datadir += "\033[0m"; + } } std::string rc_file = environment["YOINKRC"]; @@ -227,55 +257,75 @@ void Main::printInfo(int argc, char* argv[]) << " Built: " << COMPILE_TIME << std::endl << " Compiler: " << COMPILER_STRING << std::endl << " Assets: " << assets << std::endl - << "Build options: " -#if !USE_CLOCK_GETTIME - << "-" -#endif - << "clock_gettime " -#if !DEBUG - << "-" + << "Build options: "; + +#if USE_CLOCK_GETTIME + print_option("clock_gettime", true); +#else + print_option("clock_gettime", false); #endif - << "debug " -#if !USE_DOUBLE_PRECISION - << "-" +#if DEBUG + print_option("debug", true); +#else + print_option("debug", false); #endif - << "double-precision " -#if !USE_GTK - << "-" +#if USE_GTK + print_option("gtk", true); +#else + print_option("gtk", false); #endif - << "gtk " -#if !USE_HOTLOADING - << "-" +#if USE_HOTLOADING + print_option("hotload", true); +#else + print_option("hotload", false); #endif - << "hotloading " -#if !PROFILING_ENABLED - << "-" +#if PROFILING_ENABLED + print_option("profile", true); +#else + print_option("profile", false); #endif - << "profile " -#if !USE_QT4 - << "-" +#if USE_QT4 + print_option("qt4", true); +#else + print_option("qt4", false); #endif - << "qt4 " -#if !USE_THREADS - << "-" +#if USE_THREADS + print_option("threads", true); +#else + print_option("threads", false); #endif - << "threads" << std::endl - << " YOINKRC: " << rc_file << std::endl + std::cout << std::endl; + std::cout << " YOINKRC: " << rc_file << std::endl << "YOINK_DATADIR: " << datadir << std::endl; } +void Main::print_option(const std::string& option, bool enabled) +{ + if (isatty(1) == 1) + { + if (enabled) std::cout << "\033[1;94m"; + else std::cout << "\033[1m"; + } + if (!enabled) std::cout << "-"; + std::cout << option; + if (isatty(1) == 1) std::cout << "\033[0m"; + std::cout << " "; +} + void hello() { + if (isatty(1) == 1) std::cout << "\033[94m"; std::cout << std::endl << PACKAGE_STRING << std::endl << "Compiled " << __TIME__ " " __DATE__ << std::endl << "Send patches and bug reports to <" - PACKAGE_BUGREPORT << ">." << std::endl << std::endl; + PACKAGE_BUGREPORT << ">." << std::endl << moof::log::endl; } void goodbye() { - std::cout << std::endl << "Goodbye..." << std::endl << std::endl; + if (isatty(1) == 1) std::cout << "\033[94m"; + std::cout << std::endl << "Goodbye." << std::endl << moof::log::endl; } @@ -283,22 +333,17 @@ int main(int argc, char* argv[]) { moof::backend backend; - // FIXME: This is temporary. - moof::timer reloadTimer(boost::bind(&moof::resource::reload_as_needed), - SCALAR(2.0), - moof::timer::repeat); - if (argc > 1) { std::string arg(argv[1]); if (arg == "-h" || arg == "--help") { - Main::printUsage(); + Main::print_usage(); return 0; } else if (arg == "-i" || arg == "--info") { - Main::printInfo(argc, argv); + Main::print_info(argc, argv); return 0; } } @@ -306,9 +351,9 @@ int main(int argc, char* argv[]) hello(); atexit(goodbye); - moof::resource::add_search_paths(Main::getSearchPath()); + moof::resource::set_search_paths(Main::search_paths()); - moof::settings settings(argc, argv, Main::getConfigPath()); + moof::settings settings(argc, argv, Main::config_paths()); enum moof::log::level logLevel = moof::log::info; settings.get("loglevel", logLevel); @@ -335,11 +380,18 @@ int main(int argc, char* argv[]) catch (const std::exception& e) { moof::modal_dialog dialog(moof::modal_dialog::error, - PACKAGE_STRING, "Unhandled Exception", + PACKAGE_STRING, "unhandled exception", e.what()); - dialog.run(); - return 1; } + catch (const char* e) + { + moof::modal_dialog dialog(moof::modal_dialog::error, + PACKAGE_STRING, "unhandled exception", + e); + dialog.run(); + } + + return 1; } diff --git a/src/Main.hh b/src/Main.hh index 0a3c616..4532e41 100644 --- a/src/Main.hh +++ b/src/Main.hh @@ -24,6 +24,7 @@ #include #include +#include #include @@ -47,20 +48,23 @@ public: void draw(moof::scalar alpha) const; bool handle_event(const moof::event& event); - static std::string getSearchPath(); - static std::string getConfigPath(); + static std::string search_paths(); + static std::string config_paths(); - static void printUsage(); - static void printInfo(int argc, char* argv[]); + static void print_usage(); + static void print_info(int argc, char* argv[]); private: /** * Set OpenGL to a state we can know and depend on. */ - static void setupGL(); + static void setup_opengl(); - moof::dispatcher::handle mNewContextDispatch; + static void print_option(const std::string& option, bool enabled); + + moof::dispatcher::handle video_reloaded_; + moof::timer hotload_timer_; }; diff --git a/src/Scene.cc b/src/Scene.cc index a1218f2..af54c28 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ struct Scene::impl : public moof::manager }; Quad(const moof::vector3* vertices[4], - const std::string& texture, + const moof::image_handle& texture, int tileIndex) : mTilemap(texture, tileIndex), mBlending(false), @@ -119,7 +120,7 @@ struct Scene::impl : public moof::manager moof::matrix4 mTransform; - std::string mTexture; + moof::image_handle mTexture; std::list< boost::shared_ptr > mObjects; std::list mLines; @@ -191,8 +192,8 @@ struct Scene::impl : public moof::manager static int loadBox(moof::script& script, moof::aabb3& aabb) { - script[1].require_table(); - script[2].require_table(); + script[1].require_table("point"); + script[2].require_table("point"); script[1].push_field(1).get(aabb.min[0]); script[1].push_field(2).get(aabb.min[1]); @@ -206,8 +207,7 @@ struct Scene::impl : public moof::manager int setBounds(moof::script& script) { - int ret = loadBox(script, mBounds); - return ret; + return loadBox(script, mBounds); } int resetTransform(moof::script& script) @@ -264,10 +264,10 @@ struct Scene::impl : public moof::manager int rotate(moof::script& script) { - size_t index = 0; - script[1].require_number().get(index); + size_t index = 0; + moof::scalar value; - moof::scalar value; + script[1].require_number().get(index); script[2].require_number().get(value); moof::matrix_rotate_about_world_axis(mTransform, index, @@ -278,7 +278,9 @@ struct Scene::impl : public moof::manager int setTexture(moof::script& script) { - script[1].require_string().get(mTexture); + std::string texture_name; + script[1].require_string().get(texture_name); + mTexture = moof::resource::load(texture_name, "png"); return 0; } diff --git a/src/Scene.hh b/src/Scene.hh index 3c14b47..8c60cc5 100644 --- a/src/Scene.hh +++ b/src/Scene.hh @@ -19,7 +19,6 @@ #include #include -#include #include @@ -33,7 +32,7 @@ class settings; class Scene; typedef boost::shared_ptr SceneP; -class Scene : public moof::cullable, public moof::drawable, public moof::resource +class Scene : public moof::cullable, public moof::drawable { class impl; boost::shared_ptr impl_; diff --git a/src/moof/entity.hh b/src/moof/entity.hh index b503551..f95a94c 100644 --- a/src/moof/entity.hh +++ b/src/moof/entity.hh @@ -79,7 +79,7 @@ public: * Get the axis-aligned bounding box surrounding the entity. * \return The AABB. */ - const moof::aabb<3>& aabb() const + const moof::aabb3& aabb() const { return aabb_; } @@ -87,7 +87,7 @@ public: /** Get the bounding sphere surrounding the entity. * \return The sphere. */ - const moof::sphere<3>& sphere() const + const moof::sphere3& sphere() const { return sphere_; } @@ -95,8 +95,8 @@ public: protected: - moof::aabb<3> aabb_; - moof::sphere<3> sphere_; + moof::aabb3 aabb_; + moof::sphere3 sphere_; }; diff --git a/src/moof/image.cc b/src/moof/image.cc index 64b2f2e..7453b48 100644 --- a/src/moof/image.cc +++ b/src/moof/image.cc @@ -27,6 +27,8 @@ namespace moof { +MOOF_REGISTER_RESOURCE(image, png, textures); + //static int power_of_two(int input) //{ //int value = 1; @@ -342,23 +344,5 @@ void image::set_texture_info(const std::string& info) } -class image_resource_loader -{ -public: - - image_resource_loader() - { - resource::register_type("png", "textures"); - } - - ~image_resource_loader() - { - resource::unregister_type("png"); - } -}; - -static image_resource_loader loader; - - } // namespace moof diff --git a/src/moof/log.cc b/src/moof/log.cc index 017ce36..f9a3ad9 100644 --- a/src/moof/log.cc +++ b/src/moof/log.cc @@ -11,6 +11,13 @@ #include +#if !defined(__WIN32) +#include +#else +int isatty(int dummy) { return 0; } +#endif + + #include "log.hh" #include "script.hh" @@ -32,14 +39,49 @@ enum log::level log::level() } -std::ostream& log(std::clog); +log::log(enum level level) : + level_(level) +{ + if (isatty(1) == 0) + switch (level) + { + case log::error: prefix_ = " error: "; break; + case log::warning: prefix_ = "warning: "; break; + case log::info: prefix_ = " info: "; break; + case log::none: break; + } + else + switch (level) + { + case log::error: prefix_ = "\033[101m error: "; break; + case log::warning: prefix_ = "\033[103mwarning: "; break; + case log::info: prefix_ = " info: "; break; + case log::none: break; + } +} + +std::ostream& operator << (class log& log, log::endl_ endl) +{ + if (log::global_level_ < log.level_) return null_log; + if (isatty(1) == 0) return moof::log << std::endl; + else return moof::log << "\033[0m" << std::endl; +} + +std::ostream& operator << (std::ostream& stream, log::endl_ endl) +{ + if (isatty(1) == 0) return stream << std::endl; + else return stream << "\033[0m" << std::endl; +} + + +std::ostream& log(std::cout); static std::ofstream null_log_; std::ostream& null_log(null_log_); -class log log_error( log::error, " error: "); -class log log_warning(log::warning, "warning: "); -class log log_info( log::info, " info: "); +class log log_error( log::error); +class log log_warning(log::warning); +class log log_info( log::info); static int log_script(script& script, enum log::level level) diff --git a/src/moof/log.hh b/src/moof/log.hh index a32daad..e6e1a80 100644 --- a/src/moof/log.hh +++ b/src/moof/log.hh @@ -21,6 +21,7 @@ #include // exit #include +#include namespace moof { @@ -79,33 +80,40 @@ public: * \param level The log level. * \param prefix The string printed before each log message. */ - log(enum level level, const char* prefix) : - level_(level), - prefix_(prefix) /* only pass literal strings */ {} + log(enum level level); + + + /** + * Output this to end a line. This is equivalent to std::endl except + * this will also reset terminal format attributes. + */ + static struct endl_ + { + } endl; template void operator () (const A& a) { - *this << a << std::endl; + *this << a << endl; } template void operator () (const A& a, const B& b) { - *this << a << " " << b << std::endl; + *this << a << " " << b << endl; } template void operator () (const A& a, const B& b, const C& c) { - *this << a << " " << b << " " << c << std::endl; + *this << a << " " << b << " " << c << endl; } template void operator () (const A& a, const B& b, const C& c, const D& d) { - *this << a << " " << b << " " << c << " " << d << std::endl; + *this << a << " " << b << " " << c << " " << d << endl; } template @@ -119,18 +127,19 @@ public: << b << " " << c << " " << d << " " - << e << std::endl; + << e << endl; } private: template friend std::ostream& operator << (log&, const T&); + friend std::ostream& operator << (log&, endl_); static enum level global_level_; enum level level_; - const char* prefix_; + std::string prefix_; }; @@ -149,6 +158,9 @@ inline std::ostream& operator << (class log& log, const T& item) return moof::log << log.prefix_ << item; } +std::ostream& operator << (class log& log, log::endl_ endl); +std::ostream& operator << (std::ostream& stream, log::endl_ endl); + } // namespace moof diff --git a/src/moof/mesh.cc b/src/moof/mesh.cc index b41c377..023138b 100644 --- a/src/moof/mesh.cc +++ b/src/moof/mesh.cc @@ -25,6 +25,8 @@ #include "mesh.hh" #include "opengl.hh" +// TODO: this file needs to be cleaned up + #define AC3D_FORMAT_VERSION (0x0b) #define ZLIB_BUF_SIZE (262114) @@ -33,6 +35,9 @@ namespace moof { +MOOF_REGISTER_RESOURCE(mesh, ac, models); + + static std::string read_string(std::istream& stream) { std::string str; @@ -85,15 +90,21 @@ inline vector2 read_pair(std::istream& stream) return triplet; } - -template -inline vector< scalar, fixed > read_triplet(std::istream& stream) +inline vector3 read_triplet(std::istream& stream) { - vector< scalar, fixed > triplet; + vector3 triplet; stream >> triplet[0] >> triplet[1] >> triplet[2]; return triplet; } +inline vector4 read_color(std::istream& stream) +{ + vector4 color; + stream >> color[0] >> color[1] >> color[2]; + color[3] = SCALAR(1.0); + return color; +} + void mesh::import(std::istream& stream) { @@ -130,20 +141,18 @@ void mesh::import(std::istream& stream) materials_.push_back(material(read_string(stream))); stream >> atom; - materials_.back().diffuse = read_triplet<4>(stream); + materials_.back().diffuse = read_color(stream); stream >> atom; - materials_.back().ambient = read_triplet<3>(stream); + materials_.back().ambient = read_color(stream); stream >> atom; - materials_.back().emissive = read_triplet<3>(stream); + materials_.back().emissive = read_color(stream); stream >> atom; - materials_.back().specular = read_triplet<3>(stream); + materials_.back().specular = read_color(stream); stream >> atom >> materials_.back().shininess; - stream >> atom >> materials_.back().diffuse[3]; // transparency - materials_.back().diffuse[3] = 1.0; // FIXME: temporary - - log_info("read material", materials_.back().name, - materials_.back().diffuse); + stream >> atom >> materials_.back().diffuse[3]; + materials_.back().diffuse[3] = SCALAR(1.0) - + materials_.back().diffuse[3]; } else if (atom == "OBJECT") { @@ -153,7 +162,7 @@ void mesh::import(std::istream& stream) throw std::runtime_error("unexpected object type " + atom); } - object_ptr newObj = object::alloc(); + object_ptr newObj = object::alloc(*this); if (obj) { @@ -169,7 +178,12 @@ void mesh::import(std::istream& stream) } else if (atom == "name") { - if (obj) obj->name = read_string(stream); + if (obj) + { + obj->name = read_string(stream); + object_ptr parent = obj->parent.lock(); + if (parent) parent->kids_byname.insert(std::make_pair(obj->name, obj)); + } else throw std::runtime_error("unexpected atom: " + atom); } else if (atom == "data") @@ -208,12 +222,9 @@ void mesh::import(std::istream& stream) int numvert = 0; stream >> numvert; - log_warning("adding verts", numvert); - for (int i = 0; i < numvert; ++i) { - obj->verts.push_back(read_triplet<3>(stream)); - log_error("vert", obj->verts.back()); + obj->verts.push_back(read_triplet(stream)); } } else if (atom == "numsurf") @@ -228,8 +239,7 @@ void mesh::import(std::istream& stream) stream >> atom; if (atom != "SURF") throw std::runtime_error("uh oh"); - int flags = read_hex(stream); - log_info(flags); + read_hex(stream); int material = 0; stream >> atom; @@ -246,77 +256,104 @@ void mesh::import(std::istream& stream) if ((int)obj->faces.size() <= material) { - log_info("inserting face..."); - //obj->faces.insert(obj->faces.begin() + material, - //material_group()); obj->faces.resize(material + 1); - log_info("inserted face", material, obj->faces.size()); } - material_group& face = obj->faces[material]; - int vert; + unsigned vert; stream >> vert; vector2 uv = read_pair(stream); + if (vert < face.triangles_uv.size()) + { + if (uv != face.triangles_uv[vert]) + { + obj->verts.push_back(obj->verts[vert]); + face.triangles_uv.resize(obj->verts.size()); + vert = obj->verts.size() - 1; + } + } + else face.triangles_uv.resize(vert + 1); + face.triangles_uv[vert] = uv; face.triangles.push_back(vert); - face.triangles_uv.push_back(uv); - unsigned first = face.triangles.back(); - vector2 first_uv = face.triangles_uv.back(); + unsigned first = vert; stream >> vert; uv = read_pair(stream); + if (vert < face.triangles_uv.size()) + { + if (uv != face.triangles_uv[vert]) + { + obj->verts.push_back(obj->verts[vert]); + face.triangles_uv.resize(obj->verts.size()); + vert = obj->verts.size() - 1; + } + } + else face.triangles_uv.resize(vert + 1); + face.triangles_uv[vert] = uv; face.triangles.push_back(vert); - face.triangles_uv.push_back(uv); stream >> vert; uv = read_pair(stream); + if (vert < face.triangles_uv.size()) + { + if (uv != face.triangles_uv[vert]) + { + obj->verts.push_back(obj->verts[vert]); + face.triangles_uv.resize(obj->verts.size()); + vert = obj->verts.size() - 1; + } + } + else face.triangles_uv.resize(vert + 1); + face.triangles_uv[vert] = uv; face.triangles.push_back(vert); - face.triangles_uv.push_back(uv); - unsigned last = face.triangles.back(); - vector2 last_uv = face.triangles_uv.back(); + unsigned last = vert; for (int j = 3; j < numrefs; ++j) { - // first face.triangles.push_back(first); - face.triangles_uv.push_back(first_uv); - - // last face.triangles.push_back(last); - face.triangles_uv.push_back(last_uv); stream >> vert; uv = read_pair(stream); + if (vert < face.triangles_uv.size()) + { + if (uv != face.triangles_uv[vert]) + { + obj->verts.push_back(obj->verts[vert]); + face.triangles_uv.resize(obj->verts.size()); + vert = obj->verts.size() - 1; + } + } + else face.triangles_uv.resize(vert + 1); + face.triangles_uv[vert] = uv; face.triangles.push_back(vert); - face.triangles_uv.push_back(uv); last = face.triangles.back(); - last_uv = face.triangles_uv.back(); } } } else if (atom == "kids") { - for (int i = kids.size(); i > 0; --i) - { - if (--kids.top() <= 0) - { - ASSERT(obj && "should be an object"); - obj = obj->parent; - kids.pop(); - } - else break; - } + //while (0 < kids.size()) + //{ + //if (--kids.top() <= 0) + //{ + //ASSERT(obj && "should be an object"); + //obj = obj->parent; + //kids.pop(); + //} + //else break; + //} int numkids = 0; stream >> numkids; - if (numkids > 0) kids.push(numkids); - - if (kids.size() > 0) + if (0 < numkids) kids.push(numkids); + else { - log_info("KIDS", kids.top(), "|", kids.size()); + if (0 < kids.size() && 0 < --kids.top()) kids.pop(); + obj = obj->parent.lock(); } } else @@ -325,8 +362,41 @@ void mesh::import(std::istream& stream) } } while (stream); + + std::vector::iterator meh; + for (meh = objects_.begin(); meh != objects_.end(); ++meh) + { + object_ptr cow = *meh; + log_info("OBJ: -", cow->name, cow->kids.size()); + + std::vector::iterator foo; + for (foo = cow->kids.begin(); foo != cow->kids.end(); ++foo) + { + log_info("OBJ: -", (*foo)->name, (*foo)->kids.size()); + } + } } +//unsigned mesh::read_vertex_line(std::istream& stream) +//{ + //unsigned vert; + //stream >> vert; + //vector2 uv = read_pair(stream); + //if (vert < face.triangles_uv.size()) + //{ + //if (uv != face.triangles_uv[vert]) + //{ + //obj->verts.push_back(obj->verts[vert]); + //face.triangles_uv.resize(obj->verts.size()); + //vert = obj->verts.size() - 1; + //} + //} + //else face.triangles_uv.resize(vert + 1); + //face.triangles_uv[vert] = uv; + //face.triangles.push_back(vert); +//} + + mesh::mesh(const std::string& path) { @@ -405,16 +475,15 @@ mesh::mesh(const std::string& path) void mesh::draw(scalar alpha) const { - //glEnableClientState(GL_VERTEX_ARRAY); - //glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - std::vector::const_iterator it; for (it = objects_.begin(); it != objects_.end(); ++it) { - (*it)->draw(*this, alpha); + (*it)->draw(alpha); } + + // TODO: disable vertex array? } @@ -425,94 +494,68 @@ void mesh::set_material(int index) const void mesh::set_material(const material& material) const { - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material.diffuse.data()); - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material.ambient.data()); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material.specular.data()); - glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, material.emissive.data()); - glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material.shininess); - //glColor(material.diffuse); + glColor(material.diffuse); + glMaterial(GL_FRONT, GL_DIFFUSE, material.diffuse); + glMaterial(GL_FRONT, GL_AMBIENT, material.ambient); + glMaterial(GL_FRONT, GL_SPECULAR, material.specular); + glMaterial(GL_FRONT, GL_EMISSION, material.emissive); + glMaterial(GL_FRONT, GL_SHININESS, material.shininess); } -void mesh::object::draw(const mesh& mesh, scalar alpha) const +void mesh::object::draw(scalar alpha, bool recurse) const { - //log_info("cool", verts.size()); - //{ - //image::reset_binding(); - //std::vector::const_iterator it; - //glBegin(GL_LINE_STRIP); - //for (it = verts.begin(); it != verts.end(); ++it) - //{ - //glVertex(*it); - //} - //glEnd(); - //} - - //glPolygonMode(GL_BACK, GL_LINE); - //glVertexPointer(3, GL_SCALAR, 0, verts[0].data()); - if (texture) texture->bind(); - else image::reset_binding(); + glVertexPointer(verts); + + if (texture) + { + texture->bind(); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + } + else + { + image::reset_binding(); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } for (size_t i = 0; i < faces.size(); ++i) { const material_group& face = faces[i]; + if (face.triangles.size() == 0) continue; + mesh.set_material(i); - //it->draw(alpha); - //std::vector::const_iterator jt; - int count = face.triangles.size(); - for (int j = 0; j < count; j += 3) - { - glBegin(GL_TRIANGLES); - glTexCoord(face.triangles_uv[j]); - glVertex(verts[face.triangles[j]]); - glTexCoord(face.triangles_uv[j+1]); - glVertex(verts[face.triangles[j+1]]); - glTexCoord(face.triangles_uv[j+2]); - glVertex(verts[face.triangles[j+2]]); - glEnd(); - } - } - std::vector::const_iterator jt; - for (jt = kids.begin(); jt != kids.end(); ++jt) - { - (*jt)->draw(mesh, alpha); + if (texture) glTexCoordPointer(face.triangles_uv); + glDrawElements(GL_TRIANGLES, face.triangles); } -} -void mesh::material_group::draw(scalar alpha) const -{ - // TODO: setup material - - /* - if (triangles.size() > 0) + if (recurse) { - //log_info("drawing triangles:", triangles.size()/3); - glTexCoordPointer(2, GL_SCALAR, 0, triangles_uv[0].data()); - glDrawElements(GL_TRIANGLES, - triangles.size(), GL_UNSIGNED_INT, - &triangles[0]); + std::vector::const_iterator jt; + for (jt = kids.begin(); jt != kids.end(); ++jt) + { + (*jt)->draw(alpha); + } } - */ } -class mesh_resource_loader -{ -public: +//class mesh_resource_loader +//{ +//public: - mesh_resource_loader() - { - resource::register_type("ac", "models"); - } + //mesh_resource_loader() + //{ + //resource::register_type("ac", "models"); + //} - ~mesh_resource_loader() - { - resource::unregister_type("ac"); - } -}; + //~mesh_resource_loader() + //{ + //resource::unregister_type("ac"); + //} +//}; -static mesh_resource_loader loader; +//static mesh_resource_loader loader; } // namespace moof diff --git a/src/moof/mesh.hh b/src/moof/mesh.hh index cf267fb..0fbc3cc 100644 --- a/src/moof/mesh.hh +++ b/src/moof/mesh.hh @@ -18,11 +18,14 @@ */ #include +#include +#include #include #include +#include -#include +#include #include #include #include @@ -31,7 +34,10 @@ namespace moof { -class mesh : public boost::noncopyable, public drawable +class script; + + +class mesh : public boost::noncopyable, public entity { public: @@ -49,9 +55,9 @@ public: std::string name; vector4 diffuse; - vector3 ambient; - vector3 emissive; - vector3 specular; + vector4 ambient; + vector4 emissive; + vector4 specular; scalar shininess; }; @@ -59,13 +65,8 @@ public: void set_material(int index) const; void set_material(const material& material) const; - struct material_group : public drawable + struct material_group { - material_group() {} - - void draw(scalar alpha = SCALAR(0.0)) const; - - std::vector triangles; std::vector triangles_uv; }; @@ -73,20 +74,23 @@ public: class object; typedef boost::shared_ptr object_ptr; + typedef boost::weak_ptr object_weakptr; struct object { - object() : + object(const mesh& m) : + mesh(m), texrep(SCALAR(1.0), SCALAR(1.0)) {} - static object_ptr alloc() + static object_ptr alloc(const mesh& m) { - return object_ptr(new object); + return object_ptr(new object(m)); } + void draw(scalar alpha = SCALAR(0.0), bool recurse = true) const; - void draw(const mesh& mesh, scalar alpha = SCALAR(0.0)) const; + const moof::mesh& mesh; std::string name; std::string data; @@ -99,10 +103,25 @@ public: std::vector faces; std::vector kids; - object_ptr parent; + std::map kids_byname; + object_weakptr parent; }; + object_ptr operator [] (unsigned index) const + { + return objects_[index]; + } + + + /** + * Import script bindings for the mesh class. + * \param The script. + * \param The name of the namespace to import to. + */ + static void import(script& script, const std::string& nspace = ""); + + private: void import(std::istream& stream); diff --git a/src/moof/mesh_bindings.cc b/src/moof/mesh_bindings.cc new file mode 100644 index 0000000..02138ad --- /dev/null +++ b/src/moof/mesh_bindings.cc @@ -0,0 +1,136 @@ + +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ + +#include "log.hh" +#include "mesh.hh" +#include "script.hh" + + +namespace moof { + + +static int mesh_new(script& script) +{ + script::slot name = script[2].require_string("mesh name"); + + std::string str; + name.get(str); + + mesh_handle mesh = resource::load(str, "ac"); + if (!mesh) name.raise("unable to load mesh from file"); + + script.push(mesh); + return 1; +} + +static int mesh_draw(script& script) +{ + mesh_handle* mesh; + script[1].require_object("mesh").get(mesh); + + scalar alpha; + if (script[2].get(alpha)) (*mesh)->draw(alpha); + else (*mesh)->draw(); + + return 0; +} + +static int mesh_index(script& script) +{ + mesh_handle* mesh; + script[1].require_object("mesh").get(mesh); + + unsigned index; + script[2].require_number("index").get(index); + --index; + + script.push((**mesh)[index]); + script::slot e = script[-1].push_environment(); + e.set_field("mesh", *mesh); + e.pop(); + return 1; +} + + +static int object_new(script& script) +{ + return script.raise("cannot construct a mesh object without a mesh"); +} + +static int object_draw(script& script) +{ + mesh::object_ptr* object; + script[1].require_object("mesh object").get(object); + + scalar alpha; + bool recurse; + if (script[2].get(alpha)) + { + if (script[3].get(recurse)) (*object)->draw(alpha, recurse); + else (*object)->draw(alpha); + } + else + { + if (script[2].get(recurse)) (*object)->draw(SCALAR(0.0), recurse); + else (*object)->draw(); + } + + return 0; +} + +static int object_index(script& script) +{ + mesh::object_ptr* object; + script[1].require_object("mesh object").get(object); + + if (script[2].is_number()) + { + unsigned index; + script[2].get(index); + --index; + script.push((*object)->kids[index]); + } + else if (script[2].is_string()) + { + std::string name; + script[2].get(name); + script.push((*object)->kids_byname[name]); + } + else + { + script[2].raise_type_error("index or name"); + } + return 1; +} + + +void mesh::import(script& script, const std::string& nspace) +{ + script.check_stack(8); + + script::slot parent = script.push_table(nspace); + script::slot meta = script.push_class(mesh_new); + + meta.set_field("draw", mesh_draw); + meta.set_field("object", mesh_index); + + script::slot object_meta = script.push_class(object_new); + object_meta.set_field("draw", object_draw); + object_meta.set_field("kid", object_index); + meta.set_field("__object"); + + parent.set_field("mesh"); + parent.pop(); +} + + +} // namespace moof + diff --git a/src/moof/modal_dialog.hh b/src/moof/modal_dialog.hh index 23e929b..e1d7739 100644 --- a/src/moof/modal_dialog.hh +++ b/src/moof/modal_dialog.hh @@ -140,8 +140,8 @@ struct modal_dialog "%s", text2.c_str()); gtk_window_set_title(GTK_WINDOW(dialog), title.c_str()); - std::string icon_path(PACKAGE".png"); - if (resource::find(icon_path)) + std::string icon_path = resource::find_file(PACKAGE".png"); + if (!icon_path.empty()) { GdkPixbuf* iconPixbuf = gdk_pixbuf_new_from_file(icon_path.c_str(), NULL); @@ -180,8 +180,8 @@ struct modal_dialog dialog.setInformativeText(text2.c_str()); dialog.setStandardButtons(QMessageBox::Close); - std::string icon_path(PACKAGE".png"); - if (resource::find(icon_path)) + std::string icon_path = resource::find_file(PACKAGE".png"); + if (!icon_path.empty()) { QIcon icon(icon_path.c_str()); dialog.setWindowIcon(icon); diff --git a/src/moof/opengl.hh b/src/moof/opengl.hh index 347f3e5..06ffbaa 100644 --- a/src/moof/opengl.hh +++ b/src/moof/opengl.hh @@ -20,6 +20,8 @@ #include "config.h" +#include + #include #include @@ -105,6 +107,36 @@ OPENGL_GENERIC_FUNC(void, Rect, S4); OPENGL_GENERIC_FUNC(void, Rect, V4); +inline void glMaterial(GLenum face, GLenum pname, moof::scalar s) +{ + glMaterialf(face, pname, float(s)); +} + +inline void glMaterial(GLenum face, GLenum pname, const moof::vector4& v) +{ +#if USE_DOUBLE_PRECISION + float f[] = {v[0], v[1], v[2], v[3]}; + glMaterialfv(face, pname, f); +#else + glMaterialfv(face, pname, v.data()); +#endif +} + +inline void glVertexPointer(const std::vector& v) +{ + glVertexPointer(3, GL_SCALAR, 0, v[0].data()); +} +inline void glTexCoordPointer(const std::vector& v) +{ + glTexCoordPointer(2, GL_SCALAR, 0, v[0].data()); +} + +inline void glDrawElements(GLenum type, const std::vector& v) +{ + glDrawElements(type, v.size(), GL_UNSIGNED_INT, &v[0]); +} + + #if USE_DOUBLE_PRECISION inline void glGetScalar(GLenum a, GLscalar* b) { glGetDoublev(a, b); } #else diff --git a/src/moof/resource.cc b/src/moof/resource.cc index 57bd99b..3cf901b 100644 --- a/src/moof/resource.cc +++ b/src/moof/resource.cc @@ -11,13 +11,13 @@ #include "config.h" +#include + #ifdef USE_HOTLOADING #include #include #endif -#include - #include #include #include @@ -34,239 +34,261 @@ namespace moof { -bool resource::call_registry(const std::string& extension, - loader_ptr& loader, - registry_action action) +/*] Filesystem searching + *************************************************************************/ + +static std::vector search_paths_; + +void resource::set_search_paths(const std::string& paths) { - static type_lookup table; + boost::split(search_paths_, paths, boost::is_any_of(":")); +} - switch (action) + +std::string resource::find_file(const std::string& name) +{ + std::string ext = stlplus::extension_part(name); + std::string prefix; + std::string path; + + loader_ptr loader; + call_registry(ext, loader, lookup); + if (loader) prefix = loader->prefix(); + + std::vector::iterator it; + for (it = search_paths_.begin(); it != search_paths_.end(); ++it) { - case set: + if (!prefix.empty()) { - if (loader) table[extension] = loader; - else table.erase(extension); - break; + // try it with the prefix first + path = stlplus::filespec_to_path(*it, prefix); + path = stlplus::filespec_to_path(path, name); + log_info("looking for", name, "at", path); + if (stlplus::file_exists(path)) return path; } - case lookup: - { - std::map::iterator it; - it = table.find(extension); - if (it != table.end()) loader = (*it).second; - break; - } + path = stlplus::filespec_to_path(*it, name); + log_info("looking for", name, "at", path); + if (stlplus::file_exists(path)) return path; } - return loader; + log_error("cannot find resource file:", name); + return std::string(); } -static std::string search_paths_; - -typedef boost::weak_ptr resource_weakptr; -static hash resource_table_; - -static hash prefix_table_; +std::string resource::find_file(const std::string& name, + const std::string& ext) +{ + std::string actual_ext = stlplus::extension_part(name); + if (actual_ext != ext) + { + // try the explicit extension first + return find_file(stlplus::create_filename(name, ext)); + } + return find_file(name); +} -#ifdef USE_HOTLOADING -static hash monitor_lookup_; -static int monitor_fd_ = inotify_init1(IN_NONBLOCK); -#endif +/*] Resource loading + *************************************************************************/ -int resource::reload_as_needed() +typedef boost::weak_ptr resource_weakptr; +static struct rsrc_list { - int num_resources = 0; + // this table holds weak references to any and all loaded resources + hash table; -#ifdef USE_HOTLOADING - log_info("hotloading?"); - char bytes[BUF_SIZE]; - int num_bytes; - if (0 < (num_bytes = read(monitor_fd_, bytes, num_bytes))) +#ifdef DEBUG + // this destructor will let us know if the program exits while + // resources are still being held + ~rsrc_list() { - char* end = bytes + num_bytes; - char* byte = bytes; - - log_warning("num_bytes:", num_bytes); - log_error("1"); - - while (byte < end) + hash::iterator it; + for (it = table.begin(); it != table.end(); ++it) { - struct inotify_event* event = (struct inotify_event*)byte; + log_warning("leaked resource:", (*it).first); + } + } +#endif +} rsrc_list; - if (event->mask & IN_IGNORED) - { - log_warning("watch", event->wd, "removed"); - } +#ifdef USE_HOTLOADING +static struct watch_list +{ + // this table associates a watch descriptor with a loaded resource + hash table; - log_error("2"); - hash::iterator it; - it = monitor_lookup_.find(event->wd); - if (it != monitor_lookup_.end()) - { - log_error("3"); - std::string path = (*it).second; - monitor_lookup_.erase(it); - resource::reload(path); - } + int fd; // the inotify file descriptor - byte += sizeof(*event) + event->len; + watch_list() : + fd(inotify_init1(IN_NONBLOCK)) {} - ++num_resources; - } + ~watch_list() + { + close(fd); } -#endif - return num_resources; -} + int add(resource_ptr rsrc) + { + int wd = inotify_add_watch(fd, rsrc->path().c_str(), + IN_DELETE_SELF | IN_MODIFY); + table[wd] = rsrc; + return wd; + } + void remove(int wd) + { + if (wd != -1) inotify_rm_watch(fd, wd); + } +} watch_list; +#endif -resource::~resource() +resource_ptr resource::load(const std::string& name) { -#ifdef USE_HOTLOADING - inotify_rm_watch(monitor_fd_, wd_); -#endif + std::string ext = stlplus::extension_part(name); + return load_with_path(find_file(name, ext), ext); } - resource_ptr resource::load(const std::string& name, const std::string& ext) { - return load_with_path(find_file(name, ext)); -} - -resource_ptr resource::load(const std::string& name) -{ - return load_with_path(find_file(name)); + return load_with_path(find_file(name, ext), ext); } -resource_ptr resource::load_with_path(const std::string& path) +resource_ptr resource::load_with_path(const std::string& path, + const std::string& ext) { - std::string extension = stlplus::extension_part(path); + if (path.empty()) return resource_ptr(); + // first try to lookup the resource hash::iterator it; - it = resource_table_.find(path); - if (it != resource_table_.end()) + it = rsrc_list.table.find(path); + if (it != rsrc_list.table.end()) { - resource_weakptr rsrc = (*it).second; - resource_ptr locked = rsrc.lock(); - if (locked) return locked; + resource_ptr rsrc = (*it).second.lock(); + if (rsrc) return rsrc; } + // then proceed to use the registered loader to get the resource loader_ptr loader; - call_registry(extension, loader, lookup); + call_registry(ext, loader, lookup); if (loader) { resource_ptr rsrc(loader->load(path)); - rsrc->set_loader(path, loader); - resource_table_[path] = rsrc; - + rsrc_list.table[path] = rsrc; + rsrc->path_ = path; + rsrc->type_ = ext; #ifdef USE_HOTLOADING - int wd = inotify_add_watch(monitor_fd_, path.c_str(), IN_MODIFY); - rsrc->set_watch_descriptor(wd); - monitor_lookup_[wd] = path; + rsrc->wd_ = watch_list.add(rsrc); #endif - - log_info("loaded", rsrc.get()); return rsrc; } - log_warning("cannot load resource of unknown type:", path); + log_warning("cannot load resource of unregistered type:", path); return resource_ptr(); } -resource_ptr resource::reload(std::string& path) +/*] Hotloading + *************************************************************************/ + +int resource::reload_as_needed() { - log_info("reloading...", path); - hash::iterator it; - it = resource_table_.find(path); - if (it != resource_table_.end()) + int count = 0; + +#ifdef USE_HOTLOADING + char bytes[BUF_SIZE]; + int num_bytes; + // an inotify file descriptor lets your read inotify_event structures + if (0 < (num_bytes = read(watch_list.fd, bytes, sizeof(bytes)))) { - resource_weakptr rsrc = (*it).second; - resource_ptr locked = rsrc.lock(); - if (locked) + char* end = bytes + num_bytes; + char* byte = bytes; + + while (byte < end) { - locked->reload(); - return locked; + struct inotify_event* event = (struct inotify_event*)byte; + byte += sizeof(*event) + event->len; + + hash::iterator it; + it = watch_list.table.find(event->wd); + if (it != watch_list.table.end()) + { + resource_ptr rsrc = (*it).second.lock(); + if (rsrc) + { + rsrc->reload(); + ++count; + + if (event->mask & IN_IGNORED) + { + watch_list.table.erase(event->wd); + rsrc->wd_ = watch_list.add(rsrc); + } + } + else + { + // if we can't lock the resource, it was unloaded so we + // don't need to watch it anymore + watch_list.table.erase(event->wd); + } + } } } +#endif - return load(path); + return count; } void resource::reload() { - log_info("reloaded", path_); + loader_ptr loader; + call_registry(type_, loader, lookup); - resource* resource = loader_->load(path_); - //*this = *resource; + resource_ptr resource(loader->load(path_)); resource_ = resource->resource_; typeinfo_ = resource->typeinfo_; unloader_ = resource->unloader_; +} +resource::~resource() +{ + rsrc_list.table.erase(path_); #ifdef USE_HOTLOADING - int wd = inotify_add_watch(monitor_fd_, path_.c_str(), IN_MODIFY); - set_watch_descriptor(wd); - monitor_lookup_[wd] = path_; + watch_list.remove(wd_); #endif - - delete resource; } -void resource::add_search_paths(const std::string& paths) -{ - search_paths_ = paths; -} +/*] Resource registration + *************************************************************************/ - -std::string resource::find_file(const std::string& name) +bool resource::call_registry(const std::string& ext, + loader_ptr& loader, + registry_action action) { - std::vector paths; - boost::split(paths, search_paths_, boost::is_any_of(":")); - - std::string ext = stlplus::extension_part(name); - std::string prefix("hi"); - - loader_ptr loader; - call_registry(ext, loader, lookup); - if (loader) prefix = loader->prefix(); + static std::map table; - log_info("find_file:", ext, prefix); - - std::vector::iterator it; - for (it = paths.begin(); it != paths.end(); ++it) + switch (action) { - std::string path = stlplus::create_filespec(*it, name); - log_info("looking for", name, "at", path); - if (stlplus::file_exists(path)) return path; - - // try it with the prefix added - if (!prefix.empty()) + case set: { - *it = stlplus::create_filespec(*it, prefix); - path = stlplus::create_filespec(*it, name); - log_info("looking for", name, "at", path); - if (stlplus::file_exists(path)) return path; + if (loader) table[ext] = loader; + else table.erase(ext); + break; } - } - - log_error("cannot find resource file:", name); - return std::string(); -} - -std::string resource::find_file(const std::string& name, - const std::string& ext) -{ - std::string actual_ext = stlplus::extension_part(name); - if (actual_ext != ext) - { - return find_file(stlplus::create_filename(name, ext)); + case lookup: + { + std::map::iterator it; + it = table.find(ext); + if (it != table.end()) loader = (*it).second; + break; + } } - return find_file(name); + + return loader; } diff --git a/src/moof/resource.hh b/src/moof/resource.hh index 9d99105..094791c 100644 --- a/src/moof/resource.hh +++ b/src/moof/resource.hh @@ -17,8 +17,6 @@ * Interface for textures, sounds, and other types of resources. */ -#include "config.h" - #include #include #include @@ -45,25 +43,30 @@ class resource { public: - // XXX: this won't be necessary once the existing code is modified to - // use the resource handles - resource() {} - /** * Add a directory to search when looking for resource files. * \param paths A colon-separated list of directory paths. */ - static void add_search_paths(const std::string& paths); + static void set_search_paths(const std::string& paths); /** - * Get the path to a resource of a given name. - * \param path The name of the resource to find. Upon successful - * return, this is changed to an absolute path to the resource. - * \return True if a path to a resource was found, false otherwise. + * Get the path to a resource of a given name. This uses the search + * path(s) and resources prefixes to locate resource files. + * \param name The name or partial path of the resource to find. + * \return The full path of the resource. */ static std::string find_file(const std::string& name); + /** + * Get the path to a resource of a given name and explicit type. This + * uses the search path(s) and resources prefixes to locate resource + * files. + * \param name The name or partial path of the resource to find. + * \param ext The extension is appended to the name if the same + * extension is not already a part of name. + * \return The full path of the resource. + */ static std::string find_file(const std::string& name, const std::string& ext); @@ -85,7 +88,7 @@ public: * Unregister the type associated with a file extension. Resources of * this type will no longer be loadable, although resources which are * already loaded will remain loaded. - * \param extension The file extension + * \param extension The file extension. */ static void unregister_type(const std::string& extension) { @@ -94,34 +97,46 @@ public: } + /** + * Find and load a resource by name or path. + * \param name The name or partial path of the resource. This should + * include the extension so that the correct loader can be chosen. + * \return The resource. + */ static resource_ptr load(const std::string& name); + + /** + * Find and load a resource by name or path. + * \param name The name or partial path of the resource. This should + * include the extension so that the correct loader can be chosen. + * \param + * \return The resource. + */ static resource_ptr load(const std::string& name, const std::string& ext); - static resource_ptr reload(std::string& path); - /** - * Construct a resource container. - * \param ptr A pointer to the underlying resource data. + * Reload the resource data. This will cause the resource file to be + * reread, and the underlying resource data will change. */ - template - explicit resource(T* ptr) : - resource_(ptr), - typeinfo_(const_cast(&typeid(T))), - unloader_(new specific_unloader(ptr)) {} + void reload(); /** - * Deconstruct a resource container. + * Get the path of file from which this resource was loaded. + * \return The path. */ - virtual ~resource(); - + std::string path() const + { + return path_; + } /** - * Reload the resource data. This will cause the resource file to be - * reread, and the underlying resource data will change. + * Reloads some resources which have been modified on disk since they + * were loaded. Hotloading must have been enabled at compile-time. + * \return The number of resources reloaded. */ - void reload(); + static int reload_as_needed(); /** @@ -149,22 +164,28 @@ public: /** - * Reloads some resources which have been modified on disk since they - * were loaded. Hotloading must have been enabled at compile-time. - * \return The number of resources reloaded. + * Deconstruct a resource container. */ - static int reload_as_needed(); + virtual ~resource(); private: - static resource_ptr load_with_path(const std::string& path); + template + explicit resource(T* ptr) : + resource_(ptr), + typeinfo_(const_cast(&typeid(T))), + unloader_(new specific_unloader(ptr)), + wd_(-1) {} + + static resource_ptr load_with_path(const std::string& path, + const std::string& extension); + class loader { public: - //loader() {} loader(const std::string& prefix) : prefix_(prefix) {} @@ -193,13 +214,11 @@ private: { public: - //specific_loader() {} specific_loader(const std::string& prefix) : loader(prefix) {} virtual resource* load(const std::string& path) { - log_info("loading resource of type ", typeid(T).name()); return new resource(new T(path)); } }; @@ -224,7 +243,6 @@ private: virtual ~specific_unloader() { - log_info("unloading resource of type ", typeid(T).name()); delete object_; } @@ -235,25 +253,6 @@ private: }; - void set_loader(const std::string& path, loader_ptr loader) - { - path_ = path; - loader_ = loader; - } - - - void* resource_; - std::type_info* typeinfo_; - unloader_ptr unloader_; - - std::string path_; - loader_ptr loader_; - - typedef std::map type_lookup; - //typedef boost::shared_ptr type_lookup_ptr; - //static type_lookup_ptr type_lookup_; - //static type_lookup type_lookup_; - enum registry_action { lookup, @@ -264,14 +263,13 @@ private: loader_ptr& loader, registry_action action); -#ifdef USE_HOTLOADING - int wd_; - void set_watch_descriptor(int wd) - { - wd_ = wd; - } -#endif + void* resource_; + std::type_info* typeinfo_; + unloader_ptr unloader_; + int wd_; + std::string path_; + std::string type_; }; @@ -304,7 +302,6 @@ public: resource_(resource::load(name, ext)) {} - /** * Get whether or not the handle is dereferenceable to the type of this * handle. A resource handle is dereferenceable if it is not a null @@ -376,6 +373,23 @@ private: }; +/** + * This macro easily registers types to act as resources. It should be + * used in a module file in global scope. + * \param TYPE The type (class), qualified as needed for the scope. + * \param EXT The file extension the resource uses. + * \param PREFIX The path prefix where a resource of this type could be. + */ +#define MOOF_REGISTER_RESOURCE(TYPE, EXT, PREFIX) \ +namespace { \ + struct EXT { \ + EXT() { moof::resource::register_type(#EXT, #PREFIX); } \ + ~EXT() { moof::resource::unregister_type(#EXT); } \ + }; \ + static EXT EXT; \ +} + + } // namespace moof #endif // _MOOF_RESOURCE_HH_ diff --git a/src/moof/script.hh b/src/moof/script.hh index 85973dd..35e80d2 100644 --- a/src/moof/script.hh +++ b/src/moof/script.hh @@ -14,7 +14,7 @@ /** * \file script.hh - * A thin wrapper over Lua. This is not meant as a complicated binding + * A thin wrapper over Lua 5.1. This is not meant as a complicated binding * package between C++ and Lua. It is not meant to obscure the division * between C++ and Lua but rather to clarify it and make it more * manageable. It does not hide the concept of the Lua stack, but rather @@ -22,10 +22,13 @@ * providing a cleaner, more consistent API. */ +#include #include -#include #include +#include #include +#include +#include #include #include @@ -46,6 +49,7 @@ class script public: typedef boost::function function; + typedef int (*cfunction)(script&); enum status { @@ -65,6 +69,15 @@ public: globals_index = LUA_GLOBALSINDEX }; + + template + static int object_finalizer(script& script) + { + reinterpret_cast(script[1].get_data())->~T(); + return 0; + } + + /** * This is the most prominent abstraction on top of the standard Lua * API. A slot object represents a value on the stack. More @@ -74,14 +87,12 @@ public: * value of which will change as things are pushed onto and popped from * the stack). */ - struct slot { /** * You have direct access to the index of the value on the stack * being represented. */ - int index; @@ -99,140 +110,128 @@ public: thread = LUA_TTHREAD }; + static std::string type_name(type type) + { + switch (type) + { + case none: return "none"; + case nil: return "nil"; + case boolean: return "boolean"; + case light_data: + case data: return "userdata"; + case number: return "number"; + case string: return "string"; + case table: return "table"; + case function: return "function"; + case thread: return "thread"; + } + return "?"; + } + slot(const class script& s, int i = 0) : index(i), - script_(const_cast(s)) {} - - /** - * A copied value presently points to the same value, except the - * real index is used. That means that if a value that refers to a - * frame referenced from the top of the stack will have its - * normalized index copied into the new value object. - */ - - //slot(const slot& copy) : - //index(copy.positiveIndex()), - //script_(copy.script_) {} + script_(const_cast(&s)) {} // check the type of the value bool is_boolean() const - { return (bool)lua_isboolean(script_.state_, index); } + { return (bool)lua_isboolean(script_->state_, index); } bool is_imported_function() const - { return (bool)lua_iscfunction(script_.state_, index); } + { return (bool)lua_iscfunction(script_->state_, index); } bool is_function() const - { return (bool)lua_isfunction(script_.state_, index); } + { return (bool)lua_isfunction(script_->state_, index); } bool is_nil() const - { return (bool)lua_isnil(script_.state_, index); } + { return (bool)lua_isnil(script_->state_, index); } bool is_none() const - { return (bool)lua_isnone(script_.state_, index); } + { return (bool)lua_isnone(script_->state_, index); } bool is_none_or_nil() const - { return (bool)lua_isnoneornil(script_.state_, index); } + { return (bool)lua_isnoneornil(script_->state_, index); } bool is_number() const - { return (bool)lua_isnumber(script_.state_, index); } + { return (bool)lua_isnumber(script_->state_, index); } bool is_string() const - { return (bool)lua_isstring(script_.state_, index); } + { return (bool)lua_isstring(script_->state_, index); } bool is_table() const - { return (bool)lua_istable(script_.state_, index); } + { return (bool)lua_istable(script_->state_, index); } bool is_thread() const - { return (bool)lua_isthread(script_.state_, index); } + { return (bool)lua_isthread(script_->state_, index); } bool is_data() const - { return (bool)lua_isuserdata(script_.state_, index); } + { return (bool)lua_isuserdata(script_->state_, index); } bool is_light_data() const - { return (bool)lua_islightuserdata(script_.state_, index); } + { return (bool)lua_islightuserdata(script_->state_, index); } /** * Check the value and throw an error if its the wrong type. - * There's a little caveat: This method never returns because it - * does a long jump. Consequently, constructed C++ objects which - * exist on the stack between the current frame and some lua - * function will not be destructed. That's not a problem for - * objects that only exist on the stack, but any objects that - * allocate memory on the heap (such as containers or strings) will - * leak. Therefore, you should only call this method after - * cleaning up such objects. The best thing to do for defining - * functions is to simply check all the parameters at the get-go - * before any C++ objects are even constructed. */ - - void require_type(type t) const + const slot& require_type(type t) const { - if (t != type()) - { - luaL_typerror(script_.state_, index, - lua_typename(script_.state_, t)); - } + if (t != type()) raise_type_error(type_name(t)); + return *this; } - void raise(const char* error) + const slot& require_boolean(const std::string& what = "boolean") const { - luaL_argerror(script_.state_, index, error); + if (!is_boolean()) raise_type_error(what); + return *this; } - - - slot& require_boolean() + const slot& require_number(const std::string& what = "number") const { - if (!is_boolean()) - { - luaL_typerror(script_.state_, index, "boolean"); - } + if (!is_number()) raise_type_error(what); return *this; } - slot& require_number() + const slot& require_string(const std::string& what = "string") const { - if (!is_number()) - { - luaL_typerror(script_.state_, index, "number"); - } + if (!is_string()) raise_type_error(what); return *this; } - slot& require_string() + const slot& require_table(const std::string& what = "table") const { - if (!is_string()) - { - luaL_typerror(script_.state_, index, "string"); - } + if (!is_table()) raise_type_error(what); return *this; } - slot& require_table() + const slot& require_function(const std::string& what = "function") const { - if (!is_table()) - { - luaL_typerror(script_.state_, index, "table"); - } + if (!is_function()) raise_type_error(what); return *this; } - slot& require_function() + const slot& require_data(const std::string& what = "userdata") const { - if (!is_function()) - { - luaL_typerror(script_.state_, index, "function"); - } + if (!is_data()) raise_type_error(what); return *this; } - slot& require_data() + const slot& require_nil(const std::string& what = "nil") const { - if (!is_data()) - { - luaL_typerror(script_.state_, index, "data"); - } + if (!is_nil()) raise_type_error(what); return *this; } - slot& require_nil() + const slot& require_thread(const std::string& what = "thread") const { - if (!is_nil()) - { - luaL_typerror(script_.state_, index, "nil"); - } + if (!is_thread()) raise_type_error(what); return *this; } - slot& require_thread() + + template + const slot& require_object(const std::string& what = typeid(T).name()) const { - if (!is_thread()) + if (!is_data()) raise_type_error(what); + + slot metatable = push_metatable(); + if (!metatable.is_table()) { - luaL_typerror(script_.state_, index, "thread"); + metatable.pop(); + raise_type_error(what); } + + slot type = metatable.push_field("__cxxtype"); + std::type_info* typeinfo; + if (!type.get(typeinfo)) + { + metatable.pop(); + raise_type_error(what); + } + + metatable.pop(); + if (*typeinfo != typeid(T)) raise_type_error(what); return *this; } @@ -240,19 +239,38 @@ public: /** * Get the type of the value. */ - enum type type() const { - return (enum type)lua_type(script_.state_, index); + return (enum type)lua_type(script_->state_, index); } /** * Get the name of the type of the value as a string. */ - std::string type_name() const { - return std::string(luaL_typename(script_.state_, index)); + if (is_none()) return "none"; + else if (is_data() && !is_light_data()) + { + slot metatable = push_metatable(); + if (!metatable.is_table()) + { + metatable.pop(); + return "userdata"; + } + + slot type = metatable.push_field("__cxxtype"); + std::type_info* typeinfo; + if (!type.get(typeinfo)) + { + metatable.pop(); + return "userdata"; + } + + metatable.pop(); + return typeinfo->name(); + } + return luaL_typename(script_->state_, index); } @@ -260,15 +278,19 @@ public: * Get the length of the value according to the definition given by * Lua. */ + size_t size() const + { + return lua_objlen(script_->state_, index); + } size_t length() const { - return lua_objlen(script_.state_, index); + return size(); } - int positiveIndex() const + int positive_index() const { - if (index < 0) return index + lua_gettop(script_.state_) + 1; + if (index < 0) return index + lua_gettop(script_->state_) + 1; else return index; } @@ -277,15 +299,14 @@ public: * Get a pointer value (for userdata, tables, threads, and * functions). */ - const void* id() const { - return lua_topointer(script_.state_, index); + return lua_topointer(script_->state_, index); } bool is_identical(const slot& rhs) const { - return &script_ == &(rhs.script_) && index == rhs.index; + return script_ == rhs.script_ && index == rhs.index; } operator bool () const @@ -296,41 +317,24 @@ public: bool operator == (const slot& rhs) const { - return (bool)lua_equal(script_.state_, index, rhs.index); - } - bool operator != (const slot& rhs) const - { - return !(*this == rhs); + return (bool)lua_equal(script_->state_, index, rhs.index); } bool operator < (const slot& rhs) const { - return (bool)lua_lessthan(script_.state_, index, rhs.index); - } - bool operator <= (const slot& rhs) const - { - return *this < rhs || *this == rhs; - } - bool operator > (const slot& rhs) const - { - return !(*this <= rhs); - } - bool operator >= (const slot& rhs) const - { - return !(*this < rhs); + return (bool)lua_lessthan(script_->state_, index, rhs.index); } /** * Convert the underlying value to a C++ type. */ - template bool get(T& value) const { if (is_number()) { - value = (T)lua_tointeger(script_.state_, index); + value = (T)lua_tointeger(script_->state_, index); return true; } return false; @@ -340,7 +344,7 @@ public: { if (is_number()) { - value = (float)lua_tonumber(script_.state_, index); + value = (float)lua_tonumber(script_->state_, index); return true; } return false; @@ -349,7 +353,7 @@ public: { if (is_number()) { - value = (double)lua_tonumber(script_.state_, index); + value = (double)lua_tonumber(script_->state_, index); return true; } return false; @@ -359,7 +363,7 @@ public: { if (is_boolean()) { - value = (bool)lua_toboolean(script_.state_, index); + value = (bool)lua_toboolean(script_->state_, index); return true; } return false; @@ -369,7 +373,7 @@ public: { if (is_string()) { - value = lua_tolstring(script_.state_, index, &size); + value = lua_tolstring(script_->state_, index, &size); return true; } return false; @@ -387,15 +391,20 @@ public: return false; } - bool get(void*& value) const + template + bool get(T*& value) const { if (is_data()) { - value = lua_touserdata(script_.state_, index); + value = reinterpret_cast(lua_touserdata(script_->state_, index)); return true; } return false; } + void* get_data() const + { + return lua_touserdata(script_->state_, index); + } template bool get(std::vector& array) const @@ -404,19 +413,19 @@ public: array.clear(); - slot value = script_[-1]; - int realIndex = positiveIndex(); + slot value = (*script_)[-1]; + int realIndex = positive_index(); bool done = false; for (int i = 1; !done; ++i) { - lua_rawgeti(script_.state_, realIndex, i); + lua_rawgeti(script_->state_, realIndex, i); T v; if (value.get(v)) array.push_back(v); else done = true; - script_.pop(); + script_->pop(); } return true; @@ -429,12 +438,12 @@ public: dictionary.clear(); - slot key = script_[-2]; - slot value = script_[-1]; - int realIndex = positiveIndex(); + slot key = (*script_)[-2]; + slot value = (*script_)[-1]; + int realIndex = positive_index(); - script_.push_nil(); - while (lua_next(script_.state_, realIndex) != 0) + script_->push_nil(); + while (lua_next(script_->state_, realIndex) != 0) { std::string k; if (!key.is_number() && key.get(k)) @@ -442,9 +451,9 @@ public: T v; if (value.get(v)) dictionary[k] = v; } - script_.pop(); + script_->pop(); } - script_.pop(); + script_->pop(); return true; } @@ -452,42 +461,58 @@ public: /** * Get the value of a field from the table. */ - template - bool get(T& value, V field) const + bool get(T& value, const V& field) const { bool ret = push_field(field).get(value); - script_.pop(); + script_->pop(); return ret; } template - void set_field(T field, V value) + void set_field(const T& field, const V& value) { - script_.push(field); - script_.push(value); + script_->push(field); + script_->push(value); set_field(); } void set_field() { - lua_settable(script_.state_, index); + lua_settable(script_->state_, index); + } + + + void set_field(const std::string& field) + { + set_field(field.c_str()); + } + void set_field(const char* field) + { + lua_setfield(script_->state_, index, field); } template - void set_field(const std::string& field, T value) + void set_field(const std::string& field, const T& value) { set_field(field.c_str(), value); } template - void set_field(const char* field, T value) + void set_field(const char* field, const T& value) { - script_.push(value); - lua_setfield(script_.state_, index, field); + script_->push(value); + set_field(field); } + /** + * Set the top value to be the metatable of this value. + */ + void set_metatable() + { + lua_setmetatable(script_->state_, index); + } /** * This set method, as opposed to the others, sets the value of the @@ -496,80 +521,81 @@ public: template void set(T value) { - script_.push(value); - replace(); + script_->push(value); + set(); } - void set() - { - replace(); - } - - /** * Replace this value with the value at the top of the stack. */ + void set() + { + lua_replace(script_->state_, index); + } - void replace() + void set_nil() { - lua_replace(script_.state_, index); + script_->push_nil(); + set(); } + void remove() { - lua_remove(script_.state_, index); + lua_remove(script_->state_, index); } + /** + * Remove this value and everything above it. + */ void pop() { - // removes this slot, taking with it everything above it - script_.pop(script_.stack_size() - index + 1); + if (index < 0) script_->pop(-index); + else script_->pop(script_->stack_size() - index + 1); } /** * Inserts the top-most value on the stack at position index, * shifting other values as needed. */ - void insert_top_here() { - lua_insert(script_.state_, index); + lua_insert(script_->state_, index); } /** * Copy the value and push the copy to the stack. */ - slot push_copy() const { - lua_pushvalue(script_.state_, index); - return script_.top(); + lua_pushvalue(script_->state_, index); + return script_->top(); } slot push_metatable() const { - lua_getmetatable(script_.state_, index); - return script_.top(); + lua_getmetatable(script_->state_, index); + return script_->top(); } slot push_environment() const { - lua_getfenv(script_.state_, index); - return script_.top(); + lua_getfenv(script_->state_, index); + return script_->top(); } slot push_field() const { - lua_gettable(script_.state_, index); - return script_.top(); + lua_gettable(script_->state_, index); + return script_->top(); } template slot push_field(T index) const { - script_.push(index); + script_->push(index); return push_field(); } @@ -579,25 +605,64 @@ public: } slot push_field(const char* name) const { - lua_getfield(script_.state_, index, name); - return script_.top(); + lua_getfield(script_->state_, index, name); + return script_->top(); } class script& script() { - return script_; + return *script_; } const class script& script() const { - return script_; + return *script_; + } + + + /** + * Throw an exception with a message formatted to communicate a + * type mismatch with the argument represented by this slot. + */ + int raise_type_error(const std::string& expected) const + { + lua_Debug ar; + lua_getstack(script_->state_, 0, &ar); + lua_getinfo(script_->state_, "n", &ar); + const char* func = ar.name ? ar.name : "unknown function"; + + std::ostringstream stream; + stream << "bad argument " << index << " to '" << func + << "' (" << expected << " expected, got " + << type_name() << ")"; + + throw std::invalid_argument(stream.str()); + return 0; + } + + /** + * Throw a generic error concerning this particular slot. + */ + int raise(const std::string& message) const + { + lua_Debug ar; + lua_getstack(script_->state_, 0, &ar); + lua_getinfo(script_->state_, "n", &ar); + const char* func = ar.name ? ar.name : "unknown function"; + + std::ostringstream stream; + stream << "bad argument " << index << " to '" << func + << "' (" << message << ")"; + + throw std::invalid_argument(stream.str()); + return 0; } private: - class script& script_; + mutable class script* script_; }; @@ -622,7 +687,6 @@ public: { if (state_) destroy(); state_ = luaL_newstate(); - registry().set_field("Script_hh_Object", (void*)this); } @@ -631,58 +695,84 @@ public: luaL_openlibs(state_); } + void import_safe_standard_libraries() + { + import_base_library(); + import_string_library(); + import_table_library(); + import_math_library(); + import_os_library(); + import_debug_library(); + + slot g = globals(); + + push_nil(); g.set_field("dofile"); + push_nil(); g.set_field("loadfile"); + push_nil(); g.set_field("require"); + push_nil(); g.set_field("io"); + push_nil(); g.set_field("package"); + slot os = g.push_field("os"); + push_nil(); os.set_field("execute"); + push_nil(); os.set_field("exit"); + push_nil(); os.set_field("getenv"); + push_nil(); os.set_field("remove"); + push_nil(); os.set_field("rename"); + push_nil(); os.set_field("tmpname"); + pop(); + } + void import_base_library() { - lua_pushcfunction(state_, luaopen_base); + push(luaopen_base); push(LUA_COLIBNAME); call(1, 0); } void import_package_library() { - lua_pushcfunction(state_, luaopen_package); + push(luaopen_package); push(LUA_LOADLIBNAME); call(1, 0); } void import_string_library() { - lua_pushcfunction(state_, luaopen_string); + push(luaopen_string); push(LUA_STRLIBNAME); call(1, 0); } void import_table_library() { - lua_pushcfunction(state_, luaopen_table); + push(luaopen_table); push(LUA_TABLIBNAME); call(1, 0); } void import_math_library() { - lua_pushcfunction(state_, luaopen_math); + push(luaopen_math); push(LUA_MATHLIBNAME); call(1, 0); } void import_io_library() { - lua_pushcfunction(state_, luaopen_io); + push(luaopen_io); push(LUA_IOLIBNAME); call(1, 0); } void import_os_library() { - lua_pushcfunction(state_, luaopen_os); + push(luaopen_os); push(LUA_OSLIBNAME); call(1, 0); } void import_debug_library() { - lua_pushcfunction(state_, luaopen_debug); + push(luaopen_debug); push(LUA_DBLIBNAME); call(1, 0); } @@ -705,7 +795,7 @@ public: } - /** + /* * Thread-handling methods. */ @@ -714,9 +804,10 @@ public: return script(state_); } - void push_thread() + slot push_thread() { lua_pushthread(state_); + return top(); } status resume(int nargs) @@ -724,7 +815,7 @@ public: return status(lua_resume(state_, nargs)); } - status getStatus() const + status thread_status() const { return status(lua_status(state_)); } @@ -736,28 +827,36 @@ public: bool is_main_thread() const { - return is_main_thread_; + bool is_main = lua_pushthread(state_); + lua_pop(state_, 1); + return is_main; } /** - * Throw an error with the value at the top of the stack. This method - * never returns because it does a long jump. Consequently, - * constructed C++ objects which exist on the stack between the - * current frame and some lua function will not be destructed. That's - * not a problem for objects that only exist on the stack, but any - * objects that allocate memory on the heap (such as containers or - * strings) will leak. Therefore, you should only call this method - * after cleaning up such objects. + * Throw an error with the value at the top of the stack. If this is + * called from an imported function, the error will be caught and + * returned on the stack when the execution aborts. */ + int raise() + { + throw std::runtime_error(""); + return 0; + } - void raise() + /** + * Throw an error with a given message describing the problem. If this + * is called from an imported function, the error will be caught and + * returned on the stack when the execution aborts. + */ + int raise(const std::string& message) { - lua_error(state_); + throw std::runtime_error(message); + return 0; } - /** + /* * Get significant values. */ @@ -817,7 +916,7 @@ public: * enough to hold whatever you want to push on it. This is usually * only an issue if you're pushing stuff in a loop. */ - bool checkStack(int extra) + bool check_stack(int extra) { return (bool)lua_checkstack(state_, extra); } @@ -832,11 +931,56 @@ public: } - /** + /* * Push some values onto the stack. */ - template - slot push(T value) + + slot push(char value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(unsigned char value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(short value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(unsigned short value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(int value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(unsigned int value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(long value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(unsigned long value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(long long value) + { + lua_pushinteger(state_, lua_Integer(value)); + return top(); + } + slot push(unsigned long long value) { lua_pushinteger(state_, lua_Integer(value)); return top(); @@ -850,12 +994,12 @@ public: slot push(float value) { - lua_pushnumber(state_, (lua_Number)value); + lua_pushnumber(state_, lua_Number(value)); return top(); } slot push(double value) { - lua_pushnumber(state_, (lua_Number)value); + lua_pushnumber(state_, lua_Number(value)); return top(); } @@ -877,18 +1021,56 @@ public: slot push(const function& function) { - functions_.push_back(function); - lua_pushlightuserdata(state_, (void*)&functions_.back()); - lua_pushcclosure(state_, dispatch_call, 1); + push(function); + push_pointer(this); + push(call_functor, 2); return top(); } - - slot push(void* data) + slot push(cfunction function) { - lua_pushlightuserdata(state_, data); + push_pointer(function); + push_pointer(this); + push(call_function, 2); return top(); } + template + slot push(const T& object) + { + void* storage; + slot copy = push_data(storage, sizeof(T)); + new(storage) T(object); + + push_class_metatable(); + copy.set_metatable(); + return copy; + } + + template + slot push_class(const function& ctor) + { + slot metatable = push_class_metatable(); + + slot constructor = push_table(); + push(ctor); + constructor.set_field("__call"); + metatable.set_metatable(); + + return metatable; + } + template + slot push_class(cfunction ctor) + { + slot metatable = push_class_metatable(); + + slot constructor = push_table(); + push(ctor); + constructor.set_field("__call"); + metatable.set_metatable(); + + return metatable; + } + slot push_nil() { lua_pushnil(state_); @@ -917,18 +1099,59 @@ public: return top(); } - slot push_new_data(void*& data, size_t size) + slot push_data(void*& data, size_t size) { data = lua_newuserdata(state_, size); return top(); } - slot push_new_table(int narr = 0, int nrec = 0) + template + slot push_pointer(const T* ptr) + { + lua_pushlightuserdata(state_, const_cast((const void*)ptr)); + return top(); + } + slot push_pointer(cfunction function) + { + return push_pointer((void*)function); + } + + slot push_table(const std::string& name, int narr = 0, int nrec = 0) + { + if (name.empty()) return globals().push_field("_G"); + + slot table = globals().push_field(name); + if (table.is_table()) return table; + + pop(); + push_table(narr, nrec); + globals().set_field(name); + + return globals().push_field(name); + } + slot push_table(int narr = 0, int nrec = 0) { lua_createtable(state_, narr, nrec); return top(); } + slot push_metatable(const std::string& type, bool& is_new) + { + is_new = luaL_newmetatable(state_, type.c_str()); + return top(); + } + slot push_metatable(const std::string& type) + { + luaL_newmetatable(state_, type.c_str()); + return top(); + } + + template + slot push_type() + { + return push_pointer(&typeid(T)); + } + /** * Call a function on the stack. The correct procedure is to push a @@ -936,7 +1159,6 @@ public: * will pop them off upon return, leaving up to nresults return values * (default is any number of return values, depending on the callee). */ - status call(int nargs = 0, int nresults = LUA_MULTRET) { return status(lua_pcall(state_, nargs, nresults, 0)); @@ -946,7 +1168,6 @@ public: /** * Pops n values from the top of the stack. */ - void pop(int n = 1) { lua_pop(state_, n); @@ -956,44 +1177,42 @@ public: /** * Index into the stack to get a slot. */ - slot operator [] (int index) const { return slot(*this, index); } - /** + /* * Control over the garbage collection process. */ - void collect_all() + void collect_garbage() { lua_gc(state_, LUA_GCCOLLECT, 0); } + void collect_garbage(int step) + { + lua_gc(state_, LUA_GCSTEP, step); + } - void stop_collector() + void disable_garbage_collector() { lua_gc(state_, LUA_GCSTOP, 0); } - - void restart_collector() + void enable_garbage_collector() { lua_gc(state_, LUA_GCRESTART, 0); } - int memory_used() const + float memory_used() const { // in kilobytes - return lua_gc(state_, LUA_GCCOUNT, 0); + return lua_gc(state_, LUA_GCCOUNT, 0) + + lua_gc(state_, LUA_GCCOUNTB, 0) / 1024.0f; } - void collect(int step) - { - lua_gc(state_, LUA_GCSTEP, step); - } - - void tune_collector(int pause, int step) + void tune_garbage_collector(int pause, int step = 200) { lua_gc(state_, LUA_GCSETPAUSE, pause); lua_gc(state_, LUA_GCSETSTEPMUL, step); @@ -1003,32 +1222,139 @@ public: private: script(lua_State* state) : - state_(lua_newthread(state)), - is_main_thread_(false) {} + state_(lua_newthread(state)) {} + + slot push(lua_CFunction function, int upvalues = 0) + { + lua_pushcclosure(state_, function, upvalues); + return top(); + } + + template + slot push_class_metatable() + { + bool is_new; + slot metatable = push_metatable(typeid(T).name(), is_new); + if (is_new) + { + metatable.push_copy(); // class behavior + metatable.set_field("__index"); + + push_type(); + metatable.set_field("__cxxtype"); // type_info + + push(object_finalizer_); + metatable.set_field("__gc"); // finalizer + + //push(object_tostring_); + //metatable.set_field("__tostring"); // tostring + } + return metatable; + } + + template + static int object_tostring_(lua_State* state) + { + std::ostringstream stream; + stream << *reinterpret_cast(lua_touserdata(state, 1)); + lua_pushlstring(state, stream.str().c_str(), stream.str().length()); + return 1; + } + + template + static int object_finalizer_(lua_State* state) + { + reinterpret_cast(lua_touserdata(state, 1))->~T(); + return 0; + } - static int dispatch_call(lua_State* state) + static int call_functor(lua_State* state) { - const function* function = (const script::function*)lua_touserdata(state, + function* function = (script::function*)lua_touserdata(state, lua_upvalueindex(1)); - lua_getfield(state, LUA_REGISTRYINDEX, "Script_hh_Object"); - script* script = (moof::script*)lua_touserdata(state, -1); - lua_pop(state, 1); + script* script = (moof::script*)lua_touserdata(state, + lua_upvalueindex(2)); - return (*function)(*script); + try + { + return (*function)(*script); + } + catch (const std::exception& e) + { + if (0 < std::strlen(e.what())) + { + luaL_where(state, 1); + lua_pushstring(state, e.what()); + lua_concat(state, 2); + } + return lua_error(state); + } + catch (const char* e) + { + luaL_where(state, 1); + lua_pushstring(state, e); + lua_concat(state, 2); + return lua_error(state); + } + catch (...) + { + return lua_error(state); + } + } + + + static int call_function(lua_State* state) + { + cfunction function = (cfunction)lua_touserdata(state, + lua_upvalueindex(1)); + + script* script = (moof::script*)lua_touserdata(state, + lua_upvalueindex(2)); + + try + { + return function(*script); + } + catch (const std::exception& e) + { + if (0 < std::strlen(e.what())) + { + luaL_where(state, 1); + lua_pushstring(state, e.what()); + lua_concat(state, 2); + } + return lua_error(state); + } + catch (const char* e) + { + luaL_where(state, 1); + lua_pushstring(state, e); + lua_concat(state, 2); + return lua_error(state); + } + catch (...) + { + return lua_error(state); + } } + void destroy() { - if (is_main_thread_) lua_close(state_); + if (is_main_thread()) lua_close(state_); } + lua_State* state_; - bool is_main_thread_; - std::list functions_; }; +using namespace std::rel_ops; + +/** + * Output a script value to a stream. + */ inline std::ostream& operator << (std::ostream& stream, const script::slot& slot) { diff --git a/src/moof/sound.cc b/src/moof/sound.cc index 0714698..2c19d26 100644 --- a/src/moof/sound.cc +++ b/src/moof/sound.cc @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -25,22 +24,24 @@ #include "hash.hh" #include "log.hh" -#include "manager.hh" #include "sound.hh" #include "resource.hh" #include "timer.hh" #ifndef BUF_SIZE -#define BUF_SIZE (4096) +#define BUF_SIZE (4096 * 64) #endif -#define NUM_BUFFERS (8) +#define NUM_BUFFERS (4) namespace moof { +/*] Sound backend + *************************************************************************/ + class sound_backend { public: @@ -104,27 +105,11 @@ ALCcontext* sound_backend::al_context; class sound_resource; typedef resource_handle sound_handle; - -class sound_resource_loader -{ -public: - - sound_resource_loader() - { - resource::register_type("ogg", "sounds"); - } - - ~sound_resource_loader() - { - resource::unregister_type("ogg"); - } -}; - -static sound_resource_loader loader; - +MOOF_REGISTER_RESOURCE(sound_resource, ogg, sounds); -// SOUND BUFFER +/*] Sound buffer + *************************************************************************/ class buffer { @@ -226,7 +211,8 @@ buffer::retcount_lookup buffer::retain_counts_; -// SOUND RESOURCE +/*] Sound resource + *************************************************************************/ class sound_resource : public boost::noncopyable { @@ -334,6 +320,8 @@ private: }; +/*] Sound class + *************************************************************************/ class sound::impl { @@ -419,7 +407,7 @@ public: if (!stream_timer_.is_valid()) { stream_timer_.init(boost::bind(&impl::stream_update, this, _1, _2), - 0.01, timer::repeat); + SCALAR(0.5), timer::repeat); } alSourcePlay(source_); @@ -603,12 +591,6 @@ void sound::enqueue(const std::string& path) void sound::play() -{ - // pass through - impl_->play(); -} - -void sound::stream() { // pass through impl_->stream(); @@ -637,7 +619,6 @@ void sound::toggle() { if (is_playing()) pause(); else play(); - // TODO: what about streaming sources? } bool sound::is_playing() const diff --git a/src/moof/sound.hh b/src/moof/sound.hh index e9d4bcf..f920f49 100644 --- a/src/moof/sound.hh +++ b/src/moof/sound.hh @@ -27,6 +27,9 @@ namespace moof { +class script; + + class sound { public: @@ -38,7 +41,6 @@ public: void enqueue(const std::string& name); void play(); - void stream(); void stop(); void pause(); void rewind(); @@ -58,6 +60,7 @@ public: static void listener_orientation(const vector3& forward, const vector3& up); + static void import(script& script, const std::string& nspace = ""); private: diff --git a/src/moof/sound_bindings.cc b/src/moof/sound_bindings.cc new file mode 100644 index 0000000..9e81aa3 --- /dev/null +++ b/src/moof/sound_bindings.cc @@ -0,0 +1,112 @@ + +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ + +#include "script.hh" +#include "sound.hh" + + +namespace moof { + + +static int sound_new(script& script) +{ + script::slot name = script[2].require_string("sound name"); + + std::string str; + name.get(str); + + script.push(sound(str)); + return 1; +} + +static int sound_enqueue(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + + std::string name; + script[2].require_string("sound name").get(name); + + sound->enqueue(name); + return 0; +} + +static int sound_play(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + sound->play(); + return 0; +} + +static int sound_stop(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + sound->stop(); + return 0; +} + +static int sound_pause(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + sound->pause(); + return 0; +} + +static int sound_rewind(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + sound->rewind(); + return 0; +} + +static int sound_toggle(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + sound->toggle(); + return 0; +} + +static int sound_is_playing(script& script) +{ + sound* sound; + script[1].require_object("sound").get(sound); + script.push(sound->is_playing()); + return 1; +} + + +void sound::import(script& script, const std::string& nspace) +{ + script.check_stack(4); + + script::slot parent = script.push_table(nspace); + script::slot meta = script.push_class(sound_new); + + meta.set_field("enqueue", sound_enqueue); + meta.set_field("play", sound_play); + meta.set_field("stop", sound_stop); + meta.set_field("pause", sound_pause); + meta.set_field("rewind", sound_rewind); + meta.set_field("toggle", sound_toggle); + meta.set_field("is_playing", sound_is_playing); + + parent.set_field("sound"); + parent.pop(); +} + + +} // namespace moof + diff --git a/src/moof/string.cc b/src/moof/string.cc index a2c27bb..61bbf8f 100644 --- a/src/moof/string.cc +++ b/src/moof/string.cc @@ -11,129 +11,308 @@ #include +#include + #include "ConvertUTF.h" +#include "script.hh" #include "string.hh" namespace moof { -// TODO this code is ugly - wstring multi_to_wide(const string& multi) { - size_t length = multi.length(); + typedef boost::shared_array buffer; if (sizeof(wchar_t) == 2) { - wchar_t* wide = new wchar_t[length + 1]; - - const UTF8* srcStart = reinterpret_cast(multi.c_str()); - const UTF8* srcEnd = srcStart + length; - UTF16* targetStart = reinterpret_cast(wide); - UTF16* targetEnd = targetStart + length+1; + size_t length = multi.length(); + buffer wide(new wchar_t[length + 1]); + const UTF8* src1 = (const UTF8*)multi.c_str(); + const UTF8* src2 = src1 + length; + UTF16* dst1 = (UTF16*)wide.get(); + UTF16* dst2 = dst1 + length+1; - ConversionResult res = ConvertUTF8toUTF16(&srcStart, srcEnd, - &targetStart, targetEnd, lenientConversion); - if (res != conversionOK) + if (ConvertUTF8toUTF16(&src1, src2, + &dst1, dst2, lenientConversion) != conversionOK) { - delete[] wide; - throw std::runtime_error("bad conversion from multi to wide characters"); + throw std::runtime_error("bad string conversion"); } - *targetStart = 0; - wstring convertedStr(wide); - delete[] wide; - - return convertedStr; + *dst1 = 0; + wstring str(wide.get()); + return str; } else if (sizeof(wchar_t) == 4) { - wchar_t* wide = new wchar_t[length]; - - const UTF8* srcStart = reinterpret_cast(multi.c_str()); - const UTF8* srcEnd = srcStart + length; - UTF32* targetStart = reinterpret_cast(wide); - UTF32* targetEnd = targetStart + length; + size_t length = multi.length(); + buffer wide(new wchar_t[length + 1]); + const UTF8* src1 = (const UTF8*)multi.c_str(); + const UTF8* src2 = src1 + length; + UTF32* dst1 = (UTF32*)wide.get(); + UTF32* dst2 = dst1 + length+1; - ConversionResult res = ConvertUTF8toUTF32(&srcStart, srcEnd, - &targetStart, targetEnd, lenientConversion); - if (res != conversionOK) + if (ConvertUTF8toUTF32(&src1, src2, + &dst1, dst2, lenientConversion) != conversionOK) { - delete[] wide; - throw std::runtime_error("bad conversion from multi to wide characters"); + throw std::runtime_error("bad string conversion"); } - *targetStart = 0; - wstring convertedStr(wide); - delete[] wide; - - return convertedStr; + *dst1 = 0; + wstring str(wide.get()); + return str; } else { throw std::runtime_error("unknown size of wide characters"); } - return L""; } string wide_to_multi(const wstring& wide) { - size_t length = wide.length(); + typedef boost::shared_array buffer; if (sizeof(wchar_t) == 2) { - size_t multiLength = 3 * length + 1; - char* multi = new char[multiLength]; - - const UTF16* srcStart = reinterpret_cast(wide.c_str()); - const UTF16* srcEnd = srcStart + length; - UTF8* targetStart = reinterpret_cast(multi); - UTF8* targetEnd = targetStart + multiLength; + size_t length = wide.length(); + size_t multi_length = 3 * length + 1; + buffer multi(new char[multi_length]); + const UTF16* src1 = (const UTF16*)wide.c_str(); + const UTF16* src2 = src1 + length; + UTF8* dst1 = (UTF8*)multi.get(); + UTF8* dst2 = dst1 + multi_length; - ConversionResult res = ConvertUTF16toUTF8(&srcStart, srcEnd, - &targetStart, targetEnd, lenientConversion); - if (res != conversionOK) + if (ConvertUTF16toUTF8(&src1, src2, + &dst1, dst2, lenientConversion) != conversionOK) { - delete[] multi; - throw std::runtime_error("bad conversion from wide to multi-characters"); + throw std::runtime_error("bad string conversion"); } - *targetStart = 0; - string convertedStr(multi); - delete[] multi; - - return convertedStr; + *dst1 = 0; + string str(multi.get()); + return str; } else if (sizeof(wchar_t) == 4) { - size_t multiLength = 4 * length + 1; - char* multi = new char[multiLength]; + size_t length = wide.length(); + size_t multi_length = 4 * length + 1; + buffer multi(new char[multi_length]); + const UTF32* src1 = (const UTF32*)wide.c_str(); + const UTF32* src2 = src1 + length; + UTF8* dst1 = (UTF8*)multi.get(); + UTF8* dst2 = dst1 + multi_length; - const UTF32* srcStart = reinterpret_cast(wide.c_str()); - const UTF32* srcEnd = srcStart + length; - UTF8* targetStart = reinterpret_cast(multi); - UTF8* targetEnd = targetStart + multiLength; - - ConversionResult res = ConvertUTF32toUTF8(&srcStart, srcEnd, - &targetStart, targetEnd, lenientConversion); - if (res != conversionOK) + if (ConvertUTF32toUTF8(&src1, src2, + &dst1, dst2, lenientConversion) != conversionOK) { - delete[] multi; - throw std::runtime_error("bad conversion from wide to multi-characters"); + throw std::runtime_error("bad string conversion"); } - *targetStart = 0; - string convertedStr(multi); - delete[] multi; - - return convertedStr; + *dst1 = 0; + string str(multi.get()); + return str; } else { throw std::runtime_error("unknown size of wide characters"); } - return ""; +} + + +static script& regex_script() +{ + static script script; + static bool init = true; + if (init) + { + script.import_string_library(); + script.globals().push_field("string").push_field("match"); + script.globals().set_field("match"); + script.top().push_field("gmatch"); + script.globals().set_field("gmatch"); + script.top().push_field("gsub"); + script.globals().set_field("gsub"); + script.push_nil(); + script.globals().set_field("string"); + script.pop(); + init = false; + } + return script; +} + + +regex::regex(const string& pattern) +{ + regex::pattern(pattern); +} + +regex::regex(const string& pattern, const string& source) +{ + regex::pattern(pattern); + match(source); +} + +regex::~regex() +{ + script& script = regex_script(); + + script.push_pointer(this); + script.push_nil(); + script.globals().set_field(); + script.push_pointer(this); + script.push_nil(); + script.registry().set_field(); +} + + +string regex::pattern() const +{ + script& script = regex_script(); + script.push_pointer(this); + script::slot saved = script.registry().push_field(); + + string pattern; + saved.get(pattern); + + saved.pop(); + return pattern; +} + +void regex::pattern(const string& pattern) +{ + script& script = regex_script(); + script.push_pointer(this); + script.push(pattern); + script.registry().set_field(); +} + + +void regex::match(const string& source) +{ + script& script = regex_script(); + script.push_pointer(this); + + script.globals().push_field("gmatch"); + script.push(source); + script.push_pointer(this); + script.registry().push_field(); + script.call(2, 1); + + script.globals().set_field(); +} + +bool regex::get(string& match) +{ + script& script = regex_script(); + script.push_pointer(this); + script::slot value = script.globals().push_field(); + if (!value.is_function()) + { + script.clear_stack(); + return false; + } + + script.call(0, 1); + bool result = value.get(match); + script.pop(); + return result; +} + +bool regex::get(std::vector& captures) +{ + script& script = regex_script(); + script.push_pointer(this); + script::slot value = script.globals().push_field(); + if (!value.is_function()) + { + script.clear_stack(); + return false; + } + + script.call(); + captures.clear(); + + while (value.is_string()) + { + captures.resize(captures.size() + 1); + value.get(captures.back()); + ++value.index; + } + + script.clear_stack(); + return 0 < captures.size(); +} + + +bool regex::match(string& match, + const string& pattern, + const string& source, + int position) +{ + script& script = regex_script(); + + script::slot value = script.globals().push_field("match"); + script.push(source); + script.push(pattern); + ++position; // Lua indices count from one. + script.push(position); + script.call(3, 1); + + bool result = value.get(match); + script.clear_stack(); + return result; +} + +bool regex::match(std::vector& captures, + const string& pattern, + const string& source, + int position) +{ + script& script = regex_script(); + + script::slot value = script.globals().push_field("match"); + script.push(source); + script.push(pattern); + ++position; // Lua indices count from one. + script.push(position); + script.call(3); + + captures.clear(); + + while (value.is_string()) + { + captures.resize(captures.size() + 1); + value.get(captures.back()); + ++value.index; + } + + script.clear_stack(); + return 0 < captures.size(); +} + + +int regex::sub(string& substitution, + const string& pattern, + const string& source, + const string& replacement) +{ + script& script = regex_script(); + + script::slot value = script.globals().push_field("gsub"); + script.push(source); + script.push(pattern); + script.push(replacement); + script.call(3, 2); + + value.get(substitution); + + ++value.index; + int count = 0; + value.get(count); + + script.clear_stack(); + return count; } diff --git a/src/moof/string.hh b/src/moof/string.hh index d666aa1..dd9d791 100644 --- a/src/moof/string.hh +++ b/src/moof/string.hh @@ -14,11 +14,13 @@ /** * \file string.hh - * Functions related to string manipulations. + * Functions and classes related to string manipulation. */ #include +#include + namespace moof { @@ -42,8 +44,152 @@ wstring multi_to_wide(const string& multi); string wide_to_multi(const wstring& wide); -} // namespace moof +/** + * Class exposing the pattern-matching and substitution methods used in + * Lua. + */ +class regex : public boost::noncopyable +{ +public: + + /** + * Construct a regex object. + */ + regex() {} + + /** + * Construct a regex object with a pattern. + * \param pattern The pattern. + */ + regex(const string& pattern); + + /** + * Construct a regex object with a pattern and source to match. + * \param pattern The pattern. + * \param source The source string. + */ + regex(const string& pattern, const string& source); + + /** + * Deconstruct the regex. + */ + ~regex(); + + + /** + * Get the regex pattern. + */ + string pattern() const; + + /** + * Set the regex pattern. + */ + void pattern(const string& pattern); + + + /** + * Match a string against the pattern iteratively. + * \param source The source string. + */ + void match(const string& source); + + /** + * Get the next match. If the pattern contains captures, this version + * will only get the first capture. + * \param match Reference to a string to be assigned the match. + * \return True if there was a match to get, false otherwise. + */ + bool get(string& match); + + /** + * Get the next match. Use this version if the pattern contains more + * than one capture to get all of the captures. + * \param captures Reference to a vector of strings to hold the result. + * \return True if there was a match to get, false otherwise. + */ + bool get(std::vector& captures); + + + /** + * Match a string against a pattern all at one time. + * \param pattern The pattern. + * \param source The source string. + * \param position The index of the first character of source to match. + * \return The match. + */ + static string match(const string& pattern, + const string& source, + int position = 0) + { + string match; + regex::match(match, pattern, source, position); + return match; + } + + /** + * Match a string against a pattern all at one time. + * \param match A reference to a string to be assigned the match. + * \param pattern The pattern. + * \param source The source string. + * \param position The index of the first character of source to match. + * \return True if a match was made, false otherwise. + */ + static bool match(string& match, + const string& pattern, + const string& source, + int position = 0); + + /** + * Match a string against a pattern all at one time. If the pattern + * contains captures, the resulting vector will contain all of the + * captures. + * \param captures A reference to a vector of strings to contain the + * result. + * \param pattern The pattern. + * \param source The source string. + * \param position The index of the first character of source to match. + * \return True if a match was made, false otherwise. + */ + static bool match(std::vector& captures, + const string& pattern, + const string& source, + int position = 0); + + + /** + * Substitute a string using a pattern and replacement string. + * \param pattern The pattern. + * \param source The source string. + * \param replacement The replacement string; may also contain + * references to captures. + * \return The string with any substitutions made. + */ + static string sub(const string& pattern, + const string& source, + const string& replacement) + { + string substitution; + regex::sub(substitution, pattern, source, replacement); + return substitution; + } + + /** + * Substitute a string using a pattern and replacement string. + * \param substitution A reference to a string to contain the result. + * \param pattern The pattern. + * \param source The source string. + * \param replacement The replacement string; may also contain + * references to captures. + * \return The number of substitutions made. + */ + static int sub(string& substitution, + const string& pattern, + const string& source, + const string& replacement); +}; + +} // namespace moof #endif // _MOOF_STRINGTOOLS_HH_ diff --git a/src/moof/timer.cc b/src/moof/timer.cc index 89f3e9d..74acc1c 100644 --- a/src/moof/timer.cc +++ b/src/moof/timer.cc @@ -139,11 +139,6 @@ bool timer::is_repeating() const } -void timer::fire_expired_timers() -{ - fire_expired_timers(ticks()); -} - void timer::fire_expired_timers(scalar t) { if (next_expiration_ > t) return; @@ -191,7 +186,7 @@ scalar timer::ticks() ASSERT(result == 0 && "cannot access clock"); return scalar(ts.tv_sec - reference_) + - scalar(ts.tv_nsec) / 1000000000.0; + scalar(ts.tv_nsec) * SCALAR(0.000000001); } void timer::sleep(scalar seconds, mode mode) @@ -201,7 +196,7 @@ void timer::sleep(scalar seconds, mode mode) if (mode == absolute) seconds -= ticks(); ts.tv_sec = time_t(seconds); - ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * 1000000000.0); + ts.tv_nsec = long((seconds - scalar(ts.tv_sec)) * SCALAR(1000000000.0)); do { @@ -221,13 +216,13 @@ void timer::sleep(scalar seconds, mode mode) scalar timer::ticks() { Uint32 ms = SDL_GetTicks(); - return scalar(ms / 1000) + scalar(ms % 1000) / 1000.0; + return scalar(ms / 1000) + scalar(ms % 1000) * SCALAR(0.001); } void timer::sleep(scalar seconds, mode mode) { if (mode == absolute) seconds -= ticks(); - SDL_Delay(Uint32(clamp(int(seconds * 1000.0), 0, 1000))); + SDL_Delay(Uint32(clamp(Uint32(seconds * SCALAR(1000.0)), 0, 1000))); } #endif // USE_CLOCK_GETTIME diff --git a/src/moof/timer.hh b/src/moof/timer.hh index a86f445..cb50c3b 100644 --- a/src/moof/timer.hh +++ b/src/moof/timer.hh @@ -201,7 +201,10 @@ public: * Fire any timers which are not yet invalidated but have an expiration * time in the past. */ - static void fire_expired_timers(); + static void fire_expired_timers() + { + fire_expired_timers(ticks()); + } /** * Fire any timers which are not yet invalidated but have an expiration