mesh and other random adjustments
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Tue, 27 Jul 2010 04:36:54 +0000 (22:36 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Tue, 27 Jul 2010 04:36:54 +0000 (22:36 -0600)
32 files changed:
arch/gentoo/yoink.ebuild
configure
data/models/classic.ac
data/models/classic.blend
data/scenes/Classic.lua
src/Animation.cc
src/Animation.hh
src/GameLayer.cc
src/GameLayer.hh
src/Main.cc
src/Main.hh
src/Scene.cc
src/Scene.hh
src/moof/entity.hh
src/moof/image.cc
src/moof/log.cc
src/moof/log.hh
src/moof/mesh.cc
src/moof/mesh.hh
src/moof/mesh_bindings.cc [new file with mode: 0644]
src/moof/modal_dialog.hh
src/moof/opengl.hh
src/moof/resource.cc
src/moof/resource.hh
src/moof/script.hh
src/moof/sound.cc
src/moof/sound.hh
src/moof/sound_bindings.cc [new file with mode: 0644]
src/moof/string.cc
src/moof/string.hh
src/moof/timer.cc
src/moof/timer.hh

index 16781c7a5343d1113e5205556514e1a01185956c..6e167d0bf3daa0424232b349e463145f3e0104e8 100644 (file)
@@ -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
index bea16f44f4ce2eb12e3ce0b0482f262bb05aac23..292639cb2a2cd8ed2bff026675125860a672e6cc 100755 (executable)
--- 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
 
 
 --
index ef7f6320a20ad50823ee3c0931accc1ce9088e22..7b1317686fdebaf32e39f8cd07c1c8da04f85cd1 100644 (file)
@@ -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
index 8ed07734cfc81af37262790133c07b0bbf6520a4..122fc036f6ec2b6f64d465cb23b6cd959cb4ca55 100644 (file)
Binary files a/data/models/classic.blend and b/data/models/classic.blend differ
index 2d00a67755fd2fd41d7ae2d57beba36e9a3465ac..8476279e0d3aefd94ae4e7746dcc541cf35173ce 100644 (file)
@@ -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)
index fead5cab1697f67682d5df9546f14f7308356779..a9710ce66b525e0536789394ca014b5323a89b2f 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <moof/manager.hh>
 #include <moof/log.hh>
+#include <moof/resource.hh>
 #include <moof/script.hh>
 
 #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);
index 3875b45f4819dccb880d4df763fbd676a8f4a708..97e916d8b5f3a77ae502cd50c878b79733020355 100644 (file)
@@ -22,7 +22,6 @@
 #include <boost/shared_ptr.hpp>
 
 #include <moof/math.hh>
-#include <moof/resource.hh>
 
 
 class Animation;
@@ -36,7 +35,7 @@ typedef boost::shared_ptr<Animation> AnimationP;
  * about anything to whatever drawing context is used to render the frame.
  */
 
-class Animation : public moof::resource
+class Animation
 {
 public:
 
index 5e95b7615393c57709b1cf3bb4d6b578f4d0ef80..8ff3a75a1cd5fecdb85144d2c7625ad5a7664731 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <moof/log.hh>
 #include <moof/math.hh>
+#include <moof/mesh.hh>
 #include <moof/opengl.hh>
 #include <moof/settings.hh>
 #include <moof/video.hh>
 
 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();
index 54b49962d0ab2a26a8ba4bb889ee9ee2564c5938..f3814430e72417f87cd007fe29f4ab23efec5656 100644 (file)
@@ -24,7 +24,6 @@
 #include <boost/shared_ptr.hpp>
 
 #include <moof/math.hh>
-#include <moof/mesh.hh>
 #include <moof/sound.hh>
 
 #include <moof/line.hh>                // 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;
index ae183ec49ab845ee9f5921f8b47642e6445526be..13681ee0625fa74d578fd1dcdb24f49db5e5129e 100644 (file)
 #include <iostream>
 #include <string>
 
+#if !defined(__WIN32)
+#include <termios.h>
+#else
+int isatty(int dummy) { return 0; }
+#endif
+
 #include <stlplus/portability/file_system.hpp>
 #include <stlplus/portability/subprocesses.hpp>
 
@@ -25,6 +31,7 @@
 #include <moof/opengl.hh>
 #include <moof/resource.hh>
 #include <moof/settings.hh>
+#include <moof/string.hh>
 #include <moof/video.hh>
 
 #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;
 }
 
index 0a3c616a685a4774a4cde93561ad0e4741a2b134..4532e41ea2e3b4a409513fea1b30df1d9ab76a64 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <moof/dispatcher.hh>
 #include <moof/math.hh>
+#include <moof/timer.hh>
 #include <moof/view.hh>
 
 
@@ -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_;
 };
 
 
index a1218f29b6f14eed579aa5bc0681f1fb35785705..af54c28768cfa92af735ccb9858d211f0a0789b2 100644 (file)
@@ -18,6 +18,7 @@
 #include <moof/log.hh>
 #include <moof/manager.hh>
 #include <moof/math.hh>
+#include <moof/resource.hh>
 #include <moof/script.hh>
 #include <moof/settings.hh>
 #include <moof/sprite.hh>
@@ -39,7 +40,7 @@ struct Scene::impl : public moof::manager<impl>
                };
 
                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<impl>
 
 
        moof::matrix4           mTransform;
-       std::string                     mTexture;
+       moof::image_handle      mTexture;
 
        std::list< boost::shared_ptr<impl::Quad> >      mObjects;
        std::list<moof::line2>                                          mLines;
@@ -191,8 +192,8 @@ struct Scene::impl : public moof::manager<impl>
 
        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<impl>
 
        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<impl>
 
        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<impl>
 
        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;
        }
 
index 3c14b47e81564ee89c76a29e5631ec7d86e35845..8c60cc50bb0f533b9e3fa1c83b24b0fbc153b30b 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <moof/cullable.hh>
 #include <moof/drawable.hh>
-#include <moof/resource.hh>
 #include <moof/script.hh>
 
 
@@ -33,7 +32,7 @@ class settings;
 class Scene;
 typedef boost::shared_ptr<Scene> 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> impl_;
index b503551b38f2422fa4b9f6597c79314f1d91a0c0..f95a94cc1fba513549ac4e56fd6ec0e8fa17dbb0 100644 (file)
@@ -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_;
 };
 
 
index 64b2f2eb1a6a19b5219669380e154ac9eef34508..7453b4849be2e9153fa3d1c2d428824e0f96ec19 100644 (file)
@@ -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<image>("png", "textures");
-       }
-
-       ~image_resource_loader()
-       {
-               resource::unregister_type("png");
-       }
-};
-
-static image_resource_loader loader;
-
-
 } // namespace moof
 
index 017ce36b2209fe087a79ea43010d9fc2f47f3986..f9a3ad97d3c397b4a21e33b4793ca8bcea021622 100644 (file)
 
 #include <fstream>
 
+#if !defined(__WIN32)
+#include <termios.h>
+#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)
index a32daadd8b13b79cc5d8c83dce762d802c67c856..e6e1a80c980400475e4476e271448f5bfdf75e00 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <cstdlib>             // exit
 #include <iostream>
+#include <string>
 
 
 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 <class A>
        void operator () (const A& a)
        {
-               *this << a << std::endl;
+               *this << a << endl;
        }
 
        template <class A, class B>
        void operator () (const A& a, const B& b)
        {
-               *this << a << " " << b << std::endl;
+               *this << a << " " << b << endl;
        }
 
        template <class A, class B, class C>
        void operator () (const A& a, const B& b, const C& c)
        {
-               *this << a << " " << b << " " << c << std::endl;
+               *this << a << " " << b << " " << c << endl;
        }
 
        template <class A, class B, class C, class D>
        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 <class A, class B, class C, class D, class E>
@@ -119,18 +127,19 @@ public:
                          << b << " "
                          << c << " "
                          << d << " "
-                         << e << std::endl;
+                         << e << endl;
        }
 
 
 private:
 
        template <class T> 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
 
index b41c377f29429514a1bcfffe48b91e16e877f3cc..023138b6df39fa8a79aa8f043b62bc5a5a58f5ea 100644 (file)
@@ -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 <int D>
-inline vector< scalar, fixed<D> > read_triplet(std::istream& stream)
+inline vector3 read_triplet(std::istream& stream)
 {
-       vector< scalar, fixed<D> > 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<object_ptr>::iterator meh;
+       for (meh = objects_.begin(); meh != objects_.end(); ++meh)
+       {
+               object_ptr cow = *meh;
+               log_info("OBJ: -", cow->name, cow->kids.size());
+
+               std::vector<object_ptr>::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<object_ptr>::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<vector3>::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<unsigned>::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<object_ptr>::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<object_ptr>::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<mesh>("ac", "models");
-       }
+       //mesh_resource_loader()
+       //{
+               //resource::register_type<mesh>("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
index cf267fba65d8a437a014301869e24dcf78245d44..0fbc3cc5b303a526f6aa99f0b19ec075fadeb6e8 100644 (file)
  */
 
 #include <iostream>
+#include <map>
+#include <vector>
 
 #include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
 
-#include <moof/drawable.hh>
+#include <moof/entity.hh>
 #include <moof/image.hh>
 #include <moof/math.hh>
 #include <moof/resource.hh>
 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<unsigned>   triangles;
                std::vector<vector2>    triangles_uv;
        };
@@ -73,20 +74,23 @@ public:
 
        class object;
        typedef boost::shared_ptr<object> object_ptr;
+       typedef boost::weak_ptr<object>   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<material_group>     faces;
 
                std::vector<object_ptr>         kids;
-               object_ptr                                      parent;
+               std::map<std::string,object_ptr>                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 (file)
index 0000000..02138ad
--- /dev/null
@@ -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_handle>("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_handle>("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_ptr>("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_ptr>("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_handle>(mesh_new);
+
+       meta.set_field("draw", mesh_draw);
+       meta.set_field("object", mesh_index);
+
+       script::slot object_meta = script.push_class<mesh::object_ptr>(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
+
index 23e929b4a3c6afc3cba59087a42af69783aa2040..e1d773989bebcf41c8912c0004b05221eeb686ac 100644 (file)
@@ -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);
index 347f3e5bd55da409c47e32a0115ec65d43ae0ae8..06ffbaa9866dec512ce397be6179ed867e0d06f5 100644 (file)
@@ -20,6 +20,8 @@
 
 #include "config.h"
 
+#include <vector>
+
 #include <SDL/SDL_opengl.h>
 
 #include <moof/math.hh>
@@ -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<moof::vector3>& v)
+{
+       glVertexPointer(3, GL_SCALAR, 0, v[0].data());
+}
+inline void glTexCoordPointer(const std::vector<moof::vector2>& v)
+{
+       glTexCoordPointer(2, GL_SCALAR, 0, v[0].data());
+}
+
+inline void glDrawElements(GLenum type, const std::vector<GLuint>& 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
index 57bd99b927df9fabfdee70f22faeae208c2d823b..3cf901b06473ae730fccd87d556a05d973460fa6 100644 (file)
 
 #include "config.h"
 
+#include <queue>
+
 #ifdef USE_HOTLOADING
 #include <sys/inotify.h>
 #include <sys/ioctl.h>
 #endif
 
-#include <queue>
-
 #include <boost/algorithm/string.hpp>
 #include <boost/weak_ptr.hpp>
 #include <stlplus/portability/file_system.hpp>
 namespace moof {
        
 
-bool resource::call_registry(const std::string& extension,
-                                                        loader_ptr& loader,
-                                                        registry_action action)
+/*] Filesystem searching
+ *************************************************************************/
+
+static std::vector<std::string> 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<std::string>::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<std::string,loader_ptr>::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> resource_weakptr;
-static hash<std::string,resource_weakptr,hash_function> resource_table_;
-
-static hash<std::string,std::string,hash_function> 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<int,std::string,hash_function> monitor_lookup_;
-static int monitor_fd_ = inotify_init1(IN_NONBLOCK);
-#endif
+/*] Resource loading
+ *************************************************************************/
 
-int resource::reload_as_needed()
+typedef boost::weak_ptr<resource> resource_weakptr;
+static struct rsrc_list
 {
-       int num_resources = 0;
+       // this table holds weak references to any and all loaded resources
+       hash<std::string,resource_weakptr,hash_function> 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<std::string,resource_weakptr,hash_function>::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<int,resource_weakptr,hash_function> table;
 
-                       log_error("2");
-                       hash<int,std::string,hash_function>::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<std::string,resource_weakptr,hash_function>::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<std::string,resource_weakptr,hash_function>::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<int,resource_weakptr,hash_function>::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<std::string> 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<std::string,loader_ptr> table;
 
-       log_info("find_file:", ext, prefix);
-
-       std::vector<std::string>::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<std::string,loader_ptr>::iterator it;
+                       it = table.find(ext);
+                       if (it != table.end()) loader = (*it).second;
+                       break;
+               }
        }
-       return find_file(name);
+
+       return loader;
 }
 
 
index 9d991053c21b841be3ebc164e6b538244c80bb82..094791c30f383b34538f6713227a190f69452ba3 100644 (file)
@@ -17,8 +17,6 @@
  * Interface for textures, sounds, and other types of resources.
  */
 
-#include "config.h"
-
 #include <map>
 #include <stdexcept>
 #include <string>
@@ -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 <class T>
-       explicit resource(T* ptr) :
-               resource_(ptr),
-               typeinfo_(const_cast<std::type_info*>(&typeid(T))),
-               unloader_(new specific_unloader<T>(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 <class T>
+       explicit resource(T* ptr) :
+               resource_(ptr),
+               typeinfo_(const_cast<std::type_info*>(&typeid(T))),
+               unloader_(new specific_unloader<T>(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<std::string,loader_ptr> type_lookup;
-       //typedef boost::shared_ptr<type_lookup> 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<TYPE>(#EXT, #PREFIX); } \
+               ~EXT() { moof::resource::unregister_type(#EXT); } \
+       }; \
+       static EXT EXT; \
+}
+
+
 } // namespace moof
 
 #endif // _MOOF_RESOURCE_HH_
index 85973dd0402f1823434ced4b2da57305b046146d..35e80d22eb6a8e57cec4d2b81fc148249888b863 100644 (file)
@@ -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
  * providing a cleaner, more consistent API.
  */
 
+#include <cstring>
 #include <iostream>
-#include <list>
 #include <map>
+#include <stdexcept>
 #include <string>
+#include <sstream>
+#include <utility>
 #include <vector>
 
 #include <boost/bind.hpp>
@@ -46,6 +49,7 @@ class script
 public:
 
        typedef boost::function<int(script&)> function;
+       typedef int (*cfunction)(script&);
 
        enum status
        {
@@ -65,6 +69,15 @@ public:
                globals_index           = LUA_GLOBALSINDEX
        };
 
+
+       template <class T>
+       static int object_finalizer(script& script)
+       {
+               reinterpret_cast<T*>(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<class script&>(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<class script*>(&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 <class T>
+               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 <class T>
                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 <class T>
+               bool get(T*& value) const
                {
                        if (is_data())
                        {
-                               value = lua_touserdata(script_.state_, index);
+                               value = reinterpret_cast<T*>(lua_touserdata(script_->state_, index));
                                return true;
                        }
                        return false;
                }
+               void* get_data() const
+               {
+                       return lua_touserdata(script_->state_, index);
+               }
 
                template <class T>
                bool get(std::vector<T>& 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 <class T, class V>
-               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 <class T, class V>
-               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 <class T>
-               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 <class T>
-               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 <class T>
                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 <class T>
                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 <class T>
-       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<script::function>(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 <class T>
+       slot push(const T& object)
+       {
+               void* storage;
+               slot copy = push_data(storage, sizeof(T));
+               new(storage) T(object);
+
+               push_class_metatable<T>();
+               copy.set_metatable();
+               return copy;
+       }
+
+       template <class T>
+       slot push_class(const function& ctor)
+       {
+               slot metatable = push_class_metatable<T>();
+
+               slot constructor = push_table();
+               push(ctor);
+               constructor.set_field("__call");
+               metatable.set_metatable();
+
+               return metatable;
+       }
+       template <class T>
+       slot push_class(cfunction ctor)
+       {
+               slot metatable = push_class_metatable<T>();
+
+               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 <class T>
+       slot push_pointer(const T* ptr)
+       {
+               lua_pushlightuserdata(state_, const_cast<void*>((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 <class T>
+       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 <class T>
+       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<T>();
+                       metatable.set_field("__cxxtype");       // type_info
+
+                       push(object_finalizer_<T>);
+                       metatable.set_field("__gc");            // finalizer
+
+                       //push(object_tostring_<T>);
+                       //metatable.set_field("__tostring");    // tostring
+               }
+               return metatable;
+       }
+
+       template <class T>
+       static int object_tostring_(lua_State* state)
+       {
+               std::ostringstream stream;
+               stream << *reinterpret_cast<T*>(lua_touserdata(state, 1));
+               lua_pushlstring(state, stream.str().c_str(), stream.str().length());
+               return 1;
+       }
+
+       template <class T>
+       static int object_finalizer_(lua_State* state)
+       {
+               reinterpret_cast<T*>(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<function>     functions_;
 };
 
+using namespace std::rel_ops;
+
 
+/**
+ * Output a script value to a stream.
+ */
 inline std::ostream& operator << (std::ostream& stream,
                                                                  const script::slot& slot)
 {
index 0714698673f02f8d7a757e0923ba39ca509f2191..2c19d265b721f0b9d0e01a94f0bd93007157f948 100644 (file)
@@ -13,7 +13,6 @@
 #include <deque>
 #include <list>
 #include <stdexcept>
-#include <string>
 
 #include <boost/algorithm/string.hpp>
 #include <boost/cstdint.hpp>
 
 #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_resource> sound_handle;
 
-
-class sound_resource_loader
-{
-public:
-       
-       sound_resource_loader()
-       {
-               resource::register_type<sound_resource>("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
index e9d4bcf4f12820a8bd09cceb3f62f9bbefd74d16..f920f49daf16804e735424fea855b4b207b38a03 100644 (file)
@@ -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 (file)
index 0000000..9e81aa3
--- /dev/null
@@ -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<moof::sound>("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<moof::sound>("sound").get(sound);
+       sound->play();
+       return 0;
+}
+
+static int sound_stop(script& script)
+{
+       sound* sound;
+       script[1].require_object<moof::sound>("sound").get(sound);
+       sound->stop();
+       return 0;
+}
+
+static int sound_pause(script& script)
+{
+       sound* sound;
+       script[1].require_object<moof::sound>("sound").get(sound);
+       sound->pause();
+       return 0;
+}
+
+static int sound_rewind(script& script)
+{
+       sound* sound;
+       script[1].require_object<moof::sound>("sound").get(sound);
+       sound->rewind();
+       return 0;
+}
+
+static int sound_toggle(script& script)
+{
+       sound* sound;
+       script[1].require_object<moof::sound>("sound").get(sound);
+       sound->toggle();
+       return 0;
+}
+
+static int sound_is_playing(script& script)
+{
+       sound* sound;
+       script[1].require_object<moof::sound>("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>(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
+
index a2c27bb25cf3b670d9b04c66c498c55e53530f9e..61bbf8fa6e77982a92b2c4fdf1542a24ab96a42b 100644 (file)
 
 #include <stdexcept>
 
+#include <boost/shared_array.hpp>
+
 #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<wchar_t> buffer;
 
        if (sizeof(wchar_t) == 2)
        {
-               wchar_t* wide = new wchar_t[length + 1];
-
-               const UTF8* srcStart = reinterpret_cast<const UTF8*>(multi.c_str());
-               const UTF8* srcEnd = srcStart + length;
-               UTF16* targetStart = reinterpret_cast<UTF16*>(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<const UTF8*>(multi.c_str());
-               const UTF8* srcEnd = srcStart + length;
-               UTF32* targetStart = reinterpret_cast<UTF32*>(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<char> buffer;
 
        if (sizeof(wchar_t) == 2)
        {
-               size_t multiLength = 3 * length + 1;
-               char* multi = new char[multiLength];
-
-               const UTF16* srcStart = reinterpret_cast<const UTF16*>(wide.c_str());
-               const UTF16* srcEnd = srcStart + length;
-               UTF8* targetStart = reinterpret_cast<UTF8*>(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<const UTF32*>(wide.c_str());
-               const UTF32* srcEnd = srcStart + length;
-               UTF8* targetStart = reinterpret_cast<UTF8*>(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<string>& 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<string>& 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;
 }
 
 
index d666aa1eba748037ddb79100d384c7d375dfb877..dd9d7918deb13ef9e27feab36423a66154db410d 100644 (file)
 
 /**
  * \file string.hh
- * Functions related to string manipulations.
+ * Functions and classes related to string manipulation.
  */
 
 #include <string>
 
+#include <boost/noncopyable.hpp>
+
 
 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<string>& 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<string>& 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_
 
index 89f3e9da825676ef16e8ad94086e52f91615af74..74acc1c203a9bc45b7cb894835e55b9e760162fc 100644 (file)
@@ -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
index a86f445d4168a9e2b19073a88593cc4790d9e9a0..cb50c3bbc0f6d40a1328d584b93655abf945d2fa 100644 (file)
@@ -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
This page took 0.239023 seconds and 4 git commands to generate.