]> git.xonotic.org Git - xonotic/netradiant.git/commitdiff
Merge commit 'c5a6237a2b002c9811719172931b0c9cc5a725f4' into master-merge
authorThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 02:04:02 +0000 (04:04 +0200)
committerThomas Debesse <dev@illwieckz.net>
Tue, 21 Jun 2022 02:04:02 +0000 (04:04 +0200)
498 files changed:
.appveyor.yml [new file with mode: 0644]
.gitmodules
.patchsets [deleted file]
CMakeLists.txt
COMPILING [deleted file]
CONTRIBUTORS [deleted file]
ChangeLog [deleted file]
ChangeLog.idsoftware [deleted file]
DoxyConfig [deleted file]
Doxyfile [deleted file]
Makefile
README.md
appveyor.yml [deleted file]
branch-manager [deleted file]
bundle/CMakeLists.txt [new file with mode: 0644]
cmake/FindGLIB.cmake
cmake/FindGtkGLExt.cmake
conftest.cpp
contrib/CMakeLists.txt
contrib/bkgrnd2d/plugin.cpp
contrib/bobtoolz/bobToolz-GTK.cpp
contrib/bobtoolz/ctfToolz-GTK.cpp
contrib/bobtoolz/dialogs/dialogs-gtk.cpp
contrib/bobtoolz/dialogs/dialogs-gtk.h
contrib/bobtoolz/funchandlers-GTK.cpp
contrib/bobtoolz/funchandlers.h
contrib/bobtoolz/misc.cpp
contrib/brushexport/export.cpp
contrib/brushexport/interface.cpp
contrib/brushexport/plugin.cpp
contrib/brushexport/plugin.h
contrib/camera/camera.cpp
contrib/camera/camera.h
contrib/camera/funchandlers.cpp
contrib/gtkgensurf/gensurf.h
contrib/gtkgensurf/plugin.cpp
contrib/hydratoolz/plugin.cpp
contrib/prtview/AboutDialog.cpp [deleted file]
contrib/prtview/AboutDialog.h [deleted file]
contrib/prtview/CMakeLists.txt
contrib/prtview/ConfigDialog.cpp
contrib/prtview/ConfigDialog.h
contrib/prtview/prtview.cpp
contrib/prtview/prtview.h
contrib/shaderplug/shaderplug.cpp
contrib/shaderplug/shaderplug.h
contrib/sunplug/sunplug.cpp
contrib/sunplug/sunplug.h
contrib/ufoaiplug/ufoai.cpp
contrib/ufoaiplug/ufoai.h
cross-Makefile.conf [deleted file]
docs/index.html
easy-builder [new file with mode: 0755]
flake.nix [new file with mode: 0644]
gamepack-manager
generic_cpp.py [deleted file]
generic_h.py [deleted file]
generic_module.py [deleted file]
icons/h2data.ico
icons/h2data.xcf [new file with mode: 0644]
icons/netradiant.desktop [new file with mode: 0755]
icons/netradiant.ico [new file with mode: 0644]
icons/netradiant.png [new file with mode: 0644]
icons/q2map.ico
icons/q3data.ico
icons/q3data.xcf [new file with mode: 0644]
icons/q3map2.ico
icons/radiant-src.png [deleted file]
icons/radiant.ico [deleted file]
icons/x-netradiant-map.xml [new file with mode: 0644]
include/CMakeLists.txt
include/igtkgl.h [deleted file]
include/ishaders.h
include/lib.rc [new file with mode: 0644]
include/qerplugin.h
include/version.h [deleted file]
install-dlls-fedora.sh [deleted file]
install-dlls.sh [deleted file]
install-dylibs.sh [deleted file]
library-bundler [new file with mode: 0755]
libs/CMakeLists.txt
libs/cmdlib.h
libs/cmdlib/CMakeLists.txt
libs/cmdlib/cmdlib.cpp
libs/container/CMakeLists.txt
libs/container/hashfunc.h
libs/crnrgba/CMakeLists.txt
libs/crnrgba/crn_rgba.cpp
libs/crunch
libs/ddslib.h
libs/ddslib/CMakeLists.txt
libs/debugging/CMakeLists.txt
libs/eclasslib.h
libs/entitylib.h
libs/etclib/CMakeLists.txt
libs/filematch/CMakeLists.txt
libs/fs_path.h
libs/generic/CMakeLists.txt
libs/generic/callback.h
libs/globaldefs.h
libs/gtkutil/CMakeLists.txt
libs/gtkutil/cursor.cpp
libs/gtkutil/cursor.h
libs/gtkutil/dialog.cpp
libs/gtkutil/filechooser.cpp
libs/gtkutil/glwidget.cpp
libs/gtkutil/glwidget.h
libs/gtkutil/messagebox.cpp
libs/gtkutil/messagebox.h
libs/gtkutil/paned.cpp
libs/gtkutil/paned.h
libs/gtkutil/window.cpp
libs/gtkutil/xorrectangle.cpp
libs/l_net/CMakeLists.txt
libs/math/CMakeLists.txt
libs/math/vector.h
libs/mathlib/CMakeLists.txt
libs/mathlib/bbox.c
libs/memory/CMakeLists.txt
libs/modulesystem/CMakeLists.txt
libs/os/CMakeLists.txt
libs/os/path.h
libs/picomodel.h
libs/picomodel/CMakeLists.txt
libs/picomodel/lwo/lwio.c
libs/picomodel/picointernal.c
libs/picomodel/picointernal.h
libs/picomodel/picomodel.c
libs/picomodel/picomodules.c
libs/picomodel/pm_3ds.c
libs/picomodel/pm_ase.c
libs/picomodel/pm_fm.c
libs/picomodel/pm_fm.h
libs/picomodel/pm_iqm.c [new file with mode: 0644]
libs/picomodel/pm_lwo.c
libs/picomodel/pm_md2.c
libs/picomodel/pm_md3.c
libs/picomodel/pm_mdc.c
libs/picomodel/pm_ms3d.c
libs/picomodel/pm_obj.c
libs/picomodel/pm_terrain.c
libs/profile/CMakeLists.txt
libs/property.h
libs/script/CMakeLists.txt
libs/signal/CMakeLists.txt
libs/splines/CMakeLists.txt
libs/splines/math_angles.h
libs/splines/math_quaternion.h
libs/splines/math_vector.h
libs/stream/CMakeLists.txt
libs/string/CMakeLists.txt
libs/string/string.h
libs/transformpath/CMakeLists.txt [new file with mode: 0644]
libs/transformpath/transformpath.cpp [new file with mode: 0644]
libs/transformpath/transformpath.h [new file with mode: 0644]
libs/uilib/CMakeLists.txt
libs/uilib/uilib.cpp
libs/uilib/uilib.h
libs/xml/CMakeLists.txt
libs/xml/xmltextags.cpp
merge-from-zerowing.sh [deleted file]
mingw-Makefile.conf [deleted file]
mingw-Makefile.inc [deleted file]
mingw-fedora-Makefile.conf [deleted file]
mingw-radiantdeps-Makefile.inc [deleted file]
oldstuff/.patchsets [new file with mode: 0644]
oldstuff/COMPILING [new file with mode: 0644]
oldstuff/CONTRIBUTORS [new file with mode: 0644]
oldstuff/ChangeLog [new file with mode: 0644]
oldstuff/ChangeLog.idsoftware [new file with mode: 0644]
oldstuff/DoxyConfig [new file with mode: 0644]
oldstuff/Doxyfile [new file with mode: 0644]
oldstuff/branch-manager [new file with mode: 0755]
oldstuff/cross-Makefile.conf [new file with mode: 0644]
oldstuff/generic_cpp.py [new file with mode: 0644]
oldstuff/generic_h.py [new file with mode: 0644]
oldstuff/generic_module.py [new file with mode: 0644]
oldstuff/install-dlls-fedora.sh [new file with mode: 0755]
oldstuff/install-dlls.sh [new file with mode: 0755]
oldstuff/install-dylibs.sh [new file with mode: 0755]
oldstuff/merge-from-zerowing.sh [new file with mode: 0755]
oldstuff/mingw-Makefile.conf [new file with mode: 0644]
oldstuff/mingw-Makefile.inc [new file with mode: 0644]
oldstuff/mingw-fedora-Makefile.conf [new file with mode: 0644]
oldstuff/mingw-radiantdeps-Makefile.inc [new file with mode: 0644]
oldstuff/uncrustify.cfg [new file with mode: 0644]
plugins/CMakeLists.txt
plugins/archivezip/CMakeLists.txt
plugins/archivezip/archive.cpp
plugins/entity/rotation.h
plugins/imagepng/plugin.cpp
plugins/iqmmodel/CMakeLists.txt [deleted file]
plugins/iqmmodel/iqm.cpp [deleted file]
plugins/iqmmodel/iqm.h [deleted file]
plugins/iqmmodel/modeliqm.def [deleted file]
plugins/iqmmodel/plugin.cpp [deleted file]
plugins/iqmmodel/plugin.h [deleted file]
plugins/md3model/md2.cpp
plugins/shaders/shaders.cpp
plugins/spritemodel/plugin.cpp
plugins/textool/StdAfx.h
plugins/textool/TexTool.cpp
plugins/vfspk3/vfs.cpp
radiant/CMakeLists.txt
radiant/brush.h
radiant/brushmanip.cpp
radiant/brushmodule.cpp
radiant/brushmodule.h
radiant/brushtokens.h
radiant/brushxml.h
radiant/build.cpp
radiant/camwindow.cpp
radiant/camwindow.h
radiant/console.cpp
radiant/console.h
radiant/csg.cpp
radiant/dialog.cpp
radiant/dialog.h
radiant/eclass_def.cpp
radiant/environment.cpp
radiant/environment.h
radiant/error.cpp
radiant/glwidget.cpp [deleted file]
radiant/glwidget.h [deleted file]
radiant/groupdialog.cpp
radiant/gtkdlgs.cpp
radiant/help.cpp
radiant/image.cpp
radiant/main.cpp
radiant/mainframe.cpp
radiant/mainframe.h
radiant/map.cpp
radiant/mru.cpp
radiant/multimon.cpp
radiant/plugin.cpp
radiant/plugintoolbar.cpp
radiant/preferences.cpp
radiant/preferences.h
radiant/qe3.cpp
radiant/radiant.ico [deleted file]
radiant/radiant.rc
radiant/radiant_old.ico [deleted file]
radiant/referencecache.cpp
radiant/renderstate.cpp
radiant/scenegraph.h
radiant/server.cpp
radiant/surfacedialog.cpp
radiant/textures.cpp
radiant/texwindow.cpp
radiant/texwindow.h
radiant/treemodel.cpp
radiant/watchbsp.cpp
radiant/xywindow.cpp
radiant/xywindow.h
setup/apple/.gitignore [deleted file]
setup/apple/Makefile [deleted file]
setup/apple/NetRadiant.app/Contents/Info.plist [deleted file]
setup/apple/NetRadiant.app/Contents/MacOS/radiant [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/etc/fonts/fonts.conf [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/etc/gtk-2.0/gtkrc [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/etc/pango/pangorc [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/lib/.turd [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/radiant.icns [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/icons/.turd [deleted file]
setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/themes/.turd [deleted file]
setup/apple/README.md [deleted file]
setup/data/tools/bitmaps/window5.png [new file with mode: 0644]
setup/data/tools/global.xlink
setup/macos/Contents/Info.plist [new file with mode: 0644]
setup/macos/Contents/Resources/netradiant.icns [new file with mode: 0644]
setup/macos/NetRadiant [new file with mode: 0755]
tools/CMakeLists.txt
tools/heretic2/CMakeLists.txt [new file with mode: 0644]
tools/heretic2/common/bspfile.c [new file with mode: 0644]
tools/heretic2/common/bspfile.h [new file with mode: 0644]
tools/heretic2/common/cmdlib.c [new file with mode: 0644]
tools/heretic2/common/cmdlib.h [new file with mode: 0644]
tools/heretic2/common/her2_threads.h [new file with mode: 0644]
tools/heretic2/common/inout.c [new file with mode: 0644]
tools/heretic2/common/inout.h [new file with mode: 0644]
tools/heretic2/common/l3dslib.c [new file with mode: 0644]
tools/heretic2/common/l3dslib.h [new file with mode: 0644]
tools/heretic2/common/lbmlib.c [new file with mode: 0644]
tools/heretic2/common/lbmlib.h [new file with mode: 0644]
tools/heretic2/common/mathlib.c [new file with mode: 0644]
tools/heretic2/common/mathlib.h [new file with mode: 0644]
tools/heretic2/common/md4.c [new file with mode: 0644]
tools/heretic2/common/md4.h [new file with mode: 0644]
tools/heretic2/common/path_init.c [new file with mode: 0644]
tools/heretic2/common/polylib.c [new file with mode: 0644]
tools/heretic2/common/polylib.h [new file with mode: 0644]
tools/heretic2/common/qfiles.c [new file with mode: 0644]
tools/heretic2/common/qfiles.h [new file with mode: 0644]
tools/heretic2/common/scriplib.c [new file with mode: 0644]
tools/heretic2/common/scriplib.h [new file with mode: 0644]
tools/heretic2/common/threads.c [new file with mode: 0644]
tools/heretic2/common/token.c [new file with mode: 0644]
tools/heretic2/common/token.h [new file with mode: 0644]
tools/heretic2/common/trilib.c [new file with mode: 0644]
tools/heretic2/common/trilib.h [new file with mode: 0644]
tools/heretic2/h2data/adpcm.h [new file with mode: 0644]
tools/heretic2/h2data/animcomp.c [new file with mode: 0644]
tools/heretic2/h2data/animcomp.h [new file with mode: 0644]
tools/heretic2/h2data/anorms.h [new file with mode: 0644]
tools/heretic2/h2data/book.c [new file with mode: 0644]
tools/heretic2/h2data/fmodels.c [new file with mode: 0644]
tools/heretic2/h2data/h2data.rc [new file with mode: 0644]
tools/heretic2/h2data/images.c [new file with mode: 0644]
tools/heretic2/h2data/jointed.c [new file with mode: 0644]
tools/heretic2/h2data/jointed.h [new file with mode: 0644]
tools/heretic2/h2data/joints.h [new file with mode: 0644]
tools/heretic2/h2data/models.c [new file with mode: 0644]
tools/heretic2/h2data/pics.c [new file with mode: 0644]
tools/heretic2/h2data/qd_fmodel.h [new file with mode: 0644]
tools/heretic2/h2data/qd_skeletons.c [new file with mode: 0644]
tools/heretic2/h2data/qd_skeletons.h [new file with mode: 0644]
tools/heretic2/h2data/qdata.c [new file with mode: 0644]
tools/heretic2/h2data/qdata.h [new file with mode: 0644]
tools/heretic2/h2data/resource.h [new file with mode: 0644]
tools/heretic2/h2data/sprites.c [new file with mode: 0644]
tools/heretic2/h2data/svdcmp.c [new file with mode: 0644]
tools/heretic2/h2data/tables.c [new file with mode: 0644]
tools/heretic2/h2data/tmix.c [new file with mode: 0644]
tools/heretic2/h2data/video.c [new file with mode: 0644]
tools/heretic2/qcommon/angles.h [new file with mode: 0644]
tools/heretic2/qcommon/arrayedlist.h [new file with mode: 0644]
tools/heretic2/qcommon/flex.h [new file with mode: 0644]
tools/heretic2/qcommon/fmodel.h [new file with mode: 0644]
tools/heretic2/qcommon/h2common.h [new file with mode: 0644]
tools/heretic2/qcommon/placement.h [new file with mode: 0644]
tools/heretic2/qcommon/q_typedef.h [new file with mode: 0644]
tools/heretic2/qcommon/qfiles.h [new file with mode: 0644]
tools/heretic2/qcommon/reference.c [new file with mode: 0644]
tools/heretic2/qcommon/reference.h [new file with mode: 0644]
tools/heretic2/qcommon/resourcemanager.c [new file with mode: 0644]
tools/heretic2/qcommon/resourcemanager.h [new file with mode: 0644]
tools/heretic2/qcommon/skeletons.c [new file with mode: 0644]
tools/heretic2/qcommon/skeletons.h [new file with mode: 0644]
tools/quake2/CMakeLists.txt [new file with mode: 0644]
tools/quake2/common/cmdlib.c
tools/quake2/common/cmdlib.h
tools/quake2/common/path_init.c
tools/quake2/common/threads.c
tools/quake2/extra/common/cmdlib.c
tools/quake2/extra/common/cmdlib.h
tools/quake2/q2map/main.c
tools/quake2/q2map/q2map.h
tools/quake2/q2map/q2map.rc [new file with mode: 0644]
tools/quake2/q2map/qbsp.c
tools/quake2/q2map/qrad.c
tools/quake2/q2map/qrad.h
tools/quake2/qdata/qdata.rc [new file with mode: 0644]
tools/quake2/qdata_heretic2/adpcm.h [deleted file]
tools/quake2/qdata_heretic2/animcomp.c [deleted file]
tools/quake2/qdata_heretic2/animcomp.h [deleted file]
tools/quake2/qdata_heretic2/anorms.h [deleted file]
tools/quake2/qdata_heretic2/book.c [deleted file]
tools/quake2/qdata_heretic2/common/bspfile.c [deleted file]
tools/quake2/qdata_heretic2/common/bspfile.h [deleted file]
tools/quake2/qdata_heretic2/common/cmdlib.c [deleted file]
tools/quake2/qdata_heretic2/common/cmdlib.h [deleted file]
tools/quake2/qdata_heretic2/common/her2_threads.h [deleted file]
tools/quake2/qdata_heretic2/common/inout.c [deleted file]
tools/quake2/qdata_heretic2/common/inout.h [deleted file]
tools/quake2/qdata_heretic2/common/l3dslib.c [deleted file]
tools/quake2/qdata_heretic2/common/l3dslib.h [deleted file]
tools/quake2/qdata_heretic2/common/lbmlib.c [deleted file]
tools/quake2/qdata_heretic2/common/lbmlib.h [deleted file]
tools/quake2/qdata_heretic2/common/mathlib.c [deleted file]
tools/quake2/qdata_heretic2/common/mathlib.h [deleted file]
tools/quake2/qdata_heretic2/common/md4.c [deleted file]
tools/quake2/qdata_heretic2/common/md4.h [deleted file]
tools/quake2/qdata_heretic2/common/path_init.c [deleted file]
tools/quake2/qdata_heretic2/common/polylib.c [deleted file]
tools/quake2/qdata_heretic2/common/polylib.h [deleted file]
tools/quake2/qdata_heretic2/common/qfiles.c [deleted file]
tools/quake2/qdata_heretic2/common/qfiles.h [deleted file]
tools/quake2/qdata_heretic2/common/scriplib.c [deleted file]
tools/quake2/qdata_heretic2/common/scriplib.h [deleted file]
tools/quake2/qdata_heretic2/common/threads.c [deleted file]
tools/quake2/qdata_heretic2/common/token.c [deleted file]
tools/quake2/qdata_heretic2/common/token.h [deleted file]
tools/quake2/qdata_heretic2/common/trilib.c [deleted file]
tools/quake2/qdata_heretic2/common/trilib.h [deleted file]
tools/quake2/qdata_heretic2/fmodels.c [deleted file]
tools/quake2/qdata_heretic2/icon1.ico [deleted file]
tools/quake2/qdata_heretic2/images.c [deleted file]
tools/quake2/qdata_heretic2/jointed.c [deleted file]
tools/quake2/qdata_heretic2/jointed.h [deleted file]
tools/quake2/qdata_heretic2/joints.h [deleted file]
tools/quake2/qdata_heretic2/models.c [deleted file]
tools/quake2/qdata_heretic2/pics.c [deleted file]
tools/quake2/qdata_heretic2/qcommon/angles.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/arrayedlist.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/flex.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/fmodel.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/h2common.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/placement.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/q_typedef.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/qfiles.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/reference.c [deleted file]
tools/quake2/qdata_heretic2/qcommon/reference.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/resourcemanager.c [deleted file]
tools/quake2/qdata_heretic2/qcommon/resourcemanager.h [deleted file]
tools/quake2/qdata_heretic2/qcommon/skeletons.c [deleted file]
tools/quake2/qdata_heretic2/qcommon/skeletons.h [deleted file]
tools/quake2/qdata_heretic2/qd_fmodel.h [deleted file]
tools/quake2/qdata_heretic2/qd_skeletons.c [deleted file]
tools/quake2/qdata_heretic2/qd_skeletons.h [deleted file]
tools/quake2/qdata_heretic2/qdata.c [deleted file]
tools/quake2/qdata_heretic2/qdata.h [deleted file]
tools/quake2/qdata_heretic2/resource.h [deleted file]
tools/quake2/qdata_heretic2/script1.aps [deleted file]
tools/quake2/qdata_heretic2/script1.rc [deleted file]
tools/quake2/qdata_heretic2/sprites.c [deleted file]
tools/quake2/qdata_heretic2/svdcmp.c [deleted file]
tools/quake2/qdata_heretic2/tables.c [deleted file]
tools/quake2/qdata_heretic2/tmix.c [deleted file]
tools/quake2/qdata_heretic2/video.c [deleted file]
tools/quake3/CMakeLists.txt
tools/quake3/common/aselib.c
tools/quake3/common/bspfile.c
tools/quake3/common/cmdlib.c
tools/quake3/common/cmdlib.h
tools/quake3/common/imagelib.c
tools/quake3/common/polylib.c
tools/quake3/common/scriplib.c
tools/quake3/common/threads.c
tools/quake3/common/trilib.c
tools/quake3/common/vfs.c
tools/quake3/common/vfs.h
tools/quake3/q3data/md3lib.c
tools/quake3/q3data/p3dlib.c
tools/quake3/q3data/q3data.c
tools/quake3/q3data/q3data.rc [new file with mode: 0644]
tools/quake3/q3map2/brush.c
tools/quake3/q3map2/bsp.c
tools/quake3/q3map2/bsp_analyze.c
tools/quake3/q3map2/bspfile_abstract.c
tools/quake3/q3map2/bspfile_ibsp.c
tools/quake3/q3map2/bspfile_rbsp.c
tools/quake3/q3map2/convert_bsp.c
tools/quake3/q3map2/decals.c
tools/quake3/q3map2/exportents.c
tools/quake3/q3map2/facebsp.c
tools/quake3/q3map2/game__null.h
tools/quake3/q3map2/game_darkplaces.h
tools/quake3/q3map2/game_dq.h
tools/quake3/q3map2/game_ef.h
tools/quake3/q3map2/game_etut.h
tools/quake3/q3map2/game_ja.h
tools/quake3/q3map2/game_jk2.h
tools/quake3/q3map2/game_nexuiz.h
tools/quake3/q3map2/game_oa.h [new file with mode: 0644]
tools/quake3/q3map2/game_prophecy.h
tools/quake3/q3map2/game_q3rally.h [new file with mode: 0644]
tools/quake3/q3map2/game_qfusion.h
tools/quake3/q3map2/game_quake3.h
tools/quake3/q3map2/game_quakelive.h
tools/quake3/q3map2/game_reaction.h
tools/quake3/q3map2/game_smokinguns.h [new file with mode: 0644]
tools/quake3/q3map2/game_sof2.h
tools/quake3/q3map2/game_tenebrae.h
tools/quake3/q3map2/game_tremulous.h
tools/quake3/q3map2/game_unvanquished.h
tools/quake3/q3map2/game_warfork.h [new file with mode: 0644]
tools/quake3/q3map2/game_warsow.h [new file with mode: 0644]
tools/quake3/q3map2/game_wolf.h
tools/quake3/q3map2/game_wolfet.h
tools/quake3/q3map2/game_wop.h [new file with mode: 0644]
tools/quake3/q3map2/game_xonotic.h
tools/quake3/q3map2/help.c
tools/quake3/q3map2/image.c
tools/quake3/q3map2/light.c
tools/quake3/q3map2/light_bounce.c
tools/quake3/q3map2/light_ydnar.c
tools/quake3/q3map2/lightmaps_ydnar.c
tools/quake3/q3map2/main.c
tools/quake3/q3map2/map.c
tools/quake3/q3map2/mesh.c
tools/quake3/q3map2/minimap.c
tools/quake3/q3map2/model.c
tools/quake3/q3map2/patch.c
tools/quake3/q3map2/path_init.c
tools/quake3/q3map2/portals.c
tools/quake3/q3map2/q3map2.h
tools/quake3/q3map2/q3map2.rc
tools/quake3/q3map2/shaders.c
tools/quake3/q3map2/surface.c
tools/quake3/q3map2/surface_foliage.c
tools/quake3/q3map2/surface_meta.c
tools/quake3/q3map2/tjunction.c
tools/quake3/q3map2/vis.c
tools/quake3/q3map2/visflow.c
tools/quake3/q3map2/writebsp.c
tools/unvanquished/CMakeLists.txt [new file with mode: 0644]
tools/unvanquished/daemonmap [new submodule]
uncrustify.cfg [deleted file]

diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644 (file)
index 0000000..d98cc73
--- /dev/null
@@ -0,0 +1,27 @@
+platform: x64
+
+shallow_clone: true
+
+install:
+  - set "PATH=C:\msys64\usr\bin;%PATH%"
+  - bash -lc "pacman --noconfirm --needed -Sy bash pacman pacman-mirrors msys2-runtime msys2-runtime-devel"
+  - ps: >-
+      bash -lc @"
+        exec 0</dev/null 2>&1
+        pacman --noconfirm -Su
+        pacman --noconfirm --needed -S base-devel mingw-w64-x86_64-{toolchain,clang,cmake,gtk2,gtkglext}
+      "@
+
+build_script:
+  - set HOME=.
+  - set MSYSTEM=MINGW64
+  - ps: >-
+      bash -lc @"
+        set -e
+        exec 0</dev/null 2>&1
+        # export CC=clang
+        # export CXX=clang++
+        cmake --version
+        cmake -H. -Bbuild -G 'MSYS Makefiles' -DGTK2_GLIBCONFIG_INCLUDE_DIR=/mingw64/lib/glib-2.0/include -DGTK2_GDKCONFIG_INCLUDE_DIR=/mingw64/lib/gtk-2.0/include
+        cmake --build build
+      "@
index d20f6e35835027edcedd18a4d484cbf4841ded21..f8d6fc747fcc64e60bffbafa291bcd25918c2920 100644 (file)
@@ -1,3 +1,6 @@
 [submodule "libs/crunch"]
        path = libs/crunch
        url = https://github.com/DaemonEngine/crunch.git
+[submodule "tools/unvanquished/daemonmap"]
+       path = tools/unvanquished/daemonmap
+       url = https://github.com/DaemonEngine/daemonmap.git
diff --git a/.patchsets b/.patchsets
deleted file mode 100644 (file)
index cebd1b5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-master = https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/1.5
-revisions_applied = 1-327
-
index e920fd6216c4e3522bedc5814d6d51c012e91015..c2d795c846fde527ec8b323aef6d935047668b02 100644 (file)
-cmake_minimum_required(VERSION 2.8.12 FATAL_ERROR)
-list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
+cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
+
 project(NetRadiant C CXX)
 
+#-----------------------------------------------------------------------
+# Builtins: configuration
+#-----------------------------------------------------------------------
+
+set(BUILTINS_INSTALL_DIR "${CMAKE_BINARY_DIR}/builtins")
+set(BUILTINS_INCLUDE_DIR "${BUILTINS_INSTALL_DIR}/include")
+set(BUILTINS_LIB_DIR "${BUILTINS_INSTALL_DIR}/lib")
+set(BUILTINS_PKGCONFIG_DIR "${BUILTINS_INSTALL_DIR}/lib/pkgconfig")
+
+option(BUILTIN_GTKGLEXT "Builtin GtkGLExt" OFF)
+option(BUILTIN_GTKTHEME_MOJAVE "Builtin Mojave GTK theme" OFF)
+
+if (APPLE)
+    set(BUILTIN_GTKGLEXT ON)
+    set(BUILTIN_GTKTHEME_MOJAVE ON)
+endif ()
+
+set(BUILTIN_GTKGLEXT_BUILT OFF CACHE INTERNAL "...")
+if (EXISTS "${BUILTINS_PKGCONFIG_DIR}/gtkglext-1.0.pc")
+    set(BUILTIN_GTKGLEXT_BUILT ON)
+endif ()
+
+if (EXISTS "${BUILTINS_INCLUDE_DIR}")
+    include_directories("${BUILTINS_INCLUDE_DIR}")
+endif ()
+
+if (EXISTS "${BUILTINS_LIB_DIR}")
+    set(ENV{LD_LIBRARY_PATH} "$ENV{LD_LIBRARY_PATH}:${BUILTINS_LIB_DIR}")
+    link_directories("${BUILTINS_LIB_DIR}")
+endif ()
+
+if (EXISTS "${BUILTINS_PKGCONFIG_DIR}")
+    set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${BUILTINS_PKGCONFIG_DIR}")
+endif ()
+
+#-----------------------------------------------------------------------
+# CMake modules
+#-----------------------------------------------------------------------
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
+
+#-----------------------------------------------------------------------
+# Submodules
+#-----------------------------------------------------------------------
+
+if (EXISTS "${PROJECT_SOURCE_DIR}/libs/crunch/inc/crn_decomp.h")
+    set(DEFAULT_BUILD_CRUNCH ON CACHE INTERNAL "...")
+else ()
+    set(DEFAULT_BUILD_CRUNCH OFF CACHE INTERNAL "...")
+endif ()
+
+if (EXISTS "${PROJECT_SOURCE_DIR}/tools/unvanquished/daemonmap/tools/quake3/q3map2/main.c")
+    set(DEFAULT_BUILD_DAEMONMAP ON CACHE INTERNAL "...")
+else ()
+    set(DEFAULT_BUILD_DAEMONMAP OFF CACHE INTERNAL "...")
+endif ()
+
+#-----------------------------------------------------------------------
+# Build options
+#-----------------------------------------------------------------------
+
 option(BUILD_RADIANT "Build the GUI" ON)
-option(BUILD_CRUNCH "Build Crunch image support" OFF)
+option(BUILD_TOOLS "Build the tools" ON)
+option(BUILD_CRUNCH "Build Crunch image support" ${DEFAULT_BUILD_CRUNCH})
+option(BUILD_DAEMONMAP "Build daemonmap navigation mesh generator" ${DEFAULT_BUILD_DAEMONMAP})
+option(DOWNLOAD_GAMEPACKS "Download game packs" ON)
 option(USE_WERROR "Build with -Werror -pedantic-errors" OFF)
+option(FHS_INSTALL "Install according to Filesystem Hierarchy Standard" OFF)
+option(FHS_INSTALL_ABSOLUTE "Install using absolute paths (requires FHS_INSTALL)" OFF)
+
+set(BUILD_BINARIES OFF CACHE INTERNAL "...")
+if (BUILD_RADIANT OR BUILD_TOOLS)
+    set(BUILD_BINARIES ON)
+endif ()
+
+if (BUILD_BINARIES)
+    if (WIN32
+        OR APPLE
+        OR "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"
+        OR "${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD" )
+        set(BUNDLING_SUPPORTED ON)
+    endif()
+
+    if (BUNDLING_SUPPORTED)
+        if(WIN32 AND NOT CMAKE_CROSSCOMPILING)
+            set(BUNDLE_LIBRARIES_DEFAULT ON)
+        else ()
+            set(BUNDLE_LIBRARIES_DEFAULT OFF)
+        endif ()
+
+        option(BUNDLE_LIBRARIES "Bundle libraries" ${BUNDLE_LIBRARIES_DEFAULT})
+    endif ()
+
+    if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
+        set(FHS_INSTALL OFF CACHE PATH "Disabled because of BUNDLE_LIBRARIES is enabled" FORCE)
+    endif ()
+
+    if (NOT FHS_INSTALL AND FHS_INSTALL_ABSOLUTE)
+        set(FHS_INSTALL_ABSOLUTE OFF CACHE PATH "Disabled because of FHS_INSTALL is disabled" FORCE)
+    endif ()
+endif ()
+
+#-----------------------------------------------------------------------
+# Paths
+#-----------------------------------------------------------------------
 
 if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
     set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/install" CACHE PATH "..." FORCE)
 endif ()
 
+if (APPLE)
+    set(APPLE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}/NetRadiant.app)
+    set(FINAL_INSTALL_PREFIX ${APPLE_INSTALL_PREFIX}/Contents/Prefix)
+else ()
+    set(FINAL_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX})
+endif ()
+
+set(RADIANT_NAME "NetRadiant" CACHE INTERNAL "...")
+add_definitions(-DRADIANT_NAME="${RADIANT_NAME}")
+set(RADIANT_BASENAME "netradiant" CACHE INTERNAL "...")
+add_definitions(-DRADIANT_BASENAME="${RADIANT_BASENAME}")
+
+set(RADIANT_BIN_DIR ${FINAL_INSTALL_PREFIX} CACHE INTERNAL "...")
+set(RADIANT_LIB_DIR ${FINAL_INSTALL_PREFIX}/lib CACHE INTERNAL "...")
+set(RADIANT_ADDONS_DIR ${FINAL_INSTALL_PREFIX} CACHE INTERNAL "...")
+set(RADIANT_SHARE_DIR ${FINAL_INSTALL_PREFIX}/share CACHE INTERNAL "...")
+set(RADIANT_DATA_DIR ${FINAL_INSTALL_PREFIX} CACHE INTERNAL "...")
+
+if (FHS_INSTALL)
+    add_definitions(-DRADIANT_FHS_INSTALL='ON')
+
+    set(RADIANT_BIN_DIR ${FINAL_INSTALL_PREFIX}/bin)
+    set(RADIANT_LIB_DIR ${FINAL_INSTALL_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE})
+    set(RADIANT_ADDONS_DIR ${RADIANT_LIB_DIR}/${RADIANT_BASENAME})
+    set(RADIANT_SHARE_DIR ${FINAL_INSTALL_PREFIX}/share)
+    set(RADIANT_DATA_DIR ${RADIANT_SHARE_DIR}/${RADIANT_BASENAME})
+    set(RADIANT_LIB_DIR ${FINAL_INSTALL_PREFIX}/lib/${CMAKE_LIBRARY_ARCHITECTURE})
+
+    if (FHS_INSTALL_ABSOLUTE)
+        add_definitions(-DRADIANT_ADDONS_DIR="${RADIANT_ADDONS_DIR}")
+        add_definitions(-DRADIANT_DATA_DIR="${RADIANT_DATA_DIR}")
+    else ()
+        add_definitions(-DRADIANT_LIB_ARCH="${CMAKE_LIBRARY_ARCHITECTURE}")
+    endif ()
+endif ()
+
+
+set(GAMEPACKS_DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download CACHE PATH "Where to store downloaded game packs")
+
 #-----------------------------------------------------------------------
 # Version
 #-----------------------------------------------------------------------
 
 # CMake 3.0+ would allow this in project()
-set(NetRadiant_VERSION_MAJOR 1)
-set(NetRadiant_VERSION_MINOR 5)
-set(NetRadiant_VERSION_PATCH 0)
-set(NetRadiant_VERSION "${NetRadiant_VERSION_MAJOR}.${NetRadiant_VERSION_MINOR}.${NetRadiant_VERSION_PATCH}")
-
-file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_MAJOR" ${NetRadiant_VERSION_MAJOR})
-file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_MINOR" ${NetRadiant_VERSION_MINOR})
-file(WRITE "${PROJECT_BINARY_DIR}/RADIANT_PATCH" ${NetRadiant_VERSION_PATCH})
+set(RADIANT_VERSION_MAJOR 1)
+set(RADIANT_VERSION_MINOR 5)
+set(RADIANT_VERSION_PATCH 0)
+set(RADIANT_VERSION "${RADIANT_VERSION_MAJOR}.${RADIANT_VERSION_MINOR}.${RADIANT_VERSION_PATCH}")
 
 set(RADIANT_ABOUTMSG "Custom build" CACHE STRING "About message")
 
-find_package(Git REQUIRED)
-execute_process(
-        COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE GIT_VERSION
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-)
-set(RADIANT_VERSION_STRING "${NetRadiant_VERSION}n")
-if (GIT_VERSION)
-    set(RADIANT_VERSION_STRING "${RADIANT_VERSION_STRING}-git-${GIT_VERSION}")
+set(RADIANT_VERSION_STRING "${RADIANT_VERSION}n")
+
+if (NOT DEFINED GIT_VERSION)
+     find_package(Git REQUIRED)
+
+     execute_process(
+          COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
+          WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+          OUTPUT_VARIABLE GIT_VERSION
+          OUTPUT_STRIP_TRAILING_WHITESPACE
+     )
+
+     if (GIT_VERSION)
+         set(RADIANT_VERSION_STRING "${RADIANT_VERSION_STRING}-git-${GIT_VERSION}")
+     endif ()
 endif ()
 
 message(STATUS "Building ${PROJECT_NAME} ${RADIANT_VERSION_STRING} ${RADIANT_ABOUTMSG}")
@@ -44,20 +186,23 @@ message(STATUS "Building ${PROJECT_NAME} ${RADIANT_VERSION_STRING} ${RADIANT_ABO
 # Language standard
 #-----------------------------------------------------------------------
 
-set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-set(CMAKE_CXX_EXTENSIONS OFF)
-if (CMAKE_VERSION VERSION_LESS "3.1")
-    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
-        include(CheckCXXCompilerFlag)
-        check_cxx_compiler_flag(--std=c++${CMAKE_CXX_STANDARD} STD_CXX)
-        if (STD_CXX)
-            set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++${CMAKE_CXX_STANDARD}")
+if (BUILD_BINARIES)
+    set(CMAKE_CXX_STANDARD 11)
+    set(CMAKE_CXX_STANDARD_REQUIRED ON)
+    set(CMAKE_CXX_EXTENSIONS OFF)
+
+    if (CMAKE_VERSION VERSION_LESS "3.1")
+        if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
+            include(CheckCXXCompilerFlag)
+            check_cxx_compiler_flag(--std=c++${CMAKE_CXX_STANDARD} STD_CXX)
+            if (STD_CXX)
+                set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++${CMAKE_CXX_STANDARD}")
+            else ()
+                message(SEND_ERROR "Requires C++${CMAKE_CXX_STANDARD} or better")
+            endif ()
         else ()
-            message(SEND_ERROR "Requires C++${CMAKE_CXX_STANDARD} or better")
+            message(WARNING "Unrecognized compiler: ${CMAKE_CXX_COMPILER_ID}, make sure it supports C++${CMAKE_CXX_STANDARD}")
         endif ()
-    else ()
-        message(WARNING "Unrecognized compiler: ${CMAKE_CXX_COMPILER_ID}, make sure it supports C++${CMAKE_CXX_STANDARD}")
     endif ()
 endif ()
 
@@ -65,119 +210,257 @@ endif ()
 # Flags
 #-----------------------------------------------------------------------
 
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
-macro(addflags_c args)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${args}")
-endmacro()
-macro(addflags_cxx args)
-    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${args}")
-endmacro()
-macro(addflags args)
-    addflags_c("${args}")
-    addflags_cxx("${args}")
-endmacro()
-addflags("-fno-strict-aliasing")
-if (NOT WIN32)
-    addflags("-fvisibility=hidden")
-endif ()
+if (BUILD_BINARIES)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
+
+    macro (addflags_c args)
+        set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${args}")
+    endmacro ()
+
+    macro (addflags_cxx args)
+        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${args}")
+    endmacro ()
+
+    macro (addflags args)
+        addflags_c("${args}")
+        addflags_cxx("${args}")
+    endmacro ()
 
-if (USE_WERROR)
-    addflags("-Werror")
-    addflags("-pedantic-errors")
+    addflags("-fno-strict-aliasing")
+    if (NOT WIN32)
+        addflags("-fvisibility=hidden")
+    endif ()
+
+    if (USE_WERROR)
+        addflags("-Werror")
+        addflags("-pedantic-errors")
+    endif ()
+
+    addflags("-Wall")
+    addflags("-Wextra")
+    addflags("-pedantic")
+
+    addflags_c("-Wno-deprecated-declarations") # vfs.c: g_strdown
+
+    addflags("-Wno-unused-function")
+    addflags("-Wno-unused-variable")
+    addflags("-Wno-unused-parameter")
+
+    if (APPLE)
+        add_definitions(-DGL_SILENCE_DEPRECATION=1)
+    endif()
+
+    set(CMAKE_POSITION_INDEPENDENT_CODE 1)
 endif ()
 
-addflags("-Wall")
-addflags("-Wextra")
-addflags("-pedantic")
+if (BUILD_RADIANT)
+    set(GTK_TARGET 2 CACHE STRING "GTK target")
+    add_definitions(-DGTK_TARGET=${GTK_TARGET})
 
-addflags_c("-Wno-deprecated-declarations") # vfs.c: g_strdown
+    if (WIN32)
+        add_definitions(-DWORKAROUND_WINDOWS_FLOATING_WINDOW=1)
 
-addflags("-Wno-unused-function")
-addflags("-Wno-unused-variable")
-addflags("-Wno-unused-parameter")
+        if (GTK_TARGET EQUAL 2)
+            add_definitions(-DWORKAROUND_WINDOWS_GTK2_GLWIDGET=1)
+        endif ()
+    endif ()
 
-set(CMAKE_POSITION_INDEPENDENT_CODE 1)
-set(GTK_TARGET 2 CACHE STRING "GTK target")
-add_definitions(-DGTK_TARGET=${GTK_TARGET})
+    if (APPLE)
+        if (GTK_TARGET EQUAL 2)
+            add_definitions(-DWORKAROUND_MACOS_GTK2_DESTROY=1)
+            add_definitions(-DWORKAROUND_MACOS_GTK2_GLWIDGET=1)
+            add_definitions(-DWORKAROUND_MACOS_GTK2_LAGGYPOINTER=1)
+        endif ()
+    endif ()
+endif ()
 
 #-----------------------------------------------------------------------
 # Defs
 #-----------------------------------------------------------------------
 
-add_definitions(-DRADIANT_VERSION="${NetRadiant_VERSION}")
-add_definitions(-DRADIANT_MAJOR_VERSION="${NetRadiant_VERSION_MAJOR}")
-add_definitions(-DRADIANT_MINOR_VERSION="${NetRadiant_VERSION_MINOR}")
-add_definitions(-DRADIANT_PATCH_VERSION="${NetRadiant_VERSION_PATCH}")
+if (BUILD_BINARIES)
+    add_definitions(-DRADIANT_VERSION="${RADIANT_VERSION}")
+    add_definitions(-DRADIANT_VERSION_STRING="${RADIANT_VERSION_STRING}")
+
+    if (NOT CMAKE_BUILD_TYPE MATCHES Release)
+        add_definitions(-D_DEBUG=1)
+    endif ()
+endif ()
 
-add_definitions(-DRADIANT_ABOUTMSG="${NetRadiant_ABOUT}")
+if (BUILD_RADIANT)
+    add_definitions(-DRADIANT_ABOUTMSG="${RADIANT_ABOUTMSG}")
 
-if (NOT CMAKE_BUILD_TYPE MATCHES Release)
-    add_definitions(-D_DEBUG=1)
+    macro (disable_deprecated name gtk2only)
+        add_definitions(-D${name}_DISABLE_SINGLE_INCLUDES)
+        if ((${gtk2only} EQUAL 0) OR (GTK_TARGET EQUAL 2))
+            add_definitions(-D${name}_DISABLE_DEPRECATED)
+        endif ()
+    endmacro ()
+
+    disable_deprecated(ATK 0)
+    disable_deprecated(G 0)
+    disable_deprecated(GDK 0)
+    disable_deprecated(GDK_PIXBUF 0)
+    disable_deprecated(GTK 1)
+    disable_deprecated(PANGO 0)
 endif ()
 
-macro(disable_deprecated name gtk2only)
-    add_definitions(-D${name}_DISABLE_SINGLE_INCLUDES)
-    if ((${gtk2only} EQUAL 0) OR (GTK_TARGET EQUAL 2))
-        add_definitions(-D${name}_DISABLE_DEPRECATED)
-    endif ()
-endmacro()
+if (BUILD_BINARIES)
+    add_custom_target(binaries ALL)
 
-disable_deprecated(ATK 0)
-disable_deprecated(G 0)
-disable_deprecated(GDK 0)
-disable_deprecated(GDK_PIXBUF 0)
-disable_deprecated(GTK 1)
-disable_deprecated(PANGO 0)
+    if(APPLE OR ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
+        link_directories(
+            /usr/local/lib
+        )
+    endif ()
 
-if (APPLE)
-    option(XWINDOWS "Build against X11" ON)
-    add_definitions(
-            -DPOSIX=1
-    )
-elseif (WIN32)
-    add_definitions(
+    if (WIN32)
+        add_definitions(
             -DWIN32=1
             -D_WIN32=1
-    )
-else ()
-    set(XWINDOWS ON)
-    add_definitions(
+        )
+    else ()
+        add_definitions(
             -DPOSIX=1
-    )
+        )
+    endif ()
 endif ()
 
-if (XWINDOWS)
+if (BUILD_RADIANT AND NOT APPLE AND NOT WIN32)
+    set(XWINDOWS ON)
     find_package(X11 REQUIRED)
     include_directories(${X11_INCLUDE_DIR})
     add_definitions(-DXWINDOWS=1)
 endif ()
 
-include_directories("${PROJECT_SOURCE_DIR}/include")
-include_directories("${PROJECT_SOURCE_DIR}/libs")
+if (BUILD_BINARIES)
+    include_directories("${PROJECT_SOURCE_DIR}/include")
+    include_directories("${PROJECT_SOURCE_DIR}/libs")
 
-if (WIN32 AND NOT CMAKE_CROSSCOMPILING)
-    set(BUNDLE_LIBRARIES_DEFAULT ON)
-else ()
-    set(BUNDLE_LIBRARIES_DEFAULT OFF)
+    macro (copy_dlls target)
+        if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
+            add_custom_command(TARGET ${target} POST_BUILD
+                COMMAND "${PROJECT_SOURCE_DIR}/library-bundler"
+                "register" "${PROJECT_BINARY_DIR}" "$<TARGET_FILE:${target}>"
+                VERBATIM
+            )
+            add_dependencies(bundle ${target})
+        endif ()
+    endmacro ()
 endif ()
-option(BUNDLE_LIBRARIES "Bundle libraries" ${BUNDLE_LIBRARIES_DEFAULT})
 
-macro(copy_dlls target)
-    if (BUNDLE_LIBRARIES)
-        add_custom_command(TARGET ${target} POST_BUILD
-                COMMAND bash
-                ARGS -c "ldd '$<TARGET_FILE:${target}>' | grep -v /c/Windows | awk '{ print $1 }' | while read dll; do cp \"$(which $dll)\" '${PROJECT_BINARY_DIR}'; done"
-                VERBATIM
-                )
+#-----------------------------------------------------------------------
+# Bundle
+#-----------------------------------------------------------------------
+
+if (BUILD_BINARIES)
+    if (BUNDLE_LIBRARIES AND BUNDLING_SUPPORTED)
+        add_subdirectory(bundle)
     endif ()
-endmacro()
+endif ()
+
+#-----------------------------------------------------------------------
+# Builtins: targets
+#-----------------------------------------------------------------------
+
+add_custom_target(builtins)
+
+if (BUILTIN_GTKGLEXT OR BUILTIN_GTKTHEME_MOJAVE)
+    include(${CMAKE_ROOT}/Modules/ExternalProject.cmake)
+endif ()
+
+if (BUILTIN_GTKGLEXT)
+    set(GTKGLEXT_PKGNAMES "gdk-2.0 gtk+-2.0 glib-2.0")
+
+    if (NOT APPLE)
+        set(GTKGLEXT_PKGNAMES "${GTKGLEXT_PKGNAMES} gl")
+    endif ()
+
+    execute_process(COMMAND pkg-config --libs ${GTKGLEXT_PKGNAMES}
+        OUTPUT_VARIABLE GTKGLEXT_LDFLAGS
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+
+    set(GTKGLEXT_LDFLAGS "$ENV{LDFLAGS} -lm ${GTKGLEXT_LDFLAGS}")
+
+    execute_process(COMMAND pkg-config --cflags ${GTKGLEXT_PKGNAMES}
+        OUTPUT_VARIABLE GTKGLEXT_CFLAGS
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+
+    set(GTKGLEXT_CFLAGS "$ENV{CFLAGS} ${GTKGLEXT_CFLAGS}")
+
+
+    set(CONFIGURE_OPTIONS --disable-gtk-doc --disable-gtk-doc-html --disable-gtk-doc-pdf --disable-dependency-tracking --without-x)
+
+    if (CMAKE_BUILD_TYPE MATCHES Release)
+        set(CONFIGURE_OPTIONS ${CONFIGURE_OPTIONS} --disable-debug)
+    endif ()
+
+    if (APPLE)
+        set(GTKGLEXT_GIT_TAG macos)
+    else ()
+        set(GTKGLEXT_GIT_TAG fixes)
+    endif ()
+
+    if (APPLE)
+        set(GTKGLEXT_CFLAGS "${GTKGLEXT_CFLAGS} -DGL_SILENCE_DEPRECATION=1 -Wno-deprecated-declarations")
+    endif ()
+
+    ExternalProject_Add(gtkglext
+        GIT_REPOSITORY https://gitlab.gnome.org/illwieckz/gtkglext.git
+        GIT_TAG ${GTKGLEXT_GIT_TAG}
+        BUILD_IN_SOURCE ON
+        CONFIGURE_COMMAND export CCFLAGS=${GTKGLEXT_CFLAGS}
+        CONFIGURE_COMMAND && export LDFLAGS=${GTKGLEXT_LDFLAGS}
+        CONFIGURE_COMMAND && export NOCONFIGURE=1
+        CONFIGURE_COMMAND && ./autogen.sh
+        CONFIGURE_COMMAND && ./configure --prefix "${BUILTINS_INSTALL_DIR}" ${CONFIGURE_OPTIONS}
+        BUILD_COMMAND $(MAKE)
+        BUILD_COMMAND CFLAGS=${GTKGLEXT_CFLAGS}
+        BUILD_COMMAND LDFLAGS=${GTKGLEXT_LDFLAGS}
+        INSTALL_COMMAND $(MAKE) install
+    )
+
+    include_directories("${BUILTINS_INCLUDE_DIR}/gtkglext-1.0")
+    include_directories("${BUILTINS_LIB_DIR}/gtkglext-1.0/include")
+
+    add_dependencies(builtins gtkglext)
+    set_target_properties(gtkglext PROPERTIES EXCLUDE_FROM_ALL ON)
+endif ()
+
+if (BUNDLE_LIBRARIES)
+    # It was required to tell cmake to not patch rpath on macos builtins.
+    # It was also required to tell cmake to not patch rpath on freebsd binaries.
+    # Patching rpath is done in library_bundler instead so we can skip this
+    # step entirely when bundling.
+    set(CMAKE_SKIP_RPATH ON)
+endif()
+
+if (BUILTIN_GTKTHEME_MOJAVE)
+    ExternalProject_Add(gtktheme-mojave
+        GIT_REPOSITORY https://github.com/vinceliuice/Mojave-gtk-theme.git
+        GIT_TAG master
+        BUILD_IN_SOURCE ON
+        CONFIGURE_COMMAND echo
+        BUILD_COMMAND echo
+        INSTALL_COMMAND ./install.sh -o standard -a standard -s standard -i standard -d "${PROJECT_BINARY_DIR}/themes"
+    )
+    add_dependencies(builtins gtktheme-mojave)
+    set_target_properties(gtktheme-mojave PROPERTIES EXCLUDE_FROM_ALL ON)
+endif ()
 
 #-----------------------------------------------------------------------
 # Libraries
 #-----------------------------------------------------------------------
 
-add_subdirectory(libs)
-add_subdirectory(include)
+if (BUILD_BINARIES)
+    add_subdirectory(libs)
+endif ()
+
+if (BUILD_RADIANT)
+    add_subdirectory(include)
+endif ()
 
 #-----------------------------------------------------------------------
 # Plugins
@@ -199,90 +482,114 @@ endif ()
 # Radiant
 #-----------------------------------------------------------------------
 
-if (CMAKE_EXECUTABLE_SUFFIX)
-    string(REGEX REPLACE "^[.]" "" RADIANT_EXECUTABLE ${CMAKE_EXECUTABLE_SUFFIX})
-else ()
-    execute_process(
-            COMMAND uname -m
-            OUTPUT_VARIABLE RADIANT_EXECUTABLE
-            OUTPUT_STRIP_TRAILING_WHITESPACE
-    )
-endif ()
+if (BUILD_BINARIES)
+    macro (radiant_tool name)
+        add_dependencies(binaries ${name})
+
+        if (WIN32)
+            add_executable(${name} ${ARGN} ${PROJECT_SOURCE_DIR}/include/lib.rc)
+        else ()
+            add_executable(${name} ${ARGN})
+        endif()
 
-macro(radiant_tool name)
-    add_executable(${name} ${ARGN})
-    install(
+        copy_dlls(${name})
+
+        install(
             TARGETS ${name}
-            RUNTIME DESTINATION .
-    )
-    if (NOT (CMAKE_EXECUTABLE_SUFFIX STREQUAL ".${RADIANT_EXECUTABLE}"))
-        add_custom_command(TARGET ${name} POST_BUILD
-                COMMAND ln -f -s "$<TARGET_FILE_NAME:${name}>" "${PROJECT_BINARY_DIR}/${name}.${RADIANT_EXECUTABLE}"
-                VERBATIM
-                )
-        install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
-                ${name}${CMAKE_EXECUTABLE_SUFFIX} ${CMAKE_INSTALL_PREFIX}/${name}.${RADIANT_EXECUTABLE})
-                ")
-    endif ()
-endmacro()
+            RUNTIME DESTINATION ${RADIANT_BIN_DIR}
+        )
+    endmacro ()
 
-if (BUILD_RADIANT)
-    add_subdirectory(radiant _radiant)
-    set_target_properties(radiant PROPERTIES
-            COMPILE_DEFINITIONS RADIANT_EXECUTABLE="${RADIANT_EXECUTABLE}"
-            )
+    if (BUILD_RADIANT)
+        add_subdirectory(radiant)
+    endif ()
 endif ()
 
 #-----------------------------------------------------------------------
 # Tools
 #-----------------------------------------------------------------------
 
-add_subdirectory(tools)
+if (BUILD_TOOLS)
+    add_subdirectory(tools)
 
-file(GLOB DATA_FILES "${PROJECT_SOURCE_DIR}/setup/data/tools/*")
+    file(GLOB DATA_FILES "${PROJECT_SOURCE_DIR}/setup/data/tools/*")
 
-if (NOT (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR))
-    # Copy data files from sources to the build directory
-    message(STATUS "Copying data files")
-    file(COPY ${DATA_FILES} DESTINATION "${PROJECT_BINARY_DIR}")
+    if (NOT (PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR))
+        # Copy data files from sources to the build directory
+        message(STATUS "Copying data files")
+        file(COPY ${DATA_FILES} DESTINATION "${PROJECT_BINARY_DIR}")
+    endif ()
 endif ()
 
 #-----------------------------------------------------------------------
 # Game packs
 #-----------------------------------------------------------------------
 
-option(DOWNLOAD_GAMEPACKS "Download game packs" ON)
-
 set(GAMEPACKS_LICENSE_LIST free CACHE STRING "Download game packs by license")
 set(GAMEPACKS_NAME_LIST none CACHE STRING "Download game packs by name")
 
 if (DOWNLOAD_GAMEPACKS)
-   add_custom_target(game_packs ALL
-      COMMAND "${PROJECT_SOURCE_DIR}/gamepack-manager" --license ${GAMEPACKS_LICENSE_LIST} --name ${GAMEPACKS_NAME_LIST} --download-dir "${PROJECT_BINARY_DIR}/download" --install-dir "${PROJECT_BINARY_DIR}" --download --install
-      COMMENT "Downloading ${GAMEPACKS_LICENSE_LIST} game packs"
-   )
-endif()
+    add_custom_target(gamepacks ALL
+       COMMAND "${PROJECT_SOURCE_DIR}/gamepack-manager" --license ${GAMEPACKS_LICENSE_LIST} --name ${GAMEPACKS_NAME_LIST} --download-dir "${GAMEPACKS_DOWNLOAD_DIR}" --install-dir "${PROJECT_BINARY_DIR}/gamepacks" --download --install
+       COMMENT "Downloading game packs"
+    )
+endif ()
 
 #-----------------------------------------------------------------------
 # Install
 #-----------------------------------------------------------------------
 
-install(
-        FILES
-        "${PROJECT_BINARY_DIR}/RADIANT_MAJOR"
-        "${PROJECT_BINARY_DIR}/RADIANT_MINOR"
-        "${PROJECT_BINARY_DIR}/RADIANT_PATCH"
-        DESTINATION .
-)
-
-install(
-        DIRECTORY
-        setup/data/tools/
+if (BUILD_BINARIES)
+    install(DIRECTORY
+        setup/data/tools/base
+        setup/data/tools/bitmaps
+        setup/data/tools/gl
+        setup/data/tools/plugins
         docs
-        DESTINATION .
-)
+        DESTINATION ${RADIANT_DATA_DIR}
+    )
 
-install(CODE "execute_process(COMMAND \"${PROJECT_SOURCE_DIR}/gamepack-manager\" --license ${GAMEPACKS_LICENSE_LIST} --name ${GAMEPACKS_NAME_LIST} --download-dir \"${PROJECT_BINARY_DIR}/download\" --install-dir \"${CMAKE_INSTALL_PREFIX}\" --install)"
-)
+    install(FILES
+        setup/data/tools/global.xlink
+        DESTINATION ${RADIANT_DATA_DIR}
+    )
+endif ()
+
+if (DOWNLOAD_GAMEPACKS)
+    install(DIRECTORY
+        ${PROJECT_BINARY_DIR}/gamepacks
+        DESTINATION ${RADIANT_DATA_DIR}
+    )
+endif ()
+
+if (BUILD_BINARIES AND FHS_INSTALL AND NOT WIN32 AND NOT APPLE)
+    install(FILES
+        icons/netradiant.png
+        DESTINATION ${RADIANT_SHARE_DIR}/pixmaps
+    )
+    install(FILES
+        icons/netradiant.desktop
+        DESTINATION ${RADIANT_SHARE_DIR}/applications
+    )
+    install(FILES
+        icons/x-netradiant-map.xml
+        DESTINATION ${RADIANT_SHARE_DIR}/mime/application
+    )
+endif ()
+
+if (APPLE)
+    install(DIRECTORY
+        setup/macos/Contents
+        DESTINATION ${APPLE_INSTALL_PREFIX}
+    )
+    install(DIRECTORY
+    ${PROJECT_BINARY_DIR}/themes
+        DESTINATION ${APPLE_INSTALL_PREFIX}/Contents/Prefix/share
+    )
+    install(PROGRAMS
+        setup/macos/NetRadiant
+        DESTINATION ${APPLE_INSTALL_PREFIX}/Contents/MacOS
+    )
+endif ()
 
 include(cmake/scripts/package.cmake)
diff --git a/COMPILING b/COMPILING
deleted file mode 100644 (file)
index 29a707c..0000000
--- a/COMPILING
+++ /dev/null
@@ -1,95 +0,0 @@
-
-developer documentation for NetRadiant
-======================================
-
-(NOTE: outdated stuff has been ROT13ed)
-
-getting the source
-==================
-
-The latest source is available from the git repository.
-  git://git.icculus.org/divverent/netradiant.git
-
-The git client can be obtained from the Subversion site.
-  http://git-scm.org
-
-To get a copy of the source using the commandline git client:
-  Change the current directory to the desired location for the source.
-  git clone git://git.icculus.org/divverent/netradiant.git
-  cd netradiant
-
-
-
-Linux(using X-windows)
-======================
-
-environment:
-- gcc >= version 3.1 (preferably)
-- GNU make
-- svn >= 1.1 (some build steps use svn)
-
-dependencies:
-- gtk+ >= 2.4.0 (requires glib, atk, pango, iconv, etc)
-- gtkglext >= 1.0.0 (requires opengl)
-- libxml2 >= 2.0.0
-- zlib >= 1.2.0 (for archivezip module)
-- libpng >= 1.2.0 (for imagepng module)
-
-build:
-run 'make'
-
-run:
-Execute 'install/radiant.x86'
-
-OSX(using X-windows)
-====================
-
-environment:
-- OS X 10.5 or 10.6
-- Xcode developer tools installed (OSX DVD)
-- X11 (from the OS X DVD)
-- MacPorts or fink or homebrew installed
-- the following packages installed:
-  Macports:
-    gtkglext pkgconfig glib2-devel libxml2 gtk2 pango atk gettext wget
-  Fink:
-    gtkglext1 pkgconfig glib2-dev libxml2 gtk+2 gtk+2-dev pango1-xft2-ft219-dev atk1 gettext-dev wget
-  homebrew:
-    gtk+ gtkglext
-
-build:
-run 'make'
-
-homebrew build:
-run 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig
-make'
-
-run:
-Switch into the install folder, and run NetRadiant.app
-
-Win32 (2000, XP, Vista or Windows 7)
-==================
-
-environment:
-- MinGW (http://www.mingw.org/wiki/Getting_Started)
-  Install this to c:\mingw, and select the components C compiler, C++ compiler
-  and MSYS Basic System
-- Start the MSYS shell once, then exit it
-- Prepackaged Radiant dependencies (Gtk and other stuff):
-  http://www.icculus.org/netradiant/files/netradiant-dependencies-mingw32-20101211-7z.exe
-  Extract this one to
-  c:\mingw\msys\1.0\home\username
-  (if you do this with 7zip, keep the "netradiant-dependencies-mingw32" folder
-  name of the contents)
-- now download the source from the MSYS shell, if you don't already have it:
-  ~/netradiant-dependencies-mingw32/util/bin/git clone git://git.icculus.org/divverent/netradiant.git
-
-build:
-- Start the MSYS shell
-- Switch to the directory with NetRadiant source
-- make MAKEFILE_CONF=mingw-Makefile.conf
-
-run:
-- in the "install" directory, double click netradiant.exe
-- if you get a DLL not found error, copy the DLL from either c:\mingw\bin or
-  from c:\mingw\msys\1.0\bin to the "install" directory
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
deleted file mode 100644 (file)
index cee478d..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-GtkRadiant past contributors and credits
-last update: 01/15/2001
-
-GtkRadiant 1.5 development:
--------
-Thomas "namespace" Nitschke spam@codecreator.net
-Stefan "Shaderman" Greven
-"Topsun"
-SmallPileofGibs spog@planetquake.com
-"Tr3b"
-
-Small contributions and improvements for 1.5
---------
-Eric "eb" Barth
-
-Loki
-----
-Leonardo Zide leo@lokigames.com
-Mike Phillips (Loki QA)
-Bernd Kreimeier (overall coordination)
-
-QER.com
--------
-TTimo timo@idsoftware.com
-^Fishman (Pablo Zurita) fish@gamedesign.net
-RR2DO2 rr2do2@q3f.com
-SmallPileofGibs spog@planetquake.com
-
-Curry plugin
-------------
-Mike "mickey" Jackman
-Tim "Maj" Rennie
-
-PrtView plugin, various bug fixes and q3map guru
-------------------------------------------------
-Geoffrey DeWan
-
-Gensurf plugin
---------------
-David Hyde
-
-PicoModel
----------
-seaw0lf with assist by ydnar
-
-Q3Map2
-------
-Randy 'ydnar' Reddig
-
-Updated shader files, textures, entities.def, keyboard shortcut list
-overall testing and feedback
-----------------------------
-Jean-Francois "Eutectic" Groleau
-
-Improvements and bug fixing
----------------------------
-Jan Paul "MrElusive" van Waveren
-Robert Duffy
-Forest "LordHavoc" Wroncy-Hale
-Nurail
-AcidDeath
-Chronos
-Michael Schlueter
-Jamie Wilkinson
-Robert "Tr3B" Beckebans
-
-Web
----
-Dave "Bargle" Koenig
-Jason "Wolfen" Spencer
-Shawn "EvilTypeGuy" Walker
-
-Thanks to John Hutton, AstroCreep and W2k for web help
-
-FAQ
----
-Equim and Wex
-
-
-Testing/Feedback
----
-Black_Dog, d0nkey, Fjoggis, Jago, jetscreamer, gibbie, Godmil, Gom Jabbar,
-Mindlink, mslaf, necros, Promit, Ravo, RPG, scampie, sock, sponge, thiste,
-voodoochopsticks, Zwiffle
-
-
-Misc
-----
-Thanks to everyone on the beta mailing list and
-irc.telefragged.com #qeradiant for testing and feedback.
-Updated icons by AstroCreep!
-Bitch-slapping by RaYGunn!
-Last minute bugs by SPoG! (SPoG--)
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644 (file)
index 40bd4d0..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,279 +0,0 @@
-2009-04-26 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: minimap generation for Nexuiz
-       * q3map2: better progress indicators
-
-2009-04-23 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: misc_model spawnflag 64 turns off normal smoothing
-       * q3map2: improved output of vis
-
-2009-04-21 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: more MAX_MAP_VISIBILITY
-
-2009-04-15 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: new toolbar bitmaps by sev
-
-2009-04-13 Rudolf Polzer divVerent(at)alientrap.org
-       * all: fix some MSVC compile errors
-
-2009-04-10 Rudolf Polzer divVerent(at)alientrap.org
-       * all: add WarsowPack
-       * q3map2: add alias _shadeangle to _smoothnormals
-       * q3map2: fix crash in reading RBSP files
-
-2009-04-09 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: fix font size handling
-
-2009-04-08 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: force disable composition on Vista (should fix "white 3D window" issues)
-
-2009-04-05 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: fix ViewSide command (no longer does the same as ViewTop)
-       * q3map2: generate origin brushes when decompiling
-       * q3map2: allow more portals per leaf, to help with -bsp -deep
-
-2009-04-04 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: -bsp -deep also including detail brushes into the BSP tree at lowest priority, should give higher fps while increasing compile time and BSP size
-       * q3map2: fix crash when decompiling to .map
-
-2009-04-03 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: -vis -mergeportals speeding up vis a lot, while not making vis much worse
-
-2009-04-02 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: portable radiant: when a subdir "settings" exists where radiant.exe resides, config is stored there so you can take it with you on a USB stick
-
-2009-04-01 Rudolf Polzer divVerent(at)alientrap.org
-       * all: compile fix on Win64
-
-2009-03-31 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: merged feature -bsp -altsplit (27), alternate way to weight BSP splits, should give higher fps in original Q3 engine (needs testing)
-       * q3map2: also compare shaders when comparing surfaces for sorting (27)
-       * q3map2: misc_model spawnflag 32 copies vertex alpha from color, for terrain blending on models (27)
-
-2009-03-29 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: _ls key shorthand for _lighmapscale (VorteX)
-       * q3map2: -samplescale switch (VorteX)
-       * q3map2: in dq and prophecy games, func_wall casts shadows by default (VorteX)
-       * q3map2: some more prints (VorteX)
-       * q3map2: q3map_floodlight <red> <green> <blue> <distance> <brightness> <power> shader keyword (VorteX)
-       * q3map2: more MAX_TW_VERTS (VorteX)
-       * q3map2: _patchMeta 1 entity keyword (VorteX)
-       * q3map2: q3map_deprecateShader <newershader> shader keyword (VorteX)
-       * q3map2: tangentspace deluxemaps (-deluxemode 1) (VorteX)
-       * q3map2: _smoothnormals entity key to easier set shadeangle (VorteX)
-       * q3map2: -keeplights switch in -light (VorteX)
-       * q3map2: spawnflag 32 on light: unnormalized color (VorteX)
-       * q3map2: spawnflag 64 on light: distance falloff (VorteX)
-       * q3map2: option -gridscale, -gridambientscale (VorteX)
-
-2009-03-27 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: fix a crash on "regroup entities"
-
-2009-03-25 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: editable keyboard shortcuts
-
-2009-03-23 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: avoid a crash if a surface is huge
-
-2009-03-20 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: command line option -celshader
-       * q3map2: let Q_mkdir create all parent directories too
-       * q3map2: fix some crashes
-
-2009-03-16 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: command line option -fs_homebase
-
-2009-03-13 Rudolf Polzer divVerent(at)alientrap.org
-       * all: support objs without material groups
-
-2009-03-11 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: detect being installed inside Q2World
-
-2009-03-08 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: indicate the direction of the clip plane in the 2D view
-
-2009-03-11 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: detect being installed inside Nexuiz
-
-2009-03-09 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: OS X compile fixes
-
-2009-03-04 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: -global-Key Value and -gamename.game-Key Value options to set
-         config settings from the command line
-
-2009-02-25 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: fix two bugs in tjunction fixing
-       * q3map2: -lightmapdir option
-       * q3map2: eliminate MAX_MAP_PLANES limit
-
-2009-02-23 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: -scale -tex ("no texture lock while scaling")
-
-2009-02-15 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: non-uniform -scale x y z
-
-2009-02-10 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: remove LOTS of limits
-
-2009-02-08 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: put the command line parameters into a worldspawn key
-         _q3map2_cmdline; currently not yet supported for -onlyents
-
-2009-02-07 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: use gtk default font instead of defined ones for linux/windows
-         which could happen to be not installed (merged from uforadiant)
-
-2009-02-06 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: OS X icon by airscout
-
-2009-01-15 Rudolf Polzer divVerent(at)alientrap.org
-       * all: more fixes for OS X
-
-2009-01-14 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: use %f format for angles, prevents weird looking angles
-
-2009-01-09 Rudolf Polzer divVerent(at)alientrap.org
-       * all: lots of fixes for compiling on OS X
-
-2009-01-07 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: handle ALL key binds properly using GDK methods
-
-2009-01-03 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: fix the translation of entities used by mirroring or scaling
-
-2009-01-02 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: command "regroup entities", allows moving brushes in/out of
-         entities
-
-2009-01-01 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: "clone selection" no longer changes targetnames by default.
-         Hold shift while pressing space to do change them as before.
-       * all: handle "origin" keys for brush entities (more consistency, should
-         break no maps)
-
-2008-12-10 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: properly handle the [ and ] keys on german layout
-       * q3map2: fix dotProduct2scale to match the documentation
-
-2008-11-28 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: -dirty: don't treat skybox surfaces as solid for dirtmapping;
-         prevents Quake 2-ish "dark near skybox" effect.
-
-2008-11-21 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: applied win32 font and build fix by ingar
-
-2008-11-20 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: extend some more limits but just by a bit this time to not
-         let memory usage rise too high
-       * radiant: fix finding the .mtl file for .obj models
-
-2008-11-18 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: get rid of the MAX_MAP_DRAW_VERTS limit (the array already was
-         dynamic anyway); allows creating BSPs of over 400 MB in size ;)
-
-2008-11-10 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: draw targeting arrows also for target2, etc. keys even in Q3
-         map mode; this is good for Nexuiz which now supports target, target2,
-         target3 and target4.
-
-2008-11-07 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: fix buffer overruns because of using the realpath function
-         with an insufficient buffer; there might be more of these in the code
-         base
-
-2008-10-27 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: -convert -format ase -shadersasbitmap convert mode that writes
-         the shader names in the *BITMAP field in the .ase. That way, the .ase
-         files work without changing as mapobjects.
-
-2008-10-12 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: fix the deluxemap contribution from ambient lighting. minLight
-         is still broken with deluxemapping. If you must use minLight, combine it
-         with 1/2 or 1/4 of its amount in ambient.
-
-2008-09-30 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: fix deluxemap when lit from the wrong side as good as possible
-         by ignoring the deluxemap contribution. Now the invariant "deluxemap
-         vector points away from the surface" should hold. Avoids sudden black
-         spots when deluxemapping.
-
-2008-09-26 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: turn the Urban Terror vis nudge and triangle check into options
-         -extravisnudge and -trianglecheck, as they break some Nexuiz maps.
-         Evaluate the usefulness of these options later.
-       * q3map2: make sure the intermediate .bsp when bouncing always is loadable
-         into the game (by unparsing the entities, so if gridsize got modified,
-         that change gets written too)
-
-2008-09-23 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: print a warning if the specified samplesize cannot be used with
-         the current lightmap size
-
-2008-09-22 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: add dotProduct2scale alphamod
-       * q3map2: add -minsamplesize command line option to override lightmapscale
-         specified in map files
-
-2008-09-19 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: add a "Strafe Mode" option
-       * radiant: ctrl-tab now focuses all XYZ views in the three-part view (as
-         that is what the user is likely to want there)
-       * radiant: make rotate/scale dialogs non-modal
-
-2008-09-18 Rudolf Polzer divVerent(at)alientrap.org
-       * radiant: handle missing anisotropy extension; fixes display bug on
-         Windows XP software renderer
-       * radiant: make logging kick in earlier
-       * radiant: add svn release to the version number
-
-2008-09-15 Rudolf Polzer divVerent(at)alientrap.org
-       * all: added a Makefile to build GtkRadiant; this replaces scons and
-         python install.py
-       * all: got rid of libmhash dependency, using mdfour.c from DarkPlaces
-         instead
-       * q2data: remove RSA security copyrighted md4.c, using mdfour.c from DP
-         instead as a drop-in replacement
-       * all: get rid of version.h and aboutmsg.h, instead set the version in the
-         Makefile
-       * all: support cross compiling using mingw32
-
-2008-09-13 Rudolf Polzer divVerent(at)alientrap.org
-       * q3map2: update to ZeroRadiant's q3map2
-       * q3map2: added lightmap exposure feature: -exposure 4.2 (Urban Terror)
-       * q3map2: check whether a lightmap sample is actually in the triangle
-         (Urban Terror)
-       * q3map2: nudge light sample origin by 1qu away from planes (Urban Terror)
-       * q3map2: floodlight: usage is "_floodlight" "red green blue distance
-         intensity", default "240 240 255 1024 128"; works somewhat similar to
-         dirtmapping (Urban Terror); uses a switch -lowquality
-       * q3map2: added -debugnormals feature (Urban Terror)
-       * q3map2: fix -convert -format map decompiling (note: outputs map in
-         "Alternate Texture Projection" format); no longer messes up texcoords
-       * q3map2: added -game nexuiz to use good default paths for Nexuiz
-       * q3map2: added -game quakelive to enable in-game adverts
-       * q3map2: fix incorrect plane snapping often causing holes in terrain
-       * q3map2: spawnflags on misc_model: 8 extrudes with original normals, 16
-         extrudes with up/down normals (terrain), default: extrudes with axial
-         normals (like before)
-       * q3map2: fix obvious (and reported, and patch sent in) bug when importing
-         models when the normals were pointing in a 45 degrees direction
-       * q3map2: when importing models, allow "surfaceparms structural". This
-         also turns off any plane snapping, as it is intended for caulk brushes
-         inside a model
-       * q3map2: added parameters -ne to set normal epsilon, and -de to set
-         distance epsilon (to customize plane snapping)
-       * q3map2: fix q3map_lightRGB (Urban Terror)
-       * q3map2: add a build script to cross compile q3map2 to Win32
-       * radiant: when displaying normals on a model, scale them to 8 unit size
-         on the output (so "modelscale" can be used without LOTS of lines on the
-         screen)
-       * radiant: also support "killtarget" as target key for drawing the
-         targeting lines
-       * radiant: "expand selection to whole entities" now also selects the
-         entity ITSELF; result: Ctrl-Alt-E Space makes a NEW entity now, instead of
-         just duplicating the brush (old behaviour caused bugs in maps with copied
-         func_ladders)
-       * picomodel: support .obj format as exported by Blender, with a .mtl file
-         defining the shader names for each material; to export using Blender,
-         enable "Materials" and "Material Groups" in the .obj export dialog
-       * all: bump version to 1.5.0-div0
diff --git a/ChangeLog.idsoftware b/ChangeLog.idsoftware
deleted file mode 100644 (file)
index 47deae2..0000000
+++ /dev/null
@@ -1,8216 +0,0 @@
-This is the changelog for developers, != changelog for the end user 
-that we distribute with the binaries. (see changelog)
-
-28/06/2007 (dunkfordyce@gmail.com)
-- fixed mnemonics for MRU list
-- fixed find functionality
-- added option to always use caulk texture for new brushes
-- fixed(?) a small bug in install.py that was trying to copy msvc files on linux
-
-28/06/2007
-- Added material-support to brushexport-plugin (Shaderman)
-
-26/04/2007
-- Disabled auto-search for texbrowser and entityinspector even when the option
-  is turned on in the gtkrc
-
-26/04/2007
-- Fixed q3map2 lightbounce bug (by Unknown)
-
-26/04/2007
-- Fixed another texcompression bug
-
-25/04/2007
-- Fixed texcompression beeing disabled after each restart
-- Fixed gtk-searchpopup in treeviews
-
-15/04/2007
-namespace
-- Fixed brushexport2 output float-format (Shaderman)
-
-27/03/2007
-namespace
-- Fix: Added missing xml-writer pop-calls
-- Ported mapxml plugin to Doom3
-- mapxml now exports brushes with its vertices
-
-19/03/2007
-namespace
-- Fix: Selection is now deleted when creating a patch out of it (aumüller / namespace)
-
-08/03/2007
-namespace
-- Win32 compile fix (woekele)
-
-07/03/2007
-namespace
-- Updated UFA:Plugin (mattn2)
-
-04/03/2007
-namespace
-- Reverted Q3 translucency fix since it randomly made brushes
-  fully transparent in Doom3 mode.
-
-04/03/2007
-namespace
-- Final update for installerfiles (Shaderman / namespace)
-- Removed installer.py validation checks since they are incompatible with Vista
-- Updated msiquery module to python 2.5
-- Added msiquery module for python 2.5
-
-03/03/2007
-namespace
-(THIS IS A TRANSITIONAL REVISION, DO NOT USE, WAIT FOR UPDATED DEPS)
-- Fixed weird msvcrt bugs caused by dbghelp.dll
-- Activated new radiant icon on Linux (Topsun)
-- First update for installerfiles (Shaderman)
-- New MODT for q3map2 :)
-- tiny changes
-
-28/02/2007
-namespace
-- Radiant is now Vista compatible (Aero must be disabled)
-- Updated all radiant dependencies (gtk is now 2-2.10)
-  New dependency packages can be found here
-http://zerowing.idsoftware.com/files/radiant/developer/1.5/gtkradiant-1.5-dependencies-1.0.zip
-  or here
-http://www.codecreator.net/radiant/gtkradiant-1.5-dependencies-1.0.zip
-- Removed Win32 filechooser
-   - Fixes crashes caused by utf-8 encoded filenames
-   - Fixes Vista "SaveAs"-Bug
-- Converted all projects to Visual Studio 2005
-- Codefixes for vc2k5 compiler
-- Removed old unused projectfiles for Visual Studio 6
-- Simplified dependency filestructure
-- Simplified install.py
-- Updated CONTRIBUTORS list
-
-26/01/2007
-namespace
-- SnapPlane reenabled by namespace because of multiple reports of
-  q3map2-crashes which were triggered by this patch.
-
-24/01/2007
-namespace
-- Added Undo/Redo-Toolbarbuttons (Shaderman)
-- Fixed Bug #1078 (sogined)
-
-18/01/2007
-namespace
-- Weird shiftvalues are now hidden to the user, shiftvalues will
-  stay in ]-shader_size;shader_size[ range for display.
-  For the sake of floatingpoint precision, it would be nice
-  to keep the internal values in that range too, but thats "nice to have".
-- Fixed missing librarypaths in ufoai-plugin
-  
-18/01/2007
-LordHavoc
-- disabled SnapPlane because it slightly corrupts collision brushes from
-  embedded model triangles
-
-17/01/2007
-namespace
-- Fixed "jumping" texcoords when switching to a shader with different size
-- (Todo) Toolbar: add button for refresh-models. (Shaderman)
-- Aniso fix (Shaderman)
-- Translucency fix (Shaderman)
-
-05/01/2007
-namespace
-- UFO:Alien Invasion Plugin (mattn2)
-- Fix: Filtering models in ET doesn't filter misc_gamemodels (Shaderman)
-
-25/12/2006
-namespace
- - Brushplugin Version 2.0, supports multiple collapse modes and a materialignore list (namespace)
- - Camera movement speed changes. Increase speed = SHIFT+KP_PLUS, decrease speed = SHIFT+KP_MINUS.
-   New option to link the strafe speed to camera movement speed (default: linked). (Shaderman)
- - Fixed bug in sample plugin (Shaderman)
- - Merry Christmas
-
-17/12/2006
-namespace
- - Radiant warzow-support (Topsun + Warzow-Mappers)
-
-15/12/2006
-namespace
- - Inverted bevel can be used with end caps (Topsun)
- - Removed needless .pdb files from win32 installer (Topsun)
- - Fixed .ase picomodel loader to load shaders again (Shaderman)
- - Removed translucent brushes fix because of wrong rendering behaviour on Linux
- - New cool(!) radiant icon by eb
-
-13/12/2006
-namespace
-- Added tremoulus-support to q3map2
-
-08/12/2006
-namespace
-- Entity names are now drawn for group entities in Doom3 and Quake 3 mode (namespace)
-- Fixed translucent brushes becoming invisible when selected (Shaderman)
-
-06/11/2006
-namespace
-- (TODO) Texture sizes sometimes vary wildly. New texture browser option: View -> Fixed Size.
-  Code parts taken from DarkRadiant. (Shaderman)
-- Added new texture browser option: View -> Hide Image Missing. (Shaderman)
-- Fixed new D3 lights don't have a light_radius key. (Shaderman)
-- Fixed hotkey collision (paste to camera/view menu). New View shortcut = ALT+W. (Shaderman)
-- Fixed .wad MMB 3d view texture selection bug. (Shaderman)
-
-04/11/2006
-namespace
-- Added warzow-support to q3map2
-
-12/10/2006
-namespace
-- Updated help menu web links (removed map-center.com, added ETB documentation) (Shaderman)
-- Added check for existing worldspawn if a new one should be added with the entity menu (Shaderman)
-- Fixed Entity -> Ungroup (Topsun)
-- Fixed hotkey collision ALT+M (filter botclip/Modify menu). New Modify shortcut = ALT+O (Shaderman)
-- Updated Window Layout images (Shaderman)
-- Fixed (TODO) XYWindow: save show-workzone option (Shaderman)
-- Fixed (TODO) Toolbar: add shortcut to tooltips for toolbar buttons (Shaderman)
-- Fixed (TODO) GUI: detachable submenus (Shaderman)
-
-09/10/2006
-namespace
-- Added option to toggle the camera window stats on/off (Shaderman)
-  (view --> show --> show stats)
-
-
-08/10/2006
-namespace
-- Fix for bug 1106 - .wad files don't get listed in the textures menu (Shaderman)
-  (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1106)
-- Added initial support for Prey (Shaderman)
-- Fixed entity inspector sliders to always show (Shaderman)
-- Added NOTES subsection to the entity inspector listing .def "editor_usage*" values (Shaderman)
-
-07/10/2006
-namespace
-- Added "select inside" and "select touching"
-  Both functions now work with multiple selectionbrushes, allowing complex
-  selection operations.
-- Added entries for the selectionfunctions in "Edit" and the main toolbar.
-
-06/10/2006
-namespace
-- Changed ETB not to show any texture if a tag search doesn't match anything (Shaderman)
-- Added View -> Filter -> "Invert filters/Reset filters" function (Shaderman)
-- Fixed (TODO) Textures: remove "shaders only" option for doom3 (Shaderman)
-- Fixed show shaders / shader only / shader info for doom3 and .wad file games (Shaderman)
-
-03/10/2006
-namespace
-- Fix for Bug 1113 (Topsun)
-  (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1113)
-
-03/10/2006
-namespace
-- Changed ETB tag toolbar to a notebook with tag/texture pages (Shaderman)
-- Added a context menu (add/delete/rename tag) to the ETB tag tree view (Shaderman)
-- Added new win32 installer HOWTO (Shaderman/Topsun)
-
-01/10/2006
-namespace
-- Added missing xml files for win32 installer
-
-30/09/2006
-namespace
-- Fixed Etb saving custom tags to global tagfile (Shaderman/namespace)
-- Fixed postbuild step for brushexport, shaderplug and sunplug (Shaderman)
-- Added installersupport for new files and plugins (Shaderman)
-
-30/09/2006
-namespace
-- Added LocalLcPath to plugin interface
-- Added enhanced Texturebrowser (ETB) by Shaderman
-- Added shaderplug by Shaderman, accompanies the ETB
-- Added xmltagging lib by Shaderman, accompanies the ETB
-- Added new icons for ETB, Console, Entityinspector and Lighteditor
-- Fixed minor warning in Sunplug Project
-- Fixed PATH_MAX namecollision in ptrview plugin on Linux
-- Final fix for 64 bit patch.h issue
-
-
-
-12/09/2006
-namespace
-- Fixed 64 Bit issue in patch.h, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1109
-  for details
-
-11/09/2006
-namespace
-- Fixed unnecessary warnings, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1108
-  for details
-
-11/09/2006
-namespace
-- Added sunplug (Mapcoordinator-plugin for ET) by Topsun
-  ET only: setting mapcoordsmins and mapcoordsmaxs in the worldspawn
-  Tester: Shaderman
-- Added brushexport Plugin by namespace
-  Exports selected brushes as wavefront object.
-  Tester: Shaderman
-
-11/09/2006
-namespace
-- Fixed compile error on x86_64, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1105
-  for details.
-
-09/09/2996
-namespace
-- Added strafing for the camerawindow while holding ctrl
-- Additional forward movement can be enabled by pressing shift during strafe
-
-22/08/2006
-SPoG
-- Added VFS support for locating the archive a file was loaded from.
-- Changed Doom3 entity definition parser to gracefully handle parse errors.
-- Fixed crash when loading entity definitions in quake4 1.3 point release.
-
-13/08/2006
-SPoG
-- Disabled 'detail' content flag checkbox in quake2 Surface Inspector.
-
-22/07/2006
-SPoG
-- Fixed doom3 func_static with model not appearing to move when dragged. 
-- Changed ASE model loader to parse material names the same way as DoomEdit.
-- Fixed title of wait-dialog when loading a model.
-- Fixed doom3 func_static with blank 'model' key being invisible.
-- Changed doom3 func_static model creation to replace selected models.
-- Added support for loading both .ent and .def files at the same time.
-
-09/07/2006
-Shaderman
-- Updated win32 libxml2 package to 2.6.24.
-namespace
-- Ported win32 stack-backtrace to use new DebugHelp API.
-- Added stack-backtrace functionality for Linux/OSX.
-
-11/06/2006
-SPoG
-- Fixed arbitrary rotation X and Y axes appearing to be transposed.
-
-04/06/2006
-SPoG
-- Fixed crash when deleting items from Build menu.
-
-03/06/2006
-SPoG
-- Changed doom3 entity creation to add model key for brush-entities.
-- Fixed crash in Save Region.
-- Fixed detail brushes being turned structural when texture is set.
-
-29/05/2006
-SPoG
-- Changed default doom3 light_radius to be taken from the entity-definition.
-- Fixed error when entering and exiting camera freemove with LMB pressed.
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1090
-
-13/05/2006
-LordHavoc
-- Added -fPIC for Linux builds to support x86_64.
-- Removed static-linked libstdc++ hack for non-final builds.
-- Removed gcc explicit linking hack for non-final builds.
-- Added workaround for gcc static-member-pointer-as-template-argument bug.
-- Fixed bobtoolz linux compile errors.
-- Added Nexuiz and Darkplaces support.
-SPoG
-- Changed 'inconsistent vertex count' assert to be non-fatal.
-- Changed 'failed to remove accelerator' assert to be non-fatal.
-- Fixed crash due to broken module dependencies.
-- Fixed default settings for Build Monitoring.
-- Fixed nudge-selection when using the drag tool mode.
-- Added support for patches in texture-painting tool.
-
-30/04/2006
-SPoG
-- Fixed memory leak in signals library.
-- Ported bobtoolz to use new module APIs.
-
-01/04/2006
-SPoG
-- Added key-observer interface to entity module API.
-- Rewrote callback library to add support for return-values.
-- Added minimal API to support bobtoolz plugin.
-- Refactored brush for-each functions to take Functor instead of Visitor.
-- Added signals library.
-
-31/03/2006
-SPoG
-- Changed doom3 light creation to use size of selected brushes.
-
-20/03/2006
-SPoG
-- Fixed crash when resetting preferences after startup failure.
-- Fixed crash on next-leak-spot with build-monitoring enabled.
-- Fixed doom3/quake4 blended-decal rendering when toggling lighting mode.
-- Fixed fit-texture with rotated texture transforms.
-
-20/03/2006
-SPoG
-- Changed Copy/Paste to work on face textures if any faces are selected.
-- Fixed GTK_WIDGET_REALIZED assert when selecting entities (linux).
-
-28/02/2006
-namespace, SPoG
-- Added drag-resizing for doom3/quake4 light_radius boxes.
-
-25/02/2006
-SPoG
-- Fixed objects sometimes dissappearing when at high zoom level in Ortho views.
-
-24/02/2006
-SPoG
-- Added GPL text to win32 installer.
-- Fixed gtk wimp theme not working after using gtkthemeselector.
-
-21/02/2006
-namespace
-- Added command to toggle lighting/textured modes, shortcut F3.
-
-20/02/2006
-SPoG
-- Fixed crash when disabling lighting for a second time.
-
-19/02/2006
-SPoG
-- Fixed crash when loading invalid ASE models.
-
-11/02/2006
-SPoG
-- Added install.py script.
-- Updated COMPILING instructions.
-- Fixed transparency rendering on quake3 shaders.
-- Fixed hint/caulk filtering for Jedi Academy shaders.
-
-04/02/2006
-SPoG
-- Added Radiant Manual shortcut to win32 installation.
-- Added 'use alternative texture projection' option to prefs.
-- Fixed caching bug causing import-map to not reload modified maps.
-- Added blended-decal rendering for doom3 and quake4.
-
-30/01/2006
-SPoG
-- Added expand-selection-to-entities with default shortcut ctrl+alt+e.
-- Fixed crash in gtk file-chooser with some versions of GTK+.
-
-29/01/2006
-SPoG
-- Changed create-group-entity to re-select brushes after creation.
-
-26/01/2006
-SPoG
-- Changed far-clip-plane setting to increase exponentially with distance.
-- Fixed selected entities moving when drag-resizing brushes.
-- Changed patches to be selectable from the back in wireframe views.
-- Speed improvements for transform-selection code.
-
-25/01/2006
-SPoG
-- Added default-texture-scale option to preferences.
-- Added default-grid-spacing option to preferences.
-
-23/01/2006
-Shamus
-- Fixed editing of doom3/quake4 faces with negative texture scale factors.
-
-22/01/2006
-SPoG
-- Fixed shortcut for toggle-far-clip.
-- Fixed broken link in 1.5 user docs.
-
-10/01/2006
-SPoG
-- Changed script parser to ignore comments that start in the middle of tokens.
-- Added support for editor_int/editor_string keys in doom3 entity definitions.
-- Changed doom3/quake4 .mtr and .guide searching to look in subfolders.
-- Added experimental support for doom3/quake4 projected lights.
-
-20/12/2005
-SPoG
-- Added support for quake4 .guide material templates.
-- Fixed GCC4 compile errors with anonymous enums.
-- Added light_radius and light_center GUI to doom3 entity inspector.
-
-10/12/2005
-SPoG
-- Added support for loading and saving Quake4 map format.
-- Added support for built-in shader images such as _noFalloff.
-- Added experimental code to render projected lights.
-- Added support for loading quake4 entity definitions.
-- Fixed picomodel bug loading .lwo files with texture names >64 in length.
-
-22/10/2005
-SPoG
-- Fixed minor memory leak in zip-archive reader.
-
-21/10/2005
-SPoG
-- Fixed model rotation using free-rotation tool.
-- Fixed behaviour of angle/rotation keys for Doom3 entities.
-- Added entity angle-editing for entities that display a model.
-- Stopped size-info being drawn if selection has zero size.
-- Added support for 'angle' key on doom3 entities.
-
-20/10/2005
-SPoG
-- Fixed minor one-time memory leak in build-shader-list.
-- Added functional free-scale tool.
-- Improved precision preservation for free-rotation and free-scale tools.
-- Fixed misc_model rotation using free-rotation tool.
-
-09/10/2005
-SPoG
-- Added entity angle-editing using rotate-tool or rotation toolbar buttons.
-- Fixed start-on-primary-monitor (win32).
-- Fixed camera-view freelook when window is on secondary monitor (win32).
-
-05/10/2005
-paxed
-- Added texture-lock toolbar button.
-SPoG
-- Added stack-trace output to all debug popup messages (win32).
-- Fixed vertex/edge selection behaviour on undoing brush edits.
-- Changed doom3 light centre rendering to use a point instead of a box.
-- Changed map and shader parsers to gracefully handle bad data.
-
-24/09/2005
-SPoG
-- Fixed crash when importing a file after deleting the world entity.
-- Changed copy/paste/import to select world brushes instead of world entity.
-- Added win32-specific stack-trace logging support.
-
-31/08/2005
-SPoG
-- Fixed clipper removing brushes on incorrect side of clip-plane when flipped.
-
-21/08/2005
-SPoG
-- Optimised light-dragging.
-- Changed connect-entities to not break existing connections where possible.
-
-24/07/2005
-SPoG
-- Fixed q3 entity definition for item_health_small.
-
-02/07/2005
-SPoG
-- Fixed build menu becoming empty if editing of default menu is cancelled.
-
-01/07/2005
-SPoG
-- Fixed snap-planes-to-integer preference not being saved.
-
-26/06/2005
-SPoG
-- Changed doom3 light_radius box to draw flat-shaded translucent in camera view.
-- Fixed progress window not being shown when loading maps.
-- Refactored shortcut handling to make focussed widgets override global shortcuts.
-  Allows using ctrl+c to copy console text, undo/redo without main-window focus.
-
-23/06/2005
-SPoG
-- Fixed crash when handling assert/error before gtk_init.
-- Changed Help menu to display only the help menu relevant to the current game.
-
-21/06/2005
-SPoG
-- Fixed double-maps-directory when using non-native file open dialog on win32.
-- Changed find/replace-textures window to update when selecting textures with MMB.
-- Fixed handling of non-UTF-8 wad-names in textures menu.
-
-20/06/2005
-SPoG
-- Changed home-path prefix to be optional on linux/osx for q1/q2.
-- Changed OpenGL module to work correctly with GL_VERSION 2.0.0.
-- Fixed spawnflags in Enemy Territory entity definitions.
-- Added missing Enemy Territory entity types.
-
-19/06/2005
-SPoG
-- Changed clipper-point selection/rendering to behave the same at all zoom levels.
-- Changed clipper-point selection to always pick the closest point to the cursor.
-- Fixed clipper colour not being updated until after restarting.
-- Fixed QE tool not deselecting edges when left-clicking on a vertex without shift.
-- Fixed grid rendering with grid settings other than 8-unit.
-- Fixed textures menu always behaving as if show-shaderlist-only is enabled.
-
-18/06/2005
-SPoG
-- Added saving of camera render mode preference.
-- Changed default camera render mode to Textured for Doom3.
-- Changed default texture render mode to Trilinear.
-
-17/06/2005
-SPoG
-- Ported Team Arena entity definitions to xml format.
-- Added xml q3 entity-definitions to win32 and linux setups.
-
-14/06/2005
-SPoG
-- Fixed QE-tool component-drag selecting components of unselected brushes.
-
-13/06/2005
-SPoG
-- Changed clipper mode and component-editing modes to be mutually exclusive.
-- Changed camera A/Z/D/C keys to obey "discrete movement" checkbox.
-- Added support for up/down movement in freelook mode.
-- Fixed clipper-tool-uses-caulk option.
-- Added prompt for engine path at startup if not found.
-
-12/06/2005
-SPoG
-- Added entity-inspector GUI support for func_button/func_door direction attribute.
-- Added angle/model/sound GUI to entity-inspector for old-style entity-definitions.
-- Added clipper-plane rendering using stippled back-face-culled polygon.
-- Fixed entity-inspector failing to handle non-ascii characters in entity keys.
-
-11/06/2005
-SPoG
-- Fixed entity-inspector window position changing while hidden.
-
-09/06/2005
-SPoG
-- Fixed region-set-selected for model entities.
-
-08/06/2005
-SPoG
-- Added option to enable or disable snapping brush planes to integer on map load/save.
-- Added 0.125 grid.
-- Changed grid rendering to always show major/minor grid colours whatever the zoom level.
-- Increased maximum zoom level for XY views.
-
-06/06/2005
-SPoG
-- Added 'File > Refresh models' - reloads models that have changed outside Radiant.
-
-05/06/2005
-SPoG
-- Fixed model files not being closed after being read.
-- Fixed build menu dialog not saving changes to build commands.
-- Changed build menu to save xml only if changed by user.
-- Fixed CSG-merge.
-- Reduced CSG-merge tolerance for misaligned brushes.
-Michael Kluskens
-- Updated STVEF default build menu to version 2 format.
-- Updated STVEF game configuration file and removed synapse.config.
-
-02/04/2005
-SPoG
-- Changed HashTable insert/remove operations to not invalidate iterators.
-- Changed ReferenceCache realise/unrealise to take advantage of new HashTable behaviour.
-- Refactored containers to use std::swap.
-- Refactored bitfield.h.
-Tr3B
-- Fixed endianness for .lwo loading on linux.
-- Extended q3map2 mathlib functionality.
-
-28/03/2005
-SPoG
-- Specialised filters list for doom3 entity/material types.
-- Added ASE-loader support for shader names specified as a bitmap absolute-path.
-- Fixed monitored-compile debug-feedback display.
-- Added TGA-loader support for vertical and horizontal flipping.  
-- Enabled auto-generation of smooth normals for all LWO models.
-
-27/03/2005
-Tr3B
-- Fixed map-xml module.
-- Added support for qer_trans keyword in doom3 materials.
-
-08/03/2005
-SPoG
-- Added GUI updates during map load and engine-path/game-dir changes.
-- Fixed main window being hidden behind another application on closing a floating window.
-
-07/03/2005
-SPoG
-- Fixed crash when selecting the root node in the entity-list window.
-- Fixed detail flag saving for quake3 map format.
-
-06/03/2005
-SPoG
-- Optimised type-casts for scene-graph type system.
-- Disabled substitution of 'unspecified' for entity key values that match the default.
-- Refactored module-system api - added globalModuleServer().
-- Fixed rotation origin for doom3 func_static models.
-
-05/03/2005
-SPoG
-- Added support for doom3 model-entity 'skin' key.
-- Added noshadows/nospecular/nodiffuse/falloff doom3 light keys to entity-inspector.
-
-04/03/2005
-SPoG
-- Added camera move up/down one floor.
-- Added support for 'unspecified' contents/flags/value for Quake2 brush faces.
-
-26/02/2005
-SPoG
-- Added auto-complete for shader attributes in entity inspector.
-- Added support for doom3-material heightmap to normalmap conversion.
-
-22/02/2005
-SPoG
-- Fixed missing prefix attribute in quake game configuration file.
-- Added auto-completion for find/replace-textures texture-name entries.
-- Removed redundant buttons and options in find/replace-textures window.
-
-21/02/2005
-SPoG
-- Added auto-completion for surface-inspector texture-name entry.
-
-20/02/2005
-SPoG
-- Fixed failure to load shaders containing '.' such as Heretic II model skins.
-- Removed unused legacy cmdlib functions.
-- Added support for fractional repeat values to brush-fit-texture.
-
-19/02/2005
-SPoG
-- Changed entity-connect-selected to use the parent entity of a selected brush.
-- Added q2map and bspc to installation packages.
-Jamie Wilkinson
-- Fixed path to q2map in quake2 build-menu.
-
-13/02/2005
-SPoG
-- Fixed crash in 'Misc > Find Brush' when searching for a non-existent brush.
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1059
-- Limited the maximum number of sides of a prefab brush-cone to 32.
-
-11/02/2005
-SPoG
-- Changed display of angled box-entities to show un-rotated bounding boxes.
-
-10/02/2005
-SPoG
-- Disabled rotation of light entities for games other than Doom 3.
-
-09/02/2005
-David Constanzo
-- Fixed episode flag names on Quake item_sigil and func_episodegate entities.
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1056
-- Added detailed description of Quake item_sigil and func_episodegate entities.
-SPoG
-- Fixed position of light-entity names.
-- Fixed q3map2 feedback xml streams containing non-UTF-8 text.
-- Optimised Locale<->UTF-8 text conversion.
-
-08/02/2005
-SPoG
-- Fixed selecting a texture not resetting the current selected texture-projection.
-- Added handling of OpenGL drivers that don't implement all reported extensions. 
-
-07/02/2005
-SPoG
-- Added support for multi-byte UTF-8 characters in xml content (not markup).
-- Added UTF-8 support in entity-inspector, prefs dialog, recent-files menu, console.
-- Fixed potentially misaligned objects.
-
-05/02/2005
-SPoG
-- Added rendering of entity names for non-group entities.
-- Removed context-dependent opengl calls before opengl context is created.
-
-04/02/2005
-SPoG
-- Fixed crash when printing extended-ascii text in the console.
-- Added conversion of extended-ascii text to utf8 for gtk text-buffer widgets.
-
-03/02/2005
-David Constanzo
-- Fixed typo in Quake entity-definitions.
-SPoG
-- Fixed undo of brush-set-structural and brush-make-structural.
-- Refactored image-loader module api.
-- Added full support for Quake II and Heretic II surface-flags in surface-inspector.
-- Fixed crash in patch-inspector for games other than doom3.
-
-01/02/2005
-SPoG
-- Changed shader-list and entity-definition searching to also search base-dir.
-
-29/01/2005
-SPoG
-- Fixed title of floating entities/console/textures window.
-- Fixed destruction of floating windows on shutdown.
-- Added shortcut handling when entity-inspector/texture-browser are active.
-David Constanzo
-- Fixed crash while auto-saving snapshots.
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1049
-
-28/01/2005
-SPoG
-- Added rendering of fixed S/T tesselation on doom3 patches.
-- Changed creation of doom3 func_static entities to prompt for a model.
-- Fixed zero-sized primitives being rendered for culled entity-connection-lines.
-
-25/01/2005
-SPoG
-- Added support for setting fixed S/T tesselation on doom3 patches.
-- Changed patch inspector to be completely non-modal.
-
-24/01/2005
-SPoG
-- Added support for rotating lights using the rotation tool.
-
-23/01/2005
-SPoG
-- Fixed crash on startup with texture-subsets enabled.
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1045
-- Added support for doom3 lights combined with brushes and patches.
-- Added support for doom3 light_origin on lights.
-- Added support for doom3 light_rotation and rotation key on lights.
-
-22/01/2005
-SPoG
-- Fixed crash when accessing links from help menu.
-- Fixed broken links in help menu.
-- Added game-specific docs to win32 setup.
-- Changed q3 connect-entities to preserve existing targetname key.
-- Changed q3 connect-entities to generate targetname key based on target classname.
-
-21/01/2005
-SPoG
-- Moved information in synapse.config into .game files.
-- Added api versioning for module-system.
-
-20/01/2005
-SPoG
-- Fixed keys/values for brush entities not being editable unless parent is selected.
-- Fixed brush-entities not being deleted when the last child brush is deleted.
-- Fixed scenarios where worldspawn is not the first entity in the map.
-
-19/01/2005
-SPoG
-- Fixed numerical instability in brush winding-generation.
-
-16/01/2005
-SPoG
-- Added Jedi Academy support to linux installer.
-- Fixed main-window jumping to front during autosave.
-- Fixed saving of empty brushes.
-Jame Wilkinson
-- Fixed build errors when compiling for big-endian target.
-
-15/01/2005
-SPoG
-- Fixed launching q3map2 from build-menu on linux/osx.
-- Added version checking of generated config files.
-- Fixed key-up events being missed while holding ctrl/shift/alt.
-- Fixed texture-compression support.
-Jago
-- Changed q1 trigger_relay and trigger_counter to be point entities.
-
-11/01/2005
-SPoG
-- Changed brush-save to not write non-contributing faces.
-- Fixed rendering artifacts on outlines of selected box-entities.
-
-10/01/2005
-SPoG
-- Added patch-cap-cylinder.
-
-09/01/2005
-SPoG
-- Fixed texture-browser scroll-to-selected-texture.
-- Added brush face texture painting.
-
-08/01/2005
-SPoG
-- Fixed ungroup-selected-entities.
-- Added 'Entity' menu.
-- Removed items unrelated to entity-creation from xy-window right-click menu.
-- Fixed minor memory leaks in core.
-- Removed code that ignores empty alpha-channel in tga loader.
-- Fixed memory leak in model module.
-- Fixed memory leaks in picomodel library: ase and lwo loaders.
-- Changed default tool to 'QE' tool.
-
-04/01/2005
-SPoG
-- Changed start-on-primary-screen default to 'true' with multiple screens.
-- Added enter/escape as shortcuts for OK/Cancel buttons on modal dialogs.
-- Disabled mouse-chase scrolling in XY window when drag-selecting.
-- Fixed xlink I/O warnings on linux.
-- Removed light-creation 'intensity' dialog in doom3 config.
-- Changed the default vertical size of the shortcut-list window to 400. 
-- Fixed patch-creation with zero-sized workzone.
-- Fixed crash when rendering doom3 light_radius box.
-
-03/01/2005
-SPoG
-- Added arbfp1/arbvp1 vertex/fragment program lighting support.
-- Fixed colour-selection dialog not going away after OK/Cancel.
-- Fixed tangent/bitangent calculation on degenerate patches.
-- Added resizing of patches with QE tool.
-
-02/01/2005
-SPoG
-- Added stippled hidden-line rendering for rotate/translate manipulators.
-- Refactored high-level camera/orthographic rendering functions.
-- Fixed failure to load models with back-slashes in path.
-- Improved peformance of doom3 lighting with large models.
-
-01/01/2005
-SPoG
-- Changed entity renderering to draw connections for culled entities.
-- Fixed runtime errors on shutdown after cycling between lighting/textured.
-- Fixed 'Cancel' button in modal dialogs behaving like 'OK' button.
-- Changed 'clip' brush filtering to use shader parameters instead of names.
-- Added rendering of origin-point for selected model entities.
-- Fixed doom3 light-interaction updates for model entities.
-
-31/12/2004
-SPoG
-- Removed menu-splitting functionality.
-- Refactored entity-class menu construction.
-- Replaced const_reference with ConstReference.
-- Renamed string_t to CopiedString.
-- Changed code using Str::Format and Str::operator+= to use StringOutputStream.
-- Refactored shortcut command parsing code.
-- Changed light entity rendering to show light_radius box only in doom3 config.
-- Added 2x overbrightening for doom3 lighting preview.
-
-16/12/2004
-SPoG
-- Changed default doom3 light_radius to 300.
-- Fixed initial value of doom3 light_center.
-- Reduced frequency of gui updates during map load.
-
-13/12/2004
-SPoG
-- Fixed crash in monitored-compile feedback dialog.
-
-12/12/2004
-SPoG
-- Added visualisation of halflife texture-projection format.
-- Added texture-lock for halflife texture-projection format.
-- Changed brush-texture-lock default to enabled for doom3 and halflife.
-
-11/12/2004
-SPoG
-- Refactored script-tokeniser.
-- Fixed doom3 lighting on ATI cards.
-- Added support for list attributes in entity definitions.
-- Added utf8-normalisation on text printed to console.
-- Fixed missing default_build_menu.xml in halflife game config.
-
-10/12/2004
-SPoG
-- Fixed missing commas in entity-inspector comments.
-- Added support for default values in entity-definitions.
-
-09/12/2004
-SPoG
-- Enabled doom3 realtime lighting preview.
-
-05/12/2004
-SPoG
-- Fixed gcc compile warnings in patch.cpp.
-- Added q1 and q2 support to linux installer.
-
-02/12/2004
-SPoG
-- Added highlighting of entity-list nodes that have selected descendants.
-
-29/11/2004
-SPoG
-- Fixed xy-window failing to update after map-load.
-
-28/11/2004
-SPoG
-- Fixed error on shutdown when game-select dialog is disabled.
-- Added surface/light-interaction debugging mode.
-- Added per-plane light-culling for brush faces.
-- Added support for bump shaders using 'blend' layer keyword.
-- Added support for light-shaders.
-- Fixed edge/border clamping on light-attenuation textures.
-- Added 'Lighting' camera render-mode for doom3 config.
-
-25/11/2004
-SPoG
-- Fixed right-click-menu on linux.
-
-13/11/2004
-SPoG
-- Changed light-entity to draw radii only when selected.
-
-07/11/2004
-SPoG
-- Fixed shortcuts for creating n-sided brush-prisms.
-
-19/10/2003
-SPoG
-- Fixed user-customisable shortcuts support.
-
-16/10/2003
-SPoG
-- Added restore-main-window call when a modal-dialog dialog-box is shown.
-
-13/10/2003
-Jamie Wilkinson
-- Fixed SConstruct cpu detection on Power Macintosh.
-- Added more verbose warning settings for gcc builds.
-SPoG
-- Changed buffered-text-input-stream API to not use magic EOF value.
-
-06/10/2004
-Jamie Wilkinson
-- Fixed debug-break on non-x86 platforms.
-
-05/10/2004
-SPoG
-- Fixed new doom3 entities not being given unique names.
-
-02/10/2004
-SPoG
-- Fixed autosave causing the main-window to jump to the front.
-- Fixed window-title when changing view direction in floating-windows layout.
-- Added status information to wait dialogs.
-- Changed map-save to overwrite/refresh files modified/deleted outside radiant.
-- Changed component selection in QE tool to treat near-equal points as one.
-- Added texture browser window to View menu.
-- Changed white overlay in camera-window to draw hidden lines in 75% grey.
-- Reduced point-size for vertex/edge/face handles by 2/3.
-
-25/09/2004
-SPoG
-- Added component-editing for curves on doom3 entities.
-- Added normalisation of translation for texture-lock on doom3 brushes.
-- Added update of surface inspector for texdef changes caused by texture-lock.
-- Changed floating-windows layout to centre all ortho views on center-xy-views.
-- Stopped autosave from saving unmodified maps after first-time load.
-Shamus
-- Textool improvements.
-
-21/09/2004
-Michael Schlueter
-- Changed file-chooser dialogs to use GtkFileChooser.
-
-20/09/2004
-SPoG
-- Added basic rendering for 'curve_CatmullRomSpline' on doom3 entities.
-
-19/09/2004
-SPoG
-- Added basic rendering for 'curve_Nurbs' on doom3 entities.
-
-18/09/2004
-SPoG
-- Added doom3 entity-definition editor_usage* key support.
-- Added doom3 entity-definition editor_* key info to entity-inspector comments.
-- Added specialised attribute-entry in entity-inspector for boolean attributes.
-- Fixed crash in find-brush when entering the index of a fixed-size entity.
-- Added support for rendering doom3 'targetN' -> 'name' entity connections.
-- Changed connect-entities to use 'targetN' and 'name' keys on doom3 entities.
-- Improved handling of brushes with near-duplicate planes.
-- Fixed crash in snap-to-grid on brushes with non-contributing faces.
-
-17/09/2004
-Michael Schlueter
-- Fixed gcc build errors.
-SPoG
-- Fixed stability problems with doom3 brush-entities.
-
-16/09/2004
-SPoG
-- Added automatic renaming of entity target/name keys for paste and import-map.
-
-13/09/2004
-SPoG
-- Fixed rotation/mirror toolbar buttons using wrong axes in certain situations.
-- Fixed incorrect filter settings display in filters menu.
-- Added automatic renaming of entity target/name keys when cloned.
-- Fixed quake2 support.
-
-12/09/2004
-SPoG
-- Added shortcut support for all menu commands and toolbar buttons.
-- Fixed patch shader-name saving for doom3 patches created by user.
-
-10/09/2004
-SPoG
-- Fixed patch-cap-endcap and patch-cap-reverse-endcap.
-
-09/09/2004
-SPoG
-- Fixed status-bar labels showing 'Label' at startup.
-- Fixed textures-menu grouping bug.
-- Fixed mirroring on brushes with doom3 plane-defs.
-
-08/09/2004
-SPoG
-- Changed patch-cap-selected to prompt for cap type only once.
-- Fixed infinite-loop in patch-cap-selected.
-- Changed autosave to only save if the map has changed since the last autosave.
-- Changed "file exists, overwrite?" to go back to the file-chooser if 'no' is selected.
-
-07/09/2004
-Michael Schlueter
-- Removed unused source files - qsysprintf, gtkfilesel.
-- Changed linux exectuable-path resolution to use '/proc/self/exe'.
-- Changed 'file exists, overwrite?' prompt to default to 'no'.
-
-06/09/2004
-SPoG
-- Fixed crash when handling duplicate shader definitions.
-- Fixed crash on startup after changing game-type (sp/mp).
-- Changed compute-axis-base to be more stable in degenerate cases.
-Michael Schlueter
-- Cleaned up loki_path stuff.
-Shamus
-- Added textool rotation manipulator.
-
-01/09/2004
-Michael Schlueter
-- Changed linux installer to copy *.game files from game-packs instead of generating them.
-
-29/08/2004
-SPoG
-- Moved doom3 shader parsing into a separate function.
-- Fixed saving of visibility of yz-side and xz-front in floating-windows layout.
-- Added inheritance of doom3 entityDef 'editor_* *' keys.
-- Added support for doom3 entityDef 'editor_* *' keys other than 'editor_var'.
-- Changed entity-inspector attributes panel to be scrollable.
-- Changed shaders module to load *.mtr for doom3 instead of using shaderlist.
-- Improved doom3 material parsing.
-- Fixed crash loading maps containing patches with large numbers of control points.
-- Changed face-selection in camera view to use polygon test.
-- Changed face-selection-mode rendering in camera view to cull back-faces.
-- Changed shaders module to use diffusemap on doom3 shaders with no qer_editorimage.
-
-28/08/2004
-SPoG
-- Fixed undefined-behaviour bug causing a crash with gcc optimisation.
-- Fixed opengl extension support on linux.
-- Added support for half-life .fgd entity-definitions.
-- Fixed loading of half-life maps with texture-names containing '{'.
-
-26/08/2004
-SPoG
-- Updated win32 install to use gtk+-2.4.7 and gtk-wimp-0.6.2.
-- Removed 'unknown model type: ""' and 'Texture load failed: ""' errors.
-- Changed pivot-point calculation to use entity-origin for fixed-size entities.
-- Fixed errors drawing selection-rectangle in floating-windows layout.
-- Fixed shortcuts becoming disabled in floating-windows layout.
-- Removed snap-to-integer on entity angle/angles/scale keys.
-- Fixed dragging of doom3 brush-entities.
-Michael Schlueter
-- Fixed gcc compiler error and warnings.
-- linux installer fixes.
-
-25/08/2004
-Michael Schlueter
-- Changed linux build system to copy '$GAME.game/*' for installer.
-- Changed linux installer to use 1.5's module set.
-- Removed optimisation from linux build to fix optimiser-related crash.
-- Added Doom3 support to linux installer.
-SPoG
-- Changed texdef export to not snap shift/rotate to integer.
-
-17/08/2004
-SPoG
-- Fixed texture-browser height update bug.
-- Changed texture-browser to show only the texture-set selected from the menu.
-- Fixed bug loading quake maps.
-
-16/08/2004
-SPoG
-- Fixed shortcuts for shift/rotate/scale-texture on patches.
-- Fixed patch-inspector rows/cols combos not being cleared between selections.
-- Changed entity/brush counts to use counters instead of polling every second.
-- Changed archivewad module to check lump types and ignore non-miptex files.
-- Added support for worldcraft/hammer half-life map format.
-
-15/08/2004
-SPoG
-- Added doom3 md5mesh loader.
-- Added support for doom3 entityDef 'model' key.
-- Changed textures-menu to show/load only shaders in the form 'textures/<menu-item>/*'.
-- Fixed texture-browser height calculation bug.
-- Added support for doom3 entityDef 'editor_var *' key.
-- Fixed support for patchDef3 subdivision settings.
-
-14/08/2004
-Chronos
-- Added doom3 light_radius and light_center rendering.
-SPoG
-- Disabled default-shaders for doom3.
-- Added one-click dragging of vertices/edges/faces on brushes and patches.
-- Fixed detail flag being lost on brush-clone or save-as.
-
-12/08/2004
-SPoG
-- Fixed workzone being invalidated when a brush is deleted.
-- Fixed pivot updates when switching from translate-tool to rotate-tool.
-- Fixed crash in misc_model.
-- Changed file_dialog to show '*.*' when pattern is not specified.
-- Added undo support for patch-inspector XYZUV tweaking.
-- Removed 'Apply'/'Done' buttons from patch-inspector.
-
-11/08/2004
-redfella
-- Converted RTCW entities.def to xml format.
-SPoG
-- Added support for "name" key for doom3 entities.
-
-10/08/2004
-SPoG
-- Added support for loading text files from VFS archives.
-
-09/08/2004
-SPoG
-- Changed .map writer to always use decimal notation for floats.
-- Added filtering of monster_clip/full_clip/player_clip.
-- Added support for inheritance in doom3 entity-definitions.
-- Fixed doom3 patchDef2 material-name import/export.
-
-06/08/2004
-SPoG
-- Doom3 support:
-  - Map load/save.
-  - Materials parsing.
-  - entityDef parsing.
-  - Fixed brush-primitives texturing bug.
-  - Added texture-lock for brush-primitives texturing on all transforms.
-  - Added support for model/rotation/origin keys on func_ entities.
-- Added DDS image module.
-
-03/08/2004
-SPoG
-- Fixed copy/paste copying all brushes of an entity when only one is selected.
-- Fixed discrete-camera-movement shortcuts becoming disabled after using freemove-camera.
-
-27/07/2004
-Shallow
-- Converted ET entities.def to xml format.
-
-26/07/2004
-SPoG
-- Fixed SI when not in face-selection mode.
-- Changed patch-create-prefab to use current workzone.
-- Changed engine attribute to be optional in game-description.
-
-24/07/2004
-SPoG
-- Changed module server to support wildcard modules.
-- Cleaned up docs/developer, added README.
-- Removed old TODO.
-
-23/07/2004
-Shamus
-- Initial version of textool.
-MindLink
-- Fixed const bug for vs.net 2005 compiler.
-
-22/07/2004
-SPoG
-- Fixed copy/paste and export-selected failing to export stuff.
-
-19/07/2004
-SPoG
-- Updated win32 setup scripts for q1 entity definitions.
-
-18/07/2004
-SPoG
-- Updated win32 setup scripts.
-- Fixed bug loading 8-bit bmp with <256 palette entries.
-- Added support for loading textures from arbitrary locations.
-- Changed shaders module to load notex/shadernotex from bitmaps/ in .bmp format.
-- Fixed bugs in brush-primitives texdef code.
-
-17/07/2004
-SPoG
-- Added STV:EF support to win32 installer.
-- Moved hardcoded game-specific configuration stuff into .game files.
-
-16/07/2004
-SPoG
-- Fixed crash bug in brush edge/vertex/face selection.
-
-15/07/2004
-SPoG
-- Moved .def files from <enginepath>/<basegame>/scripts/ to <radiantpath>/<gamefilename>/<game>/.
-- Changed entity inspector UI to be driven by entities xml.
-
-14/07/2004
-SPoG
-- Fixed map load/save in brusb-primitives mode.
-- Added files required to run in brush-primitives mode.
-- Added support for changing engine-path while a map is loaded.
-
-
-11/07/2004
-SPoG
-- Changed entity inspector to support custom UI for each entity-class.
-
-10/07/2004
-SPoG
-- Added support for experimental xml version of .def format.
-- Rewrote token parser.
-- Rewrote .def parser.
-- Fixed failure to read show-workzone preference.
-- Refactored quake3 entities module.
-
-03/07/2004
-SPoG
-- Changed QE-style Drag tool to move as well as resize.
-- Fixed shortcuts becoming disabled.
-- Fixed loading file types with upper-case extensions.
-
-30/06/2004
-AcidDeath
-- Added support for plugin submenus.
-
-27/06/2004
-SPoG
-- Added build-menu-command editing.
-- Fixed texture-object reshuffle caused by changing gamma.
-- Refactored vfs/shaders/renderstates/eclass/texturemenu unrealise/realise systems.
-
-26/06/2004
-SPoG
-- Added printf-formatting support to output streams.
-- Added error/warning printing to xml parser.
-- Changed build-menu xml format to allow easier editing.
-- Added sample plugin.
-
-25/06/2004
-SPoG
-- Changed paste and import-map to select pasted/imported entities and world brushes.
-
-24/06/2004
-SPoG
-- Changed create-entity API to use eclass instead of classname.
-- Changed nodes with unknown entity types to use a group-entity if the node has children.
-
-18/06/2004
-SPoG
-- Changed image-loaders interface to use a file object instead of VFS.
-- Changed model-loader interface to support in-place model reloading.
-- Changed picomodel-loader module to support configuration of suppported model types in synapse.config.
-- PicoModel: added support for loading models from an abstract input stream.
-
-14/06/2004
-SPoG
-- Refactored texture browser.
-- Removed GLWindow.
-- Fixed mousewheel movement in camera window.
-
-13/06/2004
-SPoG
-- Added load-entire-wad from textures menu in Quake/HL mode.
-- Fixed bug with writing negative integers to .map format.
-- Fixed texture-browser hide-unused to show only in-use shaders. 
-- Fixed texture-browser scrollbar positioning and origin-clamping.
-- Fixed prompting to save unchanged new maps.
-- Changed unsaved-changes message box default to "Yes, save" instead of "OK, don't save".
-- Changed all message boxes to appear centrally.
-- Removed minimize/maximize buttons from all message boxes.
-
-12/06/2004
-SPoG
-- Disabled shortcut keys during drags.
-- Fixed window updates for edge/vertex multi-selection.
-- Added apply/cancel on enter/escape for texture-browser filter entry.
-- Changed undo system to use explicit start/finish pair to specify undoable operations.
-- Changed undo system to print undoable command after command completion instead of before.
-- Added printing of movement parameters for translate/rotate manipulator drags.
-- Changed brush-subtract to not delete the selection after subtracting.
-- Fixed texture browser to not display textures if only in-use by nodes in the undo-queue.
-- Fixed another workzone-update performance issue causing area-selection to be slow.
-- Added code to brush build-B-Rep to handle duplicate edges.
-
-10/06/2004
-SPoG
-- Added lazy evaluation of local->world transforms and world-space AABBs.
-- Added shortcut key for translate mode, default 'W'.
-- Added toolbar buttons for edge/face/vertex modes.
-- Changed Escape shortcut to deselect-components if components are selected.
-
-02/06/2004
-SPoG
-- Fixed performance bug with workzone updates not being lazily evaluated.
-- Fixed brush edge-graph bug by removing degenerate winding edges.
-
-01/06/2004
-SPoG
-- Added mode information to status bar.
-- Added console feedback describing undoable commands executed.
-- Fixed assertion failures on updating degenerate edge/vertex selections.
-- Fixed detail brushes turning structural when clipped.
-
-31/05/2004
-SPoG
-- Added support for more than one edge/vertex selected per brush.
-
-29/05/2004
-SPoG
-- Refactored groupdialog - decoupled notebook from console/textures/entity pages.
-- Fixed crash in patch tesselator.
-- Fixed floating windows startup crash.
-- Fixed null texture name for patches.
-
-28/05/2004
-SPoG
-- Hide arrows on translate manipulator when obscured by square part.
-- Workaround for main window not being brought to front when a floating window is closed.
-- Fixed rendering of selected components of degenerate brush faces.
-- Fixed double typedef in picomodel.
-- Fixed bug in allocator stuff.
-- Fixed up clipper tool button state.
-- Added workzone updates when selection bounds change.
-- Fixed transient setting on floating inspector windows.
-
-27/05/2004
-Tr3b
-- Fixed gcc build errors.
-SPoG
-- Fixed crash bug in game selection dialog.
-
-26/05/2004
-SPoG
-- Cleaned up project settings.
-- Changed autosave/snapshots to only save modified maps.
-- Refactored build menu.
-
-23/05/2004
-SPoG
-- Fixed minor picomodel ase loader smoothing-groups bug.
-
-19/05/2004
-SPoG
-- Allocator system improvements, fixed warnings
-
-18/05/2004
-SPoG
-- PicoModel: added support for per-vertex smoothing-group, used in generation of normals.
-- PicoModel ASE loader: added support for per-face 'MESH_SMOOTHING' id.
-- PicoModel: changed normal generation code to create smooth normals across texcoord/colour discontinuities.
-- Fixed cosmetic menu bug.
-- Fixed file handle leak in tga loader.
-- Added experimental allocator system.
-
-15/05/2004
-Tr3b
-- Fixed gcc build errors.
-
-11/05/2004
-SPoG
-- Fixed version.h custom build step on win32
-- Refactored preferences dialog to eliminate dependencies on other modules.
-- Redesigned preferences dialog ui layout.
-
-06/05/2004
-SPoG
-- Refactored texture browser.
-
-05/05/2004
-SPoG
-- Upgraded win32 gtk2 version to 2.4.1.
-- Migrated from GtkCombo to GtkComboBox.
-- Texture browser improvements.
-- Fixed malloc/free mismatch bug.
-
-05/05/2004
-SPoG
-- Refactored surface inspector and texture browser.
-
-02/05/2004
-Nurail
-- Added imageq2 module with support for quake2 and heretic2 texture formats: wal, m8, m32.
-
-30/04/2004
-SPoG
-- Changed texture window not to auto-scroll when selecting faces.
-- Changed surface inspector to apply shader seperately from shift/scale/rotate.
-- Changed selected face tracking to use separate selection list.
-
-26/04/2004
-SPoG
-- Added per-file change tracking - only modified (unsaved) files are saved by SaveMap().
-
-18/04/2004
-SPoG
-- Fixed texture-increment-matches-grid.
-- Changed selecting a texture to only change the shader on the selected brushes.
-- Changed 'Axial' button in surface inspector to reset the texdef for selected brushes/faces.
-- Removed MAX_TEXTUREDIRS limit.
-
-11/04/2004
-SPoG
-- OS library module added to wrap calls to rename/unlink/access/stat.
-- OpenGL-view selection tests constrained to current window.
-- Cleaned up OpenURL.
-- Added jk2 and sof2 support to win32 installer.
-
-09/04/2004
-TTimo
-- update the OSX setup / .info generation code
-
-08/04/2004
-SPoG
-- Added integer quantisation for brush edge/vertex drags to fix FP-drift on planes.
-TTimo
-- fix for scons 0.95
-- re-enable Python >= 2.1 version check
-- OSX 10.3: remove obsolete dlsym_auto_underscore (bug #920)
-- OSX: disable q2 tools build (broken thread code)
-
-07/04/2004
-SPoG
-- Moved profile.cpp into a separate static library.
-
-06/04/2004
-SPoG
-- Refactored preferences to be more modular.
-- Fixed preferences being corrupted if a crash occurs during preference saving.
-- Refactored window position saving.
-- Fixed bug in radio button creation in preferences dialog.
-
-24/03/2004
-SPoG
-- Changed surface inspector to unfocus after pressing escape or return, to enable shortcuts.
-- Added refresh of surface inspector for shift/scale/rotate-texdef shortcuts.
-- Fixed bug causing some operations to be applied twice.
-
-21/03/2004
-SPoG
-- Added depth-test and normalisation for translate-manipulator rendering.
-- Added basic clipper-preview rendering.
-
-18/03/2004
-SPoG
-- Added maya-style arrow-heads to translate manipulator.
-- Changed square part of translate manipulator to be viewplane-oriented.
-- Changed square part of translate manipulator to take priority for selection.
-
-15/03/2004
-SPoG
-- Added recalculation of pivot-point when grid size changes.
-- Changed win32 SHGetFolderPath to link with shfolder.lib instead of shell32.lib.
-- Fixed failure to recover brushes from an invalid state.
-
-14/03/2004
-SPoG
-- Improved event handling to make manipulator-dragging smoother in complex scenes.
-- Refactored camera window camera-movement handling.
-
-06/03/2004
-SPoG
-- Fixed vertex/edge undo failing to update selected-vertex position.
-
-29/02/2004
-SPoG
-- Re-enabled next-xy-view in floating windows mode.
-- Reinstated light-radius rendering.
-- Added Wolfenstein support to win32 setup.
-
-24/02/2004
-SPoG
-- Changed create-brush-prism to use correct dimension for prism radius.
-- Changed freelook selection to use window-centre position.
-
-22/02/2004
-SPoG
-- Optimised undo for adding/removing scenegraph nodes.
-- Changed entity-list view to sort the tree by name.
-
-18/02/2004
-SPoG
-- Moved default shaderlist to <AppPath>/<GameFileName>/<GameName>/default_shaderlist.txt
-- Moved user shaderlist to <AppData>/<Version>/<GameFileName>/<GameName>/shaderlist.txt
-
-11/02/2004
-SPoG
-- Refactored clipboard copy/paste code to allow re-use.
-
-10/02/2004
-SPoG
-- Fixed false-positive-intersection bug in CSG subtract algorithm.
-
-07/02/2004
-SPoG
-- SceneGraph: Refactored per-instance functionality.
-- Fixed intermittent culling bug caused by bad bounding boxes.
-- Fixed missing ToggleCubicClip shortcut.
-- Removed modal buttons from Surface Inspector.
-- Changed Surface Inspector keys:
-  - Escape: revert not-yet-committed values to previous state.
-  - Enter: commit not-yet-committed values immediatly.
-- Changed Surface Inspector to update when selection changes.
-
-31/01/2004
-SPoG
-- Cleaned up functional.h template usage with typedefs.
-- Fixed autosave path.
-- Added q1 component to installer.
-- Added radiant_manual component to installer.
-- Added q3-example-maps package to installer.
-
-29/01/2004
-SPoG
-- Added error reporting for module system initialisation failure.
-- Added MSI package creation tools in setup/win32.
-  note: requires MSI SDK binaries in http://zerowing.idsoftware.com/radiant-files/msi/msitools.zip
-- Added initial version of scripts to build basic win32 setup.
-
-26/01/2004
-SPoG
-- Added storing EnginePath for each game in local.pref.
-- Added EnginePath editing to prefs dialog.
-- Added vfs shutdown/init when gamename changes.
-- Added vfs shutdown/init when enginepath changes.
-
-25/01/2004
-SPoG
-- Fixed filtering updates.
-- Moved default bsp menu to <AppPath>/<GameFileName>/default_build_menu.xml
-- Moved user bsp menu to <AppData>/<Version>/<GameFileName>/build_menu.xml
-- Moved synapse.config to <AppPath>/<GameFileName>/synapse.config
-- Moved game-specific .xlink files to <AppPath>/<GameFileName>/*.xlink
-
-25/01/2004
-SPoG
-- Redesigned filter system:
-  - Filtered status updated when filterable attributes change.
-  - Supports per-brush-face filtering.
-- Removed long-dead project-settings stuff:
-  - Moved gamemode and gamename storage into local.pref temporarily.
-  - Moved bsp commands over to a new format, disabled gui editing for now.
-
-20/01/2004
-SPoG
-- Changed win32 Application Data path lookup to use win32 API instead of getenv.
-
-14/01/2004
-SPoG
-- Fixed main menu mnemonics.
-- Fixed crash on exit after viewing pointfile.
-
-13/01/2004
-SPoG
-- Fixed not always resetting 
-component-mode when selection is cleared.
-
-11/01/2004
-Tr3B
-- Added parse/write support for BrushDef3 and PatchDef3.
-  Requires editing synapse.config to enable.
-SPoG
-- Rearranged menus:
-  File = new/open/import/export
-  Edit = manipulate scene hierarchy and selection
-  View = toggle entityinspector/entitylist/surfaceinspector/camera/xy
-    edit camera/xy parameters
-    filters/hideshow/region
-  Modify = transform scene elements
-  Build = bsp menu
-- Fixed Brush-Primitives support:
-  Requires editing synapse.config to enable.
-  Supports load/save of BP mapfiles, and editing BP texdefs in surface inspector
-  (Not yet possible to convert between formats).
-  
-15/12/2003
-SPoG
-- Changed user-prefs to be stored in user-profile directory on win32.
-
-14/12/2003
-SPoG
-- Fixed entitylist window visibility tracking.
-- Implemented find/replace-shader for patches.
-- Changed get-texture-from-selected to update find/replace-shader dialog.
-- Implemented reparent-selected for more than one selected node.
-- Added checks to stop assignment of invalid texture names.
-- Fixed uninitialised texture-compression setting.
-- Fixed bsp menu.
-
-------- spog_branch merged to trunk
-
-10/12/2003
-SPoG
-- Ported imagehl module.
-- Ported imagepng module.
-
-03/12/2003
-SPoG
-- Changed brush winding generation to use use double precision planes.
-- Fixed tracking of modifier key state.
-
-29/11/2003
-SPoG
-- Replaced mathlib with c++ vector/matrix library.
-- Added expression-templates for common vector/matrix operations.
-
-21/11/2003
-SPoG
-- Refactored component-selection stuff.
-- Ported m4x4_t library to c++ Matrix4.
-
-16/11/2003
-SPoG
-- Changed shortcuts.ini to be written automatically.
-- Moved more prefs into specific modules.
-- Changed c++ NULL usage to 0 for maximum portability.
-
-11/11/2003
-SPoG
-- #include cleanup.
-- Added debug output/assert for module initialisation.
-
-09/11/2003
-SPoG
-- Refactored status bar stuff.
-- Refactored window updates to use closures.
-- General cleanup and refactoring.
-
-08/11/2003
-SPoG
-- Increased priority of window redraw events.
-- Ported model module to new module system.
-
-07/11/2003
-SPoG
-- Refactored window updates.
-
-05/11/2003
-SPoG
-- Changed menubar/toolbars to be non-detachable.
-- Fixed empty-undos created when left-clicking in XY window.
-- Refactored camera modelview/projection matrix updates. 
-- Moved application-specific code out of mainframe.cpp.
-- Reinstated brush/entity count in statusbar.
-
-04/11/2003
-SPoG
-- Reinstated instant status-bar updates.
-
-30/10/2003
-SPoG
-- Fixed crosshair cursor in clipper mode.
-
-29/10/2003
-SPoG
-- Changed camera to maintain valid projection/modelview matrices.
-- Moved manipulator-transform update from frustum class to selection system.
-- Removed frame-rate dependency in 3d-window freelook.
-
-27/10/2003
-SPoG
-- Smoothed out xy-window mouse-chasing.
-- Changed mouse-chasing to occur 16 pixels inside the window edges.
-- Changed xy-window to maintain valid projection/modelview matrices.
-- Fixed invalid workzone generated when deselecting with no selection.
-
-26/10/2003
-SPoG
-- Ported changes from trunk between rev 3818 and rev 4036.
-
-25/10/2003
-SPoG
-- Refactored xy-window mouse event handling.
-
-22/10/2003
-SPoG
-- Fixed freelook focus-out event.
-- Changed selection mouse event handling to use modifiers on button-release.
-
-21/10/2003
-SPoG
-- Refactored all mouse event handling for camera window.
-- Changed menus/toolbars/accelerators to use anonymous closures.
-
-20/10/2003
-SPoG
-- Fixed get-pointer-in-screen-coordinates on win32.
-- Changed patch prefs to use preference-system module.
-- Fixed selection of side-on faces.
-- Changed brush rendering to avoid glPushClientAttrib - workaround for ATI driver issue.
-
-19/10/2003
-SPoG
-- Changed VFS directory initialisation to occur after module initialisation.
-- Changed load-preferences to occur after module initialisation.
-- Added preference-system module.
-- Changed undo prefs to use preference-system module.
-- Restored splash screen with non-intrusive behaviour.
-- Cleaned up main-toolbar creation.
-- Fixed floating windows behaviour when main window is minimised.
-- Changed shader-list parsing to use new script tokeniser.
-- Changed deprecated code using GtkPixmap to use GtkImage.
-- Removed bitmap-loading from core.
-- Removed pc-speaker beep on map-save.
-
-17/10/2003
-SPoG
-- Fixed crash when trying to undo on an empty undo queue.
-- Refactored gtkdlgs, using helper functions to create common widgets.
-- Changed Dialog class to use std::list for data.
-
-13/10/2003
-SPoG
-- Refactored entity inspector.
-- Removed miscellaneous unused functions.
-- Refactored qe3 header.
-- Moved texture-window preferences into texwindow.cpp.
-
-12/10/2003
-SPoG
-- Moved layout-mode dependant code into main-frame creation.
-- Replaced prefs system with new import/export system.
-- Fixed gcc3.3 build errors.
-
-11/10/2003
-SPoG
-- Moved unnecessary methods from MainFrame into free functions.
-- Removed unsupported toolbar buttons and menu items.
-- Changed misc->gamma to not require restart.
-- Fixed unmaximised window-size when loading main window maximised.
-- Fixed saving of rotate increment preference.
-
-10/10/2003
-SPoG
-- Fixed keyboard shortcuts intercepting input to texture-subsets text-entry.
-
-09/10/2003
-SPoG
-- Fixed gcc3 build errors, compiled and tested on linux.
-
-08/10/2003
-SPoG
-- Fixed brush snap-to-grid creating huge coordinate values.
-- Fixed minor bug in selection menu.
-
-07/10/2003
-SPoG
-- Cleaned up MainFrame.
-- Added quantisation of plane pts when dragging.
-- Fixed create-empty-brush bug.
-
-06/10/2003
-SPoG
-- Moved control of camera keyboard-accelerators into camera window module.
-
-05/10/2003
-SPoG
-- Separated keyboard-accelerators from menu items, using functors.
-- Completed factoring out HandleCommand.
-
-04/10/2003
-SPoG
-- Changed 4-way-split mode to automatically reposition separators when window size changes.
-- Fixed gtk error in floating-entity/textures/console window.
-- Fixed position of console horizontal pane separator.
-
-03/10/2003
-SPoG
-- Work-in-progress factoring out HandleCommand.
-
-02/10/2003
-SPoG
-- Fixed pink icons on main window on win32.
-- Replaced g_bIgnoreCommands with signal block/unblock.
-- Refactored MainFrame startup.
-
-01/10/2003
-SPoG
-- Fixed entity-window redraw on selection change.
-- Moved control over VFS init/shutdown to module system.
-- Fixed failure to release translucency render-states.
-- Added support for realise/unrealise of all opengl texture objects.
-- Refactored startup/shutdown logic.
-  Changed quit commands to do nothing but call gtk_main_quit().
-  Added code after gtk_main() to destroy stuff.
-- Changed 25ms timeout-handler to an idle-handler for window updates.
-  (reduces redraw-request response time on fast machines)
-- Moved gl-shutdown control to glwidget.
-  Textures are realised/unrealised when the shared context is created/destroyed.
-- Fixed lack of a valid gl context when unrealising gl textures.
-
-30/09/2003
-SPoG
-- Added support for translucent entity rendering.
-
-29/09/2003
-SPoG
-- Changed all global modules to use GlobalModule helper templates.
-- Ported qgl.c to c++.
-- Changed win32 project to dynamic-link with opengl32.lib.
-
-28/09/2003
-SPoG
-- Added new experimental xml preference import/export system.
-- Refactored dialog base class:
-  Moved common dialog-element-creation code into helper functions.
-  Changed UpdateData to use per-element callback functions.
-- Refactored preferences dialog.
-
-26/09/2003
-SPoG
-- Reversed winding order for circle primitives.
-
-25/09/2003
-SPoG
-- Fixed slow selection response in large maps.
-
-21/09/2003
-SPoG
-- Added sharing of global modules within a client.
-- Added quake map module and wal image module.
-- Ported mip image module and hlw image module.
-- Cleaned up imagehl module.
-- Fixed crash in pcx image module.
-- Rewrote md3 model module.
-- Ported mdl, md2 and mdc model modules.
-- Added filtering of q1/q2 clip brushes.
-- Added ati-crash-workaround rendering path.
-- Upgraded to gtk+-2.2.4 on win32:
-  Fixed capslock affecting shortcut-keys.
-- Upgraded to gtkglext-1.0.4 on win32.
-- Fixed copy/paste.
-- Added shortcut-key support to entity treeview.
-
-17/09/2003
-SPoG
-- Fixed failure to call vfsFreeFile on an empty buffer.
-- Fixed calling convention for dlls in new module system.
-- Changed map.cpp to support maps without a worldspawn entity.
-- Fixed crash on attempting to clone a map root.
-- Added filter-update calls after loading or cloning stuff.
-- Fixed reference cache failing to save a file.
-
-16/09/2003
-SPoG
-- Refactored client-side module system code for direct module access.
-- Changed shaders, vfs, model, brush, patch and entity module interfaces
-  to use abstract base class.
-- Removed unused functions from shaders and vfs interfaces.
-
-15/09/2003
-SPoG
-- Removed synapse dependencies for win32 makefiles.
-- Added find-first-module-of-type helper function.
-
-14/09/2003
-SPoG
-- Added new lightweight module system:
-  Initialises each module the first time it is requested.
-  Does not allow configurations with cyclic runtime dependencies.
-  Provides templates for simple type-safe client-side implementation.
-  Requires no client-side linkage.
-- Split radiant API into multiple APIs:
-  core, textures, scenegraph, selection, renderstate, filters, filetypes.
-- Ported radiant, core, mapq3, mapxml, md3model, entity, shaders, image,
-  vfspk3, archivewad, archivepak, archivezip to new module system.
-
-11/09/2003
-SPoG
-- Removed edge and vertex integer-snapping during selection.
-
-10/09/2003
-SPoG
-- Replaced map in referencecache.cpp with a hashtable.
-- Changed ReferenceCache interface to take a path string,
-  which can be either absolute or relative.
-
-08/09/2003
-SPoG
-- Cleaned up qertypes.h - split into multiple files.
-- Moved texdef stuff into itexdef.h.
-- Fixed shutdown destruction order bug. 
-
-07/09/2003
-SPoG
-- Refactored texwindow.cpp.
-  Moved texture management code into textures.cpp.
-  Added textures api.
-  Replaced globals from texwindow.h with accessor functions.
-- Cleaned up shaders module.
-  Removed color-shader stuff.
-  Rewrote shader-activation logic to use textures API.
-  Removed appshaders API.
-- Refactored shutdown logic.
-  Moved non-mainframe shutdown stuff into Radiant_Shutdown().
-  Added deferred render-state realisation.
-- Fixed failure to create gl contexts in 16-bit mode for latest nvidia drivers.
-- Changed hashtable template to use traits parameter
-  for case-insensitive hasher and keyequal functions.
-- Removed unused functions from qerplugin API.
-
-02/09/2003
-SPoG
-- Refactored code to remove global-object accesses:
-  Passing global objects as parameters to functions.
-- Refactored texwindow.
-- Moved synapse server out of pluginmanager.
-  Changed pluginmanager to handle nothing but IPlugin stuff.
-
-01/09/2003
-SPoG
-- Refactored scenelib.h, split into multiple files.
-- Refactored #includes related to scenelib.h.
-- Refactored preferences for xywindow and camwindow.
-- Refactored references to g_pParentWnd in xywindow and camwindow.
-
-30/08/2003
-SPoG
-- Ported changes from trunk since 17/08/2003.
-- Ported all changes from bug800-spog_branch (vfs rewrite and q1 support).
-
-29/08/2003
-SPoG
-- Refactored component-selection stuff.
-- Fixed selection-tracking bug in patches.
-
-28/08/2003
-SPoG
-- Added support for line-strips to Selectors.
-- Fixed selection for entity treeview.
-- Refactored external-resource loading.
-
-20/08/2003
-SPoG
-- Fixed snap-to-grid in edge and vertex modes.
-- Added a default model to use when a model load fails.
-
-19/08/2003
-SPoG
-- Changed snap-to-grid to vastly reduce the possibility of creating an invalid plane.
-
-17/08/2003
-SPoG
-- Ported changes from trunk since 01/08/2003.
-
-12/08/2003
-SPoG
-- Changed entity key/value tracking to only track keys already added to the entity.
-- Fixed bug causing undo system to track scene changes during a queue-flush operation.
-
-12/08/2003
-SPoG
-- Fixed bug in project settings bsp-commands display.
-- Fixed empty undos being created by rotation buttons.
-- Fixed rotation pivot for rotation buttons.
-
-09/08/2003
-SPoG
-- Added property svn:eol-style=native to all text files.
-- Added property evn:eol-style=CRLF to all dsp and dsw files.
-- Partially ported bobtoolz to use new spog_branch module APIs.
-- Removed Sys_UpdateScene.
-- Added Map_Name() for access to currentmap variable.
-- Added initial drag-n-drop support for graph tree-model.
-
-01/08/2003
-SPoG
-- Fixed uninitialised refcount in entity key class.
-- Fixed memory leak in shader parsing.
-- Added reference-counting holder for worldspawn node.
-- Moved string class and utilities into a new header in libs dir.
-- Fixed external-file-resource cache to use case-insensitive name compare on win32.
-- Fixed shaders to use case-insensitive name compare.
-- Fixed shader module to display SHADER_NOT_FOUND when appropriate.
-- Changed the default texture name to "NULL" instead of SHADER_NOT_FOUND.
-- Changed move-into-entity to perform parent-selection-to-last-selected-node.
-- Added a new implementation of GtkTreeModel operating directly on the scenegraph.
-- Fixed disable-screen-updates to queue update requests instead of ignoring them.
-- Merged from trunk (tag head-cvs2svn-2).
-
-22/07/2003
-SPoG
-- Changed scale/flip-selection to use the manipulator as a pivot point.
-- Added OnShutdown callback for CSynapseClient, used in entity module.
-- Fixed console updates when loading maps/models.
-
-20/07/2003
-SPoG
-- Added renderer support for qer_alphatest and qer_cull.
-- Merged 'picomodule' module into 'model' module.
-- Added rendering of area-selection rectangle.
-
-19/07/2003
-SPoG
-- Merged from trunk.
-
-18/07/2003
-SPoG
-- Disabled deleting classname key in entity inspector window.
-- Cleaned up some stuff in selection system.
-- Added basic versions of std::mem_fun and std::bind1st to function-object library.
-
-10/07/2003
-SPoG
-- Implemented connect-entities.
-
-09/07/2003
-SPoG
-- Completed local-space rotation manipulator.
-- Fixed cloning objects within a misc_model subgraph.
-- Fixed crash bug in loading certain models.
-
-06/07/2003
-SPoG
-- Added function-object library header, similar to boost::function.
-- Changed undo system to improve performance.
-- Refactored entity inspector implementation.
-
-22/06/2003
-SPoG
-- Refactored selection observing stuff.
-- Changed shader parsing to use new tokeniser.
-- Changed implementation of entities to use generic container.
-- Refactored entity wrapper system.
-- Fixed undo on delete/reset entity keys.
-
-21/06/2003
-SPoG
-- Added rendering of target/targetname connection lines.
-- Moved entity and eclass stuff out of qertypes.h into ientity and ieclass.
-- Refactored entity_t to hide it behind Entity interface.
-- Removed global project settings entity.
-- Cleaned up bsp-command editing in project settings dialog.
-
-17/06/2003
-SPoG
-- Fixed back-face-culling for selections by working in screen-space.
-
-16/06/2003
-SPoG
-- Added workaround for nvidia driver opengl vertex arrays bug.
-
-15/06/2003
-SPoG
-- Refactored Patch implementation.
-- Refactored scene graph system to allow multiple graph instances.
-
-13/06/2003
-SPoG
-- Added snap-selected-components-to-grid for faces edges and vertices.
-
-11/06/2003
-SPoG
-- Improved normal-quantisation code.
-
-10/06/2003
-SPoG
-- Changed renderer vertex types to be struct instead of typedef'd array.
-- Added experimental quantisation of normals.
-
-05/06/2003
-SPoG
-- Fixed intermittent crash in face-fit-texture.
-- Changed patch rendering to display components only in vertex mode.
-
-02/06/2003
-SPoG
-- Added nameable interface for scene graph nodes.
-- Fixed undo for set-detail and set-structural.
-- Added rendering of arrow for angled entities.
-
-01/06/2003
-SPoG
-- Fixed handling of invalid planes during brush b-rep build.
-- Refactored brush copy-construction/assignment.
-- Fixed lack of rebuild after removing empty faces.
-- Added lightjunior entity display.
-- Fixed display of spawnflags/info for selected entity.
-- Fixed update of entity window on setting spawnflags.
-- Fixed botclip filtering.
-- Fixed uninitialised alpha channel on jpg images by ignoring alpha.
-
-31/05/2003
-SPoG
-- Cleaned up undo calls in brush and patch implementation.
-- Changed brush implementation to defer rebuilds until needed.
-- Fixed undo for find/replace shader.
-- Refactored brush implementation, removed empty-face list.
-- Fixed crash on loading unrecognised entities containing brushes.
-- Fixed crashes in renderer caused by state-stack underflow.
-- Fixed handling of invalid and duplicate planes during brush editing.
-- Fixed failure to save brush faces during save-as.
-- Refactored brush data members.
-
-28/05/2003
-SPoG
-- Fixed crash on selecting stuff from entity list window.
-
-27/05/2003
-SPoG
-- Fixed window title after save-as.
-
-22/05/2003
-SPoG
-- Refactored selection system interface slightly.
-- Removed old brushwrapper stuff.
-- Fixed clipper-split-selection to keep both parts selected.
-
-21/05/2003
-SPoG
-- Added select-faces-by-shader.
-- Fixed find/replace-shader.
-
-19/05/2003
-SPoG
-- Fixed rotation on misc_model.
-
-13/05/2003
-SPoG
-- Fixed lack of undo on create-n-sided-brush.
-
-29/04/2003
-SPoG
-- Fixed per-face find/replace and per-face nudge rotation.
-
-25/04/2003
-SPoG
-- Fixed find-brush.
-- Changed rotation buttons to use perfect precision for 90-degree rotations.
-
-24/04/2003
-SPoG
-- Added find-dir-for-relative-filename and find-dir-for-absolute-filename to vfs.
-- Changed resource manager to handle per-mod resources using vfs.
-- Changed resource manager to allow resources with absolute paths.
-- Fixed selection-test behaving like an ellipse instead of a rectangle.
-
-23/04/2003
-SPoG
-- Changed selection test to choose closest-to-cursor over closest-to-camera.
-
-22/04/2003
-SPoG
-- Fixed reference counting on shaders loaded from a texture directory.
-- Fixed show-in-use and show-all shaders.
-- Fixed undo for patch-set-shader.
-- Changed shaders module to use STL map container instead of CShaderArray.
-- Fixed SelectAllOfType for entities and patches.
-- Cleaned up unused functions in shaders API.
-- Decoupled selecting a texture in texture window from applying a texture to selection.
-
-21/04/2003
-SPoG
-- Fixed memory leaks in image loaders, texdef_t, csg subtract, picomodel module.
-- Fixed uninitialised memory references in renderer, texdef_t, eclass loader, undo system.
-- Refactored tga loader.
-- Cleaned up image module, enabled pcx and bmp loaders.
-
-17/04/2003
-SPoG
-- Fixed shift-texture on selected brush faces.
-- Changed brush b-rep algorithm to have higher tolerance for similar planes.
-- Changed brush b-rep algorithm to always produce a valid connectivity graph.
-- Added setting/getting shader for patches.
-
-16/04/2003
-SPoG
-- Fixed tracking of in-use shaders (though undo queue still keeps shader references).
-- Changed brush faces to store state in undo-system cleanly.
-- Fixed flush & reload shaders and sleep/wake.
-- Ensured that shaders are never leaked.
-- Fixed bool conversion warnings.
-
-15/04/2003
-SPoG
-- Added clamping of planepts on export to nearest 65536th of 1 unit.
-- Changed m4x4 rotation functions to use double-precision for angles in radians.
-- Changed m4x4 quaternion rotation to use double-precision internally.
-- Changed float printing to use %g instead of %f (strips trailing zeros).
-
-13/04/2003
-SPoG
-- Fixed brush import failing to update bounding boxes.
-
-11/04/2003
-SPoG
-- Refactored Brush class into Brush, BrushInstance and BrushNode.
-- Fixed various flaws stopping brush b-rep algorithm from being 100% reliable.
-
-02/04/2003
-SPoG
-- Changed manipulator to move to position of selected brush components.
-
-01/04/2003
-SPoG
-- Fixed xml parser failing to resolve predefined entities.
-
-31/03/2003
-SPoG
-- Fixed asserts in brush manipulation when creating invalid brushes.
-- Removed automatic update of current texdef.
-- Added Get Texture and Set Texture to textures menu.
-
-29/03/2003
-SPoG
-- Fixed array template failing to free zero-sized allocations.
-- Changed clipper mode to behave as a component-editing-mode.
-- Removed right-click-to-drop-clip-point - use X and leftclick instead.
-
-28/03/2003
-SPoG
-- Changed scene graph to sort objects in ascending order of creation time.
-
-27/03/2003
-SPoG
-- Fixed bug in clone-selection causing only first selected brush to be cloned.
-- Optimised select-all for brush/patch components.
-- Changed edge/face/vertex toggles to toggle correctly.
-
-26/03/2003
-SPoG
-- Removed win32/x dependencies from gl interface.
-- Removed win32/glib dependencies from core interface.
-- Replaced void* in gtk helper functions with forward-declared GtkWidget.
-- Changed gtk helper functions to return enumerated values instead of win32 IDOK.
-- Removed WINAPI macro for __stdcall from all interfaces.
-- Removed unnecessary dependencies from core stdafx/qe3 header.
-
-25/03/2003
-SPoG
-- Changed class-level render states to be static for Brush and Patch.
-- Refactored brush implementation - breaking it up into smaller parts.
-- Added refcounted ptr template to track refcounts.
-- Fixed refcount bug introduced by new clone-selection.
-- Fixed warnings in brush implementation.
-- Cleaned up plugin interface header inclusion.
-
-24/03/2003
-SPoG
-- Fixed crash on building unbounded brushes in release build.
-- Changed assertion failures to be non-fatal in release build.
-- Moved OS-specific gl headers into separate files.
-- Moved app-shaders interface into a separate file.
-- Cleaned up dependencies for brush implementation.
-
-23/03/2003
-SPoG
-- Added per-instance selection of patch vertices.
-- Fixed per-instance vertex selection rendering on multiple instances.
-- Refactored patch/brush render code.
-- Changed manipulator transforms to convert to local space before applying.
-- Fixed selection test for picomodule meshes.
-- Fixed selection test winding order for triangles.
-- Fixed update of window title on new-map and load-map.
-- Changed selection to work with exactly side-on faces.
-- Refactored instance implementation to reduce code bloat.
-- Fixed map export always exporting root.
-
-21/03/2003
-SPoG
-- Fixed external resource tracking to preserve uppercase characters in names.
-- Changed clone-selection to not use global copy/paste.
-
-20/03/2003
-SPoG
-- Changed map-save to save all saveable files that the map references.
-
-16/03/2003
-SPoG
-- Moved hashtable and hashfunc into libs.
-- Cleaned up renderer interface and selection interface.
-- Refactored frustum testing class.
-
-12/03/2003
-SPoG
-- Moved winding-specific stuff from brush obj to winding obj.
-- Refactored filter subsystem to remove dependency on entity/brush/patch.
-
-07/03/2003
-SPoG
-- Fixed crash when clicking cancel from patch cap-dialog.
-- Changed selection tests to ignore back-facing faces.
-
-05/03/2003
-SPoG
-- Fixed failure to release cloned scene graph nodes.
-- Fixed selection manager failing to release render states.
-- Fixed eclass system failing to release render states.
-
-04/03/2003
-SPoG
-- Fixed writing-past-end of vertex arrays in brush rendering.
-- Fixed releasing data stored in undo system when deleting undoables.
-- Fixed crash in misc_model when model fails to load.
-- Fixed undo for clone/rotate/flip/nudge/set-texture operations.
-- Cleaned up surface dialog.
-
-01/03/2003
-SPoG
-- Changed clipper split-selection to keep result selected.
-- Cleaned up and finalised picomodule, adding to cvs.
-
-28/02/2003
-SPoG
-- Cleaned up entity list window.
-- Fixed crash on freeing a map while entity list node is selected.
-- Fixed crash on clone/copy of externally referenced brushes.
-- Added multiple-selection support to entity list.
-- Added updating entity list selection display on selection changes.
-
-26/02/2003
-SPoG
-- Added stl_warnings include.
-- Fixed tracking of map-modified-since-last-saved.
-
-24/02/2003
-SPoG
-- Fixed missing map-release when map-load fails.
-- Changed map-rename (save-as) to flush undo queue.
-- Fixed bug in exporting selections.
-
-23/02/2003
-SPoG
-- Fixed redo on changing misc_model "model" key.
-
-22/02/2003
-SPoG
-- Changed undo interface to factor out global undo system.
-
-21/02/2003
-SPoG
-- Started cleaning up Map subsystem.
-
-20/02/2003
-SPoG
-- Added 'clone subgraph' feature to core, using direct xml import/export.
-- Added 'save' feature to reference cache.
-- Added scope timer object.
-- Changed scene graph interface to allow setting scene root.
-- Changed core to use reference cache to track current map.
-- Removed mapmodel module.
-- Fixed relative paths for loading maps as misc_model.
-
-19/02/2003
-SPoG
-- Changed model/map modules to register their file types on load.
-- Added map module manager to support unlimited map loader modules.
-
-18/02/2003
-SPoG
-- Changed vertex buffer template to support resizing.
-- Changed vertex buffer search algorithm to iterate instead of recurse.
-
-17/02/2003
-SPoG
-- Fixed sorting bug with render-states.
-- Fixed colour state when disabling gl_color_array.
-- Fixed unterminated loop in scenegraph traversal.
-- Fixed freeing project entity twice on shutdown (infinite loop).
-- Fixed failing to destroy the scene graph on exit (oops).
-
-07/02/2003
-SPoG
-- Added updating current texdef when a face is selected.
-- Fixed crash when creating a brush with duplicate planes.
-
-06/02/2003
-SPoG
-- Fixed various issues with 'save region'.
-- Changed default current texdef to use game-specific scale.
-- Changed brush creation to use current texdef.
-- Changed clipper to use current texdef.
-- Fixed bug in selection counting for patch control points.
-
-05/02/2003
-SPoG
-- Fixed reversed solid-selection-outline preference.
-- Finished factoring out face_t.
-- Added script token writer interface for map export.
-- Changed map export interface to use script token writer.
-
-04/02/2003
-SPoG
-- Added depth-buffer-write enable/disable feature to renderer.
-- Changed Pointfile class to use renderer.
-- Continued factoring out face_t.
-
-03/02/2003
-SPoG
-- Fixed temporary objects leaving dangling references in the undo system.
-- Changed import-map to not modify existing selection.
-
-02/02/2003
-SPoG
-- Fixed frustum culling for transformed nodes.
-- Fixed hide/filter/region to work independently.
-- Added highlighting of selected brush faces in component mode.
-- Fixed bug detecting thin area-selection if dragged down or left.
-- Renamed brush_type to Brush.
-- Renamed face_type to Face.
-- Started factoring out face_t.
-
-01/02/2003
-SPoG
-- Improved edge and vertex manipulation.
-- Removed unnecessary graph traversals for rendering/selection.
-
-31/01/2003
-SPoG
-- Merged changes since last merge from merge-1_2_10-post to spog_branch.
-- Merged changes since last merge from HEAD to spog_branch.
-- Tagged HEAD after merging as 'merge-spog_branch-post'.
-- Added walker to merge sibling worldspawns.
-- Merged changes to Construct for PPC from trunk.
-- Fixed over-enthusiastic worldspawn merging.
-- Fixed misc_model "angle" key setting pitch instead of yaw.
-- Fixed entity set-key-value changing scene-graph topology.
-
-30/01/2003
-SPoG
-- Added subgraph traversal feature to scenegraph traversal.
-
-29/01/2003
-SPoG
-- Changed scene graph implementation to allow nested traversals.
-
-28/01/2003
-SPoG
-- Fixed angles key order for misc_model.
-
-27/01/2003
-SPoG
-- Fixed typo causing set-texture-of-selection to behave incorrectly.
-
-26/01/2003
-SPoG
-- Replaced all tabs with spaces in CHANGES.
-- Fixed entity bounds updates for 'light'.
-- Fixed code that doesn't conform to c++ standard as enforced by gcc.
-
-24/01/2003
-SPoG
-- Added missing file: icharstream.h.
-- Fixed bug with synchronisation of brush-face instance data.
-- Added .map format import/export interfaces.
-- Removed last remnants of IBrush.
-- Removed IPatch.
-- Moved walkers defined in in mainframe.cpp to appropriate places.
-
-23/01/2003
-SPoG
-- Changed scenegraph traversals to use a compiled graph.
-
-20/01/2003
-SPoG
-- Changed selection interface to hide per-instance data.
-- Added streaming tokeniser for .map format.
-- Changed mapq3 module to use streaming tokeniser.
-- Added xml stream interface for input and output.
-- Added xml stream parser based on libxml2 SAX.
-- Changed mapxml module to use xml stream input.
-- Changed brush and patch to use xml stream input.
-- Added xml stream writer.
-- Changed mapxml module to use stream output.
-- Changed brush and patch to use xml stream output.
-
-
-16/01/2003
-SPoG
-- Disabled pivot updates while selection is being manipulated.
-- Changed pivot calculation to use instanced world-bounding-box.
-- Fixed crash bug in PositionView.
-
-14/01/2003
-SPoG
-- Merged with branch merge-1_2_10-post at tag spog_merge_merge-1_2_10-post
-- Removed 10k+ lines of unused #if 0 code.
-- Removed unused declarations in qe3.h.
-- Removed brush and face types from qertypes.h.
-- Removed plugin API stuff dependant on brush type.
-- Added per-instance selection for brush faces.
-
-08/01/2003
-SPoG
-- Added selection counters for primitive/component modes.
-- Added face-drag mode (default shortcut key = F).
-- Added face-centre-point rendering/selection/editing.
-
-07/01/2003
-SPoG
-- Changed selection to work per-instance.
-
-06/01/2003
-SPoG
-- Changed selector interface to allow per-entity selection tests.
-
-06/12/2002
-SPoG
-- Added selection-test and selector objects to clean up selection system.
-- Unified key modifiers for selection in both primitive and component modes.
-- Added mapmodel module to load .map and .xmap as misc_model.
-
-02/12/2002
-SPoG
-- Added debug rendering of a selection test.
-- Fixed bugs in triangle/line clipper, making selection work properly.
-- Refactored selection system interface.
-- Added undo for texture nudge.
-- Fixed minor render-state bug.
-
-29/11/2002
-SPoG
-- Optimised wireframe drawing of brushes with back-face culling.
-- Optimised brush-winding generation.
-- Changed winding generation to be more robust with large world extents.
-- Fixed crashes with unbounded-face and degenerate-edge cases.
-
-20/11/2002
-SPoG
-- Completed rotation manipulator.
-- Added translation manipulator for the default editing mode.
-- Changed XY mouse-chaser speed to depend on distance mouse moved outside window.
-
-15/11/2002
-SPoG
-- Added initial version of maya-style manipulators - rotation manipulator.
-
-07/11/2002
-SPoG
-- Fixed false asserts in Brush ConstructPrefab.
-- Undo system optimisation - uses binary-sorted container to speed up finding already-added objects.
-- Fixed crash when transforming objects which don't support edit_interface.
-- Fixed clone command to nudge the selection after cloning.
-- Fixed clipper to remove brushes that are completely behind the clip plane.
-
-06/11/2002
-SPoG
-- Brushes: cleaned up per-face operations to use face visitor pattern.
-- Fixed setting brush face texdef, with fully functioning undo on individual brush faces.
-
-04/11/2002
-SPoG
-- Refactored renderer to two objects, camera and XY renderer - XY uses entity shaders.
-- Experimental pivot object.. work-in-progress.
-- Modified scene-graph instance-caching to maintain multiple instances within nodes.
-- Fixed undo bug, deleting a void* doesn't call the destructor.
-- Rewrote filters system to work with scene graph system.
-- Cleaned up quake entity module to provide same functionality as before.
-- Refactored render-state cache to use generic hashtable and reference-cache templates.
-
-19/10/2002
-SPoG - spog_branch - experimental - work-in-progress
-- added scene graph library: defines interfaces, generic graph node types,
-  re-usable systems for traversals, traversal paths, node containers,
-  multiple-instance caching of world-space-transforms/bounding-volumes/visibility.
-- added scene graph traversals to replace all traversals of 'active_brushes',
-  'selected_brushes', 'filtered_brushes' and 'entities' linked-lists.
-- added view module: view-volume-culling system acting on the scene graph,
-  uses scene heirarchy to minimise culling tests per frame.
-- added opengl-state module: sorts opengl-state objects (shaders) to minimise
-  opengl state changes during rendering.
-- added renderer module: culls objects outside the view volume,
-  gathers non-culled renderable objects from the scene graph,
-  keeps track of state during traversal, adds renderable objects to correct opengl-state.
-- added selection module: sets view volume to the selection box/ray, culls
-  objects outside the view volume, gathers non-culled selectable objects
-  from the scene graph (entity/primitive/component),
-  selects gathered objects (select/toggle/cycle) or moves things if already-selected.
-- added patch module: encapsulates a patch as a scene graph node,
-  optimised patch tesselation.
-- added brush module: encapsulates a brush as a scene graph node,
-  adapts multiple-brush operations to use the scene graph.
-- adapted entity module: encapsulates an entity as a scene graph node/subtree,
-  shares common code between different visualised entity types.
-- adapted model module: encapsulates a model as a scene graph node/subtree.
-- added undo module: completely new compact infinite-undo-system,
-  operates on undoable objects, uses minimal-state data to store objects,
-  uses refcounting to undo "deleted" objects.
-
-TODO: cleanup: many simple things are still broken or not functioning in the right way..
-see !\todo items in the code (not all are documented yet though).
-Selection module probably needs refactoring some more - perhaps split off the move-already-selected stuff.
-The dependencies are still pretty bad.. need to refactor stdafx.h/qertypes.h.
-Some of the above modules are not really modules, they're static-linked to the core, but could easily be dynamic-linked.
-The interfaces to brushes and entities still expose brush_t and entity_t for backwards-compatibility.
-NOTE: some todos are #if 0 because their functionality is (or will be) replaced by the new systems.
-
------- branch point - spog_branch
-
-30/08/2003
-SPoG
-- Ported changes from trunk.
-
-17/08/2003
-SPoG
-- Ported changes from trunk.
-- Added quake pack to win32 setup scripts.
-- Fixed crash in RunBsp.
-
-17/05/2003
-SPoG
-- Renamed stream interfaces with C and I prefix.
-- Shoehorned bytestream into idatastream.
-- Moved member classes out of IArchive, replaced with member typedefs.
-- Renamed filesystem, path, dynamic string, file input stream with C and I prefix.
-- Documented filesystem, path, dynamic string, file input stream.
-- Cleaned up game-specific encapsulation classes a little.
-
-16/05/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=815
-  found out about string_t that slept through my reviews
-
-Updated list of broken stuff on this branch:
-
-- include/bytestream.h: remove this file, extend idatastream.h header
-from the code conventions:
-  include/ directory:
-  This directory is holding the API header files for the synapse modules (plus a few build control and version related headers)
-  All headers that describe synapse APIs should start with an i: ishader.h igl.h 
-
-  The few files in include/ that don't start with a lowercase i are specific files for build control and configuration.
-  Regular developement never creates non i-prefixed files in include/
-  
-the merge with IDataStream goes like this (note the corrected class names):
-class IInputStream
-class IOutputStream
-
-class IDataStream : public IInputStream, IOutputStream
-
-class ISeekableStream
-class ISeekableInputStream : public IInputStream, public ISeekableStream
-class ISeekableOutputStream : public IOutputStream, public ISeekableStream
-
-typedef unsigned int size_type; goes away, use size_t
-
-- include/iarchive.h
-
-renamed VisitorFunc to IArchiveVisitor
-move it out of IArchive class (keep it in iarchive.h though)
-from code conventions:
-  Don't declare classes inside classes. Makes the code harder to read and isn't useful to anything.
-
-- remove libs/bytestreamutils.h
-put that functionality into the IStream stuff / idatastream.h stuff
-anything you retrieve from an IStream should be endian-correct
-
-- libs/filestream.h
-I'd rather see a header without embedded code, and a .cpp file for it
-
-- libs/fs_filesystem.h libs/fs_path.h
-those totally lack documentation about what they are doing
-same as above. way too much embedded code. makes things harder to maintain. implement in a .cpp
-and as usual, name the classes correctly, C and I prefixes
-
-- gamespecific_t: rename correctly to CGameSpecific
-I like the idea of gathering all hardocded game-specific behaviours inside one same class.
-But is it really the topic of bug800?
-
-- gamespecific_executable_t: rename correctly to CGameSpecificExecutable
-shouldn't this be merged with CGameSpecific?
-
-12/05/2003
-SPoG
-- Fixed win32 build error (win32 has no <dirent.h>).
-- Added dir_good() check to handle failure of dir_open() in posix DIR wrapper.
-- Renamed dynamic_string_t and path_t to DynamicString and UnixPath respectively.
-- Removed unnecessary use of 'inline' and 'virtual' keywords in class definitions (bad habit).
-- Documented archive interface.
-
-09/05/2003
-TTimo
-- some easy fixes to get it to startup on Linux
-- tagging the current source as bug800-spog, preparing rollback
-
-
-SPoG
-- Added an implementation of IArchive to do OS filesystem access.
-- Changed vfspk3 to use above implementation for OS filesystem access.
-- Added const qualifiers to vfsGetFullPath and everything dependant on it.
-- Changed vfsGetFileList to use "*" to indicate all-files instead of a NULL pointer.
-- Extended IArchive interface to allow for extra filesystem functionality.
-  Added method to check if a file exists quickly.
-  Added method to traverse the filesystem with control on start-dir and depth of recursion.
-- Defined implementation requirements for IArchive.
-  An archive contains a heirarchy of directories and files, and may contain empty directories.
-  An archive can be traversed in directory order.
-  Directories can be distinguished from files during a traversal.
-  Directory paths will always end with a separator.
-  File entries can be opened as an IArchiveFile.
-  IArchiveFile provides a simple non-seekable input stream which can only be read forwards.
-  Any number of files may be opened and read from an archive simultaneously.
-  An archive may be released while one or more files are still open, the files will remain valid until released.
-- Changed archivepak, archivezip and archivewad to implement all IArchive requirements.
-- Factored common code from archive implementations out into new lib/headers:
-  fs_filesystem.h: a templated filesystem container, with iterators and efficient traversal.
-  fs_path.h: a dynamic filesystem path object, with separator checking and efficient memory management.
-  ibytestream.h: abstract interfaces for input byte streams.
-  bytestream.h: utilities operating on abstract input byte streams.
-  filestream.h: a c++ wrapper for stdc FILE object, implementing a seekable input stream.
-- Added a new pkzip-reader implementation, designed to be orthogonal to the compression library used.
-- Added a zlib input stream object, which decompresses data from an abstract byte stream on the fly.
-- Removed archivezip code copy/pasted/hacked from zlib and unzip.c, replaced by pkzip-reader and zlib input stream.
-- Changed vfsLoadFile to return 0 for a zero-sized file, only returning -1 if it failed to load the file.
-- Removed halflife-specific disabling of shader-loading, thereby allowing common-hydra.shader to work.
-- Added archivezip, archivewad and archivepak to win32 setup scripts.
-- Updated win32 setup scripts for halflife media.
-- Updated cons scripts for archivezip, archivewad and archivepak.
-- Added printing of warnings when vfs functions are given invalid input paths.
-
-
--------- branchpoint: "bug800-spog_branch"
-
-
-30/08/2003
-SPoG
-- Ported changes from trunk since branch point.
-
-11/08/2003
-SPoG
-- Split qe3.h up into multiple headers.
-- Cleaned up use of win32 symbols:
-  WINAPI macro for module functions removed.
-  GUID for module interfaces replaced by string.
-  boolean replaced by bool.
-  MB_OK etc gui defines replaced by enumerations.
-- Removed plugin stuff deprecated by synapse from qerplugin.h.
-- Cleaned up use of glib symbols:
-  guint32, gdouble, gboolean typedefs removed from non-glib-dependent code.
-  TRUE/FALSE replaced by c++ bool true/false.
-- Removed all "extern" function declarations.
-- Removed dependency on MainFrame from preferences.h.
-- Moved synapse server and pluginmanager instances to pluginmanager.cpp.
-- Split pluginmanager.cpp into three parts:
-  Radiant's synapse client stuff in plugin.cpp.
-  Implementation of brush/entity/patch-handles stuff in pluginapi.cpp.
-  Synapse server init/shutdown in pluginmanager.cpp.
-- Added forward-declarations to avoid including other headers.
-- Replaced CString usage with Str;
-- Removed unused brush-scripts stuff.
-- Cleaned up patch-vertex-area-selection logic.
-- Removed very old code chunks that were commented or #if 0.
-- Replaced project-entity with a dedicated key/value string map.
-
----- branch point - spog-cleanup
-
-06/12/2003
-SCDS_ReyalP
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=930
-  shortcuts to change texture window scale
-
-02/12/2003
-SCDS_ReyalP
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=913
-  fix for single monitor window positioning save
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=924
-  fixes to CenterXYView shortcut, correctly bound to Shift+Control+Tab now
-TTimo
-- add a 'q3map2' command line to win32_install.py, factorize and remove win32_install_q3map2.py
-
--- linux 1.3.14 test build 1
-
-29/11/2003
-TTimo
-- heretic2 has no q2map. linux setup tries to install and breaks
-  removed faulty setup line
-- cleaned more Linux setup fuckage caused by q2/her2
-  a tip: rm -rf build install before building and testing a new setup
-
-28/11/2003
-ydnar
-- full SCC purge of the vs.net project files (for real this time)
-- added seperate Q3Map2 build targets
-- added seperate Q3Map2 post-build Python script
-- _skybox entity support
-- _skybox and _decal in entities.def (Q3)
-
--- win32 1.3.14 test build 1
-
-28/11/2003
-djbob
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=899
-  bobtoolz update (icon functionality is in menu too)
-djbob & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=842
-  migration of the win32 build system to vs.net/VC7
-  new libxml and libpng packages are required:
-  http://zerowing.idsoftware.com/libxml/
-  http://zerowing.idsoftware.com/libpng/
-  updated win32_install.py for new names and paths
-TTimo
-- assraped the vcproj with sed to remove Scc entries
-SCDS_ReyalP
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=88
-  2D background image plugin
-TTimo
-- putting together win32 setup updates for 1.3.14
-  msvcr70.dll goes in core directory
-  bkgrnd2d plugin content
-  changed file paths (libxml/libpng)
-  .xlink for new JA content
-
-27/11/2003
-TTimo
-- using a central scons.signatures file for checksums
-- version bump to 1.3.14
-- a libxml-related build bug in qe3.cpp on Debian sid
-- it looks like Sid no longer has inflate_mask exported from /usr/lib/libz.so
-  switched the mask to be defined in our source
-  this may be a problem on other distros, and on holy box (Woody)
-SCDS_ReyalP
-- bug 921 and 922, Z floating window fixes
-- bug 926, hullcaulk, hintskip, subtlehint
-EvilTypeGuy
-- bug 505 - select all faces with a given texture
-
-19/11/2003
-ydnar
-- clipper tool plane points default to 1st selected patch mesh
-
-17/11/2003
-TTimo
-- upgraded server to subversion 0.33
-
--- released 1.3.13
-
-10/11/2003
-SCDS_reyalP
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917
-  floating windows startup crash
-
-09/11/2003
-TTimo
-- fix M4_GAME_ET ( OSX setup )
-AstroCreep
-- cleaned up JA shader scripts
-
-01/11/2003
-ydnar
-- Merged ASE submaterial/subobject code from BirdDawg
-- Made Q2/Heretic2 tools not use precompiled headers to eliminate Win32 compilation errors
-- Added glColor4ubv() support to the GL function table
-- Changed PicoModel rendering to use glColor4ubv() instead of 4 divides and pass-by-value glColor4f()
-- Fixed bug 900 by setting alpha to 255 explicitly in image module, rather than 3 input components,
-  which was borking Q3Map2 jpeg loading, and thus compiles
-
-24/10/2003
-TTimo
-- bump to 1.3.13
-Anders
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
-new osx patch, fixes strip bug in setup. merging setup patches to a single file
-SCDS_reyalP
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=900
-Some jpegs get garbaged alpha channel
-
-22/10/2003
--- merge https://zerowing.idsoftware.com:666/radiant/GtkRadiant/branches/Release-1.3.12/
-  19/10/2003
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
-    scons BUILD=info to generate a tarball and it's .info
-
-  18/10/2003
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=888
-    patch for 16 bit RGBA support in glwidget
-
-  -- released 1.3.12 Linux
-
-  14/10/2003
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=879
-    fixed hellish dlclose issue only occuring with holy builds
-
-  -- released 1.3.12 win32
--- end merge
-Arnout
-- added epsilon testing to hashtable compares to eliminate almost-identical vertices
-- pico surfaces now use the normals from LWO vertices
-
-21/10/2003
-Arnout
-- added hashtable for faster vertex matching during LWO surface generation
-- model rendering now uses DrawElements and will use vertex colours in wireframe/flats shade mode 
-
-20/10/2003
-Arnout
-- added LWO support to picomodel.
-    shader names are derived from surface name
-    only geometry from layer 0 is used
-- added support for 'vertical flipped' TGAs
-
-19/10/2003
-Arnout
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=893
-  fixed starton primary monitor
-  fixed mouse pointer setting on win32 to properly translate gdk's offset coordinate system in windows' one
-  
--- released 1.3.12 win32
-
-11/10/2003
-Spog
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=865
-  fix texture subsets
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=889
-  misc update, missing JA system textures
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=824
-  fixed .pref file trashing
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=881
-  BSP monitoring disabled by default in Q2
-
-09/10/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=883
-  more JA pack: shaders and mapextras.pk3 textures
-- fix Q2 win32_install.py to put the tools at the right spot
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=878
-  correctly support PNG images with an alpha channel
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=885
-  fix console to refresh during a texture directory load
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=739
-  fix weird Shift + Control + Z causing a Redo in non-floating window mode
-
-07/10/2003
-Nurail & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
-  Q2 tools, added -fs_basepath. Need corresponding setup and .proj updates
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=875
-  fixed broken surface properties in Q2 surface plugin
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
-  more fixes, build paths in scons, take out INSTALL config on command line (not functional + not need)
-  added Q2 tools back to Linux setup
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
-  using "*" as the shaders minor in surface plugin
-- updated makeself copy to the latest from icculus.org cvs
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=574
-  sprite plugins, tweak to make it functional for all games
-- updated Q2 tools .dsp
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=876
-  more Jedi Academy setup work and content
-  moving imagepng.dll module to the core, as now both Sof2 and JA need it
-  sample maps reorg, new siege_hoth_sample.map
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=874
-  a lot more models - using a dynamic File Group in IS to cope with that
-- Q2 IS setup fix, was not properly putting stuff in baseq2/
-  IS setup: tweak to Q2 tools stuff
-
-06/10/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
-  Q2 setup needs to be cleaned up and unified between win32 and Linux
-  using INSTALL_Q2 and TOOLS_Q2 in SCons script to install the Q2 tools
-  fixed the setup build dependencies to reference the Q2 tools targets
-  moved the Q2 specific modules imagewad and vfspak to q2/modules
-
-05/10/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=871
-  updating the gtk2 version to 2.2.4
-  adding an SVN module with the Gtk2 developer package: checkout gtk2-win32
-  updating IS to the new files
-  sed'ing the .dsp to replace src-gtk2 by gtk2-win32
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=609
-  Q2 tools: comment out dupe strupr on win32
-  update IS setup to missing Q2 stuff ( vfspak and tools )
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=866
-  Fixed Camera inspector window not refreshing. Was a missing top level gtk_widget_show call
-
-03/10/2003
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=609
-  quake2 tools build scripts
-  Linux setup updates - Q2 game pack in Linux setup
-TTimo
-- scan through all URL links in game.xlink to update them
-- added JA links (Raven and MapCenter forums)
-
-30/09/2003
-TTimo
-- update all synapse.config, win32 .dsw and install_win32.py for new surface module
-- Jedi Academy and Quake II game packs in IS setups
-- hardcoded hacks in editor core for JA, copied over from JKII
-- bug #867, disable sleep by default
-- q3map2 bug fix
-
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=862
-  Q2's 'no patch' stuff
-
-29/09/2003
-TTimo
-- OSX: fixup setup.xml.in
-
--- merge bug856 back into trunk
-16/09/2003
-Nurail
-- new patch + win32 stuff for surface module
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=804
-  refactored the XML synapse.config handling:
-    better detection of invalid XML file
-    less code, factorized to CSynapseClient::ConfigXML
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=828
-  fixing bobtoolz 'shaders' major loading issues
-  added '*' minor. to be used with lots of caution. only if the given major will have a single API such as 'shaders'
-  also, map module was missing a VFS entry in non-HL configs. that's bad karma, using a minor "*" instead
-  NOTE: on a lot of modules we could be using a '*' entry instead of having lines in synapse.config
-- took out obsolete md3model
-
-15/09/2003
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=856
-  quake2 surface module
-
-07/09/2003
-Nurail & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=856
-  a surface inspector module to customize per-game API
-  removing DO_SURFACEPLUGIN define (enabled implicitely)
-  removing bSurfacePropertiesPlugin (true implicitely)
-  remove SI_SetActiveInRadiant, it's always on by default
-  why was USE_UNDOTABLE_DEFINE taken out? - put back in
-  removed DBG_PLUGIN define and related code, that stuff is from way back and no longer relevant
-  cleanup QERApp_FreeShaders in shader module from DO_SURFACEPLUGIN stuff
-  the WINAPI stuff in interfaces is not needed, that's an old remnant. Cleaned up
--- end merge bug856 back into trunk
-
-19/09/2003
-Justin Blur
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=785
-  fix ~/.radiant permission bug
-Nurail & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=849
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=851
-  win32 updates for the new modules and install_win32.py
-
-16/09/2003
-Nurail & Hydra
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=848
-  q2 map format minor
-
-08/09/2003
-Tr3B
-- imagepng.so / PNG format support in Linux
-  NOTE: atm no official supported Linux game by GtkR uses this
-
-07/09/2003
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=851
-  imagewal.so module / wal image format
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=840
-  md2 support in picomodel
-
-06/09/2003
-Nurail & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=848
-  renaming mapq3.so to map.so
-  added hooks for Q2 map format load/save to single map module (minor mapq2)
-Nurail
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=849
-  vfspak port to synapse and updates
-
-04/09/2003
-SPoG
-- Fixed crash in RunBsp caused by passing an invalid pointer to printf.
-- Changed console to wrap long lines instead of using horizontal scrollbar.
-
-30/08/2003
-Anders & TTimo
-- OSX setup, new patch to make scons SETUP=1 produce a .run
-- don't put bspc Linux binary in the setup
-
-30/08/2003
-Anders & TTimo
-- OSX setup, new patch to make scons SETUP=1 produce a .run
-- don't put bspc Linux binary in the setup
-
-26/08/2003
-Anders
-- more scons OSX, start on setup stuff
-
-25/08/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=855
-  make 'move into worldspawn' work again
-Anders Gudmundson & TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
-  OSX scons build system
-
-24/08/2003
-ydnar
-- Removed "test.cpp" from radiant.dsp (merge artifact?)
-- Added ddslib to radiant.dsw
-- Correctly set lib deps for q3map2.dsp for ddslib
-- [bug 852] Increased buffers from 260 bytes on Win32 to 4096 bytes
-
-TTimo
-- bump to ver 1.3.12
-- EnsurePythonVersion broke in 0.91 (commented out)
-
-David Hogue
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=844
-  q3data Linux. q3data can read .ase and turn them into .md3
-
-23/08/2003
-ydnar
-- Added ddslib to repository, based on nvidia sample code, cleaned up a bit
-  straight C, loads DXT1, DXT3 and DXT5 format DDS textures.
-
-22/08/2003
-TTimo
-- https://zerowing.idsoftware.com:666/viewsvn/
-- Arnout's commit email script - try #2
-  the commit script doesn't handle viewsvn root remaps (radiant instead of radiant.svn)
-  adding a prefix to the report
-
-04/08/2003
-TTimo
-- conversion from CVS to Subversion:
-repository convert completed (with revml)
-module repositories glued together in a single one
-hooking email commit scripts and backup scripts
-- Python >= 2.1 required instead of 2.2
-
-01/08/2003
-SPoG
-- Changed gl widget to request maximum available depth buffer precision.
-- Changed all uses of deprecated GtkCList and GtkCTree to use GtkTreeView/Model.
-- Fixed directory handle leakage in synapse module search.
-- Fixed dir_dialog always returning NULL for Textures -> Load Directory.
-
-23/07/2003
-SPoG
-- Ported focus_out_event handlers in gensurf to gtk2 signals system.
-- Fixed failure to load models for entities other than misc_model.
-- Fixed crash in model module shutdown caused by mismatched resource capture/release.
-
-22/07/2003
-TTimo
-- fix q3map2 .dsp for correct glib-2.0 includes (common/vfs.c)
-- camera plugin installs to core now (RTCW and ET)
-- fixups to the merged setup stuff
-- patched cvsreport to provide explicit diff for some files #2
-- fix to work with scons 0.90 / added LIBPREFIX ('lib') where needed
-  https://sourceforge.net/tracker/?func=detail&atid=398971&aid=766975&group_id=30337
-SPoG
-- Fixed crash in cmdlib ExtractFileBase when source filename is an empty string.
-
-20/07/2003
-TTimo
-- SCons scripts for the ported plugins: bobtoolz, camera, prtview, gensurf
-- ET Linux setup script + new plugins
-- q3map2.x86 is installed and wrapped through a q3map2 script (libstdc++ LD_LIBRARY_PATH)
-- update ChangeLog and credits
-- put back the GTKRAD_DIR in .fgl
-
-19/07/2003
-SPoG
-- Tagged trunk before merge as bug537-merge-3.
-- Tagged branch port_gtk2_20030307 as gtk2-merge-final.
-- Merged changes since tag bug537-merge-2 into trunk.
-- Removed gtk dependency from plugin toolbar interface.
-- Ported prtview, bobtoolz and gensurf to gtk2.
-
-18/07/2003
-Anders Gud
-- OSX build fix
-
-16/07/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=814
-  merging ET support code into to trunk
-- cvsreport 0.3.0 - http://www.nongnu.org/cvsreport/
-  rolling out this ver since old cvsreport setup broke
-- fixup to build on Linux (including fixing plugin builds)
-
--- release-1_3_8-ET
-
-02/07/2003
-TTimo
-- new setup build, with patches and updates from SD
-- local fixing of bobtoolz dependency against libcmd, and itoolbar.h gtk header bustage
-
-19/06/2003
-TTimo
-- missing plugins. add them to .dsw for default build, add them to IS setup:
-  camera, gensurf, bobtoolz, prtview
-- fixup bobtoolz code for VC6. for(int i=0 causing duplicate definition errors
-- removed pk3man from IS (we no longer distribute/maintain it)
-  TODO: cvs remove the IS files for it
-- re-enabled plugins in build by default, disabled curry and textool
-  TODO: following error when bring up About box of bobtoolz:
-  BobToolz::ERROR->Failed To Load Exclusion List: C:\Program Files\GtkRadiant-ET-1.3\plugins\bobtoolz.dllbt\bt-el2.txt
-
-18/06/2003
-TTimo
-- add ET game pack. from Arnout's full dump of editor source + game pack data
-  trunk tagged at ET-tag for this
-- Dlg_SdAskCorePath:
-    szDir   = "C:\\Program Files\\GtkRadiant-ET-1.<<RADIANT_MAJOR>>";
-
-09/06/2003
-ydnar
-- Added Q3Map2 keys/entities to Quake 3 entities.def
-- Removed obsolete vlight keys from Quake 3 entities.def
-- Added MD5 functionality to mathlib, from:
-  http://sourceforge.net/projects/libmd5-rfc/
-
-------- merged changes since tag bug537-merge-2 from branch port_gtk2_20030307 to trunk
-
-TTimo
-- try checkin on branch see if cvsreport 0.3.0 will verbose it
-
-08/07/2003
-SPoG
-- Fixed recent-files list for file names containing underscores.
-
-07/07/2003
-SPoG
-- Fixed crash and file-type bugs in gtk file-dialog.
-TTimo
-- converted the setup code from perl to python
-- added copy over of libgcc_s and libstdc++, and LD_LIBRARY_PATH in the wrapper script
-
-06/07/2003
-SPoG
-- Changed console popup menu to include cut/copy/paste as well as clear.
-
-05/07/2003
-SPoG
-- Fixed the way surface-inspector dialog responds to escape key.
-
-04/07/2003
-TTimo
-- linux building / SCons
-  0.90 is broken, use 0.14 for now. added version check
-  adding scons SETUP=1 option to spawn setup build
-  enable back vfswad in scons
-  TODO: grab Conscript-setup, convert it to python in build_setup function
-
-02/07/2003
-TTimo
-- building a win32 setup, using -gtk2 suffix (game packs in Radiant-1.3-gtk2 and core in GtkRadiant-1.3-gtk2)
-SPoG
-- Ported vfswad to gtk2.
-- Fixed memory leak in vfspk3 directory search.
-- Added vfswad to win32_install.py.
-
-09/06/2003
-TTimo
-- tagging setup/ as gtk2_setup_rollback
-  rolling back trunk setup code to the branch to build an experimental release
-- merge trunk to branch:
--- tagged HEAD with bug537-merge-2
--- merge HEAD between bug537 and bug537-merge-2 into the branch --
-  31/05/2003
-  TTimo
-  - grab back vfswad code that I forgot in bug 800 rollback
-  - add prtview back to the project, fix it to build (#817)
-
-  27/05/2003
-  djbob
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=817
-    prtview fixes, upgrade to synapse
-
-  -- release-1_3_8
--- end merge HEAD between bug537 and bug537-merge-2 into the branch --
-- freshly merged in vfswad is broken
-- freshly merged in prtview is broken
-- q3radiant.dsp -> GtkRadiant.dsp, outputs GtkRadiant.exe
-- removed vc5 dsps
-SPoG
-- Updated win32 setup stuff to use gtk2 dlls.
-- Modified setup.pl to run correctly (tested on cygwin perl 5.6).
-
-08/06/2003
-TTimo
-- Linux:
-  check gcc 3.x, better ldd check
-  add gcc version to about message
-  kill old cons stuff
-- added q3map2.x86 scons build  
-- header conflict libs/cmdlib.h tools/quake3/common/cmdlib.h
-  grepped through q3map2 source to change #include "cmdlib.h" to common/cmdlib.h
-- killed more cons files remnants
-SPoG
-- Improved error reporting for win32 setup system.
-- Fixed errors reported when running setup scripts.
-- Fixed scale of xor selection rectangle in XY window.
-
-07/06/2003
-SPoG
-- Fixed X Window System error when entering freelook on *nix.
-
-06/06/2003
-SPoG
-- Fixed copy/paste on *nix.
-- Changed copy/paste on *nix to use GtkClipboard api.
-- Changed copy/paste on win32 to be non-window-specific.
-- Further cleaned up MainFrame::Create.
-- Changed freelook to use gdk_window_get_origin instead of gdk_window_get_root_origin to place the cursor.
-
-05/06/2003
-SPoG
-- Fixed grey statusbar in 4-way-split mode.
-- Redirected gtk messages before creating main window.
-- Removed unused XYFriend hack from camwindow.
-
-04/06/2003
-TTimo
-- win32_install.py settings loaded/saved from site.conf
-
-02/06/2003
-TTimo
-- fixed python running with no output. Make sure VC6 finds native Python before any cygwin Python
-  look at the Directories settings in Tools > Options to either kill the c:\cygwin\bin path, or have Python path first
-- renamed dupe files to avoid header collision and general confusion between entity and model
-- added win32_install.py to perform post-build install (need to load the configuration paths from a non-cvs stored site.conf file)
-
-01/06/2003
-TTimo
-- bind gen.dsp to makeversion.py
-- added a run_python.bat to check for python presence and execute
-
-27/05/2003
-TTimo
-- write makeversion.py module - hook it up to SCons build - cleaner, easier to use
-- comment out vfswad build lines. source is still not in tree (bug 800 aftermath I think)
-
-18/05/2003
-SPoG
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
-  Changed Sys_FPrintf_VA to immediately process console events during map load.
-  Changed startup to create main window after QE_Init().
-  Fixed loading last map on startup.
-  Fixed crash on exit.
-  Fixed colour dialog.
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
-  have to delay merging back to trunk. 
-  have a behaviour problem between debug and release builds.
-  while debug is fine, release is screwed (see bug item)
-
--- tagged HEAD with bug537
--- merge HEAD between merge-gtk2-20030413 and bug537 into the branch -----
-  11/05/2003
-  Dan Olofson & TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
-    workaround for ATI drivers bug (polygon backfaces)
-    use Preferences > 2D Display/rendering > ATI cards with broken drivers
-  Riant
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=806
-    updated synapse.config for SoF2 png
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=805
-    dir_dialog is broken - is only used in prefab path prompt
-
-  -- release-1_3_7
-
-  14/04/2003
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=801
-    moved "ignoring sprite for entity.." to be a _DEBUG only thing
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=802
-    fixed models not drawing on win32. was a setup bug
-  - OSX setup build updates - added dependency against libpng3-shlibs
-  - added openurl.sh to open urls on *nix (with setup updates)
-  Riant  
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=803
-    RTCW - default_project.proj in setup
-
-  13/04/2003
-  Michael Schlueter & EvilTypeGuy
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=684
-    imagepng building under Linux
-  Riant & TTimo  
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=797
-    fixed texture compression support
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=799
-    regen project file from template on version upgrade
-    updated all default_project.proj to have "version" "1"
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=798
-    missing modules/bitmaps/model_reload_entity.bmp from Linux setup
--- end merge HEAD between merge-gtk2-20030413 and bug537 into the branch -----
-  
-17/05/2003
-TTimo
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
-  http://www.qeradiant.com/wikifaq/index.php?Gtk2%20build%20notes
-  went through the new dll dependencies, listed required files preparing for a single zip package
-  updated all the project files to rely on src-gtk2/
-
-13/04/2003
-SPoG
-- Tagged HEAD with 'merge-gtk2-20030413' and merged HEAD --> port_gtk2_20030307.
-
-12/04/2003
-SPoG
-- Added gtk-2.x libraries to win32 setup.
-- Changed win32 setup to use 'dynamic' file-groups, making it possible to add files without
-  modifying installshield scripts.
-- Modified win32/setup.pl to copy setup data to dynamic file-group directories.
-
-30/03/2003
-TTimo
-- added scons scripts. the scons engine is included in the tree. you just need to have python
-  have ldd -r safe check on .so  
-  TODO:
-  - make sure it's gcc3
-  - check OSX
-  - add q3map2 build
-
-29/03/2003
-TTimo
-- tracked and fixed the startup bomb on Debian sid:
-  `pkg-config gtk+-2.0 --libs`
-  -Wl,--export-dynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
-  http://www.gnu.org/manual/ld-2.9.1/html_chapter/ld_2.html#SEC3
-  --export-dynamic
-    When creating a dynamically linked executable, add all symbols to the dynamic symbol table. 
-    The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time. 
-    If you do not use this option, the dynamic symbol table will normally contain only those symbols 
-    which are referenced by some dynamic object mentioned in the link. If you use dlopen to load 
-    a dynamic object which needs to refer back to the symbols defined by the program, rather than 
-    some other dynamic object, then you will probably need to use this option when linking the program 
-    itself.
-  this causes symbol confusion, shaders.so's g_ShaderTable suddenly resolves to the core's g_ShaderTable
-  one is a 'shaders' API, the other an 'appshaders' .. everything gets badly mixed up
-  added a check in the cons script, using `pkg-config gtk+-2.0 --libs-only-L` `pkg-config gtk+-2.0 --libs-only-l`
-  (same for gtkglext)
-    
-28/03/2003
-TTimo
-- propagate jpeg compile fix from bug750 branch
-- use PKG_CONFIG_PATH when building radiant/ (alternate gtkglext-1.0)
-- on OSX, you need gtk+2-dev package, and pkgconfig, atk1
-  build gtkglext from source http://gtkglext.sourceforge.net
-
-17/03/2003
-TTimo
-- updated the build system to glib2/gtk2/gtkglext
-  atm it compiles and starts on my dev box (Debian Sid)
-  but doesn't reach end of initialization, hangs on
-   q = (qtexture_t*)g_hash_table_lookup (g_ShadersTable.m_pfnQTexmap (), stdName);
-   in shaders.cpp QERApp_Try_Texture_ForName
-  need to have the gtk2 dev packages, and libgtkglext1-dev
-
-12/03/2003
-SPoG
-- Replaced alpha-blended area-selection rect with XOR rect.
-- Fixed YX/XZ/YZ toggle in floating windows layout.
-- Cleaned up xor rectangle code.
-
-11/03/2003
-SPoG
-- Fixed console scroll-to-last-text-inserted.
-- Fixed console error/warning colours.
-- Refactored or removed WIN32-specific gtk-related stuff.
-- Removed win32 SetCapture/ReleaseCapture on GLWindow.
-- Removed win32 gtk_main_iteration calls in glwindow mousemoved.
-- Cleaned up start-on-primary-monitor stuff.
-- Changed main window to use standard save/load window position/size.
-- Replaced deprecated gtk_widget_set_uposition with gtk_window_move.
-- Removed win32/X gl functions from igl.
-- TODO: replace/remove deprecated gtk_widget_usize.
-
-10/03/2003
-SPoG
-- Changed fonts in win32 rc file to 8pt tahoma.
-- Fixed flat-grey gui in Regular layout mode.
-- Changed main-window save/restore maximized to use gtk API.
-- Fixed button_press_event handling on console/entity/entitylist windows.
-
-09/03/2003
-SPoG
-- Fixed crash on shutdown after changing floating-z-window preference.
-- Removed win32_realize_floating hack.
-- Refactored MainFrame::Create to make it more readable.
-- Fixed key_press_event handlers for entity/surface/patch dialogs.
-- Fixed delete_event handlers for dialogs derived from Dialog class.
-
-08/03/2003
-SPoG
-- Fixed viewport for entity window comment text.
-- Fixed x-shrinking for entity window comment text.
-- Fixed menu underscore shortcut hack in MRU list.
-- Changed groupdialog to connect switch_page signal after creating all pages. 
-- Changed gl widget to use gtkglext/pango to create fonts.
-- Cleaned up gtkglext glwidget implementation.
-- Reduced border size on toolbar widgets.
-- Replaced font with font_name in win32 rc file.
-- Added viewports for all scrolled text boxes.
-- Fixed entities/textures/console window title update when page is changed.
-- Fixed floating windows not being transient to main window (don't want them on taskbar).
-
-07/03/2003
-SPoG
-- Created a new branch for the port to gtk 2.x. 
-- Fixed menu underscore shortcuts to use gtk_label_new_with_mnemonic.
-- Fixed global keyboard shortcuts by using mainframe_keypress.
-- Fixed use of deprecated gtk_color_selection_get_color.
-- Removed use of deprecated gtk_paned_set_gutter_size.
-- Replaced deprecated gtk_widget_draw with gtk_widget_queue_draw.
-- Replaced deprecated gtk_object_get/set_data with g_object_get/set_data.
-- Replaced deprecated gdk functions with 2.x equivalents.
-
-
------ branch port_gtk2_20030307 ------
-
-
-13/04/2003
-Michael Schlueter & EvilTypeGuy
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=684
-  imagepng building under Linux
-Riant & TTimo  
-- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=797
-  broken texture compression support
-
-
-
-31/01/2003
-SPoG
-- bug #752 - Construct fix for ppc, patch applied.
-
-26/01/2003
-TTimo
-- bug #750 - revamp of the setup stuff on Linux
-  (under way, see bug for progress - feel free to help!)
-- reworked the cons scripts, setup is hooked in to cons now
-  also, added gcc version select on command line, using Cons_gcc.pm utility
-
-22/01/2003
-TTimo
-- merged merge-1_2_10-post back to trunk
-
-
-===============================================================
--- merging release-1_2_9 -> merge-post-1_2_10 into trunk
-   trunk before merge is tagged pre-merge-1_2_10
-===============================================================
-
-22/01/2003
-TTimo
-- finished up the TODO items, turned into bug items or dropped them. branch is ready to move back in to trunk
-
-18/01/2003
-TTimo
-- fixed ID_SELECTION_MERGE
-
-17/01/2003
-TTimo
-- fixups
-  FlushReloadSelectedToolbarButton -> CFlushReloadSelected
-  incorrect naming: RadiantToolbarModuleManager -> CRadiantToolbarModuleManager
-  ToolbarButton -> IToolbarButton, and C* implementations
-  http://www.qeradiant.com/wikifaq/admin.php?Code%20Conventions
-
-14/01/2003
-ydnar
-- Minor Cons fix for OS X (bug 729)
-
-13/01/2003
-ydnar
-- GtkRadiant now builds on OS X, Linux, and Win32 out of the same tree
-- OSX build uses gtkfileselect-linux now, as the Darwin version was broken/old
-  fixme: change this to use OS X open dialog box or something?
-- Minor fixes to a few files to fix gcc warnings
-- Model module now builds on OS X and Linux, using Synapse properly
-- PicoModel change to invert T coordinate on ASE models
-- Q3Map2 change to export ASE models with T coordinate flipped
-- Misc Q3Map2 changes
-
-09/01/2003
-ydnar
-- Updated Construct with Darwin/OS X ld flags for 4MB stack size
-- Misc Q3Map2 updates (2.3.35-dev)
-
-05/01/2003
-ydnar
-- "angles" key now properly ordered, to work with current mathlib
-  (also changed in Q3Map2)
-
-31/12/2002
-ydnar
-- PicoModel: Minor fix to MDC loader (naming/define)
-- Q3Map2: 2.3.34-pre-1 updates
-- MapXML dsp unix->dos newlines
-
-29/12/2002
-SPoG
-- Merged q3map2-texturing prefs key.
-- Merged vfs check for gamemode project key.
-
-27/12/2002
-TTimo
-- fix GetTickCount stuff
-- added q3map2 cons script
-- fixed Linux build
-
-23/12/2002
-SPoG
-- Added model cache API, moved model cache implementation from entity module to core. 
-- Added file-type registry API, replaced core file-type manager with registry.
-- Changed model module to register supported file types with core registry.
-- Removed or #ifdef'd non-functional code from model module.
-- Added support for misc_gamemodel and model_static to entity module.
-- Cleaned up entity module's on-epair-changed API.
-- Moved light-entity-specific code to a seperate file in entity module.
-- Cleaned up file dialog interface - specify file-type-lists with a string.
-
-22/12/2002
-SPoG
-- Ported camera plugin to synapse, adding support for camera and ui APIs.
-
-20/12/2002
-SPoG
-- Fixed default prefs setting for selected-brushes-camera, gridmajor-alt and gridminor-alt.
-- Merged CEntityEclassModel::Draw in entity module.
-- Ported imagepng module to synapse.
-- Fixed warning for CamDragMultiSelect preference bool used as int.
-
-19/12/2002
-SPoG
-- Fixed white-textures bug caused by texture compression preferences.
-- Ported light-radius rendering to 1.3 entity module.
-
-18/12/2002
-SPoG
-- Merged win32 project files, with the exception of camera plugin.
-- Ported model module to synapse API.
-- Redesigned toolbar API to remove gtk-dependency from toolbar plugins.
-- Refactored window-position preference save/load.
-
-17/12/2002
-TTimo
-- kick doxygen generation for branch merge-1_2_10-post
-
-15/12/2002
-TTimo
-- having the linux version compile and start again. took out numerous elements while merging, built a list of TODO stuff
-  the main thing to do being to bring the win32 build back up too, then to go through TODO list and fix stuff
-  until the win32 version runs too, I check this in to a seperate branch merge-1_2_10-post
-- There is quite a massive update in mainframe.cpp switch case for all events.
-  Looks like it's just a reordering of stuff, but it looks bad in the diffs.
-- added m_MapReg pattern
-
-- At some point, I'm thinking that forcing correct TAB/SPACE conversion on the server end would be a good thing to have.
-  Nazisticly forcing the formatting sounds like the only viable solution.
-
-               11/12/2002
-               RR2DO2
-               - #418, mdc load and display (RTCW)
-               - #597, CenterCamera shortcut
-               Use Ctrl+Shift+TAB to center the views onto the current camera location
-               - #714, bitmap loading fixes and speedups
-               - #715, fixed Alt+Shift cycle/drill select to work with brush-based entities
-               EvilTypeGuy
-               - #718, fix compilation warnings
-               Riant
-               - #707, fixed HM mode in STV:EF
-
-               10/12/2002
-               EvilTypeGuy
-               - Fix gcc3 compilation warning
-               EvilTypeGuy and X-Man
-               - Fix OpenURL so browser launching works on XDarwin (Mac) systems.
-
-               8/12/2002
-               RR2DO2
-               - #710, AssignSound pattern
-               - #711, SoF2 model_static drawing
-               - #713, sync 2d and 3d rendering of models
-               - #238, apply 0..1 T range when Fitting a patch (instead of 0..-1 previously)
-               - #633, Add ability to change default color in 3D window Misc > Colors > Camera background
-               ydnar
-               - Q3Map 2.3.33 (see changes.q3map2.txt)
-               - Quake 3 + TA common.shader updates (q3map_terrain, hint)
-
-               3/12/2002
-               TTimo
-               - merging Stable-1_2-Apple into Stable-1_2
-               - why INSTALL.TXT? re-used INSTALL, updated to point to wiki
-               - why the -machinedump test against i386-redhat-linux? removed
-               - using $is_darwin flag instead of $gcc_machine tests in the build scripts:
-               gotta leave some room for a Linux ppc build, and darwin x86
-               exporting it for use in sub scripts
-               - the addition of ccache support broke some Apple SConstruct patches to $ENV{PATH}, fixing
-               merged version is compiling fine on Debian Sid
-               checking in on a branch, need to validate win32 build and OSX build before applying in Stable-1_2
-
-               -- release-1_2_11
-
-               30/11/2002
-               TTimo
-               - added seaw0lf to credits
-               - ydnar's changelog.q3map2, added to global.xlink and Linux setup
-               - 1.2.11 version tag
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=699
-               updated IS setup for q3map_terrain keyword
-               also fixed details in STVEF media
-               Arnout
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=569
-               http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=698
-               fixed drill select, Ctrl bug in vertex mode, and updated changelog.txt
-
-               29/11/2002
-               TTimo
-               - 1.2.11-rc1
-               - update changelog credits links for release
-               - update linux setup, putting EULA and new README instructions  
-
-               28/11/2002
-               ydnar
-               - Removed redundant 'p' from "developers"
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=637 - fixed
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=694 - fixed
-               - Updated to Q3Map 2.3.32
-               - Added epsilon to texture plane choose code to eliminate numerical
-               inconsistencies on brush faces slanted at 45 degree angles (bug 637)
-               - Fixed bug in lightmap export after lighting when map contains 0 BSP lightmaps
-               - Adjusted some light tracing constants to fix certain brush/patch seam shadows
-               - Tinkered with skylight code again
-               - Fixed bug where lightgrid would be black if level was compiled with -nogrid
-               - Fixed -approx code to work in floating-point space, using _minlight
-               - Fixed bug where vertex light code was using invalid pvs data to create
-               light list for surface, leading to incorrect vertex lighting
-               - Fixed related bug in anti-light-leak code that was causing brush faces to go
-               black (bug 694)
-               - New: _minlight sets _minvertexlight and (new) _mingridlight automatically
-               - New: _mingridlight key to set minimum grid lighting
-
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=637
-               added preference setting in Preferences > BSP monitoring
-               added an item on the wiki
-
-               27/11/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
-               picomodel-based model.dll module (new model.dll, removed md3module.dll)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=664
-               media/setup updates for q3map2 support
-               added modified quakev3.qe4, bumped internal version to 4 for all games
-               SOF2 and JKII were forcing BSP monitoring off because of sof2map, now only printing a warning
-               added -rename to SOF2 BSP phase
-               Q3 & RTCW new templates are working
-               haven't tested the STVEF & SOF2 versions
-               updated IS setup scripts to make sure quakev3.qe4 is updated in nightly release
-               (not needed on Linux, we will be doing a full release)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
-               updated win32 setup to provide right model.dll stuff
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=621
-               typo was causing memory error
-
-               RR2DO2 & TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
-               more model fixes, fixed the Linux build to build model.so
-               added search path to modules/ for bitmaps
-               model reload, patch and bitmap
-
-               26/11/2002
-               RR2DO2
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=569
-               area select - Alt+Shift for area select (complete tall)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=621
-               broken undo creating ghost undo entities (and trashes memory)
-               partly fixes the issue, it's a memory error still
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=659
-               updates to RTCW camera plugin - works in 4 view mode
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
-               more fixes to plugin API
-
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=638
-               libpng in the core DLLs instead of SoF2 (for q3map2 dependencies)
-               putting q3map2 binary with the Core Binaries
-
-               25/11/2002
-               TTimo
-               - added ccache support to cons build system - http://ccache.samba.org/
-
-               21/11/2002
-               ydnar
-               - minor bugfix to PicoModel ASE material loader
-               - Q3Map2 updated to 2.3.31 (Splash Damage)
-               - Stitching the edges of lightmaps on patches that wrap around (cyls and cones)
-                       so the seam is no longer visible
-               - The -patchmeta switch works better now, the patches are still stored in the
-                       BSP for collision, but are pre-tesselated into nonplanar meta surfaces for
-                       more efficient rendering
-               - Better, more uniform lightmap sample position finding on patch meshes
-               - Moved q3map_tcMod and q3map_alphaMod processing to the final phase
-               - New: q3map_skylight AMOUNT ITERATIONS to replace surfacelight on sky surfaces
-                       for much faster and more uniform sky illumination
-               - Fixed bug in PicoModel ASE material parsing code
-               - Fixed a few seam/lightmap precision/projection errors
-               - Increased MAX_SHADER FILES to 1024 and fixed overrun error when more than that
-                       number of shaders was listed in shaderlist.txt
-               - Increased a few compiler maximums for larger maps
-               - New: -np N switch on BSP phase, works like -shadeangle, in that it forces all
-                       planar shaders to be nonplanar with the shading angle specified
-               - New: -nohint switch on BSP phase, omits hint brushes from compile for testing
-               - New: -debugaxis switch on light mode. Colors lightmaps based on their lightmap
-                       axis (which direction the lightmap was projected on)
-               - New: -debugorigin switch on light mode. Colors lightmaps based on the luxel
-                       origin relative to the raw lightmap's bounding box
-               - New: -debugcluster switch on light mode. Colors lightmaps based on the pvs
-                       cluster the luxel falls into
-               - New: -convert switch to convert BSP to ASE file (experimental)
-               - New: q3map_lightmapmergable directive to allow terrain to be mapped onto a
-                       single lightmap page for seamless terrain shadows    
-
-               18/11/2002
-               TTimo
-                       - fixed pk3man build system to work with new cons layout
-                       - fixing linux setup system to work with new cons layout
-                       Linux 1.2.11 will be a full setup, much easier that way
-                       - update makeself to the latest (and best) version
-                       - add q3map2 to Linux setup. goes in core (g_strAppPath)
-                       NOTE: has a dynamic dependency to libpng
-                       - pk3man still has issues with the zlib code that's been thrown in it
-                       unresolved which I don't have time to look at
-                               since we plan to drop pk3man in 1.3, dropping it now is just as good
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=644
-                       detect GOTY install     from registry and use it as default path
-
-               13/11/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
-               reworked to have the UI in game settings dialog
-               (this is strictly win32 thing, if that broke Linux build, then fix the typos)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=630
-               mouse AngleSpeed setting was getting clobbered. fixed and upped the max values
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=623
-               applied a fix, rolls back the values when the compression formats are not supported
-               fix ain't very clean, if we have to deal with extensions some more, we need to deal with the settings persistance better
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=624
-               updated the setup code for town_*.shader (both in full setup and update)
-               updated files in WolfPack
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=672
-               using a QE4_VERSION define, added a message if there's a project template with wrong version
-
-               12/11/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=671
-               guard junk.txt path between " "
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
-               fix to CommitBrushHandleToEntity stuff
-
-               RR2DO2
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=660
-               previously you could select patch control points when patch selected + vertex edit (V) in 2D view. Works in camera view now
-
-               12/11/2002
-               TTimo
-               - nudging zerowing to trigger Stable-1_2-Apple doxygen generation
-               http://zerowing.idsoftware.com/doxygen/
-
-               11/11/2002
-               TTimo
-               - http://ttimo.net/web/anjuta
-               modified the .prj to work with the cons patches (linked dirs)
-               still way experimental
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
-               fixing linking for radiant.x86
-
-               10/11/2002
-               RR2DO2
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=669
-                       patch inspector bug - fixed
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
-                               fucked up change in the plugin API caused breakage of several plugins
-               still have to fix bobtoolz http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=665
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=661
-                       Undolevels not set properly
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=660
-                               drag selection to the camwindow for patches in controlpoint edit mode
-                               (not sure about the actual shortcuts, Ctrl+Alt on my current Linux setup)
-
-               TTimo
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=657
-                       mark map modified on editing entity keys
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
-                       added the correct link and ldflags statements to have static linking everywhere
-                               didn't check gcc 3 build, check correct static on Debian Sid and holy box
-                               has a $staticstdcxx in Construct to toggle On/Off if needed
-
-               09/11/2002
-               TTimo
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
-               reworking the cons building. support for gcc2 and gcc3
-                       cons -- gcc=<gcc-name>
-                               read gcc version and configure accordingly
-                               changed _NO_STLPORT to Q_NO_STLPORT
-                               independant BASE_CFLAGS and BASE_CXXFLAGS
-                               correcting usage of CC/CXX for c/cpp source and linking
-                               fixed missing -lz in vfspk3.so
-                               changed the way we build curry.so, works from the GtkRadiant tree now
-                               (NOTE: gcc 3.2 build of curry.so spews quite a few warnings)
-                               tweaked the way we do -fno-rtti -fno-exception
-
-               04/11/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=638
-               .qe4 version 4, udpated q3's .qe4 template, update setup to put q3map2 in the right place
-                       bumped version to 1.2.11-test for test setups
-
-               03/11/2002
-               ydnar
-               - fixed bug in jpeg loading code (4 components instead of 3 for RGB images, mh)
-               - updated PicoModel to 0.8.8 and Q3Map2 sundry fixes (2.3.29):
-               - Merged with latest CVS, fixed minor issues with matrix order
-               - Fixed minor Sys_FPrintf/Sys_Printf substitution typo in Q3Map2
-               - Expanded debug colors to 12 for debugging surface meshes
-               - PicoModel: fixed ASE loader to support > 1 texture coordinate per-vertex,
-               so more models supported correctly, also loading vertex normals
-               - PicoModel: md3 shader names are now cleaned. Suffixes (such as .tga or .jpg)
-               are stripped, and \ path separators are changed to /
-               - New: Add :q3map to the end of any shader name, and it will be interpreted as
-               the named shader minus :q3map. Example:
-               textures/shaderlab/concrete:q3map -> textures/shaderlab/concrete
-               One potential use is the -approx feature to collapse lightmapped  surfaces
-               into vertexlit surfaces, saving lightmap space/memory
-               - New: q3map_clipModel -- does what you think it does, sort of. This code ix
-               really experimental, and should *only* be used on large models such as terrain
-               (not small decorative models). This code will be evolving. Note: the shader's
-               surfaceparms are inherited by the magic clip brush, so if you have nonsolid
-               in your model's shader that uses q3map_clipModel, then the brush will also
-               be nonsolid
-
-               03/11/2002
-               TTimo
-               - cleaning up some cons stuff, checking that the setup building process is still good on Linux
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
-               updated Linux setup to put the bitmap
-
-               02/11/2002
-               ydnar
-               - PicoModel: replaced stricmp with _pico_stricmp
-
-               02/11/2002
-               ydnar
-               - PicoModel: added obj.c and ms3d.c, removed wfobj.c
-
-               02/11/2002
-               ydnar - seaw0lf
-               - Updated Q3Map2 to 2.3.29 sources
-               2.3.29
-                       - Merged with latest CVS, fixed minor issues with matrix order
-               2.3.28
-               - Bug 654 (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=654):
-               Fixed problem where brush faces, drawsurfaces, and surfaceparms weren't living
-               together in perfect harmony (terrain surfaceparms now inherited by brushes)
-               - Nodraw fog works now, albeit when you're underneath, surfaces above don't get
-               fogged properly. Could be good for foggy water where you want the above-water
-               portions to only be occluded by the water surface
-               - Bug 656 (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=656):
-               Number of lightgrid points displayed (byte size is currently out of proportion
-               due to internal storage format) when Q3Map is called with the -info switch
-               - Fixed wack surface merging bug where code would attempt to merge triangles not
-               adjacent to the current set, causing bad lightmap projections on nonplanar
-               surfaces
-               - Fixed tiny 1-character bug in 2d lightmap texture allocator where adjacent
-               luxels were being checked for occlusion rather than the actual source luxel
-               2.3.27
-               - Fixed minor bug in scriplib bugfix where the last character in a file wasn't
-               being read.
-               - Fixed bug where 0-area or bogus triangles were causing crash in MapRawLightmap
-               if they used a shader with a normalmap (thanks ShadowSpawn)
-               - Fixed bug where lightmaps were getting hosed levelwide on a prerelease version
-               of 2.3.27
-               - Fixed bug where lightmaps were getting knackered on models and certain patches
-               - Merged latest PicoModel version from seaw0lf, adding support for ASE and WF OBJ
-               models (preliminary)
-               - Increased MAX_MAP_PLANES to 0x40000 (~256k)
-               2.3.26
-               - Now using GtkRadiant's libpng and zlib config (linked as DLLs)
-               - Fixed bug in script parser where repeat calls to GetToken() were causing
-               memory corruption
-               - Fixed SOF2 -rename bug
-               - When using -game sof2 or -game jk2, the -flares argument is implied
-               - Added -noflares argument to disable the above behavior
-               - Added support for flares on entities. Use one of the following keys:
-               "_flare" "1" -- use default flare (different for each game)
-               "_flareshader" "path/to/flareshader" -- use a specific flare shader
-               Note: This only matters in SOF2/JK2 now. Make a light targetted (a spotlight)
-               to get it to aim the correct direction, otherwise it defaults to pointing 
-               downward. You cannot have omnidirectional flares
-               - Lightgrid size is automatically increased to accomodate large maps. The
-               MAX_MAP_LIGHTGRID error will never happen again
-               - Update PicoModel to 0.8.7 sources
-               - ASE support
-                       - Alias|Wavefront OBJ support
-                       - <modelname>.remap shader remapping suport
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=655
-               handle grayscale jpegs gracefully
-               - mathlib: fixed VectorClear(), got rid of braces
-               - scriplib: fixed double-free memory corruption bug
-               - radiant: added new color scheme to emulate Lightwave/Maya/3DS Max
-
-               02/11/2002
-               TTimo
-               - too many issues with build system reading system's libjpeg.h instead of libs/libjpeg.h
-               renamed libs/libjpeg.h to libs/radiant_libjpeg.h, updated sources
-
-               29/10/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
-               running from a network share - saving prefs per-user
-
-               27/10/2002
-               TTimo
-               - merged in some more m4x4 code for q3map2
-               - fixed unresolved code in picomodel (strlwr / strnicmp)
-               - reworked the tools building to build both q3map and q3map2 without trouble
-
-               25/10/2002
-               ydnar
-               - q3map2 and picomodel source, initial checkin to Stable-1_2 branch (does not compile yet, tweaking to be done)
-
-               23/10/2002
-               TTimo
-               - camera.dll goes into $(RTCWRADIANTDIR)/plugins instead of $(RTCWRADIANTDIR)/modules
-               fixed up camera compile (exports)
-                       added camera bitmap (plugin toolbar)
-
-               21/10/2002
-               TTimo
-               - quickfix to the build (typo)
-               - changed dynamic linking on Linux to look for libGL.so.1 by default
-               fixes "all textures are blank" Linux bug with NVidia cards
-                       (you still have to have a working NVidia GL installation though, xlibmesa-dev on Debian screws things up)
-               - checked in modified q3 .qe4   with q3map2 menu (see bug #638)
-
-               09/10/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
-               reworked the plugin toolbar to rely on interface instead of straight exports
-               cleaned up the botclip monsterclip Brush_Draw filtering, added proper selection filtering (Brush_Ray)
-               merged bug-622 back into Stable-1_2, bug-622 branch is dead now
-
-               06/09/2002  
-               James Monroe - RR2DO2 - TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=619
-               light globes, applying patch by RR2DO2 built from the initial light globe code
-               - note to self: indent -kr -nut -st -ts2 -i2
-
-               RR2DO2 - TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
-               massive patch update from SD's GtkRadiant
-               - camera plugin: new bitmap
-               fixed Linux install path for camera plugin to wolf/plugins
-               - fixed various warnings in camera build gcc / Linux  
-               - fixed pref crash if plugin toolbar disabled  
-               - fixed Gtk-WARNING on bad cast in AddPlugInToolbarItem
-               - renamed the new select to 'Use paint-select in camera view:' in prefs
-               (camera paint-select, should be our default name for this)
-
-               NEW: you can 'paint select' in the camera view: 'camera paint-select'
-               press shift and move the mouse over the camera view to paint over brushes you want to select
-               configurable in prefs to enable / use Shift key, or use 'classic mode' ctrl+alt
-
-               NEW: light radius drawing
-               Added in-editor light envelope drawing. Outer circle is max envelope, 
-               inner fullbright radius. Optional classic mode emulates the similar drawing 
-               from Rituals and Ravens tools (not q3map correct, easier for the level designer 
-               to understand/legacy).
-
-               NOTE: 'angles' is q3map2 only
-               NOTE: could manipulate angles directly from the views (2d and 3d with some handles)
-
-               NOTE TO SELF: 
-               <TTimo> hey guys .. just a quick question if you don't mind .. I'm trying to track a Gtk-WARNING .. is there a way to make those apps cause a break to track them easily ?
-               <andersca> just run your app with --g-fatal-warnings
-
-               TODO: add new bitmap to win32 & linux setups
-               TODO: don't use exports for the plugin toolbar, use entry functions
-               do something like CPlugIn::InitBSPFrontendPlugin
-               TODO: botclip is broken with the new Brush_Ray code  
-
-               initial ChangeLog for the patch:
-
-               28-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Added 'angles' support for models (misc_model/misc_gamemodel).
-                       + Prevented pivot drawing of model from scaling and rotating.
-                       + Cleaned up the dropdown boxes in the preferences a bit (all use 
-               tables now, so not multiline).
-                       + Added 'Classic Key Setup' option to camera paint select configuration, this 
-               drag-selects with ctrl+alt instead of shift.
-                       + Changed XYWnd::PositionView to position on the center of the 
-               selection, not on the mins.
-
-               27-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Added in-editor light envelope drawing. Outer circle is max envelope, 
-               inner fullbright radius. Optional classic mode emulates the similar drawing 
-               from Rituals and Ravens tools (not q3map correct, easier for the level designer 
-               to understand/legacy).
-
-               26-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Upped MAX_TEXTUREDIRS to 256 (from 128).
-
-               25-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Fixed patches not being drawn in XY window with colour of parent 
-               entity.
-                       + Made paste to camera snap destination spot snap to grid.
-
-               18-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Changed Select_Reselect to be much faster.
-
-               12-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Fixed curve point drag-selection area not showing properly in XY 
-               views.
-                       + Fixed size info breaking over 9999.9 units.
-                       + Fixed AllocateSelectedPatchHandles not setting patchesmode to 
-               ESelectedPatches.
-                       + Changed the horizontal and vertical tc shift spin control to have a 
-               limit of 8192.
-                       + Moved SPoG's implementation of redisperse cols to a seperate function 
-               and reinstated the old code.
-                       + Added 'Paste to Camera', shortcut Alt+V, which pastes the contents of 
-               the clipboard to the current camera origin.
-                       + Added centerview functionality to 4 window mode. Ctrl+tab will focus 
-               on the selection, or if non existant, on the camera.
-
-               11-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Made sure settings set in savedinfo.bin get initialized to their 
-               proper defaults.
-                       + Added botclip filter (filters *botclip* and *monsterclip*).
-
-               10-09-2002
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Removed .reg from normal map saving, can only save as region 
-               using 'Save region'.
-                       + Added outline style cycling (j) cycle between z buffered outlines and 
-               selected colour rendering.
-                       + Added colour dialog to pick the colour of selected surfaces in the 
-               camwindow.
-                       + Third coordinate for clip points now gets set to the center of the 
-               selection.
-                       + Changed arbitrary rotation dialog to accept negative angles as well.
-                       + Changed texture alignment dialog to accept values up to 2 decimal 
-               points.
-                       + Fixed entity inspector to say 'Textures:' in the window title.
-                       NOTE: still broke in floating window mode
-                       + Changed entity inspector so that tab doesn't clear the epair value 
-               field anymore, so it retains the value while jumping to it.
-                       + Disabling camera paint-select now returns selection behaviour for groups to 
-               the old behaviour as well (shift+click selects whole group).
-                       + Changed load_plugin_bitmap to load bitmaps from g_strAppPath if 
-               g_strGameToolsPath fails.
-                       + Added plugin toolbar and api.
-                       + Fixed m_pfnCommitBrushHandleToEntity, wasn't creating brushes 
-               properly (well, not at all really).
-
-               Older changes:
-                                       Arnout <rr2do2@splashdamage.com>
-                       + Added misc_gamemodel drawing.
-                       + Ported camera paint-select over from 1.3.
-                       + Fixed statusbar display of text (removed a bunch of \n's).
-                       + Added area selection in 3d view for patches.
-
-               30/09/2002
-                       TTimo
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=556
-                               quickfix crash bug
-
-               27/09/2002
-                       TTimo
-                       - more CORERADIANTDIR cleanup (q3data)
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=602
-                               added cascading to the entity submenu (doesn't cascade the main menu, only the sub ones, NPC_* for instance)
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=556
-                               with clip and caulk filtered out, won't be selected anymore in camera view (i.e. selecting invisible faces)
-                               added SF_CAMERA to the flags in the selection process
-                               cleanup up various ugly syntaxes in the selection code:
-                               don't ever do if (flags == SF_SINGLEFACE) on a bitmask and assert that the other flags will always be NULL
-                                       don't do arithmetic on bitmasks:
-                                               if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL)
-                       return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST);
-                       is WRONG
-                                               using flags & ~SF_ENTITIES_FIRST is the appropriate way
-
-               23/09/2002
-               Riant
-               - new IS scripts to go with recent media updates
-                       Riant & TTimo
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=615
-                               reworked the fix to use "caulk_shader" in .game
-                               updated IS .rul script to generate special values for Sof2 and JKII
-
-               21/09/2002
-               Riant
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=595
-               more texture compression, dialog and settings
-               Michael Schlueter  
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=592
-               fixes to the Linux build system, exclusive q3 or wolf working now
-
-               22/08/2002
-               EvilTypeGuy
-               - Fix @*$&)@)$$ memory leak of my own doing, yes it's really been in there this long.
-               This should help memory usage drastically, especially when flushing & reloading
-               the same sets of textures, GtkRadiant's memory usage no longer becomes heinous.
-
-               14/08/2002
-               EvilTypeGuy
-               - Fix build on some linux boxen by including qertypes.h for proper boolean type declaration
-
-               -- release-1_2_10
-
-               16/08/2002
-               TTimo
-               - STVEF media update finalized (some .def)
-               - 1_2 Core Update for shader manual update
-               - in JKII, typo with nar_shader? replaced by nar_shaddar, with proper support in update too
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
-               Q3/TA media update with cleaned up shaders
-               - validated the update content by a diff between 1.2.9 + 1.2.10-update and 1.2.10 full  
-               - added a DO_NIGHTLY_BOOL to setup.rul AND a warning during setup about update content for games that are not installed
-               - built 1.2.10-sof2, SoF2 full install
-
-               15/08/2002
-               Michael Schlueter
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=590
-               added the option to build a Linux setup with the debug binaries
-
-               TTimo  
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
-               cleaned up shaders, done nightly setup update on Linux
-               updated Linux nightly for 1.2 to use /usr/local/games/GtkRadiant-1.2 as default base
-               - using version 1.2.10-update. Full Sof2 setup will be 1.2.10-sof2
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=426
-               don't straffe when using Ctrl+Shift(+Alt)
-               - camera.so RTCW plugin in Linux setup
-               - quickfix to non-initialized var in camera code
-               - awfull piece of work that had been completely left out, nightly elements for JK2 and STVEF
-               added JKII media update and STVEF media update (for the DIR_GAME elements)
-               JKII nightly is finalized
-
-               14/08/2002
-               TTimo
-               - fixed a missing file
-                       - Linux build quickfix
-               - fixed silly rendering bug
-               - added pref to force texture compression off (hey why would you do that??)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=466
-               fixed MAX_POINTS_ON_WINDING overflow in q3map (and relevant code to handle in radiant)
-
-               13/08/2002
-               TTimo
-               - cleared up notexture (dead code)
-               - cleaned up QERApp_LoadTextureRGBA gamma table init
-               - having a shot at 1.3 texture compression
-               sees the extension, binds the texture with the currect setting
-               but rendering is fucked .. someone explain?
-
-               08/7/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=586
-               search and destroy Q3Radiant -> Radiant
-
-               07/7/2002
-               SCDS_reyalP
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
-               wolf_entities.def update
-
-               riant
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=548
-               STV:EF updates
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
-               SOF2 updates
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=584
-               JKII updates
-
-               06/7/2002
-               Riant
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
-               Sof2 patches and IS setup    
-               TTimo
-               - game pack prompt asking about STVEF, fixed
-               - mp_examples was leaked and non lighted, fixed
-               - imagepng.dll goes into Sof2 install / modules, and not in DIR_CORE
-               - libpng12.dll needs installed only with Sof2 pack (added 'SOF2 Pogram DLL')
-               default texture scale is 0.125  
-
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=582
-               nomipmap -> nomipmaps in shader manual  
-               - removed libs/pak, this was still being linked in to Radiant, but not used at all  
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=580
-               .PK3 are recognized along .pk3 files (strcmp ->strcasecmp)
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
-               added the RTCW camera plugin to IS setup
-
-               Michael Schlueter
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=581
-               GL warning fix      
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=567
-               GL font display fixes (mostly Linux)
-               applied the changes with some tweaking
-
-               31/6/2002
-               TTimo
-                       - compiling the camera plugin on Linux:
-                       move the GUID and other misc compatibility definitions to include/misc_def.h
-                               GetTickCount being used in camera.so, this is from radiant/missing.cpp (unresolved)
-                               -> use QGetTickCount instead (in main function table)
-
-               30/6/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
-               cleaned the .shader from 'light 1' statements
-               updated the IS script for the updated .shader
-
-               17/6/2002
-               TTimo
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
-               Sof2 support, PNG format
-               wrote imagepng module, dynamic dependencies to zlib and libpng
-               changes in the core:
-               some hardcoded to "sof2.game" for png interface loading and extensions
-               in GetTextureExtension, killed outdated support for texture plugins
-               if ! "sof2.game", png is not loaded, support disabled
-               http://zerowing.idsoftware.com/libpng/
-               correctly configured for VC build (post build steps and dependencies)
-               is required on win32 to build imagepng
-               - added m_pfnGetGameFileName to the main function table (was needed for png stuff)
-               - cleaned up the QERApp_LoadTextureRGBA path
-               using (unsigned char* pPixels, int nWidth, int nHeight)
-               cleaning up internal access path
-               RR2DO2
-               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
-               camera plugin for RTCW
-               TTimo: wrote the .dsp, post build steps etc.
-               IMPORTANT: you need to have RTCWRADIANTDIR env variable pointing to the RTCW Radiant files
-               (default C:\Program Files\Return To Castle Wolfenstein\Radiant)
-
-
-               12/6/2002
-               RR2DO2
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=299
-                       MP/SP pk3 filtering in VFS
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
-                       .camera support: splines library, camera plugin
-                               TTimo: portability fixups, cons build, guarding pragma, __cdecl BOOL
-                               virtual functions but non-virtual destructor
-                                       declaration with no type
-                                       int idCameraFOV::start - control reaches end of non-void, making it void
-                                       enumeration not handled in switch
-                                       no _MAX_PATH, the portable one is PATH_MAX
-                                       implicit declaration of int _fullpath
-                                       for(int i = 0; ..
-                                       struct _IO_FILE has no member named '_bufsiz'
-                                       stricmp -> Q_stricmp
-                                       attempt at implementation in .h file (InitIglToQgl)
-                               camera stuff still vastly broken (particularly on Linux), need to check in because of new fixes incoming        
-                       djbob   
-                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17
-                       quick fix to spawnflags getting corrupted when multiple entities selected
-                               (doesn't completely solve the problems we have with spawnflags yet though)
-
-===============================================================
-END -- merging release-1_2_9 -> merge-post-1_2_10 into trunk - END
-===============================================================
-
-12/12/2002
-  Hydra
-  - #197, HL support update
-
-11/12/2002
-  TTimo
-  - added cmdlib dependency to mapq3.so (fixes unresolved)
-
-25/10/2002
-  Hydra
-  - vfsGetFullPath() can now (optionally) search PK3/WAD files
-  - Half-life map loading is now un-borked (my original patch worked
-    but some conditional code in the patch was incorrectly applied.
-    That, coupled with the missing vfsFileExists and vfsFindFile replacements)
-  - A patch to imagehl/lbmlib.cpp/LoadIDSP() was missed out, causing all sprite
-    models to be reverse-rendered (due to an inverted alphamask)
-  - Renamed HydraToolz to HydraToolz-HL as it's half-life specific
-    changed project files and renamed all appropriate files and directories
-    (for the merge, just delete contrib/hydratoolz and apply the diff)
-
-  - Comments on previous notes:
-
-    - TODO: need to rationalize where the modules are placed and identify HL specific modules
-      (this affects the build system / post build step too)
-      imagehl and spritemodel are halflife specific and can be placed in
-        either $coreradiantdir/modules or $hlradiantdir/modules
-        I've updated the .dsp files so that they are copied to $coreradiantdir/modules
-        spritemodel can actually be used for other engines, not just HL so it makes sense
-        to keep it in $coreradiantdir/modules
-      hydratoolz is a half-life specific plugin and must go in $hlradiantdir/modules as it
-        is NOT to be used for any other engines.  I've also updated the "about text" to
-        reflect this.
-
-14/08/2002
-  EvilTypeGuy
-  - fix build process for textool plugin on some Linux boxen by including qertypes.h
-
-11/06/2002
-  TTimo
-  - spritemodels in build system
-  - applying HL setup patch (att 270, bug 197)
-    - the templating went one filename seperator too far, causing all *.fgl to be modified .. 
-      fixed so that we only have the relevant changes
-    - modules added to main Executable Files, TODO for later will need to identify what is HL specific
-    - .game generation: don't want enginename yet, gamename is ok
-    - updated HL .game generation for eclass_singleload and no_patch   
-    - update hydratoolz location in setup
-    - update maphl in synapse.config
-
-07/06/2002
-  TTimo
-  - realized that \func doesn't work in doxygen, should be \fn (updated everywhere)
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
-    applying the HL patch (see original list of changes below)
-    - ugly eclass API changes
-      eclassfgd/plugin.cpp.rej, eclass API changes involved, a bunch of .rej
-      SupportsMultiple tries to send configuration information from the eclass format file module to the eclass manager
-      dropping it, using a proper configuration node instead (eclass_singleload)
-    - added "no_patch" prop to disable patch support
-      the patch toolbar prompts are only present in prefs if there is patch support
-      otherwise everything is force-disabled
-    - PFN_VFSFINDFILE PFN_VFSFILEEXISTS:
-      one of the problems we have is that the 'manager' code and file format code are in the same module
-      (i.e. vfspk3 / vfswad: two formats, but the manager part is pretty much the same)
-      vfsFindFile(relative filename):
-        this worked by searching through the list of loaded pk3/wad files for the file
-        then trying to search through the search directories
-        - wasn't properly documented about what it does / how is the search performed
-        - not consistent with existing code, duplicate of vfsGetFullPath for the most part
-          can't be added to the VFS API as-is, it would confuse the interface
-        - usage of vfsFindFile in the code doesn't justify the way it proceeds for search
-        foxing it, replacing by calls to vfsGetFullPath
-      vfsFileExists(relative filename):
-        returns wether a file exist, can be flagged to search in pk3/wad or straight filesystem
-        - this is a duplicate / particular case of vfsGetFileCount
-        foxing it too, we need to extend and update vfsGetFileCount instead
-    - mapq3: the changes completely fucked q3 map parsing
-      need reorganization. same module provides parsing for all .map based formats
-      we use wrappers around the actual calls and globals in the module to select formats
-      MAPVERSION_Q2 and MAPVERSION_Q1 don't need to be there yet, they are not supported
-      MAPVERSION_HL means WC >= 2.2
-      (when introduced, MAPVERSION_Q2 would be Q2 or qer+hl plugin (same))
-      MAPVERSION_HL uses "maphl" minor name (instead of mapq2)
-      cleaned up the Q3 read/write code that got broken
-      cleaned up various commenting/hack that deal with Q2!=HL format .. we'll see about Q2 when we actually do it
-      bad cut and paste from cmdlib code, using actual dependency to cmdlib instead (see below for some cmdlib updates)
-    - took out all SafeRead SafeWrite code from cmdlib, removed annoying cmdlib dependency to Error function
-      all file access go through VFS module, the cmdlib 07/06/2002 15:47file code was way old  
-    - radiant/points.cpp pointfile code changes (that's used only for non-monitored compiling now)
-    - applied patch 267 (hydratoolz fixes)
-    - commented out some bworldcraft flagged stuff in mapq3/parse.cpp
-    - updated the .dsw .dsp to compile and copy HL stuff  
-    - TODO: need to rationalize where the modules are placed and identify HL specific modules
-    - TODO: seems to be a synapse crash when unloading plugins (hydratools)
-      (looks like I didn't look at the plugin unload code yet actually)  
-    - TODO: make sure HL setup puts eclass_singleload="1" and no_patch="1" 
-    - TODO: WATCHBSP_KEY and TEXTURE_KEY hardcoded for HL need cleanup
-    - TODO: imagehl duplicates some image functionality
-      imagehl is supposed to be only for HL-specific image formats
-      it 'adds' the required formats to the stuff that image makes available for everyone already
-    - TODO: HL doesn't have a BSP menu!  
-    - TODO: rename mapq3/ into map/, the map module handles all .map formats
-    - TODO: it's likely that we only need a vfs/ module instead of vfspk3/ and vfspak/
-      think about it, see if we really act on this (or do we need to abstract the manager and some file format modules)
-    - TODO: HL synapse.config needs to use maphl
-    - TODO: wtf is enginename="quake2" in hl.game
-    - TODO: I don't have a sample HL map to play with, so I didn't test the changes against
-
-05/06/2002
-  TTimo
-  - fixups to make 1.3 start (Q3 mode)
-  - turned off C++ exception support in the modules/plugins, as we don't use it
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
-    exit properly if missing chunks in synapse.config, don't crash
-      
-  Hydra
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=558
-    fix for version check in release build
-
-  ======================================================================================
-  -- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
-     HL support patch
-  ======================================================================================
-  04/6/2002
-    Hydra
-    - Patched in some CVS changes and fixed a little issue with the
-      new entity file loader code.
-  
-  28/5/2002
-    Hydra
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=544
-      Selected Entity Bounding Box obscured by brushes fix.
-    - Moved the "wad" keypair creation code from the Map module into
-      a new plugin called HydraToolz, this means that wad keypair is
-      done manually by the user, as in fact it should be.  (as the
-      order of the wads is actually important).
-    - Fixed a problem with the wads in the wad list being re-ordered.
-  
-  27/5/2002
-    Hydra
-    - Created an inital implementation of a sprite model plugin.
-      According to the powers that be, it seems creating a model
-      plugin is hackish.
-      It works ok, but there is no way to attach models (sprites if you will)
-      to non-fixedsize entities (like func_bombtarget)
-      Also, I can't get the alpha map stuff right so I had to invert the alpha
-      mask in the spr loader so that 0xff = not drawn pixel.
-  
-  17/5/2002
-    Hydra
-    - "Wad" keypairs are now used when loading a map and speeds up map loading
-      significantly. This sorts out quite a few issues that could otherwise occur.
-    - Map loader now uses textures from wads listed in the the "wad" keypair first.
-    - Added a texture name mapping cache system to the .map loader
-      this significantly improves load times of maps that don't store texture
-      names along with paths (e.g. "mytexture" not "mytextures/mytexture".)
-    - Added vfsFileExists() to the vfs table (for above) and added it to
-      vfspk3 and vfswad
-    - Map loading and saving times are printed to the console.
-    - Wad file names from the "wad" key pair are logged to the console when
-      a map is loaded
-    - The user is informed if the textures loaded were not found in the
-      wad files in the "wad" keypair.
-    - The user is informed if the textures was not found in any wad file at all
-      (Q2/HL only, the shader module still gives you similar information for other
-      games when a shader activation fails)
-  
-  
-  8/5/2002
-    Hydra
-    - Added basic support in mapq3 for reading maps saved by Worldcraft 2.2+
-      in .map format (It uses [ ]'s round some of the texture co-ordinates)
-      TODO: do we need to be able to save a map in this format too ?
-    - Added support for loading ZHLT style point files (*.lin)
-    - Added wad filename information when loading textures.
-      (This helps take the ambiguity out of which wad files textures come from,
-      so that we can correctly setup the worldspawn "wads" e-pair manually.)
-      Note: This will be removed when the "wads" worldspawn key is built by radiant.
-    - added vfsFindFile() to vfs table.
-    - VFSWAD: vfsLoadFile() no longer ignores paths when loading textures
-      (this was by design, but the design has changed for the better)
-    - When loading a Quake2 map file, vfsFindFile() is used to find the actual path of
-      the shader/texture being loaded.
-      This fixes all the weird issues that crop up when we were able to use non
-      wad-relative texture names (<shader>) and wad-relative(<wadname>/<shader>).
-      (such as having an image loaded twice in memory.)
-      We also now get the correct shader name in the suface inspector too.
-      Note: not sure if this code should stay in the map parser, or wether it should
-      be moved to where shaders are first initialised.
-      Note: maybe this needs to be when a halflife map is loaded, not specifically a
-      quake2 map file.
-    - added EClass_SupportsMultiple to the EClass loader API.
-      Note: this is poop.  FGD files can be additive but radiant makes it so they can't be.
-      This function would not be needed if the eclass loader itself took care of the init,
-      rather then the manager taking care of the init.  Also note that if the loader were
-      to take care of the init then FGD files *CAN* be additive, as it's not down to the
-      format of the FGD files.  However, it'll do for the moment because all the supplied
-      FGD files that come with halflife and it's mods are meant to be used one at a time.
-    - removed support for having an additional (not external) eclass loader.
-      Just ifdef'd for now, grep for USEADDITIONALECLASSLOADER.
-      We never mix entity definition formats and synapse.config allows us to just have the
-      right one and also there is no mechanism for setting g_bHaveEClassExt anymore.
-    - Texture subset on by default for halflife.
-    - default texture scale is now set to 1 instead of 0.5 for halflife.
-      (needs to be 1 for q1/q2 too)
-    - patch toolbar disabled by default for halflife and it's also disabled
-      in the preferences so it can't be turned back on)
-      (needs to be 1 for q1/q2 too)
-    - bsp monitoring disabled by default for halflife
-    - When you drop a light entity the epair "_light" is used instead of "light" (halflife specific)
-    - removed -fs_game additions to the map compiler commands; ZHLT doesn't support it.
-    - saving of contents/flags/values in q2 format maps disabled (ZHLT doesn't like em !#?!)
-      TODO: re-enable for Q2 (but not halflife) format maps when we can
-      can figure out what game/engine combo we're using from within a module
-    - configured mapq3 to have dynamic VFS API too
-    - Added halflife shaderlist.txt parsing back in, it's actually useful
-      afterall (for editor shaders).
-  ======================================================================================
-  -- end HL support patch
-  ======================================================================================
-  
-01/06/2002
-  TTimo
-  - merging 1.2.7 -> 1.2.9 changes into 1.3, merge notes:
-    - the win32 .dsp are a bit different, using the $(CORERADIANTDIR) post build commands now
-    - merged in the JKII/STVEF hardcoded chunks, should probably check that everything is still fine on that end
-      was setting the "dir" epair in project files intead of "gamename" like all other games?
-      (which should really be "fs_game" anyway, I wonder who decided to call it "gamename")
-    - rebuilt a setup. we have a problem with RADIANT_MAJOR RADIANT_MINOR it seems
-    TODO: setup needs to use GtkRadiant-1.<MAJOR> as basename in start menu, and base for installation
-    C:\Program Files\GtkRadiant-1.3 and C:\quake3\Radiant-1.3 etc. for the game packs
-    TODO: add HL setup chunks!
-
-===============================================================
--- merging release-1_2_7 -> release-1_2_9 into 1.3
-===============================================================
-28/5/2002
-  TTimo
-  - final fixes for Linux 1.2.9 setup
-
-27/5/2002
-  TTimo
-  - bug 521, q3 entities.def trigger_hurt fix
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=542
-  default texture scale is configured in .game
-  defaults to 0.5 (q3/wolf) if nothing specified, under the prop "default_scale"
-  removed the item from the prefs dialog too
-  updated the nightly setup to put the proper param in JKII .game
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=509
-  changing texture window scale changes selected brushes texture
-  re-selecting the previous texture can be done, but is a bit tedious to write
-  made sure we deselect before re-init of the tex window view
-  - fixed linux setup code bug. won't be any update, only a full release on linux
-
-26/5/2002
-  TTimo
-       - parallel cons working at last! was a problem with the targets list ('Default' command)
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=515
-       using the eclass extents for the box if model can't be found
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=435
-       changed the submenu cascading params to avoid the overlap (we fit less stuff now obviously)
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=540
-       that sigchld handler is only used on Linux to report the run times
-       since we are rewriting the whole BSP code stuff, we can drop this for now
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=538
-       removed that prompt and display
-       - we build radiant.x86 in cons scripts, updated the setup code
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
-       updated the setup script to install new wolf_entities.def
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=302
-       added q3map2 URL to global.xlink, updated Linux setup
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=465
-       printing q3map version info through the net stream
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=539
-       fixed various media, some related code, and Linux setup
-  - fixed watchbsp.cpp "jk2.game", was breaking game spawn for wolf (needed else if)
-       
-       SCDS_reyalP
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=504
-       fixed bobtoolz vis viewer to work with RTCW (BSP version)
-       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
-       update of the Wolf entities file
-
-25/5/2002
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=164
-  corruption on exit, tried to look some more. Cleaned up some source, need looking at Gtk code closer
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=536
-  cleaned up SHADER_NOT_FOUND SHADER_NOTEX internals some more
-  added a clean error exit in case this happens, fixed a crash that would happen anyway (Patch_LODMatchAll)
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
-  cleanup/sanitize of the pattern filtering code, it was ugly. did some doxygen documentation
-  fixed part of the print XY code, more broken stuff showed up, dropping it
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
-  region compiling was indeed fucked, spog b0rkage
-  fixed so that it works again
-  denying compile with camera out of the region
-  reworked SelectBrush to deal with regioning and select the right brushes
-
-24/5/2002
-  TTimo
-  - Linux build fix
-
-23/5/2002
-  Riant & TTimo
-  - STVEF patch and setup scripts
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516
-  moved error handling code to it's own file radiant/error.cpp
-  compiled with UNICODE define (that's why I had to isolate), and process the error string
-  so that Gtk can print it (that's only relevant to win32)
-
-22/5/2002
-  TTimo
-  - quickfix, cleanup of the console verbosity
-
-11/5/2002
-  TTimo
-  - final IS script updates for JKII game pack, version 1.2.8-jk2
-  - fixed a bad karma #ifdef _DEBUG chunk in Texture_NextPos (causing crash of release build)
-  - added web url support in .xlink files (strstr on http://)
-
-10/5/2002
-  TTimo
-  - cleaned the build step copy from $(QUAKE3RADIANTDIR) to $(CORERADIANTDIR)
-  - system shaders auto-load: display 'system' in the prefs
-  - force BSP monitoring off in jk2 mode
-  - cleaned up web update check, added HL (3) and Jedi Knight II (number 4) (on the web database too)
-  - updated IS setup script for mapextras.pk3
-  Riant
-  - system shaders auto-load in prefs
-  Raven
-  - mapextras.pk3 as replacement for system.pk3 (system editor textures)
-
-8/5/2002
-  Riant
-  - game pack and patches for JKII support
-  TTimo
-  - .game additions to specify .shader path (shaderlist and shader scripts)
-    NOTE: if we ever use q3map for JKII compiles, that would need to be propagated
-  - reworked the shaderlist to list all the included shaders
-  - built a system.pk3 pack for textures/system/ and textures/radiant/ (misses a few pieces still)
-  - MP / SP mapping mode toggle, SP ignores mp_*.def MP ignores sp_*.def
-  - fs_basepath does not get added during BSP command expansion for JKII mode
-  - more verbose on script location and junk.txt location when monitored compile is disabled
-    (the BSP compilation WANTS to be rewritten, it's getting VERY URGENT)
-  - JKII game back IS setup lands
-
-7/5/2002
-  TTimo
-       - using radiant.x86 as Linux target (instead of radiant, didn't fit with the setup procedure)
-       - bumped version tag
-       - TODO: bug #453 code needs backported from 1.3
-
-6/5/2002
-  TTimo
-  - fixed typo in plugins/mapq3/write.cpp Map_Write
-  g_count_entities = 0; instead of g_count_brushes
-  - more fixes which showed up while merging this with 1.3
-
--- release-1_2_7 ----------- tagged and Stable-1_2 merging into trunk
-
-02/5/2002
-  Gef
-  - added filtering on unselect for newly created brushes/entities (bugzilla: #374)
-  SPoG
-  - added undo for pasted/cloned brushes
-
-============================================================
--- end release-1_2_7 -> release-1_2_9 merge
-============================================================
-
-15/05/2002
-  TTimo
-  - rewrote the ref count code cleanly, added some elements to design and todo
-  - wrote the core shutdown code of synapse, 1.3 exits cleanly without crashing (well, in most cases it seems)
-
-10/05/2002
-  TTimo
-  - began writing proper unloading and shutdown of synapse (see libs/synapse/docs/unload.txt) 
-    design doc started, non active modules are unloaded after startup
-    need win32 implementation of ReleaseSO
-  - quickfix on win32 (ReleaseSO)
-  
-07/05/2002
-  SPoG
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=512
-  - cleaned up strHomeMaps and strFSBasePath stuff
-    prompts for maps, models, sounds etc are fs_game-dependant
-
-  ===========================================================================
-  -- merging Stable-1_2 between Stable-1_2-tag and release_1_2_7 into trunk
-  merge ChangeLog
-  =============================================================================
-  07/05/2002
-       - using RADIANT_MAJOR_VERSION and RADIANT_MINOR_VERSION for the version info, this was conflicting with synapse
-       
-       - m_strHomeMaps
-       http://zerowing.idsoftware.com/viewcvs/viewcvs.cgi/GtkRadiant/include/qertypes.h.diff?r1=1.27&r2=1.28&only_with_tag=MAIN
-       http://zerowing.idsoftware.com/archives/gtkradiant/2002-February/002170.html
-       posted on the ML, bringing it back in from 1.2
-       
-       setup scripts:
-         easily merged, as the 1.3 scripts have not been touched mostly
-       
-       qe3.cpp conflict:
-         1.2 tweaks stuff in the QE_*Project* functions
-               1.3 has them mostly commented out
-               applying manually where relevant
-               the project settings stuff is very different, and the changes can't be applied as is
-               given the fixes I had to do in 1.2, I'd expect the current 1.3 version to be fairly broken
-               a complete kill and rewrite of the prefs/project stuff might be our option anyway
-               http://zerowing.idsoftware.com/archives/gtkradiant/2002-May/003038.html
-       qe3.cpp QE_InitVFS conflict:
-         1.3 has some changes when creating the files in a new userprefix (ex. ~/.q3a/baseq3/scripts /maps /maps/prefabs etc.)
-               merged by hand, probably needs to be checked
-       qe3.cpp OpenDialog SaveAsDialog conflict:
-         commented out in 1.3, getting rid of it completely
-       
-       preferences.cpp conflict:
-         1.2 adds CUSTOMSHADEREDITOR_KEY pref
-               1.3 uses a completely different syntax for prefs
-       preferences.cpp conflict:
-               prefab path pref changes conflict with 1.3 pref syntax
-               applying changes manually to 1.3 codebase
-       
-       pmesh.cpp conflict:
-               1.2 adds pref to group / not group patch thickening
-               1.3 changes the way we manipulate entities around that code
-               merged manually, would be worth checking that the thicken pref works
-       
-       pluginmanager.cpp conflicts: synapse completely changes that part
-       on relevant 1.2 thing is the removal of pfnRadiant_Free
-       
-  map.cpp Map_ImportEntities conflict
-               1.3 has bug 453 map conversion promt that was not backported to 1.2 (caused merge to conflict a bit)
-               usin 1.3 code and checking 1.2 changes manually
-  
-       using radiant.x86 as Linux target (instead of radiant, didn't fit with the setup procedure)
-  
-       06/05/2002
-       not merging in .dsw .dsp
-       an eclass.cpp fixed moved to eclass_def.cpp
-       mainframe.cpp is always a bitch to merge, sent several mail comments to list about conflicts that arose
-         MainFrame::OnFileSaveas needed some updates that were not in the diff (correct default prompt)
-               (same for MainFrame::OnFileSaveregion)
-               MainFrame::OnFileNewproject conflicts a bit, changes have been made in 1.2 and 1.3
-               changes in 1.2 seem more crucial, using the 1.2 version, and patched the 1.3 manually over it
-                 (might need to be checked, bug #506)
-      
-       TODO: need to check for parasite g_free that I added back from the file dialog    
-  
-  propagated ChangeLog from Stable-1_2
-  =============================================================================
-       02/5/2002
-         Gef
-         - added filtering on unselect for newly created brushes/entities (bugzilla: #374)
-         SPoG
-         - added undo for pasted/cloned brushes
-         TTimo
-         - shift+left click to open shader editor no longer selects the texture on the way
-           (this was unstable, pCurrentShader could become NULL somehow)
-         - editpad bindings were completely broken
-           attempts to make it work again failed
-               taking it out
-               changed the prefs, on win32 you select between internal shader editor or win32 .shader binding
-               we have lost the ability to jump to a given line, if someone has a good solution for line jumping, let me know
-         - one more fix to the MAJOR / MINOR safe checks stuff
-         - bug #500: oooogly, I removed a line which I should not have :)
-
-       01/5/2002
-         TTimo
-         - "Save selected.." load/save in fs_game sensitive directory too
-         - removed a bunch of unused/broken project settings items
-         removed most of them actually .. project settings are .. ahem
-         - added an optional 'go to url' button in gtk_MessageBox
-
-       30/4/2002
-         Gef
-         - fixed lod drawing of selected patches when patches are filtered
-
-       29/4/2002
-         TTimo
-         - bugzilla #467
-           make patch inspector deny space textures
-           make mapq3 write code drop space textures
-         - bugzilla #132
-           removed remotebasepath and texturepath
-               rewrote the Textures > Load Directory (which was kinda relying on texturepath)
-         - bugzilla #355
-           uploading editpad zip to qeradiant.com misc/ in files section, replacing the win32 message about editpad
-           added editpad quote in qer.com totd
-         - fixing the map load/save dialogs to work correctly with mod settings on win32 (was done on Linux and still broken on win32)
-
-
-       26/4/2002
-         Gef
-         - fixed patches losing their shader if outside region when calling flush/reload 
-           (bugzilla: #492)
-         - blocked textures with spaces from loading in Texture_ShowDirectory with a warning
-           (bugzilla: #467)
-         - fixed a dud shader (liquids.shader -> textures/liquids/ripplewater2_back) didn't have
-           the textures/liquids prefix
-
-       25/4/2002
-         Gef
-         - fixed a broken image link in the shader manual (bugzilla: #486)
-         - changed prtview to use ~/.radiant/<version>/prtview.ini instead of 
-           ~/.q3a/radiant/prtview.ini on linux
-         - fixed prtview loading/saving config (bugzilla: #424)
-         TTimo
-         - removed QERApp_RadiantFree from the function table
-         we can malloc and free across modules configured correctly for the CRT (Common Runtime DLLs)
-         cleaned up related broken malloc / free strategy in the plugins (vfsLoadFile uglyness)
-         - added main build date and version to curry / pk3man / prtview
-
-       23/4/2002
-         SmallPileOfGibs
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=229
-         flush and reload was affecting texturing of selected brushes
-         TTimo
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=489
-         File > Check for update menu item, jumps to the website and checks for update
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
-         win32 part, RADIANT_MAJOR RADIANT_MINOR written out by setup
-         - more stuff on File > New Project and common mod setup issues (not finished yet)
-
-       22/4/2002
-         TTimo
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
-         reworking a bit the installer stuff
-         wrote the version checking
-         needs testing on win32 (RADIANT_MAJOR and RADIANT_MINOR are required in the install now)
-
-       21/4/2002
-         TTimo
-         - trying more seriously to get a new nightly out
-         updating the ChangeLog for current 1.2.7 from this file
-         cleanups, browsing through the bugs to close/update/fix
-         - http://zerowing.idsoftware.com/bugzilla/showattachment.cgi?attach_id=197
-         I kinda fixed that myself already, going through the diff and applying the missing stuff
-         creating the prefabs/ dir in QE_InitVFS
-         - added a line about the games dialog / auto-select at startup in the dialog frame
-
-       15/4/2002
-         TTimo
-         - cleaning some old commented out map load code
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=477
-         on Linux:
-           - strHomeMaps was init without taking care of m_strFSGame
-           - SaveAsDialog was not using strHomeMaps
-           NOTE: should strHomeMaps be spcific to Linux, or we will do better if we unify
-         need similar checks on win32
-
-       13/4/2002
-         TTimo
-         - kicking the source to generate new doxygen on zerowing
-
-       09/4/2002
-         Gef
-         - setting the sel_mode accordingly when (i)nverting selection, verts were being drawn when 
-           they shouldn't have been
-
-       05/4/2002
-         Gef
-         - fix File/New Project for mods so it doesn't fail if the dir exists (bugzilla: #459)
-         - add Linux-isms for New Projects & read/write permissions...
-           note: for a total conversion, basepath needs to be manually set
-         - prevent opening multiple internal shader editor dialogs
-         - added preference for using a custom shader editor
-         - set horizontal scrollbar to be automatic instead of never for entity keyval list (bugzilla: #4)
-         - added a call to Select_Reselect() in XYWnd->OnViewEntity() to make sure its modifying the 
-           current selection (bugzilla: #436)
-         - fixed entity dialog passing events through to main window (bugzilla: #454) return values
-           were backwards
-         - patching in the .pfb extension adding stuff (bugzilla: #259)
-         - fixed thickened patches not being grouped (bugzilla: #226). this was supposed to be happening
-           anyway, the entity create code was called before the patches were selected
-
-       02/4/2002
-         EvilTypeGuy
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=457
-         add entity #X and brush #X comments back to saved .map files
-
-       24/3/2002
-         Hydra & TTimo
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=444
-         only show empty alpha channel warning if the tga texture is actually 32 bit
-         (24 bit would always have empty alpha, the warning was useless in this case)
-
-       19/3/2002
-         Gef
-         http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=217
-         - Set show value to true for angle and movement velocity sliders in preferences
-         - Increased the maximum value of angle velocity from 6 to 100
-
-       18/3/2002
-         SPoG
-         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=419
-               fixed File->Save with region active acts the same as File->SaveRegion for ents
-
-
-  end merge  
-  =============================================================================
-
-16/4/2002
-  SPoG
-  - fixed MDC_XYZ_SCALE value
-
-12/4/2002
-  SPoG
-  - fixed win32 compile error - vc6 being nitpicky
-  - fixed refcount init on CSynapseAPIManager
-  - cleaned up md3model win32 project file
-
-9/4/2002
-  Gef
-  - added nudging for selected brush and patch vertices (bugzilla: #240)
-  - added selected brush vertex highlighting
-  - sorted all the ID_'s in HandleCommand alphabetically to make it easier to track things down
-  - setting the sel_mode accordingly when (i)nverting selection, verts were being drawn when 
-    they shouldn't have been
-
-5/4/2002
-  EvilTypeGuy & djbob
-  - patched in djbob's grid minor/major color settings for gridsize < 1
-    http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=24
-
-1/4/2002
-  TTimo
-  - configured md3model to have dynamic VFS API too
-  - cleaned up texwindow.cpp texture extension loop
-  - updated current HL media with hl's synapse.config
-    http://zerowing.idsoftware.com/stuff/HL-media-0401.zip
-  - checking in new synapse.config for Q3/RTCW
-  - fixed win32 project files, removed hltoggle.h
-  - bumped version to 1.3.3
-  
-31/3/2002
-  TTimo
-  - XML runtime configuration of synapse
-  uses a synapse.config in the gametools path, we can add a line in the .game to specify the file later on
-  - various cleanups and removal of dead code
-  - Linux build system: sanitized CFLAGS, libxml, STLPort and glib include path all in the toplevel Construct file
-  - removed the 'cons -- halflife' option, the binaries are unified again
-  - cleaned up image loading
-
-
-29/3/2002
-  TTimo
-  - patching in Hydra's code for Half-Life, builds and runs on Linux, need to quickfix on win32 now
-  - build system on Linux: some things are still hardcoded into the core, you need a different core
-    for Q3/RTCW or HL for now. do ./cons -- halflife to build HL mode (build trees are seperate)
-  - there is no media / install procedure yet, but a zip with what you may need for install is available:
-    http://zerowing.idsoftware.com/stuff/HL-media-0329.zip
-  - cvs added all the new files
-  - patched various things from the patches, don't have a precise list
-    cleaned up the interface requests, isolated HL specific between TMP_HALFLIFE defines
-    removed 'tga' from imagehl, two modules providing the same API has unexpected results
-    
-  TODO: the image loading is the main problem right now. We should not have any place that scans the 
-  extensions, this is done internally to the image load manager? texwindow.cpp does enumeration of the
-  minors too .. but that may be legal in this case.
-  
-  TODO: synapse config at runtime through XML (rather big piece)
-
-  - fixing build on win32
-  bad coding practices: 'for (GSList *choicelst = ..'
-  added a quick hack include/hltoggle.h for easy switch q3/rtcw or hl compile
-    (remaining hardcoded stuff is temporary)
-
-
-28/3/2002
-  Gef
-  - added linux pthreads support to tools
-  - removed old terrain.c and lightv.c from q3map2 Conscript
-
-27/3/2002
-  Gef
-  - updated cons for q3map 2
-  - minor q3map2 fixes for linux compile errors/warnings
-  - minor warning fix in map.cpp
-  SPoG
-  - changed entity_addtolist to add entities to end of list instead of beginning
-  - added eclass_forname to eclassmanager interface
-  - fixed setting eclass before model-update for entities loaded from map
-  - fixed setting bounding box for models after model-update
-  ydnar - q3map2
-  - fixed crash on -connect and other gremlins related to argument processing
-  - removed flag that prevented Castle's maps from compiling
-
-
-27/3/2002
-
-  Hydra
-
-  Important Changes:
-
-  - Added VFSWAD modules for extracting textures from WAD files.
-  - Added ImageHL for loading textures contained in WAD files
-  - Updated shaders source code so that you can produce ShadersHL.dll
-    (single minor using #ifdefs)
-  - MapQ3 source updated so that it can load and save q2 format maps
-    provides a multiple minors.
-  - Added EClassFGD for loading FGD definition files
-    (I documented this code quite well, if you're interested...)
-  - Added support for iconsprite() settings in the FGD loader, we set
-    eclass_t->skinpath with the name of the sprite
-    TODO: write a sprite model plugin.
-
-  Fixes:
-
-  - Fixed incorrect line numbers being reported when script files had // comments in them
-  - Removed EClass_Create from the EClass manager _EClassManagerTable
-  - Replaced all occurences of "textures/radiant/notex" in shaders.cpp with a define.
-  - Fixed a crash in shaders.cpp when there was no default texture.
-  - Fixed a possible issue with g_bCancel_Map_LoadFile
-  - Added a crash fix for uninitialised patchMesh_t->pSymbiot
-
-  Core Changes Required for HalfLife Support:
-
-  - Set MAX_FLAGS to 16 to support Halflife's extra spawnflags, adjusted
-    entity inspector to display the new spawnflags, updated FGD loader
-    to load them correctly (previously it only loaded the ones with values <8)
-    (Done without breaking the old Q2 code that was commented out)
-  - Added GetTokenExtra to the _ScripLibTable
-  - Kludged texwindow.cpp to allow loading extension other than "tga" and "jpg"
-    TODO: ttimo, we need something in synapse to help with this.
-  - Plugin manager requests different API's depending on .game file used.
-    TODO: this needs to be done on a PER GAME basis, not PER .GAME FILE.
-  - Shaderlist.txt is not parsed on startup if hl.game is used.
-    TODO: this needs to be done on a PER ENGINE basis, not PER GAME.
-
-  Cosmetic Changes:
-
-  - Changed MAPQ3's minor_name from "map" to "mapq3" (also adds "mapq2" as a minor)
-  - Changed XMAP's minor_name from "xmap" to "mapxml"
-  - Changed VFS's minor_name from "quake3" to "pk3", more inline with VFSWAD now.
-  - Changed file/Load to file/Import on the menus
-  - When a shader (Q3/HL) is not found a message is displayed in the console
-    (only once for each shader that is not found).  This is so the user can
-    quickly get a list of missing textures/shaders.
-
-26/3/2002
-  ydnar
-  - initial q3map 2.0 source import
-    new tools/quake3/q3map2 directory
-         common/qfiles.h and common/surfaceflags.h modified
-         affects q3map 1.x too, bumped MAX_MAP_BRUSHSIDES to 0x40000
-         will need to write the build scripts and compile on Linux too
-  SPoG
-  - Re-added dialog prompting user to convert/change-mode/abort when map BP mode
-    conflicts with project settings
-  - large entity/models update
-  +++ include/ientity.h   25 Mar 2002 11:37:54 -0000
-    entity module
-      - interface cleanup
-      - common #defines for easy transition
-  +++ include/igl.h       25 Mar 2002 11:37:55 -0000
-    opengl module
-      - Vertex Arrays support
-  +++ include/imodel.h    25 Mar 2002 11:37:57 -0000
-    model module
-      - interface cleanup
-  +++ libs/mathlib.h      25 Mar 2002 11:37:59 -0000
-    vector macros - cleanup
-    m4x4
-      - documentation of matrix layout
-      - interface for utility functions for axis-angle and quaternion rotations
-      - interface for new utilities for specifically transforming points/normals 
-    aabb
-      - interface for faster aabb-ray test without finding intersection point
-      - interface for utility to calculate an aabb to contain a transformed aabb 
-  +++ libs/mathlib/bbox.c 25 Mar 2002 11:38:01 -0000
-      - cleanup of use of qboolean
-      - implementation of fast aabb-ray-test
-      - implementation of aabb-for-transformed-aabb
-  +++ libs/mathlib/m4x4.c 25 Mar 2002 11:38:02 -0000
-      - implementation of utility for rotation matrix from axis-angle/quaternion
-      - cleanup of implementation of matrix multiplication functions (optimise for in-order array traversal)
-      - implementation of new utilities for specifically transforming points/normals
-  +++ libs/mathlib/ray.c  25 Mar 2002 11:38:02 -0000
-      - replace use of m4x4_transform_vec3 with new point/normal specific utils
-  +++ plugins/mapq3/plugin.cpp    25 Mar 2002 11:38:06 -0000
-      - rename g_EntityTable using #define in ientity.h
-  +++ plugins/mapq3/plugin.h      25 Mar 2002 11:38:06 -0000
-      - rename g_EntityTable using #define in ientity.h
-  +++ plugins/mapxml/xmlparse.cpp 25 Mar 2002 11:38:06 -0000
-      - buffer-safe dtd path construction (without using string class, in case of unknown bugs)
-  +++ plugins/md3model/Conscript  25 Mar 2002 11:38:06 -0000
-      - remove entity-module files from md3model conscript 
-  +++ plugins/md3model/md3model.cpp       25 Mar 2002 11:38:07 -0000
-      - implementation of generic quake-style-model class CModel
-      - implementation of CModel-derived md3/mdc classes
-  +++ plugins/md3model/md3model.dsp       25 Mar 2002 11:38:08 -0000
-      - remove entity-module files from md3model dsp
-  +++ plugins/md3model/md3model.h 25 Mar 2002 11:38:08 -0000
-      - interface for generic quake-style-model class CModel
-      - interface for CModel-derived md3/mdc classes
-  +++ plugins/md3model/md3surface.cpp     25 Mar 2002 11:38:09 -0000
-      - implementation of generic quake-style-model class CSurface
-      - implementation of CSurface-derived md3/md2/mdl/mdc classes
-  +++ plugins/md3model/md3surface.h       25 Mar 2002 11:38:09 -0000
-      - interface for generic quake-style-model class CSurface
-      - interface for CSurface-derived md3/md2/mdl/mdc classes
-  +++ plugins/md3model/plugin.cpp 25 Mar 2002 11:38:10 -0000
-      - provide support to synapse for loading md3/mdc/mdl/md2 models, and mdl images
-  +++ plugins/md3model/plugin.h   25 Mar 2002 11:38:10 -0000
-      - interface for loading md3/mdc/mdl/md2 models, and mdl images 
-  +++ radiant/brush.cpp   25 Mar 2002 11:38:18 -0000
-      - #ifdef remove Group/Brush-Patch-Epair related stuff
-      - const correctness for ValueForKey interface const change
-      - add bounding-box update for models in Brush_Build
-      - remove old brush parsing/writing stuff
-      - remove old eclass-model loading/displaying stuff
-      - enable vertex arrays on light drawing
-      - moved brush is-selected? utility to brush.cpp
-  +++ radiant/brush.h     25 Mar 2002 11:38:18 -0000
-      - comment out interface for old brush parse/write stuff
-      - comment out interface for brush epair stuff
-  +++ radiant/brush_primit.cpp    25 Mar 2002 11:38:20 -0000
-      - remove old brush-primitives parsing/writing stuff
-  +++ radiant/camwindow.cpp       25 Mar 2002 11:38:23 -0000
-      - moved brush-bbox update for models to brush.cpp:Brush_Build
-      - bugfix for material colour setting when drawing models
-  +++ radiant/eclass.cpp  25 Mar 2002 11:38:24 -0000
-      - removed old eclass-model checking/loading stuff
-      - added const checking for Eclass_ForName interface
-  +++ radiant/entity.cpp  25 Mar 2002 11:38:26 -0000
-      - REMOVE THIS FILE
-  +++ radiant/entity.h    25 Mar 2002 11:38:26 -0000
-      - REMOVE THIS FILE
-  +++ radiant/groupdialog.cpp     25 Mar 2002 11:38:29 -0000
-      - change entity creation to not use Entity_Create (function was removed)
-      - commented groups stuff
-  +++ radiant/gtkdlgs.cpp 25 Mar 2002 11:38:36 -0000
-      - const correctness for ValueForKey
-  +++ radiant/gtkmisc.cpp 25 Mar 2002 11:38:39 -0000
-      - added filetype patterns for mdc/mdl/md2
-  +++ radiant/main.cpp    25 Mar 2002 11:38:41 -0000
-      - const correctness fixes
-  +++ radiant/mainframe.cpp       25 Mar 2002 11:38:59 -0000
-      - change selection -> merge entity and selection -> separate from entity to go through mainframe class
-      - implementation of mainframe functions for selection -> merge entity and selection -> separate from entity
-      - made entity grouping and detail/structural settings undoable
-      - commented out old groups stuff
-  +++ radiant/mainframe.h 25 Mar 2002 11:39:01 -0000
-      - interface for mainframe functions for selection -> merge entity and selection -> separate from entity
-  +++ radiant/map.cpp     25 Mar 2002 11:39:04 -0000
-      - const correctness fixes
-  +++ radiant/pluginmanager.cpp   25 Mar 2002 11:39:08 -0000
-      - removed model table
-      - stopped requesting model table from synapse
-      - request undo table from synapse
-      - commented out support for IEpairs stuff - NOTE: to be integrated with entity module
-      - fill interface table for opengl vertex array support 
-      - fill interface table for undo
-  +++ radiant/pmesh.cpp   25 Mar 2002 11:39:18 -0000
-      - cleanup patch cap and patch thicken to create entities using entity module interface (without Entity_Create)
-      - removed old patch parse/write stuff
-      - #ifdef'd out patch epair/groups stuff
-  +++ radiant/qe3.cpp     25 Mar 2002 11:39:21 -0000
-      - const fixes
-      - buffer-safe dtd path construction (without using string class, in case of unknown bugs)
-  +++ radiant/qe3.h       25 Mar 2002 11:39:24 -0000
-      - don't include entity.h, include ientity.h and forward-declare entity-table instead
-      - include imodel.h but don't forward declare model-table
-      - include iundo.h and forward-declare undo table
-      - comment out interface to old patch parse/write stuff
-      - comment out interface to old brush parse/write stuff
-      - comment out iepairs header include.. NOTE: to be integrated with entity module/interface 
-      - include eclass interface (we don't have an eclass.h)
-      - declare interface for CreateEntityFromName (generic useful func)
-      - declare target/targetname utils interface (we don't have a targetname.h)
-  +++ radiant/select.cpp  25 Mar 2002 11:39:27 -0000
-      - cleanup implementation of entity selection-grouping/ungrouping utlities
-  +++ radiant/select.h    25 Mar 2002 11:39:27 -0000
-      - cleanup interface for entity selection-grouping/ungrouping utlities
-  +++ radiant/undo.cpp    25 Mar 2002 11:39:29 -0000
-      - removed workaround for wierd entity_clone behaviour (changed in entity module)
-      - avoid using Entity_FreeEpairs (not exposed by entity module)
-  +++ radiant/xywindow.cpp        25 Mar 2002 11:39:35 -0000
-      - const fixes
-      - cleanup implementation of CreateEntityFromName to be a usful generic utiliy function
-      - enable vertex arrays in XY_Draw
-      - enable undo for right-click dropping entities in XY window
-  TTimo
-  - various fixes to make the above compile on Linux, checkin to cvs
-  - fixing some win32 build stuff
-  
-  Hydra
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=434
-  fixed setSpecialLoad in .def code
-
-19/3/2002
-  Gef
-  - Modified the fix for LoadImage to be more consistent with other code
-  - Applied Hydra's fix for empty alpha channel warnings & cleaned up indentations (tabs) in lbmlib.cpp
-    also added output of the tga type when a tga file fails to load
-  - Reverted my over complex fix (read; mess) for strtok_r to use strtok instead of manual tokenising
-
-17/3/2002
-  Gef
-  - Fixed LoadImage API list not being incremented while trying to find image minors, result was
-    infinite loop when loading images that weren't of the first type (tga)
-  - Fixed cloning giving dtd errors. mapxml/xmlparse.cpp:ParseXMLStream() was using 
-    g_FuncTable.m_pfnGetQERPath() as the dtds path... disabled validation until spog can check 
-    that my fix is the right solution
-  - Added simple formatting to xmap file output so that each node has a new line for readability
-
-13/3/2002
-  TTimo
-  - introduced API List managers
-    we deal with two types of APIManager now, the ones that matching all minors for a given major
-    and the ones that require a fixed list of minors
-  - converted the image loaders to go through a API list manager
-  - fixed various things in synapse (introduced more bugs?)
-  - fixed plugins, realized it was still broken
-
-12/3/2002
-  Hydra & TTimo
-  - EClass_Create in the EClass manager _EClassManagerTable
-  - removed InitFromText from _EClassTable
-
-8/3/2002
-  TTimo
-  - some commented out code cleanups
-  - added eclassfgd/ fgd.so module skeleton
-    loaded up in radiant core as an optional entity format
-    added eclass manager code to deal with the new format if present
-    this still loads .def, the actual .fgd code needs to be written now
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=433
-    added a g_strDTDPath global
-    disabled DTD validation, broken on win32
-  - Str copy constructor (const Str &) working correctly with a __strDup
-
-7/3/2002
-  TTimo
-  - added verbosity in file accesses for CXMLPropertyBag
-  - more fixes to project lookup
-  - dropping dtds/ prefix, this is installation dependent
-  - removed ipluginentities.h, the plugin entities stuff was disabled long time ago already
-  - cleaned up some old commented out stuff
-  - proof of concept synapse builtin module: new class CSynapseClientBuiltin allows to have
-    modules builtin to the application (i.e. statically linked)
-    adding
-      include/ieclass.h (eclass loader API)
-      radiant/eclass_def.cpp (.def class loader, builtin)
-      radiant/eclass_def.h (.def loade, API public to the core)
-
-    NOTE: radiant/eclass_def.cpp needs to be added to the win32 projects  
-  - quickfix to project file loading ("/scripts/")  
-  - introduced an EClass manager, hooked up the .def builtin module through it
-    (not yet possible to push new entity format modules, but .def reading is already fully synapsed)
-
-6/3/2002
-  Gef
-  - Fixed a segfault when getting mUserPathPrefix in CGameDescription::CGameDescription()
-  - added preferences check for fixing target/name collisions
-  - fixed a logical error on my part, where setting g_qeglobals.m_strHomeGame in
-    CGameDescription constructor results in a value from the last file parsed. Moved it
-    to a more appropriate location, where it gets a value from the selected .game file.
-  SPoG
-  - changed g_strGameToolsPath to g_strAppPath in GetQERPath API
-  - fixed mapq3.dtd
-  - enabled DTD validation of xmap files
-  - added mapq3.dtd to setup scripts (not tested)
-  TTimo
-  - added OnActivated() to synapse clients, override to put some init code
-  - fixing default project path lookup and user project increment (again)
-  - fix to linux setup, no trailing slash in basegame items
-    (wolf.game and q3.game)
-  - removed old plugin/modules code, leaving only the synapse implementation
-    recoded image loading and Map_Import/Map_Export  
-    still some temporary solutions and cleanup work to be done
-    removed plugin.cpp from the tree / build system
-
-5/3/2002
-  SPoG
-  - TODO: add default project for wolf to WolfPack CVS module
-  - changed xml project file load to search for DTD "dtds/project.dtd" under radiant path
-  - fixed crash in mapq3 on trying to read uninitialised token ptr
-  - changed .map to be default map format for now
-  - changed runbsp to not hardcode -fs_basepath
-  - added -fs_basepath to quake3 default project
-  - added project.dtd to setup scripts and swapped quakev2.qe4 for default_project.proj (not tested)
-
-4/3/2002
-  TTimo
-  - merged synapse2 branch back into trunk, checked Linux and win32 builds ok
-  - updated the .dsp to work with new libxml2 2.4.16
-  - fixed broken enginepath guessing, and broken project path rotation / saving
-
-28/2/2002
-  Gef
-  - Added extra checks for target/targetname collisions
-  - Find Brush dialog title correction (bugzilla #393)
-
-26/2/2002
-  Gef
-  - Added Entity_Connect() to entity.cpp to avoid duplicating code
-  - Fixed target/targetname collisions - entities being cross-linked when copied
-    Bugzilla #385 : http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=385
-
-16/2/2002
-  Gef
-  - cleaned up the kyro gl_point workaround stuff
-  - taught ClipPoint's (clips & path points) how to draw themselves
-
-8/2/2002
-  Gef
-  - Added mapxml.so to linux setup
-  - strip debug symbols option in setup
-  - removed g_qeglobals.m_strHomeMaps, writing it to project instead
-    fixes a bunch of re-broken path issues. Also uses fs_game now.
-  - Minor grid colour in QER Black & Green theme
-  - Save window's pos/size for all view types in MainFrame::OnDestroy
-
----------------------------  on branch synapse2
-4/3/2002
-  - modules don't show up in plugins menu, added a dump in console before entering interactive mode
-  - added compile time def for synapse verbosity
-
-3/3/2002
-  - finished converting all the modules to synapse, disabled old ResolveInterface call
-
-24/2/2002
-  - hooked TexTool into Radiant plugin menu through synapse
-  - added iplugin.h which I had forgotten earlier
-  - ported synapse code to compile and run on win32
-
-19/2/2002
-  - SYN_REQUIRE_ANY / multiple API manager code
-    can load multiple interfaces based on a matching pattern
-    converted TexTool to load that way
-
-18/2/2002
-  - added iplugin.h with basic interface for plugins  
-
-13/2/2002
-  - synapse on modules currently disabled,
-    the basics of the code are working fine, need to look at multiple interfaces matches before going further
-  - started converting shaders, requires conversion of a lot more others
-  - image converted to synapse
-  - no longer using GUID in synapse, all done through *_MAJOR strings
-  HOWTO: convert a module to synapse:
-    configure it to link against synapse static lib
-    (+include path to STLPort required)
-    add #include "synapse.h" to the plugin header
-    declare the : public CSynapseClient in plugin header
-    implement it (listing provides and requires, implement the request code)
-
-12/2/2002
-  - vfspk3 converted to synapse
-
-11/2/2002
-  TODO: get rid of all WINAPI crap
-  - debugged the API dependencies solver to actually work  
-  - added newer cons at the head of the tree
-
-10/2/2002
-  TTimo
-  - added the basic code for solving API dependencies and requesting the various tables
-  - more diagnostic printing code fixes
-  - version checkings
-  - some more design work (libs/synapse/doc)
-
-9/2/2002
-  TTimo
-  - some changes to the files layout, cleanup of the diagnostics printing
-  (stuff's mostly broken right now)
-  - reworked the complete Sys_Printf stuff to rely on va_list implementation
-  - include/isynapse.h declared useless and foxed without mercy
-  - added include/irefcount.h
-
-8/2/2002
-  TTimo
-  - adding an experimental Anjuta project file to play around with
-
-7/2/2002
-  TTimo
-  - various fixes to build on linux, listed a bunch of current issues
-  - fixing terrademo.map to remove broken mapobj~1 -> mapobjects
-  -- synapse2 branch --
-  - propagate the code from old synapse branch to a new branch out of 1.3 tree
-    (builds and runs on linux, that's about it for now)
-
---------------------------- end branch synapse2
-  
-7/2/2002
-  djbob
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=354
-  moved all the preferences code to XML
-
-6/2/2002
-  SPoG
-  - checked all paths conform to: unix dir separators + trailing separator
-  - changed file dialogs for load/save of maps to default to "mapspath"
-  - removed OpenDialog and SaveAsDialog, use file_dialog instead
-  - removed FileSystem paths stored in QEGlobals_t.. replaced by CGameDescription
-  - removed dependence on EnginePath from preferences, replaced by CGameDescription
-  - removed hardcoded g_get_home_dir calls for file dialogs
-  - added validation of project settings entry paths before they are set
-
-5/2/2002
-  EvilTypeGuy
-  - moved filters.cpp related function declarations to filters.h
-    and added #include "filters.h" to brush.cpp, csg.cpp, main.cpp,
-    mainframe.cpp, map.cpp, select.cpp as not all files include
-    qe3.h and qe3.h is a rather monolithic header this seems to be
-    a cleaner solution per SPoG's suggestion...Fixes compilation.
-
-  Gef
-  - contrib/plugins BOOL cleanup (uses qboolean now) fixes X header conflict
-  - cons update for mapxml
-  - SaveAsDialog() changed to match path's used in OpenDialog()
-  - removed radiant/xy.h - moved contents to qe3.h (FilterBrush declaration)
-
-4/2/2002
-  SPoG
-  - changed QE_LoadProject and QE_SaveProject to load/save xml project file format
-  - changed request dialog for project files to loop until a valid file is found
-  - fixed memleaks in CGameDescription constructor for xmlGetProp
-  - added converting gametoolspath unix format when parsed from game file
-
-  - fixed m4x4 lib to use column-major order (more compatible with opengl)
-  - added divergence parameter to ray-point intersection test
-    (now easier to select distant points in perspective views)
-  - cleaned up modelview/projection matrix manipulations in 2d/3d view
-  - cleaned up map modules / interface source files a bit
-
-  - added ability to specify map module version when importing/exporting map
-  - cleaned up file dialog code, returned filename is static and in unix format
-  - save-as dialogs force a file extension depending on filetype selected
-  - added filetype manager to support registering custom file types
-  - fixed loading and cleaning engine path from radiant.ini correctly
-
-3/2/2002
-  EvilTypeGuy
-  - fixed win32 compilation (userpathprefix is Linux specific)
-
-  ETG & Powzer
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=308
-    added preference to allow 'paint drag-select' brushes/faces in 3d camera view
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=389
-    added preference to strafe camera foward/back in 3d view while freelook is active
-
-  ETG & RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=388
-    patch adds ability to strafe up/down/left right while freelook is active
-
-1/2/2002
-  TTimo
-  - bumped to 1.3.1-nightly
-
--- 1.2 stable branch branched here
-
-  Gef & TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=372
-    http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=376
-    appplied the patch, corrected the mapspath expansion stuff
-  TTimo  
-  - linux nightly setup code
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=384
-    hacked a corrective action in the nightly setup
-
-  SPoG
-  - fixed creating region brushes that fill the entire grid for Save Region
-
-31/1/2002
-
-  Micheal Schlueter
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=375
-  syntax fix to q3map path_init.c
-  
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
-  patch 185 == 186
-  tweaking to config stuff in linux setup
-  patch 187
-  Ensures the games directory exists before trying to create a file there
-  patch 177
-  Adds *.cf files & uses them. I think I have all the files in the right places now... maybe
-  (some additional fixes on top by me)
-  
-  ETG
-  quick fix to shader prefs load
-
-29/1/2002
-
-  EvilTypeGuy
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=345
-  more detachable menus fixes
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=334
-  fixes 'load shaders at startup' preference
-
-  SPoG
-  - fixed misc_model "modelscale" and "modelscale_vec" support
-  
-  TTimo
-  - upgraded setup scripts to support nightly build
-  - last minute fix to the modelscale and modelscale_vec code (md3 module)
-
-  ydnar
-  q3map 1.2.4-y2
-
-    New features:
-    - -nopatchfix argument. This disables lightmap patch fixes and makes a map suitable for lighting with -vlight.
-    - Degenerate patches are treated like broken brushes. They are ignored, warned about, and selected in Radiant if you ran with the -connect option (or from the BSP menu). This was what was causing the "0 valued axis" error some people were experiencing.
-
-    New entity keys:
-    - "_lightmapscale" key for brush entities (worldspawn, func_*). This lets a mapper scale the lightmap samplesize per-entity. For large constructions, 2.0 or 3.0 is a fine value, and keeps BSP size down and compile times low. For those areas you want to have high-detail shadows, make a func_group and use a value of 0.25 or so. It will scale the samplesize value for the surface's shader (default 16) or the -samplesize argument.
-    - "modelscale" and "modelscale_vec" keys for misc_models (1.0 = default). This was for proper RTCW support and is available for Quake 3 maps as well. Lets you scale up map models in the world, getting around the MD3 size limitation. The next build of GtkRadiant has SPoG's code to support this in-editor so you can see what effect a scale has.
-    - Flare surfaces are now supressed from the BSP. They serve no purpose other than add to the vert & surfacecount in a BSP. These surfaces were created silently when a shader has "light 1" or "q3map_flareshader X." Use the new -flares switch when BSPing your map to have them emitted.
-
-    Changes:
-    - GtkRadiant 1.2.4-nightly version increment.
-    - Full WolfSDK style lighting enabled with -game wolf, including lightJuniors. This includes linear lights by default (no angle attenuation) and support for the additional RTCW "fade" and "angle" keys, and spawnflag changes, including q3map_nondynamic on light entities. This may require maps being constructed for RTCW with the current toolset to change their light entities. Sorry. :) Note, Wolf-style lighting only works with -light, and not -vlight.
-    - Vertex light stitching now uses a near-ambient light check for dark vertexes as opposed to lower-than-average fixups. This preserves some shadow detail better while getting the buried verts lit properly. Comments encouraged.
-    - Surfaces' samplesize are now stored in the BSP. This change makes BSPs generated from this version incompatible with all other q3maps. The upside is that -samplesize N is no longer necessary on the -light or -vlight stage. This feature is necessary to support the "_lightmapscale" key.
-    - Additional PVS optimizations in lighting.
-
-    Fixes:
-    - Will compile for RTCW properly (1.2.1-y12 didn't).
-    - No more sparklies where fog meets brush faces. They're split properly now.
-    - Crash bug in vlight fixed.
-    - Vertex light fixups/stitching is considerably faster.
-    - Vertex light fixups ONLY stitch faces with lightmaps. For pointlight surfaces you're on your own.
-    - Better snapping logic when merging nearly-coincident vertexes on complex brush windings.
-    - Bug where the .prt file had some bogus or nearly-borked portals. They're cleaned up like everything else now.
-    - A few stupid bugs in path initialization. Should work better. Also includes TTimo's fixes to my code so it would work properly on Linux.
-    - RR2DO2's PCX loading patch for alphamaps. This bug was manifesting itself in the form of offset or incorrect samples being used on terrain entities.
-    - A ton of other minor little fixes here and there.
-
-28/1/2002
-
-  TTimo
-  - win32 fixes
-  - 1.2.4-nightly
-
-  djbob
-  - EClass_ForName fix if malformed name
-
----- 1.2.3 linux released
-
-  TTimo
-  - fixed BSP version depending on game mode in q3map
-    (home dir guessing is still fucked, have to fix before release)
-  - fixed q3map init_path.c home path bug on init
-
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=369
-    more fixes to texture paths in gensurf
-
-27/1/2002
-  TTimo
-  - switching to v3 project file, forcing reload of template if non-v3
-  need to distribute quakev3.qe4 in setups now (done for linux setup, will have to in win32)
-  - renamed Main to main in q3map init paths
-  - fixes the ~/. inits and init order in q3map
-  - added m_pfnPathForPluginName to the main function table, returns the directory a plugin is running from
-    used in bobtoolz / curry / pk3man to find various files
-    see also todo: http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=368
-  - some fixes to textures loading paths in curry
-  - linux setup copying correct content for curry (pk3 in wolf media) and bobtoolz (bt/ in plugins/)
-  - building 1.2.2 setups  
-  
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=362
-  gensurf fix
-  
-  djbob
-  - bobtoolz update
-  
-  Hydra
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=361
-  fixes a bug with the texture menu loading, now we see the non-shaderlist directories too
-
-26/1/2002
-  Gef - Michael Schlueter - TTimo 
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
-  applied several patches (to setup code and to the setup scripts)
-  modified makesdk.pl to update with more content
-  added an "enginepath" attribute to the game file, reworked the handling in editor
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=347
-    took out the refresh command from the plugin menu
-  - more linux fixes:
-    bringing all the plugins to compile again on linux
-    polishing the setup code (all the right files in the right places)
-  - for linux release, bumping ver to 1.2.2
-    win32 will have a 1.2.3-nightly after that
-  - added correct init of ~/.q3a or ~/.wolf
-    *nix systems have a 'prefix' attribute in the .game file to specify
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=359
-    identified the mod compiling problems
-    applying back the old fs_basepath fs_game code to the BSP generation
-    
-  ydnar- TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=351
-    cleaner path init code
-    it doesn't init for ~/.q3a and ~/.wolf paths yet
-
-25/1/2002
-  SPoG
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=352
-  using the wrong matrix stack for XY_Draw caused stack overflow error
-  - texture_mode was set to an invalid enum in wireframe/flatshade mode
-  - changed plugin API to expect gamedir-relative texturenames
-  - fixed gensurf to create faces/patches with gamedir-relative textures
-
-24/1/2002
-  SPoG
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=322
-  added modelscale key check to misc_model entity in md3/entity module
-  added angle key check to eclassmodel class in md3/entity module
-  fixed bugs in BP writing and reading in map module
-  TTimo (commited as SPoG)
-  - fixing permissions on cvsreport and doxygen stuff, upgraded dot
-
-23/1/2002
-  SPoG
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=336
-  plugin API bugfix - fixes textures on stuff created by plugins
-
----- 1.2.1 was released here
-
-22/1/2002
-  Gef
-  - linux build fixes
-  SCDS_reyalP
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=325
-  wrong file packaged in setup
-  RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=327
-  fix to PCX loading  
-  SPoG
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=298
-  cut & paste bugfix
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=332
-  update origin key on entities
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=333
-  made fixedsize entities not scalable
-
-21/1/2002
-  TTimo
-  - scanning in g_strAppPath/modules/ and plugins/ prior to g_strGameToolsPath
-  using the main path to put general plugins and modules
-  - fixed bobtoolz bug, init of epairs table was relying on wrong params
-  - fixed curry to compile again on 1.2
-  - fixed pk3man to compile again on 1.2
-  - updated IS setup:
-    installing the plugins with the core
-    installing the common modules in the core
-  - Compiling manual, more IS stuff, .xlink etc.
-
-  RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=315
-    patches for improved multimonitor support (with some associated pref items)
-
-  ydnar
-  - more q3map: http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=324
-    - radiosity fixes (proper handling of ambient light)
-    - polygonoffset fixes
-    - lightmaps on patches work better (normal calcs adjusted, planar patches are 
-      box projected like brush sides)
-    - double vfs init in bsp stage removed (this needs to be tested on Linux)
-    - lighting is faster again
-    - a couple crash bugs resolved
-    - other tasty nibbles
-
-20/1/2002
-  EvilTypeGuy
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=313
-  detachable menus set as preference (in layout)
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=255
-  path prompt
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=307
-  patch dialog names
-  ETG & RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=306
-  fix 'Natural' texturing crash
-  ETG & TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=291
-  found out the problem, Wolf SP spawn works now
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=144
-  fixed more problems with model loading vfsExtractRelativePath
-  prolly broke the linux build, just a matter of putting a bunch of #idfdef
-  - fixed an additionnal .pid lock situation, cleaning the global prefs on game .pid lock
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=301
-  fixed md3 tris test selection bug
-  djbob
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=219
-  fixed bobtoolz for 1.2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=318
-  filter structural
-  RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=305
-  filter in viewmenu for lightgrid brushes (ydnar's q3map)
-  fixes image lib loading bugs
-  Hydra
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=298
-  copy/clone deselects the copied stuff
-  added a pref to deselect or not, and to nudge pasted stuff or not
-
-19/1/2002
-  djbob
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=311
-  IEpair wrapper to access project entity from plugins
-  RR2DO2
-  - missing IncRef in CShaderArray::AddSingle
-  TTimo
-  - game.xlink files in gametools path, is scanned to build items in the Help menu
-  (and the associated code)
-
-18/1/2002
-  Gef / Michael Schlueter / TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
-  patches 133 and 138 applied, new setup code
-
-14/1/2002
-  TTimo
-  - adding djbob write access for bobtoolz
-
-13/1/2002
-  ydnar
-  - q3map code updates 1.2.1-y8
-    new lightgrid surface flag feature
-       lightgrid shader and editor image for Wolf and Q3/TA: in the common .pk3 and in all common.shader
-       cvs remove setup/data/baseq3/common-q3r.pk3 (unused, we use common-spog.pk3)
-  TTimo
-  - updating setup to use mapq3 module instead of map (both Wolf and Q3 game packs)
-    (also checked the lightgrid option)
-  - fixed setup.pl bug for template gen from WorkDir/
-  - correct spawning between SP and MP mapping mode
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
-    .pid check, console logging and prefs cleanup
-  Wolfen
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=294
-    checked in updates to the manual links page and setup instructions
-    (i.e. new prefs dialog)
-
-12/1/2002
-  Gef & Michael Schlueter
-  - bugs #295 and #279, new patches applied
-  EvilTypeGuy & djbob
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=220
-    patch selection crash
-  EvilTypeGuy
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=260
-    Dense and Very Dense Cylinders have wrong number of rows    
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=292
-    latching patch toolbar settings
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=144
-    win32 long/short pathname bugs reappearing, switching back to short paths for project settings
-  - removed obsolete radiant/vfs.cpp radiant/vfs.h
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=291
-    using new .qe4 for Wolf, fixed stuff editor side (long path names and engine spawn)
-  SCDS_reyalP
-  - http://zerowing.idsoftware.com/bugzilla/showattachment.cgi?attach_id=118
-    realloc bug in terrain
-
-11/1/2002
-  SPoG
-  - unpatched bug #239, unintended duplication of brushes, patch #96
-       Note: bug #239 now unresolved
-  EvilTypeGuy
-  - bug #295 fixes for compile under Linux
-
-10/1/2002
-  SPoG
-  - fixed CEntityEclassModel referencing eclass after eclass has been deleted
-  SPoG - map-module branch
-  - new map module, provides current functionality, using new map interface
-  - cleaned up merging/creating of entity array used by map module
-  - implemented MemStream::printf(const char,...) - can't print strings larger than 1024 currently
-  - changed copy/paste to use the map module, via abstraction of FileStream/MemStream as DataStream
-  - fixed Save Region and Save Selected
-  - new xml map module "mapxml"
-  - cleaned up map.cpp
-
-6/1/2002
-  TTimo
-  - removed m_bPak from pref dialogs (it was dead code)
-
-5/1/2002
-  RR2DO2
-  - q3map terrain blending fix for >5 layers
-  EvilTypeGuy
-  - fs_homepath patch on linux
-  Gef
-  - bug #279, linux setup, patch #102
-  - bug #239, unintended duplication of brushes, patch #96
-  TTimo
-  - added Wolf specific project settings dialog:
-    correct fs_game selection and combo names
-    added multiplayer / single player mapping mode selection
-
-4/1/2002
-  TTimo
-  - adding -game wolf switch to q3map (-game quake3 works too, but it's the default anyway)
-    using different bsp version and different fs_basegame on wolf
-  - updated the setup/win32/setup.pl script to generate from a config file instead of hardcoded
-    (added corresponding q3.cf wolf.cf and all.cf config files)
-  - added a default Start Menu shortcut name (RR2DO2 special)
-  - diffing against Id's internal SOS source and merging in new stuff:
-    - bumped MAX_SURFACE_INFO to 4096 in shaders.c
-       - new terrain code (Jim Dose)
-         ParseTerrain() addition in terrain.c
-         Creates a mapDrawSurface_t from the terrain text
-       - VL_SurfaceRadiosity and VL_SurfaceRadiosity
-         MrElusive's vlight radiosity code
-       - speedups to vis.c and visflow.c (MrElusive)
-
-3/1/2002
-  TTimo
-  - merge gameselect branch back into trunk
-  the IS setup scripts have been updated for the new paths layout
-  developement environment needs to be updated to copy binaries to the right places for debug
-  it is recommended to run a 1.2.1 setup on win32 prior to compile and install debug bins
-  - updated the setup to be more templated for inclusion/non inclusion of game packs on demand
-
-  - propagating recent fixes to Alpha into the trunk
-  based on diffing between Merge-1_1_1 and Merge-1_1_2:
-  =====================================================================
-  13/11/2001
-    djbob
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=244
-    reverted again the shader manual and tcMod docs
-
-    TTimo
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=214
-    patched aselib.c, was calling strstr badly (relative path extraction)
-
-  12/11/2001
-    djbob
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=241
-    applied patch, will release in next nightly
-
-    Spog
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=254
-    patch for safe_malloc
-
-    TTimo
-    - fixing STLPort config checks and XML config (CHAR -> xmlChar)
-    - added safe_malloc_info and safe_malloc in the common/ dir
-    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=179
-    added XML stream version checking between Radiant and q3map
-  ========================================================================  
-  also, manual merge of docs/manual and setup media
-  this merge work is related to bug #280 too:
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=280
-  
-  ydnar
-  - new q3map, radiosity and bug fixes, code merged in with the trunk version
-  (TODO: add more detailed changes log)
-
-  EvilTypeGuy
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=274
-  broken auto caulking fix
-
-  EvilTypeGyu & LordHavoc
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=207
-  (two new files, project settings updated)
-  
-2/1/2002
-  TTimo - branch gameselect
-  - copying over the linux setup binaries (setup, uninstall, setup.gtk)
-  from Alpha branch. Those have the ability to prompt destination path
-  per component.
-  Gef - branch gameselect
-  - patch 101 for bug 279
-  .game files generation by the setup, makesdk.sh and postinstall.sh fixups
-
-1/1/2002
-  Gef - branch gameselect
-  - linux source fix http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
-  (we use PATH_MAX as the cross platform define instead of MAX_PATH which only works on win32)
-  
-  TTimo - branch gameselect
-  - cleanup and homogeneisation of the paths for prefs storage
-    m_global_rc_path:
-      win32: g_strAppPath
-      linux: ~/.radiant/<version>/
-    m_rc_path:
-      win32: g_strGameToolsPath
-      linux: ~/.radiant/<version>/<gamename>
-    so that global.pref goes in ~/.radiant/<version>/global.pref
-    and radiant.ini ~/.radiant/<version>/<gamename>/radiant.ini  
-
-27/12/2001
-  TTimo - branch gameselect
-  - global prefs file (global.pref), XML based in core directory
-    stores game selection setting
-       stores autoload setting
-  - dropping 'gameid' from .game file, gonna use a 'gamefile' in global prefs instead
-    (and the .game file name .. thks Gef)
-  - TODO: radiant.log stuff in global prefs?
-
-21/12/2001
-  TTimo - branch gameselect
-  - more Wolf setup tweaking for an experimental build release:
-    quakev2.qe4 project template file
-       using a 'gameid' attribute in the game file to select hardcoded features in the editor binary
-       'basegame' node for lookup of the default project file
-       'engine' node for engine path
-  - added experimental Wolf game pack to IS
-  - added setup/win32/HOWTO with extensive information about the procedure to
-    add new game packs
-  - reading the 'name' attribute in the game node for game selection dialog
-  - TODO: pid files to make safe startup?
-  The .pid stuff should be happening after game selection, since it covers game-specific 
-  preference settings. 
-  - TODO: console logging pref should be a global pref, goes with game autoload?
-
-17/12/2001
-  TTimo - branch gameselect
-  - updating the setup script for experimental 1.2.0 setup:
-  
-  merged some of the docs back into trunk (Radiant manual, some TA docs)
-  will need to perform a complete diffing between Alpha and trunk about docs/manual at some point
-  merged bitmaps from Alpha too
-  
-  added the Q3 modules (image, map, md3model, shaders, vfspk3) to Q3 game pack in setup
-  
-  generating per-game config file q3.game in OnMoved (IS setup)
-  will need equivalent with linux setup of course
-  
-  various other generic fixes to the setup code
-  
-  - multiple games support, list of changes, and TODO:
-  NOTE: this is on a 'gameselect' branch for now
-  Doxygen documentation should be at http://zerowing.idsoftware.com/doxygen
-    for this branch too.
-
-  The installation procedure has changed. The win32 installer is partly ready, linux installer
-  will need to be modified too. The editor binary and the Gtk DLLs are installed in a common
-  location, i.e. 'C:\Program Files\GtkRadiant' typically. The game specific binaries and modules
-  go in the same location as usual, for instance 'C:\Program Files\Quake III Arena\GtkRadiant\'
-  (and also 'C:\Program Files\Quake III Arena\GtkRadiant\modules' 'C:\<..>\plugins')
-
-  The environment variables used by the build system (VC6 project files) have been adapted:
-  $(QUAKE3RADIANTDIR) is still used
-  $(CORERADIANTDIR) is used for the main editor location
-
-  When editor starts, it looks for games/*.game under g_strAppPath and prompts the user for a game
-  Once game is selected, parameters are used for regular startup.
-  You need to write your own q3.game for now, it will be generated by the setup procedure
-  my C:\Program Files\GtkRadiant\games\q3.game looks like that:
-  <?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
-  <!-- Q3 game definition file -->
-  <!-- those are generated -->
-  <game 
-    name="Quake III Arena / Quake III: Team Arena and modifications"
-       gametools="c:/quake3/Radiant/"
-  />
-
-  given that, the editor does a complete startup, and the basics are here for multiple games
-
-  - precise changes:
-
-  g_strToolsPath renamed to g_strGameToolsPath
-  most of former g_strAppPath uses g_strGameToolsPath
-  the name change was also meant for homogeneity with DIR_GAMETOOLS_* variables we use in the setups
-  g_strAppPath still used, points to the main installation path
-
-  added the game selection code in CPrefsDlg::Init
-  using several classes and a dialog box, parsing XML files
-
-  - TODO:
-  
-  the console 'Radiant.log' doesn't catch the game selection stuff as it is now
-  initialize it to the main install, without the game setting
-  (console logging is a debugging tool anyway, no reason it should go to the proper game folder
-  each time)
-
-  the 'preferences reset/cleanup' code is probably broken, specially when used with the .pid checking
-  since we check for .pid even before we know where the GameTools path is
-
-  on linux, we need to sanitize the ~/.q3a dir usage. Switch to ~/.radiant, use the version tag
-  to maintain things independant, and use the game name to isolate per-game settings?
-  ~/.radiant/1.2.0-nightly/quake3/radiant.ini (.pid, .log)
-  ~/.radiant/1.2.0-nightly/wolf/..
-
-  also, when looking for those files (.ini mostly), win32 stores them in a main installation, and
-  linux has them in ~/.radiant/.. (which is the read/write area). This should be homogenized?
-  Maybe by adding a 'Main' to the readonly path and a new variable with 'RW', pointing to 'Main' on
-  win32 and to ~/.radiant on linux
-
-11/12/2001
-  TTimo
-  - replaced setup/win32/setup.sh by setup/win32/setup.pl
-  same functionality level + abiliy to generate back a template from a work version
-  - major rework on the IS scripts, basics of multiple games support installer
-  clean seperation between editor core and game pack
-  design doc and analysis of custom setup generation, setup script UI requierements
-  see setup/win32/TODO for more details
-
-10/12/2001
-  TTimo
-  - new generation of InstallShield setup
-  using a template/ directory instead of a .zip file
-  requires rewrite of the processing script
-  allows easier maintenance of the IS script
-
-23/11/2001
-  TTimo
-  - yet another update to cvsreport script, 
-  catch the branch and forward the info to user commands too
-  able to build doxygen for several branches selectively now:
-  http://zerowing.idsoftware.com/doxygen 
-
-22/11/2001
-  TTimo
-  - new cvsreport script, should send explicit diff of the CHANGES file now
-
-03/12/2001
-  TTimo - md3-module branch
-  - validated the fixes and the build on linux, ready to merge in trunk
-  SPoG - md3-module branch
-  - changed function naming conventions in mathlib for m4x4, ray, bbox, to be consistent
-  - fixed bug in m4x4_invert
-
-29/11/2001
-  TTimo - md3-module branch
-  - flagged all new mathlib functions that need a name change or an argument order change
-  also added various \todo to point out inconsistencies
-
-28/11/2001
-  TTimo - md3-module branch
-  - updated linux build
-  - fixed CEntityMiscModel and CEntityEclassModel destructors
-    (any destructor should be virtual)
-
-27/11/2001
-  Spog - md3-module branch
-  - stopped texturewindow showing shaders without the "textures/" path
-  - made md3 module functionally identical to current radiant md3 code
-
-22/11/2001
-  TTimo - md3-module branch
-  - fixes to the core for linux build
-  - model.so module builds on linux
-  - added plugins/md3model/doc/md3-design.txt
-  - several doxy-friendly \todo chunks about the module model
-
-  Spog - md3-module branch
-  - fixed aabb_add_aabb() algorithm wasn't very reliable
-  - added VectorMid, VectorNegative and CrossProduct macros to mathlib
-  - added bbox_intersect_plane()
-
-21/11/2001
-  Spog & TTimo - md3-module branch
-  - initial code from Spog following a preparatory design work
-  merging in as new 'md3-module' branch
-  geomlib code merged into mathlib
-  some reorganisation of the source layout and cleanup (more stuff in imodel.h, less in qertypes.h)
-
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=261
-  fix applied
-
-20/23/11/2001
-  TTimo
-  - yet another update to cvsreport script, 
-  catch the branch and forward the info to user commands too
-  able to build doxygen for several branches selectively now:
-  http://zerowing.idsoftware.com/doxygen 
-
-22/11/2001
-  TTimo
-  - new cvsreport script, should send explicit diff of the CHANGES file now
-
-11/2001
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=253
-  additional fixes
-  TTimo
-  - renamed tools/quake3/common/threads.h to qthreads.h
-  avoids a collision with system headers
-
-19/11/2001
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=251
-  Fixed "Move into worldspawn" deleting entities with only one brush
-  Fixed Brush_Move using texture lock on fixedsize entity brushes
-  Fixed Textures > Texture Lock > Rotations toggle checkbox
-
-16/11/2001
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=247
-  applied patch 77, using a notebook layout for preferences dialog
-  also patched in some preferences saving that had been forgotten
-  (such as invert mouse in freelook)
-  
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=253
-  patch 84 + additional modifs, bug still open
-
-15/11/2001
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=252
-  rewritten rendering pipeline for cam window - fixes some hacks, improves speed, 
-  makes rendering modes more consistent with each other
-
-07/11/2001
-  TTimo
-  - more IMAP interface, adding a blind data void *pData to entity_t
-    more info about it and why it's done is in map.cpp, should be a small base for next additions to the editor
-
-31/10/2001
-  TTimo
-  - using IDataStream in map module, moved back some of the module code into the trunk
-
-30/10/2001
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=245
-    applied patch 76
-    
-  TTimo
-  - renaming istream.h to idatastream.h, this had nasty conflicts with OS includes
-  already had to IStream -> IDataStream some time ago anyway
-
-27/10/2001
-  TTimo
-  - updated cvsreport, testing new ver
-  - added a static version of texdef (no memory alloc on the texture name)
-    unused for now, was just experimental
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=245
-    applied patch 75
-
-26/01/2001
-  TTimo
-  - various updates:
-  new GtkSDK precompiled binaries
-  updated libxml2 package (to 2.4.3)
-  updated STLPort (to 4.5)
-    now compiling with STLPort and threading (since we are using threading throughout the app)
-  - exposing the data stream API to the modules, renamed some stuff on the way
-    need to update the map module to use it now
-  - cleanup on qtexture_t definition
-    guarding and disabling chunks of the surface plugin code behind DO_SURFACEPLUGIN
-       (see earlier patch on plugin entities)
-
-25/01/2001
-  Hydra
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=202
-  applied patch commenting out plugin entities code
-  might come back in 1.2 under another implementation
-  the code is still there, only commented out for now
-
-17/01/2001
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=93
-  checking in doxygen content, setting up generation on zerowing
-  auto generation on zerowing upon a commit:
-  http://zerowing.idsoftware.com/doxygen
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=231
-  checked in the patch
-  - switching to a new cvs commit script
-
-14/10/2001
-  TTimo
-  - libs/mathlib library
-    unifies mathlib code squattered all over the tree
-    mainly a merge of tools math code and radiant/mathlib.cpp
-    C implementation, using an extern "C" construct for use from C++
-    need to check on linux, win32 builds ok
-    extracted qboolean code into libs/bytebool.h on the way
-
-11/10/2001
-  TTimo
-  merged TmpMerge-1_1_1 branch back in the trunk, the update process from Alpha 1.1.1 is done
-
-  TTimo - branch TmpMerge-1_1_1
-  looking through all remaining .rej files and applying the failed patches accordingly
-  bobtoolz is broken, but it's not due to the merge
-    the plugin API is different and some things need updated
-    (disabled bobtoolz build in contrib/Construct for now)
-  same for gensurf
-  same for prtview
-  same for textool
-  setup: replaced the existing stuff with 1.1.1 code
-  fixed various things for win32 build, checked correct CRT lib config
-
-10/10/2001
-  TTimo - branch TmpMerge-1_1_1
-  building modules, going through all the .rej
-  merging radiant/missing.h and modules/shaders/missing.h into a single one, moving to libs/
-  exposing BuildShaderList PreloadShaders in _QERAppShadersTable
-  have to review all the remaining .rej to finalize the merge now
-
-04/10/2001
-  TTimo - branch TmpMerge-1_1_1
-  using this branch as temporary location for merge process
-  copied over new binary files. mostly .dsp (prolly broken)
-  and setup/linux/setup.data stuff
-
-25/08/2001
-  TTimo
-  map module successfully loaded and saved q3dm1, the saved file was then loaded back into 1.1-TA without problems
-  rebuilt and checked on win32
-  merged IMap back in trunk, fixed some memory conflicts on win32
-  Took me a lot more time than I would have liked to, but there's a script tied to the CVS server now, which will post on this list a diff of the docs/developer/CHANGES file whenever it gets updated. This will probably be very handy for me since I'll only have to put update information in the CHANGES file instead of having to post on the list too.
-  The script is likely to be a bit laggy, or miss some features (for instance I'd like to extract the branch name .. anyone know how I can get the branch name (Alpha/IMap/HEAD) from the version number?
-  PS: I can email this script to anyone who would like to have a look
-
-22/08/2001
-  TTimo
-  did more work on map module, one big chunk of work left: the core should broadcast interface requests to plugins
-    when it doesn't know how to do it by itself..
-  Gef
-  new doxygen patch, generates output from core (libs/ include/ and radiant/)
-
-21/08/2001
-  TTimo
-  removed Makefile, use cons damnit!
-
-18/08/2001
-  Gef
-  automated documentation via doxygen, new scripts and content
-
-18/08/2001
-  EvilTypeGuy
-  patch for CHAR to xmlChar conversion (xml2 consistency)
-
-09/08/2001
-  TTimo
-  the map module starts to look like something, cleaned up the interface stuff
-  started moving the actual code out in the module and removing it from the core
-  lots of issues raised on the way, some structures to export, and the macro scheme to access API functions more easily
-  it compiles right now, but won't run because it's missing a lot of things .. the process simply happens to be "under way"
-
-04/08/2001
-  TTimo
-  patched more path code, to look for stuff in "bitmaps/" and "modules/" instead of "tools/bitmaps" and "tools/modules"
-  modified the Construct files accordingly
-  merged in radiant/ishaders.cpp diff into plugins/shaders/shaders.cpp (PreloadShaders)
-  merged in radiant/lbmlib.cpp diff into plugins/images/lbmlib.cpp (Sys_FPrintf)
-  checked the .rej and patched a few remaining things
-  NOTE
-    the diffs are space/tab sensisitive, and we used the "beautify source" a bunch of times, so it's a bit fucked now
-    next time, generate the diffs not space sensitive..
-  TODO
-    map loading is fucked, "textures/" prefix issue?
-
-27/07/2001
-  TTimo
-  merging recent changes from Alpha branch into the Trunk
-  this could not be done with a regular cvs merge because we already did a cvs merge of Alpha into trunk some time ago
-  manually built a diff between the current Alpha (now tagged Merge-1_1-TA_1-nightly)
-  and the Alpha we had right after the former cvs merge: -r Alpha -D 2000-05-28
-  binary files ignored in the diff, only going for source stuff
-  built with diff -Nru Reference/ Current/
-  then patch -p1 < patchfile
-  next, started rebuilding:
-    big manual updates were in vfs.cpp and texwindow.cpp
-  cleaned up some VFS stuff .. it had an absurd QERAppFileSystem / QERPlugFileSystem scheme
-  TODO:
-    the ISSetup has not been copied over from Alpha
-    OK check the Construct files
-    OK radiant/ishaders.cpp no longer exists .. apply the patch on the shader module
-    OK radiant/lbmlib.cpp no longer exists .. in the image code?
-    OK look at the *.rej files
-
-03/10/2001
-  TTimo
-  - adding a pref to select patches by BBox, fixes
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=212
-
-02/10/2001
-  TTimo
-  - reverting Spog patch 67 to bug #209, starting from scratch
-  applied again, with HasModel returning NULL safe checks
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=211
-  fixed overlays drawing (XY and Cam)
-
-01/10/2001
-  TTimo
-  - building and distributing q3data (.ase -> .md3 conversion utility)
-  updated q3data to show main GtkRadiant version information and build date
-  - generating a new GUID per-setup
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=206
-  Gef
-  - updated credits.html and links.htm, look much better
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=200
-  - update Z-checker view on camera up and down
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=199
-  Spog
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=209
-  Fixed QERApp_ReloadShaders.. PreloadShaders needs a BuildShaderList call 
-  Fixed Flush & Reload Shaders for md3 models
-
-25/09/2001
-  Gef / djbob
-  - several patches to the key handling code, for linux specific issues and sticky keys
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=191
-  TTimo
-  - fixing q3map bug, not processing the argv correctly
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=192
-  - fixed ToggleCubicClip shortcut Ctrl+\ (win32 Gtk source patch)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=15
-
-18/09/2001
-  RR2DO2
-  - discreet movement for camera (prefs setting)
-    fixes texture window bug
-    latching view layout changes until restart
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-  djbob
-  - added back "view > show > show angles" in view filters
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=188
-
-15/09/2001
-  G_Dewan
-  - fixed problems with q3map when not using -connect
-  SPoG
-  - fixed q3map texture projection for brushes belonging to entities with local origin
-  - added SafeOpenRead() check, terminating map->bsp stage if .map file cannot be read
-
-13/09/2001
-  RR2DO2
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=181
-  fixing key handling bug (key pressed with repetition was not properly catched)
-  TTimo
-  - added new Radiant manual elements (GtkRad section) to the win32 full setup
-  - reverting version to nightly, going back to nightly / RC delayed
-  - patched linux setup, now prompting for component path only if at least
-    one of the options is checked. Still need to handle Cancel in dialog though.
-
-12/09/2001
-  TTimo
-  - more fixes to linux script, copy plugins right now
-
-10/09/2001
-  TTimo
-  - patched contrib plugins, using seperate build scheme
-  - fixed textool issues, compiles again
-
-09/09/2001
-  TTimo
-  - sub-menu cascading
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=178
-  - udpated the Q3Radiant manual with some new GtkRadiant stuff
-  - updated the FAQ with 1.1.1 known issues
-  Gef
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=174
-  applied all the patches 
-
-07/09/2001
-  SPoG
-  - fixed qer_editorimages outside "textures/" being ignored
-  - stopped q3map_lightimage being used to set shader image dimensions
-  - changed bsp menu to remove "bsp_", changed menu text in default .qe4
-  - fixed patch LOD update - now always occurs on both cam/xy draw
-
-  djbob
-  - dynamic DEpair class strings in bobtoolz
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=171
-  - decrease VESF verbosity
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=169
-
-  TTimo
-  - fixed Gtk keyboard bug Ctrl + [ and ]
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=15
-
-06/09/2001
-  TTimo
-  - merged FullSetup branch into the trunk, we have basic functionality
-  for a full linux setup (components prompting for path)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=158
-
-  Gef
-  - CapDialog source cleanup patch (got rid of the namespace)
-
-  RR2DO2
-  - more camera fixes, wheel mouse and texture drag drop
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-  - additionnal patch to optimize camera refreshes
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-  
-  djbob
-  - remember last key/pair in entity dialog for easy "apply again"  
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=18
-  - re-enabled texture name edit on PI
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=18
-
-04/09/2001
-  djbob
-  - left pane on status bar
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=166
-  
-  RR2DO2
-  - cam window cursor fix
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-  
-  TTimo (FullSetup branch)
-  patched setupdb and setup to allow for path prompt in install
-  modified the setup script scheme to go towards a solution similar to what
-    we do under win32 (build a full and nightly build)
-  the binaries in setup.data/ (setup and setup.gtk) still need to be updated 
-    with proper binaries built from setup and setupdb cvs source
-
-03/09/2001
-  TTimo
-  - wheel mouse in texture window on win32 (with a pref setting for increment)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=160
-  - not saving prefs while exit on sleep
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=157
-  - fixed select all of type (changed behaviour to something that makes more sense?)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=79
-  
-  Gef
-  - final tweaks to wheel mouse scrolling (locks texwin scrolling and scrollbar update)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=160
-  - prevent multiple color selection dialog for light entity
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=165
-  
-  djbob & TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=137
-  window positions
-  applied patch to store SI and PI positions
-  storing entity info and map info positions
-  reworked the overall position load/save scheme
-  added an enum for the view style, makes things more readable
-
-02/09/2001
-  TTimo
-  - added/cleanup ToggleFreeMode to camwindow.cpp .. stopped working on cam stuff since RR2DO2 has another patch in preparation
-  Gef
-  - patched Conscript to accept 'cons -- release' on the command line to performa a release build
-  djbob
-  - added patch splitting to bobtoolz
-  - fix to patch control points bug in camera
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=159
-  - handling of NWUV errors in q3map
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=147
-  RR2DO2
-  - new patch for camera control
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-
-01/09/2001
-  SPoG
-  - Fixed .wal texture support, searches for .wal extension if .tga and .jpg fail
-    NOTE: requires a "pics/colormap.pcx" file to obtain a palette from
-  - Added variable default texture scale in preferences (ini key: TextureDefaultScale)
-
-01/09/2001
-  djbob
-  - fixed surface inspector "fit" bug
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=161
-  - single face deselection on a selected brush
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=153
-
-31/08/2001
-  TTimo
-  - Moved *.def files to scripts/ in win32 setup
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=116
-  - Applied patch for background position on widgets (win32)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=108
-  - Checked C runtime lib configs
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=135
-  - updating docs (add to CVS, update setups etc.)
-    added TA teams manual to the full setup
-    uploaded on web site
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=97
-  - changed versioning to 1.1.1-nightly, next release will be 1.1.1
-  (the -TA part was removed, since we now support ALL mods)
-  - removed AFX_MANAGE_STATE calls, this is old MFC related code for win32
-  - moved texdef_t::name to private, added const char * GetName()
-  (doesn't fix explosion on exit for win32 debug builds though)
-  - fixed DoTextEdit / EditPad b0rkage (due to recent Q_Exec changes)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=134
-  - added targetShaderName documentation to shader manual
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=102
-  - added "notta" and "notq3a" documentation to the TA Mapping manual
-  - fixed entities.def on shootable doors and buttons
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=101
-
-  djbob
-  - added MAX_POINT_ON_WINDING error handling
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=129
-  - bobtoolz update
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=123
-
-  RR2DO2
-  - noclip-type camera movement
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
-
-30/08/2001
-  TTimo
-  - Fixed CHANGES commit script bug
-  - Fixed -onlyents bug in q3map / origin brushes
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=92
-  - added mouse wheel to the texture window
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=81
-  SPoG
-  - Fixed texture rotation not updating correctly on patches
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=136
-  - Fixed long delay on toggling cubic clip by removing call to Map_BuildBrushData()
-  - Added note in entities.def for default worldspawn _color value
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=105
-  - Added IncRef and DecRef to Patch_FindReplaceTexture()
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=95
-  - Fixed misc_model updating on changing model key or with invalid model
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=138
-
-30/08/2001
-  SPoG
-  - Added negative vertical scale on SET and FIT in patch/surface inspector
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=65
-
-27/08/2001
-  Gef
-  - running makeversion.sh from Conscript
-  - a bunch of patches to cleanup compile warnings on linux
-  - added VectorSnap on float grid
-  - IWindowListener modified to pass float values for X Y in click messages
-  TTimo
-  - fixed crash when adding a misc_model if Gtk dialog is on
-  djbob
-  - md3 filtering for misc_model dialog
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=76
-
-26/08/2001
-  Gef
-  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=152
-    Kyro II GL drivers bug
-  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=150
-    using a scrolling textbox for GL extensions in the about list
-  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=150
-    func_group toggle in cap dialog
-    
-  TTimo
-  fixed running BSP commands on linux
-  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=133
-    VFS        init on linux
-    
-around 15/08/2001
-  TTimo
-  quakecon fixes: switched to long filenames in project and misc_model dialogs,
-    removed all occurences of win32 conversion to old 8.3 filenames
-  NOTE: this might raise some bugs and issues, but it's the way to go for the future,
-    already fixes more issues than it creates
-
-03/08/2001
-  djbob
-  fixed Radiant hijacks win32 copy/paste
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=36
-
---- merged Alpha into Trunk, see Merge-1_1-TA-nightly tag
-
-25/07/2001
-  TTimo
-  fixed project dialog to behave right
-  proper .def scanning
-  fixed shader loading with VFS and mod stuff
-  added a local to texwindow.cpp GSList *l_shaderfiles
-    holds the names of the active .shader files
-  modified q3map to read "fs_basepath" and "fs_game"
-  TODO:
-    .def files in the media need to move to <fs_game>/scripts/
-    rename entities-TA.def to entities-ta.def
-
-24/07/2001
-  TTimo
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=116
-  updated cmdlib's Q_Exec to be more widely used through Radiant (during watchbsp.cpp cleanup)
-  patching in MarsMattel's code for mod support, and started fixing:
-    added m_strFSBasePath m_strFSMain m_strFSGame to g_qeglobals to match Q3's filesystem
-    reworked the project file dialog
-    changed the way we load and initialize eclass and shaders to work with mod code
-    updated VFS initialisation code, cleaner and better console output
-    the "game" key in the project file is no longer relevant, only "dir" is
-      (if "dir" is not present, then no mod support, vanilla Q3)
-    changed the loading of the .def files to scan in scripts/, you might need to move your entites.def to use
-    TODO:
-      cleanup .. (search where "basepath" is used for instance)
-      using fs_game when calling q3map
-      fixing project dialog to behave right
-      shader loading using VFS functions (seems to work again but I'm not sure)
-      win32 ver. might be slightly broken
-      .def scanning, don't scan ALL .def
-
-23/07/2001
-  TTimo
-  added version and build info to the log file + current timestamp
-
-22/07/2001
-  SPoG
-  fixed selection of misc_model when viewed as a bounding box
-  
-20/07/2001
-  TTimo
-  cons script for q3map building
-  added general GtkRadiant versioning (version.h) to q3map
-  nightly setup on linux:
-    using the right install path (with GtkRadiant's version name)
-    cleaned up options to only the stuff relevant to nightly
-    fixed Radiant and core binaries path in setup
-    added some template processing of setup.xml (similar to what is being done on win32)
-  
-19/07/2001
-  TTimo
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=112
-  applied ^Fishman's path
-  inclusion of version.h and aboutmsg.h moved to qe3.h
-  changed base path location process (in most cases it will prompt)
-  fixed the path construction to initialize according to the new layout
-
-16/07/2001
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=115
-  fixed wake up crash on linux
-
-12/07/2001
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=117
-  fixed
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=120
-  fixed installer bug on win98, was a problem with cygwin config
-
-11/07/2001
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=64
-  cleanup and fixed
-
-06/07/2001
-  TTimo
-  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=100
-  can't locate the "textures: in use" problem, has been fixed already?
-  now selecting the right entity in the list, had to go around an inifinite recursion problem
-    (i.e. selection message in the entity class list causes UpdateSel recursion)
-
-04/07/2001
-  TTimo
-  - added botclip to missionpack/common.shader
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=114
-
-01/07/2001
-  TTimo
-  - backported cons scripts to Alpha branch. Type 'cons' at the head to build
-  regular makefiles should soon be outdated..
-
-30/06/2001
-  TTimo
-  - updated the IS script (Gtk changes and and BACK problem)
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=68
-  - bunch of fixed to make it build on win32 against new STLPort
-  http://zerowing.idsoftware.com/STLPort/
-  using an STLPort configured locally in GtkRadiant (with stl_config.h, new file)
-
-29/06/2001
-  TTimo
-  - fixed GDI leak affecting text widgets, specially the console and the entity inspector
-
-18/06/2001
-  TTimo
-  - more win32 project file cleanup, removing libs/libxml2 from the tree
-  - importing back "gtkr_list.h" from 1.2, made Alpha branch STLport compliant too
-    http://www.qeradiant.com/faq/fom-serve/cache/174.html
-
-30/05/2001
-  TTimo
-  - added libxml2 as an external dependency. libxml2 should be installed as a seperate
-  directory on win32. dynamic linking now instead of static previously.
-  - cleaned up q3map win32 project file, removed opengl dependency
-  (the drawflag command line is inoperant now .. I don't think it was used anyway?)
-
-26/07/2001
-  TTimo
-  - checking in Gef's doxygen files
-
-14/06/2001
-  TTimo
-  - added .dsp for map module on win32
-  - fixed several issues with module loading, stability of the debug and release builds
-    http://www.qeradiant.com/faq/index.cgi?file=197
-
-12/06/2001
-  TTimo
-  - got rid of of SysMsg thing, using SysPrintf and SysFPrintf now
-  - got rid of InfoMsg functions (can't remember what it was)
-  - changed the m_pfnError in the plugin API to match Radiant's (void)(char *, ...)
-  - changed Warning to Sys_Warning, as #define to Sys_FPrintf(SYS_WRN,
-  
-11/06/2001
-  TTimo
-  - new map module, in plugins/map, required for execution (linux Makefiles written, win32 needs to be)
-    this is using the imap.h interface
-  - added Sys_ functions to the main table (Sys_BeginWait Sys_EndWait)
-  - got rid of AFX_MANAGE_STATE macros .. those are crappy MFC remnants
-  - reverted Spog's changes to the console logging switches to their original behaviour
-  - removed m_fVersion from the func table .. we use the size of the table to do the checks
-  XMLmap merge from 31/11/2000:
-  - started moving the map loading code into a module
-  
-08/06/2001
-  TTimo
-  - updates to the plugin loading code, verbose a bit more, and more interesting information
-
-05/06/2001
-  TTimo
-  - some fixes to vfspk3 string code, using the proper str implementation
-  http://www.qeradiant.com/faq/index.cgi?file=175
-  - added and tweaked various cons build files, Radiant 1.2 core and required Q3 modules are building now
-  - fixes to image module
-
-04/06/2001
-  TTimo
-  - started using cons for the linux (*NIX) build system
-  see http://www.dsmit.com/cons/
-  
-  SPoG
-  - Fixed drawing too much coordinate text in XY window
-  - Changed grid line drawing in XY window to be more consistent
-  - Fixed clipper-tool-uses-caulk to only apply common/caulk to solid opaque brushes
-    (shaders.dll now parses some new surfaceparms)
-  - Changed shader parsing to pass over layer information in shaders,
-    rather than parsing and ignoring it all
-  - Changed misc_model selection to ignore back-facing triangles
-  - Added axes to show the grid origin in XY window
-  - Changed misc_model rendering and selection to minimise the number of extra
-    transformation calculations
-  - Fixed texture directory listing to allocate and free memory correctly using vfs
-  - Added qglDeleteTextures() to plugin GL API - fixes crash
-  - Fixed image.dll to correctly allocate and free memory for jpgs
-  - Moved modules to /modules from /plugins, updated win32 project files.
-    (linux/mac makefiles will need to be updated)
-  - Changed console logging toggle in main() to automatically disable logging after any successful startup
-  - Changed console logging to only activate when a Release build finds a .pid file
-  - Changed "found .pid" and "logging console output" messageboxes to give a clearer message
-  - Added vfsFreeFile - which is kinda redundant if we use g_free and g_malloc for everything
-  
-31/05/2001
-  TTimo
-  - cleanup of the win32 project file and C++ options.\
-  Turned off exception handling, changed some code generation options and fixed
-  some threaded/non-threaded linking problems
-  - STL in GtkRadiant or a plugin must now use STLPort
-  a custom configured version of STLPort is available at http://zerowing.idsoftware.com/STLPort
-  still need to write some guidelines about it
-  bascially, we are using STL: iostreams disabled, no namespace, no threading, no exceptions
-
-30/05/2001
-  TTimo
-  - removed libxml2 from tree, use a seperate libxml2/ directory next to GtkRadiant/ for win32
-  libxml2 will be distributed seperately as an archive based on official release (same as win32 Gtk SDK)
-  (check on zerowing for the latest archive)
-  libxml2 is now used as dynamic shared object on win32, makes sense since many module will rely on it
-  - cleaned q3map, removed GL dependencies
-  - updated Debug and Release builds on win32, it compiles and runs now
-
-28/05/2001
-  Spog
-  - moved vfsExtractRelativePath and vfsGetFullPath to vfs.cpp in vfspk3,
-    added vfsExtractRelativePath and vfsGetFullPath to IFileSystem. Copied BuildShortPathName() from qe3.cpp to vfs.cpp as a Temp fix.
-  - Changed Error() calls in bmp.cpp as a Temp fix, they relied on definition of Error in qe3.cpp. Should probably use Error() from cmdlib instead.
-  - Fixed unresolved external in jpgload.obj - merged bufsize argument into jpeg_stdio_src from Alpha branch... assuming Alpha is the newer version.
-  - Changed GtkWidget* to void* in image.cpp.. this could be cleaned up more.. i only did enough to make it compile.
-  - Added jpeg.cpp to msvc project for image.dll.. changed declaraction of LoadJPG() in image.cpp to an extern... is this correct?
-  - TODO: update vfs.cpp, vfspak.cpp and vfs.h in plugins/vfspak
-  - fixed unresolved external load_pixmap() - merged load_pixmap declaration from Alpha branch into gtkmisc.cpp
-  - moved vfsBasePromptPath() to qe3.cpp as a Temp fix - not currently required in vfs module, but it will be in future.
-  - two calls to free() in texwindow.cpp freeing memory allocated by vfs module, causing debug assert errors - changed them to g_free()
-  - TODO: Delete vfs.cpp and vfs.h from /radiant
-  TTimo
-  - additional fixes after Spog's merge (linux version), removed messaging.cpp messaging.h (name changed to ui.h ui.cpp)
-    updated linux makefile accordingly
-  - merge of Alpha version into trunk (massive amount of changes and merges, not detailed)
-
-25/05/2001
-  TTimo (Alpha branch)
-  - merged the recent MacOS branch back into Alpha
-  this makes a potential source codebase for a MacOS release
-
-24/05/2001
-  TTimo (Alpha branch)
-  - patching Spog's recent changes to fix linux build
-  using DBL_MAX and FLT_MAX from <limits.h> for float and double max
-
-23/05/2001
-  TTimo (Alpha branch)
-  - testing Spog's write access
-  
-  SPoG (Alpha branch)
-  - Added variable LOD for PatchMeshes based on curvature
-  - Added LOD-matching to eliminate gaps between patches with mismatched LOD
-  - Fixed texture shift/scale on LOD'd PatchMeshes
-  - Added opengl lighting (three infinite light sources)
-  - Added dynamically calculating vertex normals for PatchMeshes, for gl lighting
-  - Added decoding/transforming md3 vertex normals for gl lighting
-  - Changed camera drawing routine to minimise gl state changes
-  - Removed Patch_InsertDelete() - not functional
-  - Added CV lattice to selected patches
-  - Added Per-polygon patch selection
-  - Added Per-polygon misc_model selection
-  - Changed default "patch subdivisions" to 4
-  - Rewrote camwindow drawing to only change opengl state within the camwnd's member functions
-       fixes all rendering modes to be more consistent, speeds up rendering
-
---------- GtkRadiant 1.1-TA win32 and linux release ----------
-
-13/05/2001
-
-  Spog (patched in TTimo) (Alpha branch)
-  - Fixed "Fix entity-target/targetname collisions" to use next available tN if tN, else use next available name_N
-  - Changed patch point selection to pick already-selected points in preference over non-selected
-  - Changed RemoveCols and RemoveRows to not extrapolate unless a col/row is selected
-
-11/05/2001
-  TTimo (Alpha branch)
-  - final fix pass to the generated version and about message tags
-  - improved texture adjustment code (shift+arrows shortcuts)
-
-  texture adjustment commands now affect the texture relatively to their current orientation
-  they will move along their texture axis, and not along world axis
-  the texture adjustment commands are now interpreted to be more intuitive:
-    Radiant will match the up/down/right/left translation messages to the face that is affected
-       depending on the way the camera is looking at the face, the right move commands will be used
-
-  changes start in Select_ShiftTexture, using new ShiftTextureRelative_Camera
-
-  ShiftTextureRelative_Camera uses several new functions:
-
-  // get the two relative texture axes for the current texturing
-  BrushPrimit_GetRelativeAxes(f, vecS, vecT);
-
-  MatchViewAxes does the matching between up/down/left/right commands and world directions:
-  // vec defines a direction in geometric space and P an origin point
-  // the user is interacting from the camera view
-  // (for example with texture adjustment shortcuts)
-  // and intuitively if he hits left / right / up / down 
-  //   what happens in geometric space should match the left/right/up/down move in camera space
-  // axis = 0: vec is along left/right
-  // axis = 1: vec is along up/down
-  // sgn = +1: same directions
-  // sgn = -1: opposite directions
-  // Implementation:
-  //   typical use case is giving a face center and a normalized vector
-  //   1) compute start and endpoint, project them in camera view, get the direction
-  //     depending on the situation, we might bump into precision issues with that
-  //   2) possible to compute the projected direction independently?
-  //     this solution would be better but right now I don't see how to do it..
-  void CamWnd::MatchViewAxes(const vec3_t P, const vec3_t vec, int &axis, float &sgn)
-
-  // shift a texture (texture adjustments) along it's current texture axes
-  // x and y are geometric values, which we must compute as ST increments
-  // this depends on the texture size and the pixel/texel ratio
-  void ShiftTextureRelative_BrushPrimit( face_t *f, float x, float y)
-
-  those functions are using various new utility functions:
-  
-    // GL matrix product
-    void GLMatMul(vec_t M[4][4], vec_t A[4], vec_t B[4]);
-
-    // project a 3D point onto the camera space
-    // we use the GL viewing matrixes
-    // this is the implementation of a glu function (I realized that afterwards): gluProject
-    void CamWnd::ProjectCamera(const vec3_t A, vec_t B[2])
-
-  - UI abstraction layer (interfaces for Gtk MFC and Q3 UI)
-
-09/05/2001
-  Maj (Alpha branch)
-  - new splash screen
-
-  Spog (patched in by TTimo) (Alpha branch)
-  
-  patcing in changes:
-  - moving void VectorSnap(vec3_t point, int snap); to mathlib
-  - NOTE: STL dependency removed .. leaving this comment
-    this will rely on M$ implementation of STL on win32 and the libstdc++ for linux
-    it should work fine for basic stuff
-      but M$ implementation doesn't follow the standards when it comes to advanced stuff
-    it is probably better to leave the STL header in local files and not go towards including it directly from qe3.h
-
-  Spog's Changelog:
-  
-  rushing this a bit.. make sure you check it doesn't remove anything you 
-  changed. This only contains changes within /radiant .. i'm pretty sure I didn't 
-  change anything else, but i'll check again. Patch below.
-
-  Fixed ctrl+G SnapToGrid, now never creates degenerate face-planes
-  Fixed setting an origin for multiple brushes to use origin point of fixedsize 
-  entities
-  Fixed mirroring and rotation of fixedsize entities including misc_model
-  Fixed undo/redo on multiple entities to link brushes to entities correctly
-  Fixed "view > entities as.." menu to display correct default setting
-  Fixed "view > entities as.." toolbar button to show menu
-  Changed selection-area of edge/vertex control handles to stay constant when 
-  zoomed
-  Fixed undo on ctrl+G SnapToGrid
-  Fixed Selection Invert to set bSelected correctly on patches
-  Fixed XY-window Z selection origin to be g_MaxWorldCoord
-  Changed RotateIcon to draw same size at all zoom levels
-
-  Fixed origin drift on saving misc_model with null md3Class
-  Fixed creation of cap for 'Bevel' type patches
-  Fixed inverted cap being created for 'Endcap' type patches
-  Fixed inverting patches on mirror operations
-  Added snap-selected-to-grid affects only the patch points selected
-  Cleaned up Select_ApplyMatrix and Select_SnapToGrid
-  Added drawing of brush planepts in debug build
-  Fixed texture quality slider adjustment
-  Removed redundant menu items curve > cap > inverted bevel/inverted endcap
-  Fixed texture scrolling not working when scrollbar is disabled
-  Fixed textures with odd dimensions being skewed with texture quality less than 
-  max
-  Changed Patch Inspector Horizontal/Vertical increment to use pixel values 
-  (default 8)
-  Changed Patch Inspector Horizontal increment to subtract from S values but not 
-  T values
-  Changed Patch Inspector Stretch spinner to do something useful
-  Changed Patch Inspector Stretch default amount to 0.5
-  Changed Arbitrary Rotation dialog to reset rotation spinner values to 0 on Apply
-  !! stops output in console window !! - Added sending q3map output 
-  to /temp/junk.txt to bsp commands, in win32 only
-  Fixed Patch_Naturalize to calculate T values backwards, correcting texture 
-  vertical flip
-  Changed patch row/column Insert/Remove to interpolate/extrapolate from existing 
-  curves
-  Fixed point selection on patches when new points are added
-  Fixed redundant edge/vertex handles being created for patch brushes and 
-  fixedsize brushes
-  Fixed refusal to activate brush vertex-drag mode if any patches are selected
-  Partly fixed Undo picking up patch point drags when no points are selected
-  Fixed behaviour of vertex selection on patches
-  Fixed patch point colours in textured mode in cam window
-  Changed patch point selection to update selection pool on each selection click
-
-06/05/2001
-  TTimo (Alpha branch)
-  - more setup script changes, will rely on version information
-    various other fixes in the script file
-
-02/05/2001
-  TTimo (Alpha branch)
-  - added makeversion.sh to the root, will generate version and date files before compilation
-  version.h and date.h
-  - cleanup and fixes to the linux setup scripts
-
-  Spog (CVS add and config by TTimo) (Alpha branch)
-  - win32 setup script, run setup/setup.sh from cygwin to create a working directory for the setup <STILL EXPERIMENTAL>
-
-01/05/2001
-  TTimo (Alpha branch)
-  - fixes to linux version from previous set of patches
-
-19/04/2001
-  Hydra (patched in TTimo) (Alpha branch)
-  http://fenris.lokigames.com/show_bug.cgi?id=3458 :
-  - *.pfb filter
-
-  SpoG (patched in TTimo) (Alpha branch)
-  - updated setup data: entities.def common.shader(Q3) and common-spog.pk3
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=25 :
-  - Patches: Curve > matrix > redisperse > rows/columns
-    I changed this function to treat a patch as multiple 3by3 sections when doing 
-  redispersal of control points. The effect is that green patch points are never 
-  moved. I also removed the call to Patch_Naturalize, so the texture coordinates 
-  are not changed (user can hit ctrl+n to naturalize afterwards if desired).
-  - rewrote the patch_captexture function to be more reliable
-  - Fixed YZ view drawing and selection being mirrored on plane X=0
-  - Fixed X and Z rotation direction to be clockwise as shown on the toolbar button 
-    icons
-  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8 :
-  - Fixed: Removed orientation-switching hack to fix 2pt-clip orientation problems, 
-    originally stemming from ass-backwards representation of grid axes. Fixed 
-    clipper to generate 3rd clip point correctly for each axis instead.
-  - Fixed: Stopped clipper-caulker from NOT applying caulk if the first face of a 
-    brush was "common/caulk".
-
-  TTimo (Alpha branch)
-  - removed some unused code in the Gtk file dialog, hopefully stabilizing it
-
-02/04/2001
-  TTimo (Alpha branch)
-  - changed the regular/BP conversion prompt
-
-01/04/2001
-  Spog (patched in by TTimo) (Alpha branch)
-  - Fixed view > show coordinates now affects Z window
-  - Fixed minimum/maximum world coordinates now -65536/65536
-  - Fixed view > show blocks now only draws vertical lines if not XY view
-  - Added variable blocksize (gtkr only displays 1024 < blocksize < 65536)
-  - Changed XY/Z window grid drawing to use floats internally
-  - Fixed broken XY window grid drawing for higher zoom levels
-  - Changed camera and Z-checker icons to stay the same size when zoom level changes
-
-24/03/2001
-  Spog (patched in by TTimo) (Alpha branch)
-  - added filters.cpp to the VC6 Makefile. Linux build needs updating
-  - Changed Filter system to use brush-flags updated only on actions that affect filtering
-  - Changed Filter system to allow further extension and future customisation
-  - Changed show/hide to use brush filter flags
-  - Changed Find/Replace textures to only rebuild brushes that changed.
-  - Changed View > Filter menu shortcuts and behaviour
-  - Fixed various minor spelling errors
-
-  TTimo (Alpha branch)
-  - Fixed the 'Clean' command in preferences, used to remove only Radiant.ini and not SavedInfo.bin
-
-06/03/2001
-  TTimo (Alpha branch)
-  - better parse error information: added the line number of the error in (hopefully) all cases
-
-30/02/2001
-  TTimo (Alpha branch)
-  - texture locking in BP mode for axis flipping and axis rotation (toolbar buttons) (Id bugfix request)
-  - fixed undo in BP mode
-  - MatchToken error message in q3map improved with the script name
-
-27/02/2001
-  TTimo (Alpha branch)
-  - switched linux makefiles to xml2-config instead of xml-config
-  latest version of libxml2 is using xml2-config instead of xml-config now
-
-26/02/2001
-  TTimo (Alpha branch)
-  - fixed a loki_initpath misbehaviour, was overriding the path to the binary with RADIANT_DATA if defined
-
-21/02/2001
-  - Added setup data and a script to build linux setups to the cvs
-  TTimo (Alpha branch)
-  - various printf -> Sys_Printf
-  - added vslick/ directory for Visual Slickedit 6.0 on win32 <- THIS IDE RULES
-
-20/02/2001
-  - Removed "Show Paths" option, already in the filter menu
-
-19/02/2001
-  - Fixed the Enter key handling on the surface inspector (suggested by Spog)
-  - Fixed skewed textures with lower texture quality
-  - Changed the order the include directories are searched under Linux
-
-15/02/2001
-  - Moved the Show Cluster Portals option to the Filter menu
-  - Fixed the rotate and scale toolbar buttons being incorrectly checked
-  - Fixed arbitrary rotation bug (#3073)
-
-14/02/2001
-  - Fixed CreateFont memory leak on glwidget
-
-12/02/2001
-  TTimo (Alpha branch)
-  - fixed save as prefab stuff (right dialog name and overwrite prompt)
-
-10/02/2001
-  TTimo (Alpha branch)
-  - was crashing on win32 boxes where HOME env var was not defined (loading bookmarks)
-
-09/02/2001
-  TTimo (Alpha branch)
-  - change some code in the file dialog to use g_malloc g_free instead of new 
-    for win32 file dialog and malloc for Gtk file dialog. (all of this trying to get rid of
-    some of the crashes)
-
-07/02/2001
-  - Fixed Load command initial path
-  - Fixed some toolbar buttons not being correctly initialized
-
------------?
-
-06/02/2001
-  (Alpha branch)
-  - Fixed pk3man file dialog errors
-  - New RC uploaded
-  - Changed conflicting shortcuts: FilterModels = Shift+M, FilterTriggers = Ctrl+Shift+T
-  TTimo (Alpha branch)
-  - fix to hide/show, still selecting hidden brushes
-
-05/02/2001
-  (Alpha branch)
-  - Fixed compile errors (use stat, not _stat)
-  - Removed --nofonts option
-
-04/02/2001
-  TTimo (Alpha branch)
-  - fenris #2866, added a pref to turn on/off name conflicts resolution, rewrote the whole algorithm
-  - fenris #2823, fixed patch and brush dragging in 0.25 0.5 grids (it's an ugly hack btw)
-  - fixed the black squares at end of line in Gtk text boxes
-  RR2DO2 (Alpha branch)
-  - fix to the "entitypath" fixup in QE_CheckProject. might not compile on linux yet (use of _stat?)
-
-03/02/2001
-  TTimo (Alpha branch)
-  - fenris #2867, limiting the amount of "spawnflags" "0" appearing in entities. This bug has work left to do,
-    there are some oddities in the entity inspector behavior described.
-
-02/02/2001
-  (Alpha branch)
-  - Fixed sleep mode not restoring windows correctly
-  - Fixed some minimize/restore issues on floating views mode
-  TTimo (Alpha branch)
-  - fixed more gtkfilesel stuff. pattern filtering works for both Gtk dialogs
-    and win32 native. Also checked on linux that it compiles. Renamed gtkfilesel.h
-    to gtkfilesel-linux.h for consistency.
-
-31/01/2001
-  (Alpha branch)
-  - New file selection widget with filtering, masks and all other shit we need
-  TTimo (Alpha branch)
-  - changed some gtkfilesel API and fixed some bugs on pattern filtering, need to reboot on linux and fix some more
-
-30/01/2001
-  (Alpha branch)
-  - Added an option to keep the Z and XY views on the same window in floating views mode
-  - Did some cleanup
-  TTimo (Alpha branch)
-  - removed the 3 layers in terrain entities limitation, increase version tag to patchlevel 3
-  sent for testing to AstroCreep, bug is still there
-  - fixed one more thing with RC file (get it in the right dir)
-  - worked on file dialog and pattern filtering, still issues left
-
-29/01/2001
-  Jonas (patched in by TTimo) (Alpha branch)
-  - Using RC file to tweak the font size on win32, looks much nicer now!
-  - Fixed fenris #2773: esc key behaviour when group window has focus / dependant on view modes
-
-28/01/2001
-  TTimo (Alpha branch)
-  - Finished fenris #2810 (Snap T to grid), it was a bitch
-  - Fixed fenris #2769: raise the brush max size (it was already big, now it's just not sane)
-  - Fixed fenris #2965: eclass (entities) loading code broken, needs to be checked on linux build before closing
-
-27/01/2001
-  TTimo (Alpha branch)
-  - Fixed vertex edit prefs broken
-  - more fixes in Gtk libs
-  - Fixed clipping + brush primitives bug (#2644)
-  - Fixed clip caulk related issues (#2912)
-  - Added Snap T to grid back (#2810) <- still need to test and validate it, I'm too tired tonight
-
-25/01/2001
-  TTimo (Alpha branch)
-  - New Gtk file selection dialog seems stabilized, built a Gtk SDK for the new Gtk libs.
-
-24/01/2001
-  (Alpha branch)
-  - Fixed elapsed time displayed by q3map
-  - Fixed Radiant loading some TGA files upside down
-  TTimo (Alpha branch)
-  - more work done on the file selector. Added a win32 pref to select between regular win32 file dialog and Gtk one.
-  The advanced file selector is still not stabilized on win32. I am thinking about letting go and sticking to the regular one.
-
-23/01/2001
-  (Alpha branch)
-  - Fixed q3map not finding md3 files under missionpack/
-  - Prompt to save changes when choosing a recent file
-  - Fixed window title when choosing File/Load Map
-  - Don't show hidden brushes in the Z window
-
-22/01/2001
-  (Alpha branch)
-  - More File Dialog fixes
-
-21/01/2001
-  TTimo (Alpha branch)
-  - version first version of the advanced file selector on win32
-  seems to work nicely, but crashes when you actually load something .. needs debugging!
-
-  leo (Alpha branch)
-  - Set correct initial directory for the File/Load command
-
-17/01/2001
-  (Alpha branch)
-  - Fixed q3map is crash if a .shader file is referenced in shaderlist and not found
-
-  TTimo (Alpha branch)
-  - fixed some license headers on gtkfilesel.c, started looking into porting gtkfilesel.c to win32
-
-16/01/2001
-  raistlin
-  - the tree is opened whoooo!
-
-  TTimo (Alpha branch)
-  - replaced the old Id header by the newer version (BIG update, to trunk and Alpha)
-  - switched str.h to BSP
-  - added LGPL license to the sample dll
-
-15/01/2001
-  (Alpha branch)
-  - Added camera window toggle option to all views mode
-
-  TTimo
-  for trunk and Alpha:
-  - renamed TOOL_SOURCE_EULA to LICENSE_ID
-  - renamed CONTRIBUTOR to CONTRIBUTOR_AGREEMENT
-  - added CONTRIBUTORS and LICENSE
-
-14/01/2001
-  (Alpha branch)
-  - plugin SDK is back in setup/ moved the sample dll to be in plugins/, need to rewrite the SDK scripts
-  - built a lightweight plugin SDK with cygwin makefile for the sample plugin
-
-12/01/2001
-  (Alpha branch)
-  - Set map modified flag when deleting a brush
-  - Minimize all windows when the main window is minimized in floating views mode
-
-11/01/2001
-  (Alpha branch)
-  - Cleaned up the View/Show submenu
-  - Fixed texture menu splitting 
-  - Fixed major grid lines on 128 and 256 grids
-  - Load only a single .def file if specified in the project settings
-  - Fixed q3map Makefile
-
-  TTimo
-  (Alpha branch)
-  - Removed plugins/shaders from Alpha branch
-  - got rid of common2/ and code, moved qfiles.h and surfaceflags.h into common/
-  - put the licensing headers in all source files (forgot some? byte me)
-
-10/01/2001
-  leo (Alpha branch)
-  - Added new filter system based on FAKK2 Radiant
-
-  TTimo
-  - fixed whatever could be fixed to make it compile with the new directory layout
-  (Alpha branch)
-  - project files update
-
-09/01/2001
-  (Alpha branch)
-  - Added undo for patch redisperse rows and patch redisperse cols commands
-  - Fixed Show Z Outline menu item
-
-30/11/2000
-  TTimo
-  - removed content flags and value from qtexture_t, these have moved to the IShader
-    (NOTE: qtexture_t != texdef_t, texdef_t still using flags value and content)
-
-  - Rewrote the linux plugins Makefiles
-
-29/11/2000
-  - Improved the way modules are loaded
-  - Added new parameter to QERPlug_RequestInterface
-  - finished VC6 project files conversion for new directory structure
-  - fixed shader blending on terrain maps bug
-08/01/2001
-  - Updated Makefiles for the new directory structure
-  - Fixed View/Show/Entities menu not being checked correctly
-  - Fixed "Invert Selection" command selecting hidden brushes
-  - Fixed "Select All of Type" command not working correctly after the Enitity Window is closed
-  - Fixed grid being drawn even when it's the same color of the background
-  - Fixed "Toggle Size Paint" not turning off
-05/01/2001
-  - Fixed autosave interval being calculated wrong
-  - Fixed autosave path under Linux
-  - Fixed q3map crash when trying to load missing pcx files
-  - Fixed q3map not finding .bmp files for the terrain alpha map
-04/01/2001
-  - Fixed GL stack underflow when loading a misc_model
-03/01/2001
-  - Fixed patches remaining half-selected after "Region set selected" (#2748)
-  - Fixed Surface Inspector spin buttons rate (#2776)
-  - Fixed some shortcuts not appearing on menu items (#2786)
-
-
-================================================================================
-                                  1.1-TA beta
-================================================================================
-
-02/01/2001
-  - Fixed memory problem if a file without extension is entered in the file save dialog.
-  - Fixed double slashes "//" on filenames when saving a map
-  - Fixed pk3man plugin not finding the toolbar bitmaps
-  - Fixed double clicks being considered 2 mouse clicks
-
-  RR2DO2 (applied by TTimo)
-  - Clusterportal filtering ('View > Show > Show clusterportal' toggle)
-
-01/01/2001
-  TTimo
-  - updated Web/ with new stuff, web site ready for release
-  - fixed a crash with multiple edge dragging on win32 (was caused by compiler optimizations,
-    this one was a major pain)
-
-31/12/2000
-  - fixed the file open/save dialogs initial directory
-
-  RR2DO2 (applied by TTimo)
-  - bug fix in the terrain loading speedup
-
-  TTimo
-  - tried to lookup the Z window minimum width problem, added #define DBG_WINDOWPOS code to investigate
-
-30/12/2000
-  RR2DO2 (applied by TTimo)
-  - fix to CSG Merge in the menu drop down (menu was there, command not hooked)
-  - some message formatting fixes
-
-  TTimo
-  - rudimentary pattern matching in file selection, affects the plugin API too
-  - fixed silly bug in the "clipper uses caulk" code
-  - major speedup to the loading code on terrain entities
-  (in mpterra2, from 113s to 4s for the main terrain entity)
-  - patched back the file open/save dialogs initial directory to override in TA mode
-  - fixed Patch output crash in the plugin API
-  - fixed BP conversion in the brush output of the plugin API
-
-  minkey (applied by TTimo)
-  - fix to the m_pfnLoadFile code to use VFS
-
-29/12/2000
-  - Remember main window position in floating views mode
-  - Fixed wake up when running the engine in floating views mode under win32
-
-  TTimo
-  - various fixes and debug hooks for PJ bug reports
-
-28/12/2000
-  - Fixed VFS initialization order
-  - Removed texture menu splitting option from preferences (now it's automatic)
-
-  TTimo
-  - built an initial setup, updated the changelog file for 1.1-TA-beta
-
-27/12/2000
-  - Fixed Q3Map output window being too wide on some errors
-  - Added VFS to q3map
-
-  TTimo
-  - replace a printf in q3map by Sys_Printf (!), which is what should actually be used
-  - added a set of functions to vfs to help with file dialogs, building relative files etc.
-  - reworked the file dialogs so they default in the right location (open/save as/md3 loading/sound loading)
-  - fixed shader editor to work with the right path
-
-26/12/2000
-  TTimo
-  - put the converted HTML manuals (Radiant, shaders and model) in the tree (and the win32 setup)
-  - added the new Terrain and Team Arena mapping manuals (added to the setups too)
-
-  leo
-  - Copy and paste across different instances of Radiant
-  - Fixed wait cursor when copying
-  - Print engine command line to the console
-  - Fix glib warnings when running the engine
-  - Fixed shader files being loaded twice
-  - Texture menu now automatically breaks when it reaches the maximum screen height
-
-24/12/2000
-  - Fixed q3map to compile with the new LoadJPGBuf parameter
-
-  TTimo
-  - added TA paths to the BSP commands and running engine
-  - fixed a bug if running with monitoring disabled (generating the .bat was borked)
-  - changed the -moddir implementation to a global switch in q3map (same as -connect)
-  - moddirparam as a global variable in cmdlib, added a TA_HACK in there
-  - changed the SetQDirFromPath to stick to "baseq3/" when using -moddir
-  TODO: check standalone files
-
-23/12/2000
-  TTimo
-  - fixed some sleep/wake code (crashes and wakeup problems on models)
-  - vfsInitDirectory for TA directory (needs to be checked on linux)
-  - changed my mind on entities.def, if TA is enabled, load entities-TA.def on top of regular entities.def
-
-  mickey (applied by TTimo)
-  - some memory overrun fixes
-
-22/12/2000
-  - Fixed plugin Makefiles to not use private/
-
-  RR2DO2 (applied by leo)
-  - Fixed SetTallBrush undo
-  - Added bug report link to help menu
-
-21/12/2000
-  - Daily Linux compilation fixes
-  - Fixed q3map to read .pk3 files from the directory set by -moddir
-  - Fixed vfs not listing all files correctly
-  - Fixed libjpeg crashing on some jpeg files
-  - Load .def files depending on the current game
-
-20/12/2000
-  - Applied Mickey's patch to fix win32 window position save/load.
-  - removed missing _msize call
-
-  TTimo
-  - cleaned up more g_malloc g_free problems, cleaned a INPUT_BUF_SIZE problem in jpeglib
-
-19/12/2000
-  - More manual updates
-  - Fixed bugs comparing file extensions
-  - Added VFS to the Alpha branch
-
-  TTimo
-  - moved game selection to the project settings
-  - got leo's vfs fixes, started changing the memory allocation scheme to glib
-  - moved 'free' calls to g_free with a #define in cmdlib, Radiant seems to run nicely again
-  - removed calls to _msize .. those were causing heap debug assertion failures
-  - upped more stuff
-
-18/12/2000
-  - Added popup menus with the list of active textures to the find texture dialog
-  - Fixed some menu checkbuttons
-  - Changed max number of shader files parsed by q3map to 128
-  - Updated manual images 
-
-17/12/2000
-  - Fixed bug with the texture window scrollbar range
-
-  Mickey (patched in by TTimo)
-  - fix to the floating windows mode, don't send windows to the desktop when raising something else (#2659)
-
-  TTimo
-  - finalized the merge and move into worldspawn commands by adding the undo stuff
-  - fixed the clamping problems when flipping or mirroring patches
-  - added 0.5 and 0.25 grids
-  - added undo to Select_CompleteTall Select_PartialTall and Select_Inside
-  - added on-the-fly conversion between regular brush coordinates and brush primitives texturing in the plugin API
-
-15/12/2000
-  - Fixed crash on Shift-A (Select all of type)
-  - Save the state of the toolbar buttons
-  - Remember the state of the Show Patch Bounding Box button
-  - Double clicking on an entity on the Entity View tree selects the entity
-  - Sort the list columns of the map info dialog
-  - Fixed a bug that would allow multiple Entity View dialogs
-
-  Mickey (patched in by TTimo)
-  - saving position and size of the entity window between runs and during usage
-
-  TTimo
-  - two new commands in the drop down menu:
-  "move into worldspawn" will move selected brushes to worldspawn and eventually delete entities which end up with no brushes
-  "merge brushes" will merge brushes into an entity (from worldspawn or from another entity)
-  - added cleaned HTML version of the editor manual in the tree
-
-14/12/2000
-  - When pressing a letter key in the entity window list, scroll to the entity starting with the key pressed
-  - Fixed backspace not working on the texture subset entry
-  - Added version check when loading savedinfo.bin
-
-  TTimo
-  - started implementing Select_Merge and Select_Seperate for workflow improvement on terrain maps
-
-13/12/2000
-  - Finished GtkGenSurf
-
-  RR2DO2 (merged in by TTimo)
-  - patch to q3map, added option -custinfoparams for custom surface flags (still need documentation)
-
-  TTimo
-  - zoom out and grid drawing taylored to the world size
-
-12/12/2000
-  TTimo
-  - quick win32 update to gensurf
-  - fixed #2610 (MAX_NETMESSAGE) .. needed a consistent rewrite of the way we parse the stream
-
-11/12/2000
-  - Fixed linux compiler errors from recent changes
-  Not fixed today but I forgot to add those to the Alpha changelog
-  - Fixed multiple Map Info dialogs bug
-  - Fixed texture window not scrolling to the top when a new directory is loaded
-  - Fixed GL Windows grab pointer bug
-  - Fixed crash after map compilation if the map leaked
-  - Fixed q3map crash if MAX_SHADER_FILES is reached
-
-28/11/2000
-  - Fixed sleep mode restoring hidden windows (win32)
-  - Fixed find/replace textures dialog layout and keep it always on top of the main window
-  - Replaced malloc/free calls with g_malloc/g_free to avoid the win32 limitation
-
-27/11/2000
-  - Removed glu.h dependencies
-  - Added new file selection dialog
-  - Removed g_PrefsDlg.m_bDisableAlphaChannel (always FALSE)
-  - Added shortcuts for sleep and simple patch mesh
-  - Fixed crash after sleep mode (no GL context current)
-
-24/11/2000
-  - Rewrote the jpeg functions of the image plugin
-  - Replaced some MFC classes with glib
-  - More shader plugin fixes
-  - Fixed bug with select all entities command
-
-  TTimo
-  - fixed q3map to handle the new LoadJPGBuff length parameter
-
-22/11/2000
-  - Fixed crash in Error() if there's no current GL context
-  - Fixes to the shaders plugin
-
-  TTimo
-  - created VC6 project file for image module
-  - modified the m_pfnError in qerplugin.h to use (char *, ...) construct
-
-21/11/2000
-  - Ensured that the plugins are loaded in the correct order
-  - Added Sys_FPrintf and Sys_Printf to the plugin interfaces
-  - Some VC++ fixes
-
-  TTimo
-  - more fixes to the world size
-  - modified moduleentry_t so it compiles on win32. need to update the code in all modules probably
-  - other minor fixes and updates to get everything building on win32
-
-20/11/2000
-  - Moved image loading code to a plugin
-  - Fixed some bugs in the shader plugin
-  - Now using glGenTextures to set texture ids
-
-19/11/2000
-  TTimo
-  - shader code removed from Radiant core, relies on shader module
-  - added ctrl-alt-LBUTTON = multiple brush select without selecting whole entities (from TA update)
-  - added an XML testing proggy in DevDocs/
-
-18/11/2000
-  TTimo
-  - shader module is compiling
-  - reworked the way we deal with required interfaces,
-  automated the interface request process and added code to check the required modules have been found
-
-17/11/2000
-  - Q1 VFS plugin
-  - Changes to the VFS API to detect the format supported by a plugin
-  - Added checks to PluginManager to load the correct VFS plugin
-
-  TTimo
-  - made a mess with XML MAX_NETMESSAGE error, still not fixed
-  - merged q3map 1.0r (TA update from Id) into the tree - important files modified: surfaceflags.h qfiles.h
-
-08/12/2000
-  TTimo (shit I'm 24 now)
-  - added gtk gensurf, VC6 project files are up to date, linux Makefile not checked
-  - fix some WINAPI stuff on above code
-  - add idata.h for raw access to editor data
-  - new _QERAppShaderTable for shader module -> editor functions
-  - added new entries in various tables (GL, parser etc.)
-  - shader module is well under way
-
-16/11/2000
-  - Added a color selection dialog function to the plugin API
-  - Added profile read/write functions to the plugin API
-
-  TTimo
-  - MAX_NETMESSAGE bug: patched q3map so it sends in several messages if the problem occurs
-  still need to update Radiant to recognize XML nodes split into several messages (using an input buffer)
-  - added a test map for MAX_NETMESSAGE: sput.map
-  - project file for vfspk3and win32 patching
-
-15/11/2000
-  - More plugin cleanup
-  - Added IsEqualGUID() to qerplugin.h
-
-  TTimo
-  - merged Alpha back in (didn't try to merge this CHANGES file)
-  - backported some stuff from the trunk to here, the Sys_Printf, gtk_MessageBox and profile stuff
-  - created VC project file for gtk-based gensurf plugin
-
-14/11/2000
-  - Fixed DumpUnreferencedShaders()
-
-  TTimo
-  - added QE_CheckProjectEntity to check paths are following the right conventions
-
-13/11/2000
-  - Fixed bugs in the vfs plugin
-  - Added support to vfs plugins in Radiant
-
-  TTimo
-  - updated project file to libxml2-2.2.8, use libxml2 as the directory name for whatever version..
-          NOTE: libxml2-2.2.8 needs some patching to compile right..
-
-12/11/2000
-  TTimo
-  - all Radiant functions that might be exported in interfaces need to use the WINAPI calling convention
-  modified the GTK functions code accordingly
-  - started writing the shaders module
-
-10/11/2000
-  - Added new GTK functions to the plugin API
-  - Added 'parent' parameter to MessageBox, file_dialog and dir_dialog
-  - Fixed Help commands (Linux)
-
-09/11/2000
-  - Fixed bug in the Z wnd code
-  - Fixed copy text from the console (win32)
-
-       TTimo
-       - moved the libxml library out of the tree, updated the VC6 project files accordingly
-
-08/11/2000
-       - ZWnd always on top (view #2, win32)
-
-       TTimo
-       - added Escape key to hide the entity inspector
-       - S and Shift+S now act as toggles on the inspectors
-
-07/11/2000
-       - Added ungroup command to right click menu
-       - Fixed message box accelerator bug
-       - Fixed GL error on win32 startup
-
-       TTimo
-       - additions to the BSP interface
-       - fixed DestroyCursor error
-       - clipper caulks faces (and prefs checkbox)
-
-06/11/2000
-       - Cleaned PrtView and TexTool plugins
-       - Fixed bug in texture menu names (#2506)
-       - Added splitters to Entity dialog
-
-       TTimo
-       - started clipper caulk implementation
-       - fix to the pointfile not drawing in 2D views
-       - MAX_BUILD_SIDES in q3map debug stream
-
-05/11/2000
-       - Merged Alpha branch with the trunk
-
-       TTimo
-       - more plugin interface for Q3Build, and plugin SDK additions
-       - merged q3map Realloc back into Alpha branch
-
-04/11/2000
-       - Fixed crash during startup if Zwnd was hidden in views #2 and #3
-       - Fixed ToggleConsole command
-       - Fixed ToggleEntity and ToggleTexture commands in view #2
-       - Fixed plugin Makefiles
-       - Removed -rdynamic from Radiant link options (crashes pk3man plugin)
-
-03/11/2000
-       TTimo
-       - directory reorganisation for the plugin SDK, added an interface/ directory
-
-02/11/2000
-       - Save ZWnd state in views #2 and #3
-       - Entity dlg always on top (linux)
-       - Fixed shortcuts.ini parsing bug
-       - Fixed editpad crash if editpad not present (win32)
-       - Fixed bugs in the internal shader editor
-       - Fixed widget_show if window moved after gtk_widget_set_uposition
-
-================================================================================
-                                    1.1 beta
-================================================================================
-
-31/10/2000
-       - Continue loading if glXGetProcAddressARB is not present (Utah-GLX fix)
-       - Fix BSP commands not working if a map is not in "mapspath" (linux)
-
-30/10/2000
-       - fixed the Region commands, "Region > Set brush" is working
-         Region uses the camera as spawn point.
-       - Fixed view/show menu initialization
-       - Fixed warning when starting view #2
-       - Fixed z wnd in view #3
-       - Fixed win32 sleep mode crashes on views #2 and #3
-       - Added "Restart" message when changing texture quality in the preferences
-       - Cleanup: removed radbsp.cpp (unused) and unzip.cpp (already in pak.a)
-
-29/10/2000
-       - Fixed SIGCHLD handler
-       - Built 1.1b setups
-
-28/10/2000
-       - Fixed q3map bug visbytes > MAX_MAP_VISIBILITY
-       - Fixed clipper display bug
-
-       TTimo
-       - updated quakev2.qe4 with -vlight options
-       - added checks in q3map to prevent crashing on allocating a winding too big
-       will stop with an error now.
-       - added the corresponding editor support for debug messages if MAX_POINTS_ON_WINDING is exceeded
-
-       G_Dewan
-       - improved q3map, reducing minimal memory footprint by about 45Mb
-
-27/10/2000
-       - Fixed crash in BSP debug window
-       - Reorganized the preferences dialog
-       - Fixed q3map Makefile
-       - Fixed +/- bug in win32 (Gtk patch)
-       - Fixed Alt shortcuts bug in win32 (Gtk patch)
-       - Fixed q3map crash when visbytes > MAX_MAP_VISIBILITY
-
-       TTimo
-       - improved snapshots behaviour, doesn't snapshot non-modified maps
-
-26/10/2000
-       - Fixed patch inspector not showing after it has been closed
-       - Added 'Reset' button to entity dialog
-
-25/10/2000
-       - Fixed more grid issues
-       - Fixed load window position bug (saved pos greater than screen resolution)
-       - Fixed selection nudge bug
-       - Improved entity windows layout
-       - Fixed GL font not being recreated when exiting sleep mode
-
-       TTimo
-       - cleaned m_nTextureTweak and m_bSnapTToGrid
-       - improved the CycleCapTexturePatch command, now cycles across the 3 planes only 
-       and works on multiple patches at once
-
-24/10/2000
-       - Added an overwrite prompt when saving files
-       - Fixed 128 and 256 grid display
-       - Commented-out grouping code (not functional yet)
-
-23/10/2000
-       - Fixed q3map to load jpgs under Linux
-       - Fixed wake-up crash when floating windows were closed (#2423)
-
-21/10/2000
-       - More q3map and radiant Makefile fixes
-       - Remember size/position of the entities dialog
-
-20/10/2000
-       - Redirect Gdk warnings
-       - Draw border around active XY wnd
-       - Moved some scripts to the Makefile
-       - Added shift+rclick to zoom in/out
-       - Removed minimize/maximize buttons for z wnd in floating mode under win32
-
-       TTimo
-       - Two new entries in View > Show: Show Outline and Show Axes
-       Show Outline turns on/off colored outline of the current view
-       Show Axes turns on/off display of a small axis base in the 2D view
-       - fix q3map Makefile to use external libxml2 source
-       
-       G_DEWAN
-       - Fix to bogus noshader error message in q3map
-
-19/10/2000
-       - Added new console functions that support colors
-       - Revised linux makefile for debug/release builds
-       - Redirect Gtk warnings to the console
-
-       TTimo
-       - reorganized the entity inspector window, layout depends on the number of flags to get
-       more space in the comment window.
-
-18/10/2000
-       - Fixed add/remove bsp items in project settings dialog
-       - Did some cleanup (removed #define WIN32_CONSOLE)
-       - Fixed console not working in view #3
-       - Fixed warning when exiting in views #2 #3
-
-       TTimo
-       - fix to entity inspector comment window for the eclass_t on win32 (removed the white squares)
-
-17/10/2000
-       - Fixed texwindow not scrolling when last texture is large
-       - Added LOD for patches
-       - Fixed prefab path & user ini in preferences dialog
-
-13/10/2000
-       TTimo (XML branch)
-       - basic architecture for XML feedback is functional
-       see radiant/feedback.cpp radiant/watchbsp.cpp q3tools/common2/inout.c
-       merging back in alpha
-
-04/10/2000
-       TTimo (XML branch)
-       - sax interface is in Radiant, need to add a state machine and proper processing
-
-04/10/2000
-       TTimo (XML branch)
-       - experimental use of SAX interface to parse the stream on the server side, see q3tools/q3map/NetTest
-
-03/10/2000
-       TTimo (XML branch)
-       - adding libxml2 in the repository, based on libxml2-2.2.4 with project files and stuff to build on win32
-
-31/09/2000
-       TTimo (XML branch)
-       - new common2/ dir, output system rewritten through Sys_Printf
-       - experimental use of libxml
-
-28/09/2000
-       TTimo (Inspector branch)
-       - shift+arrows matches the increments from the surface inspector
-       - button 'Match Grid' in the SI to set the increment according to current grid
-
-25/09/2000
-       TTimo (Inspector branch)
-       - fixed crappy bug in SavedInfo.bin upgrade (when the struct sizes don't match)
-       - surface inspector has inc step dialog boxes (+saved in prefs)
-       - face selection is always on (was something weird from the prefs)
-       - undo works better with the surface inspector
-
-25/09/2000
-       - Added ARB_Multitexture support
-
-21/09/2000
-       - Fixed preferences dialog warning
-       - Added new grid sizes
-
-20/09/2000
-       - Fixed small bugs reported from Fenris
-
-17/09/2000
-       TTimo
-       - fixed a bug with template project loading / path to the engine safecheck (a weird hidden one)
-       G_Dewan & TTimo
-       - fixes to the process spawning (Q_Exec in cmdlib) + appropriate warning and error messages
-       Fishman
-       - antialiased drawing in 2D views
-
-14/09/2000 
-       TTimo
-       - radiant.log commandlist.txt and radiant.pid are create in g_strAppPath on win32 and g_strTempPath on linux
-       - moved the splash screen after the .pid code
-       - I suspect a bug in the .pid removal, added a check and message box
-       - help works again on win32, spawning Word with the Q3Rad_Manual.doc (temporary solution of course)
-       - surface inspector: removed all Q2 related stuff, fixed horizontal shift, reorganized the widgets layout
-               hooked the widgets to apply the changes on the fly (the inspectors need a good chunk of work)
-       - fixed a radiant.pid bug
-       - added icon to MSVC6 project (with some help)
-       
-       G_Dewan
-       - fix to BSP menu order getting mixed up
-       - fix to the file dialog
-
-11/09/2000
-       - Added splash screen
-
-25/08/2000 TTimo
-       - launch sleep mode before running game
-       - fixed Map_Snapshot bug
-       - going to sleep works on view n2, raising is still screwed (contexts)
-
-24/08/2000 TTimo
-       - fixed some sleep mode stuff
-       - fixed map snapshot bug
-
-21/08/2000
-       - fixed stuff to build on linux
-       - Merged in q3map 1.0p
-
-18/08/2000
-       - Removed "High Color Textures" option (always on)
-       - Removed "Status Point Size" option
-
-17/08/2000
-       - Fixed win32 console issues
-
-16/08/2000
-       - added g_strTempPath
-       - restore maximized window state
-       - fixed logo.bmp
-
-15/08/2000 TTimo
-       - fixed keyboard shortcuts
-       - fixed engine path in prefs (must use the file dialog to change)
-       - fixed a bug related to engine path and project templates
-
-15/08/2000
-       - Removed QE4 update model option (always on)
-       - Removed Buggy ICD option (always off)
-       - Reorganized the preferences dialog to take a bit less space
-
-14/08/2000 TTimo
-       - using profile.cpp code to read shortcut keys files
-       - moved DevDocs/changelog.txt to data/changelog.txt
-               (data/ should be used for user-side stuff and DevDocs/ for developpers)
-       - added data/quickstart.txt with a beginning of info about the main differences
-               between Q3Radiant 202 and GtkRadiant. to be used as a doc later.
-
-13/08/2000 TTimo
-       - added DevDocs/WIN32SETUP and DevDocs/changelog.txt
-               changelog.txt is end user changes
-               WIN32SETUP the TODO list for install specific stuff
-       - wrapped a first version of the win32 installers (full and patch)
-
-11/08/2000 TTimo
-       - quickfix to put undo/redo back in
-       - added DevDocs/WIN32SETUP, describes what I'm up to with the setup of win32 version
-
-10/08/2000 TTimo
-       - added back the window position saving code that was in earlier tree
-               NOTE: would have rather have it done in prefs than hooked in mainframe_delete and MainFrame::Create
-               (would have been cleaner IMO)
-               NOTE: IT'S STILL BROKEN .. I ADDED THE CODE BUT I MUST BE MISSING SOMETHING
-               NOTE: it doesn't remember the maximized state. It should.
-
-08/08/2000 TTimo
-       - fixed win32 build for GLWidget code, added WINAPI calling convention on all exported stuff
-       - fixed TexTool to compile under win32
-
-07/08/2000 TTimo
-       - fixed some crash with the new jpeg lib
-       - fixed console logging behaviour (was always turned on at startup)
-       - added console logging checkbutton in prefs
-
-07/08/2000
-       - Merged the GLWidget branch
-       - Merged 202 patches
-       - Fixed "clean" button in the preferences dialog
-       - Added pid startup detection
-       - Updated plugin interface with GLWidget functions
-       - Updated TexTool plugin
-
-04/08/2000
-       - Added "errno" string to the Error() message box
-       - More 202 patches
-
-03/08/2000
-       - Merged changes from MFC Radiant 202
-        - Fixed the win32 GLWidget stuff
-02/08/2000
-        - new OpenGL widget to keep all platform specific code in only one file
-
-01/08/2000
-       - Added code to restore the windows when coming out of sleep mode
-       - Rewrote the TexTool plugin
-
-31/07/2000 TTimo
-       - added vc6 projects for PrtView
-       - tested PrtView and Radiant against latest binary release of Gtk (works great)
-
-       Leo:
-       - Updated VC5 projects
-       - Fixed plugin loading under win32
-       - Updated PrtView to compile under win32
-       - Radiant is now iconified when going in sleep mode
-
-30/07/2000 TTimo
-       - prefs dialog for BSP monitoring
-       - Added data/ directory with entities.def and quakev2.qe4
-       - stabilized syntax of v2 project file, same project file for both platforms
-       - added DevDocs/WIN32BETA with a list of stuff to do before going on public beta on win32
-       - added DevDocs/d2u .. handy script to remove linefeeds from DOS files
-       - added radiant/radiant.proj, project file for source navigator (SN rules)
-
-       Leo:
-       - Fixed the logfile crash when ~/.q3a/radiant doesn't exist (fenris #1953)
-
-28/07/2000 TTimo
-       - Fix to the win32 console to use window's default font
-       - Added File > Sleep for experimentation
-               NOTE: we need to keep Radiant minimized when going into sleep mode
-
-28/07/2000
-       - Finished the win32 console replacement
-       - Fixed bug 1952 (map loading segfault)
-       - Added a Makefile to the libs dir
-
-26/07/2000
-       - Added PrtView plugin
-       - Added qvm target to source/Makefile
-       - Another release candidate sent to QA
-
-18/07/2000
-       - Fixed the slow updates issue in the win32 version
-       - Added 3 new variables to fix the paths issue
-
-17/07/2000
-       - Fixed the plugin search directory (broken with the changes to g_strAppPath)
-
-14/07/2000
-       - Increased the timer speed in MainFrame::RoutineProcessing
-       - Added code to release and recreate the contexts to the win32 version
-       - Fixed the mouse capture under win32
-
-13/07/2000
-       - Fixed the new path and bsp problems
-       - Sent new version to QA for testing/release
-
-12/07/2000
-       - Added "tools/" back to g_strAppPath under linux
-
-11/07/2000
-       - Added code to release and the recreate the GL contexts (linux)
-
-10/07/2000
-       - Changed directory structure
-
-09/07/2000
-       - Added CS_OWNDC for win32 with a GDK hack
-
-07/07/2000
-       - Fixed "white textures" bug (gluBuild2DMipmaps bug)
-
-03/07/2000
-TTimo:  - main.cpp l386, removed tools/ appending to g_strAppPath, g_strAppPath is expected to point to the app.. (hope it doesn't break anything)
-
-02/07/2000
-       - Added precompiled headers for faster win32 builds
-
-01/07/2000
-       - Finally got q3asm/lcc working
-
-26/06/2000
-       - 201 patches
-       - Added screenshot option
-       - Added an error message if X is running in 8 bits
-
-23/06/2000
-       - Updated with build 200 source
-
-13/06/2000
-       - Remove --noshare option
-       - Added --nofonts option to workaround a bug using glXUseXFonts in XFree 4.0
-
-04/06/2000
-       - Fixed bug with the Ctrl-X accelerator for the File/Exit menu
-
-02/06/2000
-       - Converting the TexTool plugin
-
-30/05/2000
-       - Changes to the plugin loading code
-
-28/05/2000
-       - Files with an underscore character are now correctly parsed in the MRU menu
-
-25/05/2000
-       - Fixed _exit bugs
-       - Fixed bug in CMapStringToString::SetAt
-       - Fixed copy/paste/clone bug
-
-24/05/2000
-       - Finished applying the 199 patches
-       - Fixed a bug in CShaderArray::SortShaders() that was calling the wrong version of InsertAt()
-       - Added numbers to the MRU menu items
-
-23/05/2000
-       - Fixed the floating point bug in gluBuild2DMipmaps
-       - Fixed the time display after a bsp command is executed
-       - Applied several patches from the 199 version
-       - The console is now visible by default
-
-21/05/2000
-       - Added a replacement for gluBuild2DMipmaps
-
-20/05/2000
-       - Fixed the repeating textures bug when playing a map, "brush_primit" must be set to "1".
-       - Fixed the bug about no current GL context when exiting in computers with 3dfx cards.
-       - Textures in the directory pointed by "texturepath" are now loaded correctly in Radiant.
-       - Fixed bug in q3map where it would require a shaderlist.txt file in ~/.q3a/baseq3/scripts.
-
-19/05/2000
-       - Fixed a bug in the multiple directories hack in libs/pakstuff.cc
-       - Finished the filter in the texture window
-       - The wait cursor is now correctly set in the XY window
-       - Added replacements for gluPerspective and gluLookAt
-       - Textures can now be stored in 2 places:
-       * The path pointed by "texturepath" (defaults to ~/.q3a/baseq3/textures,
-         but can be changed in the project settings)
-       * The base texture path (<install_path>/baseq3/textures)
-       - Radiant and the q3map tool now looks for shaders in ~/.q3a/baseq3/shaderlist.txt
-          and <install_path>/baseq3/scripts/shaderlist.txt
-
-18/05/2000
-       - Plugin menu fixes
-       - Created a simple text editor to edit the shaders (instead of calling an external program)
-       - Copy and paste now work
-       - Fixed some bugs with the MRU menu
-       - Some menu items are now enabled/disabled correctly in MainFrame::RoutineProcessing () 
-       - Added a new command line option (--cdpath) to set the CD-ROM path
-       - Fixed some bugs in the entity window, now it's possible to add/edit/remove properties
-       - New directory paths:
-       * maps now default to ~/.q3a/baseq3/maps
-       * autosave files are saved in ~/.q3a/baseq3/maps
-       * .pk3 files can be in ~/.q3a/baseq3, <install_path>/baseq3 and in the CD-ROM
-
-17/05/2000
-       - Fixed bug deselecting a brush after the surface dialog is open
-       - hide cursor when right-dragging XYWnd
-       - files saved to /tmp are now saved in ~/.q3a/radiant
-       - Disabled undo
-       - Fixed a bug in FillTextureMenu
-       - User can now correctly change the accelerators at run-time
-       - Accelerators are read from ~/.q3a/radiant/radiant.ini
-
-16/05/2000
-       - Finished the patch inspector
-       - Finished the texture toolbar
-       - more small bug fixes
-
-11/05/2000
-       - Finished the GroupDlg stuff
-       - Added support to read pak files from the Quake3 CD-ROM
-       - moved /tmp/paklog.txt to ~/.q3a/radiant/paklog
-       - added functions to replace GetKeyState and SetCursorPos
-       - fixed the command key handlers for the mainwindow
diff --git a/DoxyConfig b/DoxyConfig
deleted file mode 100644 (file)
index b9c0619..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-# Included Doxygen Config file
-#---------------------------------------------------------------------------
-# Project name & version number
-#---------------------------------------------------------------------------
-PROJECT_NAME           = 
-PROJECT_NUMBER         = 
-
-#---------------------------------------------------------------------------
-# Where to put the output
-# Note: The images dir should be next to the created html dir within the
-#      output dir.
-#       eg;
-#       [Current Dir]
-#               L__[OUTPUT_DIRECTORY]
-#                      L__[html]
-#                      L__[images]
-#---------------------------------------------------------------------------
-OUTPUT_DIRECTORY       = ../GtkRadiant-doxygen
-
-#---------------------------------------------------------------------------
-# Where to read the sources
-# you can add more than one source...
-# INPUT                   = radiant/ \
-#                           tools/quake3/q3map \
-#                           tools/quake3/q3data
-#
-# Recursive is set on, so setting it to ./ (current dir) would read source
-# files recursively from the current dir down. (which would take a while)
-#
-# eg: To document just include, if the current directory is ../GtkRadiant/ 
-# then...
-#---------------------------------------------------------------------------
-INPUT                  = radiant/
-
-#---------------------------------------------------------------------------
-# Misc settings
-# TAB_SIZE     - sets the indenting for the inline source and the source 
-#                browser
-# INCLUDE_PATH - will include documentation for included files from other
-#                packages. You can specify more than one path the same as
-#                shown in the INPUT example Leave it blank if you don't want 
-#                this.
-# PERL_PATH    - path to the perl executable
-#
-#---------------------------------------------------------------------------
-PERL_PATH              = /usr/bin/perl
-
diff --git a/Doxyfile b/Doxyfile
deleted file mode 100644 (file)
index b87c164..0000000
--- a/Doxyfile
+++ /dev/null
@@ -1,1117 +0,0 @@
-# Doxyfile 1.3.6
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
-PROJECT_NAME           = GtkRadiant
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
-PROJECT_NUMBER         = 1.5.0
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
-OUTPUT_DIRECTORY       = doxygen-out
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
-# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
-# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, 
-# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
-
-OUTPUT_LANGUAGE        = English
-
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = YES
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is used 
-# as the annotated text. Otherwise, the brief description is used as-is. If left 
-# blank, the following values are used ("$name" is automatically replaced with the 
-# name of the entity): "The $name class" "The $name widget" "The $name file" 
-# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       = 
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
-# members of a class in the documentation of that class as if those members were 
-# ordinary class members. Constructors, destructors and assignment operators of 
-# the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user-defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. It is allowed to use relative paths in the argument list. 
-# If left blank the directory from which doxygen is run is used as the 
-# path to strip.
-
-STRIP_FROM_PATH        = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
-# explicit @brief command for a brief description.
-
-JAVADOC_AUTOBRIEF      = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
-# will output the detailed description near the top, like JavaDoc.
-# If set to NO, the detailed description appears after the member 
-# documentation.
-
-DETAILS_AT_TOP         = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# re-implements.
-
-INHERIT_DOCS           = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
-TAB_SIZE               = 2
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
-# only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
-OPTIMIZE_OUTPUT_FOR_C  = NO
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
-# For instance, namespaces will be presented as packages, qualified scopes 
-# will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
-EXTRACT_ALL            = NO
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
-EXTRACT_PRIVATE        = NO
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
-EXTRACT_STATIC         = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# users are advised to set this option to NO.
-
-CASE_SENSE_NAMES       = YES
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
-# Note: This option applies only to the class list, not to the 
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = NO
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text.
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
-INPUT                  = radiant/ plugins/ libs/ include/
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
-# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
-
-FILE_PATTERNS          = 
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
-RECURSIVE              = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
-# that are symbolic links (a Unix filesystem feature) are excluded from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories.
-
-EXCLUDE_PATTERNS       = */.svn/*
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH           = radiant/ plugins/ libs/ include/
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS       = 
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.
-
-INPUT_FILTER           = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
-# then for each documented function all documented 
-# functions referencing it will be listed.
-
-REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES (the default) 
-# then for each documented function all documented entities 
-# called/used by that function will be listed.
-
-REFERENCES_RELATION    = YES
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
-ALPHABETICAL_INDEX     = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
-GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER            = 
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET        = 
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
-# written to the html output directory.
-
-CHM_FILE               = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX          = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
-# generated containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
-# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
-# probably better off using the HTML help feature.
-
-GENERATE_TREEVIEW      = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
-GENERATE_LATEX         = YES
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
-# invoked. If left blank `latex' will be used as the default command name.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
-PAPER_TYPE             = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = NO
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = NO
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation.
-
-GENERATE_XML           = YES
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = doxygen-xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_SCHEMA             = 
-
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_DTD                = 
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = NO
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed.
-
-PREDEFINED             = 
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse the 
-# parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
-# super classes. Setting the tag to NO turns the diagrams off. Note that this 
-# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
-# recommended to install and use dot, since it yields more powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
-HAVE_DOT               = YES
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
-# Language.
-
-UML_LOOK               = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
-# generate a call dependency graph for every global function or class method. 
-# Note that enabling this option will significantly increase the time of a run. 
-# So in most cases it will be better to enable call graphs for selected 
-# functions only using the \callgraph command.
-
-CALL_GRAPH             = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT       = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found on the path.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS           = 
-
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
-
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes that 
-# lay further from the root node will be omitted. Note that setting this option to 
-# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
-# note that a graph may be further truncated if the graph's image dimensions are 
-# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
-# If 0 is used for the depth value (the default), the graph is not depth-constrained.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP            = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-
-# The SEARCHENGINE tag specifies whether or not a search engine should be 
-# used. If set to NO the values of all tags below this one will be ignored.
-
-SEARCHENGINE           = NO
index bf98684f13c36c55cf4768731771b3e33714f9de..e66cd7f2f37985519d84678d0c6b31c80dd3e882 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,13 @@
+# TODO: when deleting this Makefile, don't forget to also delete conftest.cpp
+# which is only required by this Makefile
+
+ifeq ($(I_KNOW_MAKEFILE_IS_DEPRECATED),)
+    $(shell printf 'ERROR: Makefile build is deprecated, use CMake instead, see README.md\n\n' >&2)
+    $(error I_KNOW_MAKEFILE_IS_DEPRECATED is not set)
+else
+    $(shell printf 'WARNING: deprecated Makefile build enforced\n\n' >&2)
+endif
+
 MAKEFILE_CONF      ?= Makefile.conf
 -include $(MAKEFILE_CONF)
 
@@ -14,6 +24,8 @@ CXXFLAGS           ?=
 CPPFLAGS           ?=
 LIBS               ?=
 RADIANT_ABOUTMSG   ?= Custom build
+RADIANT_NAME       ?= NetRadiant
+RADIANT_BASENAME   ?= netradiant
 
 # warning: this directory may NOT contain any files other than the ones written by this Makefile!
 # NEVER SET THIS TO A SYSTEM WIDE "bin" DIRECTORY!
@@ -198,7 +210,7 @@ ifeq ($(OS),Linux)
 else
 
 ifeq ($(OS),Win32)
-       CPPFLAGS_COMMON += -DWIN32 -D_WIN32 -D_inline=inline
+       CPPFLAGS_COMMON += -DWIN32 -D_WIN32 -D_inline=inline -DWORKAROUND_WINDOWS_FLOATING_WINDOW=1 -DWORKAROUND_WINDOWS_GTK2_GLWIDGET=1
        CFLAGS_COMMON += -mms-bitfields
        LDFLAGS_DLL = -Wl,--add-stdcall-alias
        LIBS_COMMON = -lws2_32 -luser32 -lgdi32 -lole32
@@ -252,16 +264,13 @@ RADIANT_VERSION_NUMBER = $(RADIANT_MAJOR_VERSION).$(RADIANT_MINOR_VERSION).$(RAD
 RADIANT_VERSION = $(RADIANT_VERSION_NUMBER)n
 Q3MAP_VERSION = 2.5.17n
 
-# Executable extension
-RADIANT_EXECUTABLE := $(EXE)
-
 GIT_VERSION := $(shell $(GIT) rev-parse --short HEAD $(STDERR_TO_DEVNULL))
 ifneq ($(GIT_VERSION),)
        RADIANT_VERSION := $(RADIANT_VERSION)-git-$(GIT_VERSION)
        Q3MAP_VERSION := $(Q3MAP_VERSION)-git-$(GIT_VERSION)
 endif
 
-CPPFLAGS += -DRADIANT_VERSION="\"$(RADIANT_VERSION)\"" -DRADIANT_MAJOR_VERSION="\"$(RADIANT_MAJOR_VERSION)\"" -DRADIANT_MINOR_VERSION="\"$(RADIANT_MINOR_VERSION)\"" -DRADIANT_PATCH_VERSION="\"$(RADIANT_PATCH_VERSION)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\"" -DRADIANT_EXECUTABLE="\"$(RADIANT_EXECUTABLE)\""
+CPPFLAGS += -DRADIANT_VERSION="\"$(RADIANT_VERSION)\"" -DRADIANT_VERSION_STRING="\"$(RADIANT_VERSION_STRING)\"" -DRADIANT_ABOUTMSG="\"$(RADIANT_ABOUTMSG)\"" -DRADIANT_NAME="\"${RADIANT_NAME}\"" -DRADIANT_BASENAME="\"${RADIANT_BASENAME}\"" -DQ3MAP_VERSION="\"$(Q3MAP_VERSION)\""
 CPPFLAGS += -DGTK_TARGET=2
 
 .PHONY: all
@@ -432,8 +441,8 @@ binaries-qdata3: \
 
 .PHONY: binaries-h2data
 binaries-h2data: \
-       $(INSTALLDIR)/heretic2/h2data.$(EXE) \
-       $(INSTALLDIR)/heretic2/h2data \
+       $(INSTALLDIR)/h2data.$(EXE) \
+       $(INSTALLDIR)/h2data \
 
 .PHONY: binaries-tools-quake3
 binaries-tools-quake3: \
@@ -1020,46 +1029,45 @@ $(INSTALLDIR)/plugins/bkgrnd2d.$(DLL): \
        contrib/bkgrnd2d/dialog.o \
        contrib/bkgrnd2d/plugin.o \
 
-$(INSTALLDIR)/heretic2/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML)
-$(INSTALLDIR)/heretic2/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/quake2/qdata_heretic2/common -Itools/quake2/qdata_heretic2/qcommon -Itools/quake2/qdata_heretic2 -Itools/quake2/common -Ilibs -Iinclude
-$(INSTALLDIR)/heretic2/h2data.$(EXE): \
-       tools/quake2/qdata_heretic2/common/bspfile.o \
-       tools/quake2/qdata_heretic2/common/cmdlib.o \
-       tools/quake2/qdata_heretic2/common/inout.o \
-       tools/quake2/qdata_heretic2/common/l3dslib.o \
-       tools/quake2/qdata_heretic2/common/lbmlib.o \
-       tools/quake2/qdata_heretic2/common/mathlib.o \
-       tools/quake2/qdata_heretic2/common/md4.o \
-       tools/quake2/qdata_heretic2/common/path_init.o \
-       tools/quake2/qdata_heretic2/common/qfiles.o \
-       tools/quake2/qdata_heretic2/common/scriplib.o \
-       tools/quake2/qdata_heretic2/common/threads.o \
-       tools/quake2/qdata_heretic2/common/token.o \
-       tools/quake2/qdata_heretic2/common/trilib.o \
-       tools/quake2/qdata_heretic2/qcommon/reference.o \
-       tools/quake2/qdata_heretic2/qcommon/resourcemanager.o \
-       tools/quake2/qdata_heretic2/qcommon/skeletons.o \
-       tools/quake2/qdata_heretic2/animcomp.o \
-       tools/quake2/qdata_heretic2/book.o \
-       tools/quake2/qdata_heretic2/fmodels.o \
-       tools/quake2/qdata_heretic2/images.o \
-       tools/quake2/qdata_heretic2/jointed.o \
-       tools/quake2/qdata_heretic2/models.o \
-       tools/quake2/qdata_heretic2/pics.o \
-       tools/quake2/qdata_heretic2/qdata.o \
-       tools/quake2/qdata_heretic2/qd_skeletons.o \
-       tools/quake2/qdata_heretic2/sprites.o \
-       tools/quake2/qdata_heretic2/svdcmp.o \
-       tools/quake2/qdata_heretic2/tables.o \
-       tools/quake2/qdata_heretic2/tmix.o \
-       tools/quake2/qdata_heretic2/video.o \
+$(INSTALLDIR)/h2data.$(EXE): LIBS_EXTRA := $(LIBS_XML)
+$(INSTALLDIR)/h2data.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) -Itools/heretic2/common -Itools/heretic2/qcommon -Itools/heretic2/h2data -Itools/quake2/common -Ilibs -Iinclude
+$(INSTALLDIR)/h2data.$(EXE): \
+       tools/heretic2/common/bspfile.o \
+       tools/heretic2/common/cmdlib.o \
+       tools/heretic2/common/inout.o \
+       tools/heretic2/common/l3dslib.o \
+       tools/heretic2/common/lbmlib.o \
+       tools/heretic2/common/mathlib.o \
+       tools/heretic2/common/md4.o \
+       tools/heretic2/common/path_init.o \
+       tools/heretic2/common/qfiles.o \
+       tools/heretic2/common/scriplib.o \
+       tools/heretic2/common/threads.o \
+       tools/heretic2/common/token.o \
+       tools/heretic2/common/trilib.o \
+       tools/heretic2/qcommon/reference.o \
+       tools/heretic2/qcommon/resourcemanager.o \
+       tools/heretic2/qcommon/skeletons.o \
+       tools/heretic2/h2data/animcomp.o \
+       tools/heretic2/h2data/book.o \
+       tools/heretic2/h2data/fmodels.o \
+       tools/heretic2/h2data/images.o \
+       tools/heretic2/h2data/jointed.o \
+       tools/heretic2/h2data/models.o \
+       tools/heretic2/h2data/pics.o \
+       tools/heretic2/h2data/qdata.o \
+       tools/heretic2/h2data/qd_skeletons.o \
+       tools/heretic2/h2data/sprites.o \
+       tools/heretic2/h2data/svdcmp.o \
+       tools/heretic2/h2data/tables.o \
+       tools/heretic2/h2data/tmix.o \
+       tools/heretic2/h2data/video.o \
        libl_net.$(A) \
        $(if $(findstring $(OS),Win32),icons/h2data.o,) \
 
 .PHONY: install-data
 install-data: binaries
-       $(MKDIR) $(INSTALLDIR)/games
-       DOWNLOAD_GAMEPACKS="$(DOWNLOAD_GAMEPACKS)" DOWNLOADDIR="$(DOWNLOADDIR)" INSTALLDIR="$(INSTALLDIR)" GIT="$(GIT)" SVN="$(SVN)" WGET="$(WGET)" RM_R="$(RM_R)" MV="$(MV)" UNZIPPER="$(UNZIPPER)" ECHO="$(ECHO)" SH="$(SH)" CP="$(CP)" CP_R="$(CP_R)" $(SH) gamepack-manager
+       DOWNLOAD_GAMEPACKS="$(DOWNLOAD_GAMEPACKS)" DOWNLOADDIR="$(DOWNLOADDIR)" INSTALLDIR="$(INSTALLDIR)/gamepacks" GIT="$(GIT)" SVN="$(SVN)" WGET="$(WGET)" RM_R="$(RM_R)" MV="$(MV)" UNZIPPER="$(UNZIPPER)" ECHO="$(ECHO)" CP="$(CP)" CP_R="$(CP_R)" ./gamepack-manager
        $(ECHO) $(RADIANT_MAJOR_VERSION) > $(INSTALLDIR)/RADIANT_MAJOR
        $(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR
        $(ECHO) $(RADIANT_PATCH_VERSION) > $(INSTALLDIR)/RADIANT_PATCH
index 25c6ad5c9d5b84afae5c8852ee00c62ee77d4aca..3b5fd112a7cf903925b9fcf3222f0eb61c27d4ba 100644 (file)
--- a/README.md
+++ b/README.md
 NetRadiant
 ==========
 
-![NetRadiant logo](setup/data/tools/bitmaps/splash.png)
+[![NetRadiant logo](setup/data/tools/bitmaps/splash.png)](https://netradiant.gitlab.io)
 
-The open source, cross platform level editor for idtech games (Radiant fork).
+The open source, cross platform level editor for id Tech-derivated games, heir of GtkRadiant.
 
-# Getting the Sources
+Learn more on NetRadiant website: [netradiant.gitlab.io](https://netradiant.gitlab.io).
 
-The latest source is available from the git repository:
-https://gitlab.com/xonotic/netradiant.git
 
-The git client can be obtained from the Git website:
-http://git-scm.org
+## Download NetRadiant
 
-To get a copy of the source using the command line git client:
+Prebuilt binaries can be found on the [Download page](https://netradiant.gitlab.io/page/download/).
 
-```
+
+## Compatibility matrix
+
+|System   |Build    |Bundle    |Run      |Build requirements                            |
+|---------|---------|----------|---------|----------------------------------------------|
+|Linux    |**Yes**  |**Yes**   |**Yes**  |_GCC or Clang_                                |
+|FreeBSD  |**Yes**  |**Yes**   |**Yes**  |_GCC or Clang_                                |
+|Windows  |**Yes**  |**Yes**   |**Yes**  |_MSYS2/Mingw64 or Mingw32_                    |
+|Wine     |-        |-         |**Yes**  |-                                             |
+|macOS    |**Yes**  |**Yes**   |**Yes**  |_Homebrew, GCC or Clang and builtin GtkGLExt_ |
+
+NetRadiant is known to build and run properly on Linux, FreeBSD and Windows using MSYS2, and build on macOS with Homebrew (some bugs are known though). Windows build is known to work well on wine, which can be used as a fallback on some system.
+
+At this time library bundling is supported on Linux, FreeBSD, Windows/MSYS2, and macOS/Homebrew. Since bundling copies things from the host, a clean build environment has to be used in order to get a clean bundle. Linux and FreeBSD bundles do not ship GTK: users are expected to have a working GTK environment with GtkGLExt installed, usually installing GtkGLExt is enough to pull everything that is required.
+
+
+## Getting the sources
+
+Source browser, issues and more can be found on the gitlab project: [gitlab.com/xonotic/netradiant](https://gitlab.com/xonotic/netradiant)
+
+The latest source is available from the git repository: `https://gitlab.com/xonotic/netradiant.git`
+
+The `git` client can be obtained from your distribution repository or from the Git website: [git-scm.org](http://git-scm.org)
+
+A copy of the source tree can be obtained by using the `git` command line client this way:
+
+```sh
 git clone --recursive https://gitlab.com/xonotic/netradiant.git
 cd netradiant
 ```
 
-See also https://gitlab.com/xonotic/netradiant/ for a source browser, issues and more.
 
-# Dependencies
+## Dependencies
 
- * OpenGL
- * LibXml2
- * GTK2
- * GtkGLExt
- * LibJpeg
- * LibPng
- * LibWebp
- * Minizip
- * ZLib
+* OpenGL, LibXml2, GTK2, GtkGLExt, LibJpeg, LibPng, LibWebp, Minizip, ZLib.
 
-## msys2
+To fetch default game packages you'll need Git, Subversion, Wget and `unzip`.
 
-Under MSYS2, the mingw shell must be used
+It's possible to build against GTK3 using the `-DGTK_TARGET=3` cmake option, but some problems may be encountered, see [GUI/GTK](https://gitlab.com/xonotic/netradiant/-/issues?label_name[]=GUI%2FGTK3) issues. GTK2 remains recommended for now.
 
-### 32 bit:
 
+### Ubuntu:
+
+```sh
+apt-get install --reinstall build-essential cmake \
+    lib{x11,gtk2.0,gtkglext1,xml2,jpeg,webp,minizip}-dev \
+    git subversion unzip wget
 ```
-pacman -S --needed base-devel mingw-w64-i686-{toolchain,cmake,make,gtk2,gtkglexti,libwebp}
-```
 
-### 64 bit:
+If you plan to build a bundle, you also need to install `uuid-runtime patchelf`
+
+This is enough to build NetRadiant but you may also install those extra packages to get proper GTK2 graphical and sound themes: `gnome-themes-extra gtk2-engines-murrine libcanberra-gtk-module`
 
+
+### MSYS2:
+
+Under MSYS2, the mingw shell must be used.
+
+If you use MSYS2 over SSH, add `mingw64` to the path this way (given you compile for 64 bit Windows, replace with `mingw32` if you target 32 bit Windows instead): 
+
+```sh
+export PATH="/mingw64/bin:${PATH}"
 ```
-pacman -S --needed base-devel mingw-w64-x86_64-{toolchain,cmake,make,gtk2,gtkglext,libwebp}
+
+Install the dependencies this way:
+
+```sh
+pacman -S --needed base-devel git subversion unzip \
+    mingw-w64-$(uname -m)-{ntldd-git,toolchain,cmake,make,gtk2,gtkglext,libwebp,minizip-git}
 ```
 
-## OS X:
+Explicitely use `mingw-w64-x86_64-` or `mingw-w64-i686-` prefix instead of `mingw-w64-$(uname -m)` if you need to target a non-default architecture.
+
+
+### FreeBSD:
 
+```sh
+pkg install cmake gtkglext pkgconf minizip webp coreutils gsed git subversion wget unzip
 ```
-brew install gtkglext
-brew install webp
-brew install Caskroom/cask/xquartz
+
+If you plan to build a bundle, you also need to install `patchelf`
+
+
+### macOS:
+
+Note: some dependencies of gtk+ seems to only be pulled with gtk+3, gtkglext seems to require libffi.
+
+```sh
+brew install cmake glib libffi gtk+ gtk+3 pkgconfig minizip webp coreutils gnu-sed wget sassc
 brew link --force gettext
 ```
 
-# Submodules
 
- * Crunch (optional, disabled by default, only supported with CMake build)
+## Submodules
 
-If you have not used `--recursive` option at `git clone` time, you can fetch Crunch this way (run it within the NetRadiant repository):
+ * Crunch (optional, not built if submodule is not present)
 
+If you have not used `--recursive` option at `git clone` time, you can fetch Crunch this way (run this within the `netradiant` repository):
 
-```
+```sh
 git submodule update --init --recursive
 ```
 
-# Compiling
+
+## Simple compilation
+
+It is required to first download the sources using `git` (do not use tarballs) and to have dependencies installed, see [Getting the sources](#getting-the-sources) and [Dependencies](#dependencies) above.
+
+
+### Easy builder assistant
+
+If you have standard needs and use well-known platform and operating system, you may try the provided `easy-builder` script which may be enough for you, you can run it this way:
+
+```sh
+./easy-builder
+```
+
+If everything went right, you'll find your netradiant build in `install/` subdirectory.
+
+If you need to build a debug build (to get help from a developer, for example), you can do it this way:
+
+```sh
+./easy-builder --debug
+```
+
+By default, build tools and compilers are using the `build/` directory as workspace.
+
+For supported system, bundling dependencies can be done this way:
+
+```sh
+./easy-builder -DBUNDLE_LIBRARIES=ON
+```
+
+Note: always do bundling on a clean system without unrelated software installed.
+
+
+## Advanced compilation
+
+### Initial build
 
 This project uses the usual CMake workflow:
 
-## Debug
 
+#### Debug build
+
+```sh
+cmake -G "Unix Makefiles" -S. -Bbuild -DCMAKE_BUILD_TYPE=Debug
+cmake --build build -- -j$(nproc)
 ```
-cmake -G "Unix Makefiles" -H. -Bbuild && cmake --build build -- -j$(nproc)
+
+
+#### Release build
+
+```sh
+cmake -G "Unix Makefiles" -S. -Bbuild -DCMAKE_BUILD_TYPE=Release
+cmake --build build -- -j$(nproc)
 ```
 
-## Release
+Note: macOS users need to build built-in GtkGLExt before building NetRadiant:
 
+```sh
+cmake -G "Unix Makefiles" -S. -Bbuild -DCMAKE_BUILD_TYPE=Release
+cmake --build build -- -j$(nproc) builtins
+cmake -G "Unix Makefiles" -S. -Bbuild
+cmake --build build -- -j$(nproc)
 ```
-cmake -G "Unix Makefiles" -H. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build -- -j$(nproc)
+
+
+### Subsequent builds
+
+The initial build will download the gamepacks and build NetRadiant and tools. If you frequently recompile you can skip downloading the gamepacks:
+
+```sh
+cmake --build build --target binaries -- -j$(nproc)
+```
+
+You should still periodically update gamepacks:
+
+```sh
+cmake --build build --target gamepacks
 ```
 
-## More Compilation Details
 
-options:
+### Build and installation details
+
+#### Compilation details
+
+Options:
+
+* `BUILD_RADIANT=OFF`  
+  Do not build NetRadiant (default: `ON`, build netradiant graphical editor);
+* `BUILD_TOOLS=OFF`  
+  Do not build q3map2 and other tools (default: `ON`, build command line tools);
+* `BUILD_DAEMONMAP=OFF`  
+  Do not build daemonmap tool (default: `ON` if submodule is there, buils daemonmap navigation mesh generator);
+* `BUILD_CRUNCH=OFF`  
+  Disable crunch support (default: `ON` if submodule is there, enable crunch support);
+* `RADIANT_ABOUTMSG="Custom build by $(whoami)"`  
+  A message shown in the about dialog (default: `Custom build`).
+
+Targets:
+
+* `binaries`            Compile all binaries;
+  - `netradiant`        Compile the netradiant editor;
+  - `modules`           Compile all modules (each module has its own target as well);
+  - `plugins`           Compile all plugins (each plugin has its own target as well);
+  - `tools`             Compile all tools (each tool has its own target as well);
+     * `quake2`         Compile all the Quake 2 tools: `q2map`, `qdata3`;
+     * `heretic2`       Compile all the Heretic2 tools: `q2map`, `h2data`;
+     * `quake3`         Compile all the Quake 3 tools:
+         - `q3map2`     Compile the Quake 3 map compiler;
+         - `q3data`     Compile the q3data tool;
+     * `unvanquished`   Compile all the Unvanquished tools: `daemonmap`, `q3map3`, `q4data`;
+         - `daemonmap`  Compile the daemonmap navigation mesh generator.
+
+Type `make help` to get an exhaustive list of targets.
+
+
+#### Download details
+
+Options:
+
+* `DOWNLOAD_GAMEPACKS=OFF`  
+  Do not automatically download the gamepack data on each compilation and do not install already downloaded game packs (default: `ON`);
+* `GAMEPACKS_LICENSE_LIST=all`  
+  Download all gamepacks whatever their license (default: `free`, download free gamepacks, can be set to `none` to only filter by name);
+* `GAMEPACKS_NAME_LIST="Xonotic Unvanquished"`  
+  Download gamepacks for the given games (default: `none`, do not select more gamepacks to download).
+
+Target:
+
+* `gamepacks` Downloads the game pack data.
+
+Run `./gamepacks-manager -h` to know about available licenses and other available games. Both lists are merged, for example setting `GAMEPACKS_LICENSE_LIST=GPL` and `GAMEPACKS_NAME_LIST=Q3` will install both GPL gamepacks and the proprietary Quake 3 gamepack.
+
+
+#### Installation details
+
+Options:
+
+* `BUNDLE_LIBRARIES=ON`  
+  Bundle libraries, only Linux, FreeBSD, macOS and MSYS2 are supported at this time (default: `OFF`);
+* `FHS_INSTALL=ON` (available on POSIX systems)  
+  Install files following the Filesystem Hierarchy Standard (`bin`, `lib`, `share`, etc.)  
+  Also setup XDG mime and application support on Linux-like systems (default: `OFF`, install like in 1999);
+* `CMAKE_INSTALL_PREFIX=/usr`  
+  Install system-wide on Posix systems, always set `FHS_INSTALL` to `ON` when doing this (default: `install/` directory within source tree).
+
+Target:
 
- * `DOWNLOAD_GAMEPACKS=ON`  
-   Automatically download the gamepack data during the first compilation
- * `BUILD_CRUNCH=ON`  
-   Enable crunch support
- * `RADIANT_ABOUTMSG="Custom build"`  
-   A message shown in the about dialog
+* `install` Install files.
 
-targets:
 
- * `radiant`    Compiles the radiant core binary
- * `modules`    Compiles all modules (each module has its own target as well)
- * `plugins`    Compiles all plugins (each plugin has its own target as well)
- * `game_packs` Downloads the game pack data
- * `quake3`     Compiles all the Quake3 tools
-   - `q3map2`     Quake3 map compiler
-   - `q3data`
+## Additonnal information
 
-## Note about Crunch
+### About Crunch
 
 The crnlib used to decode `.crn` files is the one from [Dæmon](http://github.com/DaemonEngine/Daemon) which is the one by [Unity](https://github.com/Unity-Technologies/crunch/tree/unity) made cross-platform and slightly improved. Since Unity brokes compatibility with [BinomialLLC's legacy tree](https://github.com/BinomialLLC/crunch) it's required to use either the `crunch` tool from Dæmon or the one from Unity to compress textures that have to be read by radiant or q3map2.
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644 (file)
index d98cc73..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-platform: x64
-
-shallow_clone: true
-
-install:
-  - set "PATH=C:\msys64\usr\bin;%PATH%"
-  - bash -lc "pacman --noconfirm --needed -Sy bash pacman pacman-mirrors msys2-runtime msys2-runtime-devel"
-  - ps: >-
-      bash -lc @"
-        exec 0</dev/null 2>&1
-        pacman --noconfirm -Su
-        pacman --noconfirm --needed -S base-devel mingw-w64-x86_64-{toolchain,clang,cmake,gtk2,gtkglext}
-      "@
-
-build_script:
-  - set HOME=.
-  - set MSYSTEM=MINGW64
-  - ps: >-
-      bash -lc @"
-        set -e
-        exec 0</dev/null 2>&1
-        # export CC=clang
-        # export CXX=clang++
-        cmake --version
-        cmake -H. -Bbuild -G 'MSYS Makefiles' -DGTK2_GLIBCONFIG_INCLUDE_DIR=/mingw64/lib/glib-2.0/include -DGTK2_GDKCONFIG_INCLUDE_DIR=/mingw64/lib/gtk-2.0/include
-        cmake --build build
-      "@
diff --git a/branch-manager b/branch-manager
deleted file mode 100755 (executable)
index 2fd5a8f..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-#!/usr/bin/perl
-
-use strict;
-use warnings;
-
-sub OutputOf($@)
-{
-       my ($cmd, @args) = @_;
-       $cmd =~ s/#(\d)/"\$ARG$1"/g;
-       $ENV{"ARG$_"} = $args[$_-1]
-               for 1..@args;
-
-       open my $fh, '-|', $cmd
-               or die "popen $cmd: $!";
-
-       $ENV{"ARG$_"} = ''
-               for 1..@args;
-
-       undef local $/;
-       my $ret = <$fh>;
-       close $fh;
-
-       return $ret;
-}
-
-my %conf = 
-(
-       master => '',
-       revisions_applied => ''
-);
-my @revisions_applied = (); # array of [first, last] ranges
-
-sub LoadSettings()
-{
-       open my $fh, '<', ".patchsets"
-               or return;
-       while(<$fh>)
-       {
-               chomp;
-               /^([^=]*?)\s*=\s*(.*?)$/s
-                       or next;
-               die "Invalid config item: $1 (allowed: @{[sort keys %conf]})"
-                       if not exists $conf{$1};
-               $conf{$1} = $2;
-       }
-
-       @revisions_applied = map { /^(\d+)-(\d+)$/s or die "Invalid revision spec $_"; [$1, $2]; } split /,/, $conf{revisions_applied};
-}
-
-sub WriteSettings()
-{
-       $conf{revisions_applied} = join ',', map { "$_->[0]-$_->[1]" } @revisions_applied;
-
-       open my $fh, '>', ".patchsets"
-               or die "writing settings: $!";
-       for(sort keys %conf)
-       {
-               print $fh "$_ = $conf{$_}\n";
-       }
-}
-
-sub AddPatch($$)
-{
-       my ($first, $last) = @_;
-       die "Invalid range" if $first > $last;
-
-       my @rev = sort { $a->[0] <=> $b->[0] } (@revisions_applied, [$first, $last]);
-
-       my $i = 0;
-       while($i < @rev - 1)
-       {
-               my $a = $rev[$i][0];
-               my $b = $rev[$i][1];
-               my $c = $rev[$i+1][0];
-               my $d = $rev[$i+1][1];
-
-               if($b >= $c)
-               {
-                       die "overlapping patch: $a-$b overlaps $c-$d";
-               }
-               if($b == $c - 1)
-               {
-                       splice @rev, $i, 2, [$a, $d];
-                       next;
-               }
-               ++$i;
-       }
-
-       @revisions_applied = @rev;
-}
-
-sub RemovePatch($$)
-{
-       my ($first, $last) = @_;
-       die "Invalid range" if $first > $last;
-
-       my @rev = sort { $a->[0] <=> $b->[0] } (@revisions_applied);
-
-       my $i = 0;
-       while($i < @rev)
-       {
-               my $a = $rev[$i][0];
-               my $b = $rev[$i][1];
-
-               if($first >= $a && $last <= $b)
-               {
-                       # this is the range
-                       my @replacement;
-
-                       if($first == $a && $last == $b)
-                       {
-                               @replacement = ();
-                       }
-                       elsif($first == $a)
-                       {
-                               @replacement = ([$last + 1, $b]);
-                       }
-                       elsif($last == $b)
-                       {
-                               @replacement = ([$a, $first - 1]);
-                       }
-                       else
-                       {
-                               @replacement = ([$a, $first - 1], [$last + 1, $b]);
-                       }
-                       splice @rev, $i, 1, @replacement;
-                       @revisions_applied = @rev;
-                       return;
-               }
-       }
-
-       die "could not remove range: not in set";
-}
-
-sub GetUnappliedRanges($)
-{
-       my ($lastrev) = @_;
-       my @unapplied = ();
-
-       my $cur = 0;
-       for(@revisions_applied)
-       {
-               my ($a, $b) = @$_;
-               if($a - 1 >= $cur + 1)
-               {
-                       push @unapplied, [$cur + 1, $a - 1];
-               }
-               $cur = $b;
-       }
-       if($lastrev >= $cur + 1)
-       {
-               push @unapplied, [$cur + 1, $lastrev];
-       }
-       return @unapplied;
-}
-
-sub GetMasterRev()
-{
-       my $svninfo = OutputOf 'svn info #1', $conf{master};
-       $svninfo =~ /^Last Changed Rev: (\d+)$/m
-               or die "could not get svn info";
-       return $1;
-}
-
-sub GetLog($$)
-{
-       my ($first, $last) = @_;
-       my $log = OutputOf 'svn log -r#1:#2 #3', $first, $last, $conf{master};
-       $log =~ s/^-*$//gm;
-       $log =~ s/\n+/\n/gs;
-       $log =~ s/^\n//s;
-       $log =~ s/\n$//s;
-       return $log;
-}
-
-sub GetDiff($$)
-{
-       my ($first, $last) = @_;
-       return OutputOf 'svn diff -r#1:#2 #3', $first-1, $last, $conf{master};
-}
-
-my ($cmd, @args) = @ARGV;
-$cmd = 'help' if not defined $cmd;
-
-if($cmd eq 'info')
-{
-       LoadSettings();
-       for(@revisions_applied)
-       {
-               my ($a, $b) = @$_;
-               print "Applied: $a to $b\n";
-       }
-       for(GetUnappliedRanges(GetMasterRev()))
-       {
-               my ($a, $b) = @$_;
-               print "Unapplied: $a to $b\n";
-       }
-}
-elsif($cmd eq 'unmerged-diff')
-{
-       LoadSettings();
-       my @autoadd = ();
-       for(GetUnappliedRanges(GetMasterRev()))
-       {
-               my ($a, $b) = @$_;
-               my $log = GetLog $a, $b;
-               if($log eq '')
-               {
-                       push @autoadd, [$a, $b];
-                       next;
-               }
-               $log =~ s/^/  /gm;
-               print "Unapplied: $a to $b\n";
-               print "$log\n";
-               print GetDiff $a, $b;
-               print "\n";
-       }
-       for(@autoadd)
-       {
-               my ($a, $b) = @$_;
-               print "Autofilled revision hole $a to $b\n";
-               AddPatch $a, $b;
-       }
-       WriteSettings() if @autoadd;
-}
-elsif($cmd eq 'unmerged')
-{
-       LoadSettings();
-       my @autoadd = ();
-       for(GetUnappliedRanges(GetMasterRev()))
-       {
-               my ($a, $b) = @$_;
-               my $log = GetLog $a, $b;
-               if($log eq '')
-               {
-                       push @autoadd, [$a, $b];
-                       next;
-               }
-               $log =~ s/^/  /gm;
-               print "Unapplied: $a to $b\n";
-               print "$log\n\n";
-       }
-       for(@autoadd)
-       {
-               my ($a, $b) = @$_;
-               print "Autofilled revision hole $a to $b\n";
-               AddPatch $a, $b;
-       }
-       WriteSettings() if @autoadd;
-}
-elsif($cmd eq 'merge')
-{
-       my ($first, $last, $force) = @args;
-       die "Usage: $0 merge first last [--force]"
-               if not defined $first;
-       $last = $first if not defined $last;
-
-       die "Usage: $0 merge first last"
-               if "$first$last" =~ /[^0-9]/;
-
-       die "There is an uncommitted merge"
-               if -f '.commitmsg' and $force ne '--force';
-
-       LoadSettings();
-       AddPatch $first, $last;
-
-       print OutputOf 'svn merge -r#1:#2 #3', ($first - 1), $last, $conf{master};
-       print "You may also want to run $0 unmerged to fill possible revision holes\n";
-       print "Make sure there are no conflicts, then run $0 commit\n";
-       print "To abort, use $0 revert\n";
-       
-       open my $fh, '>>', '.commitmsg'
-               or die "open .commitmsg";
-       print $fh GetLog $first, $last;
-       print $fh "\n";
-       close $fh;
-
-       WriteSettings();
-}
-elsif($cmd eq 'undo')
-{
-       my ($first, $last, $force) = @args;
-       die "Usage: $0 undo first last"
-               if not defined $first;
-       $last = $first if not defined $last;
-
-       die "Usage: $0 merge first last"
-               if "$first$last" =~ /[^0-9]/;
-
-       die "There is an uncommitted merge"
-               if -f '.commitmsg' and $force ne '--force';
-
-       LoadSettings();
-       RemovePatch $first, $last;
-
-       print OutputOf 'svn merge -r#2:#1 #3', ($first - 1), $last, $conf{master};
-       print "Make sure there are no conflicts, then run $0 commit\n";
-       print "To abort, use $0 revert\n";
-
-       open my $fh, '>>', '.commitmsg'
-               or die "open .commitmsg";
-       print $fh "undo the following merge:\n", GetLog $first, $last;
-       close $fh;
-
-       WriteSettings();
-}
-elsif($cmd eq 'commit')
-{
-       system 'vim .commitmsg';
-       print "Hit Enter if OK to commit, Ctrl-C otherwise...\n";
-       my $ok = <STDIN>;
-       if(!system 'svn commit -F .commitmsg')
-       {
-               unlink '.commitmsg';
-       }
-}
-elsif($cmd eq 'revert')
-{
-       if(!system 'svn revert -R .')
-       {
-               unlink '.commitmsg';
-       }
-}
-elsif($cmd eq 'init')
-{
-       my ($master, $rev) = @args;
-       $conf{master} = $master;
-       @revisions_applied = [1, $rev];
-       WriteSettings();
-}
-else
-{
-       print <<EOF;
-Usage:
-  $0 init masterrepo rev
-  $0 info
-  $0 unmerged
-  $0 unmerged-diff
-  $0 merge rev1 [rev2] [--force]
-  $0 undo rev1 [rev2] [--force]
-  $0 commit
-  $0 revert
-EOF
-}
diff --git a/bundle/CMakeLists.txt b/bundle/CMakeLists.txt
new file mode 100644 (file)
index 0000000..790b918
--- /dev/null
@@ -0,0 +1,42 @@
+if (WIN32)
+    set(BUNDLE_OS_NAME "windows")
+    set(BUNDLE_SHARE ON)
+elseif (APPLE)
+    set(BUNDLE_OS_NAME "macos")
+    set(BUNDLE_SHARE ON)
+    set(BUNDLE_ETC ON)
+elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
+    set(BUNDLE_OS_NAME "linux")
+elseif ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
+    set(BUNDLE_OS_NAME "freebsd")
+else ()
+    set(BUNDLE_OS_NAME "unsupported")
+endif ()
+
+add_custom_target(bundle ALL
+    COMMAND
+    export LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH} &&
+    "${PROJECT_SOURCE_DIR}/library-bundler"
+    "${BUNDLE_OS_NAME}" "${PROJECT_BINARY_DIR}"
+    VERBATIM
+    COMMENT "Bundling libraries"
+)
+
+install(DIRECTORY
+    ${PROJECT_BINARY_DIR}/lib
+    DESTINATION ${FINAL_INSTALL_PREFIX}
+)
+
+if (BUNDLE_SHARE)
+    install(DIRECTORY
+        ${PROJECT_BINARY_DIR}/share
+        DESTINATION ${FINAL_INSTALL_PREFIX}
+    )
+endif ()
+
+if (BUNDLE_ETC)
+    install(DIRECTORY
+        ${PROJECT_BINARY_DIR}/etc
+        DESTINATION ${FINAL_INSTALL_PREFIX}
+    )
+endif ()
index 4b1b26504b27c0ee2beb6b1aea50f2a1619a22f2..cf12399e3f95c8d24043058a1bff32eb92e6e229 100644 (file)
@@ -1,5 +1,10 @@
 find_package(PkgConfig)
 if (PKG_CONFIG_FOUND)
+    if (APPLE)
+        # libffi is provided by base system so brew does not take the risk to override it
+        # hence then need for an explicit look-up
+        set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/opt/libffi/lib/pkgconfig")
+    endif ()
     if (GLIB_FIND_REQUIRED)
         set(_pkgconfig_REQUIRED REQUIRED)
     endif ()
index b30a1e1185fe57a11b891f277bccba0df94f0bfb..fa8ddda9af38d324e0789a37bc6faf7d0c2c8441 100644 (file)
@@ -1,14 +1,15 @@
 find_package(PkgConfig)
+if (NOT BUILTIN_GTKGLEXT OR BUILTIN_GTKGLEXT_BUILT)
 if (PKG_CONFIG_FOUND)
     if (GtkGLExt_FIND_REQUIRED)
         set(_pkgconfig_REQUIRED REQUIRED)
     endif ()
-    if (XWINDOWS)
+    if (APPLE)
+        pkg_check_modules(GtkGLExt ${_pkgconfig_REQUIRED} gtkglext-1.0 gtkglext-quartz-1.0)
+    elseif (XWINDOWS)
         pkg_check_modules(GtkGLExt ${_pkgconfig_REQUIRED} gtkglext-x11-1.0)
     elseif (WIN32)
         pkg_check_modules(GtkGLExt ${_pkgconfig_REQUIRED} gtkglext-win32-1.0)
-    else ()
-        pkg_check_modules(GtkGLExt ${_pkgconfig_REQUIRED} gtkglext-quartz-1.0)
     endif ()
 else ()
     find_path(GtkGLExt_INCLUDE_DIRS gtkglwidget.h)
@@ -25,3 +26,4 @@ else ()
     endif ()
 endif ()
 mark_as_advanced(GtkGLExt_INCLUDE_DIRS GtkGLExt_LIBRARIES)
+endif()
index 10b7a62098d66c63a1e659c07e2e1bb144f35b09..1c5721fc95b0e6cb2d651f543e496209504a1af8 100644 (file)
@@ -1,3 +1,5 @@
+// used by the legacy makefile to test if libraries work
+
 #include <stdio.h> /* jpeglib.h needs it */
 #include CONFTEST_HEADER
 int main(){
index 8233ea1e672581e7c4febfff5b58fde1b4c5f3df..6fbe90a9eabde0782defc700ffd560cfc6590d73 100644 (file)
@@ -8,7 +8,7 @@ macro(radiant_plugin name)
     copy_dlls(${name})
     install(
             TARGETS ${name}
-            LIBRARY DESTINATION plugins
+            LIBRARY DESTINATION ${RADIANT_ADDONS_DIR}/plugins
     )
 endmacro()
 
index 35fb072071286131eff680f1ea983cd2e79c63b2..d426ecf5a149b206025a4ce43c492187040f9729 100644 (file)
@@ -292,8 +292,6 @@ bool CSynapseClientBkgrnd2d::RequestAPI( APIDescriptor_t *pAPI ){
        return false;
 }
 
-#include "version.h"
-
 const char* CSynapseClientBkgrnd2d::GetInfo(){
        return "2d Background plugin built " __DATE__ " " RADIANT_VERSION;
 }
index bbc3979c56332e3ea3ad9abaf954451ea5655fd5..898c94cb00f63357d8c9d34ee144b47d779b88ed 100644 (file)
@@ -34,6 +34,8 @@
 #include "dialogs/dialogs-gtk.h"
 #include "../../libs/cmdlib.h"
 
+#define PLUGIN_NAME "bobToolz"
+
 void BobToolz_construct(){
 }
 
@@ -56,25 +58,16 @@ void BobToolz_destroy(){
        }
 }
 
-// plugin name
-const char* PLUGIN_NAME = "bobToolz";
-
 // commands in the menu
 static const char* PLUGIN_COMMANDS = "About...,-,Reset Textures...,PitOMatic,-,Vis Viewer,Brush Cleanup,Polygon Builder,Caulk Selection,-,Tree Planter,Drop Entity,Plot Splines,-,Merge Patches,Split patches,Split patches cols,Split patches rows,Turn edge";
 
 // globals
-ui::Window g_pRadiantWnd{ui::null};
-
-static const char *PLUGIN_ABOUT =   "bobToolz for SDRadiant\n"
-                                                                       "by digibob (digibob@splashdamage.com)\n"
-                                                                       "http://www.splashdamage.com\n\n"
-                                                                       "Additional Contributors:\n"
-                                                                       "MarsMattel, RR2DO2\n";
+static ui::Window main_window{ui::null};
 
 extern "C" const char* QERPlug_Init( void* hApp, void* pMainWidget ) {
-       g_pRadiantWnd = ui::Window::from(pMainWidget);
+       main_window = ui::Window::from(pMainWidget);
 
-       return "bobToolz for GTKradiant";
+       return PLUGIN_NAME " for " RADIANT_NAME;
 }
 
 extern "C" const char* QERPlug_GetName() {
@@ -122,7 +115,7 @@ extern "C" void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool
                DoFlipTerrain();
        }
        else if ( string_equal_nocase( p, "reset textures..." ) ) {
-               DoResetTextures();
+               DoResetTextures( main_window );
        }
        else if ( string_equal_nocase( p, "pitomatic" ) ) {
                DoPitBuilder();
@@ -143,10 +136,25 @@ extern "C" void QERPlug_Dispatch( const char *p, vec3_t vMin, vec3_t vMax, bool
                DoMakeChain();
        }
        else if ( string_equal_nocase( p, "path plotter..." ) ) {
-               DoPathPlotter();
+               DoPathPlotter( main_window );
        }
        else if ( string_equal_nocase( p, "about..." ) ) {
-               DoMessageBox( PLUGIN_ABOUT, "About", eMB_OK );
+               static const char *label_text =
+                       PLUGIN_NAME " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "by digibob <digibob@splashdamage.com>\n"
+                       "https://www.splashdamage.com\n\n"
+                       "Additional Contributors:\n"
+                       "Arnout van Meer <rr2do2@splashdamage.com>\n"
+                       "Mars Mattel\n\n"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                       __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( main_window, label_text,
+                                                                               "About " PLUGIN_NAME,
+                                                                               eMB_OK,
+                                                                               eMB_ICONDEFAULT );
        }
 }
 
index 4e5231d13fa80acc4e55f543d0105a23da4c9a3b..c4b6c6d511b869a461ae0010866a59fbb431dbde 100644 (file)
 
 #include "dialogs/dialogs-gtk.h"
 
+#define PLUGIN_NAME "ctfTools"
+#define CMD_ABOUT = "About..."
+
 // Radiant function table
 _QERFuncTable_1 g_FuncTable;
 _QERAppBSPFrontendTable g_BSPTable;             // for map name
 
 BOOL g_bBSPInitDone                 = FALSE;
 
-// plugin name
-static const char *PLUGIN_NAME = "ctfToolz";
-
 // commands in the menu
-static const char *PLUGIN_COMMANDS = "About...,Colour Changer...,Swap Light Colours,Change Angles 180,Swap Spawn Points";
+static const char *PLUGIN_COMMANDS = ABOUT_CMD ",Colour Changer...,Swap Light Colours,Change Angles 180,Swap Spawn Points";
 
 // globals
-GtkWidget *g_pRadiantWnd = NULL;
-
-static const char *PLUGIN_ABOUT = "ctfToolz for NetRadiant\n"
-                                                                 "by djbob\n"
-                                                                 "http://www.planetquake.com/toolz\n\n";
+GtkWidget *main_window = NULL;
 
 extern "C" LPVOID WINAPI QERPlug_GetFuncTable(){
        return &g_FuncTable;
 }
 
 extern "C" LPCSTR WINAPI QERPlug_Init( HMODULE hApp, GtkWidget* pMainWidget ){
-       g_pRadiantWnd = pMainWidget;
+       main_window = pMainWidget;
        memset( &g_FuncTable, 0, sizeof( _QERFuncTable_1 ) );
        g_FuncTable.m_fVersion = QER_PLUG_VERSION;
        g_FuncTable.m_nSize = sizeof( _QERFuncTable_1 );
@@ -79,8 +75,20 @@ extern "C" void WINAPI QERPlug_Dispatch( LPCSTR p, vec3_t vMin, vec3_t vMax, boo
                }
        }
 
-       if ( !strcmp( p, "About..." ) ) {
-               DoMessageBox( PLUGIN_ABOUT, "About", IDOK );
+       if ( !strcmp( p, CMD_ABOUT ) ) {
+               const char *label_text =
+                       PLUGIN_NAME for " RADIANT_NAME "\n\n"
+                       "Written by djbob\n\n"
+//                     20190605 dead link
+//                     "http://www.planetquake.com/toolz\n\n"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION "\n"
+                       __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( main_window, label_text,
+                                                                               "About " PLUGIN_NAME,
+                                                                               eMB_OK,
+                                                                               eMB_ICONDEFAULT );
        }
        else if ( !strcmp( p, "Colour Changer..." ) ) {
                DoCTFColourChanger();
index 9329f306a2817e7823d6e95fb456ee9e310861b3..a5732ff5cb30b00b87a9dd79221bb8905f0680ff 100644 (file)
@@ -24,6 +24,7 @@
 #include <list>
 #include <gtk/gtk.h>
 #include "gtkutil/pointer.h"
+#include "gtkutil/dialog.h"
 
 #include "../lists.h"
 #include "../misc.h"
@@ -90,7 +91,7 @@ static void dialog_button_callback( ui::Widget widget, gpointer data ){
        *ret = (EMessageBoxReturn)gpointer_to_int( data );
 }
 
-static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
+static gint custom_dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
        widget.hide();
        int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop");
        *loop = 0;
@@ -210,7 +211,7 @@ EMessageBoxReturn DoMessageBox( const char* lpText, const char* lpCaption, EMess
        int loop = 1;
 
        auto window = ui::Window( ui::window_type::TOP );
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
        gtk_window_set_title( window, lpCaption );
        gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
@@ -312,7 +313,7 @@ EMessageBoxReturn DoIntersectBox( IntersectRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Intersect" );
@@ -405,7 +406,7 @@ EMessageBoxReturn DoPolygonBox( PolygonRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Polygon Builder" );
@@ -573,7 +574,7 @@ EMessageBoxReturn DoBuildStairsBox( BuildStairsRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Stair Builder" );
@@ -823,7 +824,7 @@ EMessageBoxReturn DoDoorsBox( DoorRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Door Builder" );
@@ -1025,18 +1026,17 @@ EMessageBoxReturn DoDoorsBox( DoorRS* rs ){
 //-djbob
 }
 
-EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs ){
+EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs, ui::Window main_window ){
        ui::Widget w{ui::null};
+       ModalDialog dialog;
 
        EMessageBoxReturn ret;
        int loop = 1;
 
-       auto window = ui::Window( ui::window_type::TOP );
+       auto window = main_window.create_dialog_window( "Path Plotter", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
-       gtk_window_set_title( window, "Texture Reset" );
        gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
 
        g_object_set_data( G_OBJECT( window ), "loop", &loop );
@@ -1044,8 +1044,6 @@ EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs ){
 
        gtk_widget_realize( window );
 
-
-
        auto vbox = ui::VBox( FALSE, 10 );
        window.add(vbox);
        vbox.show();
@@ -1204,7 +1202,7 @@ EMessageBoxReturn DoCTFColourChangeBox(){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "CTF Colour Changer" );
@@ -1265,20 +1263,19 @@ EMessageBoxReturn DoCTFColourChangeBox(){
        return ret;
 }
 
-EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs ){
+EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs, ui::Window main_window ){
        Str texSelected;
 
        ui::Widget w{ui::null};
+       ModalDialog dialog;
 
        EMessageBoxReturn ret;
        int loop = 1;
 
-       auto window = ui::Window( ui::window_type::TOP );
+       auto window = main_window.create_dialog_window( "Texture Reset", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
-       gtk_window_set_title( window, "Texture Reset" );
        gtk_container_set_border_width( GTK_CONTAINER( window ), 10 );
 
        g_object_set_data( G_OBJECT( window ), "loop", &loop );
@@ -1491,7 +1488,6 @@ EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs ){
 
        // ---- /vbox ----
 
-       gtk_window_set_position( window, GTK_WIN_POS_CENTER );
        window.show();
        gtk_grab_add( window );
 
@@ -1571,7 +1567,7 @@ EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Train Thing" );
@@ -1806,7 +1802,7 @@ EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs ){
 
        auto window = ui::Window( ui::window_type::TOP );
 
-       window.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
+       window.connect( "delete_event", G_CALLBACK( custom_dialog_delete_callback ), NULL );
        window.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
 
        gtk_window_set_title( window, "Make Chain" );
index a8490459fac9e7922c7386a48a2a3186bac84c0e..f45a197bd4ffdf17e735b05a41213ece5a92f89e 100644 (file)
@@ -98,10 +98,10 @@ struct TwinWidget {
 EMessageBoxReturn DoMessageBox( const char* lpText, const char* lpCaption, EMessageBoxType type );
 EMessageBoxReturn DoIntersectBox( IntersectRS* rs );
 EMessageBoxReturn DoPolygonBox( PolygonRS* rs );
-EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs );
+EMessageBoxReturn DoResetTextureBox( ResetTextureRS* rs, ui::Window main_window );
 EMessageBoxReturn DoBuildStairsBox( BuildStairsRS* rs );
 EMessageBoxReturn DoDoorsBox( DoorRS* rs );
-EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs );
+EMessageBoxReturn DoPathPlotterBox( PathPlotterRS* rs, ui::Window main_window );
 EMessageBoxReturn DoCTFColourChangeBox();
 EMessageBoxReturn DoTrainThingBox( TrainThingRS* rs );
 EMessageBoxReturn DoMakeChainBox( MakeChainRS* rs );
index b07bf328f7642c0d5776bc70a340d9801d506d1b..decbf8ad49825f1ae49404e33ff484b97100bbb0 100644 (file)
@@ -202,7 +202,7 @@ void DoFixBrushes(){
        globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n";
 }
 
-void DoResetTextures(){
+void DoResetTextures( ui::Window main_window ){
        UndoableCommand undo( "bobToolz.resetTextures" );
        static ResetTextureRS rs;
 
@@ -217,7 +217,7 @@ void DoResetTextures(){
        }
 
        EMessageBoxReturn ret;
-       if ( ( ret = DoResetTextureBox( &rs ) ) == eIDCANCEL ) {
+       if ( ( ret = DoResetTextureBox( &rs, main_window ) ) == eIDCANCEL ) {
                return;
        }
 
@@ -362,10 +362,10 @@ void DoBuildDoors(){
        }
 }
 
-void DoPathPlotter(){
+void DoPathPlotter( ui::Window main_window ){
        UndoableCommand undo( "bobToolz.pathPlotter" );
        PathPlotterRS rs;
-       EMessageBoxReturn ret = DoPathPlotterBox( &rs );
+       EMessageBoxReturn ret = DoPathPlotterBox( &rs, main_window );
        if ( ret == eIDCANCEL ) {
                return;
        }
index 6062ea6e453328557984b6b154b5aa96770246b6..124f47258c7a2ca74574263f9667ed91fea8d16b 100644 (file)
@@ -17,6 +17,8 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include "uilib/uilib.h"
+
 class DBobView;
 class DVisDrawer;
 class DTrainDrawer;
@@ -54,10 +56,10 @@ void DoIntersect();
 void DoPolygonsTB();
 void DoPolygons();
 void DoFixBrushes();
-void DoResetTextures();
+void DoResetTextures( ui::Window main_window );
 void DoBuildStairs();
 void DoBuildDoors();
-void DoPathPlotter();
+void DoPathPlotter( ui::Window main_window );
 void DoPitBuilder();
 void DoCTFColourChanger();
 void DoMergePatches();
index f73c9787a0267a0fe49236bac473542e91f1c986..b0f7bcfb7689b54f00d67ea8d9144de6a8592c94 100644 (file)
@@ -384,7 +384,7 @@ void MakeNormal( const vec_t* va, const vec_t* vb, const vec_t* vc, vec_t* out )
 }
 
 char* GetFilename( char* buffer, const char* filename ) {
-       strcpy( buffer, GlobalRadiant().getAppPath() );
+       strcpy( buffer, GlobalRadiant().getDataPath() );
        strcat( buffer, "plugins/" );
        strcat( buffer, filename );
        return buffer;
index cbc4abf608fc26dae7fbb56e20c5b3df6bee9829..86a7767ba4f542298444394a0b68a1e57b3b6348 100644 (file)
@@ -296,7 +296,7 @@ bool ExportDataAsWavefront::WriteToFile( const std::string& path, collapsemode m
                        return false;
                }
 
-               outMtl << "# Wavefront material file exported with NetRadiants brushexport plugin.\n";
+               outMtl << "# Wavefront material file exported with " RADIANT_NAME " brushexport plugin.\n";
                outMtl << "# Material Count: " << (const Unsigned)materials.size() << "\n\n";
                for ( std::set<std::string>::const_iterator it( materials.begin() ); it != materials.end(); ++it )
                {
index d464a02a810e96c89520c0ad2276b8252be99c42..068325ea2bbf88b6a56d00026bfaa5806e162822 100644 (file)
@@ -4,6 +4,7 @@
 #include "debugging/debugging.h"
 #include "callbacks.h"
 #include "support.h"
+#include "gtkutil/dialog.h"
 
 #define GLADE_HOOKUP_OBJECT( component,widget,name ) \
        g_object_set_data_full( G_OBJECT( component ), name, \
        g_object_set_data( G_OBJECT( component ), name, (void *) widget )
 
 // created by glade
-ui::Widget create_w_plugplug2( void ){
+ui::Widget create_w_plugplug2( ui::Window main_window ){
        GSList *r_collapse_group = NULL;
+       ModalDialog dialog;
 
-       auto w_plugplug2 = ui::Window( ui::window_type::TOP );
+       auto w_plugplug2 = main_window.create_dialog_window( "BrushExport", G_CALLBACK( dialog_delete_callback ), &dialog );
        gtk_widget_set_name( w_plugplug2, "w_plugplug2" );
-       gtk_window_set_title( w_plugplug2, "BrushExport-Plugin 3.0 by namespace" );
-       gtk_window_set_position( w_plugplug2, GTK_WIN_POS_CENTER );
        gtk_window_set_destroy_with_parent( w_plugplug2, TRUE );
 
        auto vbox1 = ui::VBox( FALSE, 0 );
@@ -180,10 +180,10 @@ ui::Widget create_w_plugplug2( void ){
 ui::Widget g_brushexp_window{ui::null};
 
 // spawn plugin window (and make sure it got destroyed first or never created)
-void CreateWindow( void ){
+void CreateWindow( ui::Window main_window ){
        ASSERT_TRUE( !g_brushexp_window );
 
-       ui::Widget wnd = create_w_plugplug2();
+       ui::Widget wnd = create_w_plugplug2( main_window );
 
        // column & renderer
     auto col = ui::TreeViewColumn::from(gtk_tree_view_column_new());
index 2a221c7143d201067edc57c3e97c198f8b0d5afb..3bef9d5a713636003c2590cbdb82c578bbc67e9d 100644 (file)
@@ -43,7 +43,9 @@
 
 #include "typesystem.h"
 
-void CreateWindow( void );
+#define CMD_ABOUT "About..."
+
+void CreateWindow( ui::Window main_window );
 void DestroyWindow( void );
 bool IsWindowOpen( void );
 
@@ -60,24 +62,34 @@ const char* getName(){
        return "Brush export Plugin";
 }
 const char* getCommandList(){
-       return "Export selected as Wavefront Object;About";
+       return CMD_ABOUT ";-;Export selected as Wavefront Object";
 }
 const char* getCommandTitleList(){
        return "";
 }
 
 void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){
-       if ( string_equal( command, "About" ) ) {
-               GlobalRadiant().m_pfnMessageBox( g_mainwnd, "Brushexport plugin v 2.0 by namespace (www.codecreator.net)\n"
-                                                                                                                                 "Enjoy!\n\nSend feedback to spam@codecreator.net", "About me...",
-                                                                                eMB_OK,
-                                                                                eMB_ICONDEFAULT );
+       if ( string_equal( command, CMD_ABOUT ) ) {
+               const char *label_text =
+                       PLUGIN_NAME " " PLUGIN_VERSION " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "Written by namespace <spam@codecreator.net>\n\n"
+//                     20200404 dead link
+//                     "http://www.codecreator.net"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                       __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( g_mainwnd, label_text,
+                                                                               "About " PLUGIN_NAME,
+                                                                               eMB_OK,
+                                                                               eMB_ICONDEFAULT );
        }
        else if ( string_equal( command, "Export selected as Wavefront Object" ) ) {
                if ( IsWindowOpen() ) {
                        DestroyWindow();
                }
-               CreateWindow();
+               CreateWindow( g_mainwnd );
        }
 }
 }
@@ -101,7 +113,7 @@ class BrushExportModule : public TypeSystemRef
 _QERPluginTable m_plugin;
 public:
 typedef _QERPluginTable Type;
-STRING_CONSTANT( Name, "brushexport2" );
+STRING_CONSTANT( Name, PLUGIN_NAME );
 
 BrushExportModule(){
        m_plugin.m_pfnQERPlug_Init = &BrushExport::init;
index d924f64728304201369e6b6cebb50994008965a3..a2dc6cb63edc734f2af1377da84862ecde7d85f5 100644 (file)
@@ -22,4 +22,7 @@
 #if !defined( INCLUDED_BRUSH_EXPORT_H )
 #define INCLUDED_BRUSH_EXPORT_H
 
+#define PLUGIN_NAME "BrushExport"
+#define PLUGIN_VERSION "2.0"
+
 #endif
index 60996afc67b373563e26c1d94013145058a97bf1..3831c0beb384a91bac81c340e3cd6a31fafa096b 100644 (file)
@@ -49,12 +49,17 @@ int g_iEditMode = 0;                    // 0: editting points 1: adding points
 int g_iActiveTarget = -1;
 int g_iPreviewRunning = 0;              // 0: no preview 1: start preview 2: preview in progress
 
-static const char *PLUGIN_ABOUT = "Camera v1.0 for NetRadiant\n"
-                                                                 "by Arnout van Meer (rr2do2@splashdamage.com)\n\n"
-                                                                 "This product contains software technology\n"
-                                                                 "from id Software, Inc. ('id Technology').\n"
-                                                                 "id Technology (c) 2001, 2002 id Software, Inc.";
-
+static const char *PLUGIN_ABOUT =
+                       PLUGIN_NAME " " PLUGIN_VERSION " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "Written by Arnout van Meer <rr2do2@splashdamage.com)\n\n"
+                       "Written by Geoffrey DeWan <gdewan@prairienet.org>\n\n"
+                       "This product contains software technology\n"
+                       "from id Software, Inc. ('id Technology').\n"
+                       "id Technology (c) 2001, 2002 id Software, Inc.\n\n";
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION "\n"
+                       __DATE__;
 
 #include "iplugin.h"
 
@@ -84,7 +89,7 @@ const char* QERPlug_Init( void* hApp, void* pMainWidget ){
 
        GetFileTypeRegistry()->addType( "camera", "", filetype_t( "Camera file", "*.camera" ) );
 
-       return "Camera for NetRadiant";
+       return "Camera for " RADIANT_NAME;
 }
 
 const char* QERPlug_GetName(){
@@ -221,8 +226,6 @@ bool CameraSynapseClient::RequestAPI( APIDescriptor_t *pAPI ){
        return false;
 }
 
-#include "version.h"
-
 const char* CameraSynapseClient::GetInfo(){
        return "Camera plugin v1.0 - Arnout van Meer - built " __DATE__ " " RADIANT_VERSION;
 }
index ba008a2cc0e2c342137034c54061894848b9c55c..56ce2fea7532980b79384061fe51355584f4e852 100644 (file)
@@ -27,6 +27,9 @@
 #ifndef _CAMERA_H_
 #define _CAMERA_H_
 
+#define PLUGIN_NAME "Camera"
+#define PLUGIN_VERSION "1.0"
+
 typedef unsigned char byte;
 
 #include "mathlib.h"
index 5d72242b5eb48654cd2e96b6d990632feb75c5be..70e3eb403188941857bfe056249a52be2e96517f 100644 (file)
@@ -194,7 +194,7 @@ void DoSaveCamera() {
                        }
                        else if ( !strcmp( fullpathtofile, checkCam->GetFileName() ) ) {
                                char error[PATH_MAX + 64];
-                               sprintf( error, "Camera file \'%s\' is currently loaded by NetRadiant.\nPlease select a different filename.", fullpathtofile );
+                               sprintf( error, "Camera file \'%s\' is currently loaded by " RADIANT_NAME "\nPlease select a different filename.", fullpathtofile );
                                g_FuncTable.m_pfnMessageBox( (GtkWidget *)g_pRadiantWnd, error, "Save error", eMB_OK );
                                return;
                        }
index 84a78cd6d0b4c448bafe329f81e9bc1f5bb0a95f..8ed2dd5305f32b5231429d6112281dd525901523 100644 (file)
@@ -57,7 +57,7 @@ extern _QERBrushTable __BRUSHTABLENAME;
 #define PLUGIN
 #define Q3RADIANT
 
-//#if GDEF_OS_LINUX || GDEF_OS_MACOS
+//#if !GDEF_OS_WINDOWS
 #if 1
 #include <algorithm>
 #else
index 6acaa4b9bf41a378cd420078e0a9c40c18b26582..3af80d63a98292025e6dd70178190234ab4e8ded 100644 (file)
@@ -197,8 +197,6 @@ bool GenSurfSynapseClient::RequestAPI( APIDescriptor_t *pAPI ){
        return false;
 }
 
-#include "version.h"
-
 const char* GenSurfSynapseClient::GetInfo(){
        return "GtkGenSurf - built " __DATE__ " " RADIANT_VERSION;
 }
index 14f2c4b8b09d561325db145b34a60797fc16edcd..b1dfcfe3248a5f0163666086bf319c8bec86f404 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include "plugin.h"
-#include "version.h"
 
 /*! \file plugin.cpp
     \brief HydraToolz!
diff --git a/contrib/prtview/AboutDialog.cpp b/contrib/prtview/AboutDialog.cpp
deleted file mode 100644 (file)
index f320de2..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-   PrtView plugin for GtkRadiant
-   Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "AboutDialog.h"
-#include <gtk/gtk.h>
-#include <gtkutil/pointer.h>
-#include <uilib/uilib.h>
-#include "version.h"
-#include "gtkutil/pointer.h"
-
-#include "prtview.h"
-#include "ConfigDialog.h"
-
-static void dialog_button_callback( ui::Widget widget, gpointer data ){
-       int *loop, *ret;
-
-       auto parent = widget.window();
-       loop = (int*)g_object_get_data( G_OBJECT( parent ), "loop" );
-       ret = (int*)g_object_get_data( G_OBJECT( parent ), "ret" );
-
-       *loop = 0;
-       *ret = gpointer_to_int( data );
-}
-
-static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
-       widget.hide();
-       int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop");
-       *loop = 0;
-       return TRUE;
-}
-
-void DoAboutDlg(){
-       int loop = 1, ret = IDCANCEL;
-
-       auto dlg = ui::Window(ui::window_type::TOP);
-       gtk_window_set_title(dlg, "About Portal Viewer");
-       dlg.connect("delete_event", G_CALLBACK(dialog_delete_callback), NULL);
-       dlg.connect("destroy", G_CALLBACK(gtk_widget_destroy), NULL);
-       g_object_set_data(G_OBJECT(dlg), "loop", &loop);
-       g_object_set_data(G_OBJECT(dlg), "ret", &ret);
-
-       auto hbox = ui::HBox(FALSE, 10);
-       hbox.show();
-       dlg.add(hbox);
-       gtk_container_set_border_width(GTK_CONTAINER(hbox), 10);
-
-       char const *label_text = "Version 1.000\n\n"
-                       "Gtk port by Leonardo Zide\nleo@lokigames.com\n\n"
-                       "Written by Geoffrey DeWan\ngdewan@prairienet.org\n\n"
-                       "Built against NetRadiant " RADIANT_VERSION "\n"
-                       __DATE__;
-       auto label = ui::Label(label_text);
-       label.show();
-       hbox.pack_start( label, TRUE, TRUE, 0);
-       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
-
-       auto vbox = ui::VBox(FALSE, 0);
-       vbox.show();
-       hbox.pack_start( vbox, FALSE, FALSE, 0);
-
-       auto button = ui::Button("OK");
-       button.show();
-       vbox.pack_start( button, FALSE, FALSE, 0);
-       button.connect("clicked", G_CALLBACK(dialog_button_callback), GINT_TO_POINTER(IDOK));
-       button.dimensions(60, -1);
-
-       gtk_grab_add(dlg);
-       dlg.show();
-
-       while (loop)
-               gtk_main_iteration();
-
-       gtk_grab_remove(dlg);
-       dlg.destroy();
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-// CAboutDialog message handlers
diff --git a/contrib/prtview/AboutDialog.h b/contrib/prtview/AboutDialog.h
deleted file mode 100644 (file)
index b46fa93..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-   PrtView plugin for GtkRadiant
-   Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#if !defined( INCLUDED_ABOUTDIALOG_H )
-#define INCLUDED_ABOUTDIALOG_H
-
-void DoAboutDlg();
-
-#endif
index f08707f1368a46c9beebaf14cbaacc01dc0e5b60..c54e49a65c5a2dabccc5dfd19dd842c2e46472b2 100644 (file)
@@ -1,5 +1,4 @@
 radiant_plugin(prtview
-        AboutDialog.cpp AboutDialog.h
         ConfigDialog.cpp ConfigDialog.h
         LoadPortalFileDialog.cpp LoadPortalFileDialog.h
         portals.cpp portals.h
index 1d7f2743499b4a31460baa1b26376d230d39bb14..688a66b18f20223bf611af831e12dee113208642 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <gtk/gtk.h>
 #include <uilib/uilib.h>
+#include "gtkutil/dialog.h"
 #include "gtkutil/pointer.h"
 
 #include "iscenegraph.h"
@@ -28,6 +29,8 @@
 #include "prtview.h"
 #include "portals.h"
 
+ui::Window config_dialog{ui::null};
+
 static void dialog_button_callback( ui::Widget widget, gpointer data ){
        int *loop, *ret;
 
@@ -39,7 +42,7 @@ static void dialog_button_callback( ui::Widget widget, gpointer data ){
        *ret = gpointer_to_int( data );
 }
 
-static gint dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
+static gint custom_dialog_delete_callback( ui::Widget widget, GdkEvent* event, gpointer data ){
        widget.hide();
        int *loop = (int *) g_object_get_data(G_OBJECT(widget), "loop");
        *loop = 0;
@@ -58,6 +61,7 @@ static int DoColor( PackedColour *c ){
        clr.green = (guint16) (GetBValue(*c) * (65535 / 255));
 
        auto dlg = ui::Widget::from(gtk_color_selection_dialog_new( "Choose Color" ));
+       gtk_window_set_transient_for( GTK_WINDOW( dlg ), config_dialog );
        gtk_color_selection_set_current_color( GTK_COLOR_SELECTION( gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dlg)) ), &clr );
        dlg.connect( "delete_event", G_CALLBACK( dialog_delete_callback ), NULL );
        dlg.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
@@ -233,17 +237,16 @@ static void OnClip(ui::Widget widget, gpointer data ){
        SceneChangeNotify();
 }
 
-void DoConfigDialog(){
+void DoConfigDialog( ui::Window main_window ){
        int loop = 1, ret = IDCANCEL;
+       ModalDialog dialog;
 
-       auto dlg = ui::Window( ui::window_type::TOP );
-       gtk_window_set_title( dlg, "Portal Viewer Configuration" );
-       dlg.connect( "delete_event",
-                                               G_CALLBACK( dialog_delete_callback ), NULL );
-       dlg.connect( "destroy",
-                                               G_CALLBACK( gtk_widget_destroy ), NULL );
+       auto dlg = main_window.create_dialog_window( "Portal Viewer Configuration", G_CALLBACK( custom_dialog_delete_callback ), &dialog );
+       
+       dlg.connect( "destroy", G_CALLBACK( gtk_widget_destroy ), NULL );
        g_object_set_data( G_OBJECT( dlg ), "loop", &loop );
        g_object_set_data( G_OBJECT( dlg ), "ret", &ret );
+       config_dialog = dlg;
 
        auto vbox = ui::VBox( FALSE, 5 );
        vbox.show();
index a9725847e6294506947494317ed5f5fd0f2505ad..e17e41267790cd0f44bbb7136cdf2e6d6284427e 100644 (file)
@@ -20,6 +20,8 @@
 #if !defined( INCLUDED_CONFIGDIALOG_H )
 #define INCLUDED_CONFIGDIALOG_H
 
-void DoConfigDialog();
+#include <uilib/uilib.h>
+
+void DoConfigDialog( ui::Window main_window );
 
 #endif
index 080af13a3c8ba35a8b1e087a4cc7a7865c95b3a5..14aeec1325bb80feec981cda000f8170d6c21bb0 100644 (file)
 #include "stream/stringstream.h"
 
 #include "portals.h"
-#include "AboutDialog.h"
 #include "ConfigDialog.h"
 #include "LoadPortalFileDialog.h"
 
 #define Q3R_CMD_SPLITTER "-"
-#define Q3R_CMD_ABOUT "About Portal Viewer"
+#define Q3R_CMD_ABOUT "About..."
 #define Q3R_CMD_LOAD "Load .prt file"
 #define Q3R_CMD_RELEASE "Unload .prt file"
 #define Q3R_CMD_SHOW_3D "Toggle portals (3D)"
 #define Q3R_CMD_SHOW_2D "Toggle portals (2D)"
-#define Q3R_CMD_OPTIONS "Configure Portal Viewer"
+#define Q3R_CMD_OPTIONS "Configure..."
 
 CopiedString INIfn;
 
@@ -66,6 +65,7 @@ const char *TRANS_3D = "Transparency";
 const char *CLIP_RANGE = "ClipRange";
 const char *CLIP = "Clip";
 
+static ui::Window main_window{ui::null};
 
 void PrtView_construct(){
        StringOutputStream tmp( 64 );
@@ -185,9 +185,6 @@ void INISetInt( const char *key, int val, const char *comment /* = NULL */ ){
        save_var( INIfn.c_str(), CONFIG_SECTION, key, s );
 }
 
-
-// plugin name
-static const char *PLUGIN_NAME = "Portal Viewer";
 // commands in the menu
 static const char *PLUGIN_COMMANDS =
        Q3R_CMD_ABOUT ";"
@@ -203,7 +200,10 @@ static const char *PLUGIN_COMMANDS =
 
 
 const char* QERPlug_Init( void *hApp, void* pMainWidget ){
-       return "Portal Viewer for Q3Radiant";
+       main_window = ui::Window::from(pMainWidget);
+       ASSERT_TRUE( main_window );
+
+       return PLUGIN_NAME " for " RADIANT_NAME;
 }
 
 const char* QERPlug_GetName(){
@@ -224,7 +224,19 @@ void QERPlug_Dispatch( const char* p, float* vMin, float* vMax, bool bSingleBrus
        globalOutputStream() << MSG_PREFIX "Command \"" << p << "\"\n";
 
        if ( !strcmp( p,Q3R_CMD_ABOUT ) ) {
-               DoAboutDlg();
+               const char *label_text =
+                               PLUGIN_NAME " " PLUGIN_VERSION " for "
+                               RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                               "Gtk port by Leonardo Zide <leo@lokigames.com>\n"
+                               "Written by Geoffrey DeWan <gdewan@prairienet.org>\n\n"
+                               "Built against "
+                               RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                               __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( main_window, label_text,
+                                                                               "About " PLUGIN_NAME,
+                                                                               eMB_OK,
+                                                                               eMB_ICONDEFAULT );
        }
        else if ( !strcmp( p,Q3R_CMD_LOAD ) ) {
                if ( DoLoadPortalFileDialog() == IDOK ) {
@@ -270,7 +282,7 @@ void QERPlug_Dispatch( const char* p, float* vMin, float* vMax, bool bSingleBrus
                }
        }
        else if ( !strcmp( p,Q3R_CMD_OPTIONS ) ) {
-               DoConfigDialog();
+               DoConfigDialog( main_window );
                SaveConfig();
 
                SceneChangeNotify();
@@ -294,7 +306,7 @@ class PrtViewPluginModule
 _QERPluginTable m_plugin;
 public:
 typedef _QERPluginTable Type;
-STRING_CONSTANT( Name, "prtview" );
+STRING_CONSTANT( Name, PLUGIN_NAME );
 
 PrtViewPluginModule(){
        m_plugin.m_pfnQERPlug_Init = QERPlug_Init;
index 6b0487826aff3b6b7834b80e9c5488c3e3c21d23..e6942cc99ea3811b0ad7b6bd94c407c9b7092f68 100644 (file)
 #if !defined( INCLUDED_PRTVIEW_H )
 #define INCLUDED_PRTVIEW_H
 
-#define MSG_PREFIX "Portal Viewer plugin: "
+#define PLUGIN_NAME "Portal Viewer"
+#define PLUGIN_VERSION "1.0"
+
+#define MSG_PREFIX PLUGIN_NAME " plugin: "
 
 void InitInstance();
 void SaveConfig();
@@ -31,5 +34,4 @@ void INISetInt( const char *key, int val, const char *comment = 0 );
 const int IDOK                = 1;
 const int IDCANCEL            = 2;
 
-
 #endif
index 9d7bc4c52c78eca92c1e9d80095534675e5dc5d0..06c378a5ec956bc2cffd0e7a2268ed2b421f18e4 100644 (file)
@@ -41,6 +41,8 @@
 
 #include "generic/callback.h"
 
+#define CMD_ABOUT "About..."
+
 namespace {
 const char SHADERTAG_FILE[] = "shadertags.xml";
 }
@@ -57,7 +59,7 @@ ShaderPlugPluginDependencies() :
 
 namespace Shaderplug
 {
-ui::Window g_window{ui::null};
+ui::Window main_window{ui::null};
 
 std::vector<const char*> archives;
 std::set<std::string> shaders;
@@ -67,26 +69,38 @@ XmlTagBuilder TagBuilder;
 void CreateTagFile();
 
 const char* init( void* hApp, void* pMainWidget ){
-       g_window = ui::Window::from(pMainWidget);
+       main_window = ui::Window::from(pMainWidget);
        return "";
 }
+
 const char* getName(){
-       return "ShaderPlug";
+       return PLUGIN_NAME;
 }
+
 const char* getCommandList(){
-       return "About;Create tag file";
+       return CMD_ABOUT ";-;Create tag file";
 }
+
 const char* getCommandTitleList(){
        return "";
 }
+
 void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){
-       if ( string_equal( command, "About" ) ) {
-               GlobalRadiant().m_pfnMessageBox( g_window, "Shaderplug (1.0)\n\n"
-                                                                                                                                "by Shaderman (shaderman@gmx.net)",
-                                                                                "About",
+       if ( string_equal( command, CMD_ABOUT ) ) {
+               const char *label_text =
+                       PLUGIN_NAME " " PLUGIN_VERSION " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "Written by Shaderman <shaderman@gmx.net>\n\n"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                       __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( main_window, label_text,
+                                                                                "About " PLUGIN_NAME,
                                                                                 eMB_OK,
                                                                                 eMB_ICONDEFAULT );
        }
+
        if ( string_equal( command, "Create tag file" ) ) {
                CreateTagFile();
        }
@@ -130,25 +144,25 @@ void GetAllShaders(){
 
 void GetArchiveList(){
        GlobalFileSystem().forEachArchive(makeCallbackF(loadArchiveFile));
-       globalOutputStream() << "Shaderplug: " << (const Unsigned)Shaderplug::archives.size() << " archives found.\n";
+       globalOutputStream() << PLUGIN_NAME ": " << (const Unsigned)Shaderplug::archives.size() << " archives found.\n";
 }
 
 void CreateTagFile(){
        const char* shader_type = GlobalRadiant().getGameDescriptionKeyValue( "shaders" );
 
        GetAllShaders();
-       globalOutputStream() << "Shaderplug: " << (const Unsigned)shaders.size() << " shaders found.\n";
+       globalOutputStream() << PLUGIN_NAME ": " << (const Unsigned)shaders.size() << " shaders found.\n";
 
        if ( string_equal( shader_type, "quake3" ) ) {
                GetTextures( "jpg" );
                GetTextures( "tga" );
                GetTextures( "png" );
 
-               globalOutputStream() << "Shaderplug: " << (const Unsigned)textures.size() << " textures found.\n";
+               globalOutputStream() << PLUGIN_NAME ":" << (const Unsigned)textures.size() << " textures found.\n";
        }
 
        if ( shaders.size() || textures.size() != 0 ) {
-               globalOutputStream() << "Shaderplug: Creating XML tag file.\n";
+               globalOutputStream() << PLUGIN_NAME ":Creating XML tag file.\n";
 
                TagBuilder.CreateXmlDocument();
 
@@ -172,26 +186,26 @@ void CreateTagFile(){
                char message[256];
                strcpy( message, "Tag file saved to\n" );
                strcat( message, tagFile );
-               strcat( message, "\nPlease restart Radiant now.\n" );
+               strcat( message, "\nPlease restart " RADIANT_NAME " now.\n" );
 
                if ( file_exists( tagFile ) ) {
-                       EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox( g_window ,
+                       EMessageBoxReturn result = GlobalRadiant().m_pfnMessageBox( main_window ,
                                                                                                                                                "WARNING! A tag file already exists! Overwrite it?", "Overwrite tag file?",
                                                                                                                                                eMB_NOYES,
                                                                                                                                                eMB_ICONWARNING );
 
                        if ( result == eIDYES ) {
                                TagBuilder.SaveXmlDoc( tagFile );
-                               GlobalRadiant().m_pfnMessageBox( g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK );
+                               GlobalRadiant().m_pfnMessageBox( main_window, message, "INFO", eMB_OK, eMB_ICONASTERISK );
                        }
                }
                else {
                        TagBuilder.SaveXmlDoc( tagFile );
-                       GlobalRadiant().m_pfnMessageBox( g_window, message, "INFO", eMB_OK, eMB_ICONASTERISK );
+                       GlobalRadiant().m_pfnMessageBox( main_window, message, "INFO", eMB_OK, eMB_ICONASTERISK );
                }
        }
        else {
-               GlobalRadiant().m_pfnMessageBox( g_window,
+               GlobalRadiant().m_pfnMessageBox( main_window,
                                                                                 "No shaders or textures found. No XML tag file created!\n"
                                                                                 "",
                                                                                 "ERROR",
@@ -206,7 +220,7 @@ class ShaderPluginModule
 _QERPluginTable m_plugin;
 public:
 typedef _QERPluginTable Type;
-STRING_CONSTANT( Name, "ShaderPlug" );
+STRING_CONSTANT( Name, PLUGIN_NAME );
 
 ShaderPluginModule(){
        m_plugin.m_pfnQERPlug_Init = &Shaderplug::init;
index d30c625d4ce8ff4f0132a86b47cd862bbc187fd2..a7f198110c2d59c700ca7e9f66f84ce4eba9a307 100644 (file)
@@ -24,4 +24,7 @@
 
 #include "xml/xmltextags.h"
 
+#define PLUGIN_NAME "ShaderPlug"
+#define PLUGIN_VERSION "1.0"
+
 #endif
index ac8233d1fd87f29d2986fd21d8134c1fece223fa..11aca066381717c90fa67ebc983945af20120824 100644 (file)
@@ -37,7 +37,8 @@
 
 #include <gtk/gtk.h>     // to display something with gtk (windows, buttons etc.), the whole package might not be necessary
 
-void about_plugin_window();
+#define CMD_ABOUT "About..."
+
 void MapCoordinator();
 
 #if !GDEF_OS_WINDOWS
@@ -190,13 +191,13 @@ char MenuList[100] = "";
 
 const char* init( void* hApp, void* pMainWidget ){
        main_window = ui::Window::from(pMainWidget);
-       return "Initializing SunPlug for GTKRadiant";
+       return "Initializing " PLUGIN_NAME " for " RADIANT_NAME;
 }
 const char* getName(){
-       return "SunPlug"; // name that is shown in the menue
+       return PLUGIN_NAME; // name that is shown in the menue
 }
 const char* getCommandList(){
-       const char about[] = "About...";
+       const char about[] = CMD_ABOUT;
        const char etMapCoordinator[] = ";ET-MapCoordinator";
 
        strcat( MenuList, about );
@@ -209,8 +210,19 @@ const char* getCommandTitleList(){
        return "";
 }
 void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){ // message processing
-       if ( string_equal( command, "About..." ) ) {
-               about_plugin_window();
+       if ( string_equal( command, CMD_ABOUT ) ) {
+               char const *label_text = 
+                       PLUGIN_NAME " " PLUGIN_VERSION " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "Written by Topsun\n\n"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                       __DATE__;
+
+               GlobalRadiant().m_pfnMessageBox( main_window, label_text,
+                                                                               "About " PLUGIN_NAME,
+                                                                               eMB_OK,
+                                                                               eMB_ICONDEFAULT );
        }
        if ( string_equal( command, "ET-MapCoordinator" ) ) {
                MapCoordinator();
@@ -223,7 +235,7 @@ class SunPlugModule : public TypeSystemRef
 _QERPluginTable m_plugin;
 public:
 typedef _QERPluginTable Type;
-STRING_CONSTANT( Name, "SunPlug" );
+STRING_CONSTANT( Name, PLUGIN_NAME );
 
 SunPlugModule(){
        m_plugin.m_pfnQERPlug_Init = &SunPlug::init;
@@ -252,33 +264,6 @@ extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer& server
 // ** my stuff **
 //  ************
 
-// About dialog
-void about_plugin_window(){
-       auto window = ui::Window( ui::window_type::TOP ); // create a window
-       gtk_window_set_transient_for( window, SunPlug::main_window ); // make the window to stay in front of the main window
-       window.connect( "delete_event", G_CALLBACK( delete_event ), NULL ); // connect the delete event
-       window.connect( "destroy", G_CALLBACK( destroy ), NULL ); // connect the destroy event for the window
-       gtk_window_set_title( window, "About SunPlug" ); // set the title of the window for the window
-       gtk_window_set_resizable( window, FALSE ); // don't let the user resize the window
-       gtk_window_set_modal( window, TRUE ); // force the user not to do something with the other windows
-       gtk_container_set_border_width( GTK_CONTAINER( window ), 10 ); // set the border of the window
-
-       auto vbox = ui::VBox( FALSE, 10 ); // create a box to arrange new objects vertically
-       window.add(vbox);
-
-       auto label = ui::Label( "SunPlug v1.0 for NetRadiant 1.5\nby Topsun" ); // create a label
-       gtk_label_set_justify( GTK_LABEL( label ), GTK_JUSTIFY_LEFT ); // text align left
-       vbox.pack_start( label, FALSE, FALSE, 2 ); // insert the label in the box
-
-       auto button = ui::Button( "OK" ); // create a button with text
-       g_signal_connect_swapped( G_OBJECT( button ), "clicked", G_CALLBACK( gtk_widget_destroy ), (void *) window ); // connect the click event to close the window
-       vbox.pack_start( button, FALSE, FALSE, 2 ); // insert the button in the box
-
-       gtk_window_set_position( window, GTK_WIN_POS_CENTER ); // center the window on screen
-
-       gtk_widget_show_all( window ); // show the window and all subelements
-}
-
 // get the current bounding box and return the optimal coordinates
 void GetOptimalCoordinates( AABB *levelBoundingBox ){
        int half_width, half_heigth, center_x, center_y;
index 8ea4f50cca2a9eaced1154a77bcb02d01db6ae8a..402709dfbcafbf589fa2d22995d2b13df2a4e55e 100644 (file)
@@ -19,7 +19,9 @@
  */
 
 #ifndef _PLUGIN_SUNPLUG_
-  #define _PLUGIN_SUNPLUG_
+#define _PLUGIN_SUNPLUG_
 
+#define PLUGIN_NAME "SunPlug"
+#define PLUGIN_VERSION "1.0"
 
 #endif // _PLUGIN_SUNPLUG_
index 99815ab013b670aec626b4f3c0993d7f8e2bf62b..33b6d3be9be9b74ed5588d9afad99a7d548d1e11 100644 (file)
 
 #include "iplugin.h"
 
-#include "version.h"
-
 #include "string/string.h"
 #include "modulesystem/singletonmodule.h"
 
 #include <gtk/gtk.h>
 
-#define PLUGIN_VERSION "0.4"
-
 #include "ifilter.h"
 #include "ibrush.h"
 #include "iundo.h"       // declaration of undo system
@@ -43,6 +39,8 @@
 #include "qerplugin.h"   // declaration to use other interfaces as a plugin
 #include "ieclass.h"
 
+#define CMD_ABOUT "About..."
+
 class UFOAIPluginDependencies :
        public GlobalRadiantModuleRef,  // basic class for all other module refs
        public GlobalUndoModuleRef,     // used to say radiant that something has changed and to undo that
@@ -66,24 +64,29 @@ const char* init( void* hApp, void* pMainWidget ){
        return "Initializing GTKRadiant UFOAI plugin";
 }
 const char* getName(){
-       return "UFO:AI";
+       return PLUGIN_NAME;
 }
 const char* getCommandList(){
        /*GlobalRadiant().getGameName()*/
-       return "About;-;Worldspawn reset;Worldspawn;Perform check;-;Level 1;Level 2;Level 3;Level 4;Level 5;Level 6;Level 7;Level 8;-;StepOn;ActorClip;WeaponClip;Nodraw";
+       return CMD_ABOUT ";-;Worldspawn reset;Worldspawn;Perform check;-;Level 1;Level 2;Level 3;Level 4;Level 5;Level 6;Level 7;Level 8;-;StepOn;ActorClip;WeaponClip;Nodraw";
 }
 const char* getCommandTitleList(){
        return "";
 }
 void dispatch( const char* command, float* vMin, float* vMax, bool bSingleBrush ){
        char const *message = NULL;
-       if ( string_equal( command, "About" ) ) {
-               char const *version_string = "UFO:AI Plugin (http://ufoai.sf.net)\nBuild: " __DATE__
-                       "\nRadiant version: " RADIANT_VERSION
-                       "\nPlugin version: " PLUGIN_VERSION
-                       "\nAuthor: Martin Gerhardy (tlh2000/mattn)\n";
+       if ( string_equal( command, CMD_ABOUT ) ) {
+               const char *label_text = 
+                       PLUGIN_NAME " " PLUGIN_VERSION " for "
+                       RADIANT_NAME " " RADIANT_VERSION "\n\n"
+                       "Written by Martin Gerhardy (tlh2000/mattn)\n"
+                       "for the UFO:AI project (http://ufoai.org)\n\n"
+                       "Built against "
+                       RADIANT_NAME " " RADIANT_VERSION_STRING "\n"
+                       __DATE__;
+
                GlobalRadiant().m_pfnMessageBox( g_mainwnd,
-                                                                                version_string, "About",
+                                                                                label_text, "About" PLUGIN_NAME,
                                                                                 eMB_OK, eMB_ICONDEFAULT );
        }
        else if ( string_equal( command, "Level 1" ) ) {
index 38ad4ccf437889cef010cd0190e4a7cf35b8d597..4611e3c49d1fa8c7af95c5331f02f33eec895331 100644 (file)
@@ -19,4 +19,7 @@
 #if !defined( INCLUDED_UFOAI_H )
 #define INCLUDED_UFOAI_H
 
+#define PLUGIN_NAME "UFO:AI"
+#define PLUGIN_VERSION "0.4"
+
 #endif
diff --git a/cross-Makefile.conf b/cross-Makefile.conf
deleted file mode 100644 (file)
index caba2e6..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# Usage:
-# copy this file to Makefile.conf
-# edit the paths in here
-
-# how to call the mingw tools
-MINGW_EXEC_PREFIX = i486-mingw32-
-
-# use mingw32
-include mingw-Makefile.inc
-include mingw-radiantdeps-Makefile.inc
index de757e082ddf9ee4360fd4bce4be492b86724c35..54217e42e031ad13e93c1fd8cdbadba96c0f590e 100644 (file)
@@ -1,16 +1,11 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-  <meta http-equiv="Content-Style-Type" content="text/css">
-  <title></title>
-  <meta name="Generator" content="Cocoa HTML Writer">
-  <meta name="CocoaVersion" content="1038.25">
-  <style type="text/css">
-    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
-  </style>
-</head>
-<body>
-<p class="p1"><a href="https://gitlab.com/xonotic/xonotic/wikis/Mapping">Xonotic Mapping Wiki</A></p>
-</body>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+       <head>
+               <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+               <meta http-equiv="refresh" content="0;URL=https://gitlab.com/xonotic/xonotic/wikis/Mapping">
+               <title>Xonotic Mapping Wiki</title>
+       </head>
+       <body>
+               <p><a href="https://gitlab.com/xonotic/xonotic/wikis/Mapping">Xonotic Mapping Wiki</a></p>
+       </body>
 </html>
diff --git a/easy-builder b/easy-builder
new file mode 100755 (executable)
index 0000000..220649f
--- /dev/null
@@ -0,0 +1,167 @@
+#! /usr/bin/env bash
+
+# This script is meant to be kept small and simple
+# If you think about adding features, it's probably a bad idea
+
+set -e # exit if a command fails
+set -o pipefail # Will return the exit status of make if it fails
+
+project_source_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+build_dir="${project_source_dir}/build${SUBDIR:+/${SUBDIR}}"
+install_dir="${project_source_dir}/install${SUBDIR:+/${SUBDIR}}"
+
+install_target='install/strip'
+build_type='Release'
+
+case "$(uname -s)" in
+       # Stripping is known to make non-PIE Linux netradiant binary unusable.
+       # Maybe that's related to the way we patch rpath?
+       #
+       # Building NetRadiant as non-PIE is required because of
+       # a mistake in the mimetype-library that prevents users
+       # to run the application from file managers on Linux.
+       #
+       # See: https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11
+       #
+       # After installation it's possible to strip manually all binaries except
+       # the netradiant one.
+       'Linux')
+               install_target='install'
+               ;;
+       # Stripping is known to make FreeBSD binaries unusable.
+       # Maybe that's related to the way we patch rpath?
+       'FreeBSD')
+               install_target='install'
+               ;;
+esac
+
+_job_count=4
+
+_nproc () {
+       if command -v 'nproc' >/dev/null
+       then
+               nproc
+       else
+               case "$(uname -s)" in
+                       'Linux')
+                               egrep "^processor" /proc/cpuinfo | wc -l
+                               ;;
+                       'FreeBSD')
+                               sysctl -n hw.ncpu
+                               ;;
+                       'Darwin')
+                               sysctl -n hw.logicalcpu \
+                               || sysctl -n hw.ncpu
+                               ;;
+                       'MSYS_NT-'*|'CYGWIN_NT-'*|'MINGW'*'_NT-'*)
+                               if command -v 'wmic' >/dev/null
+                               then
+                                       wmic cpu get NumberOfLogicalProcessors/Format:List \
+                                               | grep -m1 '=' | cut -f2 -d'='
+                               else
+                                       echo "${NUMBER_OF_PROCESSORS:-${_job_count}}"
+                               fi
+                               ;;
+                       *)
+                               echo "${_job_count}"
+                               ;;
+               esac
+       fi
+}
+
+job_count="$(_nproc)" 2>/dev/null
+job_count="${job_count:-${_job_count}}"
+
+declare -a cmake_user_opts
+while [ ! -z "${1}" ]
+do
+       case "${1}" in
+       '-j'*)
+               job_count="${1:2}"
+               shift
+               ;;
+       '--debug')
+               install_target='install'
+               build_type='Debug'
+               shift
+               ;;
+       *)
+       cmake_user_opts[${#cmake_user_opts[@]}]="${1}"
+       shift
+               ;;
+       esac
+done
+
+declare -a fetch_submodules_cmd
+for submodule_file in 'libs/crunch/inc/crn_decomp.h' \
+       'tools/unvanquished/daemonmap/tools/quake3/q3map2/main.c'
+do
+       if ! [ -f "${project_source_dir}/${submodule_file}" ]
+       then
+               fetch_submodules_cmd=(git -C "${project_source_dir}" submodule update --init --recursive)
+       fi
+done
+
+case "$(uname -s)" in
+       'Darwin')
+               cmake_user_opts[${#cmake_user_opts[@]}]='-DBUILTIN_GTKGLEXT=ON -DBUILTIN_GTKTHEME_MOJAVE=ON'
+               ;;
+esac
+
+task_enter_build_dir () {
+       sync
+       mkdir -pv "${build_dir}"
+       cd "${build_dir}"
+}
+
+task_fetch_submodules () {
+       sync
+       "${fetch_submodules_cmd[@]}"
+}
+
+task_configure () {
+       sync
+       cmake \
+               -G'Unix Makefiles' \
+               -D'CMAKE_INSTALL_PREFIX'="${install_dir}" \
+               -D'CMAKE_BUILD_TYPE'="${build_type}" \
+               "${cmake_user_opts[@]}" \
+               "${project_source_dir}"
+}
+
+task_build_builtins () {
+       sync
+       make -j"${job_count}" builtins
+}
+
+task_discover_builtins () {
+       sync
+       cmake "${project_source_dir}"
+}
+
+task_build () {
+       sync
+       make -j"${job_count}"
+}
+
+task_install () {
+       sync
+       make "${install_target}"
+}
+
+set -x
+
+task_enter_build_dir
+
+task_fetch_submodules
+
+task_configure
+
+task_build_builtins
+
+task_discover_builtins
+
+task_build
+
+task_install
diff --git a/flake.nix b/flake.nix
new file mode 100644 (file)
index 0000000..cdfed9f
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,42 @@
+{
+  #description = "a toolset to manage and build `pk3` or `dpk` source directories";
+
+  inputs = {
+    nixpkgs.url = "flake:nixpkgs";
+  };
+
+  outputs = { self, nixpkgs }:
+    let
+      pkgs = nixpkgs.legacyPackages.x86_64-linux;
+    in {
+
+      packages.x86_64-linux.quake-tools =
+        pkgs.stdenv.mkDerivation {
+          name = "quake-tools";
+
+          src = pkgs.lib.cleanSource ./.;
+
+          cmakeFlags = [
+            "-DGIT_VERSION=nix" # meh
+            "-DDOWNLOAD_GAMEPACKS=OFF"
+            "-DBUNDLE_LIBRARIES=OFF"
+            "-DBUILD_CRUNCH=OFF"
+            "-DBUILD_DAEMONMAP=OFF"
+            "-DBUILD_RADIANT=OFF"
+            "-DBUILD_TOOLS=ON"
+            "-DFHS_INSTALL=ON"
+          ];
+
+          buildInputs = with pkgs; [
+            pkg-config gtk2 glib libwebp libxml2 minizip
+          ];
+          nativeBuildInputs = with pkgs; [
+            cmake subversion unzip
+            python3 python38Packages.pyyaml
+          ];
+
+          postInstall = "rm -r $out/share";
+        };
+
+    };
+}
index 6f280f6e0d112e505c4a7fe48d44e2d2fb14cb04..232c75962dc9ad21a60a937e24cad02c8bc7cbf4 100755 (executable)
@@ -3,8 +3,8 @@
 # get usage help this way:
 # ./gamepack_manager -h
 
-: "${CP:=cp -v}"
-: "${CP_R:=cp -r --preserve=timestamps}"
+: "${CP:=cp -va}"
+: "${CP_R:=cp -Rva}"
 : "${GIT:=git}"
 : "${SVN:=svn}"
 : "${WGET:=wget}"
@@ -40,48 +40,108 @@ cat <<\EOF
 # Obsolete packs                                      #
 #######################################################
 
-# Quake2World was renamed as Quetoo
-# Other gamepacks have better version available
-
-# OpenArena     unknown      zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OpenArenaPack.zip
-# Quake         proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/QuakePack.zip
-# Quake2World   GPL          svn     svn://jdolan.dyndns.org/quake2world/trunk/gtkradiant
-# Tremulous     proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/TremulousPack/branches/1.5/
-# Unvanquished  unknown      zip     http://ingar.intranifty.net/gtkradiant/files/gamepacks/UnvanquishedPack.zip
-# Warsow        GPL          svn     https://svn.bountysource.com/wswpack/trunk/netradiant/games/WarsowPack/
-# Warsow        GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/WarsowPack.zip
+# Quake2World was renamed as Quetoo.
+# JediAcademy and JediOutcast gamepacks are unusable.
+# Other gamepacks have better version available.
+
+# JediAcademy   no   proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/JAPack/branches/1.5/
+# JediOutcast   no   proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/JK2Pack/branches/1.5/
+# Kingpin       no   unknown      zip     http://download.kingpin.info/kingpin/editing/maps/map_editors/NetRadiant/addon/Kingpinpack.zip
+# Neverball     no   proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/NeverballPack.zip
+# OpenArena     no   unknown      zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OpenArenaPack.zip
+# Quake2World   no   GPL          svn     svn://jdolan.dyndns.org/quake2world/trunk/gtkradiant
+# Quake3        no   proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q3Pack/trunk/ 29
+# Quake         no   proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/QuakePack.zip
+# Tremulous     no   proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/TremulousPack/branches/1.5/
+# Tremulous     no   proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/TremulousPack.zip
+# Unvanquished  no   unknown      zip     http://ingar.intranifty.net/gtkradiant/files/gamepacks/UnvanquishedPack.zip
+# Warfork       no   GPL          zip     https://cdn.discordapp.com/attachments/611741789237411850/659512520553267201/netradiant_warfork_gamepack.zip
+# Warsow        no   GPL          svn     https://svn.bountysource.com/wswpack/trunk/netradiant/games/WarsowPack/
+# Warsow        no   GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/WarsowPack.zip
 
 #######################################################
 # Usable packs                                        #
 #######################################################
 
-DarkPlaces      GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/DarkPlacesPack/branches/1.5/
-Doom3           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Doom3Pack/branches/1.5/
-ET              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/ETPack/branches/1.5/
-Heretic2        proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Her2Pack/branches/1.5/
-JediAcademy     proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/JAPack/branches/1.5/
-Neverball       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/NeverballPack.zip
-Nexuiz          GPL          gitdir  git://git.icculus.org/divverent/nexuiz.git misc/netradiant-NexuizPack master
-OpenArena       GPL          git     https://github.com/NeonKnightOA/oagamepack.git
-Osirion         GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OsirionPack.zip
-Prey            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/PreyPack/trunk/
-Q3              proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q3Pack/trunk/ 29
-Quake2          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q2Pack/branches/1.5/
-Quake4          proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q4Pack/branches/1.5/
-Quake           GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/Quake1Pack.zip
-Quetoo          GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/QuetooPack/branches/1.5/
-Tremulous       proprietary  zip     http://ingar.intranifty.net/files/netradiant/gamepacks/TremulousPack.zip
-TurtleArena     proprietary  git     https://github.com/Turtle-Arena/turtle-arena-radiant-pack.git
-UFOAI           proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/UFOAIPack/branches/1.5/
-Unvanquished    BSD          git     https://github.com/Unvanquished/unvanquished-mapeditor-support.git
-Warsow          GPL          git     https://github.com/Warsow/NetRadiantPack.git
-Wolf            proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/WolfPack/branches/1.5/
-Xonotic         GPL          git     https://gitlab.com/xonotic/netradiant-xonoticpack.git
+AlienArena      yes  GPL          svn     https://svn.code.sf.net/p/alienarena-cc/code/trunk/tools/netradiant_gamepack/AlienArenaPack
+DarkPlaces      yes  GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/DarkPlacesPack/branches/1.5/
+Doom3           yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Doom3Pack/branches/1.5/
+ET              yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/ETPack/branches/1.5/
+Heretic2        yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Her2Pack/branches/1.5/
+Kingpin         yes  unknown      git     https://gitlab.com/netradiant/gamepacks/kingpin-mapeditor-support.git
+Neverball       yes  proprietary  git     https://gitlab.com/netradiant/gamepacks/neverball-mapeditor-support.git
+Nexuiz          yes  GPL          gitdir  git://git.icculus.org/divverent/nexuiz.git misc/netradiant-NexuizPack master
+OpenArena       yes  GPL          git     https://github.com/NeonKnightOA/oagamepack.git
+Osirion         yes  GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/OsirionPack.zip
+Prey            yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/PreyPack/trunk/
+Q3Rally         yes  proprietary  svn     https://svn.code.sf.net/p/q3rallysa/code/tools/radiant-config/radiant15-netradiant/
+Quake2          yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q2Pack/branches/1.5/
+Quake3          yes  proprietary  git     https://gitlab.com/netradiant/gamepacks/quake3-mapeditor-support.git
+Quake4          yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/Q4Pack/branches/1.5/
+QuakeLive       yes  proprietary  git     https://gitlab.com/netradiant/gamepacks/quakelive-mapeditor-support.git
+Quake           yes  GPL          zip     http://ingar.intranifty.net/files/netradiant/gamepacks/Quake1Pack.zip
+Quetoo          yes  GPL          svn     svn://svn.icculus.org/gtkradiant-gamepacks/QuetooPack/branches/1.5/
+SmokinGuns      yes  unknown      git     https://github.com/smokin-guns/smokinguns-mapeditor-support.git
+SoF2            yes  unknown      git     https://gitlab.com/netradiant/gamepacks/sof2-mapeditor-support.git
+STVEF           yes  unknown      git     https://gitlab.com/netradiant/gamepacks/stvef-mapeditor-support.git
+Tremulous       yes  proprietary  git     https://gitlab.com/netradiant/gamepacks/tremulous-mapeditor-support.git
+TurtleArena     yes  proprietary  git     https://github.com/Turtle-Arena/turtle-arena-radiant-pack.git
+UFOAI           yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/UFOAIPack/branches/1.5/
+Unvanquished    yes  BSD          git     https://github.com/Unvanquished/unvanquished-mapeditor-support.git
+UrbanTerror     yes  unknown      git     https://gitlab.com/netradiant/gamepacks/urbanterror-mapeditor-support.git
+Warfork         yes  GPL          git     https://gitlab.com/netradiant/gamepacks/warfork-mapeditor-support.git
+Warsow          yes  GPL          git     https://github.com/Warsow/NetRadiantPack.git
+Wolf            yes  proprietary  svn     svn://svn.icculus.org/gtkradiant-gamepacks/WolfPack/branches/1.5/
+WoP             yes  proprietary  git     https://github.com/PadWorld-Entertainment/wop-mapeditor-support.git
+Xonotic         yes  GPL          git     https://gitlab.com/xonotic/netradiant-xonoticpack.git
+ZEQ2Lite        yes  unknown      git     https://gitlab.com/netradiant/gamepacks/zeq2lite-mapeditor-support.git
 EOF
 }
 
+if command -v gsed >/dev/null
+then
+       SED=gsed
+elif sed --help >/dev/null 2>&1
+then
+       SED=sed
+else
+       printf 'ERROR: GNU sed is missing\n' >&2
+       exit 1
+fi
+
+printRealPath ()
+{
+       if command -v grealpath >/dev/null
+       then
+               grealpath "${1}"
+       elif command -v realpath >/dev/null
+       then
+               realpath "${1}"
+       elif command -v greadlink >/dev/null
+       then
+               # test greadlink first as greadlink has the feature on macos
+               # but readlink only has it on linux, note that it's probably
+               # the same on bsd
+               # note: (g)readlink requires the file to be create first
+               greadlink -f "${1}"
+       elif command -v readlink >/dev/null
+       then
+               # --help and -f options are GNU readlink things
+               if readlink --help >/dev/null 2>&1
+               then
+                       readlink -f "${1}"
+               else
+                       if ! python -c "import os; print(os.path.realpath('${1}'))"
+                       then
+                               printf 'ERROR: GNU realpath or other way to compute real path of a file is missing\n' >&2
+                               exit 1
+                       fi
+               fi
+       fi
+}
+
 sanitizeDB () {
-       sed -e 's/#.*//;s/[ \t][ \t][ \t]*/\t/g;s/^[ \t]*//;s/[ \t]*$//' \
+       ${SED} -e 's/#.*//;s/[ \t][ \t][ \t]*/\t/g;s/^[ \t]*//;s/[ \t]*$//' \
        | grep -v '^$'
 }
 
@@ -99,7 +159,7 @@ printList () {
 dedupeList () {
        printList "${1}" \
        | tr '\n' ' ' \
-       | sed -e 's/ $//'
+       | ${SED} -e 's/ $//'
 }
 
 printGamePackDB () {
@@ -109,7 +169,7 @@ printGamePackDB () {
 
 printLicenseList () {
        printGamePackDB \
-       | awk '{ print $2 }' \
+       | awk '{ print $3 }' \
        | sort -u
 }
 
@@ -156,9 +216,9 @@ printNameListByLicense () {
        for license in ${license_list}
        do
                printGamePackDB \
-               | awk '$2 == "'"${license}"'"' \
+               | awk '$3 == "'"${license}"'"' \
                | awk '{ print $1 }'
-       done
+       done | sort -u
 }
 
 printNameListByName () {
@@ -176,14 +236,15 @@ printNameListByName () {
                                break
                                ;;
                        'all')
-                               local name_list
                                name_list="$(printNameList)"
                                break
                                ;;
+                       'validated')
+                               name_list="${name_list} validated"
+                               ;;
                        *)
                                if printNameList | inList "${name}"
                                then
-                                       local name_list
                                        name_list="${name_list} ${name}"
                                else
                                        printError "unknown name: ${name}"
@@ -196,6 +257,13 @@ printNameListByName () {
 
        for name in ${name_list}
        do
+               if [ "${name}" = 'validated' ]
+               then
+                       printGamePackDB \
+                       | awk '$2 == "yes"' \
+                       | awk '{ print $1 }'
+               fi
+
                printGamePackDB \
                | awk '$1 == "'"${name}"'"' \
                | awk '{ print $1 }'
@@ -249,9 +317,10 @@ downloadPack () {
        download_dir="${1}"
        name="${2}"
 
-       license="$(getValue "${name}" '2')"
-       source_type="$(getValue "${name}" '3')"
-       source_url="$(getValue "${name}" '4')"
+       validation="$(getValue "${name}" 2)"
+       license="$(getValue "${name}" 3)"
+       source_type="$(getValue "${name}" 4)"
+       source_url="$(getValue "${name}" 5)"
 
        pack="${name}${pack_suffix}"
 
@@ -275,7 +344,7 @@ downloadPack () {
 
                case "${source_type}" in
                        'svn')
-                               reference="$(getValue "${name}" '5')"
+                               reference="$(getValue "${name}" 6)"
                                if [ -z "${reference}" ]
                                then
                                        reference='HEAD'
@@ -307,12 +376,17 @@ downloadPack () {
                                )
                                ${RM_R} "${pack}"
                                ${MKDIR} "${pack}"
-                               ${MV} 'zipdownload/'*'/'* "${pack}/"
+                               if [ -d 'zipdownload/games' ]
+                               then
+                                       ${MV} 'zipdownload/'* "${pack}/"
+                               else
+                                       ${MV} 'zipdownload/'*'/'* "${pack}/"
+                               fi
                                ${RM_R} 'zipdownload'
                                ;;
                        'gitdir')
-                               local subdir="$(getValue "${name}" '5')"
-                               local branch="$(getValue "${name}" '6')"
+                               local subdir="$(getValue "${name}" 6)"
+                               local branch="$(getValue "${name}" 7)"
                                ${RM_R} "${pack}"
                                ${GIT} archive --remote="${source_url}" --prefix="${pack}/" "${branch}":"${subdir}" \
                                | ${TAR} xvf -
@@ -389,10 +463,14 @@ installPack () {
                        ;;
        esac
 
-       # mkeditorpacks-based gamepack
        if [ -d "${download_dir}/${pack}/build/netradiant" ]
        then
+               # mkeditorpacks-based gamepack
                pack="${pack}/build/netradiant"
+       elif [ -d "${download_dir}/${pack}/netradiant" ]
+       then
+               # other layout
+               pack="${pack}/netradiant"
        fi
 
        path="${download_dir}/${pack}"
@@ -444,7 +522,7 @@ printHelp () {
        local prog_name
 
        tab="$(printf '\t')"
-       prog_name="$(basename "$(readlink -f "${0}")")"
+       prog_name='gamepack-manager'
 
        cat <<-EOF
        Usage: ${prog_name} [OPTION] [SELECTION <ARGUMENTS>] [ACTION]
@@ -459,15 +537,15 @@ printHelp () {
        SELECTIONS:
        ${tab}-n, --name NAMES…
        ${tab}${tab}select games by name (default: none)
-       ${tab}${tab}special keyword: all, none
+       ${tab}${tab}special keyword: validated, all, none
        ${tab}${tab}available games:
-       $(printNameList | sed -e 's/^/\t\t\t/')
+       $(printNameList | ${SED} -e 's/^/\t\t\t/')
 
        ${tab}-l, --license LICENSES…
        ${tab}${tab}select games by license (default: none)
        ${tab}${tab}special keyword: free, all, none
        ${tab}${tab}available licenses:
-       $(printLicenseList | sed -e 's/^/\t\t\t/')
+       $(printLicenseList | ${SED} -e 's/^/\t\t\t/')
 
        ACTIONS:
        ${tab}-ln, --list-names
@@ -476,7 +554,7 @@ printHelp () {
        ${tab}-ll, --list-licenses
        ${tab}${tab}list all game licenses
 
-       ${tab}-ls, --list
+       ${tab}-ls, --list-selected
        ${tab}${tab}list selected games
 
        ${tab}-d, --download
@@ -488,9 +566,13 @@ printHelp () {
        ${tab}-h, --help
        ${tab}${tab}print this help
 
-       Example:
+       Examples:
+       ${tab}${prog_name} --license GPL BSD --list-selected
        ${tab}${prog_name} --license GPL BSD --download --install
 
+       ${tab}${prog_name} --name validated --list-selected
+       ${tab}${prog_name} --name validated --download --install
+
        EOF
 
        exit
@@ -534,14 +616,14 @@ do
        fi
 
        case "${1}" in
-               '--list-licenses'|'-ll')
+               '--list-names'|'-ln')
                        arg_type=''
-                       list_licenses='true'
+                       list_names='true'
                        option_list="${option_list} ${1}"
                        ;;
-               '--list-names'|'-ln')
+               '--list-licenses'|'-ll')
                        arg_type=''
-                       list_names='true'
+                       list_licenses='true'
                        option_list="${option_list} ${1}"
                        ;;
                '--list-selected'|'-ls')
@@ -585,12 +667,12 @@ do
                        ;;
                *)
                        case "${arg_type}" in
-                               'pack-license')
-                                       license_list="${license_list} ${1}"
-                                       ;;
                                'pack-name')
                                        name_list="${name_list} ${1}"
                                        ;;
+                               'pack-license')
+                                       license_list="${license_list} ${1}"
+                                       ;;
                                'download-dir')
                                        if [ -z "${download_dir}" ]
                                        then
@@ -620,12 +702,24 @@ done
 # compatibility with legacy Makefile
 if [ "${DOWNLOAD_GAMEPACKS}" = 'yes' ]
 then
-       ! [ -z "${DOWNLOADDIR}" ] && download_dir="${DOWNLOADDIR}"
-       ! [ -z "${INSTALLDIR}" ] && install_dir="${INSTALDIR}"
+       if ! [ -z "${DOWNLOADDIR}" ]
+       then
+               download_dir="${DOWNLOADDIR}"
+       fi
+
+       if ! [ -z "${INSTALLDIR}" ]
+       then
+               install_dir="${INSTALLDIR}"
+       fi
+
        license_list='free'
        by_license='true'
+
        download_packs='true'
+       mkdir_download='true'
+
        install_packs='true'
+       mkdir_install='true'
 fi
 
 if [ -z "${download_dir}" ]
@@ -638,14 +732,14 @@ then
        install_dir="${default_install_dir}"
 fi
 
-if "${by_license}"
+if "${by_name}"
 then
-       selected_list="${selected_list} $(printNameListByLicense "${license_list}")"
+       selected_list="${selected_list} $(printNameListByName "${name_list}")"
 fi
 
-if "${by_name}"
+if "${by_license}"
 then
-       selected_list="${selected_list} $(printNameListByName "${name_list}")"
+       selected_list="${selected_list} $(printNameListByLicense "${license_list}")"
 fi
 
 selected_list="$(dedupeList "${selected_list}")"
@@ -653,24 +747,25 @@ selected_list="$(dedupeList "${selected_list}")"
 if "${mkdir_download}"
 then
        ${MKDIR_P} "${download_dir}"
-       real_download_dir="$(readlink -f "${download_dir}")"
+       real_download_dir="$(printRealPath "${download_dir}")"
 fi
 
 if "${mkdir_install}"
 then
        ${MKDIR_P} "${install_dir}"
-       real_install_dir="$(readlink -f "${install_dir}")"
+       real_install_dir="$(printRealPath "${install_dir}")"
 fi
 
-if "${list_licenses}"
+if "${list_names}"
 then
-       printLicenseList
+       printNameList
 fi
 
-if "${list_names}"
+if "${list_licenses}"
 then
-       printNameList
+       printLicenseList
 fi
+
 if "${list_selected}"
 then
        printList "${selected_list}"
diff --git a/generic_cpp.py b/generic_cpp.py
deleted file mode 100644 (file)
index 62d51ed..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2001-2006 William Joseph.
-# For a list of contributors, see the accompanying CONTRIBUTORS file.
-# 
-# This file is part of GtkRadiant.
-# 
-# GtkRadiant is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-# 
-# GtkRadiant is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GtkRadiant; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-import os
-import sys
-
-def svnAddText(filename):
-  os.system("svn add " + filename);
-  os.system("svn ps svn:eol-style native " + filename);
-
-def createCPPTemplate(filename, name):
-  file = open(filename, "wt")
-  file.write("\n")
-  file.write("#include \"" + name + ".h\"\n")
-  file.write("\n")
-  file.close()
-
-if __name__ == "__main__":
-  name = sys.argv[1]
-  location = sys.argv[2]
-  filename = os.path.join(location, name + ".cpp")
-  createCPPTemplate(filename, name)
-  svnAddText(filename)
diff --git a/generic_h.py b/generic_h.py
deleted file mode 100644 (file)
index 9f8b7e9..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright (C) 2001-2006 William Joseph.
-# For a list of contributors, see the accompanying CONTRIBUTORS file.
-# 
-# This file is part of GtkRadiant.
-# 
-# GtkRadiant is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-# 
-# GtkRadiant is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GtkRadiant; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-import os
-import sys
-
-def svnAddText(filename):
-  os.system("svn add " + filename);
-  os.system("svn ps svn:eol-style native " + filename);
-
-def createHeaderTemplate(filename, name):
-  file = open(filename, "wt")
-  file.write("\n")
-  file.write("#if !defined(_INCLUDED_" + name.upper() + "_H_)\n")
-  file.write("#define _INCLUDED_" + name.upper() + "_H_\n")
-  file.write("\n")
-  file.write("#endif\n")
-
-if __name__ == "__main__":
-  name = sys.argv[1]
-  location = sys.argv[2]
-  filename = os.path.join(location, name + ".h")
-  createHeaderTemplate(filename, name)
-  svnAddText(filename)
diff --git a/generic_module.py b/generic_module.py
deleted file mode 100644 (file)
index e055e8f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright (C) 2001-2006 William Joseph.
-# For a list of contributors, see the accompanying CONTRIBUTORS file.
-# 
-# This file is part of GtkRadiant.
-# 
-# GtkRadiant is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-# 
-# GtkRadiant is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-# 
-# You should have received a copy of the GNU General Public License
-# along with GtkRadiant; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-import os
-import sys
-
-def svnAddText(filename):
-  os.system("svn add " + filename);
-  os.system("svn ps svn:eol-style native " + filename);
-
-def createHeaderTemplate(filename, name):
-  file = open(filename, "wt")
-  file.write("\n")
-  file.write("#if !defined(INCLUDED_" + name.upper() + "_H)\n")
-  file.write("#define INCLUDED_" + name.upper() + "_H\n")
-  file.write("\n")
-  file.write("#endif\n")
-
-def createCPPTemplate(filename, name):
-  file = open(filename, "wt")
-  file.write("\n")
-  file.write("#include \"" + name + ".h\"\n")
-  file.write("\n")
-  file.close()
-
-if __name__ == "__main__":
-  if not len(sys.argv) == 2:
-    print "usage: " + sys.argv[0] + " <module-path>"
-    
-  path = sys.argv[1]
-  name = os.path.split(path)[1];
-  
-  h = os.path.normpath(path + ".h")
-  print "writing " + h;
-  createHeaderTemplate(h, name)
-  svnAddText(h)
-
-  cpp = os.path.normpath(path + ".cpp")
-  print "writing " + cpp;
-  createCPPTemplate(cpp, name)
-  svnAddText(cpp)
-  
index 8f44194128ade27ac79a97e16a0100032e36fc90..cc465b8f488e71bc8dbc2979920c6f0d9dffcc2f 100644 (file)
Binary files a/icons/h2data.ico and b/icons/h2data.ico differ
diff --git a/icons/h2data.xcf b/icons/h2data.xcf
new file mode 100644 (file)
index 0000000..90bb093
Binary files /dev/null and b/icons/h2data.xcf differ
diff --git a/icons/netradiant.desktop b/icons/netradiant.desktop
new file mode 100755 (executable)
index 0000000..593510e
--- /dev/null
@@ -0,0 +1,12 @@
+[Desktop Entry]
+Version=1.5.0
+Name=NetRadiant
+GenericName=Level editor
+Comment=3D level editor for id Tech based games
+Icon=netradiant
+Exec=netradiant %f
+Terminal=false
+Type=Application
+MimeType=application/x-netradiant-map;
+Categories=Game;Graphics;3DGraphics;
+Keywords=darkplaces,nexuiz,openarena,osirion,quake,quake2,quake3,quetoo,tremulous,ufoai,unvanquished,warsow,xonotic,idtech;level;map;game development;
diff --git a/icons/netradiant.ico b/icons/netradiant.ico
new file mode 100644 (file)
index 0000000..b3f99e4
Binary files /dev/null and b/icons/netradiant.ico differ
diff --git a/icons/netradiant.png b/icons/netradiant.png
new file mode 100644 (file)
index 0000000..4ec03fa
Binary files /dev/null and b/icons/netradiant.png differ
index 5c508c916d6f6acbd73a33fbfa54412068cd1aea..fdbefc29d694d92759eafe6ea3f094ddea779c44 100644 (file)
Binary files a/icons/q2map.ico and b/icons/q2map.ico differ
index 8f44194128ade27ac79a97e16a0100032e36fc90..cc4f2d3f92303f4a962377d592a509bb2fca2414 100644 (file)
Binary files a/icons/q3data.ico and b/icons/q3data.ico differ
diff --git a/icons/q3data.xcf b/icons/q3data.xcf
new file mode 100644 (file)
index 0000000..9097384
Binary files /dev/null and b/icons/q3data.xcf differ
index 4fe56fa66b6c64f555216795121402f9f324afbc..52758dc46e98d02ce7bcc0dccae8eff0011343f7 100644 (file)
Binary files a/icons/q3map2.ico and b/icons/q3map2.ico differ
diff --git a/icons/radiant-src.png b/icons/radiant-src.png
deleted file mode 100644 (file)
index 720e985..0000000
Binary files a/icons/radiant-src.png and /dev/null differ
diff --git a/icons/radiant.ico b/icons/radiant.ico
deleted file mode 100644 (file)
index d377f82..0000000
Binary files a/icons/radiant.ico and /dev/null differ
diff --git a/icons/x-netradiant-map.xml b/icons/x-netradiant-map.xml
new file mode 100644 (file)
index 0000000..60ff0c8
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
+    <mime-type type="application/x-netradiant-map">
+    <generic-icon name="text-x-generic"/>
+    <sub-class-of type="text/plain"/>
+    <comment>Game level source</comment>
+    <glob pattern="*.map"/>
+  </mime-type>
+</mime-info>
index 40ab7936dae9a0795b5404e731566e4a2a075d27..05d4d9fc780f8386be498a5b5aa984adfee8680a 100644 (file)
@@ -14,7 +14,6 @@ add_library(includes
         ifilter.h
         igl.h
         iglrender.h
-        igtkgl.h
         iimage.h
         imap.h
         imodel.h
@@ -42,7 +41,6 @@ add_library(includes
         renderable.h
         selectable.h
         stream_version.h
-        version.h
         warnings.h
         windowobserver.h
         )
diff --git a/include/igtkgl.h b/include/igtkgl.h
deleted file mode 100644 (file)
index b445456..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#if !defined( INCLUDED_IGTKGL_H )
-#define INCLUDED_IGTKGL_H
-
-#include <uilib/uilib.h>
-#include "generic/constant.h"
-
-template<class T>
-using func = T *;
-
-struct _QERGtkGLTable {
-    STRING_CONSTANT(Name, "gtkgl");
-    INTEGER_CONSTANT(Version, 1);
-
-    func<ui::GLArea(bool zbufffer)> glwidget_new;
-    func<void(ui::GLArea self)> glwidget_swap_buffers;
-    func<bool(ui::GLArea self)> glwidget_make_current;
-    func<void(ui::GLArea self)> glwidget_destroy_context;
-    func<void(ui::GLArea self)> glwidget_create_context;
-};
-
-#endif
index 3f3419dd88724fc31fd25b916ae08164e6bb254e..5539a1441dd04379bb11a676f54222e9fa79ad48 100644 (file)
@@ -107,6 +107,8 @@ virtual qtexture_t* getBump() const = 0;
 virtual qtexture_t* getSpecular() const = 0;
 // get shader name
 virtual const char* getName() const = 0;
+virtual const char* getWadName() const = 0;
+virtual void setWadName( const char* name ) = 0;
 virtual bool IsInUse() const = 0;
 virtual void SetInUse( bool bInUse ) = 0;
 // get the editor flags (QER_NOCARVE QER_TRANS)
@@ -124,7 +126,6 @@ virtual ECull getCull() = 0;
 virtual const char* getShaderFileName() const = 0;
 
 virtual const ShaderLayer* firstLayer() const = 0;
-virtual void forEachLayer( const ShaderLayerCallback& layer ) const = 0;
 
 virtual qtexture_t* lightFalloffImage() const = 0;
 };
diff --git a/include/lib.rc b/include/lib.rc
new file mode 100644 (file)
index 0000000..3ad3a12
--- /dev/null
@@ -0,0 +1,11 @@
+1 24 /* RT_MANIFEST */
+BEGIN
+    "<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>"
+    "<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">"
+      "<dependency>"
+        "<dependentAssembly>"
+          "<assemblyIdentity type=""win32"" name=""lib"" version=""1.0.0.0""/>"
+        "</dependentAssembly>"
+      "</dependency>"
+    "</assembly>"
+END
index b6a8865f2bcc6c9b42c147f6469c3704cdb834e8..b18651fa956d9c3d88b3b4fd2ee4774883352a62 100644 (file)
@@ -65,7 +65,7 @@ enum EMessageBoxReturn
 
 // simple Message Box, see above for the 'type' flags
 
-typedef EMessageBoxReturn ( *PFN_QERAPP_MESSAGEBOX )( ui::Window parent, const char* text, const char* caption /* = "NetRadiant"*/, EMessageBoxType type /* = eMB_OK*/, EMessageBoxIcon icon /* = eMB_ICONDEFAULT*/ );
+typedef EMessageBoxReturn ( *PFN_QERAPP_MESSAGEBOX )( ui::Window parent, const char* text, const char* caption /* = RADIANT_NAME */, EMessageBoxType type /* = eMB_OK*/, EMessageBoxIcon icon /* = eMB_ICONDEFAULT*/ );
 
 // file and directory selection functions return null if the user hits cancel
 // - 'title' is the dialog title (can be null)
@@ -120,6 +120,7 @@ struct _QERFuncTable_1
        const char* ( *getLocalRcPath )( );
        const char* ( *getGameToolsPath )( );
        const char* ( *getAppPath )( );
+       const char* ( *getDataPath )( );
        const char* ( *getSettingsPath )( );
        const char* ( *getMapsPath )( );
 
diff --git a/include/version.h b/include/version.h
deleted file mode 100644 (file)
index 3df8773..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Makefile appends preprocessor flags instead now
-#ifndef RADIANT_VERSION
-#error no RADIANT_VERSION defined
-#endif
-#ifndef RADIANT_MAJOR_VERSION
-#error no RADIANT_MAJOR_VERSION defined
-#endif
-#ifndef RADIANT_MINOR_VERSION
-#error no RADIANT_MINOR_VERSION defined
-#endif
-#ifndef RADIANT_PATCH_VERSION
-#error no RADIANT_PATCH_VERSION defined
-#endif
diff --git a/install-dlls-fedora.sh b/install-dlls-fedora.sh
deleted file mode 100755 (executable)
index 5f88229..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-set -x
-
-DLL_PATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
-
-cd install
-
-STARTDIR=`pwd`
-
-COPYDEPS() 
-{
-       FILE=$1
-       if [ -e "$FILE" ] ;then
-               DEPS=`objdump -p "$FILE" 2>/dev/null |grep -i "DLL Name"|sort |uniq|cut -d\  -f3 |egrep -vi '(GDI32.dll|KERNEL32.dll|USER32.dll|msvcrt.dll|MSIMG32.DLL|ole32.dll|OPENGL32.DLL|SHELL32.DLL|WS2_32.dll)' || true`
-                               
-               for DEP in $DEPS; do
-                       basename -a "$STARTDIR"/*.dll | grep -v "*.dll"|sort >  "$STARTDIR"/.HAVES
-                       if ! cat "$STARTDIR"/.HAVES | grep "$DEP" >/dev/null ;then
-                               cp -v "$DLL_PATH"/"$DEP" "$STARTDIR" 2>/dev/null
-                               COPYDEPS "$DLL_PATH"/"$DEP"
-                       fi
-                       rm -f "$STARTDIR"/.HAVES
-               done
-       fi
-}
-
-for i in *.exe;do
-       COPYDEPS "$i";
-done
-
diff --git a/install-dlls.sh b/install-dlls.sh
deleted file mode 100755 (executable)
index 60ca8db..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-: ${WHICHDLL:=which}
-: ${GTKDIR:=/gtk}
-: ${CP:=cp}
-: ${CAT:=cat}
-: ${MKDIR:=mkdir -p}
-: ${INSTALLDIR:=.}
-
-for DLL in \
-       freetype6.dll \
-       intl.dll \
-       libatk-1.0-0.dll \
-       libcairo-2.dll \
-       libexpat-1.dll \
-       libfontconfig-1.dll \
-       libgdkglext-win32-1.0-0.dll \
-       libgdk_pixbuf-2.0-0.dll \
-       libgdk-win32-2.0-0.dll \
-       libgio-2.0-0.dll \
-       libglib-2.0-0.dll \
-       libgmodule-2.0-0.dll \
-       libgobject-2.0-0.dll \
-       libgthread-2.0-0.dll \
-       libgtkglext-win32-1.0-0.dll \
-       libgtk-win32-2.0-0.dll \
-       libjpeg-8.dll \
-       libpango-1.0-0.dll \
-       libpangocairo-1.0-0.dll \
-       libpangoft2-1.0-0.dll \
-       libpangowin32-1.0-0.dll \
-       libpng14-14.dll \
-       libxml2-2.dll \
-       zlib1.dll \
-       libgcc_s_sjlj-1.dll \
-       libstdc++-6.dll \
-; do
-       $CP "`$WHICHDLL $DLL`" $INSTALLDIR/
-done
-
-$MKDIR $INSTALLDIR/etc/fonts
-$CAT > $INSTALLDIR/etc/fonts/fonts.conf <<EOF
-<?xml version="1.0"?>
-<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
-<!-- /etc/fonts/fonts.conf file to configure system font access -->
-<fontconfig>
-
-<!--
-       DO NOT EDIT THIS FILE.
-       IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
-       LOCAL CHANGES BELONG IN 'local.conf'.
-
-       The intent of this standard configuration file is to be adequate for
-       most environments.  If you have a reasonably normal environment and
-       have found problems with this configuration, they are probably
-       things that others will also want fixed.  Please submit any
-       problems to the fontconfig bugzilla system located at fontconfig.org
-
-       Note that the normal 'make install' procedure for fontconfig is to
-       replace any existing fonts.conf file with the new version.  Place
-       any local customizations in local.conf which this file references.
-
-       Keith Packard
--->
-
-<!-- Font directory list -->
-
-       <dir>WINDOWSFONTDIR</dir>
-       
-       <dir>~/.fonts</dir>
-
-<!--
-  Accept deprecated 'mono' alias, replacing it with 'monospace'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>mono</string>
-               </test>
-               <edit name="family" mode="assign">
-                       <string>monospace</string>
-               </edit>
-       </match>
-
-<!--
-  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>sans serif</string>
-               </test>
-               <edit name="family" mode="assign">
-                       <string>sans-serif</string>
-               </edit>
-       </match>
-
-<!--
-  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>sans</string>
-               </test>
-               <edit name="family" mode="assign">
-                       <string>sans-serif</string>
-               </edit>
-       </match>
-
-<!--
-  Load local system customization file
--->
-       <include ignore_missing="yes">conf.d</include>
-
-<!-- Font cache directory list -->
-
-       <cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir>
-       <cachedir>~/.fontconfig</cachedir>
-
-       <config>
-<!--
-  These are the default Unicode chars that are expected to be blank
-  in fonts.  All other blank chars are assumed to be broken and
-  won't appear in the resulting charsets
- -->
-               <blank>
-                       <int>0x0020</int>       <!-- SPACE -->
-                       <int>0x00A0</int>       <!-- NO-BREAK SPACE -->
-                       <int>0x00AD</int>       <!-- SOFT HYPHEN -->
-                       <int>0x034F</int>       <!-- COMBINING GRAPHEME JOINER -->
-                       <int>0x0600</int>       <!-- ARABIC NUMBER SIGN -->
-                       <int>0x0601</int>       <!-- ARABIC SIGN SANAH -->
-                       <int>0x0602</int>       <!-- ARABIC FOOTNOTE MARKER -->
-                       <int>0x0603</int>       <!-- ARABIC SIGN SAFHA -->
-                       <int>0x06DD</int>       <!-- ARABIC END OF AYAH -->
-                       <int>0x070F</int>       <!-- SYRIAC ABBREVIATION MARK -->
-                       <int>0x115F</int>       <!-- HANGUL CHOSEONG FILLER -->
-                       <int>0x1160</int>       <!-- HANGUL JUNGSEONG FILLER -->
-                       <int>0x1680</int>       <!-- OGHAM SPACE MARK -->
-                       <int>0x17B4</int>       <!-- KHMER VOWEL INHERENT AQ -->
-                       <int>0x17B5</int>       <!-- KHMER VOWEL INHERENT AA -->
-                       <int>0x180E</int>       <!-- MONGOLIAN VOWEL SEPARATOR -->
-                       <int>0x2000</int>       <!-- EN QUAD -->
-                       <int>0x2001</int>       <!-- EM QUAD -->
-                       <int>0x2002</int>       <!-- EN SPACE -->
-                       <int>0x2003</int>       <!-- EM SPACE -->
-                       <int>0x2004</int>       <!-- THREE-PER-EM SPACE -->
-                       <int>0x2005</int>       <!-- FOUR-PER-EM SPACE -->
-                       <int>0x2006</int>       <!-- SIX-PER-EM SPACE -->
-                       <int>0x2007</int>       <!-- FIGURE SPACE -->
-                       <int>0x2008</int>       <!-- PUNCTUATION SPACE -->
-                       <int>0x2009</int>       <!-- THIN SPACE -->
-                       <int>0x200A</int>       <!-- HAIR SPACE -->
-                       <int>0x200B</int>       <!-- ZERO WIDTH SPACE -->
-                       <int>0x200C</int>       <!-- ZERO WIDTH NON-JOINER -->
-                       <int>0x200D</int>       <!-- ZERO WIDTH JOINER -->
-                       <int>0x200E</int>       <!-- LEFT-TO-RIGHT MARK -->
-                       <int>0x200F</int>       <!-- RIGHT-TO-LEFT MARK -->
-                       <int>0x2028</int>       <!-- LINE SEPARATOR -->
-                       <int>0x2029</int>       <!-- PARAGRAPH SEPARATOR -->
-                       <int>0x202A</int>       <!-- LEFT-TO-RIGHT EMBEDDING -->
-                       <int>0x202B</int>       <!-- RIGHT-TO-LEFT EMBEDDING -->
-                       <int>0x202C</int>       <!-- POP DIRECTIONAL FORMATTING -->
-                       <int>0x202D</int>       <!-- LEFT-TO-RIGHT OVERRIDE -->
-                       <int>0x202E</int>       <!-- RIGHT-TO-LEFT OVERRIDE -->
-                       <int>0x202F</int>       <!-- NARROW NO-BREAK SPACE -->
-                       <int>0x205F</int>       <!-- MEDIUM MATHEMATICAL SPACE -->
-                       <int>0x2060</int>       <!-- WORD JOINER -->
-                       <int>0x2061</int>       <!-- FUNCTION APPLICATION -->
-                       <int>0x2062</int>       <!-- INVISIBLE TIMES -->
-                       <int>0x2063</int>       <!-- INVISIBLE SEPARATOR -->
-                       <int>0x206A</int>       <!-- INHIBIT SYMMETRIC SWAPPING -->
-                       <int>0x206B</int>       <!-- ACTIVATE SYMMETRIC SWAPPING -->
-                       <int>0x206C</int>       <!-- INHIBIT ARABIC FORM SHAPING -->
-                       <int>0x206D</int>       <!-- ACTIVATE ARABIC FORM SHAPING -->
-                       <int>0x206E</int>       <!-- NATIONAL DIGIT SHAPES -->
-                       <int>0x206F</int>       <!-- NOMINAL DIGIT SHAPES -->
-                       <int>0x2800</int>       <!-- BRAILLE PATTERN BLANK -->
-                       <int>0x3000</int>       <!-- IDEOGRAPHIC SPACE -->
-                       <int>0x3164</int>       <!-- HANGUL FILLER -->
-                       <int>0xFEFF</int>       <!-- ZERO WIDTH NO-BREAK SPACE -->
-                       <int>0xFFA0</int>       <!-- HALFWIDTH HANGUL FILLER -->
-                       <int>0xFFF9</int>       <!-- INTERLINEAR ANNOTATION ANCHOR -->
-                       <int>0xFFFA</int>       <!-- INTERLINEAR ANNOTATION SEPARATOR -->
-                       <int>0xFFFB</int>       <!-- INTERLINEAR ANNOTATION TERMINATOR -->
-               </blank>
-<!--
-  Rescan configuration every 30 seconds when FcFontSetList is called
- -->
-               <rescan>
-                       <int>30</int>
-               </rescan>
-       </config>
-
-</fontconfig>
-EOF
diff --git a/install-dylibs.sh b/install-dylibs.sh
deleted file mode 100755 (executable)
index 6b9e530..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/bin/sh
-
-set -ex
-
-: ${OTOOL:=otool}
-: ${CP:=cp}
-: ${INSTALLDIR:=.}
-: ${EXE:=ppc}
-: ${MACLIBDIR:=/sw/lib}
-: ${CAT:=cat}
-
-
-finkgetdeps()
-{
-       otool -L "$1" | grep "$MACLIBDIR" | while read -r LIB STUFF; do
-               [ -z "${LIB##*:}" ] && continue # first line
-               [ -f "$INSTALLDIR/${LIB##*/}" ] && continue
-               cp -vL "$LIB" "$INSTALLDIR"
-               finkgetdeps "$LIB"
-       done
-}
-
-
-finkgetdeps "$INSTALLDIR/radiant.$EXE"
-echo Warning: this only works if only ONE version of gtk-2.0 and pango is installed
-
-getlib()
-{
-       LAST=
-       for LIB in "$@"; do
-               [ -f "$LIB" ] || continue
-               LAST=$LIB
-       done
-       cp -L "$LAST" "$INSTALLDIR"
-       finkgetdeps "$LAST"
-}
-
-getlib "$MACLIBDIR"/gtk-2.0/*/loaders/libpixbufloader-bmp.so "$MACLIBDIR"/gdk-pixbuf-2.0/*/loaders/libpixbufloader-bmp.so
-getlib "$MACLIBDIR"/pango/*/modules/pango-basic-fc.so
-getlib "$MACLIBDIR"/pango/*/modules/pango-basic-x.so
-
-#cp -L "$MACLIBDIR"/../etc/fonts/fonts.conf "$INSTALLDIR"
-#cp -L "$MACLIBDIR"/../etc/fonts/fonts.dtd "$INSTALLDIR"
-#cp -L "$MACLIBDIR"/../etc/gtk-2.0/gdk-pixbuf.loaders "$INSTALLDIR"
-#cp -L "$MACLIBDIR"/../etc/pango/pangorc "$INSTALLDIR"
-
-$CAT > "$INSTALLDIR/../netradiant.sh" <<EOF
-#!/bin/sh
-
-MY_DIRECTORY="\${0%/*}" # cut off the script name
-MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off MacOS
-MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off Contents
-
-export DYLD_LIBRARY_PATH="\$MY_DIRECTORY/Contents/MacOS/install"
-export PANGO_RC_FILE="\$MY_DIRECTORY/Contents/MacOS/install/pangorc"
-export GDK_PIXBUF_MODULE_FILE="\$MY_DIRECTORY/Contents/MacOS/install/gdk-pixbuf.loaders"
-export FONTCONFIG_FILE="\$MY_DIRECTORY/Contents/MacOS/install/fonts.conf"
-
-cd "\$MY_DIRECTORY/Contents/MacOS/install"
-if [ -x /usr/bin/open-x11 ]; then
-       env LC_ALL="en_US.UTF-8" /usr/bin/open-x11 ./radiant.$EXE "$@" &
-else
-       env LC_ALL="en_US.UTF-8" ./radiant.$EXE "$@" &
-fi
-EOF
-
-chmod 755 "$INSTALLDIR/../netradiant.sh"
-
diff --git a/library-bundler b/library-bundler
new file mode 100755 (executable)
index 0000000..54056c4
--- /dev/null
@@ -0,0 +1,528 @@
+#! /usr/bin/env bash
+
+set -e
+
+export LANG='C.UTF-8'
+export LANGUAGE="${LANG}"
+
+_sed () {
+       case "${system_name}" in
+               'macos'|'freebsd')
+                       gsed "${@}"
+                       ;;
+               *)
+                       sed "${@}"
+                       ;;
+       esac
+}
+
+_cp () {
+       case "${system_name}" in
+               'macos'|'freebsd')
+                       gcp -R --preserve=timestamps -H -L "${1}" "${2}"
+                       ;;
+               *)
+                       cp -R --preserve=timestamps -H -L "${1}" "${2}"
+                       ;;
+       esac
+}
+
+Common::noOp () {
+       true
+}
+
+Common::getPath () {
+       local file_path="${1}"
+
+       if command -v cygpath >/dev/null
+       then
+               if [ "${file_path}" = '-' ]
+               then
+                       tr '\n' '\0' \
+                       | xargs -0 -P1 -I{} \
+                               cygpath --unix '{}'
+               else
+                       cygpath --unix "${file_path}"
+               fi
+       else
+               if [ "${file_path}" = '-' ]
+               then
+                       cat
+               else
+                       printf '%s\n' "${file_path}"
+               fi
+       fi \
+       | _sed -e 's|/*$||'
+}
+
+Common::grepLdd () {
+       case "${system_name}" in
+               'macos')
+                       egrep '^\t/'
+                       ;;
+               *)
+                       egrep ' => '
+                       ;;
+       esac
+}
+
+Common::stripLdd () {
+       case "${system_name}" in
+               'macos')
+                       _sed -e 's/^\t\(.*\) (compatibility version .*/\1/'
+                       ;;
+               *)
+                       _sed -e 's/ (0x[0-9a-f]*)$//;s/^.* => //'
+                       ;;
+       esac
+}
+
+Multi::excludeLdd () {
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       # - always bundle built-in libraries
+                       # - always rely on up-to-date x11 and gl libraries, bundling them will break on future distros
+                       # - gtk is not easily bundlable on linux because it looks for harcoded system path to optional
+                       #   shared libraries like image codecs, theme engines, sound notification system, etc.
+                       #   so expect user to install gtk first
+                       # - since we ask user to instal gtk, we can also ask them to install gtkglext,
+                       #   which is likely to pull gtk itself, x11 and gl dependencies
+                       # - old fontconfig does not work correctly if newer fontconfig configuration is installed
+                       # - if gtk and fontconfig is installed, pango and freetype are
+                       local ldd_line
+                       while read ldd_line
+                       do
+                               if echo "${ldd_line}" | egrep '/builtins/'
+                               then
+                                       echo "${ldd_line}"
+                               elif echo "${ldd_line}" \
+                                       | egrep -q '/libc\.|/libstdc\+\+\.|/libdl\.|/libm\.|/libX|/libxcb|/libGL|/libICE\.|/libSM\.|/libpthread\.'
+                               then
+                                       Common::noOp
+                               elif echo "${ldd_line}" \
+                                       | egrep -q '/libatk|/libgdk|/libgtk|/libgio|/libglib|/libgmodule|/libgobject|/libcairo|/libpango|/libfontconfig|/libfreetype'
+                               then
+                                       Common::noOp
+                               # FreeBSD specific
+                               elif echo "${ldd_line}" \
+                                       | egrep -q '/libc++|/libgxxrt'
+                               then
+                                       Common::noOp
+                               else
+                                       echo "${ldd_line}"
+                               fi
+                       done
+                       ;;
+               'windows')
+                       egrep -i '\.dll => [A-Z]:\\msys64\\'
+                       ;;
+               'macos')
+                       egrep -v '^\t/System/|^\t/usr/lib/'
+                       ;;
+       esac
+}
+
+Multi::filterLib () {
+       Common::grepLdd \
+       | Multi::excludeLdd \
+       | Common::stripLdd \
+       | Common::getPath -
+}
+
+Multi::printLdd () {
+       local exe_file="${1}"
+
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       ldd "${exe_file}"
+                       ;;
+               'windows')
+                       ntldd --recursive "${exe_file}"
+                       ;;
+               'macos')
+                       otool -L "${exe_file}"
+       esac
+}
+
+Multi::getGtkThemeName () {
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       echo 'Adwaita'
+                       ;;
+               'windows')
+                       echo 'MS-Windows'
+                       ;;
+               *)
+                       echo 'Raleigh'
+                       ;;
+       esac
+}
+
+Multi::getGtkLibName () {
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       echo 'libgtk-x11-2.0.so.0'
+                       ;;
+               'windows')
+                       echo 'libgtk-win32-2.0-0.dll'
+                       ;;
+               'macos')
+                       echo 'libgtk-quartz-2.0.0.dylib'
+                       ;;
+       esac
+}
+
+Multi::getRootPrefix () {
+       local lib_file="${1}"
+
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       echo "${lib_file}" \
+                       | cut -f2 -d'/'
+                       ;;
+               'windows')
+                       basename "${lib_file}" \
+                       | xargs -n1 -P1 which \
+                       | cut -f2 -d'/'
+                       ;;
+               'macos')
+                       echo 'usr/local'
+       esac
+}
+
+Multi::getLibPrefix () {
+       local lib_file="${1}"
+
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       dirname "${lib_file}" \
+                       | cut -f3- -d'/'
+                       ;;
+               'windows')
+                       echo 'lib'
+                       ;;
+               'macos')
+                       echo 'lib'
+                       ;;
+       esac
+}
+
+Multi::getGtkDeps () {
+       local lib_prefix="${1}"
+       local gtk_theme_name="${2}"
+
+       case "${system_name}" in
+               'linux'|'freebsd'|'windows')
+                       cat <<-EOF
+                       share/themes/${gtk_theme_name}/gtk-2.0
+                       share/icons/hicolor
+                       ${lib_prefix}/gdk-pixbuf-2.0
+                       ${lib_prefix}/gtk-2.0
+                       EOF
+                       ;;
+               'macos')
+                       cat <<-EOF
+                       etc/fonts
+                       share/themes/${gtk_theme_name}/gtk-2.0
+                       share/fontconfig
+                       share/icons/hicolor
+                       share/locale
+                       ${lib_prefix}/gdk-pixbuf-2.0
+                       ${lib_prefix}/gtk-2.0
+                       EOF
+                       ;;
+       esac
+
+       case "${system_name}" in
+               'linux'|'freebsd')
+                       cat <<-EOF
+                       ${lib_prefix}/libatk-bridge-2.0.so.0
+                       ${lib_prefix}/libcanberra-0.30
+                       ${lib_prefix}/libcanberra.so.0
+                       ${lib_prefix}/libcanberra-gtk.so.0
+                       EOF
+                       ;;
+       esac
+}
+
+Multi::rewriteLoadersCache () {
+       local bundle_component_path="${1}"
+       local cache_file
+
+       find "${bundle_component_path}" \
+               -type f \
+               \( \
+               -name 'loaders.cache' \
+               -o -name 'immodules.cache' \
+               \) \
+       | while read cache_file
+       do
+               _sed \
+                       -e 's|^"/[^"]*/lib/|"lib/|;s| "/[^"]*/share/| "share/|;/^# ModulesPath = /d;/^# Created by /d;/^#$/d' \
+                       -i "${cache_file}"
+       done
+}
+
+Multi::bundleGtkDepsFromFile () {
+       local lib_file="${1}"
+       local component_dir
+       local real_component_dir
+       local bundle_component_dir
+
+       lib_basename="$(basename "${lib_file}")"
+
+       gtk_lib_name="$(Multi::getGtkLibName)"
+       if [ "${lib_basename}" = "${gtk_lib_name}" ]
+       then
+               root_prefix="$(Multi::getRootPrefix "${lib_file}")"
+               lib_prefix="$(Multi::getLibPrefix "${lib_file}")"
+               gtk_theme_name="$(Multi::getGtkThemeName)"
+
+               for component_dir in $(Multi::getGtkDeps "${lib_prefix}" "${gtk_theme_name}")
+               do
+                       bundle_component_dir="$(echo "${component_dir}" | _sed -e 's|^'"${lib_prefix}"'|lib|')"
+                       if ! [ -e "${bundle_dir}/${bundle_component_dir}" ]
+                       then
+                               real_component_dir="$(realpath "/${root_prefix}/${component_dir}")"
+
+                               mkdir -p "${bundle_dir}/$(dirname "${bundle_component_dir}")"
+
+                               _cp \
+                                       "${real_component_dir}" \
+                                       "${bundle_dir}/${bundle_component_dir}"
+
+                               Multi::rewriteLoadersCache "${bundle_dir}/${bundle_component_dir}"
+                       fi
+               done
+       fi
+}
+
+Multi::bundleLibFromFile () {
+       local exe_file="${1}"
+       local lib_file
+
+       Multi::printLdd "${exe_file}" \
+       | Multi::filterLib \
+       | while read lib_file
+       do
+               if [ "${lib_file}" = 'not found' ]
+               then
+                       printf 'ERROR: library not found while bundling %s (but link worked)\n' "${exe_file}" >&2
+                       Multi::printLdd "${exe_file}" | grep 'not found'
+                       exit 1
+               fi
+               lib_basename="$(basename "${lib_file}")"
+
+               if [ -f "${lib_dir}/${lib_basename}" ]
+               then
+                       continue
+               fi
+
+               _cp \
+                       "${lib_file}" \
+                       "${lib_dir}/${lib_basename}"
+
+               Multi::bundleGtkDepsFromFile "${lib_file}"
+
+               case "${system_name}" in
+                       'macos')
+                               Multi::bundleLibFromFile "${lib_file}"
+                               ;;
+               esac
+       done
+}
+
+Multi::cleanUp () {
+       # Remove from bundle things that useless to be distributed,
+       # like headers or static libraries, also remove
+       # empty directories.
+       find "${bundle_dir}/lib" \
+               -type f \
+               -name '*.a' \
+               -exec rm -f {} \;
+
+       find "${bundle_dir}/lib" \
+               -type f \
+               -name '*.h' \
+               -exec rm -f {} \;
+
+       find "${bundle_dir}/lib" \
+               -depth \
+               -type d \
+               -empty \
+               -exec rmdir {} \;
+}
+
+Linux::getRpath () {
+       local exe_file="${1}"
+
+       local exe_dir="$(dirname "${exe_file}")"
+       local path_start="$(printf '%s' "${bundle_dir}" | wc -c)"
+       path_start="$((${path_start} + 1))"
+
+       local exe_subdir="$(echo "${exe_dir}" | cut -c "${path_start}-" | _sed -e 's|//*|/|;s|^/||')"
+
+       local rpath_origin='$ORIGIN'
+
+       if [ "${exe_subdir}" = '' ]
+       then
+               printf '%s/lib\n' "${rpath_origin}"
+       else
+               if [ "${exe_subdir}" = 'lib' ]
+               then
+                       printf '%s\n' "${rpath_origin}"
+               else
+                       local num_parent_dir="$(echo "${exe_subdir}" | tr '/' '\n' | wc -l)"
+                       local rpath_subdir
+                       local i=0
+                       while [ "${i}" -lt "${num_parent_dir}" ]
+                       do
+                               rpath_subdir="${rpath_subdir}/.."
+                               i="$((${i} + 1))"
+                       done
+                       printf '%s%s/lib\n' "${rpath_origin}" "${rpath_subdir}"
+               fi
+       fi
+}
+
+Linux::patchExe () {
+       local exe_file="${1}"
+
+       local linux_rpath_string=$"$(Linux::getRpath "${exe_file}")"
+       chmod u+w,go-w "${exe_file}"
+       patchelf --set-rpath "${linux_rpath_string}" "${exe_file}"
+}
+
+Linux::patchLib () {
+       local lib_dir="${1}"
+       local exe_file
+
+       find "${lib_dir}" \
+               -type f \
+               -name '*.so*' \
+       | while read exe_file
+       do
+               Linux::patchExe "${exe_file}"
+               chmod ugo-x "${exe_file}"
+       done
+}
+
+Darwin::patchExe () {
+       local exe_file="${1}"
+
+       Multi::printLdd "${exe_file}" \
+       | Multi::filterLib \
+       | while read lib_file
+       do
+               new_path="$(echo "${lib_file}" | _sed -e 's|^/.*/lib/|@executable_path/lib/|')"
+               id_name="$(echo "${lib_file}" | _sed -e 's|.*/||g')"
+               chmod u+w,go-w "${exe_file}"
+               install_name_tool -change "${lib_file}" "${new_path}" "${exe_file}"
+               install_name_tool -id "${id_name}" "${exe_file}"
+       done
+}
+
+Darwin::patchLib () {
+       local lib_dir="${1}"
+       local exe_file
+
+       find "${lib_dir}" \
+               -type f \
+               \( \
+               -name '*.dylib' \
+               -o -name '*.so' \
+               \) \
+       | while read exe_file
+       do
+               Darwin::patchExe "${exe_file}"
+               chmod ugo-x "${exe_file}"
+       done
+}
+
+Windows::listLibForManifest () {
+       local lib_dir="${1}"
+
+       find "${lib_dir}" \
+               -maxdepth 1 \
+               -type f \
+               -name '*.dll' \
+               -exec basename {} \; \
+       | tr '\n' '\0' \
+       | xargs -0 -P1 -I{} \
+               printf '  <file name="{}"/>\n'
+}
+
+Windows::writeManifest () {
+       local lib_dir="${1}"
+
+       cat > "${manifest_file}" <<-EOF
+       <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+         <assemblyIdentity type="win32" name="lib" version="1.0.0.0"/>
+       $(Windows::listLibForManifest "${lib_dir}")
+       </assembly>
+       EOF
+}
+
+system_name="${1}"; shift
+bundle_dir="${1}"; shift
+
+if ! [ -z "${1}" ]
+then
+       exe_file="${1}"; shift
+fi
+
+bundle_dir="$(Common::getPath "${bundle_dir}")"
+registry_dir="${bundle_dir}/registry"
+lib_dir="${bundle_dir}/lib"
+
+manifest_file="${lib_dir}/lib.manifest"
+
+exe_action='Common::noOp'
+lib_action='Common::noOp'
+
+case "${system_name}" in
+       'register')
+               mkdir -p "${registry_dir}"
+               Common::getPath "${exe_file}" > "${registry_dir}/$(uuidgen)"
+               exit
+               ;;
+       'linux'|'freebsd')
+               exe_action='Linux::patchExe'
+               lib_action='Linux::patchLib'
+               ;;
+       'windows')
+               lib_action='Windows::writeManifest'
+               ;;
+       'macos')
+               exe_action='Darwin::patchExe'
+               lib_action='Darwin::patchLib'
+               ;;
+       *)
+               printf 'ERROR: unsupported system: %s\n' "${system_name}" >&2
+               exit 1
+               ;;
+esac
+
+mkdir -p "${lib_dir}"
+
+if [ -d "${registry_dir}" ]
+then
+       for registry_entry in "${registry_dir}"/*
+       do
+               exe_file="$(cat "${registry_entry}")"
+
+               Multi::bundleLibFromFile "${exe_file}"
+
+               "${exe_action}" "${exe_file}"
+
+               rm "${registry_entry}"
+
+               "${exe_action}" "${exe_file}"
+       done
+
+       rmdir "${registry_dir}"
+fi
+
+"${lib_action}" "${lib_dir}"
+
+Multi::cleanUp
index 633b965f2b1c253fde4858182300040f57c7816f..f0c157f530b4abddf77028280930bf3a6b3cdfdc 100644 (file)
@@ -1,16 +1,21 @@
 add_subdirectory(cmdlib)
 add_subdirectory(container)
+
 if (BUILD_CRUNCH)
     add_subdirectory(crnrgba)
 endif ()
+
 add_subdirectory(ddslib)
 add_subdirectory(debugging)
 add_subdirectory(etclib)
 add_subdirectory(filematch)
 add_subdirectory(generic)
+
 if (BUILD_RADIANT)
     add_subdirectory(gtkutil)
+    add_subdirectory(uilib)
 endif ()
+
 add_subdirectory(l_net)
 add_subdirectory(math)
 add_subdirectory(mathlib)
@@ -24,7 +29,7 @@ add_subdirectory(signal)
 add_subdirectory(splines)
 add_subdirectory(stream)
 add_subdirectory(string)
-add_subdirectory(uilib)
+add_subdirectory(transformpath)
 add_subdirectory(xml)
 
 add_library(libs
index abdc15a6fd3cfd6d4d2da873c2f65d58d0c54713..e901486d0ecc38c6ef709533df57bd5c5e501157 100644 (file)
@@ -44,7 +44,7 @@
 //   if the spawn was fine
 //   TODO TTimo add functionality to track the process until it dies
 
-bool Q_Exec( const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor );
+bool Q_Exec( const char *cmd, const char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor );
 
 // some easy portability crap
 
index 5d25ce82844a50f02b4b9b595c238525f2fab428..b8c48b0112bc541fc5cd06180a59574eb8236afa 100644 (file)
@@ -1,3 +1,3 @@
-add_library(cmdlib
+add_library(cmdlib STATIC
         cmdlib.cpp ../cmdlib.h
         )
index 9bfd24364dc4bff37e09a5354b10f3070cf7d364..25c5d9addeae227c569410633909a04fb700f12f 100644 (file)
@@ -40,7 +40,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
-bool Q_Exec( const char *cmd, char *cmdline, const char *, bool, bool waitfor ){
+bool Q_Exec( const char *cmd, const char *cmdline, const char *, bool, bool waitfor ){
        char fullcmd[2048];
        char *pCmd;
        pid_t pid;
@@ -91,7 +91,7 @@ bool Q_Exec( const char *cmd, char *cmdline, const char *, bool, bool waitfor ){
 #include <windows.h>
 
 // NOTE TTimo windows is VERY nitpicky about the syntax in CreateProcess
-bool Q_Exec( const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor ){
+bool Q_Exec( const char *cmd, const char *cmdline, const char *execdir, bool bCreateConsole, bool waitfor ){
        PROCESS_INFORMATION ProcessInformation;
        STARTUPINFO startupinfo = {0};
        DWORD dwCreationFlags;
@@ -102,14 +102,12 @@ bool Q_Exec( const char *cmd, char *cmdline, const char *execdir, bool bCreateCo
        else{
                dwCreationFlags = DETACHED_PROCESS | NORMAL_PRIORITY_CLASS;
        }
-       const char *pCmd;
-       char *pCmdline;
-       pCmd = cmd;
+       const char *pCmd = cmd;
        if ( pCmd ) {
                while ( *pCmd == ' ' )
                        pCmd++;
        }
-       pCmdline = cmdline;
+       char *pCmdline = strdup(cmdline);
        if ( pCmdline ) {
                while ( *pCmdline == ' ' )
                        pCmdline++;
@@ -130,8 +128,10 @@ bool Q_Exec( const char *cmd, char *cmdline, const char *execdir, bool bCreateCo
                if ( waitfor ) {
                        WaitForSingleObject( ProcessInformation.hProcess, INFINITE );
                }
+               free(pCmdline);
                return true;
        }
+       free(pCmdline);
        return false;
 }
 
index 00bfbb4a6bc14bf96fef5744432409da6ae54dee..028129ba4b5bdaf21f94147a21ee6278ba523fd2 100644 (file)
@@ -1,4 +1,4 @@
-add_library(container
+add_library(container STATIC
         array.cpp array.h
         cache.h
         container.h
index 305202d0c9f00435bdcdab0c0798363abf5a8ef2..fa796e5e6efa7ab7ea325d713101ee72c8f07df7 100644 (file)
@@ -182,7 +182,7 @@ inline ub4 hash(
        const UB1Traits& ub1traits,
        const UB4x1Traits& ub4x1traits
        ){
-       register ub4 a,b,c,len;
+       ub4 a,b,c,len;
 
        /* Set up the internal state */
        len = length;
@@ -203,6 +203,20 @@ inline ub4 hash(
        c += length;
        switch ( len )          /* all the case statements fall through */
        {
+#if defined(__GNUC__) && __GNUC__ < 7
+       case 11: c += ( ( ub4 ) UB1Traits::as_ub1( k[10] ) << 24 ); /* fall through */
+       case 10: c += ( ( ub4 ) UB1Traits::as_ub1( k[9] ) << 16 ); /* fall through */
+       case 9: c += ( ( ub4 ) UB1Traits::as_ub1( k[8] ) << 8 ); /* fall through */
+       /* the first byte of c is reserved for the length */
+       case 8: b += ( ( ub4 ) UB1Traits::as_ub1( k[7] ) << 24 ); /* fall through */
+       case 7: b += ( ( ub4 ) UB1Traits::as_ub1( k[6] ) << 16 ); /* fall through */
+       case 6: b += ( ( ub4 ) UB1Traits::as_ub1( k[5] ) << 8 ); /* fall through */
+       case 5: b += UB1Traits::as_ub1( k[4] );  /* fall through */
+       case 4: a += ( ( ub4 ) UB1Traits::as_ub1( k[3] ) << 24 ); /* fall through */
+       case 3: a += ( ( ub4 ) UB1Traits::as_ub1( k[2] ) << 16 ); /* fall through */
+       case 2: a += ( ( ub4 ) UB1Traits::as_ub1( k[1] ) << 8 ); /* fall through */
+       case 1: a += UB1Traits::as_ub1( k[0] );
+#else
        case 11: c += ( ( ub4 ) UB1Traits::as_ub1( k[10] ) << 24 ); __attribute((fallthrough));
        case 10: c += ( ( ub4 ) UB1Traits::as_ub1( k[9] ) << 16 ); __attribute((fallthrough));
        case 9: c += ( ( ub4 ) UB1Traits::as_ub1( k[8] ) << 8 ); __attribute((fallthrough));
@@ -215,6 +229,7 @@ inline ub4 hash(
        case 3: a += ( ( ub4 ) UB1Traits::as_ub1( k[2] ) << 16 ); __attribute((fallthrough));
        case 2: a += ( ( ub4 ) UB1Traits::as_ub1( k[1] ) << 8 ); __attribute((fallthrough));
        case 1: a += UB1Traits::as_ub1( k[0] );
+#endif
                /* case 0: nothing left to add */
        }
        mix( a,b,c );
@@ -240,7 +255,7 @@ inline ub4 hash2(
        ub4 initval, /* the previous hash, or an arbitrary value */
        const UB4Traits& ub4traits
        ){
-       register ub4 a,b,c,len;
+       ub4 a,b,c,len;
 
        /* Set up the internal state */
        len = length;
index 6e8463dc6668f0a326a4c2fb76b5dc847d2e31e3..a5ec18e3ff7b24be50eea30efddb756b3023c8d1 100644 (file)
@@ -1,4 +1,4 @@
-add_library(crnrgba
+add_library(crnrgba STATIC
         crn_rgba.h
         crn_rgba.cpp
         ../crunch/inc/crn_decomp.h
index 8dec126fe1423734ebd7a59ac2653624ee4a7bbf..012b95fb822121e96784ad18e4929c01003d699a 100644 (file)
@@ -25,7 +25,7 @@
 #include <string.h>
 
 #include <memory>
-
+#include <algorithm>
 
 #include "ddslib.h"
 #include "../crunch/inc/crn_decomp.h"
index 85bab3d798a54abe32a22d5275e625ec06df6917..9c25f6c4b4827bd6f2b70981cd68ddbc31ecdc6c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 85bab3d798a54abe32a22d5275e625ec06df6917
+Subproject commit 9c25f6c4b4827bd6f2b70981cd68ddbc31ecdc6c
index 4961f6ef6b17cca7817bf9f94c12d4edd7c3041f..3f8f7426532cea87542390f9d714e1398ff79875 100644 (file)
@@ -181,7 +181,7 @@ typedef struct ddsBuffer_s
        };
        unsigned int alphaBitDepth;
        unsigned int reserved;
-       void                *surface;
+       unsigned int surface; // void *surface;
        union
        {
                ddsColorKey_t ckDestOverlay;
index d4de1a7c80b859004577c85b28659b4cdc518a8c..a45ccc7f232151fab0acac7cd96c5fb0d8535e66 100644 (file)
@@ -1,3 +1,3 @@
-add_library(ddslib
+add_library(ddslib STATIC
         ddslib.c ../ddslib.h
         )
index e5880de39e33224d5ecca16d834b214e5c873881..0b8f90d83bbfa7745ff8aca17f416362cbf290d7 100644 (file)
@@ -1,3 +1,3 @@
-add_library(debugging
+add_library(debugging STATIC
         debugging.cpp debugging.h
         )
index 2a92fcdb738fcdd2fb14cf5a5027b5d9663c6c8e..15574450f8786980962336d44768976ce6fedabc 100644 (file)
@@ -38,48 +38,50 @@ typedef Vector3 Colour3;
 
 class ListAttributeType
 {
-using ListItem = std::pair<CopiedString, CopiedString>;
-using ListItems = std::vector<ListItem>;
-ListItems m_items;
+       using ListItem = std::pair<CopiedString, CopiedString>;
+       using ListItems = std::vector<ListItem>;
+       ListItems m_items;
 public:
 
-typedef ListItems::const_iterator const_iterator;
-const_iterator begin() const {
-       return m_items.begin();
-}
-const_iterator end() const {
-       return m_items.end();
-}
+       typedef ListItems::const_iterator const_iterator;
+       const_iterator begin() const {
+               return m_items.begin();
+       }
+       const_iterator end() const {
+               return m_items.end();
+       }
 
-const ListItem& operator[]( std::size_t i ) const {
-       return m_items[i];
-}
-const_iterator findValue( const char* value ) const {
-       for ( ListItems::const_iterator i = m_items.begin(); i != m_items.end(); ++i )
-       {
-               if ( string_equal( value, ( *i ).second.c_str() ) ) {
-                       return i;
+       const ListItem& operator[]( std::size_t i ) const {
+               return m_items[i];
+       }
+       const_iterator findValue( const char* value ) const {
+               for ( ListItems::const_iterator i = m_items.begin(); i != m_items.end(); ++i )
+               {
+                       if ( string_equal( value, ( *i ).second.c_str() ) ) {
+                               return i;
+                       }
                }
+               return m_items.end();
        }
-       return m_items.end();
-}
 
-void push_back( const char* name, const char* value ){
-       m_items.push_back( ListItems::value_type( name, value ) );
-}
+       void push_back( const char* name, const char* value ){
+               m_items.push_back( ListItems::value_type( name, value ) );
+       }
 };
 
 class EntityClassAttribute
 {
-public:
-CopiedString m_type;
-CopiedString m_name;
-CopiedString m_value;
-CopiedString m_description;
-EntityClassAttribute(){
-}
-EntityClassAttribute( const char* type, const char* name, const char* value = "", const char* description = "" ) : m_type( type ), m_name( name ), m_value( value ), m_description( description ){
-}
+       public:
+               CopiedString m_type;
+               CopiedString m_name;
+               CopiedString m_value;
+               CopiedString m_description;
+               EntityClassAttribute(){
+               }
+               EntityClassAttribute(const EntityClassAttribute& attr) = default;
+               EntityClassAttribute( const char* type, const char* name, const char* value = "", const char* description = "" ) : m_type( type ), m_name( name ), m_value( value ), m_description( description ){
+               }
+               EntityClassAttribute& operator=(const EntityClassAttribute& attr) = default;
 };
 
 typedef std::pair<CopiedString, EntityClassAttribute> EntityClassAttributePair;
@@ -103,44 +105,44 @@ inline const char* EntityClassAttributePair_getDescription( const EntityClassAtt
 class EntityClass
 {
 public:
-CopiedString m_name;
-StringList m_parent;
-bool fixedsize;
-bool unknown;               // wasn't found in source
-Vector3 mins;
-Vector3 maxs;
+       CopiedString m_name;
+       StringList m_parent;
+       bool fixedsize;
+       bool unknown;               // wasn't found in source
+       Vector3 mins;
+       Vector3 maxs;
 
-Colour3 color;
-Shader* m_state_fill;
-Shader* m_state_wire;
-Shader* m_state_blend;
+       Colour3 color;
+       Shader* m_state_fill;
+       Shader* m_state_wire;
+       Shader* m_state_blend;
 
-CopiedString m_comments;
-char flagnames[MAX_FLAGS][32];
+       CopiedString m_comments;
+       char flagnames[MAX_FLAGS][32];
 
-CopiedString m_modelpath;
-CopiedString m_skin;
+       CopiedString m_modelpath;
+       CopiedString m_skin;
 
-void ( *free )( EntityClass* );
+       void ( *free )( EntityClass* );
 
-EntityClassAttributes m_attributes;
+       EntityClassAttributes m_attributes;
 
-bool inheritanceResolved;
-bool sizeSpecified;
-bool colorSpecified;
+       bool inheritanceResolved;
+       bool sizeSpecified;
+       bool colorSpecified;
 
-const char* name() const {
-       return m_name.c_str();
-}
-const char* comments() const {
-       return m_comments.c_str();
-}
-const char* modelpath() const {
-       return m_modelpath.c_str();
-}
-const char* skin() const {
-       return m_skin.c_str();
-}
+       const char* name() const {
+               return m_name.c_str();
+       }
+       const char* comments() const {
+               return m_comments.c_str();
+       }
+       const char* modelpath() const {
+               return m_modelpath.c_str();
+       }
+       const char* skin() const {
+               return m_skin.c_str();
+       }
 };
 
 inline const char* EntityClass_valueForKey( const EntityClass& entityClass, const char* key ){
index 83f35f02ea959b758f4f9afbfa0cc587aee44fa2..326f2c7c6c9939f273ef160531e5117f1046fd96 100644 (file)
@@ -293,80 +293,80 @@ void render( RenderStateFlags state ) const {
 /// - Provides undo support through the global undo system.
 class KeyValue : public EntityKeyValue
 {
-typedef UnsortedSet<KeyObserver> KeyObservers;
-
-std::size_t m_refcount;
-KeyObservers m_observers;
-CopiedString m_string;
-const char* m_empty;
-ObservedUndoableObject<CopiedString> m_undo;
-static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
-public:
+       typedef UnsortedSet<KeyObserver> KeyObservers;
 
-KeyValue( const char* string, const char* empty )
-       : m_refcount( 0 ), m_string( string ), m_empty( empty ), m_undo( m_string, UndoImportCaller( *this ) ){
-       notify();
-}
-~KeyValue(){
-       ASSERT_MESSAGE( m_observers.empty(), "KeyValue::~KeyValue: observers still attached" );
-}
+       std::size_t m_refcount;
+       KeyObservers m_observers;
+       CopiedString m_string;
+       const char* m_empty;
+       ObservedUndoableObject<CopiedString> m_undo;
+       static EntityCreator::KeyValueChangedFunc m_entityKeyValueChanged;
 
-static void setKeyValueChangedFunc( EntityCreator::KeyValueChangedFunc func ){
-       m_entityKeyValueChanged = func;
-}
+public:
+       KeyValue( const char* string, const char* empty )
+               : m_refcount( 0 ), m_string( string ), m_empty( empty ), m_undo( m_string, UndoImportCaller( *this ) ){
+               notify();
+       }
+       ~KeyValue(){
+               ASSERT_MESSAGE( m_observers.empty(), "KeyValue::~KeyValue: observers still attached" );
+       }
 
-void IncRef(){
-       ++m_refcount;
-}
-void DecRef(){
-       if ( --m_refcount == 0 ) {
-               delete this;
+       static void setKeyValueChangedFunc( EntityCreator::KeyValueChangedFunc func ){
+               m_entityKeyValueChanged = func;
        }
-}
 
-void instanceAttach( MapFile* map ){
-       m_undo.instanceAttach( map );
-}
-void instanceDetach( MapFile* map ){
-       m_undo.instanceDetach( map );
-}
+       void IncRef(){
+               ++m_refcount;
+       }
+       void DecRef(){
+               if ( --m_refcount == 0 ) {
+                       delete this;
+               }
+       }
 
-void attach( const KeyObserver& observer ){
-       ( *m_observers.insert ( observer ) )( c_str() );
-}
-void detach( const KeyObserver& observer ){
-       observer( m_empty );
-       m_observers.erase( observer );
-}
-const char* c_str() const {
-       if ( string_empty( m_string.c_str() ) ) {
-               return m_empty;
+       void instanceAttach( MapFile* map ){
+               m_undo.instanceAttach( map );
        }
-       return m_string.c_str();
-}
-void assign( const char* other ){
-       if ( !string_equal( m_string.c_str(), other ) ) {
-               m_undo.save();
-               m_string = other;
-               notify();
+       void instanceDetach( MapFile* map ){
+               m_undo.instanceDetach( map );
        }
-}
 
-void notify(){
-       m_entityKeyValueChanged();
-       KeyObservers::reverse_iterator i = m_observers.rbegin();
-       while ( i != m_observers.rend() )
-       {
-               ( *i++ )( c_str() );
+       void attach( const KeyObserver& observer ){
+               ( *m_observers.insert ( observer ) )( c_str() );
+       }
+       void detach( const KeyObserver& observer ){
+               observer( m_empty );
+               m_observers.erase( observer );
+       }
+       const char* c_str() const {
+               if ( string_empty( m_string.c_str() ) ) {
+                       return m_empty;
+               }
+               return m_string.c_str();
+       }
+       void assign( const char* other ){
+               if ( !string_equal( m_string.c_str(), other ) ) {
+                       m_undo.save();
+                       m_string = other;
+                       notify();
+               }
        }
-}
 
-void importState( const CopiedString& string ){
-       m_string = string;
+       void notify(){
+               m_entityKeyValueChanged();
+               KeyObservers::reverse_iterator i = m_observers.rbegin();
+               while ( i != m_observers.rend() )
+               {
+                       ( *i++ )( c_str() );
+               }
+       }
 
-       notify();
-}
-typedef MemberCaller<KeyValue, void(const CopiedString&), &KeyValue::importState> UndoImportCaller;
+       void importState( const CopiedString& string ){
+               m_string = string;
+
+               notify();
+       }
+       typedef MemberCaller<KeyValue, void(const CopiedString&), &KeyValue::importState> UndoImportCaller;
 };
 
 /// \brief An unsorted list of key/value pairs.
@@ -419,18 +419,6 @@ private:
                }
                m_observerMutex = false;
        }
-       void forEachKeyValue_notifyInsert(){
-               for ( KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i )
-               {
-                       notifyInsert( ( *i ).first.c_str(), *( *i ).second );
-               }
-       }
-       void forEachKeyValue_notifyErase(){
-               for ( KeyValues::const_iterator i = m_keyValues.begin(); i != m_keyValues.end(); ++i )
-               {
-                       notifyErase( ( *i ).first.c_str(), *( *i ).second );
-               }
-       }
 
        void insert( const char* key, const KeyValuePtr& keyValue ){
                KeyValues::iterator i = m_keyValues.insert( KeyValues::value_type( key, keyValue ) );
index 8d8fb23a361f1d867242b95e5f0ad2c0b1f19ef8..68a12302d342488201c81e9e368790245e31a5ac 100644 (file)
@@ -1,3 +1,3 @@
-add_library(etclib
+add_library(etclib STATIC
         ../etclib.c ../etclib.h
         )
index c7d8a9edb00acc70731c0bfab540c1d2b3713ee0..fede3eb59d3c713758893ea7afc64f26cd76b130 100644 (file)
@@ -1,3 +1,3 @@
-add_library(filematch
+add_library(filematch STATIC
         ../filematch.c ../filematch.h
         )
index 2baf297ed803f9fa1d3dd4085cb7169b24444872..ee9458143685eae37a515f3a577853819ac04447 100644 (file)
 #if !defined( INCLUDED_FS_PATH_H )
 #define INCLUDED_FS_PATH_H
 
-#include "stream/stringstream.h"
-
 /// \brief A unix-style path string which can be modified at runtime.
 ///
 /// - Maintains a path ending in a path-separator.
 /// - Provides a limited STL-style interface to push and pop file or directory names at the end of the path.
 class UnixPath
 {
-StringBuffer m_string;
+std::string m_string;
 
-void check_separator(){
+void ensure_separator(){
        if ( !empty() && m_string.back() != '/' ) {
                m_string.push_back( '/' );
        }
@@ -42,7 +40,7 @@ public:
 /// \brief Constructs with the directory \p root.
 UnixPath( const char* root )
        : m_string( root ){
-       check_separator();
+       ensure_separator();
 }
 
 bool empty() const {
@@ -55,17 +53,12 @@ const char* c_str() const {
 
 /// \brief Appends the directory \p name.
 void push( const char* name ){
-       m_string.push_string( name );
-       check_separator();
-}
-/// \brief Appends the directory [\p first, \p last).
-void push( const char* first, const char* last ){
-       m_string.push_range( first, last );
-       check_separator();
+       m_string += name;
+       ensure_separator();
 }
 /// \brief Appends the filename \p name.
 void push_filename( const char* name ){
-       m_string.push_string( name );
+       m_string += name;
 }
 /// \brief Removes the last directory or filename appended.
 void pop(){
index d89f57438b40966d7ce6a41003a3b4a27196f30a..e05637efb6e8ea6c69b9d37ac7cf664ec18bfc9c 100644 (file)
@@ -1,4 +1,4 @@
-add_library(generic
+add_library(generic STATIC
         arrayrange.h
         bitfield.h
         callback.cpp callback.h
index 577dd9d958bd337082f9c2479c5c1803e664c1a3..7479826cbeb8335c6cd68846bdf3142075fe576e 100644 (file)
@@ -101,7 +101,7 @@ namespace detail {
 
        // pointer
 
-       template<class T>
+       template<class T, class U = typename std::enable_if<!std::is_function<T>::value>::type>
        inline const void *convertToOpaque(const T *t) {
                return t;
        }
@@ -113,7 +113,7 @@ namespace detail {
                }
        };
 
-       template<class T>
+       template<class T, class U = typename std::enable_if<!std::is_function<T>::value>::type>
        inline void *convertToOpaque(T *t) {
                return t;
        }
index 146dd788b1c5d24209b3f89836f92bc21ae11636..7f6b30483be2374a37453fe653208ae0d3ac038a 100644 (file)
@@ -49,7 +49,6 @@
 #define GDEF_OS_LINUX 0
 #endif
 
-
 #define GDEF_OS_BSD 0
 
 #if defined(__FreeBSD__)
 #define GDEF_OS_BSD_DRAGONFLY 0
 #endif
 
+#if defined(__osf) || defined(__osf__) || defined(__OSF__)
+#define GDEF_OS_OSF1 1
+#else
+#define GDEF_OS_OSF1 0
+#endif
+
+#if defined(_MIPS_ISA)
+#define GDEF_OS_IRIX 1
+#else
+#define GDEF_OS_IRIX 0
+#endif
+
+#if defined(NeXT)
+#define GDEF_OS_NEXT 1
+#else
+#define GDEF_OS_NEXT 0
+#endif
+
+#if GDEF_OS_LINUX || GDEF_OS_BSD
+#define GDEF_OS_XDG 1
+#else
+#define GDEF_OS_XDG 0
+#endif
+
+// EXECUTABLE EXTENSION
+
+#if GDEF_OS_WINDOWS
+#define GDEF_OS_EXE_EXT ".exe"
+#else
+#define GDEF_OS_EXE_EXT ""
+#endif
+
 // COMPILER
 
 #if defined(_MSC_VER)
 #endif
 #endif
 
-#endif
+#endif // !INCLUDED_LIBS_GLOBALDEFS
index b62098c107940d18c233c6470ecb52a81d640eb7..80eca88c62457f699f813b1d7cce4f00b93a0366 100644 (file)
@@ -1,4 +1,4 @@
-add_library(gtkutil
+add_library(gtkutil STATIC
         accelerator.cpp accelerator.h
         button.cpp button.h
         clipboard.cpp clipboard.h
index 58d68c95e1604d210f10ffcb9b47426f41ae408a..b2e1e53e95de0f3ad9027d31018812fd5afa3b6a 100644 (file)
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
 
-#if 0
+// Note: NetRadiantCustom disables them but we still make use of them.
+#if 1
+/* Note: here is an alternative implementation,
+it may be useful to try it on platforms were
+       gdk_cursor_new(GDK_BLANK_CURSOR)
+does not work:
+
+GdkCursor* create_blank_cursor(){
+       GdkPixmap *pixmap;
+       GdkBitmap *mask;
+       char buffer [( 32 * 32 ) / 8];
+       memset( buffer, 0, ( 32 * 32 ) / 8 );
+       GdkColor white = {0, 0xffff, 0xffff, 0xffff};
+       GdkColor black = {0, 0x0000, 0x0000, 0x0000};
+       pixmap = gdk_bitmap_create_from_data( 0, buffer, 32, 32 );
+       mask   = gdk_bitmap_create_from_data( 0, buffer, 32, 32 );
+       GdkCursor *cursor = gdk_cursor_new_from_pixmap( pixmap, mask, &white, &black, 1, 1 );
+       gdk_drawable_unref( pixmap );
+       gdk_drawable_unref( mask );
+
+       return cursor;
+}
+*/
 GdkCursor* create_blank_cursor(){
        return gdk_cursor_new(GDK_BLANK_CURSOR);
 }
 
-void blank_cursor( ui::Widget widget ){
-       GdkCursor* cursor = create_blank_cursor();
+void set_cursor( ui::Widget widget, GdkCursorType cursor_type ){
+       GdkCursor* cursor = gdk_cursor_new( cursor_type );
        gdk_window_set_cursor( gtk_widget_get_window(widget), cursor );
        gdk_cursor_unref( cursor );
 }
 
+void blank_cursor( ui::Widget widget ){
+       set_cursor( widget, GDK_BLANK_CURSOR );
+}
+
 void default_cursor( ui::Widget widget ){
-       gdk_window_set_cursor( gtk_widget_get_window(widget), 0 );
+       gdk_window_set_cursor( gtk_widget_get_window( widget ), NULL );
 }
 #endif
 
-
-void Sys_GetCursorPos( ui::Window window, int *x, int *y ){
-       gdk_display_get_pointer( gdk_display_get_default(), 0, x, y, 0 );
+void Sys_GetCursorPos( ui::Widget widget, int *x, int *y ){
+       GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( widget ) );
+       // No need to store the screen, it will be recovered from widget again.
+       gdk_display_get_pointer( display, NULL, x, y, NULL );
 }
 
-void Sys_SetCursorPos( ui::Window window, int x, int y ){
-       GdkScreen *screen;
-       gdk_display_get_pointer( gdk_display_get_default(), &screen, 0, 0, 0 );
-       gdk_display_warp_pointer( gdk_display_get_default(), screen, x, y );
+void Sys_SetCursorPos( ui::Widget widget, int x, int y ){
+       GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( widget ) );
+       GdkScreen *screen = gtk_widget_get_screen( GTK_WIDGET( widget ) );
+       gdk_display_warp_pointer( display, screen, x, y );
 }
 
 gboolean DeferredMotion::gtk_motion(ui::Widget widget, GdkEventMotion *event, DeferredMotion *self)
@@ -60,30 +87,122 @@ gboolean DeferredMotion::gtk_motion(ui::Widget widget, GdkEventMotion *event, De
     return FALSE;
 }
 
-gboolean FreezePointer::motion_delta(ui::Window widget, GdkEventMotion *event, FreezePointer *self)
+gboolean FreezePointer::motion_delta(ui::Widget widget, GdkEventMotion *event, FreezePointer *self)
 {
+       /* FIXME: The pointer can be lost outside of the XY Window
+       or the Camera Window, see the comment in freeze_pointer function */
        int current_x, current_y;
        Sys_GetCursorPos( widget, &current_x, &current_y );
        int dx = current_x - self->last_x;
        int dy = current_y - self->last_y;
+#if 0 // NetRadiantCustom
        int ddx = current_x - self->center_x;
        int ddy = current_y - self->center_y;
+#else
+       int ddx = current_x - self->recorded_x;
+       int ddy = current_y - self->recorded_y;
+#endif
        self->last_x = current_x;
        self->last_y = current_y;
        if ( dx != 0 || dy != 0 ) {
                //globalOutputStream() << "motion x: " << dx << ", y: " << dy << "\n";
+#if defined(WORKAROUND_MACOS_GTK2_LAGGYPOINTER)
+               ui::Dimensions dimensions = widget.dimensions();
+               int window_x, window_y;
+               int translated_x, translated_y;
+
+               gdk_window_get_origin( gtk_widget_get_window( widget ), &window_x, &window_y);
+
+               translated_x = current_x - ( window_x );
+               translated_y = current_y - ( window_y );
+
+#if 0
+               int widget_x, widget_y;
+               gtk_widget_translate_coordinates( GTK_WIDGET( widget ), gtk_widget_get_toplevel( GTK_WIDGET( widget ) ), 0, 0, &widget_x, &widget_y);
+
+               globalOutputStream()
+                       << "window_x: " << window_x
+                       << ", window_y: " << window_y
+                       << ", widget_x: " << widget_x
+                       << ", widget_y: " << widget_y
+                       << ", current x: " << current_x
+                       << ", current_y: " << current_y
+                       << ", translated x: " << translated_x
+                       << ", translated_y: " << translated_y
+                       << ", width: " << dimensions.width
+                       << ", height: " << dimensions.height
+                       << "\n";
+#endif
+
+               if ( translated_x < 32 || translated_x > dimensions.width - 32
+                       || translated_y < 32 || translated_y > dimensions.height - 32 ) {
+#if 0
+                       // Reposition the pointer to the widget center.
+                       int reposition_x = window_x + dimensions.width / 2;
+                       int reposition_y = window_y + dimensions.height / 2;
+#else
+                       // Move the pointer to the opposite side of the XY Window
+                       // to maximize the distance that can be moved again.
+                       int reposition_x = current_x;
+                       int reposition_y = current_y;
+
+                       if ( translated_x < 32 ) {
+                               reposition_x = window_x + dimensions.width - 32;
+                       }
+                       else if ( translated_x > dimensions.width - 32 ) {
+                               reposition_x = window_x + 32;
+                       }
+
+                       if ( translated_y < 32 ) {
+                               reposition_y = window_y + dimensions.height - 32;
+                       }
+                       else if ( translated_y > dimensions.height - 32 ) {
+                               reposition_y = window_y + 32;
+                       }
+#endif
+
+                       Sys_SetCursorPos( widget, reposition_x, reposition_y );
+                       self->last_x = reposition_x;
+                       self->last_y = reposition_y;
+               }
+#else
                if (ddx < -32 || ddx > 32 || ddy < -32 || ddy > 32) {
+#if 0 // NetRadiantCustom
                        Sys_SetCursorPos( widget, self->center_x, self->center_y );
                        self->last_x = self->center_x;
                        self->last_y = self->center_y;
+#else
+                       Sys_SetCursorPos( widget, self->recorded_x, self->recorded_y );
+                       self->last_x = self->recorded_x;
+                       self->last_y = self->recorded_y;
+#endif
                }
+#endif
                self->m_function( dx, dy, event->state, self->m_data );
        }
        return FALSE;
 }
 
-void FreezePointer::freeze_pointer(ui::Window window, ui::Widget widget, FreezePointer::MotionDeltaFunction function, void *data)
+/* NetRadiantCustom did this instead:
+void FreezePointer::freeze_pointer(ui::Window window, ui::Widget widget, FreezePointer::MotionDeltaFunction function, void *data) */
+void FreezePointer::freeze_pointer(ui::Widget widget, FreezePointer::MotionDeltaFunction function, void *data)
 {
+       /* FIXME: This bug can happen if the pointer goes outside of the
+       XY Window while the right mouse button is not released,
+       the XY Window loses focus and can't read the right mouse button
+       release event and then cannot unfreeze the pointer, meaning the
+       user can attempt to freeze the pointer in another XY window.
+
+       This can happen with touch screen, especially those used to drive
+       virtual machine pointers, the cursor can be teleported outside of
+       the XY Window while maintaining pressure on the right mouse button.
+       This can also happen when the render is slow.
+
+       The bug also occurs with the Camera Window.
+
+       FIXME: It's would be possible to tell the user to save the map
+       at assert time before crashing because this bug does not corrupt
+       map saving. */
        ASSERT_MESSAGE( m_function == 0, "can't freeze pointer" );
 
        const GdkEventMask mask = static_cast<GdkEventMask>( GDK_POINTER_MOTION_MASK
@@ -96,48 +215,80 @@ void FreezePointer::freeze_pointer(ui::Window window, ui::Widget widget, FreezeP
                                                                                                                 | GDK_BUTTON_RELEASE_MASK
                                                                                                                 | GDK_VISIBILITY_NOTIFY_MASK );
 
+#if defined(WORKAROUND_MACOS_GTK2_LAGGYPOINTER)
+       /* Keep the pointer visible during the move operation.
+       Because of a bug, it remains visible even if we give
+       the order to hide it anyway.
+       Other parts of the code assume the pointer is visible,
+       so make sure it is consistently visible accross
+       third-party updates that may fix the mouse pointer
+       visibility issue. */
+#else
+#if 0 // NetRadiantCustom
        //GdkCursor* cursor = create_blank_cursor();
        GdkCursor* cursor = gdk_cursor_new( GDK_BLANK_CURSOR );
        //GdkGrabStatus status =
        /*      fixes cursor runaways during srsly quick drags in camera
        drags with pressed buttons have no problem at all w/o this      */
-       gdk_pointer_grab( gtk_widget_get_window(window), TRUE, mask, 0, cursor, GDK_CURRENT_TIME );
+       gdk_pointer_grab( gtk_widget_get_window( widget ), TRUE, mask, 0, cursor, GDK_CURRENT_TIME );
        //gdk_window_set_cursor ( GTK_WIDGET( window )->window, cursor );
        /*      is needed to fix activating neighbour widgets, that happens, if using upper one */
        gtk_grab_add( widget );
        weedjet = widget;
-
+#else
+       GdkCursor* cursor = create_blank_cursor();
+       //GdkGrabStatus status =
+       gdk_pointer_grab( gtk_widget_get_window( widget ), TRUE, mask, 0, cursor, GDK_CURRENT_TIME );
        gdk_cursor_unref( cursor );
+#endif
+#endif
 
-       Sys_GetCursorPos( window, &recorded_x, &recorded_y );
+       Sys_GetCursorPos( widget, &recorded_x, &recorded_y );
 
+#if 0 // NetRadiantCustom
        /*      using center for tracking for max safety        */
        gdk_window_get_origin( GTK_WIDGET( widget )->window, &center_x, &center_y );
        auto allocation = widget.dimensions();
        center_y += allocation.height / 2;
        center_x += allocation.width / 2;
 
-       Sys_SetCursorPos( window, center_x, center_y );
+       Sys_SetCursorPos( widget, center_x, center_y );
 
        last_x = center_x;
        last_y = center_y;
+#else
+       last_x = recorded_x;
+       last_y = recorded_y;
+#endif
 
        m_function = function;
        m_data = data;
 
-       handle_motion = window.connect( "motion_notify_event", G_CALLBACK( motion_delta ), this );
+       handle_motion = widget.connect( "motion_notify_event", G_CALLBACK( motion_delta ), this );
 }
 
-void FreezePointer::unfreeze_pointer(ui::Window window)
+void FreezePointer::unfreeze_pointer(ui::Widget widget)
 {
-       g_signal_handler_disconnect( G_OBJECT( window ), handle_motion );
+       g_signal_handler_disconnect( G_OBJECT( widget ), handle_motion );
 
        m_function = 0;
        m_data = 0;
 
+#if defined(WORKAROUND_MACOS_GTK2_LAGGYPOINTER)
+       /* The pointer was visible during all the move operation,
+       so, keep the current position. */
+#else
+       // NetRadiantCustom still uses window instead of widget.
+#if 0 // NetRadiantCustom
        Sys_SetCursorPos( window, recorded_x, recorded_y );
+#else
+       Sys_SetCursorPos( widget, recorded_x, recorded_y );
+#endif
+#endif
 
 //     gdk_window_set_cursor( GTK_WIDGET( window )->window, 0 );
        gdk_pointer_ungrab( GDK_CURRENT_TIME );
+#if 0 // NetRadiantCustom
        gtk_grab_remove( weedjet );
+#endif
 }
index 81767d2e591900fa4b258c3b0d473c363c5ca022..f7a66a37d3b193f99e913229f39973a9d2c0da3a 100644 (file)
@@ -22,6 +22,7 @@
 #if !defined( INCLUDED_GTKUTIL_CURSOR_H )
 #define INCLUDED_GTKUTIL_CURSOR_H
 
+#include <gdk/gdk.h>
 #include <uilib/uilib.h>
 
 #include "debugging/debugging.h"
 typedef struct _GdkCursor GdkCursor;
 typedef struct _GdkEventMotion GdkEventMotion;
 
-#if 0
+// NetRadiantCustom disables them but we still make use of them.
+#if 1
 GdkCursor* create_blank_cursor();
+void set_cursor( ui::Widget widget, GdkCursorType cursor_type );
 void blank_cursor( ui::Widget widget );
 void default_cursor( ui::Widget widget );
 #endif
-void Sys_GetCursorPos( ui::Window window, int *x, int *y );
-void Sys_SetCursorPos( ui::Window window, int x, int y );
-
-
+void Sys_GetCursorPos( ui::Widget widget, int *x, int *y );
+void Sys_SetCursorPos( ui::Widget widget, int x, int y );
 
 class DeferredMotion
 {
@@ -117,11 +118,17 @@ void* m_data;
 public:
 FreezePointer() : handle_motion( 0 ), m_function( 0 ), m_data( 0 ){
 }
-static gboolean motion_delta( ui::Window widget, GdkEventMotion *event, FreezePointer* self );
+/* NetRadiantCustom does this instead:
+static gboolean motion_delta( ui::Window widget, GdkEventMotion *event, FreezePointer* self ); */
+static gboolean motion_delta( ui::Widget widget, GdkEventMotion *event, FreezePointer* self );
 
-void freeze_pointer( ui::Window window, ui::Widget widget, MotionDeltaFunction function, void* data );
+/* NetRadiantCustom does this instead:
+void freeze_pointer( ui::Window window, ui::Widget widget, MotionDeltaFunction function, void* data ); */
+void freeze_pointer( ui::Widget widget, MotionDeltaFunction function, void* data );
 
-void unfreeze_pointer( ui::Window window );
+/* NetRadiantCustom does this instead:
+void unfreeze_pointer( ui::Window window ); */
+void unfreeze_pointer( ui::Widget widget );
 };
 
 #endif
index aa8aad47d0a873046151804c55d918f01c5ee973..dc4ef7af6bb7cfa4791eb7ebea30add58b3d6253 100644 (file)
@@ -86,8 +86,9 @@ gboolean modal_dialog_delete( ui::Widget widget, GdkEvent* event, ModalDialog* d
 }
 
 EMessageBoxReturn modal_dialog_show( ui::Window window, ModalDialog& dialog ){
-       gtk_grab_add( window  );
        window.show();
+       g_assert( GTK_IS_WINDOW(window) );
+       gtk_grab_add( GTK_WIDGET(window) );
 
        dialog.loop = true;
        while ( dialog.loop )
@@ -171,6 +172,7 @@ ui::Window create_simple_modal_dialog_window( const char* title, ModalDialog& di
 
        auto button = create_dialog_button( "OK", G_CALLBACK( dialog_button_ok ), &dialog );
        alignment.add(button);
+       gtk_widget_grab_focus (button);
 
        return window;
 }
index f375e53a91e2cef067eb20ed828b51f640d6f1fc..abfc225dcc4b05136bf91fff90ec924d52ccffe4 100644 (file)
@@ -164,25 +164,23 @@ const char* file_dialog_show( ui::Window parent, bool open, const char* title, c
        gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT );
 
        // we expect an actual path below, if the path is 0 we might crash
-       if ( path != 0 && !string_empty( path ) ) {
+       if ( path != nullptr && !string_empty( path ) ) {
                ASSERT_MESSAGE( path_is_absolute( path ), "file_dialog_show: path not absolute: " << makeQuoted( path ) );
 
-               Array<char> new_path( strlen( path ) + 1 );
+               std::string new_path( path );
 
-               // copy path, replacing dir separators as appropriate
-               Array<char>::iterator w = new_path.begin();
-               for ( const char* r = path; *r != '\0'; ++r )
-               {
-                       *w++ = ( *r == '/' ) ? G_DIR_SEPARATOR : *r;
+               // replacing dir separators as appropriate
+               for ( char &c : new_path ) {
+                       if ( c == '/' ) {
+                              c = G_DIR_SEPARATOR;
+                       }
                }
                // remove separator from end of path if required
-               if ( *( w - 1 ) == G_DIR_SEPARATOR ) {
-                       --w;
+               if ( new_path.back() == G_DIR_SEPARATOR ) {
+                       new_path.pop_back();
                }
-               // terminate string
-               *w = '\0';
 
-               gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( dialog ), new_path.data() );
+               gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER( dialog ), new_path.c_str() );
        }
 
        // we should add all important paths as shortcut folder...
index 52cec49cf2a58d329001a7ad12a2e1ad7dfc4926..8581f7a4a4ef779a0840126e070dd40f21286e12 100644 (file)
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-// OpenGL widget based on GtkGLExt
+// OpenGL widget based on GtkGLExt / GtkGLArea
 
 #include "glwidget.h"
 
 #include "igl.h"
 
-void (*GLWidget_sharedContextCreated)() = 0;
-
-void (*GLWidget_sharedContextDestroyed)() = 0;
+// Function callbacks
+static void (*sharedContextCreated)() = nullptr;
+static void (*sharedContextDestroyed)() = nullptr;
 
 unsigned int g_context_count = 0;
 
 ui::GLArea g_shared{ui::null};
 
-void _glwidget_context_created(ui::GLArea self, void *data)
+static void _glwidget_context_created(ui::GLArea self, void *data)
 {
     if (++g_context_count == 1) {
         g_shared = self;
@@ -42,35 +42,34 @@ void _glwidget_context_created(ui::GLArea self, void *data)
         glwidget_make_current(g_shared);
         GlobalOpenGL().contextValid = true;
 
-        GLWidget_sharedContextCreated();
+        sharedContextCreated();
     }
 }
 
-void _glwidget_context_destroyed(ui::GLArea self, void *data)
+static void _glwidget_context_destroyed(ui::GLArea self, void *data)
 {
     if (--g_context_count == 0) {
         GlobalOpenGL().contextValid = false;
 
-        GLWidget_sharedContextDestroyed();
+        sharedContextDestroyed();
 
         g_shared.unref();
         g_shared = ui::GLArea(ui::null);
     }
 }
 
-void glwidget_destroy_context(ui::GLArea self)
-{
-}
-
-void glwidget_create_context(ui::GLArea self)
+void glwidget_set_shared_context_constructors(
+               void created(), void destroyed() )
 {
+       sharedContextCreated = created;
+       sharedContextDestroyed = destroyed;
 }
 
 #if GTK_TARGET == 3
 
 #include <gtk/gtk.h>
 
-GdkGLContext *glwidget_context_created(ui::GLArea self)
+static GdkGLContext *glwidget_context_created(ui::GLArea self)
 {
     _glwidget_context_created(self, nullptr);
     return gtk_gl_area_get_context(self);
@@ -78,9 +77,9 @@ GdkGLContext *glwidget_context_created(ui::GLArea self)
 
 ui::GLArea glwidget_new(bool zbuffer)
 {
-    auto self = ui::GLArea(GTK_GL_AREA(gtk_gl_area_new()));
+    auto self = ui::GLArea::from(GTK_GL_AREA(gtk_gl_area_new()));
     gtk_gl_area_set_has_depth_buffer(self, zbuffer);
-    gtk_gl_area_set_auto_render(self, false);
+    gtk_gl_area_set_auto_render(self, true); // FIXME
 
     self.connect("realize", G_CALLBACK(glwidget_context_created), nullptr);
     return self;
@@ -92,12 +91,12 @@ bool glwidget_make_current(ui::GLArea self)
 //        glwidget_context_created(self);
 //    }
     gtk_gl_area_make_current(self);
-    auto valid = GlobalOpenGL().contextValid;
     return true;
 }
 
 void glwidget_swap_buffers(ui::GLArea self)
 {
+    g_assert(GTK_IS_GL_AREA(self));
     gtk_gl_area_queue_render(self);
 }
 
@@ -116,21 +115,21 @@ struct config_t {
 };
 typedef const config_t *configs_iterator;
 
-int config_rgba32[] = {
+static int config_rgba32[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 24,
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba[] = {
+static int config_rgba[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 16,
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-const config_t configs[] = {
+static const config_t configs[] = {
         {
                 "colour-buffer = 32bpp, depth-buffer = none",
                 config_rgba32,
@@ -141,7 +140,7 @@ const config_t configs[] = {
         }
 };
 
-GdkGLConfig *glconfig_new()
+static GdkGLConfig *glconfig_new()
 {
     for (configs_iterator i = configs, end = configs + 2; i != end; ++i) {
         if (auto glconfig = gdk_gl_config_new(i->attribs)) {
@@ -153,7 +152,7 @@ GdkGLConfig *glconfig_new()
     return gdk_gl_config_new_by_mode((GdkGLConfigMode) (GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE));
 }
 
-int config_rgba32_depth32[] = {
+static int config_rgba32_depth32[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE,
@@ -163,7 +162,7 @@ int config_rgba32_depth32[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba32_depth24[] = {
+static int config_rgba32_depth24[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 24,
@@ -171,7 +170,7 @@ int config_rgba32_depth24[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba32_depth16[] = {
+static int config_rgba32_depth16[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 24,
@@ -179,7 +178,7 @@ int config_rgba32_depth16[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba32_depth[] = {
+static int config_rgba32_depth[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 24,
@@ -187,7 +186,7 @@ int config_rgba32_depth[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba_depth16[] = {
+static int config_rgba_depth16[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 16,
@@ -195,7 +194,7 @@ int config_rgba_depth16[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-int config_rgba_depth[] = {
+static int config_rgba_depth[] = {
         GDK_GL_RGBA,
         GDK_GL_DOUBLEBUFFER,
         GDK_GL_BUFFER_SIZE, 16,
@@ -203,7 +202,7 @@ int config_rgba_depth[] = {
         GDK_GL_ATTRIB_LIST_NONE,
 };
 
-const config_t configs_with_depth[] =
+static const config_t configs_with_depth[] =
         {
                 {
                         "colour-buffer = 32bpp, depth-buffer = 32bpp",
@@ -231,7 +230,7 @@ const config_t configs_with_depth[] =
                 },
         };
 
-GdkGLConfig *glconfig_new_with_depth()
+static GdkGLConfig *glconfig_new_with_depth()
 {
     for (configs_iterator i = configs_with_depth, end = configs_with_depth + 6; i != end; ++i) {
         if (auto glconfig = gdk_gl_config_new(i->attribs)) {
@@ -243,7 +242,7 @@ GdkGLConfig *glconfig_new_with_depth()
     return gdk_gl_config_new_by_mode((GdkGLConfigMode) (GDK_GL_MODE_RGBA | GDK_GL_MODE_DOUBLE | GDK_GL_MODE_DEPTH));
 }
 
-int glwidget_context_created(ui::GLArea self, void *data)
+static int glwidget_context_created(ui::GLArea self, void *data)
 {
     _glwidget_context_created(self, data);
     return false;
@@ -255,7 +254,7 @@ int glwidget_context_destroyed(ui::GLArea self, void *data)
     return false;
 }
 
-bool glwidget_enable_gl(ui::GLArea self, ui::Widget root, gpointer data)
+static bool glwidget_enable_gl(ui::GLArea self, ui::Widget root, gpointer data)
 {
     if (!root && !gtk_widget_is_gl_capable(self)) {
         const auto zbuffer = g_object_get_data(G_OBJECT(self), "zbuffer");
index 6a43da88ca3eb2379a10737d7e71661ea62bbd08..e407a03ec51f400b990476e0e646765887292f78 100644 (file)
 #if !defined( INCLUDED_GTKUTIL_GLWIDGET_H )
 #define INCLUDED_GTKUTIL_GLWIDGET_H
 
-extern void (*GLWidget_sharedContextCreated)();
-extern void (*GLWidget_sharedContextDestroyed)();
-
 ui::GLArea glwidget_new(bool zbuffer);
-void glwidget_create_context(ui::GLArea self);
-void glwidget_destroy_context(ui::GLArea self);
+void glwidget_set_shared_context_constructors(
+       void sharedContextCreated(), void sharedContextDestroyed() );
 bool glwidget_make_current(ui::GLArea self);
 void glwidget_swap_buffers(ui::GLArea self);
 
index 82d6dfe4b02ad2ddc49327f7cd4bc91e4911771c..afe74bdcf55d08b8dcfa4f9314efaf78fb072d62 100644 (file)
@@ -60,6 +60,8 @@ EMessageBoxReturn gtk_MessageBox( ui::Window parentWindow, const char* text, con
 
        ui::Window window = create_fixedsize_modal_dialog_window( parentWindow, title, dialog, 400, 100 );
 
+       gtk_window_set_position( window, GTK_WIN_POS_CENTER_ON_PARENT );
+
        if ( parentWindow ) {
                //window.connect( "delete_event", G_CALLBACK(floating_window_delete_present), parent);
                gtk_window_deiconify( parentWindow );
@@ -125,7 +127,7 @@ EMessageBoxReturn gtk_MessageBox( ui::Window parentWindow, const char* text, con
                }
 
                {
-                       auto button = create_modal_dialog_button( "OK", cancel_button );
+                       auto button = create_modal_dialog_button( "Cancel", cancel_button );
                        hbox.pack_start( button, TRUE, FALSE, 0 );
                        gtk_widget_add_accelerator( button , "clicked", accel, GDK_KEY_Escape, (GdkModifierType)0, (GtkAccelFlags)0 );
                        button.show();
index 4ae8a3f8a52c5b7fc44c6004de32847e4f538c18..05754604c4e2aa1eda5af6b627512e3f55a96080 100644 (file)
@@ -25,6 +25,6 @@
 #include "qerplugin.h"
 
 /// \brief Shows a modal message-box.
-EMessageBoxReturn gtk_MessageBox( ui::Window parent, const char* text, const char* title = "NetRadiant", EMessageBoxType type = eMB_OK, EMessageBoxIcon icon = eMB_ICONDEFAULT );
+EMessageBoxReturn gtk_MessageBox( ui::Window parent, const char* text, const char* title = RADIANT_NAME, EMessageBoxType type = eMB_OK, EMessageBoxIcon icon = eMB_ICONDEFAULT );
 
 #endif
index 4f724eef96bd6c247bd11044f0911278a5de39d4..e664aef4ee400ee5d9120f05919a918c855f7c0d 100644 (file)
  */
 
 #include "paned.h"
-
-#include <gtk/gtk.h>
-#include <uilib/uilib.h>
-
 #include "frame.h"
 
-
-class PanedState
-{
-public:
-float position;
-int size;
-};
-
 gboolean hpaned_allocate(ui::Widget widget, GtkAllocation* allocation, PanedState* paned ){
        if ( paned->size != allocation->width ) {
                paned->size = allocation->width;
index 842996efb5e3db6097b3cfa1899766e50c99cecd..951a72d7bc08237d008b2030f61229c0f28989ac 100644 (file)
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#include <gtk/gtk.h>
 #include <uilib/uilib.h>
 
 #if !defined( INCLUDED_GTKUTIL_PANED_H )
 #define INCLUDED_GTKUTIL_PANED_H
 
+class PanedState
+{
+public:
+float position;
+int size;
+};
+
+gboolean hpaned_allocate( ui::Widget widget, GtkAllocation* allocation, PanedState* paned );
+gboolean vpaned_allocate( ui::Widget widget, GtkAllocation* allocation, PanedState* paned );
+gboolean paned_position( ui::Widget widget, gpointer dummy, PanedState* paned );
+
 ui::HPaned create_split_views( ui::Widget topleft, ui::Widget topright, ui::Widget botleft, ui::Widget botright );
 
 #endif
index c1613500d12298de8664e83fe286787ab21de039..c8671a2fbcf0ab25976c5658d26a02d6abf87e44 100644 (file)
 
 inline void CHECK_RESTORE( ui::Widget w ){
        if ( gpointer_to_int( g_object_get_data( G_OBJECT( w ), "was_mapped" ) ) != 0 ) {
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+               /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+               GtkWidget* glwidget = GTK_WIDGET( g_object_get_data( G_OBJECT( w ), "glwidget" ) );
+               if ( glwidget ){
+                       gtk_widget_hide( glwidget );
+                       gtk_widget_show( glwidget );
+               }
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
+
                w.show();
 #define GARUX_GTK_WORKAROUND
 #ifndef GARUX_GTK_WORKAROUND
@@ -94,6 +104,25 @@ ui::Window create_floating_window( const char* title, ui::Window parent ){
        ui::Window window = ui::Window( ui::window_type::TOP );
        gtk_window_set_title( window, title );
 
+       /* Workaround: Windows minimizes the whole application including all the floating windows when
+        * one floating windows is minimized, this leads to an infinite loop of minimize/restore events,
+        * probably because of some race condition betwen all floating windows not having the same state
+        * at the same time, some being minimized while being restored at the same time, triggering the
+        * minimization and the restoration of the others, and so on.
+        * It's difficult to say such bug will never happen on other OS or with some window manager.
+        * While it's possible to decide this can be a design choihce since those floating windows are made
+        * to be displayed/hidden using menu or shortcuts, meaning the OS-specific way to minimize/restore
+        * them is superfluous and less efficient, the floating window mode that fixes issues on Windows
+        * is also known to be broken on KDE (the floating window does not get focus), this is likely to be
+        * a bug in kwin.
+        * In any way the mainframe is not a floating window and is not created using this function so the
+        * user minimizes the whole application including floating windows by minimizing the mainframe
+        */
+
+#ifdef WORKAROUND_WINDOWS_FLOATING_WINDOW
+       gtk_window_set_type_hint( window, GDK_WINDOW_TYPE_HINT_UTILITY );
+#endif // WORKAROUND_WINDOWS_FLOATING_WINDOW
+
        if ( parent ) {
                gtk_window_set_transient_for( window, parent );
                connect_floating_window_destroy_present( window, parent );
index e7012328d104a9df2c68916465cfbed088f85496..17d48bf9d097d3e103c6dd12866dc88a3d20be6e 100644 (file)
@@ -23,6 +23,7 @@ void XORRectangle::lazy_init()
 
 void XORRectangle::draw() const
 {
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
     const int x = float_to_integer(m_rectangle.x);
     const int y = float_to_integer(m_rectangle.y);
     const int w = float_to_integer(m_rectangle.w);
@@ -33,6 +34,7 @@ void XORRectangle::draw() const
     cairo_set_source_rgb(cr, 1, 1, 1);
     cairo_set_operator(cr, CAIRO_OPERATOR_DIFFERENCE);
     cairo_stroke(cr);
+#endif
 }
 
 XORRectangle::XORRectangle(ui::GLArea widget) : m_widget(widget), cr(0)
@@ -42,7 +44,9 @@ XORRectangle::XORRectangle(ui::GLArea widget) : m_widget(widget), cr(0)
 XORRectangle::~XORRectangle()
 {
     if (initialised()) {
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
         cairo_destroy(cr);
+#endif
     }
 }
 
index a0a19a843846403b010f218f51dd204fe8052b77..c4984b83f3b57cfd7b5d2f37e6c7b139eaab23bb 100644 (file)
@@ -7,7 +7,7 @@ else ()
     list(APPEND L_NETLIST l_net_berkley.c)
 endif ()
 
-add_library(l_net ${L_NETLIST})
+add_library(l_net STATIC ${L_NETLIST})
 
 if (WIN32)
     target_link_libraries(l_net PRIVATE ws2_32)
index 6cfedbefb42c17da3bdbb60372f75152536607e3..4dc8a8ce6cc5bab123a8fb2fcc4863ff0bd33031 100644 (file)
@@ -1,4 +1,4 @@
-add_library(math
+add_library(math STATIC
         _.cpp
         aabb.h
         curve.h
index 9bb3ef5111a0bdbb712f7453f13b26b4896784a1..c2b45b501ffe1d7e592e1865515e4b091264fc04 100644 (file)
@@ -46,16 +46,6 @@ inline __int64 llrint( double f ){
        return static_cast<__int64>( f + 0.5 );
 }
 
-#elif GDEF_OS_BSD
-
-inline long lrint( double f ){
-       return static_cast<long>( f + 0.5 );
-}
-
-inline long long llrint( double f ){
-       return static_cast<long long>( f + 0.5 );
-}
-
 #elif GDEF_COMPILER_GNU
 
 // lrint is part of ISO C99
index 5682a5e1d68c8dec76fec7f782184046fcd5b9bb..27b087a85f85868865901c0fd656247b0f447a51 100644 (file)
@@ -1,4 +1,4 @@
-add_library(mathlib
+add_library(mathlib STATIC
         bbox.c
         line.c
         m4x4.c
index fe5646d9327e683c2285d0e9f2541a6b436b68dc..8dd639b84b88cec1346979c3f108cd8c12532cbd 100644 (file)
@@ -174,7 +174,7 @@ const int MIDDLE  = 2;
 int aabb_intersect_ray( const aabb_t *aabb, const ray_t *ray, vec3_t intersection ){
        int inside = 1;
        char quadrant[NUMDIM];
-       register int i;
+       int i;
        int whichPlane;
        double maxT[NUMDIM];
        double candidatePlane[NUMDIM];
index 1c345734254cd749c6944f9bf045a15a31e1a08e..bebfc22db008d76a542f64568d42bc63f35044e2 100644 (file)
@@ -1,3 +1,3 @@
-add_library(memory
+add_library(memory STATIC
         allocator.cpp allocator.h
         )
index d27aa63382d260df34c63902bf658916956611fa..489ee4a5be423b841341854617ff0b7c4d9a1d75 100644 (file)
@@ -1,4 +1,4 @@
-add_library(modulesystem
+add_library(modulesystem STATIC
         moduleregistry.h
         modulesmap.h
         singletonmodule.cpp singletonmodule.h
index 437b506caff6c7fc78251a80af0b1acdd5f61f5c..a1e475998e10b3eac6e2af3aeb7cbc56dee10cc2 100644 (file)
@@ -1,4 +1,4 @@
-add_library(os
+add_library(os STATIC
         _.cpp
         dir.h
         file.h
index a3db167cb484ad84abbff192fc9289ae3408fcc1..9cbbc2b1361c49a21b48acb82be6b95af3e69831 100644 (file)
@@ -72,6 +72,12 @@ inline bool path_equal( const char* path, const char* other ){
 #endif
 }
 
+/// \brief Returns true if \p path and \p other refer to the same file or directory, case insensitively.
+/// O(n)
+inline bool path_equal_i( const char* path, const char* other ){
+       return string_equal_nocase( path, other );
+}
+
 /// \brief Returns true if the first \p n bytes of \p path and \p other form paths that refer to the same file or directory.
 /// If the paths are UTF-8 encoded, [\p path, \p path + \p n) must be a complete path.
 /// O(n)
@@ -175,6 +181,12 @@ inline bool extension_equal( const char* extension, const char* other ){
        return path_equal( extension, other );
 }
 
+/// \brief Returns true if \p extension is of the same type as \p other, case insensitively.
+/// O(n)
+inline bool extension_equal_i( const char* extension, const char* other ){
+       return path_equal_i( extension, other );
+}
+
 template<typename Functor>
 class MatchFileExtension
 {
index 370afef92266fb994ab5b5a14aeb631ca9d30488..eb0bc9432b0ef76844982d90f22490c994d3f7c2 100644 (file)
@@ -263,7 +263,7 @@ void                        PicoSetSurfaceShader( picoSurface_t *surface, picoSh
 void                        PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz );
 void                        PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
 void                        PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st );
-void                        PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color );
+void                        PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, const picoColor_t color );
 void                        PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index );
 void                        PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count );
 void                        PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
@@ -336,12 +336,12 @@ picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCom
 picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index );
 
 /* specialized functions */
-int                         PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup );
+int                         PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, const picoColor_t *color, picoIndex_t smoothingGroup );
 void                        PicoFixSurfaceNormals( picoSurface_t *surface );
 int                         PicoRemapModel( picoModel_t *model, char *remapFile );
 
 
-void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors, picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup );
+void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, const picoColor_t **colors, picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup );
 
 /* end marker */
 #ifdef __cplusplus
index 0f1286d0fb4056fe4349408135471de1bf9b7d76..2e0b96779cff2b47297158596bb7c5b312680fc9 100644 (file)
@@ -1,4 +1,4 @@
-add_library(picomodel
+add_library(picomodel STATIC
         lwo/clip.c
         lwo/envelope.c
         lwo/list.c
@@ -16,6 +16,7 @@ add_library(picomodel
         pm_3ds.c
         pm_ase.c
         pm_fm.c pm_fm.h
+        pm_iqm.c
         pm_lwo.c
         pm_md2.c
         pm_md3.c
index e825a3403e97d0b5b6f458cbefed03ae2513eea7..c24ef457b4a86a58c1a604cf5ad3cf5e1b8128ef 100644 (file)
@@ -54,7 +54,7 @@ int get_flen( void ) { return flen; }
    ===================================================================== */
 
 void revbytes( void *bp, int elsize, int elcount ){
-       register unsigned char *p, *q;
+       unsigned char *p, *q;
 
        p = ( unsigned char * ) bp;
 
index 09145919a1e09d05163f2ee5a168790cee260d03..54866de101522a7440d3952a0b8cea1f22011a67 100644 (file)
@@ -462,6 +462,8 @@ picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVe
        return _pico_normalize_vec( plane );
 }
 
+const picoColor_t picoColor_white = { 255, 255, 255, 255 };
+
 /* separate from _pico_set_vec4 */
 void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
        c[ 0 ] = r;
@@ -470,7 +472,7 @@ void _pico_set_color( picoColor_t c, int r, int g, int b, int a ){
        c[ 3 ] = a;
 }
 
-void _pico_copy_color( picoColor_t src, picoColor_t dest ){
+void _pico_copy_color( const picoColor_t src, picoColor_t dest ){
        dest[ 0 ] = src[ 0 ];
        dest[ 1 ] = src[ 1 ];
        dest[ 2 ] = src[ 2 ];
@@ -692,6 +694,81 @@ int _pico_getline( char *buf, int bufsize, char *dest, int destsize ){
        return pos;
 }
 
+/* expecting fileName to be relative vfs model path */
+void _pico_deduce_shadername( const char* fileName, const char* srcName, picoShader_t* shader ){
+       if( srcName == NULL || fileName == NULL )
+               return;
+       char name[strlen( srcName ) + 1];
+       strcpy( name, srcName );
+       _pico_unixify( name );
+       _pico_setfext( name, NULL );
+
+       char path[strlen( fileName ) + strlen( name ) + 1];
+       _pico_nofname( fileName, path, strlen( fileName ) + strlen( name ) + 1 );
+       _pico_unixify( path );
+
+       if( !strchr( name , '/' ) ){ /* texture is likely in the folder, where model is */
+               strcat( path, name );
+       }
+       else if( name[0] == '/' || ( name[0] != '\0' && name[1] == ':' ) || strstr( name, ".." ) ){ /* absolute path or with .. */
+               const char* p = name;
+               for (; *p != '\0'; ++p )
+                       if ( _pico_strnicmp( p, "/models/", 8 ) == 0 || _pico_strnicmp( p, "/textures/", 10 ) == 0 )
+                               break;
+               if( *p != '\0' ){
+                       strcpy( path, p + 1 );
+               }
+               else{
+                       p = _pico_nopath( name );
+                       strcat( path, p );
+               }
+       }
+       else{
+               PicoSetShaderName( shader, name );
+               return;
+       }
+
+       _pico_printf( PICO_NORMAL, "PICO: substituting shader name: %s -> %s", srcName, path );
+       PicoSetShaderName( shader, path );
+}
+
+/* deduce shadernames from bitmap or shadername paths */
+void _pico_deduce_shadernames( picoModel_t *model ){
+       for ( int i = 0; i < model->numShaders; ++i ){
+               /* skip null shaders */
+               if ( model->shader[i] == NULL )
+                       continue;
+
+               const char* mapname = model->shader[i]->mapName;
+               const char* shadername = model->shader[i]->name;
+
+               /* Detect intentional material name to not replace it with texture name.
+
+               Reimplement commits by Garux:
+               https://github.com/Garux/netradiant-custom/commit/1bd3e7ae186b55fb61e3738d2493432c0b1f5a7b
+               https://github.com/Garux/netradiant-custom/commit/ea21eee2254fb2e667732d8f1b0f83c439a89bfa
+
+               This attempts to restore proper material behaviour when the mapper knows what he is doing,
+               also called Julius' case or correct case because Julius is always correct™
+               while keeping the fallback for other situations, also called newbie's case
+               which may be compatible with third-party tools not following Quake 3 conventions.
+
+               See: https://gitlab.com/xonotic/netradiant/-/merge_requests/179#note_777324051 */
+               if ( shadername && *shadername &&
+                       ( _pico_strnicmp( shadername, "models/", 7 ) == 0
+                       || _pico_strnicmp( shadername, "models\\", 7 ) == 0
+                       || _pico_strnicmp( shadername, "textures/", 9 ) == 0
+                       || _pico_strnicmp( shadername, "textures\\", 9 ) == 0 ) )
+               {
+                       _pico_deduce_shadername( model->fileName, shadername, model->shader[i] );
+               }
+               else if( mapname && *mapname )
+                       _pico_deduce_shadername( model->fileName, mapname, model->shader[i] );
+               else if( shadername && *shadername )
+                       _pico_deduce_shadername( model->fileName, shadername, model->shader[i] );
+       }
+}
+
 /* _pico_parse_skip_white:
  *  skips white spaces in current pico parser, sets *hasLFs
  *  to 1 if linefeeds were skipped, and either returns the
index 4bcbd4c281ae026efd4ad87ea7375f17ee4adb45..98b6cf8f1cd0ff1c7f20766a576c2215dd0b9c67 100644 (file)
@@ -77,7 +77,13 @@ extern "C"
 #define PICO_IOEOF  1
 #define PICO_IOERR  2
 
+extern const picoColor_t picoColor_white;
+
 /* types */
+#ifndef byte
+       typedef unsigned char byte;
+#endif
+
 typedef struct picoParser_s
 {
        const char *buffer;
@@ -134,10 +140,11 @@ void            _pico_printf( int level, const char *format, ... );
 const char      *_pico_stristr( const char *str, const char *substr );
 void            _pico_unixify( char *path );
 int             _pico_nofname( const char *path, char *dest, int destSize );
-const char *_pico_nopath( const char *path );
+const char      *_pico_nopath( const char *path );
 char            *_pico_setfext( char *path, const char *ext );
 int             _pico_getline( char *buf, int bufsize, char *dest, int destsize );
 char            *_pico_strlwr( char *str );
+void            _pico_deduce_shadernames( picoModel_t *model );
 
 /* vectors */
 void            _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs );
@@ -148,7 +155,7 @@ void            _pico_zero_vec4( picoVec4_t vec );
 void            _pico_set_vec( picoVec3_t v, float a, float b, float c );
 void            _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d );
 void            _pico_set_color( picoColor_t c, int r, int g, int b, int a );
-void            _pico_copy_color( picoColor_t src, picoColor_t dest );
+void            _pico_copy_color( const picoColor_t src, picoColor_t dest );
 void            _pico_copy_vec( picoVec3_t src, picoVec3_t dest );
 void            _pico_copy_vec2( picoVec2_t src, picoVec2_t dest );
 picoVec_t       _pico_normalize_vec( picoVec3_t vec );
index 311f6de760c7791bb9e94f717d481a192c46dfdc..7d53683ae535688b2556f5bbd3a2fd65718e425a 100644 (file)
@@ -173,6 +173,8 @@ picoModel_t *PicoModuleLoadModel( const picoModule_t* pm, const char* fileName,
                        }
                }
 
+               _pico_deduce_shadernames( model );
+
                return model;
        }
 
@@ -484,16 +486,13 @@ void PicoFreeShader( picoShader_t *shader ){
  */
 
 picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive ){
-       int i;
-
-
        /* sanity checks */
        if ( model == NULL || name == NULL ) { /* sea: null name fix */
                return NULL;
        }
 
        /* walk list */
-       for ( i = 0; i < model->numShaders; i++ )
+       for ( int i = 0; i < model->numShaders; i++ )
        {
                /* skip null shaders or shaders with null names */
                if ( model->shader[ i ] == NULL ||
@@ -991,7 +990,7 @@ void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st
 
 
 
-void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color ){
+void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, const picoColor_t color ){
        if ( surface == NULL || num < 0 || color == NULL ) {
                return;
        }
@@ -1603,7 +1602,7 @@ picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexComb
    fixme: needs non-naive algorithm
  */
 
-int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color, picoIndex_t smoothingGroup ){
+int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, const picoColor_t *color, picoIndex_t smoothingGroup ){
        int i, j;
 
 
@@ -1647,7 +1646,7 @@ int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t
                if ( numColors > 0 && color != NULL ) {
                        for ( j = 0; j < numSTs; j++ )
                        {
-                               if ( *( (int*) surface->color[ j ] ) != *( (int*) color[ j ] ) ) {
+                               if ( *( (const int*) surface->color[ j ] ) != *( (const int*) color[ j ] ) ) {
                                        break;
                                }
                        }
@@ -2248,7 +2247,7 @@ int PicoRemapModel( picoModel_t *model, char *remapFile ){
  */
 
 void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals,
-                                                        int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
+                                                        int numSTs, picoVec2_t **st, int numColors, const picoColor_t **colors,
                                                         picoShader_t* shader, const char *name, picoIndex_t* smoothingGroup ){
        int i,j;
        int vertDataIndex;
index 77bb4918b22af6a9385cc71af558c912dc347d56..406ee16f9ba1ef81d26cd98660defacd87d23aee 100644 (file)
@@ -48,6 +48,7 @@ extern const picoModule_t picoModuleMD2;
 extern const picoModule_t picoModuleFM;
 extern const picoModule_t picoModuleLWO;
 extern const picoModule_t picoModuleTerrain;
+extern const picoModule_t picoModuleIQM;
 
 
 
@@ -64,6 +65,7 @@ const picoModule_t *picoModules[] =
        &picoModuleLWO,     /* lightwave object */
        &picoModuleTerrain, /* picoterrain object */
        &picoModuleOBJ,     /* wavefront object */
+       &picoModuleIQM,     /* interquake model */
        NULL                /* arnold */
 };
 
index e72454a170a6d851599d15ac2f4c38f3d2863e5f..c27644b247f999f3b514de34b11c42825c6ebb08 100644 (file)
@@ -35,9 +35,6 @@
 /* dependencies */
 #include "picointernal.h"
 
-/* ydnar */
-static picoColor_t white = { 255,255,255,255 };
-
 /* remarks:
  * - 3ds file version is stored in pico special field 0 on load (ydnar: removed)
  * todo:
@@ -294,7 +291,7 @@ static int GetMeshVertices( T3dsLoaderPers *pers ){
 
                /* add current vertex */
                PicoSetSurfaceXYZ( pers->surface,i,v );
-               PicoSetSurfaceColor( pers->surface,0,i,white ); /* ydnar */
+               PicoSetSurfaceColor( pers->surface, 0, i, picoColor_white );
 
 #ifdef DEBUG_PM_3DS_EX
                printf( "Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2] );
@@ -403,17 +400,15 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
 
        /* we've found a matching shader */
        if ( ( shader != NULL ) && pers->surface ) {
-               char mapName[1024 + 1];
-               char *mapNamePtr;
-               memset( mapName,0,sizeof( mapName ) );
-
                /* get ptr to shader's map name */
-               mapNamePtr = PicoGetShaderMapName( shader );
-
+               const char* mapNamePtr = PicoGetShaderMapName( shader );
                /* we have a valid map name ptr */
                if ( mapNamePtr != NULL ) {
+#if 0
                        char temp[128];
                        const char *name;
+                       char mapName[1024 + 1];
+                       memset( mapName,0,sizeof( mapName ) );
 
                        /* copy map name to local buffer */
                        strcpy( mapName,mapNamePtr );
@@ -423,7 +418,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
                        strncpy( temp, name, sizeof( temp ) );
 
                        /* remove file extension */
-                       /* name = _pico_setfext( name,"" ); */
+                       /* name = _pico_setfext( name, NULL ); */
 
                        /* assign default name if no name available */
                        if ( strlen( temp ) < 1 ) {
@@ -436,7 +431,7 @@ static int GetMeshShader( T3dsLoaderPers *pers ){
 
                        /* set shader name */
                        /* PicoSetShaderName( shader,mapName ); */      /* ydnar: this will screw up the named shader */
-
+#endif
                        /* set surface's shader index */
                        PicoSetSurfaceShader( pers->surface, shader );
 
@@ -727,9 +722,9 @@ static picoModel_t *_3ds_load( PM_PARAMS_LOAD ){
                return NULL;
        }
        /* get model's base name (eg. jeep from c:\models\jeep.3ds) */
-       memset( basename,0,sizeof( basename ) );
-       strncpy( basename,_pico_nopath( fileName ),sizeof( basename ) );
-       _pico_setfext( basename,"" );
+       memset( basename, 0, sizeof( basename ) );
+       strncpy( basename, _pico_nopath( fileName ), sizeof( basename ) - 1 );
+       _pico_setfext( basename, NULL );
 
        /* initialize persistant vars (formerly static) */
        pers.model    =  model;
index d73187c6ec706c2131b8282f89ec28a5f1f35eca..81bb99dbb6c358635a2bb4d1325645d1ca6e79bf 100644 (file)
@@ -44,9 +44,6 @@
 #include "time.h"
 #endif
 
-/* plain white */
-static picoColor_t white = { 255, 255, 255, 255 };
-
 /* jhefty - multi-subobject material support */
 
 /* Material/SubMaterial management */
@@ -402,7 +399,7 @@ static void _ase_submit_triangles_unshared( picoModel_t* model, aseMaterial_t* m
                                        }
                                        else
                                        {
-                                               PicoSetSurfaceColor( surface, 0, numVertexes, white );
+                                               PicoSetSurfaceColor( surface, 0, numVertexes, picoColor_white );
                                        }
 
                                        PicoSetSurfaceSmoothingGroup( surface, numVertexes, ( vertices[( *i ).indices[j]].id * ( 1 << 16 ) ) + ( *i ).smoothingGroup );
@@ -431,7 +428,7 @@ static void _ase_submit_triangles( picoModel_t* model, aseMaterial_t* materials,
                        picoVec3_t* xyz[3];
                        picoVec3_t* normal[3];
                        picoVec2_t* st[3];
-                       picoColor_t* color[3];
+                       const picoColor_t* color[3];
                        picoIndex_t smooth[3];
                        int j;
                        /* we pull the data from the vertex, color and texcoord arrays using the face index data */
@@ -446,7 +443,7 @@ static void _ase_submit_triangles( picoModel_t* model, aseMaterial_t* materials,
                                }
                                else
                                {
-                                       color[j] = &white;
+                                       color[j] = &picoColor_white;
                                }
 
                                smooth[j] = ( vertices[( *i ).indices[j]].id * ( 1 << 16 ) ) + ( *i ).smoothingGroup; /* don't merge vertices */
@@ -459,17 +456,6 @@ static void _ase_submit_triangles( picoModel_t* model, aseMaterial_t* materials,
        }
 }
 
-static void shadername_convert( char* shaderName ){
-       /* unix-style path separators */
-       char* s = shaderName;
-       for (; *s != '\0'; ++s )
-       {
-               if ( *s == '\\' ) {
-                       *s = '/';
-               }
-       }
-}
-
 
 /* _ase_load:
  *  loads a 3dsmax ase model file.
@@ -525,7 +511,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
        PicoSetModelFileName( model, fileName );
 
        /* initialize some stuff */
-       memset( lastNodeName,0,sizeof( lastNodeName ) );
+       memset( lastNodeName, 0, sizeof( lastNodeName ) );
 
        /* parse ase model file */
        while ( 1 )
@@ -554,7 +540,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                        }
 
                        /* remember node name */
-                       strncpy( lastNodeName,ptr,sizeof( lastNodeName ) );
+                       strncpy( lastNodeName, ptr, sizeof( lastNodeName ) - 1 );
                }
                /* model mesh (originally contained within geomobject) */
                else if ( !_pico_stricmp( p->token,"*mesh" ) ) {
@@ -886,7 +872,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                if ( level == subMaterialLevel ) {
                                        /* set material name */
                                        _pico_first_token( materialName );
-                                       shadername_convert( materialName );
+                                       _pico_unixify( materialName );
                                        PicoSetShaderName( shader, materialName );
 
                                        /* set shader's transparency */
@@ -1055,6 +1041,9 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                                        if ( name == NULL ) {
                                                                _ase_error_return( "Missing material map bitmap name" );
                                                        }
+                                                       else if( !_pico_stricmp( name, "none" ) ){ // standard empty bitmap name
+                                                               name = "";
+                                                       }
                                                        mapname = _pico_alloc( strlen( name ) + 1 );
                                                        strcpy( mapname, name );
                                                        /* skip rest and continue with next token */
@@ -1076,7 +1065,7 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                }
 
                                /* set material name */
-                               shadername_convert( materialName );
+                               _pico_unixify( materialName );
                                PicoSetShaderName( shader,materialName );
 
                                /* set shader's transparency */
@@ -1100,34 +1089,6 @@ static picoModel_t *_ase_load( PM_PARAMS_LOAD ){
                                /* set material map name */
                                PicoSetShaderMapName( shader, mapname );
 
-                               /* extract shadername from bitmap path */
-                               if ( mapname != NULL ) {
-                                       char* p = mapname;
-
-                                       /* convert to shader-name format */
-                                       shadername_convert( mapname );
-                                       {
-                                               /* remove extension */
-                                               char* last_period = strrchr( p, '.' );
-                                               if ( last_period != NULL ) {
-                                                       *last_period = '\0';
-                                               }
-                                       }
-
-                                       /* find shader path */
-                                       for (; *p != '\0'; ++p )
-                                       {
-                                               if ( _pico_strnicmp( p, "models/", 7 ) == 0 || _pico_strnicmp( p, "textures/", 9 ) == 0 ) {
-                                                       break;
-                                               }
-                                       }
-
-                                       if ( *p != '\0' ) {
-                                               /* set material name */
-                                               PicoSetShaderName( shader,p );
-                                       }
-                               }
-
                                /* this is just a material with 1 submaterial */
                                subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
                        }
index c4086184c317cf15547c4f42637dff9f9d32b85b..a4b8a11bd71a0bdec84336b0fc89ecc2aec04166 100644 (file)
@@ -198,7 +198,8 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
 
        fm_vert_normal_t    *vert;
 
-       char skinname[FM_SKINPATHSIZE];
+       char skinname[FM_SKINPATHSIZE + 1];
+       skinname[FM_SKINPATHSIZE] = '\0';
        fm_t fm;
        fm_header_t     *fm_head;
        fm_st_t         *texCoord;
@@ -212,7 +213,6 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
        picoShader_t    *picoShader;
        picoVec3_t xyz, normal;
        picoVec2_t st;
-       picoColor_t color;
 
 
        bb0 = bb = (picoByte_t*) _pico_alloc( bufSize );
@@ -375,7 +375,7 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
 #endif
 
        // detox Skin name
-       _pico_setfext( skinname, "" );
+       _pico_setfext( skinname, NULL );
        _pico_unixify( skinname );
 
        /* create new pico model */
@@ -587,6 +587,9 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
                st[ 0 ] =  ( ( texCoord[p_index_LUT[i].ST].s ) / ( (float)fm_head->skinWidth ) );
                st[ 1 ] =  ( texCoord[p_index_LUT[i].ST].t / ( (float)fm_head->skinHeight ) );
                PicoSetSurfaceST( picoSurface, 0, i, st );
+
+               /* set color */
+               PicoSetSurfaceColor( picoSurface, 0, i, picoColor_white );
        }
 
        if ( dups ) {
@@ -609,12 +612,12 @@ static picoModel_t *_fm_load( PM_PARAMS_LOAD ){
                        st[ 0 ] =  ( ( texCoord[p_index_LUT_DUPS[i].ST].s ) / ( (float)fm_head->skinWidth ) );
                        st[ 1 ] =  ( texCoord[p_index_LUT_DUPS[i].ST].t / ( (float)fm_head->skinHeight ) );
                        PicoSetSurfaceST( picoSurface, 0, i + fm_head->numXYZ, st );
+
+                       /* set color */
+                       PicoSetSurfaceColor( picoSurface, 0, i + fm_head->numXYZ, picoColor_white );
                }
        }
 
-       /* set color */
-       PicoSetSurfaceColor( picoSurface, 0, 0, color );
-
        // Free up malloc'ed LL entries
        for ( i = 0; i < fm_head->numXYZ; i++ )
        {
index 6fa317ca8714b42f18e1cc20495f739c7a68a030..8ffcc405c923bf3bbd1a0df2270e7d38fdd3f3fd 100644 (file)
 #define INFO_HEIGHT 5
 #define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT )
 
-#ifndef byte
-       #define byte unsigned char
-#endif
-
 
 //
 //     Generic header on every chunk
diff --git a/libs/picomodel/pm_iqm.c b/libs/picomodel/pm_iqm.c
new file mode 100644 (file)
index 0000000..739cbef
--- /dev/null
@@ -0,0 +1,359 @@
+/* -----------------------------------------------------------------------------
+
+   InterQuake Model - PicoModel Library
+
+   Copyright (c) 2018-2021, FTE Team <fteqw.org>
+   All rights reserved.
+
+   Redistribution and use in source and binary forms, with or without modification,
+   are permitted provided that the following conditions are met:
+
+   Redistributions of source code must retain the above copyright notice, this list
+   of conditions and the following disclaimer.
+
+   Redistributions in binary form must reproduce the above copyright notice, this
+   list of conditions and the following disclaimer in the documentation and/or
+   other materials provided with the distribution.
+
+   Neither the names of the copyright holders nor the names of its contributors may
+   be used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+   ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------------------- */
+
+/* dependencies */
+#include "picointernal.h"
+
+extern const picoModule_t picoModuleIQM;
+
+#define IQM_MAGIC "INTERQUAKEMODEL"    //15+null
+
+/*
+   ========================================================================
+
+   .IQM triangle model file format
+
+   ========================================================================
+ */
+
+enum
+{
+       IQM_POSITION = 0,
+       IQM_TEXCOORD = 1,
+       IQM_NORMAL = 2,
+       IQM_TANGENT = 3,
+       IQM_BLENDINDEXES = 4,
+       IQM_BLENDWEIGHTS = 5,
+       IQM_COLOR = 6,
+       IQM_CUSTOM = 0x10
+};
+
+enum
+{
+       IQM_BYTE = 0,
+       IQM_UBYTE = 1,
+       IQM_SHORT = 2,
+       IQM_USHORT = 3,
+       IQM_INT = 4,
+       IQM_UINT = 5,
+       IQM_HALF = 6,
+       IQM_FLOAT = 7,
+       IQM_DOUBLE = 8
+};
+
+// animflags
+#define IQM_LOOP 1
+
+typedef struct iqmHeader_s {
+       byte id[16];
+       unsigned int version;
+       unsigned int filesize;
+       unsigned int flags;
+       unsigned int num_text, ofs_text;
+       unsigned int num_meshes, ofs_meshes;
+       unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
+       unsigned int num_triangles, ofs_triangles, ofs_neighbors;
+       unsigned int num_joints, ofs_joints;
+       unsigned int num_poses, ofs_poses;
+       unsigned int num_anims, ofs_anims;
+       unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
+       unsigned int num_comment, ofs_comment;
+       unsigned int num_extensions, ofs_extensions;
+} iqmHeader_t;
+
+typedef struct iqmmesh_s {
+       unsigned int name;
+       unsigned int material;
+       unsigned int first_vertex;
+       unsigned int num_vertexes;
+       unsigned int first_triangle;
+       unsigned int num_triangles;
+} iqmmesh_t;
+
+typedef struct iqmvertexarray_s {
+       unsigned int type;
+       unsigned int flags;
+       unsigned int format;
+       unsigned int size;
+       unsigned int offset;
+} iqmvertexarray_t;
+
+//is anyone actually going to run this on a big-endian cpu?
+static iqmHeader_t SwapHeader(const iqmHeader_t *h)
+{
+       iqmHeader_t r = *h;
+       r.version = _pico_little_long(h->version);
+       r.filesize = _pico_little_long(h->filesize);
+       r.flags = _pico_little_long(h->flags);
+       r.num_text = _pico_little_long(h->num_text);
+       r.ofs_text = _pico_little_long(h->ofs_text);
+       r.num_meshes = _pico_little_long(h->num_meshes);
+       r.ofs_meshes = _pico_little_long(h->ofs_meshes);
+       r.num_vertexarrays = _pico_little_long(h->num_vertexarrays);
+       r.num_vertexes = _pico_little_long(h->num_vertexes);
+       r.ofs_vertexarrays = _pico_little_long(h->ofs_vertexarrays);
+       r.num_triangles = _pico_little_long(h->num_triangles);
+       r.ofs_triangles = _pico_little_long(h->ofs_triangles);
+       r.ofs_neighbors = _pico_little_long(h->ofs_neighbors);
+       r.num_joints = _pico_little_long(h->num_joints);
+       r.ofs_joints = _pico_little_long(h->ofs_joints);
+       r.num_poses = _pico_little_long(h->num_poses);
+       r.ofs_poses = _pico_little_long(h->ofs_poses);
+       r.num_anims = _pico_little_long(h->num_anims);
+       r.ofs_anims = _pico_little_long(h->ofs_anims);
+       r.num_frames = _pico_little_long(h->num_frames);
+       r.num_framechannels = _pico_little_long(h->num_framechannels);
+       r.ofs_frames = _pico_little_long(h->ofs_frames);
+       r.ofs_bounds = _pico_little_long(h->ofs_bounds);
+       r.num_comment = _pico_little_long(h->num_comment);
+       r.ofs_comment = _pico_little_long(h->ofs_comment);
+       r.num_extensions = _pico_little_long(h->num_extensions);
+       r.ofs_extensions = _pico_little_long(h->ofs_extensions);
+       return r;
+}
+
+// _iqm_canload()
+static int _iqm_canload( PM_PARAMS_CANLOAD ){
+       iqmHeader_t h;
+
+       //make sure there's enough data for the header...
+       if ((size_t)bufSize < sizeof(h))
+               return PICO_PMV_ERROR_SIZE;
+       h = SwapHeader(buffer);
+
+       //make sure its actually an iqm
+       if (memcmp(h.id, IQM_MAGIC, sizeof(h.id)))
+               return PICO_PMV_ERROR_IDENT;
+       //v1 is flawed, we don't know about anything higher either.
+       if (h.version != 2)
+               return PICO_PMV_ERROR_VERSION;
+       //make sure its not truncated
+       if ((size_t)h.filesize != (size_t)bufSize)
+               return PICO_PMV_ERROR_SIZE;
+
+       //looks like we can probably use it.
+       return PICO_PMV_OK;
+}
+
+// _iqm_load() loads an interquake model file.
+static picoModel_t *_iqm_load( PM_PARAMS_LOAD ){
+       picoModel_t     *picoModel;
+       picoSurface_t   *picoSurface;
+       picoShader_t    *picoShader;
+       const float *inf;
+       const byte *inb;
+       picoVec3_t xyz, normal;
+       picoVec2_t st;
+       picoColor_t color;
+
+       iqmHeader_t h;
+       iqmmesh_t m;
+       iqmvertexarray_t a;
+       size_t s, t, j, i;
+       const char *stringtable;
+       char skinname[512];
+       const unsigned int *tri;
+
+       //just in case
+       if (_iqm_canload(fileName, buffer, bufSize) != PICO_PMV_OK)
+       {
+               _pico_printf( PICO_ERROR, "%s is not an IQM File!", fileName );
+               return NULL;
+       }
+       h = SwapHeader(buffer);
+       stringtable = (const char*)buffer + h.ofs_text;
+
+       // do frame check
+       if ( h.num_anims != 0 ) {
+               _pico_printf( PICO_WARNING, "%s has animations! Using base pose only.", fileName );
+       }
+
+       /* create new pico model */
+       picoModel = PicoNewModel();
+       if ( picoModel == NULL ) {
+               _pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+               return NULL;
+       }
+
+       /* do model setup */
+       PicoSetModelFrameNum( picoModel, frameNum );
+       PicoSetModelNumFrames( picoModel, 1 ); /* sea */
+       PicoSetModelName( picoModel, fileName );
+       PicoSetModelFileName( picoModel, fileName );
+
+       for (s = 0; s < h.num_meshes; s++)
+       {
+               m = ((const iqmmesh_t*)((const char*)buffer + h.ofs_meshes))[s];
+               m.first_triangle = _pico_little_long(m.first_triangle);
+               m.first_vertex = _pico_little_long(m.first_vertex);
+               m.material = _pico_little_long(m.material);
+               m.name = _pico_little_long(m.name);
+               m.num_triangles = _pico_little_long(m.num_triangles);
+               m.num_vertexes = _pico_little_long(m.num_vertexes);
+
+               // allocate new pico surface
+               picoSurface = PicoNewSurface( picoModel );
+               if ( picoSurface == NULL ) {
+                       _pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+                       PicoFreeModel( picoModel );
+                       return NULL;
+               }
+
+               // detox Skin name
+               memcpy(skinname, stringtable+m.material, sizeof(skinname));
+               _pico_setfext( skinname, "" );
+               _pico_unixify( skinname );
+
+               PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+               PicoSetSurfaceName( picoSurface, stringtable+m.name );
+               picoShader = PicoNewShader( picoModel );
+               if ( picoShader == NULL ) {
+                       _pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+                       PicoFreeModel( picoModel );
+                       return NULL;
+               }
+
+               PicoSetShaderName( picoShader, skinname );
+
+               // associate current surface with newly created shader
+               PicoSetSurfaceShader( picoSurface, picoShader );
+
+
+               // spew the surface's indexes
+               tri = (const unsigned int *)((const char *)buffer+h.ofs_triangles) + m.first_triangle*3;
+               for (t = 0; t < m.num_triangles*3; t++)
+                       PicoSetSurfaceIndex( picoSurface, t, _pico_little_long(*tri++) - m.first_vertex );
+
+               for ( j = 0; j < h.num_vertexarrays; j++)
+               {
+                       a = ((const iqmvertexarray_t*)((const char*)buffer + h.ofs_vertexarrays))[j];
+                       a.flags = _pico_little_long(a.flags);
+                       a.format = _pico_little_long(a.format);
+                       a.offset = _pico_little_long(a.offset);
+                       a.size = _pico_little_long(a.size);
+                       a.type = _pico_little_long(a.type);
+
+                       switch(a.type)
+                       {
+                       case IQM_POSITION:
+                               if (a.format == IQM_FLOAT && a.size >= 3)
+                               {
+                                       inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+                                       for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+                                       {
+                                               xyz[0] = _pico_little_float(inf[0]);
+                                               xyz[1] = _pico_little_float(inf[1]);
+                                               xyz[2] = _pico_little_float(inf[2]);
+                                               PicoSetSurfaceXYZ( picoSurface, i, xyz );
+                                       }
+                               }
+                               break;
+                       case IQM_TEXCOORD:
+                               if (a.format == IQM_FLOAT && a.size >= 2)
+                               {
+                                       inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+                                       for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+                                       {
+                                               st[0] = _pico_little_float(inf[0]);
+                                               st[1] = _pico_little_float(inf[1]);
+                                               PicoSetSurfaceST( picoSurface, 0, i, st );
+                                       }
+                               }
+                               break;
+                       case IQM_NORMAL:
+                               if (a.format == IQM_FLOAT && a.size >= 3)
+                               {
+                                       inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+                                       for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+                                       {
+                                               normal[0] = _pico_little_float(inf[0]);
+                                               normal[1] = _pico_little_float(inf[1]);
+                                               normal[2] = _pico_little_float(inf[2]);
+                                               PicoSetSurfaceNormal( picoSurface, i, normal );
+                                       }
+                               }
+                               break;
+                       case IQM_COLOR:
+                               if (a.format == IQM_UBYTE && a.size >= 3)
+                               {
+                                       inb = (const byte*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+                                       for ( i = 0; i < m.num_vertexes; i++, inb += a.size )
+                                       {
+                                               color[0] = inb[0];
+                                               color[1] = inb[1];
+                                               color[2] = inb[2];
+                                               color[3] = (a.size>=4)?inb[3]:255;
+                                               PicoSetSurfaceColor( picoSurface, 0, i, color );
+                                       }
+                               }
+                               else if (a.format == IQM_FLOAT && a.size >= 3)
+                               {
+                                       inf = (const float*)((const char *)buffer + a.offset) + m.first_vertex*a.size;
+                                       for ( i = 0; i < m.num_vertexes; i++, inf += a.size )
+                                       {
+                                               color[0] = inf[0]*255;
+                                               color[1] = inf[1]*255;
+                                               color[2] = inf[2]*255;
+                                               color[3] = (a.size>=4)?inf[3]*255:255;
+                                               PicoSetSurfaceColor( picoSurface, 0, i, color );
+                                       }
+                               }
+                               break;
+                       case IQM_TANGENT:
+                       case IQM_BLENDINDEXES:
+                       case IQM_BLENDWEIGHTS:
+                       case IQM_CUSTOM:
+                               break;  // these attributes are not relevant.
+                       }
+               }
+       }
+
+       return picoModel;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleIQM =
+{
+       "0.1",                          /* module version string */
+       "InterQuake Model",             /* module display name */
+       "Spoike",                       /* author's name */
+       "2018-2021 FTE Team",           /* module copyright */
+       {
+               "iqm", NULL, NULL, NULL /* default extensions to use */
+       },
+       _iqm_canload,                   /* validation routine */
+       _iqm_load,                      /* load routine */
+       NULL,                           /* save validation routine */
+       NULL                            /* save routine */
+};
index 6cbf0f4c162d50916f4fec5674d42ef87011e423..6431dc2b2e236f5396c585a4f0605e518d599e09 100644 (file)
@@ -100,7 +100,8 @@ static picoModel_t *_lwo_load( PM_PARAMS_LOAD ){
        lwPolygon       *pol;
        lwPolVert       *v;
        lwVMapPt        *vm;
-       char name[ 256 ];
+       char name[256];
+       name[255] = '\0';
        int i, j, k, numverts;
 
        picoModel_t     *picoModel;
@@ -231,9 +232,9 @@ static picoModel_t *_lwo_load( PM_PARAMS_LOAD ){
                }
 
                /* detox and set shader name */
-               strncpy( name, surface->name, sizeof( name ) );
+               strncpy( name, surface->name, sizeof( name ) - 1 );
                _pico_first_token( name );
-               _pico_setfext( name, "" );
+               _pico_setfext( name, NULL );
                _pico_unixify( name );
                PicoSetShaderName( picoShader, name );
 
index 37b5466c56f712e3c36c39dd6d72aaf4dc10d667..2840949ab4e100425b14f921c67022a968478fdd 100644 (file)
@@ -56,17 +56,8 @@ typedef struct index_LUT_s
 {
        short Vert;
        short ST;
-       struct  index_LUT_s *next;
-
 } index_LUT_t;
 
-typedef struct index_DUP_LUT_s
-{
-       short ST;
-       short OldVert;
-
-} index_DUP_LUT_t;
-
 typedef struct
 {
        short s;
@@ -321,12 +312,12 @@ static int _md2_canload( PM_PARAMS_CANLOAD ){
 
 
 static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
-       int i, j, dups, dup_index;
-       index_LUT_t     *p_index_LUT, *p_index_LUT2, *p_index_LUT3;
-       index_DUP_LUT_t *p_index_LUT_DUPS;
+       int i, j, k, dups;
+       index_LUT_t     *p_index_LUT;
        md2Triangle_t   *p_md2Triangle;
 
-       char skinname[ MD2_MAX_SKINNAME ];
+       char skinname[ MD2_MAX_SKINNAME + 1 ];
+       skinname[ MD2_MAX_SKINNAME] = '\0';
        md2_t           *md2;
        md2St_t         *texCoord;
        md2Frame_t      *frame;
@@ -339,7 +330,6 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
        picoShader_t    *picoShader;
        picoVec3_t xyz, normal;
        picoVec2_t st;
-       picoColor_t color;
 
 
        /* set as md2 */
@@ -425,7 +415,7 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
        _pico_printf( PICO_VERBOSE,"Skins: %d  Verts: %d  STs: %d  Triangles: %d  Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, &skinname );
 
        // detox Skin name
-       _pico_setfext( skinname, "" );
+       _pico_setfext( skinname, NULL );
        _pico_unixify( skinname );
 
        /* create new pico model */
@@ -473,9 +463,10 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
        {
                p_index_LUT[i].Vert = -1;
                p_index_LUT[i].ST = -1;
-               p_index_LUT[i].next = NULL;
        }
 
+       index_LUT_t* p_index_LUT_dups = _pico_alloc( sizeof( index_LUT_t ) * md2->numTris * 3 ); //overallocating
+
        // Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
        dups = 0;
        for ( i = 0; i < md2->numTris; i++ )
@@ -483,78 +474,37 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
                p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + ( sizeof( md2Triangle_t ) * i ) );
                for ( j = 0; j < 3; j++ )
                {
-                       if ( p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1 ) { // No Main Entry
-                               p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
+                       const short iXYZ = p_md2Triangle->index_xyz[j];
+                       const short iST = p_md2Triangle->index_st[j];
+                       if ( p_index_LUT[iXYZ].ST == -1 ) { // No Main Entry
+                               p_index_LUT[iXYZ].ST = iST;
+                               p_index_LUT[iXYZ].Vert = iXYZ;
                        }
 
-                       else if ( p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) { // Equal to Main Entry
+                       else if ( iST == p_index_LUT[iXYZ].ST && iXYZ == p_index_LUT[iXYZ].Vert ) { // Equal to Main Entry
                                continue;
                        }
 
-                       else if ( ( p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL ) ) { // Not equal to Main entry, and no LL entry
-                               // Add first entry of LL from Main
-                               p_index_LUT2 = (index_LUT_t *)_pico_alloc( sizeof( index_LUT_t ) );
-                               if ( p_index_LUT2 == NULL ) {
-                                       _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
-                               }
-                               p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
-                               p_index_LUT2->Vert = dups;
-                               p_index_LUT2->ST = p_md2Triangle->index_st[j];
-                               p_index_LUT2->next = NULL;
-                               p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
-                               dups++;
-                       }
-                       else // Try to find in LL from Main Entry
-                       {
-                               p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
-                               while ( ( p_index_LUT2 != NULL ) && ( p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert ) ) // Walk down LL
-                               {
-                                       p_index_LUT3 = p_index_LUT2;
-                                       p_index_LUT2 = p_index_LUT2->next;
-                               }
-                               p_index_LUT2 = p_index_LUT3;
-
-                               if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) { // Found it
-                                       p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
-                                       continue;
+                       else{
+                               for( k = 0; k < dups; k++ ){ //search in dups
+                                       if( iST == p_index_LUT_dups[k].ST && iXYZ == p_index_LUT_dups[k].Vert ){
+                                               p_md2Triangle->index_xyz[j] = k + md2->numXYZ; // Make change in Tri hunk
+                                               p_md2Triangle->index_st[j] = k + md2->numXYZ; // Make change in Tri hunk
+                                               break;
+                                       }
                                }
 
-                               if ( p_index_LUT2->next == NULL ) { // Didn't find it. Add entry to LL.
-                                       // Add the Entry
-                                       p_index_LUT3 = (index_LUT_t *)_pico_alloc( sizeof( index_LUT_t ) );
-                                       if ( p_index_LUT3 == NULL ) {
-                                               _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
-                                       }
-                                       p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
-                                       p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
-                                       p_index_LUT3->ST = p_md2Triangle->index_st[j];
-                                       p_index_LUT3->next = NULL;
+                               if( k == dups ){ //add new
+                                       p_index_LUT_dups[dups].ST = iST;
+                                       p_index_LUT_dups[dups].Vert = iXYZ;
                                        p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
-                                       dups++;
+                                       p_md2Triangle->index_st[j] = dups + md2->numXYZ; // Make change in Tri hunk
+                                       ++dups;
                                }
                        }
                }
        }
 
-       // malloc and build array for Dup STs
-       p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc( sizeof( index_DUP_LUT_t ) * dups );
-       if ( p_index_LUT_DUPS == NULL ) {
-               _pico_printf( PICO_ERROR," Couldn't allocate memory!\n" );
-       }
-
-       dup_index = 0;
-       for ( i = 0; i < md2->numXYZ; i++ )
-       {
-               p_index_LUT2 = p_index_LUT[i].next;
-               while ( p_index_LUT2 != NULL )
-               {
-                       p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
-                       p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
-                       dup_index++;
-                       p_index_LUT2 = p_index_LUT2->next;
-               }
-       }
-
        // Build Picomodel
        triangle = (md2Triangle_t *) ( (picoByte_t *) ( bb + md2->ofsTris ) );
        texCoord = (md2St_t*) ( (picoByte_t *) ( bb + md2->ofsST ) );
@@ -584,55 +534,40 @@ static picoModel_t *_md2_load( PM_PARAMS_LOAD ){
                st[ 0 ] =  ( ( texCoord[p_index_LUT[i].ST].s ) / ( (float)md2->skinWidth ) );
                st[ 1 ] =  ( texCoord[p_index_LUT[i].ST].t / ( (float)md2->skinHeight ) );
                PicoSetSurfaceST( picoSurface, 0, i, st );
-       }
 
-       if ( dups ) {
-               for ( i = 0; i < dups; i++ )
-               {
-                       j = p_index_LUT_DUPS[i].OldVert;
-                       /* set vertex origin */
-                       xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
-                       xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
-                       xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
-                       PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ, xyz );
-
-                       /* set normal */
-                       normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
-                       normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
-                       normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
-                       PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ, normal );
-
-                       /* set st coords */
-                       st[ 0 ] =  ( ( texCoord[p_index_LUT_DUPS[i].ST].s ) / ( (float)md2->skinWidth ) );
-                       st[ 1 ] =  ( texCoord[p_index_LUT_DUPS[i].ST].t / ( (float)md2->skinHeight ) );
-                       PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ, st );
-               }
+               /* set color */
+               PicoSetSurfaceColor( picoSurface, 0, i, picoColor_white );
        }
 
-       /* set color */
-       PicoSetSurfaceColor( picoSurface, 0, 0, color );
-
-       // Free up malloc'ed LL entries
-       for ( i = 0; i < md2->numXYZ; i++ )
+       for ( i = 0; i < dups; i++ )
        {
-               if ( p_index_LUT[i].next != NULL ) {
-                       p_index_LUT2 = p_index_LUT[i].next;
-                       do {
-                               p_index_LUT3 = p_index_LUT2->next;
-                               _pico_free( p_index_LUT2 );
-                               p_index_LUT2 = p_index_LUT3;
-                               dups--;
-                       } while ( p_index_LUT2 != NULL );
-               }
-       }
+               const int surfN = i + md2->numXYZ;
+               vertex = &frame->verts[p_index_LUT_dups[i].Vert];
+               /* set vertex origin */
+               xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
+               xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
+               xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
+               PicoSetSurfaceXYZ( picoSurface, surfN, xyz );
+
+               /* set normal */
+               normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
+               normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
+               normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
+               PicoSetSurfaceNormal( picoSurface, surfN, normal );
+
+               j = p_index_LUT_dups[i].ST;
+               /* set st coords */
+               st[ 0 ] =  ( ( texCoord[j].s ) / ( (float)md2->skinWidth ) );
+               st[ 1 ] =  ( texCoord[j].t / ( (float)md2->skinHeight ) );
+               PicoSetSurfaceST( picoSurface, 0, surfN, st );
 
-       if ( dups ) {
-               _pico_printf( PICO_WARNING, " Not all LL mallocs freed\n" );
+               /* set color */
+               PicoSetSurfaceColor( picoSurface, 0, surfN, picoColor_white );
        }
 
        // Free malloc'ed LUTs
        _pico_free( p_index_LUT );
-       _pico_free( p_index_LUT_DUPS );
+       _pico_free( p_index_LUT_dups );
 
        /* return the new pico model */
        _pico_free( bb0 );
index d31806b7e85fb6c67e09af1c11feeb75b0db2bba..1b93c7b4d93b2fe875638332fc32510df88a2cda 100644 (file)
@@ -186,7 +186,6 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
        picoShader_t    *picoShader;
        picoVec3_t xyz, normal;
        picoVec2_t st;
-       picoColor_t color;
 
 
        /* -------------------------------------------------
@@ -341,7 +340,7 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
 
                /* detox and set shader name */
                shader = (md3Shader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
-               _pico_setfext( shader->name, "" );
+               _pico_setfext( shader->name, NULL );
                _pico_unixify( shader->name );
                PicoSetShaderName( picoShader, shader->name );
 
@@ -361,7 +360,6 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
                /* copy vertexes */
                texCoord = (md3TexCoord_t*) ( (picoByte_t *) surface + surface->ofsSt );
                vertex = (md3Vertex_t*) ( (picoByte_t*) surface + surface->ofsVertexes + surface->numVerts * frameNum * sizeof( md3Vertex_t ) );
-               _pico_set_color( color, 255, 255, 255, 255 );
 
                for ( j = 0; j < surface->numVerts; j++, texCoord++, vertex++ )
                {
@@ -387,7 +385,7 @@ static picoModel_t *_md3_load( PM_PARAMS_LOAD ){
                        PicoSetSurfaceST( picoSurface, 0, j, st );
 
                        /* set color */
-                       PicoSetSurfaceColor( picoSurface, 0, j, color );
+                       PicoSetSurfaceColor( picoSurface, 0, j, picoColor_white );
                }
 
                /* get next surface */
index 235dcecf9467c0ca90d1508e0fef403e1adf285e..ec40d5a9c842ae2fccb766505bf3dd52cee4d3ab 100644 (file)
@@ -460,7 +460,6 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
        picoShader_t        *picoShader;
        picoVec3_t xyz, normal;
        picoVec2_t st;
-       picoColor_t color;
 
 
        /* -------------------------------------------------
@@ -641,7 +640,7 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
 
                /* detox and set shader name */
                shader = (mdcShader_t*) ( (picoByte_t*) surface + surface->ofsShaders );
-               _pico_setfext( shader->name, "" );
+               _pico_setfext( shader->name, NULL );
                _pico_unixify( shader->name );
                PicoSetShaderName( picoShader, shader->name );
 
@@ -667,7 +666,6 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
                                vertexComp = (mdcXyzCompressed_t *) ( (picoByte_t *) surface + surface->ofsXyzCompressed ) + ( *mdcCompVert * surface->numVerts );
                        }
                }
-               _pico_set_color( color, 255, 255, 255, 255 );
 
                for ( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort += 4 )
                {
@@ -711,7 +709,7 @@ static picoModel_t *_mdc_load( PM_PARAMS_LOAD ){
                        PicoSetSurfaceST( picoSurface, 0, j, st );
 
                        /* set color */
-                       PicoSetSurfaceColor( picoSurface, 0, j, color );
+                       PicoSetSurfaceColor( picoSurface, 0, j, picoColor_white );
                }
 
                /* get next surface */
index 378265f30a5504d59206c95b08d6f43fb103bce7..1472de549e0d128eb31c1152ea965a780acd0557 100644 (file)
@@ -51,9 +51,6 @@
  #define DEBUG_PM_MS3D
  #define DEBUG_PM_MS3D_EX
 
-/* plain white */
-static picoColor_t white = { 255,255,255,255 };
-
 /* ms3d limits */
 const int MS3D_MAX_VERTS      = 8192;
 const int MS3D_MAX_TRIS       = 16384;
@@ -351,7 +348,7 @@ static picoModel_t *_ms3d_load( PM_PARAMS_LOAD ){
                                PicoSetSurfaceXYZ( surface,vertexIndex,vertex->xyz );
 
                                /* store vertex color */
-                               PicoSetSurfaceColor( surface,0,vertexIndex,white );
+                               PicoSetSurfaceColor( surface, 0, vertexIndex, picoColor_white );
 
                                /* store vertex normal */
                                PicoSetSurfaceNormal( surface,vertexIndex,triangle->vertexNormals[ m ] );
index 6e11a1cdbaca6875bce3d01f474b0212a690f375..7a0ebd5f4068a788900bde501de28efbb09e0c48 100644 (file)
@@ -228,9 +228,12 @@ static int _obj_mtl_load( picoModel_t *model ){
                return 0;
        }
 
-       /* helper */
+       /* helpers */
+       #define _obj_mtl_print_ok _pico_printf( PICO_NORMAL, "PICO: loading %s...OK\n", fileName )
+       #define _obj_mtl_print_fail _pico_printf( PICO_WARNING, "PICO: loading %s...FAIL\n", fileName )
        #define _obj_mtl_error_return \
        { \
+               _obj_mtl_print_fail; \
                _pico_free_parser( p ); \
                _pico_free_file( mtlBuffer ); \
                _pico_free( fileName ); \
@@ -250,9 +253,11 @@ static int _obj_mtl_load( picoModel_t *model ){
 
        /* check result */
        if ( mtlBufSize == 0 ) {
+               _obj_mtl_print_fail;
                return 1;                       /* file is empty: no error */
        }
        if ( mtlBufSize  < 0 ) {
+               _obj_mtl_print_fail;
                return 0;                       /* load failed: error */
 
        }
@@ -269,7 +274,6 @@ static int _obj_mtl_load( picoModel_t *model ){
                if ( _pico_parse( p,1 ) == NULL ) {
                        break;
                }
-#if 1
 
                /* skip empty lines */
                if ( p->token == NULL || !strlen( p->token ) ) {
@@ -309,7 +313,6 @@ static int _obj_mtl_load( picoModel_t *model ){
                /* diffuse map name */
                else if ( !_pico_stricmp( p->token,"map_kd" ) ) {
                        char *mapName;
-                       picoShader_t *shader;
 
                        /* pointer to current shader must be valid */
                        if ( curShader == NULL ) {
@@ -324,13 +327,8 @@ static int _obj_mtl_load( picoModel_t *model ){
                                _pico_printf( PICO_ERROR,"Missing material map name in MTL %s, line %d.",fileName,p->curLine );
                                _obj_mtl_error_return;
                        }
-                       /* create a new pico shader */
-                       shader = PicoNewShader( model );
-                       if ( shader == NULL ) {
-                               _obj_mtl_error_return;
-                       }
                        /* set shader map name */
-                       PicoSetShaderMapName( shader,mapName );
+                       PicoSetShaderMapName( curShader, mapName );
                }
                /* dissolve factor (pseudo transparency 0..1) */
                /* where 0 means 100% transparent and 1 means opaque */
@@ -482,12 +480,12 @@ static int _obj_mtl_load( picoModel_t *model ){
                        /* set specular color */
                        PicoSetShaderSpecularColor( curShader,color );
                }
-#endif
                /* skip rest of line */
                _pico_parse_skip_rest( p );
        }
 
        /* free parser, file buffer, and file name */
+       _obj_mtl_print_ok;
        _pico_free_parser( p );
        _pico_free_file( mtlBuffer );
        _pico_free( fileName );
@@ -564,10 +562,8 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
        PicoSetModelName( model,fileName );
        PicoSetModelFileName( model,fileName );
 
-       /* try loading the materials; we don't handle the result */
-#if 1
+       /* try loading the materials */
        _obj_mtl_load( model );
-#endif
 
        /* parse obj line by line */
        while ( 1 )
@@ -903,7 +899,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
                        {
                                shader = PicoFindShader( model, name, 1 );
                                if ( shader == NULL ) {
-                                       _pico_printf( PICO_WARNING,"Undefined material name \"%s\" in OBJ %s, line %d. Making a default shader.",name,model->fileName,p->curLine );
+                                       _pico_printf( PICO_WARNING, "Undefined material name \"%s\" in OBJ, line %d. Making a default shader.", name, p->curLine );
 
                                        /* create a new pico shader */
                                        shader = PicoNewShader( model );
@@ -922,6 +918,7 @@ static picoModel_t *_obj_load( PM_PARAMS_LOAD ){
                /* skip unparsed rest of line and continue */
                _pico_parse_skip_rest( p );
        }
+
        /* free memory used by temporary vertexdata */
        FreeObjVertexData( vertexData );
 
index a82e4b122277916d9a3c4910ab3ce22017446e1e..fb8cd89d6a4616634cb58319c59d99c9b2f6b012 100644 (file)
@@ -495,7 +495,7 @@ static picoModel_t *_terrain_load( PM_PARAMS_LOAD ) {
        }
 
        /* detox and set shader name */
-       _pico_setfext( shader, "" );
+       _pico_setfext( shader, NULL );
        _pico_unixify( shader );
        PicoSetShaderName( picoShader, shader );
        _pico_free( shader );
@@ -537,7 +537,7 @@ static picoModel_t *_terrain_load( PM_PARAMS_LOAD ) {
                                _pico_set_color( color, colorPixel[ 0 ], colorPixel[ 1 ], colorPixel[ 2 ], colorPixel[ 3 ] );
                        }
                        else{
-                               _pico_set_color( color, 255, 255, 255, 255 );
+                               _pico_copy_color( picoColor_white, color );
                        }
                        PicoSetSurfaceColor( picoSurface, 0, v, color );
 
index e3822f42283cccb147141ad4ba008b7c4211bf59..745238f3e3f6fc3b8e5f3135d066caf98147f693 100644 (file)
@@ -1,4 +1,4 @@
-add_library(profile
+add_library(profile STATIC
         file.cpp file.h
         profile.cpp profile.h
         )
index abdb32f4d4a945b84120d449c1c640c67c3ecc6e..f195ae244926adf9bdce476d6b16d6fc40f3ba16 100644 (file)
@@ -102,6 +102,23 @@ Property<T> make_property(Self &self) {
 
 // chain
 
+template<typename DST, typename SRC, typename X, typename A>
+struct make_property_chain_I_1 {
+    static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
+        PropertyImpl<SRC, DST>::Export(value, self);
+    }
+
+    static void Export(const X &self, const Callback<void(DST)> &returnz) {
+        A::Get::thunk_(self, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
+    }
+
+    static void Import(X &self, DST value) {
+        SRC out;
+        PropertyImpl<SRC, DST>::Import(out, value);
+        A::Set::thunk_(self, out);
+    }
+};
+
 template<class I_Outer, class I_Inner>
 Property<detail::propertyimpl_other<I_Outer>> make_property_chain(detail::propertyimpl_self<I_Inner> &it) {
     using DST = detail::propertyimpl_other<I_Outer>;
@@ -109,45 +126,35 @@ Property<detail::propertyimpl_other<I_Outer>> make_property_chain(detail::proper
     using X = detail::propertyimpl_self<I_Inner>;
 
     using A = property_impl<I_Inner>;
-    struct I {
-        static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
-            PropertyImpl<SRC, DST>::Export(value, self);
-        }
-
-        static void Export(const X &self, const Callback<void(DST)> &returnz) {
-            A::Get::thunk_(self, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
-        }
-
-        static void Import(X &self, DST value) {
-            SRC out;
-            PropertyImpl<SRC, DST>::Import(out, value);
-            A::Set::thunk_(self, out);
-        }
-    };
+    using I = make_property_chain_I_1<DST, SRC, X, A>;
     return make_property<PropertyAdaptor<X, DST, I>>(it);
 }
 
+template<typename DST, typename SRC, typename A>
+struct make_property_chain_I_2 {
+    static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
+        PropertyImpl<SRC, DST>::Export(value, self);
+    }
+
+    static void Export(const Callback<void(DST)> &returnz) {
+        A::Get::thunk_(nullptr, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
+    }
+
+    static void Import(DST value) {
+        SRC out;
+        PropertyImpl<SRC, DST>::Import(out, value);
+        A::Set::thunk_(nullptr, out);
+    }
+};
+
 template<class I_Outer, class I_Inner>
 Property<detail::propertyimpl_other<I_Outer>> make_property_chain() {
     using DST = detail::propertyimpl_other<I_Outer>;
     using SRC = detail::propertyimpl_self<I_Outer>;
 
     using A = property_impl_free<I_Inner>;
-    struct I {
-        static void ExportThunk(const Callback<void(DST)> &self, SRC value) {
-            PropertyImpl<SRC, DST>::Export(value, self);
-        }
-
-        static void Export(const Callback<void(DST)> &returnz) {
-            A::Get::thunk_(nullptr, ConstReferenceCaller<Callback<void(DST)>, void(SRC), ExportThunk>(returnz));
-        }
-
-        static void Import(DST value) {
-            SRC out;
-            PropertyImpl<SRC, DST>::Import(out, value);
-            A::Set::thunk_(nullptr, out);
-        }
-    };
+    using I = make_property_chain_I_2<DST, SRC, A>;
+    
     return make_property<PropertyAdaptorFree<DST, I>>();
 }
 
index 6e49527df0766e53fe87b3bddc694067ecb5c91d..0adfd1246803e20b3a8bc51a0e8e1bffb4ed99b4 100644 (file)
@@ -1,4 +1,4 @@
-add_library(script
+add_library(script STATIC
         _.cpp
         scripttokeniser.h
         scripttokenwriter.h
index 499a483805ab3e86e8cf20af65addc7b9463e28b..026c7249f735047163b9528b3ec2c4169b2996a4 100644 (file)
@@ -1,4 +1,4 @@
-add_library(signal
+add_library(signal STATIC
         isignal.h
         signal.cpp signal.h
         signalfwd.h
index 3a6b603d8fe7d4aa97a835483bd1281d4c49e637..d301f272b56abeb22b271129a390090fd5403dd4 100644 (file)
@@ -1,4 +1,4 @@
-add_library(splines
+add_library(splines STATIC
         math_angles.cpp math_angles.h
         math_matrix.cpp math_matrix.h
         math_quaternion.cpp math_quaternion.h
index f356b56943555d5586116163e983d4ad3b4cb2ff..e1916ca74d47ee0f5c1da51543e0f48a37d971d7 100644 (file)
@@ -34,50 +34,49 @@ typedef idVec3 &vec3_p;
 
 class angles_t {
 public:
-float pitch;
-float yaw;
-float roll;
+       float pitch;
+       float yaw;
+       float roll;
 
-angles_t();
-angles_t( float pitch, float yaw, float roll );
-angles_t( const idVec3 &vec );
+       angles_t();
+       angles_t( float pitch, float yaw, float roll );
+       angles_t( const idVec3 &vec );
 
-friend void     toAngles( idVec3 &src, angles_t &dst );
-friend void     toAngles( quat_t &src, angles_t &dst );
-friend void     toAngles( mat3_t &src, angles_t &dst );
+       friend void     toAngles( idVec3 &src, angles_t &dst );
+       friend void     toAngles( quat_t &src, angles_t &dst );
+       friend void     toAngles( mat3_t &src, angles_t &dst );
 
-operator vec3_p();
+       operator vec3_p();
 
-float operator[]( int index ) const;
-float&          operator[]( int index );
+       float operator[]( int index ) const;
+       float&          operator[]( int index );
 
-void            set( float pitch, float yaw, float roll );
+       void            set( float pitch, float yaw, float roll );
 
-void operator=( angles_t const &a );
-void operator=( idVec3 const &a );
+       angles_t &operator=( angles_t const &a ) = default;
+       angles_t &operator=( idVec3 const &a );
 
-friend angles_t operator+( const angles_t &a, const angles_t &b );
-angles_t        &operator+=( angles_t const &a );
-angles_t        &operator+=( idVec3 const &a );
+       friend angles_t operator+( const angles_t &a, const angles_t &b );
+       angles_t        &operator+=( angles_t const &a );
+       angles_t        &operator+=( idVec3 const &a );
 
-friend angles_t operator-( angles_t &a, angles_t &b );
-angles_t        &operator-=( angles_t &a );
+       friend angles_t operator-( angles_t &a, angles_t &b );
+       angles_t        &operator-=( angles_t &a );
 
-friend angles_t operator*( const angles_t &a, float b );
-friend angles_t operator*( float a, const angles_t &b );
-angles_t        &operator*=( float a );
+       friend angles_t operator*( const angles_t &a, float b );
+       friend angles_t operator*( float a, const angles_t &b );
+       angles_t        &operator*=( float a );
 
-friend int operator==( angles_t &a, angles_t &b );
+       friend int operator==( angles_t &a, angles_t &b );
+       friend int operator!=( angles_t &a, angles_t &b );
 
-friend int operator!=( angles_t &a, angles_t &b );
+       void            toVectors( idVec3 *forward, idVec3 *right = NULL, idVec3 *up = NULL );
+       idVec3          toForward( void );
 
-void            toVectors( idVec3 *forward, idVec3 *right = NULL, idVec3 *up = NULL );
-idVec3          toForward( void );
+       angles_t        &Zero( void );
 
-angles_t        &Zero( void );
-
-angles_t        &Normalize360( void );
-angles_t        &Normalize180( void );
+       angles_t        &Normalize360( void );
+       angles_t        &Normalize180( void );
 };
 
 extern angles_t ang_zero;
@@ -116,16 +115,11 @@ inline void angles_t::set( float pitch, float yaw, float roll ) {
        this->roll  = roll;
 }
 
-inline void angles_t::operator=( angles_t const &a ) {
-       pitch   = a.pitch;
-       yaw     = a.yaw;
-       roll    = a.roll;
-}
-
-inline void angles_t::operator=( idVec3 const &a ) {
+inline angles_t &angles_t::operator=( idVec3 const &a ) {
        pitch   = a[ 0 ];
        yaw     = a[ 1 ];
        roll    = a[ 2 ];
+       return *this;
 }
 
 inline angles_t operator+( const angles_t &a, const angles_t &b ) {
index b33f4425d28c2b6b660df07058c1ff1d56cd480b..e8341c04c1924cb299361b269ab44e7de4acc798 100644 (file)
@@ -31,44 +31,45 @@ class mat3_t;
 
 class quat_t {
 public:
-float x;
-float y;
-float z;
-float w;
+       float x;
+       float y;
+       float z;
+       float w;
 
-quat_t();
-quat_t( float x, float y, float z, float w );
+       quat_t();
+       quat_t( float x, float y, float z, float w );
+       quat_t( const quat_t & ) = default;
 
-friend void     toQuat( idVec3_t &src, quat_t &dst );
-friend void     toQuat( angles_t &src, quat_t &dst );
-friend void     toQuat( mat3_t &src, quat_t &dst );
+       friend void toQuat( idVec3_t &src, quat_t &dst );
+       friend void toQuat( angles_t &src, quat_t &dst );
+       friend void toQuat( mat3_t &src, quat_t &dst );
 
-float           *vec4( void );
+       float *vec4( void );
 
-float operator[]( int index ) const;
-float           &operator[]( int index );
+       float  operator[]( int index ) const;
+       float &operator[]( int index );
 
-void            set( float x, float y, float z, float w );
+       void set( float x, float y, float z, float w );
 
-void operator=( quat_t a );
+       quat_t &operator=( const quat_t &a ) = default;
 
-friend quat_t operator+( quat_t a, quat_t b );
-quat_t          &operator+=( quat_t a );
+       friend quat_t operator+( quat_t a, quat_t b );
+       quat_t &operator+=( quat_t a );
 
-friend quat_t operator-( quat_t a, quat_t b );
-quat_t          &operator-=( quat_t a );
+       friend quat_t operator-( quat_t a, quat_t b );
+       quat_t &operator-=( quat_t a );
 
-friend quat_t operator*( quat_t a, float b );
-friend quat_t operator*( float a, quat_t b );
-quat_t          &operator*=( float a );
+       friend quat_t operator*( quat_t a, float b );
+       friend quat_t operator*( float a, quat_t b );
+       quat_t &operator*=( float a );
 
-friend int operator==( quat_t a, quat_t b );
-friend int operator!=( quat_t a, quat_t b );
+       friend int operator==( quat_t a, quat_t b );
+       friend int operator!=( quat_t a, quat_t b );
 
-float           Length( void );
-quat_t          &Normalize( void );
+       float Length( void );
+       quat_t &Normalize( void );
 
-quat_t operator-();
+       quat_t operator-();
 };
 
 inline quat_t::quat_t() {
@@ -102,13 +103,6 @@ inline void quat_t::set( float x, float y, float z, float w ) {
        this->w = w;
 }
 
-inline void quat_t::operator=( quat_t a ) {
-       x = a.x;
-       y = a.y;
-       z = a.z;
-       w = a.w;
-}
-
 inline quat_t operator+( quat_t a, quat_t b ) {
        return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
 }
index 4fbe8d9dc5820f8071af22b13308e98aaad0288b..328ca3fea610835d3f37eeca58c27658ef0cf098 100644 (file)
@@ -124,59 +124,60 @@ static inline double idSqrt( double x ) {
 class idVec3 {
 public:
 #ifndef FAT_VEC3
-float x,y,z;
+       float x,y,z;
 #else
-float x,y,z,dist;
+       float x,y,z,dist;
 #endif
 
 #ifndef FAT_VEC3
-idVec3() {};
+       idVec3() {};
 #else
-idVec3() {dist = 0.0f; };
+       idVec3() {dist = 0.0f; };
 #endif
-idVec3( const float x, const float y, const float z );
+       idVec3( const float x, const float y, const float z );
+       idVec3( const idVec3& ) = default;
 
-operator float *();
+       operator float *();
 
-float operator[]( const int index ) const;
-float           &operator[]( const int index );
+       float operator[]( const int index ) const;
+       float &operator[]( const int index );
 
-void            set( const float x, const float y, const float z );
+       void set( const float x, const float y, const float z );
 
-idVec3 operator-() const;
+       idVec3 operator-() const;
 
-idVec3          &operator=( const idVec3 &a );
+       idVec3 &operator=( const idVec3 &a ) = default;
 
-float operator*( const idVec3 &a ) const;
-idVec3 operator*( const float a ) const;
-friend idVec3 operator*( float a, idVec3 b );
+       float operator*( const idVec3 &a ) const;
+       idVec3 operator*( const float a ) const;
+       friend idVec3 operator*( float a, idVec3 b );
 
-idVec3 operator+( const idVec3 &a ) const;
-idVec3 operator-( const idVec3 &a ) const;
+       idVec3 operator+( const idVec3 &a ) const;
+       idVec3 operator-( const idVec3 &a ) const;
 
-idVec3          &operator+=( const idVec3 &a );
-idVec3          &operator-=( const idVec3 &a );
-idVec3          &operator*=( const float a );
+       idVec3 &operator+=( const idVec3 &a );
+       idVec3 &operator-=( const idVec3 &a );
+       idVec3 &operator*=( const float a );
 
-int operator==( const idVec3 &a ) const;
-int operator!=( const idVec3 &a ) const;
+       int operator==( const idVec3 &a ) const;
+       int operator!=( const idVec3 &a ) const;
 
-idVec3          Cross( const idVec3 &a ) const;
-idVec3          &Cross( const idVec3 &a, const idVec3 &b );
+       idVec3          Cross( const idVec3 &a ) const;
+       idVec3          &Cross( const idVec3 &a, const idVec3 &b );
 
-float           Length( void ) const;
-float           Normalize( void );
+       float           Length( void ) const;
+       float           Normalize( void );
 
-void            Zero( void );
-void            Snap( void );
-void            SnapTowards( const idVec3 &to );
+       void            Zero( void );
+       void            Snap( void );
+       void            SnapTowards( const idVec3 &to );
 
-float           toYaw( void );
-float           toPitch( void );
-angles_t        toAngles( void );
-friend idVec3   LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
+       float           toYaw( void );
+       float           toPitch( void );
+       angles_t        toAngles( void );
+       friend idVec3   LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
 
-char            *string( void );
+       char            *string( void );
 };
 
 extern idVec3 vec_zero;
@@ -206,14 +207,6 @@ ID_INLINE idVec3 idVec3::operator-() const {
        return idVec3( -x, -y, -z );
 }
 
-ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) {
-       x = a.x;
-       y = a.y;
-       z = a.z;
-
-       return *this;
-}
-
 ID_INLINE void idVec3::set( const float x, const float y, const float z ) {
        this->x = x;
        this->y = y;
index 6ce79395bbb02937f8eab135bab9a1ab38f10738..ec1c9ae94751ac005dcf400eb2ce42efd9d223a7 100644 (file)
@@ -1,4 +1,4 @@
-add_library(stream
+add_library(stream STATIC
         _.cpp
         filestream.h
         memstream.h
index 4b0720a50e6891d4908b38c601794356e4c0fe93..a9c2f471a8fda5635dbaf88de546e5df76324509 100644 (file)
@@ -1,4 +1,4 @@
-add_library(string
+add_library(string STATIC
         pooledstring.cpp pooledstring.h
         string.h
         stringfwd.h
index ff7dc4536c9245ce116e612534f0d1ff826a49a6..5d63925d2c6ce14764bfa33ccfeb06eb5025665b 100644 (file)
@@ -259,50 +259,52 @@ inline char* string_to_uppercase( char* string ){
 /// \brief A re-entrant string tokeniser similar to strchr.
 class StringTokeniser
 {
-bool istoken( char c ) const {
-       if ( strchr( m_delimiters, c ) != 0 ) {
-               return false;
-       }
-       return true;
-}
-const char* advance(){
-       const char* token = m_pos;
-       bool intoken = true;
-       while ( !string_empty( m_pos ) )
-       {
-               if ( !istoken( *m_pos ) ) {
-                       *m_pos = '\0';
-                       intoken = false;
+private:
+       bool istoken( char c ) const {
+               if ( strchr( m_delimiters, c ) != 0 ) {
+                       return false;
                }
-               else if ( !intoken ) {
-                       return token;
+               return true;
+       }
+       const char* advance(){
+               const char* token = m_pos;
+               bool intoken = true;
+               while ( !string_empty( m_pos ) )
+               {
+                       if ( !istoken( *m_pos ) ) {
+                               *m_pos = '\0';
+                               intoken = false;
+                       }
+                       else if ( !intoken ) {
+                               return token;
+                       }
+                       ++m_pos;
                }
-               ++m_pos;
+               return token;
        }
-       return token;
-}
-std::size_t m_length;
-char* m_string;
-char* m_pos;
-const char* m_delimiters;
+       std::size_t m_length;
+       char* m_string;
+       char* m_pos;
+       const char* m_delimiters;
+
 public:
-StringTokeniser( const char* string, const char* delimiters = " \n\r\t\v" ) :
-       m_length( string_length( string ) ),
-       m_string( string_copy( string_new( m_length ), string ) ),
-       m_pos( m_string ),
-       m_delimiters( delimiters ){
-       while ( !string_empty( m_pos ) && !istoken( *m_pos ) )
-       {
-               ++m_pos;
+       StringTokeniser( const char* string, const char* delimiters = " \n\r\t\v" ) :
+               m_length( string_length( string ) ),
+               m_string( string_copy( string_new( m_length ), string ) ),
+               m_pos( m_string ),
+               m_delimiters( delimiters ){
+               while ( !string_empty( m_pos ) && !istoken( *m_pos ) )
+               {
+                       ++m_pos;
+               }
+       }
+       ~StringTokeniser(){
+               string_release( m_string, m_length );
+       }
+       /// \brief Returns the next token or "" if there are no more tokens available.
+       const char* getToken(){
+               return advance();
        }
-}
-~StringTokeniser(){
-       string_release( m_string, m_length );
-}
-/// \brief Returns the next token or "" if there are no more tokens available.
-const char* getToken(){
-       return advance();
-}
 };
 
 /// \brief A non-mutable c-style string.
@@ -316,40 +318,41 @@ template<typename Buffer>
 class String : public Buffer
 {
 public:
+       String()
+               : Buffer(){
+       }
+       String( const char* string )
+               : Buffer( string ){
+       }
+       String( StringRange range )
+               : Buffer( range ){
+       }
 
-String()
-       : Buffer(){
-}
-String( const char* string )
-       : Buffer( string ){
-}
-String( StringRange range )
-       : Buffer( range ){
-}
+       String(const String&) = default;
 
-String& operator=( const String& other ){
-       String temp( other );
-       temp.swap( *this );
-       return *this;
-}
-String& operator=( const char* string ){
-       String temp( string );
-       temp.swap( *this );
-       return *this;
-}
-String& operator=( StringRange range ){
-       String temp( range );
-       temp.swap( *this );
-       return *this;
-}
+       String& operator=( const String& other ){
+               String temp( other );
+               temp.swap( *this );
+               return *this;
+       }
+       String& operator=( const char* string ){
+               String temp( string );
+               temp.swap( *this );
+               return *this;
+       }
+       String& operator=( StringRange range ){
+               String temp( range );
+               temp.swap( *this );
+               return *this;
+       }
 
-void swap( String& other ){
-       Buffer::swap( other );
-}
+       void swap( String& other ){
+               Buffer::swap( other );
+       }
 
-bool empty() const {
-       return string_empty( Buffer::c_str() );
-}
+       bool empty() const {
+               return string_empty( Buffer::c_str() );
+       }
 };
 
 template<typename Buffer>
@@ -397,44 +400,45 @@ inline void swap( String<Buffer>& self, String<Buffer>& other ){
 template<typename Allocator>
 class CopiedBuffer : private Allocator
 {
-char* m_string;
+       char* m_string;
 
-char* copy_range( StringRange range ){
-       return string_clone_range( range, static_cast<Allocator&>( *this ) );
-}
-char* copy( const char* other ){
-       return string_clone( other, static_cast<Allocator&>( *this ) );
-}
-void destroy( char* string ){
-       string_release( string, string_length( string ), static_cast<Allocator&>( *this ) );
-}
+       char* copy_range( StringRange range ){
+               return string_clone_range( range, static_cast<Allocator&>( *this ) );
+       }
+       char* copy( const char* other ){
+               return string_clone( other, static_cast<Allocator&>( *this ) );
+       }
+       void destroy( char* string ){
+               string_release( string, string_length( string ), static_cast<Allocator&>( *this ) );
+       }
 
 protected:
-~CopiedBuffer(){
-       destroy( m_string );
-}
+       ~CopiedBuffer(){
+               destroy( m_string );
+       }
+
 public:
-CopiedBuffer()
-       : m_string( copy( "" ) ){
-}
-explicit CopiedBuffer( const Allocator& allocator )
-       : Allocator( allocator ), m_string( copy( "" ) ){
-}
-CopiedBuffer( const CopiedBuffer& other )
-       : Allocator( other ), m_string( copy( other.m_string ) ){
-}
-CopiedBuffer( const char* string, const Allocator& allocator = Allocator() )
-       : Allocator( allocator ), m_string( copy( string ) ){
-}
-CopiedBuffer( StringRange range, const Allocator& allocator = Allocator() )
-       : Allocator( allocator ), m_string( copy_range( range ) ){
-}
-const char* c_str() const {
-       return m_string;
-}
-void swap( CopiedBuffer& other ){
-       string_swap( m_string, other.m_string );
-}
+       CopiedBuffer()
+               : m_string( copy( "" ) ){
+       }
+       explicit CopiedBuffer( const Allocator& allocator )
+               : Allocator( allocator ), m_string( copy( "" ) ){
+       }
+       CopiedBuffer( const CopiedBuffer& other )
+               : Allocator( other ), m_string( copy( other.m_string ) ){
+       }
+       CopiedBuffer( const char* string, const Allocator& allocator = Allocator() )
+               : Allocator( allocator ), m_string( copy( string ) ){
+       }
+       CopiedBuffer( StringRange range, const Allocator& allocator = Allocator() )
+               : Allocator( allocator ), m_string( copy_range( range ) ){
+       }
+       const char* c_str() const {
+               return m_string;
+       }
+       void swap( CopiedBuffer& other ){
+               string_swap( m_string, other.m_string );
+       }
 };
 
 /// \brief A non-mutable string which uses copy-by-value for assignment.
@@ -445,65 +449,67 @@ typedef String< CopiedBuffer< DefaultAllocator<char> > > CopiedString;
 template<typename Allocator>
 class SmartBuffer : private Allocator
 {
-char* m_buffer;
-
-char* copy_range( StringRange range ){
-       char* buffer = Allocator::allocate( sizeof( std::size_t ) + ( range.last - range.first ) + 1 );
-       strncpy( buffer + sizeof( std::size_t ), range.first, range.last - range.first );
-       buffer[sizeof( std::size_t ) + ( range.last - range.first )] = '\0';
-       *reinterpret_cast<std::size_t*>( buffer ) = 0;
-       return buffer;
-}
-char* copy( const char* string ){
-       char* buffer = Allocator::allocate( sizeof( std::size_t ) + string_length( string ) + 1 );
-       strcpy( buffer + sizeof( std::size_t ), string );
-       *reinterpret_cast<std::size_t*>( buffer ) = 0;
-       return buffer;
-}
-void destroy( char* buffer ){
-       Allocator::deallocate( buffer, sizeof( std::size_t ) + string_length( c_str() ) + 1 );
-}
+private:
+       char* m_buffer;
+
+       char* copy_range( StringRange range ){
+               char* buffer = Allocator::allocate( sizeof( std::size_t ) + ( range.last - range.first ) + 1 );
+               strncpy( buffer + sizeof( std::size_t ), range.first, range.last - range.first );
+               buffer[sizeof( std::size_t ) + ( range.last - range.first )] = '\0';
+               *reinterpret_cast<std::size_t*>( buffer ) = 0;
+               return buffer;
+       }
+       char* copy( const char* string ){
+               char* buffer = Allocator::allocate( sizeof( std::size_t ) + string_length( string ) + 1 );
+               strcpy( buffer + sizeof( std::size_t ), string );
+               *reinterpret_cast<std::size_t*>( buffer ) = 0;
+               return buffer;
+       }
+       void destroy( char* buffer ){
+               Allocator::deallocate( buffer, sizeof( std::size_t ) + string_length( c_str() ) + 1 );
+       }
 
-void incref( char* buffer ){
-       ++( *reinterpret_cast<std::size_t*>( buffer ) );
-}
-void decref( char* buffer ){
-       if ( --( *reinterpret_cast<std::size_t*>( buffer ) ) == 0 ) {
-               destroy( buffer );
+       void incref( char* buffer ){
+               ++( *reinterpret_cast<std::size_t*>( buffer ) );
+       }
+       void decref( char* buffer ){
+               if ( --( *reinterpret_cast<std::size_t*>( buffer ) ) == 0 ) {
+                       destroy( buffer );
+               }
        }
-}
 
 protected:
-~SmartBuffer(){
-       decref( m_buffer );
-}
+       ~SmartBuffer(){
+               decref( m_buffer );
+       }
+
 public:
-SmartBuffer()
-       : m_buffer( copy( "" ) ){
-       incref( m_buffer );
-}
-explicit SmartBuffer( const Allocator& allocator )
-       : Allocator( allocator ), m_buffer( copy( "" ) ){
-       incref( m_buffer );
-}
-SmartBuffer( const SmartBuffer& other )
-       : Allocator( other ), m_buffer( other.m_buffer ){
-       incref( m_buffer );
-}
-SmartBuffer( const char* string, const Allocator& allocator = Allocator() )
-       : Allocator( allocator ), m_buffer( copy( string ) ){
-       incref( m_buffer );
-}
-SmartBuffer( StringRange range, const Allocator& allocator = Allocator() )
-       : Allocator( allocator ), m_buffer( copy_range( range ) ){
-       incref( m_buffer );
-}
-const char* c_str() const {
-       return m_buffer + sizeof( std::size_t );
-}
-void swap( SmartBuffer& other ){
-       string_swap( m_buffer, other.m_buffer );
-}
+       SmartBuffer()
+               : m_buffer( copy( "" ) ){
+               incref( m_buffer );
+       }
+       explicit SmartBuffer( const Allocator& allocator )
+               : Allocator( allocator ), m_buffer( copy( "" ) ){
+               incref( m_buffer );
+       }
+       SmartBuffer( const SmartBuffer& other )
+               : Allocator( other ), m_buffer( other.m_buffer ){
+               incref( m_buffer );
+       }
+       SmartBuffer( const char* string, const Allocator& allocator = Allocator() )
+               : Allocator( allocator ), m_buffer( copy( string ) ){
+               incref( m_buffer );
+       }
+       SmartBuffer( StringRange range, const Allocator& allocator = Allocator() )
+               : Allocator( allocator ), m_buffer( copy_range( range ) ){
+               incref( m_buffer );
+       }
+       const char* c_str() const {
+               return m_buffer + sizeof( std::size_t );
+       }
+       void swap( SmartBuffer& other ){
+               string_swap( m_buffer, other.m_buffer );
+       }
 };
 
 /// \brief A non-mutable string which uses copy-by-reference for assignment of SmartString.
@@ -512,9 +518,9 @@ typedef String< SmartBuffer< DefaultAllocator<char> > > SmartString;
 class StringEqualNoCase
 {
 public:
-bool operator()( const CopiedString& key, const CopiedString& other ) const {
-       return string_equal_nocase( key.c_str(), other.c_str() );
-}
+       bool operator()( const CopiedString& key, const CopiedString& other ) const {
+               return string_equal_nocase( key.c_str(), other.c_str() );
+       }
 };
 
 struct StringLessNoCase
diff --git a/libs/transformpath/CMakeLists.txt b/libs/transformpath/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5d3d0aa
--- /dev/null
@@ -0,0 +1,3 @@
+add_library(transformpath STATIC
+        transformpath.cpp transformpath.h
+        )
diff --git a/libs/transformpath/transformpath.cpp b/libs/transformpath/transformpath.cpp
new file mode 100644 (file)
index 0000000..67e482e
--- /dev/null
@@ -0,0 +1,443 @@
+/* SPDX-License-Identifier: MIT License
+
+Copyright © 2021 Thomas “illwieckz” Debesse
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the “Software”),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. */
+
+/* transformpath: transform file path based on keywords.
+
+This is not an environment variable parser, this only supports
+a set of keywords using common environment name syntax when it
+exists to make the strings easier to read.
+
+Supported substitution keywords,
+Windows:
+
+- %HOMEPATH%
+- %USERPROFILE%
+- %ProgramFiles%
+- %ProgramFiles(x86)%
+- %ProgramW6432%
+- %APPDATA%
+- [CSIDL_MYDOCUMENTS]
+
+Supported substitution keywords,
+Linux, FreeBSD, macOS:
+
+- ~
+- ${HOME}
+
+Supported substitution keywords,
+Linux, FreeBSD, other XDG systems:
+
+- ${XDG_CONFIG_HOME}
+- ${XDG_DATA_HOME}
+
+Examples,
+game engine directories:
+
+- Windows: %ProgramFiles%\Unvanquished
+- Linux: ${XDG_DATA_HOME}/unvanquished/base
+- macOS: ${HOME}/Games/Unvanquished
+
+Examples,
+game home directories:
+
+- Windows: [CSIDL_MYDOCUMENTS]\My Games\Unvanquished
+- Linux: ${XDG_DATA_HOME}/unvanquished
+- macOS: ${HOME}/Application Data/Unvanquished
+
+*/
+
+#include "globaldefs.h"
+#include "stringio.h"
+
+#include <cstring>
+#include <string>
+
+#if GDEF_OS_WINDOWS
+#include <windows.h>
+#include <iostream>
+#include <shlobj.h>
+#pragma comment(lib, "shell32.lib")
+#endif // !GDEF_OS_WINDOWS
+
+#if GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#endif // !GDEF_OS_LINUX && !GDEF_OS_BSD && !GDEF_OS_MACOS
+
+#if GDEF_OS_WINDOWS
+static std::string getUserProfilePath();
+#endif // !GDEF_OS_WINDOWS
+
+static std::string getUserName()
+{
+#if GDEF_OS_WINDOWS
+       std::string path( getenv( "USERNAME" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%USERNAME\% not found.\n";
+
+       return "";
+#endif // !GDEF_OS_WINDOWS
+
+#if GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+       std::string path( getenv( "USERNAME" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "${USERNAME} not found, guessing…\n";
+
+       path = std::string( getenv( "LOGNAME" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "${LOGNAME} not found, guessing…\n";
+
+       path = std::string( getenv( "USER" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "${USER} not found.\n";
+
+       return "";
+#endif // !GDEF_OS_LINUX && !GDEF_OS_BSD && !GDEF_OS_MACOS
+}
+
+static std::string getHomePath()
+{
+#if GDEF_OS_WINDOWS
+       std::string path( getenv( "HOMEPATH" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%HOMEPATH\% not found, guessing…\n";
+
+       std::string path1 = getUserProfilePath();
+
+       if ( ! path1.empty() )
+       {
+               return path1;
+       }
+
+       globalErrorStream() << "\%HOMEPATH\% not found.\n";
+
+       return "";
+#endif // !GDEF_OS_WINDOWS
+
+#if GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+       // Get the path environment variable.
+       std::string path( getenv( "HOME" ) );
+
+       // Look up path directory in password database.
+       if( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "${HOME} not found, guessing…\n";
+
+       static char     buf[ 4096 ];
+       struct passwd pw, *pwp;
+
+       if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 )
+       {
+               return std::string( pw.pw_dir );
+       }
+
+       globalErrorStream() << "${HOME} not found, guessing…\n";
+
+       std::string path1( "/home/" );
+
+       std::string path2 = getUserName();
+
+       if ( ! path2.empty() )
+       {
+               return path1 + path2;
+       }
+
+       globalErrorStream() << "${HOME} not found…\n";
+
+       return "";
+#endif // !GDEF_OS_LINUX && !GDEF_OS_BSD && !GDEF_OS_MACOS
+}
+
+#if GDEF_OS_WINDOWS
+static std::string getSystemDrive()
+{
+       std::string path( getenv( "SYSTEMDRIVE" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%SYSTEMDRIVE\% not found, guessing…\n";
+
+       return "C:";
+}
+
+static std::string getUserProfilePath()
+{
+       std::string path( getenv( "USERPROFILE" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%USERPROFILE\% not found, guessing…\n";
+
+       std::string path1 = getSystemDrive();
+       std::string path2 = getUserName();
+
+       if ( ! path2.empty() )
+       {
+               return path1 + "\\Users\\" + path2;
+       }
+
+       globalErrorStream() << "\%USERPROFILE\% not found.\n";
+
+       return "";
+}
+
+static std::string getProgramFilesPath()
+{
+       std::string path( getenv( "ProgramFiles" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%ProgramFiles\% not found, guessing…\n";
+
+       std::string path1 = getSystemDrive();
+       return path1 + "\\Program Files";
+}
+
+static std::string getProgramFilesX86Path()
+{
+       std::string path( getenv( "ProgramFiles(x86)" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%ProgramFiles(x86)\% not found, guessing…\n";
+
+       return getProgramFilesPath();
+}
+
+static std::string getProgramW6432Path()
+{
+       std::string path( getenv( "ProgramW6432" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%ProgramW6432\% not found, guessing…\n";
+
+       return getProgramFilesPath();
+}
+
+static std::string getAppDataPath()
+{
+       std::string path( getenv( "APPDATA" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       globalErrorStream() << "\%APPDATA\% not found, guessing…\n";
+
+       std::string path1 = getUserProfilePath();
+
+       if ( ! path1.empty() )
+       {
+               return path1 + "\\AppData\\Roaming";
+       }
+
+       globalErrorStream() << "\%APPDATA\% not found.\n";
+
+       return std::string( "" );
+}
+
+/* TODO: see also qFOLDERID_SavedGames in mainframe.cpp,
+HomePaths_Realise and other things like that,
+they look to be game paths, not NetRadiant paths. */
+
+static std::string getMyDocumentsPath()
+{
+       CHAR path[ MAX_PATH ];
+       HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path);
+
+       if ( result == S_OK )
+       {
+               return std::string( path );
+       }
+
+       globalErrorStream() << "[CSIDL_MYDOCUMENTS] not found, guessing…\n";
+
+       std::string path1 = getHomePath();
+
+       if ( ! path1.empty() )
+       {
+               path1 += "\\Documents";
+               
+               return path1;
+       }
+
+       globalErrorStream() << "[CSIDL_MYDOCUMENTS] not found.\n";
+
+       return "";
+}
+#endif // !GDEF_OS_WINDOWS
+
+#if GDEF_OS_XDG
+static std::string getXdgConfigHomePath()
+{
+       /* FIXME: we may want to rely on g_get_user_config_dir()
+       provided by GLib. */
+       std::string path ( getenv( "XDG_CONFIG_HOME" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       // This is not an error.
+       // globalErrorStream() << "${XDG_CONFIG_HOME} not found, guessing…\n";
+
+       std::string path1 = getHomePath();
+
+       if ( ! path1.empty() )
+       {
+               return path1 + "/.config";
+       }
+
+       globalErrorStream() << "${XDG_CONFIG_HOME} not found.\n";
+
+       return "";
+}
+
+static std::string getXdgDataHomePath()
+{
+       std::string path ( getenv( "XDG_DATA_HOME" ) );
+
+       if ( ! path.empty() )
+       {
+               return path;
+       }
+
+       // This is not an error.
+       // globalErrorStream() << "${XDG_DATA_HOME} not found, guessing…\n";
+
+       std::string path1 = getHomePath();
+
+       if ( ! path1.empty() )
+       {
+               return path1 + "/.local/share";
+       }
+
+       globalErrorStream() << "${XDG_DATA_HOME} not found.\n";
+
+       return "";
+}
+#endif // GDEF_OS_XDG
+
+struct pathTransformer_t
+{
+       std::string pattern;
+       std::string ( *function )();
+};
+
+static const pathTransformer_t pathTransformers[] =
+{
+#if GDEF_OS_WINDOWS
+       { "\%HOMEPATH\%", getHomePath },
+       { "\%USERPROFILE\%", getUserProfilePath },
+       { "\%ProgramFiles\%", getProgramFilesPath },
+       { "\%ProgramFiles(x86)\%", getProgramFilesX86Path },
+       { "\%ProgramW6432\%", getProgramW6432Path },
+       { "\%APPDATA\%", getAppDataPath },
+       { "[CSIDL_MYDOCUMENTS]", getMyDocumentsPath },
+#endif // GDEF_OS_WINDOWS
+
+#if GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+       { "~", getHomePath },
+       { "${HOME}", getHomePath },
+#endif // GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+
+#if GDEF_OS_XDG
+       { "${XDG_CONFIG_HOME}", getXdgConfigHomePath },
+       { "${XDG_DATA_HOME}", getXdgDataHomePath },
+#endif // GDEF_OS_XDG
+};
+
+/* If no transformation succeeds, the path will be returned untransformed. */
+std::string transformPath( std::string transformedPath )
+{
+       for ( const pathTransformer_t &pathTransformer : pathTransformers )
+       {
+               if ( transformedPath.find( pathTransformer.pattern, 0 ) == 0 )
+               {
+                       globalOutputStream() << "Path Transforming: '" << transformedPath.c_str() << "'\n";
+
+                       std::string path = pathTransformer.function();
+
+                       if ( ! path.empty() )
+                       {
+                               transformedPath.replace( 0, pathTransformer.pattern.length(), path );
+
+                               globalOutputStream() << "Path Transformed: '" << transformedPath.c_str() << "'\n";
+
+                               return transformedPath;
+                       }
+
+                       break;
+               }
+       }
+
+       globalErrorStream() << "Path not transformed: '" << transformedPath.c_str() << "'\n";
+
+       return transformedPath;
+}
diff --git a/libs/transformpath/transformpath.h b/libs/transformpath/transformpath.h
new file mode 100644 (file)
index 0000000..172971a
--- /dev/null
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT License
+
+Copyright © 2021 Thomas “illwieckz” Debesse
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the “Software”),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. */
+
+/* marker */
+#ifndef TRANSFORMPATH_H
+#define TRANSFORMPATH_H
+
+#include <string>
+
+std::string transformPath( std::string transformedPath );
+
+#endif // TRANSFORMPATH_H
index 080376b1b665dad1aee7f06f78e363efdce743b6..cfa957584d4d0b7ac844362de61d87e6c694a1bc 100644 (file)
@@ -1,4 +1,4 @@
-add_library(uilib
+add_library(uilib STATIC
         uilib.cpp
         )
 
index 1f4acb1fc7fec334f8501cd33d285bea319d40e3..8a34ded32e95a139519765e1638c5f1b4c43d1fe 100644 (file)
@@ -87,6 +87,16 @@ namespace ui {
     void IWidget::visible(bool shown)
     {
         if (shown) {
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+            /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+            GtkWidget* glwidget = GTK_WIDGET( g_object_get_data( G_OBJECT( this ), "glwidget" ) );
+            if ( glwidget ){
+                gtk_widget_hide( glwidget );
+                gtk_widget_show( glwidget );
+            }
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
+
             this.show();
         } else {
             this.hide();
@@ -260,6 +270,11 @@ namespace ui {
         gtk_box_pack_end(this, child, expand, fill, padding);
     }
 
+    void IBox::set_child_packing(ui::Widget child, bool expand, bool fill, unsigned int padding, ui::Packing packing)
+    {
+        gtk_box_set_child_packing(this, child, expand, fill, padding, (GtkPackType) packing);
+    }
+
     IMPL(VBox, GTK_VBOX);
 
     VBox::VBox(bool homogenous, int spacing) : VBox(GTK_VBOX(gtk_vbox_new(homogenous, spacing)))
@@ -311,6 +326,8 @@ namespace ui {
         gtk_text_buffer_set_text(buffer, str, -1);
     }
 
+    IMPL(TreeView, GTK_TREE_VIEW);
+
     TreeView::TreeView(ui::New_t) : TreeView(GTK_TREE_VIEW(gtk_tree_view_new()))
     {}
 
@@ -423,7 +440,7 @@ namespace ui {
 
 #if GTK_TARGET == 3
 
-    IMPL(GLArea, (void *));
+    IMPL(GLArea, GTK_GL_AREA);
 
 #elif GTK_TARGET == 2
 
index d795b75834659eff96b1e79d1514837f152b3d32..d8f41c85d88559371a36f86c2ed90a33235537c3 100644 (file)
@@ -103,6 +103,11 @@ namespace ui {
         NEVER
     };
 
+       enum class Packing {
+               START,
+               END
+       };
+
     namespace details {
 
         enum class Convert {
@@ -376,6 +381,7 @@ namespace ui {
     ,
          void pack_start(ui::Widget child, bool expand, bool fill, unsigned int padding);
          void pack_end(ui::Widget child, bool expand, bool fill, unsigned int padding);
+         void set_child_packing(ui::Widget child, bool expand, bool fill, unsigned int padding, ui::Packing packing);
     );
 
     WRAP(VBox, Box, _GtkVBox, (),
@@ -585,7 +591,7 @@ namespace ui {
     alert_response alert(
             Window parent,
             std::string text,
-            std::string title = "NetRadiant",
+            std::string title = RADIANT_NAME,
             alert_type type = alert_type::OK,
             alert_icon icon = alert_icon::Default
     );
index 96e1e216fe43971c4a656d3794e9c27e287a3ff0..cd0b040af7bd1ce239089e0173beefbff5302dce 100644 (file)
@@ -1,4 +1,4 @@
-add_library(xmllib
+add_library(xmllib STATIC
         ixml.h
         xmlelement.h
         xmlparser.h
index 00f57a057ac2337eec22fa81e6e8bd247793fbf3..3d6665f21e7846bb5d944ecea4f17155d403c2b2 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <string>
 
-#include "qerplugin.h"
 #include "stream/stringstream.h"
 
 XmlTagBuilder::XmlTagBuilder(){
diff --git a/merge-from-zerowing.sh b/merge-from-zerowing.sh
deleted file mode 100755 (executable)
index e8dc07e..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-basecommit=`git log --pretty=format:%H --grep=::zerowing-base`
-baserev=`git log --pretty=format:%s --grep=::zerowing-base | cut -d = -f 2 | cut -d ' ' -f 1`
-
-newbaserev=`svn info https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/ | grep ^Revision | cut -d ' ' -f 2`
-
-echo "$baserev -> $newbaserev"
-
-merge()
-{
-       if ! svn diff -r"$baserev":"$newbaserev" "$1" | git apply --reject --ignore-space-change --directory="$2"; then
-               if find . -name \*.rej | grep .; then
-                       echo "you have to fix these conflicts"
-                       bash
-                       echo "succeeded?"
-                       read -r LINE
-                       if [ x"$LINE" != x"y" ]; then
-                               exit 1
-                       fi
-               fi
-       fi
-}
-
-# GtkRadiant 1.5 changes
-git clean  -xdf
-
-# ZeroRadiant's q3map2 changes
-merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/1.5 /
-merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk/tools/quake3 tools/quake3
-merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk/libs/picomodel libs/picomodel
-
-git commit -a -m"::zerowing-base=$newbaserev" -e
diff --git a/mingw-Makefile.conf b/mingw-Makefile.conf
deleted file mode 100644 (file)
index a128182..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# Usage:
-# copy this file to Makefile.conf
-# edit the paths in here
-
-# how to get pkg-config
-PKGCONFIG ?= $(RADIANT_DEPENDENCIES_PREFIX)/gtk/bin/pkg-config.exe
-
-# extra utils
-GIT ?= $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/git
-SVN ?= $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/svn
-
-# these two need the "start" workaround, or they seem to crash (TODO figure out why)
-WGET ?= start $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/wget
-UNZIPPER ?= start $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/unzip
-
-# use mingw32
-include mingw-Makefile.inc
-include mingw-radiantdeps-Makefile.inc
diff --git a/mingw-Makefile.inc b/mingw-Makefile.inc
deleted file mode 100644 (file)
index d72cfe2..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# how to call the mingw tools
-MINGW_EXEC_PREFIX ?=
-
-# set the environment for make
-OS = Win32
-
-#CPPFLAGS_XML =
-#LIBS_XML = -lxml2
-
-CC = $(MINGW_EXEC_PREFIX)gcc
-CXX = $(MINGW_EXEC_PREFIX)g++
-LDD =
-RANLIB = $(MINGW_EXEC_PREFIX)ranlib
-AR = $(MINGW_EXEC_PREFIX)ar
-WINDRES = $(MINGW_EXEC_PREFIX)windres
diff --git a/mingw-fedora-Makefile.conf b/mingw-fedora-Makefile.conf
deleted file mode 100644 (file)
index d957d4d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# Usage:
-# copy this file to Makefile.conf
-# edit the paths in here
-
-# how to call the mingw tools
-MINGW_TARGET_ARCH=i686
-#MINGW_TARGET_ARCH=x86_64
-MINGW_EXEC_PREFIX = $(MINGW_TARGET_ARCH)-w64-mingw32-
-
-# use custom pkg-config
-PKGCONFIG = $(MINGW_EXEC_PREFIX)pkg-config
-
-# use custom dll install script
-DLLINSTALL = install-dlls-fedora.sh
-
-# use mingw32
-include mingw-Makefile.inc
diff --git a/mingw-radiantdeps-Makefile.inc b/mingw-radiantdeps-Makefile.inc
deleted file mode 100644 (file)
index 82e750e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# where the dependencies package is extracted
-RADIANT_DEPENDENCIES_PREFIX = $(HOME)/netradiant-dependencies-mingw32/
-
-# run the prefix fixing tool
-IGNORETHIS := $(shell cd $(RADIANT_DEPENDENCIES_PREFIX) && ./fixprefix.sh)
-
-# set the environment for make
-CFLAGS +=
-CXXFLAGS +=
-CPPFLAGS += -I$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/include
-LDFLAGS += -L$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/lib
-CPPFLAGS += -I$(RADIANT_DEPENDENCIES_PREFIX)/gtk/include
-LDFLAGS += -L$(RADIANT_DEPENDENCIES_PREFIX)/gtk/lib
-PKG_CONFIG_PATH := $(RADIANT_DEPENDENCIES_PREFIX)/gtk/lib/pkgconfig:$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/lib/pkgconfig:$(PKG_CONFIG_PATH)
-WHICHDLL = $(RADIANT_DEPENDENCIES_PREFIX)/whichdll.sh
diff --git a/oldstuff/.patchsets b/oldstuff/.patchsets
new file mode 100644 (file)
index 0000000..cebd1b5
--- /dev/null
@@ -0,0 +1,3 @@
+master = https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/1.5
+revisions_applied = 1-327
+
diff --git a/oldstuff/COMPILING b/oldstuff/COMPILING
new file mode 100644 (file)
index 0000000..29a707c
--- /dev/null
@@ -0,0 +1,95 @@
+
+developer documentation for NetRadiant
+======================================
+
+(NOTE: outdated stuff has been ROT13ed)
+
+getting the source
+==================
+
+The latest source is available from the git repository.
+  git://git.icculus.org/divverent/netradiant.git
+
+The git client can be obtained from the Subversion site.
+  http://git-scm.org
+
+To get a copy of the source using the commandline git client:
+  Change the current directory to the desired location for the source.
+  git clone git://git.icculus.org/divverent/netradiant.git
+  cd netradiant
+
+
+
+Linux(using X-windows)
+======================
+
+environment:
+- gcc >= version 3.1 (preferably)
+- GNU make
+- svn >= 1.1 (some build steps use svn)
+
+dependencies:
+- gtk+ >= 2.4.0 (requires glib, atk, pango, iconv, etc)
+- gtkglext >= 1.0.0 (requires opengl)
+- libxml2 >= 2.0.0
+- zlib >= 1.2.0 (for archivezip module)
+- libpng >= 1.2.0 (for imagepng module)
+
+build:
+run 'make'
+
+run:
+Execute 'install/radiant.x86'
+
+OSX(using X-windows)
+====================
+
+environment:
+- OS X 10.5 or 10.6
+- Xcode developer tools installed (OSX DVD)
+- X11 (from the OS X DVD)
+- MacPorts or fink or homebrew installed
+- the following packages installed:
+  Macports:
+    gtkglext pkgconfig glib2-devel libxml2 gtk2 pango atk gettext wget
+  Fink:
+    gtkglext1 pkgconfig glib2-dev libxml2 gtk+2 gtk+2-dev pango1-xft2-ft219-dev atk1 gettext-dev wget
+  homebrew:
+    gtk+ gtkglext
+
+build:
+run 'make'
+
+homebrew build:
+run 'export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig
+make'
+
+run:
+Switch into the install folder, and run NetRadiant.app
+
+Win32 (2000, XP, Vista or Windows 7)
+==================
+
+environment:
+- MinGW (http://www.mingw.org/wiki/Getting_Started)
+  Install this to c:\mingw, and select the components C compiler, C++ compiler
+  and MSYS Basic System
+- Start the MSYS shell once, then exit it
+- Prepackaged Radiant dependencies (Gtk and other stuff):
+  http://www.icculus.org/netradiant/files/netradiant-dependencies-mingw32-20101211-7z.exe
+  Extract this one to
+  c:\mingw\msys\1.0\home\username
+  (if you do this with 7zip, keep the "netradiant-dependencies-mingw32" folder
+  name of the contents)
+- now download the source from the MSYS shell, if you don't already have it:
+  ~/netradiant-dependencies-mingw32/util/bin/git clone git://git.icculus.org/divverent/netradiant.git
+
+build:
+- Start the MSYS shell
+- Switch to the directory with NetRadiant source
+- make MAKEFILE_CONF=mingw-Makefile.conf
+
+run:
+- in the "install" directory, double click netradiant.exe
+- if you get a DLL not found error, copy the DLL from either c:\mingw\bin or
+  from c:\mingw\msys\1.0\bin to the "install" directory
diff --git a/oldstuff/CONTRIBUTORS b/oldstuff/CONTRIBUTORS
new file mode 100644 (file)
index 0000000..cee478d
--- /dev/null
@@ -0,0 +1,93 @@
+GtkRadiant past contributors and credits
+last update: 01/15/2001
+
+GtkRadiant 1.5 development:
+-------
+Thomas "namespace" Nitschke spam@codecreator.net
+Stefan "Shaderman" Greven
+"Topsun"
+SmallPileofGibs spog@planetquake.com
+"Tr3b"
+
+Small contributions and improvements for 1.5
+--------
+Eric "eb" Barth
+
+Loki
+----
+Leonardo Zide leo@lokigames.com
+Mike Phillips (Loki QA)
+Bernd Kreimeier (overall coordination)
+
+QER.com
+-------
+TTimo timo@idsoftware.com
+^Fishman (Pablo Zurita) fish@gamedesign.net
+RR2DO2 rr2do2@q3f.com
+SmallPileofGibs spog@planetquake.com
+
+Curry plugin
+------------
+Mike "mickey" Jackman
+Tim "Maj" Rennie
+
+PrtView plugin, various bug fixes and q3map guru
+------------------------------------------------
+Geoffrey DeWan
+
+Gensurf plugin
+--------------
+David Hyde
+
+PicoModel
+---------
+seaw0lf with assist by ydnar
+
+Q3Map2
+------
+Randy 'ydnar' Reddig
+
+Updated shader files, textures, entities.def, keyboard shortcut list
+overall testing and feedback
+----------------------------
+Jean-Francois "Eutectic" Groleau
+
+Improvements and bug fixing
+---------------------------
+Jan Paul "MrElusive" van Waveren
+Robert Duffy
+Forest "LordHavoc" Wroncy-Hale
+Nurail
+AcidDeath
+Chronos
+Michael Schlueter
+Jamie Wilkinson
+Robert "Tr3B" Beckebans
+
+Web
+---
+Dave "Bargle" Koenig
+Jason "Wolfen" Spencer
+Shawn "EvilTypeGuy" Walker
+
+Thanks to John Hutton, AstroCreep and W2k for web help
+
+FAQ
+---
+Equim and Wex
+
+
+Testing/Feedback
+---
+Black_Dog, d0nkey, Fjoggis, Jago, jetscreamer, gibbie, Godmil, Gom Jabbar,
+Mindlink, mslaf, necros, Promit, Ravo, RPG, scampie, sock, sponge, thiste,
+voodoochopsticks, Zwiffle
+
+
+Misc
+----
+Thanks to everyone on the beta mailing list and
+irc.telefragged.com #qeradiant for testing and feedback.
+Updated icons by AstroCreep!
+Bitch-slapping by RaYGunn!
+Last minute bugs by SPoG! (SPoG--)
diff --git a/oldstuff/ChangeLog b/oldstuff/ChangeLog
new file mode 100644 (file)
index 0000000..40bd4d0
--- /dev/null
@@ -0,0 +1,279 @@
+2009-04-26 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: minimap generation for Nexuiz
+       * q3map2: better progress indicators
+
+2009-04-23 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: misc_model spawnflag 64 turns off normal smoothing
+       * q3map2: improved output of vis
+
+2009-04-21 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: more MAX_MAP_VISIBILITY
+
+2009-04-15 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: new toolbar bitmaps by sev
+
+2009-04-13 Rudolf Polzer divVerent(at)alientrap.org
+       * all: fix some MSVC compile errors
+
+2009-04-10 Rudolf Polzer divVerent(at)alientrap.org
+       * all: add WarsowPack
+       * q3map2: add alias _shadeangle to _smoothnormals
+       * q3map2: fix crash in reading RBSP files
+
+2009-04-09 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: fix font size handling
+
+2009-04-08 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: force disable composition on Vista (should fix "white 3D window" issues)
+
+2009-04-05 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: fix ViewSide command (no longer does the same as ViewTop)
+       * q3map2: generate origin brushes when decompiling
+       * q3map2: allow more portals per leaf, to help with -bsp -deep
+
+2009-04-04 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: -bsp -deep also including detail brushes into the BSP tree at lowest priority, should give higher fps while increasing compile time and BSP size
+       * q3map2: fix crash when decompiling to .map
+
+2009-04-03 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: -vis -mergeportals speeding up vis a lot, while not making vis much worse
+
+2009-04-02 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: portable radiant: when a subdir "settings" exists where radiant.exe resides, config is stored there so you can take it with you on a USB stick
+
+2009-04-01 Rudolf Polzer divVerent(at)alientrap.org
+       * all: compile fix on Win64
+
+2009-03-31 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: merged feature -bsp -altsplit (27), alternate way to weight BSP splits, should give higher fps in original Q3 engine (needs testing)
+       * q3map2: also compare shaders when comparing surfaces for sorting (27)
+       * q3map2: misc_model spawnflag 32 copies vertex alpha from color, for terrain blending on models (27)
+
+2009-03-29 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: _ls key shorthand for _lighmapscale (VorteX)
+       * q3map2: -samplescale switch (VorteX)
+       * q3map2: in dq and prophecy games, func_wall casts shadows by default (VorteX)
+       * q3map2: some more prints (VorteX)
+       * q3map2: q3map_floodlight <red> <green> <blue> <distance> <brightness> <power> shader keyword (VorteX)
+       * q3map2: more MAX_TW_VERTS (VorteX)
+       * q3map2: _patchMeta 1 entity keyword (VorteX)
+       * q3map2: q3map_deprecateShader <newershader> shader keyword (VorteX)
+       * q3map2: tangentspace deluxemaps (-deluxemode 1) (VorteX)
+       * q3map2: _smoothnormals entity key to easier set shadeangle (VorteX)
+       * q3map2: -keeplights switch in -light (VorteX)
+       * q3map2: spawnflag 32 on light: unnormalized color (VorteX)
+       * q3map2: spawnflag 64 on light: distance falloff (VorteX)
+       * q3map2: option -gridscale, -gridambientscale (VorteX)
+
+2009-03-27 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: fix a crash on "regroup entities"
+
+2009-03-25 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: editable keyboard shortcuts
+
+2009-03-23 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: avoid a crash if a surface is huge
+
+2009-03-20 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: command line option -celshader
+       * q3map2: let Q_mkdir create all parent directories too
+       * q3map2: fix some crashes
+
+2009-03-16 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: command line option -fs_homebase
+
+2009-03-13 Rudolf Polzer divVerent(at)alientrap.org
+       * all: support objs without material groups
+
+2009-03-11 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: detect being installed inside Q2World
+
+2009-03-08 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: indicate the direction of the clip plane in the 2D view
+
+2009-03-11 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: detect being installed inside Nexuiz
+
+2009-03-09 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: OS X compile fixes
+
+2009-03-04 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: -global-Key Value and -gamename.game-Key Value options to set
+         config settings from the command line
+
+2009-02-25 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: fix two bugs in tjunction fixing
+       * q3map2: -lightmapdir option
+       * q3map2: eliminate MAX_MAP_PLANES limit
+
+2009-02-23 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: -scale -tex ("no texture lock while scaling")
+
+2009-02-15 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: non-uniform -scale x y z
+
+2009-02-10 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: remove LOTS of limits
+
+2009-02-08 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: put the command line parameters into a worldspawn key
+         _q3map2_cmdline; currently not yet supported for -onlyents
+
+2009-02-07 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: use gtk default font instead of defined ones for linux/windows
+         which could happen to be not installed (merged from uforadiant)
+
+2009-02-06 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: OS X icon by airscout
+
+2009-01-15 Rudolf Polzer divVerent(at)alientrap.org
+       * all: more fixes for OS X
+
+2009-01-14 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: use %f format for angles, prevents weird looking angles
+
+2009-01-09 Rudolf Polzer divVerent(at)alientrap.org
+       * all: lots of fixes for compiling on OS X
+
+2009-01-07 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: handle ALL key binds properly using GDK methods
+
+2009-01-03 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: fix the translation of entities used by mirroring or scaling
+
+2009-01-02 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: command "regroup entities", allows moving brushes in/out of
+         entities
+
+2009-01-01 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: "clone selection" no longer changes targetnames by default.
+         Hold shift while pressing space to do change them as before.
+       * all: handle "origin" keys for brush entities (more consistency, should
+         break no maps)
+
+2008-12-10 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: properly handle the [ and ] keys on german layout
+       * q3map2: fix dotProduct2scale to match the documentation
+
+2008-11-28 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: -dirty: don't treat skybox surfaces as solid for dirtmapping;
+         prevents Quake 2-ish "dark near skybox" effect.
+
+2008-11-21 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: applied win32 font and build fix by ingar
+
+2008-11-20 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: extend some more limits but just by a bit this time to not
+         let memory usage rise too high
+       * radiant: fix finding the .mtl file for .obj models
+
+2008-11-18 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: get rid of the MAX_MAP_DRAW_VERTS limit (the array already was
+         dynamic anyway); allows creating BSPs of over 400 MB in size ;)
+
+2008-11-10 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: draw targeting arrows also for target2, etc. keys even in Q3
+         map mode; this is good for Nexuiz which now supports target, target2,
+         target3 and target4.
+
+2008-11-07 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: fix buffer overruns because of using the realpath function
+         with an insufficient buffer; there might be more of these in the code
+         base
+
+2008-10-27 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: -convert -format ase -shadersasbitmap convert mode that writes
+         the shader names in the *BITMAP field in the .ase. That way, the .ase
+         files work without changing as mapobjects.
+
+2008-10-12 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: fix the deluxemap contribution from ambient lighting. minLight
+         is still broken with deluxemapping. If you must use minLight, combine it
+         with 1/2 or 1/4 of its amount in ambient.
+
+2008-09-30 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: fix deluxemap when lit from the wrong side as good as possible
+         by ignoring the deluxemap contribution. Now the invariant "deluxemap
+         vector points away from the surface" should hold. Avoids sudden black
+         spots when deluxemapping.
+
+2008-09-26 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: turn the Urban Terror vis nudge and triangle check into options
+         -extravisnudge and -trianglecheck, as they break some Nexuiz maps.
+         Evaluate the usefulness of these options later.
+       * q3map2: make sure the intermediate .bsp when bouncing always is loadable
+         into the game (by unparsing the entities, so if gridsize got modified,
+         that change gets written too)
+
+2008-09-23 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: print a warning if the specified samplesize cannot be used with
+         the current lightmap size
+
+2008-09-22 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: add dotProduct2scale alphamod
+       * q3map2: add -minsamplesize command line option to override lightmapscale
+         specified in map files
+
+2008-09-19 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: add a "Strafe Mode" option
+       * radiant: ctrl-tab now focuses all XYZ views in the three-part view (as
+         that is what the user is likely to want there)
+       * radiant: make rotate/scale dialogs non-modal
+
+2008-09-18 Rudolf Polzer divVerent(at)alientrap.org
+       * radiant: handle missing anisotropy extension; fixes display bug on
+         Windows XP software renderer
+       * radiant: make logging kick in earlier
+       * radiant: add svn release to the version number
+
+2008-09-15 Rudolf Polzer divVerent(at)alientrap.org
+       * all: added a Makefile to build GtkRadiant; this replaces scons and
+         python install.py
+       * all: got rid of libmhash dependency, using mdfour.c from DarkPlaces
+         instead
+       * q2data: remove RSA security copyrighted md4.c, using mdfour.c from DP
+         instead as a drop-in replacement
+       * all: get rid of version.h and aboutmsg.h, instead set the version in the
+         Makefile
+       * all: support cross compiling using mingw32
+
+2008-09-13 Rudolf Polzer divVerent(at)alientrap.org
+       * q3map2: update to ZeroRadiant's q3map2
+       * q3map2: added lightmap exposure feature: -exposure 4.2 (Urban Terror)
+       * q3map2: check whether a lightmap sample is actually in the triangle
+         (Urban Terror)
+       * q3map2: nudge light sample origin by 1qu away from planes (Urban Terror)
+       * q3map2: floodlight: usage is "_floodlight" "red green blue distance
+         intensity", default "240 240 255 1024 128"; works somewhat similar to
+         dirtmapping (Urban Terror); uses a switch -lowquality
+       * q3map2: added -debugnormals feature (Urban Terror)
+       * q3map2: fix -convert -format map decompiling (note: outputs map in
+         "Alternate Texture Projection" format); no longer messes up texcoords
+       * q3map2: added -game nexuiz to use good default paths for Nexuiz
+       * q3map2: added -game quakelive to enable in-game adverts
+       * q3map2: fix incorrect plane snapping often causing holes in terrain
+       * q3map2: spawnflags on misc_model: 8 extrudes with original normals, 16
+         extrudes with up/down normals (terrain), default: extrudes with axial
+         normals (like before)
+       * q3map2: fix obvious (and reported, and patch sent in) bug when importing
+         models when the normals were pointing in a 45 degrees direction
+       * q3map2: when importing models, allow "surfaceparms structural". This
+         also turns off any plane snapping, as it is intended for caulk brushes
+         inside a model
+       * q3map2: added parameters -ne to set normal epsilon, and -de to set
+         distance epsilon (to customize plane snapping)
+       * q3map2: fix q3map_lightRGB (Urban Terror)
+       * q3map2: add a build script to cross compile q3map2 to Win32
+       * radiant: when displaying normals on a model, scale them to 8 unit size
+         on the output (so "modelscale" can be used without LOTS of lines on the
+         screen)
+       * radiant: also support "killtarget" as target key for drawing the
+         targeting lines
+       * radiant: "expand selection to whole entities" now also selects the
+         entity ITSELF; result: Ctrl-Alt-E Space makes a NEW entity now, instead of
+         just duplicating the brush (old behaviour caused bugs in maps with copied
+         func_ladders)
+       * picomodel: support .obj format as exported by Blender, with a .mtl file
+         defining the shader names for each material; to export using Blender,
+         enable "Materials" and "Material Groups" in the .obj export dialog
+       * all: bump version to 1.5.0-div0
diff --git a/oldstuff/ChangeLog.idsoftware b/oldstuff/ChangeLog.idsoftware
new file mode 100644 (file)
index 0000000..47deae2
--- /dev/null
@@ -0,0 +1,8216 @@
+This is the changelog for developers, != changelog for the end user 
+that we distribute with the binaries. (see changelog)
+
+28/06/2007 (dunkfordyce@gmail.com)
+- fixed mnemonics for MRU list
+- fixed find functionality
+- added option to always use caulk texture for new brushes
+- fixed(?) a small bug in install.py that was trying to copy msvc files on linux
+
+28/06/2007
+- Added material-support to brushexport-plugin (Shaderman)
+
+26/04/2007
+- Disabled auto-search for texbrowser and entityinspector even when the option
+  is turned on in the gtkrc
+
+26/04/2007
+- Fixed q3map2 lightbounce bug (by Unknown)
+
+26/04/2007
+- Fixed another texcompression bug
+
+25/04/2007
+- Fixed texcompression beeing disabled after each restart
+- Fixed gtk-searchpopup in treeviews
+
+15/04/2007
+namespace
+- Fixed brushexport2 output float-format (Shaderman)
+
+27/03/2007
+namespace
+- Fix: Added missing xml-writer pop-calls
+- Ported mapxml plugin to Doom3
+- mapxml now exports brushes with its vertices
+
+19/03/2007
+namespace
+- Fix: Selection is now deleted when creating a patch out of it (aumüller / namespace)
+
+08/03/2007
+namespace
+- Win32 compile fix (woekele)
+
+07/03/2007
+namespace
+- Updated UFA:Plugin (mattn2)
+
+04/03/2007
+namespace
+- Reverted Q3 translucency fix since it randomly made brushes
+  fully transparent in Doom3 mode.
+
+04/03/2007
+namespace
+- Final update for installerfiles (Shaderman / namespace)
+- Removed installer.py validation checks since they are incompatible with Vista
+- Updated msiquery module to python 2.5
+- Added msiquery module for python 2.5
+
+03/03/2007
+namespace
+(THIS IS A TRANSITIONAL REVISION, DO NOT USE, WAIT FOR UPDATED DEPS)
+- Fixed weird msvcrt bugs caused by dbghelp.dll
+- Activated new radiant icon on Linux (Topsun)
+- First update for installerfiles (Shaderman)
+- New MODT for q3map2 :)
+- tiny changes
+
+28/02/2007
+namespace
+- Radiant is now Vista compatible (Aero must be disabled)
+- Updated all radiant dependencies (gtk is now 2-2.10)
+  New dependency packages can be found here
+http://zerowing.idsoftware.com/files/radiant/developer/1.5/gtkradiant-1.5-dependencies-1.0.zip
+  or here
+http://www.codecreator.net/radiant/gtkradiant-1.5-dependencies-1.0.zip
+- Removed Win32 filechooser
+   - Fixes crashes caused by utf-8 encoded filenames
+   - Fixes Vista "SaveAs"-Bug
+- Converted all projects to Visual Studio 2005
+- Codefixes for vc2k5 compiler
+- Removed old unused projectfiles for Visual Studio 6
+- Simplified dependency filestructure
+- Simplified install.py
+- Updated CONTRIBUTORS list
+
+26/01/2007
+namespace
+- SnapPlane reenabled by namespace because of multiple reports of
+  q3map2-crashes which were triggered by this patch.
+
+24/01/2007
+namespace
+- Added Undo/Redo-Toolbarbuttons (Shaderman)
+- Fixed Bug #1078 (sogined)
+
+18/01/2007
+namespace
+- Weird shiftvalues are now hidden to the user, shiftvalues will
+  stay in ]-shader_size;shader_size[ range for display.
+  For the sake of floatingpoint precision, it would be nice
+  to keep the internal values in that range too, but thats "nice to have".
+- Fixed missing librarypaths in ufoai-plugin
+  
+18/01/2007
+LordHavoc
+- disabled SnapPlane because it slightly corrupts collision brushes from
+  embedded model triangles
+
+17/01/2007
+namespace
+- Fixed "jumping" texcoords when switching to a shader with different size
+- (Todo) Toolbar: add button for refresh-models. (Shaderman)
+- Aniso fix (Shaderman)
+- Translucency fix (Shaderman)
+
+05/01/2007
+namespace
+- UFO:Alien Invasion Plugin (mattn2)
+- Fix: Filtering models in ET doesn't filter misc_gamemodels (Shaderman)
+
+25/12/2006
+namespace
+ - Brushplugin Version 2.0, supports multiple collapse modes and a materialignore list (namespace)
+ - Camera movement speed changes. Increase speed = SHIFT+KP_PLUS, decrease speed = SHIFT+KP_MINUS.
+   New option to link the strafe speed to camera movement speed (default: linked). (Shaderman)
+ - Fixed bug in sample plugin (Shaderman)
+ - Merry Christmas
+
+17/12/2006
+namespace
+ - Radiant warzow-support (Topsun + Warzow-Mappers)
+
+15/12/2006
+namespace
+ - Inverted bevel can be used with end caps (Topsun)
+ - Removed needless .pdb files from win32 installer (Topsun)
+ - Fixed .ase picomodel loader to load shaders again (Shaderman)
+ - Removed translucent brushes fix because of wrong rendering behaviour on Linux
+ - New cool(!) radiant icon by eb
+
+13/12/2006
+namespace
+- Added tremoulus-support to q3map2
+
+08/12/2006
+namespace
+- Entity names are now drawn for group entities in Doom3 and Quake 3 mode (namespace)
+- Fixed translucent brushes becoming invisible when selected (Shaderman)
+
+06/11/2006
+namespace
+- (TODO) Texture sizes sometimes vary wildly. New texture browser option: View -> Fixed Size.
+  Code parts taken from DarkRadiant. (Shaderman)
+- Added new texture browser option: View -> Hide Image Missing. (Shaderman)
+- Fixed new D3 lights don't have a light_radius key. (Shaderman)
+- Fixed hotkey collision (paste to camera/view menu). New View shortcut = ALT+W. (Shaderman)
+- Fixed .wad MMB 3d view texture selection bug. (Shaderman)
+
+04/11/2006
+namespace
+- Added warzow-support to q3map2
+
+12/10/2006
+namespace
+- Updated help menu web links (removed map-center.com, added ETB documentation) (Shaderman)
+- Added check for existing worldspawn if a new one should be added with the entity menu (Shaderman)
+- Fixed Entity -> Ungroup (Topsun)
+- Fixed hotkey collision ALT+M (filter botclip/Modify menu). New Modify shortcut = ALT+O (Shaderman)
+- Updated Window Layout images (Shaderman)
+- Fixed (TODO) XYWindow: save show-workzone option (Shaderman)
+- Fixed (TODO) Toolbar: add shortcut to tooltips for toolbar buttons (Shaderman)
+- Fixed (TODO) GUI: detachable submenus (Shaderman)
+
+09/10/2006
+namespace
+- Added option to toggle the camera window stats on/off (Shaderman)
+  (view --> show --> show stats)
+
+
+08/10/2006
+namespace
+- Fix for bug 1106 - .wad files don't get listed in the textures menu (Shaderman)
+  (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1106)
+- Added initial support for Prey (Shaderman)
+- Fixed entity inspector sliders to always show (Shaderman)
+- Added NOTES subsection to the entity inspector listing .def "editor_usage*" values (Shaderman)
+
+07/10/2006
+namespace
+- Added "select inside" and "select touching"
+  Both functions now work with multiple selectionbrushes, allowing complex
+  selection operations.
+- Added entries for the selectionfunctions in "Edit" and the main toolbar.
+
+06/10/2006
+namespace
+- Changed ETB not to show any texture if a tag search doesn't match anything (Shaderman)
+- Added View -> Filter -> "Invert filters/Reset filters" function (Shaderman)
+- Fixed (TODO) Textures: remove "shaders only" option for doom3 (Shaderman)
+- Fixed show shaders / shader only / shader info for doom3 and .wad file games (Shaderman)
+
+03/10/2006
+namespace
+- Fix for Bug 1113 (Topsun)
+  (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1113)
+
+03/10/2006
+namespace
+- Changed ETB tag toolbar to a notebook with tag/texture pages (Shaderman)
+- Added a context menu (add/delete/rename tag) to the ETB tag tree view (Shaderman)
+- Added new win32 installer HOWTO (Shaderman/Topsun)
+
+01/10/2006
+namespace
+- Added missing xml files for win32 installer
+
+30/09/2006
+namespace
+- Fixed Etb saving custom tags to global tagfile (Shaderman/namespace)
+- Fixed postbuild step for brushexport, shaderplug and sunplug (Shaderman)
+- Added installersupport for new files and plugins (Shaderman)
+
+30/09/2006
+namespace
+- Added LocalLcPath to plugin interface
+- Added enhanced Texturebrowser (ETB) by Shaderman
+- Added shaderplug by Shaderman, accompanies the ETB
+- Added xmltagging lib by Shaderman, accompanies the ETB
+- Added new icons for ETB, Console, Entityinspector and Lighteditor
+- Fixed minor warning in Sunplug Project
+- Fixed PATH_MAX namecollision in ptrview plugin on Linux
+- Final fix for 64 bit patch.h issue
+
+
+
+12/09/2006
+namespace
+- Fixed 64 Bit issue in patch.h, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1109
+  for details
+
+11/09/2006
+namespace
+- Fixed unnecessary warnings, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1108
+  for details
+
+11/09/2006
+namespace
+- Added sunplug (Mapcoordinator-plugin for ET) by Topsun
+  ET only: setting mapcoordsmins and mapcoordsmaxs in the worldspawn
+  Tester: Shaderman
+- Added brushexport Plugin by namespace
+  Exports selected brushes as wavefront object.
+  Tester: Shaderman
+
+11/09/2006
+namespace
+- Fixed compile error on x86_64, see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1105
+  for details.
+
+09/09/2996
+namespace
+- Added strafing for the camerawindow while holding ctrl
+- Additional forward movement can be enabled by pressing shift during strafe
+
+22/08/2006
+SPoG
+- Added VFS support for locating the archive a file was loaded from.
+- Changed Doom3 entity definition parser to gracefully handle parse errors.
+- Fixed crash when loading entity definitions in quake4 1.3 point release.
+
+13/08/2006
+SPoG
+- Disabled 'detail' content flag checkbox in quake2 Surface Inspector.
+
+22/07/2006
+SPoG
+- Fixed doom3 func_static with model not appearing to move when dragged. 
+- Changed ASE model loader to parse material names the same way as DoomEdit.
+- Fixed title of wait-dialog when loading a model.
+- Fixed doom3 func_static with blank 'model' key being invisible.
+- Changed doom3 func_static model creation to replace selected models.
+- Added support for loading both .ent and .def files at the same time.
+
+09/07/2006
+Shaderman
+- Updated win32 libxml2 package to 2.6.24.
+namespace
+- Ported win32 stack-backtrace to use new DebugHelp API.
+- Added stack-backtrace functionality for Linux/OSX.
+
+11/06/2006
+SPoG
+- Fixed arbitrary rotation X and Y axes appearing to be transposed.
+
+04/06/2006
+SPoG
+- Fixed crash when deleting items from Build menu.
+
+03/06/2006
+SPoG
+- Changed doom3 entity creation to add model key for brush-entities.
+- Fixed crash in Save Region.
+- Fixed detail brushes being turned structural when texture is set.
+
+29/05/2006
+SPoG
+- Changed default doom3 light_radius to be taken from the entity-definition.
+- Fixed error when entering and exiting camera freemove with LMB pressed.
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1090
+
+13/05/2006
+LordHavoc
+- Added -fPIC for Linux builds to support x86_64.
+- Removed static-linked libstdc++ hack for non-final builds.
+- Removed gcc explicit linking hack for non-final builds.
+- Added workaround for gcc static-member-pointer-as-template-argument bug.
+- Fixed bobtoolz linux compile errors.
+- Added Nexuiz and Darkplaces support.
+SPoG
+- Changed 'inconsistent vertex count' assert to be non-fatal.
+- Changed 'failed to remove accelerator' assert to be non-fatal.
+- Fixed crash due to broken module dependencies.
+- Fixed default settings for Build Monitoring.
+- Fixed nudge-selection when using the drag tool mode.
+- Added support for patches in texture-painting tool.
+
+30/04/2006
+SPoG
+- Fixed memory leak in signals library.
+- Ported bobtoolz to use new module APIs.
+
+01/04/2006
+SPoG
+- Added key-observer interface to entity module API.
+- Rewrote callback library to add support for return-values.
+- Added minimal API to support bobtoolz plugin.
+- Refactored brush for-each functions to take Functor instead of Visitor.
+- Added signals library.
+
+31/03/2006
+SPoG
+- Changed doom3 light creation to use size of selected brushes.
+
+20/03/2006
+SPoG
+- Fixed crash when resetting preferences after startup failure.
+- Fixed crash on next-leak-spot with build-monitoring enabled.
+- Fixed doom3/quake4 blended-decal rendering when toggling lighting mode.
+- Fixed fit-texture with rotated texture transforms.
+
+20/03/2006
+SPoG
+- Changed Copy/Paste to work on face textures if any faces are selected.
+- Fixed GTK_WIDGET_REALIZED assert when selecting entities (linux).
+
+28/02/2006
+namespace, SPoG
+- Added drag-resizing for doom3/quake4 light_radius boxes.
+
+25/02/2006
+SPoG
+- Fixed objects sometimes dissappearing when at high zoom level in Ortho views.
+
+24/02/2006
+SPoG
+- Added GPL text to win32 installer.
+- Fixed gtk wimp theme not working after using gtkthemeselector.
+
+21/02/2006
+namespace
+- Added command to toggle lighting/textured modes, shortcut F3.
+
+20/02/2006
+SPoG
+- Fixed crash when disabling lighting for a second time.
+
+19/02/2006
+SPoG
+- Fixed crash when loading invalid ASE models.
+
+11/02/2006
+SPoG
+- Added install.py script.
+- Updated COMPILING instructions.
+- Fixed transparency rendering on quake3 shaders.
+- Fixed hint/caulk filtering for Jedi Academy shaders.
+
+04/02/2006
+SPoG
+- Added Radiant Manual shortcut to win32 installation.
+- Added 'use alternative texture projection' option to prefs.
+- Fixed caching bug causing import-map to not reload modified maps.
+- Added blended-decal rendering for doom3 and quake4.
+
+30/01/2006
+SPoG
+- Added expand-selection-to-entities with default shortcut ctrl+alt+e.
+- Fixed crash in gtk file-chooser with some versions of GTK+.
+
+29/01/2006
+SPoG
+- Changed create-group-entity to re-select brushes after creation.
+
+26/01/2006
+SPoG
+- Changed far-clip-plane setting to increase exponentially with distance.
+- Fixed selected entities moving when drag-resizing brushes.
+- Changed patches to be selectable from the back in wireframe views.
+- Speed improvements for transform-selection code.
+
+25/01/2006
+SPoG
+- Added default-texture-scale option to preferences.
+- Added default-grid-spacing option to preferences.
+
+23/01/2006
+Shamus
+- Fixed editing of doom3/quake4 faces with negative texture scale factors.
+
+22/01/2006
+SPoG
+- Fixed shortcut for toggle-far-clip.
+- Fixed broken link in 1.5 user docs.
+
+10/01/2006
+SPoG
+- Changed script parser to ignore comments that start in the middle of tokens.
+- Added support for editor_int/editor_string keys in doom3 entity definitions.
+- Changed doom3/quake4 .mtr and .guide searching to look in subfolders.
+- Added experimental support for doom3/quake4 projected lights.
+
+20/12/2005
+SPoG
+- Added support for quake4 .guide material templates.
+- Fixed GCC4 compile errors with anonymous enums.
+- Added light_radius and light_center GUI to doom3 entity inspector.
+
+10/12/2005
+SPoG
+- Added support for loading and saving Quake4 map format.
+- Added support for built-in shader images such as _noFalloff.
+- Added experimental code to render projected lights.
+- Added support for loading quake4 entity definitions.
+- Fixed picomodel bug loading .lwo files with texture names >64 in length.
+
+22/10/2005
+SPoG
+- Fixed minor memory leak in zip-archive reader.
+
+21/10/2005
+SPoG
+- Fixed model rotation using free-rotation tool.
+- Fixed behaviour of angle/rotation keys for Doom3 entities.
+- Added entity angle-editing for entities that display a model.
+- Stopped size-info being drawn if selection has zero size.
+- Added support for 'angle' key on doom3 entities.
+
+20/10/2005
+SPoG
+- Fixed minor one-time memory leak in build-shader-list.
+- Added functional free-scale tool.
+- Improved precision preservation for free-rotation and free-scale tools.
+- Fixed misc_model rotation using free-rotation tool.
+
+09/10/2005
+SPoG
+- Added entity angle-editing using rotate-tool or rotation toolbar buttons.
+- Fixed start-on-primary-monitor (win32).
+- Fixed camera-view freelook when window is on secondary monitor (win32).
+
+05/10/2005
+paxed
+- Added texture-lock toolbar button.
+SPoG
+- Added stack-trace output to all debug popup messages (win32).
+- Fixed vertex/edge selection behaviour on undoing brush edits.
+- Changed doom3 light centre rendering to use a point instead of a box.
+- Changed map and shader parsers to gracefully handle bad data.
+
+24/09/2005
+SPoG
+- Fixed crash when importing a file after deleting the world entity.
+- Changed copy/paste/import to select world brushes instead of world entity.
+- Added win32-specific stack-trace logging support.
+
+31/08/2005
+SPoG
+- Fixed clipper removing brushes on incorrect side of clip-plane when flipped.
+
+21/08/2005
+SPoG
+- Optimised light-dragging.
+- Changed connect-entities to not break existing connections where possible.
+
+24/07/2005
+SPoG
+- Fixed q3 entity definition for item_health_small.
+
+02/07/2005
+SPoG
+- Fixed build menu becoming empty if editing of default menu is cancelled.
+
+01/07/2005
+SPoG
+- Fixed snap-planes-to-integer preference not being saved.
+
+26/06/2005
+SPoG
+- Changed doom3 light_radius box to draw flat-shaded translucent in camera view.
+- Fixed progress window not being shown when loading maps.
+- Refactored shortcut handling to make focussed widgets override global shortcuts.
+  Allows using ctrl+c to copy console text, undo/redo without main-window focus.
+
+23/06/2005
+SPoG
+- Fixed crash when handling assert/error before gtk_init.
+- Changed Help menu to display only the help menu relevant to the current game.
+
+21/06/2005
+SPoG
+- Fixed double-maps-directory when using non-native file open dialog on win32.
+- Changed find/replace-textures window to update when selecting textures with MMB.
+- Fixed handling of non-UTF-8 wad-names in textures menu.
+
+20/06/2005
+SPoG
+- Changed home-path prefix to be optional on linux/osx for q1/q2.
+- Changed OpenGL module to work correctly with GL_VERSION 2.0.0.
+- Fixed spawnflags in Enemy Territory entity definitions.
+- Added missing Enemy Territory entity types.
+
+19/06/2005
+SPoG
+- Changed clipper-point selection/rendering to behave the same at all zoom levels.
+- Changed clipper-point selection to always pick the closest point to the cursor.
+- Fixed clipper colour not being updated until after restarting.
+- Fixed QE tool not deselecting edges when left-clicking on a vertex without shift.
+- Fixed grid rendering with grid settings other than 8-unit.
+- Fixed textures menu always behaving as if show-shaderlist-only is enabled.
+
+18/06/2005
+SPoG
+- Added saving of camera render mode preference.
+- Changed default camera render mode to Textured for Doom3.
+- Changed default texture render mode to Trilinear.
+
+17/06/2005
+SPoG
+- Ported Team Arena entity definitions to xml format.
+- Added xml q3 entity-definitions to win32 and linux setups.
+
+14/06/2005
+SPoG
+- Fixed QE-tool component-drag selecting components of unselected brushes.
+
+13/06/2005
+SPoG
+- Changed clipper mode and component-editing modes to be mutually exclusive.
+- Changed camera A/Z/D/C keys to obey "discrete movement" checkbox.
+- Added support for up/down movement in freelook mode.
+- Fixed clipper-tool-uses-caulk option.
+- Added prompt for engine path at startup if not found.
+
+12/06/2005
+SPoG
+- Added entity-inspector GUI support for func_button/func_door direction attribute.
+- Added angle/model/sound GUI to entity-inspector for old-style entity-definitions.
+- Added clipper-plane rendering using stippled back-face-culled polygon.
+- Fixed entity-inspector failing to handle non-ascii characters in entity keys.
+
+11/06/2005
+SPoG
+- Fixed entity-inspector window position changing while hidden.
+
+09/06/2005
+SPoG
+- Fixed region-set-selected for model entities.
+
+08/06/2005
+SPoG
+- Added option to enable or disable snapping brush planes to integer on map load/save.
+- Added 0.125 grid.
+- Changed grid rendering to always show major/minor grid colours whatever the zoom level.
+- Increased maximum zoom level for XY views.
+
+06/06/2005
+SPoG
+- Added 'File > Refresh models' - reloads models that have changed outside Radiant.
+
+05/06/2005
+SPoG
+- Fixed model files not being closed after being read.
+- Fixed build menu dialog not saving changes to build commands.
+- Changed build menu to save xml only if changed by user.
+- Fixed CSG-merge.
+- Reduced CSG-merge tolerance for misaligned brushes.
+Michael Kluskens
+- Updated STVEF default build menu to version 2 format.
+- Updated STVEF game configuration file and removed synapse.config.
+
+02/04/2005
+SPoG
+- Changed HashTable insert/remove operations to not invalidate iterators.
+- Changed ReferenceCache realise/unrealise to take advantage of new HashTable behaviour.
+- Refactored containers to use std::swap.
+- Refactored bitfield.h.
+Tr3B
+- Fixed endianness for .lwo loading on linux.
+- Extended q3map2 mathlib functionality.
+
+28/03/2005
+SPoG
+- Specialised filters list for doom3 entity/material types.
+- Added ASE-loader support for shader names specified as a bitmap absolute-path.
+- Fixed monitored-compile debug-feedback display.
+- Added TGA-loader support for vertical and horizontal flipping.  
+- Enabled auto-generation of smooth normals for all LWO models.
+
+27/03/2005
+Tr3B
+- Fixed map-xml module.
+- Added support for qer_trans keyword in doom3 materials.
+
+08/03/2005
+SPoG
+- Added GUI updates during map load and engine-path/game-dir changes.
+- Fixed main window being hidden behind another application on closing a floating window.
+
+07/03/2005
+SPoG
+- Fixed crash when selecting the root node in the entity-list window.
+- Fixed detail flag saving for quake3 map format.
+
+06/03/2005
+SPoG
+- Optimised type-casts for scene-graph type system.
+- Disabled substitution of 'unspecified' for entity key values that match the default.
+- Refactored module-system api - added globalModuleServer().
+- Fixed rotation origin for doom3 func_static models.
+
+05/03/2005
+SPoG
+- Added support for doom3 model-entity 'skin' key.
+- Added noshadows/nospecular/nodiffuse/falloff doom3 light keys to entity-inspector.
+
+04/03/2005
+SPoG
+- Added camera move up/down one floor.
+- Added support for 'unspecified' contents/flags/value for Quake2 brush faces.
+
+26/02/2005
+SPoG
+- Added auto-complete for shader attributes in entity inspector.
+- Added support for doom3-material heightmap to normalmap conversion.
+
+22/02/2005
+SPoG
+- Fixed missing prefix attribute in quake game configuration file.
+- Added auto-completion for find/replace-textures texture-name entries.
+- Removed redundant buttons and options in find/replace-textures window.
+
+21/02/2005
+SPoG
+- Added auto-completion for surface-inspector texture-name entry.
+
+20/02/2005
+SPoG
+- Fixed failure to load shaders containing '.' such as Heretic II model skins.
+- Removed unused legacy cmdlib functions.
+- Added support for fractional repeat values to brush-fit-texture.
+
+19/02/2005
+SPoG
+- Changed entity-connect-selected to use the parent entity of a selected brush.
+- Added q2map and bspc to installation packages.
+Jamie Wilkinson
+- Fixed path to q2map in quake2 build-menu.
+
+13/02/2005
+SPoG
+- Fixed crash in 'Misc > Find Brush' when searching for a non-existent brush.
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1059
+- Limited the maximum number of sides of a prefab brush-cone to 32.
+
+11/02/2005
+SPoG
+- Changed display of angled box-entities to show un-rotated bounding boxes.
+
+10/02/2005
+SPoG
+- Disabled rotation of light entities for games other than Doom 3.
+
+09/02/2005
+David Constanzo
+- Fixed episode flag names on Quake item_sigil and func_episodegate entities.
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1056
+- Added detailed description of Quake item_sigil and func_episodegate entities.
+SPoG
+- Fixed position of light-entity names.
+- Fixed q3map2 feedback xml streams containing non-UTF-8 text.
+- Optimised Locale<->UTF-8 text conversion.
+
+08/02/2005
+SPoG
+- Fixed selecting a texture not resetting the current selected texture-projection.
+- Added handling of OpenGL drivers that don't implement all reported extensions. 
+
+07/02/2005
+SPoG
+- Added support for multi-byte UTF-8 characters in xml content (not markup).
+- Added UTF-8 support in entity-inspector, prefs dialog, recent-files menu, console.
+- Fixed potentially misaligned objects.
+
+05/02/2005
+SPoG
+- Added rendering of entity names for non-group entities.
+- Removed context-dependent opengl calls before opengl context is created.
+
+04/02/2005
+SPoG
+- Fixed crash when printing extended-ascii text in the console.
+- Added conversion of extended-ascii text to utf8 for gtk text-buffer widgets.
+
+03/02/2005
+David Constanzo
+- Fixed typo in Quake entity-definitions.
+SPoG
+- Fixed undo of brush-set-structural and brush-make-structural.
+- Refactored image-loader module api.
+- Added full support for Quake II and Heretic II surface-flags in surface-inspector.
+- Fixed crash in patch-inspector for games other than doom3.
+
+01/02/2005
+SPoG
+- Changed shader-list and entity-definition searching to also search base-dir.
+
+29/01/2005
+SPoG
+- Fixed title of floating entities/console/textures window.
+- Fixed destruction of floating windows on shutdown.
+- Added shortcut handling when entity-inspector/texture-browser are active.
+David Constanzo
+- Fixed crash while auto-saving snapshots.
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1049
+
+28/01/2005
+SPoG
+- Added rendering of fixed S/T tesselation on doom3 patches.
+- Changed creation of doom3 func_static entities to prompt for a model.
+- Fixed zero-sized primitives being rendered for culled entity-connection-lines.
+
+25/01/2005
+SPoG
+- Added support for setting fixed S/T tesselation on doom3 patches.
+- Changed patch inspector to be completely non-modal.
+
+24/01/2005
+SPoG
+- Added support for rotating lights using the rotation tool.
+
+23/01/2005
+SPoG
+- Fixed crash on startup with texture-subsets enabled.
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=1045
+- Added support for doom3 lights combined with brushes and patches.
+- Added support for doom3 light_origin on lights.
+- Added support for doom3 light_rotation and rotation key on lights.
+
+22/01/2005
+SPoG
+- Fixed crash when accessing links from help menu.
+- Fixed broken links in help menu.
+- Added game-specific docs to win32 setup.
+- Changed q3 connect-entities to preserve existing targetname key.
+- Changed q3 connect-entities to generate targetname key based on target classname.
+
+21/01/2005
+SPoG
+- Moved information in synapse.config into .game files.
+- Added api versioning for module-system.
+
+20/01/2005
+SPoG
+- Fixed keys/values for brush entities not being editable unless parent is selected.
+- Fixed brush-entities not being deleted when the last child brush is deleted.
+- Fixed scenarios where worldspawn is not the first entity in the map.
+
+19/01/2005
+SPoG
+- Fixed numerical instability in brush winding-generation.
+
+16/01/2005
+SPoG
+- Added Jedi Academy support to linux installer.
+- Fixed main-window jumping to front during autosave.
+- Fixed saving of empty brushes.
+Jame Wilkinson
+- Fixed build errors when compiling for big-endian target.
+
+15/01/2005
+SPoG
+- Fixed launching q3map2 from build-menu on linux/osx.
+- Added version checking of generated config files.
+- Fixed key-up events being missed while holding ctrl/shift/alt.
+- Fixed texture-compression support.
+Jago
+- Changed q1 trigger_relay and trigger_counter to be point entities.
+
+11/01/2005
+SPoG
+- Changed brush-save to not write non-contributing faces.
+- Fixed rendering artifacts on outlines of selected box-entities.
+
+10/01/2005
+SPoG
+- Added patch-cap-cylinder.
+
+09/01/2005
+SPoG
+- Fixed texture-browser scroll-to-selected-texture.
+- Added brush face texture painting.
+
+08/01/2005
+SPoG
+- Fixed ungroup-selected-entities.
+- Added 'Entity' menu.
+- Removed items unrelated to entity-creation from xy-window right-click menu.
+- Fixed minor memory leaks in core.
+- Removed code that ignores empty alpha-channel in tga loader.
+- Fixed memory leak in model module.
+- Fixed memory leaks in picomodel library: ase and lwo loaders.
+- Changed default tool to 'QE' tool.
+
+04/01/2005
+SPoG
+- Changed start-on-primary-screen default to 'true' with multiple screens.
+- Added enter/escape as shortcuts for OK/Cancel buttons on modal dialogs.
+- Disabled mouse-chase scrolling in XY window when drag-selecting.
+- Fixed xlink I/O warnings on linux.
+- Removed light-creation 'intensity' dialog in doom3 config.
+- Changed the default vertical size of the shortcut-list window to 400. 
+- Fixed patch-creation with zero-sized workzone.
+- Fixed crash when rendering doom3 light_radius box.
+
+03/01/2005
+SPoG
+- Added arbfp1/arbvp1 vertex/fragment program lighting support.
+- Fixed colour-selection dialog not going away after OK/Cancel.
+- Fixed tangent/bitangent calculation on degenerate patches.
+- Added resizing of patches with QE tool.
+
+02/01/2005
+SPoG
+- Added stippled hidden-line rendering for rotate/translate manipulators.
+- Refactored high-level camera/orthographic rendering functions.
+- Fixed failure to load models with back-slashes in path.
+- Improved peformance of doom3 lighting with large models.
+
+01/01/2005
+SPoG
+- Changed entity renderering to draw connections for culled entities.
+- Fixed runtime errors on shutdown after cycling between lighting/textured.
+- Fixed 'Cancel' button in modal dialogs behaving like 'OK' button.
+- Changed 'clip' brush filtering to use shader parameters instead of names.
+- Added rendering of origin-point for selected model entities.
+- Fixed doom3 light-interaction updates for model entities.
+
+31/12/2004
+SPoG
+- Removed menu-splitting functionality.
+- Refactored entity-class menu construction.
+- Replaced const_reference with ConstReference.
+- Renamed string_t to CopiedString.
+- Changed code using Str::Format and Str::operator+= to use StringOutputStream.
+- Refactored shortcut command parsing code.
+- Changed light entity rendering to show light_radius box only in doom3 config.
+- Added 2x overbrightening for doom3 lighting preview.
+
+16/12/2004
+SPoG
+- Changed default doom3 light_radius to 300.
+- Fixed initial value of doom3 light_center.
+- Reduced frequency of gui updates during map load.
+
+13/12/2004
+SPoG
+- Fixed crash in monitored-compile feedback dialog.
+
+12/12/2004
+SPoG
+- Added visualisation of halflife texture-projection format.
+- Added texture-lock for halflife texture-projection format.
+- Changed brush-texture-lock default to enabled for doom3 and halflife.
+
+11/12/2004
+SPoG
+- Refactored script-tokeniser.
+- Fixed doom3 lighting on ATI cards.
+- Added support for list attributes in entity definitions.
+- Added utf8-normalisation on text printed to console.
+- Fixed missing default_build_menu.xml in halflife game config.
+
+10/12/2004
+SPoG
+- Fixed missing commas in entity-inspector comments.
+- Added support for default values in entity-definitions.
+
+09/12/2004
+SPoG
+- Enabled doom3 realtime lighting preview.
+
+05/12/2004
+SPoG
+- Fixed gcc compile warnings in patch.cpp.
+- Added q1 and q2 support to linux installer.
+
+02/12/2004
+SPoG
+- Added highlighting of entity-list nodes that have selected descendants.
+
+29/11/2004
+SPoG
+- Fixed xy-window failing to update after map-load.
+
+28/11/2004
+SPoG
+- Fixed error on shutdown when game-select dialog is disabled.
+- Added surface/light-interaction debugging mode.
+- Added per-plane light-culling for brush faces.
+- Added support for bump shaders using 'blend' layer keyword.
+- Added support for light-shaders.
+- Fixed edge/border clamping on light-attenuation textures.
+- Added 'Lighting' camera render-mode for doom3 config.
+
+25/11/2004
+SPoG
+- Fixed right-click-menu on linux.
+
+13/11/2004
+SPoG
+- Changed light-entity to draw radii only when selected.
+
+07/11/2004
+SPoG
+- Fixed shortcuts for creating n-sided brush-prisms.
+
+19/10/2003
+SPoG
+- Fixed user-customisable shortcuts support.
+
+16/10/2003
+SPoG
+- Added restore-main-window call when a modal-dialog dialog-box is shown.
+
+13/10/2003
+Jamie Wilkinson
+- Fixed SConstruct cpu detection on Power Macintosh.
+- Added more verbose warning settings for gcc builds.
+SPoG
+- Changed buffered-text-input-stream API to not use magic EOF value.
+
+06/10/2004
+Jamie Wilkinson
+- Fixed debug-break on non-x86 platforms.
+
+05/10/2004
+SPoG
+- Fixed new doom3 entities not being given unique names.
+
+02/10/2004
+SPoG
+- Fixed autosave causing the main-window to jump to the front.
+- Fixed window-title when changing view direction in floating-windows layout.
+- Added status information to wait dialogs.
+- Changed map-save to overwrite/refresh files modified/deleted outside radiant.
+- Changed component selection in QE tool to treat near-equal points as one.
+- Added texture browser window to View menu.
+- Changed white overlay in camera-window to draw hidden lines in 75% grey.
+- Reduced point-size for vertex/edge/face handles by 2/3.
+
+25/09/2004
+SPoG
+- Added component-editing for curves on doom3 entities.
+- Added normalisation of translation for texture-lock on doom3 brushes.
+- Added update of surface inspector for texdef changes caused by texture-lock.
+- Changed floating-windows layout to centre all ortho views on center-xy-views.
+- Stopped autosave from saving unmodified maps after first-time load.
+Shamus
+- Textool improvements.
+
+21/09/2004
+Michael Schlueter
+- Changed file-chooser dialogs to use GtkFileChooser.
+
+20/09/2004
+SPoG
+- Added basic rendering for 'curve_CatmullRomSpline' on doom3 entities.
+
+19/09/2004
+SPoG
+- Added basic rendering for 'curve_Nurbs' on doom3 entities.
+
+18/09/2004
+SPoG
+- Added doom3 entity-definition editor_usage* key support.
+- Added doom3 entity-definition editor_* key info to entity-inspector comments.
+- Added specialised attribute-entry in entity-inspector for boolean attributes.
+- Fixed crash in find-brush when entering the index of a fixed-size entity.
+- Added support for rendering doom3 'targetN' -> 'name' entity connections.
+- Changed connect-entities to use 'targetN' and 'name' keys on doom3 entities.
+- Improved handling of brushes with near-duplicate planes.
+- Fixed crash in snap-to-grid on brushes with non-contributing faces.
+
+17/09/2004
+Michael Schlueter
+- Fixed gcc build errors.
+SPoG
+- Fixed stability problems with doom3 brush-entities.
+
+16/09/2004
+SPoG
+- Added automatic renaming of entity target/name keys for paste and import-map.
+
+13/09/2004
+SPoG
+- Fixed rotation/mirror toolbar buttons using wrong axes in certain situations.
+- Fixed incorrect filter settings display in filters menu.
+- Added automatic renaming of entity target/name keys when cloned.
+- Fixed quake2 support.
+
+12/09/2004
+SPoG
+- Added shortcut support for all menu commands and toolbar buttons.
+- Fixed patch shader-name saving for doom3 patches created by user.
+
+10/09/2004
+SPoG
+- Fixed patch-cap-endcap and patch-cap-reverse-endcap.
+
+09/09/2004
+SPoG
+- Fixed status-bar labels showing 'Label' at startup.
+- Fixed textures-menu grouping bug.
+- Fixed mirroring on brushes with doom3 plane-defs.
+
+08/09/2004
+SPoG
+- Changed patch-cap-selected to prompt for cap type only once.
+- Fixed infinite-loop in patch-cap-selected.
+- Changed autosave to only save if the map has changed since the last autosave.
+- Changed "file exists, overwrite?" to go back to the file-chooser if 'no' is selected.
+
+07/09/2004
+Michael Schlueter
+- Removed unused source files - qsysprintf, gtkfilesel.
+- Changed linux exectuable-path resolution to use '/proc/self/exe'.
+- Changed 'file exists, overwrite?' prompt to default to 'no'.
+
+06/09/2004
+SPoG
+- Fixed crash when handling duplicate shader definitions.
+- Fixed crash on startup after changing game-type (sp/mp).
+- Changed compute-axis-base to be more stable in degenerate cases.
+Michael Schlueter
+- Cleaned up loki_path stuff.
+Shamus
+- Added textool rotation manipulator.
+
+01/09/2004
+Michael Schlueter
+- Changed linux installer to copy *.game files from game-packs instead of generating them.
+
+29/08/2004
+SPoG
+- Moved doom3 shader parsing into a separate function.
+- Fixed saving of visibility of yz-side and xz-front in floating-windows layout.
+- Added inheritance of doom3 entityDef 'editor_* *' keys.
+- Added support for doom3 entityDef 'editor_* *' keys other than 'editor_var'.
+- Changed entity-inspector attributes panel to be scrollable.
+- Changed shaders module to load *.mtr for doom3 instead of using shaderlist.
+- Improved doom3 material parsing.
+- Fixed crash loading maps containing patches with large numbers of control points.
+- Changed face-selection in camera view to use polygon test.
+- Changed face-selection-mode rendering in camera view to cull back-faces.
+- Changed shaders module to use diffusemap on doom3 shaders with no qer_editorimage.
+
+28/08/2004
+SPoG
+- Fixed undefined-behaviour bug causing a crash with gcc optimisation.
+- Fixed opengl extension support on linux.
+- Added support for half-life .fgd entity-definitions.
+- Fixed loading of half-life maps with texture-names containing '{'.
+
+26/08/2004
+SPoG
+- Updated win32 install to use gtk+-2.4.7 and gtk-wimp-0.6.2.
+- Removed 'unknown model type: ""' and 'Texture load failed: ""' errors.
+- Changed pivot-point calculation to use entity-origin for fixed-size entities.
+- Fixed errors drawing selection-rectangle in floating-windows layout.
+- Fixed shortcuts becoming disabled in floating-windows layout.
+- Removed snap-to-integer on entity angle/angles/scale keys.
+- Fixed dragging of doom3 brush-entities.
+Michael Schlueter
+- Fixed gcc compiler error and warnings.
+- linux installer fixes.
+
+25/08/2004
+Michael Schlueter
+- Changed linux build system to copy '$GAME.game/*' for installer.
+- Changed linux installer to use 1.5's module set.
+- Removed optimisation from linux build to fix optimiser-related crash.
+- Added Doom3 support to linux installer.
+SPoG
+- Changed texdef export to not snap shift/rotate to integer.
+
+17/08/2004
+SPoG
+- Fixed texture-browser height update bug.
+- Changed texture-browser to show only the texture-set selected from the menu.
+- Fixed bug loading quake maps.
+
+16/08/2004
+SPoG
+- Fixed shortcuts for shift/rotate/scale-texture on patches.
+- Fixed patch-inspector rows/cols combos not being cleared between selections.
+- Changed entity/brush counts to use counters instead of polling every second.
+- Changed archivewad module to check lump types and ignore non-miptex files.
+- Added support for worldcraft/hammer half-life map format.
+
+15/08/2004
+SPoG
+- Added doom3 md5mesh loader.
+- Added support for doom3 entityDef 'model' key.
+- Changed textures-menu to show/load only shaders in the form 'textures/<menu-item>/*'.
+- Fixed texture-browser height calculation bug.
+- Added support for doom3 entityDef 'editor_var *' key.
+- Fixed support for patchDef3 subdivision settings.
+
+14/08/2004
+Chronos
+- Added doom3 light_radius and light_center rendering.
+SPoG
+- Disabled default-shaders for doom3.
+- Added one-click dragging of vertices/edges/faces on brushes and patches.
+- Fixed detail flag being lost on brush-clone or save-as.
+
+12/08/2004
+SPoG
+- Fixed workzone being invalidated when a brush is deleted.
+- Fixed pivot updates when switching from translate-tool to rotate-tool.
+- Fixed crash in misc_model.
+- Changed file_dialog to show '*.*' when pattern is not specified.
+- Added undo support for patch-inspector XYZUV tweaking.
+- Removed 'Apply'/'Done' buttons from patch-inspector.
+
+11/08/2004
+redfella
+- Converted RTCW entities.def to xml format.
+SPoG
+- Added support for "name" key for doom3 entities.
+
+10/08/2004
+SPoG
+- Added support for loading text files from VFS archives.
+
+09/08/2004
+SPoG
+- Changed .map writer to always use decimal notation for floats.
+- Added filtering of monster_clip/full_clip/player_clip.
+- Added support for inheritance in doom3 entity-definitions.
+- Fixed doom3 patchDef2 material-name import/export.
+
+06/08/2004
+SPoG
+- Doom3 support:
+  - Map load/save.
+  - Materials parsing.
+  - entityDef parsing.
+  - Fixed brush-primitives texturing bug.
+  - Added texture-lock for brush-primitives texturing on all transforms.
+  - Added support for model/rotation/origin keys on func_ entities.
+- Added DDS image module.
+
+03/08/2004
+SPoG
+- Fixed copy/paste copying all brushes of an entity when only one is selected.
+- Fixed discrete-camera-movement shortcuts becoming disabled after using freemove-camera.
+
+27/07/2004
+Shallow
+- Converted ET entities.def to xml format.
+
+26/07/2004
+SPoG
+- Fixed SI when not in face-selection mode.
+- Changed patch-create-prefab to use current workzone.
+- Changed engine attribute to be optional in game-description.
+
+24/07/2004
+SPoG
+- Changed module server to support wildcard modules.
+- Cleaned up docs/developer, added README.
+- Removed old TODO.
+
+23/07/2004
+Shamus
+- Initial version of textool.
+MindLink
+- Fixed const bug for vs.net 2005 compiler.
+
+22/07/2004
+SPoG
+- Fixed copy/paste and export-selected failing to export stuff.
+
+19/07/2004
+SPoG
+- Updated win32 setup scripts for q1 entity definitions.
+
+18/07/2004
+SPoG
+- Updated win32 setup scripts.
+- Fixed bug loading 8-bit bmp with <256 palette entries.
+- Added support for loading textures from arbitrary locations.
+- Changed shaders module to load notex/shadernotex from bitmaps/ in .bmp format.
+- Fixed bugs in brush-primitives texdef code.
+
+17/07/2004
+SPoG
+- Added STV:EF support to win32 installer.
+- Moved hardcoded game-specific configuration stuff into .game files.
+
+16/07/2004
+SPoG
+- Fixed crash bug in brush edge/vertex/face selection.
+
+15/07/2004
+SPoG
+- Moved .def files from <enginepath>/<basegame>/scripts/ to <radiantpath>/<gamefilename>/<game>/.
+- Changed entity inspector UI to be driven by entities xml.
+
+14/07/2004
+SPoG
+- Fixed map load/save in brusb-primitives mode.
+- Added files required to run in brush-primitives mode.
+- Added support for changing engine-path while a map is loaded.
+
+
+11/07/2004
+SPoG
+- Changed entity inspector to support custom UI for each entity-class.
+
+10/07/2004
+SPoG
+- Added support for experimental xml version of .def format.
+- Rewrote token parser.
+- Rewrote .def parser.
+- Fixed failure to read show-workzone preference.
+- Refactored quake3 entities module.
+
+03/07/2004
+SPoG
+- Changed QE-style Drag tool to move as well as resize.
+- Fixed shortcuts becoming disabled.
+- Fixed loading file types with upper-case extensions.
+
+30/06/2004
+AcidDeath
+- Added support for plugin submenus.
+
+27/06/2004
+SPoG
+- Added build-menu-command editing.
+- Fixed texture-object reshuffle caused by changing gamma.
+- Refactored vfs/shaders/renderstates/eclass/texturemenu unrealise/realise systems.
+
+26/06/2004
+SPoG
+- Added printf-formatting support to output streams.
+- Added error/warning printing to xml parser.
+- Changed build-menu xml format to allow easier editing.
+- Added sample plugin.
+
+25/06/2004
+SPoG
+- Changed paste and import-map to select pasted/imported entities and world brushes.
+
+24/06/2004
+SPoG
+- Changed create-entity API to use eclass instead of classname.
+- Changed nodes with unknown entity types to use a group-entity if the node has children.
+
+18/06/2004
+SPoG
+- Changed image-loaders interface to use a file object instead of VFS.
+- Changed model-loader interface to support in-place model reloading.
+- Changed picomodel-loader module to support configuration of suppported model types in synapse.config.
+- PicoModel: added support for loading models from an abstract input stream.
+
+14/06/2004
+SPoG
+- Refactored texture browser.
+- Removed GLWindow.
+- Fixed mousewheel movement in camera window.
+
+13/06/2004
+SPoG
+- Added load-entire-wad from textures menu in Quake/HL mode.
+- Fixed bug with writing negative integers to .map format.
+- Fixed texture-browser hide-unused to show only in-use shaders. 
+- Fixed texture-browser scrollbar positioning and origin-clamping.
+- Fixed prompting to save unchanged new maps.
+- Changed unsaved-changes message box default to "Yes, save" instead of "OK, don't save".
+- Changed all message boxes to appear centrally.
+- Removed minimize/maximize buttons from all message boxes.
+
+12/06/2004
+SPoG
+- Disabled shortcut keys during drags.
+- Fixed window updates for edge/vertex multi-selection.
+- Added apply/cancel on enter/escape for texture-browser filter entry.
+- Changed undo system to use explicit start/finish pair to specify undoable operations.
+- Changed undo system to print undoable command after command completion instead of before.
+- Added printing of movement parameters for translate/rotate manipulator drags.
+- Changed brush-subtract to not delete the selection after subtracting.
+- Fixed texture browser to not display textures if only in-use by nodes in the undo-queue.
+- Fixed another workzone-update performance issue causing area-selection to be slow.
+- Added code to brush build-B-Rep to handle duplicate edges.
+
+10/06/2004
+SPoG
+- Added lazy evaluation of local->world transforms and world-space AABBs.
+- Added shortcut key for translate mode, default 'W'.
+- Added toolbar buttons for edge/face/vertex modes.
+- Changed Escape shortcut to deselect-components if components are selected.
+
+02/06/2004
+SPoG
+- Fixed performance bug with workzone updates not being lazily evaluated.
+- Fixed brush edge-graph bug by removing degenerate winding edges.
+
+01/06/2004
+SPoG
+- Added mode information to status bar.
+- Added console feedback describing undoable commands executed.
+- Fixed assertion failures on updating degenerate edge/vertex selections.
+- Fixed detail brushes turning structural when clipped.
+
+31/05/2004
+SPoG
+- Added support for more than one edge/vertex selected per brush.
+
+29/05/2004
+SPoG
+- Refactored groupdialog - decoupled notebook from console/textures/entity pages.
+- Fixed crash in patch tesselator.
+- Fixed floating windows startup crash.
+- Fixed null texture name for patches.
+
+28/05/2004
+SPoG
+- Hide arrows on translate manipulator when obscured by square part.
+- Workaround for main window not being brought to front when a floating window is closed.
+- Fixed rendering of selected components of degenerate brush faces.
+- Fixed double typedef in picomodel.
+- Fixed bug in allocator stuff.
+- Fixed up clipper tool button state.
+- Added workzone updates when selection bounds change.
+- Fixed transient setting on floating inspector windows.
+
+27/05/2004
+Tr3b
+- Fixed gcc build errors.
+SPoG
+- Fixed crash bug in game selection dialog.
+
+26/05/2004
+SPoG
+- Cleaned up project settings.
+- Changed autosave/snapshots to only save modified maps.
+- Refactored build menu.
+
+23/05/2004
+SPoG
+- Fixed minor picomodel ase loader smoothing-groups bug.
+
+19/05/2004
+SPoG
+- Allocator system improvements, fixed warnings
+
+18/05/2004
+SPoG
+- PicoModel: added support for per-vertex smoothing-group, used in generation of normals.
+- PicoModel ASE loader: added support for per-face 'MESH_SMOOTHING' id.
+- PicoModel: changed normal generation code to create smooth normals across texcoord/colour discontinuities.
+- Fixed cosmetic menu bug.
+- Fixed file handle leak in tga loader.
+- Added experimental allocator system.
+
+15/05/2004
+Tr3b
+- Fixed gcc build errors.
+
+11/05/2004
+SPoG
+- Fixed version.h custom build step on win32
+- Refactored preferences dialog to eliminate dependencies on other modules.
+- Redesigned preferences dialog ui layout.
+
+06/05/2004
+SPoG
+- Refactored texture browser.
+
+05/05/2004
+SPoG
+- Upgraded win32 gtk2 version to 2.4.1.
+- Migrated from GtkCombo to GtkComboBox.
+- Texture browser improvements.
+- Fixed malloc/free mismatch bug.
+
+05/05/2004
+SPoG
+- Refactored surface inspector and texture browser.
+
+02/05/2004
+Nurail
+- Added imageq2 module with support for quake2 and heretic2 texture formats: wal, m8, m32.
+
+30/04/2004
+SPoG
+- Changed texture window not to auto-scroll when selecting faces.
+- Changed surface inspector to apply shader seperately from shift/scale/rotate.
+- Changed selected face tracking to use separate selection list.
+
+26/04/2004
+SPoG
+- Added per-file change tracking - only modified (unsaved) files are saved by SaveMap().
+
+18/04/2004
+SPoG
+- Fixed texture-increment-matches-grid.
+- Changed selecting a texture to only change the shader on the selected brushes.
+- Changed 'Axial' button in surface inspector to reset the texdef for selected brushes/faces.
+- Removed MAX_TEXTUREDIRS limit.
+
+11/04/2004
+SPoG
+- OS library module added to wrap calls to rename/unlink/access/stat.
+- OpenGL-view selection tests constrained to current window.
+- Cleaned up OpenURL.
+- Added jk2 and sof2 support to win32 installer.
+
+09/04/2004
+TTimo
+- update the OSX setup / .info generation code
+
+08/04/2004
+SPoG
+- Added integer quantisation for brush edge/vertex drags to fix FP-drift on planes.
+TTimo
+- fix for scons 0.95
+- re-enable Python >= 2.1 version check
+- OSX 10.3: remove obsolete dlsym_auto_underscore (bug #920)
+- OSX: disable q2 tools build (broken thread code)
+
+07/04/2004
+SPoG
+- Moved profile.cpp into a separate static library.
+
+06/04/2004
+SPoG
+- Refactored preferences to be more modular.
+- Fixed preferences being corrupted if a crash occurs during preference saving.
+- Refactored window position saving.
+- Fixed bug in radio button creation in preferences dialog.
+
+24/03/2004
+SPoG
+- Changed surface inspector to unfocus after pressing escape or return, to enable shortcuts.
+- Added refresh of surface inspector for shift/scale/rotate-texdef shortcuts.
+- Fixed bug causing some operations to be applied twice.
+
+21/03/2004
+SPoG
+- Added depth-test and normalisation for translate-manipulator rendering.
+- Added basic clipper-preview rendering.
+
+18/03/2004
+SPoG
+- Added maya-style arrow-heads to translate manipulator.
+- Changed square part of translate manipulator to be viewplane-oriented.
+- Changed square part of translate manipulator to take priority for selection.
+
+15/03/2004
+SPoG
+- Added recalculation of pivot-point when grid size changes.
+- Changed win32 SHGetFolderPath to link with shfolder.lib instead of shell32.lib.
+- Fixed failure to recover brushes from an invalid state.
+
+14/03/2004
+SPoG
+- Improved event handling to make manipulator-dragging smoother in complex scenes.
+- Refactored camera window camera-movement handling.
+
+06/03/2004
+SPoG
+- Fixed vertex/edge undo failing to update selected-vertex position.
+
+29/02/2004
+SPoG
+- Re-enabled next-xy-view in floating windows mode.
+- Reinstated light-radius rendering.
+- Added Wolfenstein support to win32 setup.
+
+24/02/2004
+SPoG
+- Changed create-brush-prism to use correct dimension for prism radius.
+- Changed freelook selection to use window-centre position.
+
+22/02/2004
+SPoG
+- Optimised undo for adding/removing scenegraph nodes.
+- Changed entity-list view to sort the tree by name.
+
+18/02/2004
+SPoG
+- Moved default shaderlist to <AppPath>/<GameFileName>/<GameName>/default_shaderlist.txt
+- Moved user shaderlist to <AppData>/<Version>/<GameFileName>/<GameName>/shaderlist.txt
+
+11/02/2004
+SPoG
+- Refactored clipboard copy/paste code to allow re-use.
+
+10/02/2004
+SPoG
+- Fixed false-positive-intersection bug in CSG subtract algorithm.
+
+07/02/2004
+SPoG
+- SceneGraph: Refactored per-instance functionality.
+- Fixed intermittent culling bug caused by bad bounding boxes.
+- Fixed missing ToggleCubicClip shortcut.
+- Removed modal buttons from Surface Inspector.
+- Changed Surface Inspector keys:
+  - Escape: revert not-yet-committed values to previous state.
+  - Enter: commit not-yet-committed values immediatly.
+- Changed Surface Inspector to update when selection changes.
+
+31/01/2004
+SPoG
+- Cleaned up functional.h template usage with typedefs.
+- Fixed autosave path.
+- Added q1 component to installer.
+- Added radiant_manual component to installer.
+- Added q3-example-maps package to installer.
+
+29/01/2004
+SPoG
+- Added error reporting for module system initialisation failure.
+- Added MSI package creation tools in setup/win32.
+  note: requires MSI SDK binaries in http://zerowing.idsoftware.com/radiant-files/msi/msitools.zip
+- Added initial version of scripts to build basic win32 setup.
+
+26/01/2004
+SPoG
+- Added storing EnginePath for each game in local.pref.
+- Added EnginePath editing to prefs dialog.
+- Added vfs shutdown/init when gamename changes.
+- Added vfs shutdown/init when enginepath changes.
+
+25/01/2004
+SPoG
+- Fixed filtering updates.
+- Moved default bsp menu to <AppPath>/<GameFileName>/default_build_menu.xml
+- Moved user bsp menu to <AppData>/<Version>/<GameFileName>/build_menu.xml
+- Moved synapse.config to <AppPath>/<GameFileName>/synapse.config
+- Moved game-specific .xlink files to <AppPath>/<GameFileName>/*.xlink
+
+25/01/2004
+SPoG
+- Redesigned filter system:
+  - Filtered status updated when filterable attributes change.
+  - Supports per-brush-face filtering.
+- Removed long-dead project-settings stuff:
+  - Moved gamemode and gamename storage into local.pref temporarily.
+  - Moved bsp commands over to a new format, disabled gui editing for now.
+
+20/01/2004
+SPoG
+- Changed win32 Application Data path lookup to use win32 API instead of getenv.
+
+14/01/2004
+SPoG
+- Fixed main menu mnemonics.
+- Fixed crash on exit after viewing pointfile.
+
+13/01/2004
+SPoG
+- Fixed not always resetting 
+component-mode when selection is cleared.
+
+11/01/2004
+Tr3B
+- Added parse/write support for BrushDef3 and PatchDef3.
+  Requires editing synapse.config to enable.
+SPoG
+- Rearranged menus:
+  File = new/open/import/export
+  Edit = manipulate scene hierarchy and selection
+  View = toggle entityinspector/entitylist/surfaceinspector/camera/xy
+    edit camera/xy parameters
+    filters/hideshow/region
+  Modify = transform scene elements
+  Build = bsp menu
+- Fixed Brush-Primitives support:
+  Requires editing synapse.config to enable.
+  Supports load/save of BP mapfiles, and editing BP texdefs in surface inspector
+  (Not yet possible to convert between formats).
+  
+15/12/2003
+SPoG
+- Changed user-prefs to be stored in user-profile directory on win32.
+
+14/12/2003
+SPoG
+- Fixed entitylist window visibility tracking.
+- Implemented find/replace-shader for patches.
+- Changed get-texture-from-selected to update find/replace-shader dialog.
+- Implemented reparent-selected for more than one selected node.
+- Added checks to stop assignment of invalid texture names.
+- Fixed uninitialised texture-compression setting.
+- Fixed bsp menu.
+
+------- spog_branch merged to trunk
+
+10/12/2003
+SPoG
+- Ported imagehl module.
+- Ported imagepng module.
+
+03/12/2003
+SPoG
+- Changed brush winding generation to use use double precision planes.
+- Fixed tracking of modifier key state.
+
+29/11/2003
+SPoG
+- Replaced mathlib with c++ vector/matrix library.
+- Added expression-templates for common vector/matrix operations.
+
+21/11/2003
+SPoG
+- Refactored component-selection stuff.
+- Ported m4x4_t library to c++ Matrix4.
+
+16/11/2003
+SPoG
+- Changed shortcuts.ini to be written automatically.
+- Moved more prefs into specific modules.
+- Changed c++ NULL usage to 0 for maximum portability.
+
+11/11/2003
+SPoG
+- #include cleanup.
+- Added debug output/assert for module initialisation.
+
+09/11/2003
+SPoG
+- Refactored status bar stuff.
+- Refactored window updates to use closures.
+- General cleanup and refactoring.
+
+08/11/2003
+SPoG
+- Increased priority of window redraw events.
+- Ported model module to new module system.
+
+07/11/2003
+SPoG
+- Refactored window updates.
+
+05/11/2003
+SPoG
+- Changed menubar/toolbars to be non-detachable.
+- Fixed empty-undos created when left-clicking in XY window.
+- Refactored camera modelview/projection matrix updates. 
+- Moved application-specific code out of mainframe.cpp.
+- Reinstated brush/entity count in statusbar.
+
+04/11/2003
+SPoG
+- Reinstated instant status-bar updates.
+
+30/10/2003
+SPoG
+- Fixed crosshair cursor in clipper mode.
+
+29/10/2003
+SPoG
+- Changed camera to maintain valid projection/modelview matrices.
+- Moved manipulator-transform update from frustum class to selection system.
+- Removed frame-rate dependency in 3d-window freelook.
+
+27/10/2003
+SPoG
+- Smoothed out xy-window mouse-chasing.
+- Changed mouse-chasing to occur 16 pixels inside the window edges.
+- Changed xy-window to maintain valid projection/modelview matrices.
+- Fixed invalid workzone generated when deselecting with no selection.
+
+26/10/2003
+SPoG
+- Ported changes from trunk between rev 3818 and rev 4036.
+
+25/10/2003
+SPoG
+- Refactored xy-window mouse event handling.
+
+22/10/2003
+SPoG
+- Fixed freelook focus-out event.
+- Changed selection mouse event handling to use modifiers on button-release.
+
+21/10/2003
+SPoG
+- Refactored all mouse event handling for camera window.
+- Changed menus/toolbars/accelerators to use anonymous closures.
+
+20/10/2003
+SPoG
+- Fixed get-pointer-in-screen-coordinates on win32.
+- Changed patch prefs to use preference-system module.
+- Fixed selection of side-on faces.
+- Changed brush rendering to avoid glPushClientAttrib - workaround for ATI driver issue.
+
+19/10/2003
+SPoG
+- Changed VFS directory initialisation to occur after module initialisation.
+- Changed load-preferences to occur after module initialisation.
+- Added preference-system module.
+- Changed undo prefs to use preference-system module.
+- Restored splash screen with non-intrusive behaviour.
+- Cleaned up main-toolbar creation.
+- Fixed floating windows behaviour when main window is minimised.
+- Changed shader-list parsing to use new script tokeniser.
+- Changed deprecated code using GtkPixmap to use GtkImage.
+- Removed bitmap-loading from core.
+- Removed pc-speaker beep on map-save.
+
+17/10/2003
+SPoG
+- Fixed crash when trying to undo on an empty undo queue.
+- Refactored gtkdlgs, using helper functions to create common widgets.
+- Changed Dialog class to use std::list for data.
+
+13/10/2003
+SPoG
+- Refactored entity inspector.
+- Removed miscellaneous unused functions.
+- Refactored qe3 header.
+- Moved texture-window preferences into texwindow.cpp.
+
+12/10/2003
+SPoG
+- Moved layout-mode dependant code into main-frame creation.
+- Replaced prefs system with new import/export system.
+- Fixed gcc3.3 build errors.
+
+11/10/2003
+SPoG
+- Moved unnecessary methods from MainFrame into free functions.
+- Removed unsupported toolbar buttons and menu items.
+- Changed misc->gamma to not require restart.
+- Fixed unmaximised window-size when loading main window maximised.
+- Fixed saving of rotate increment preference.
+
+10/10/2003
+SPoG
+- Fixed keyboard shortcuts intercepting input to texture-subsets text-entry.
+
+09/10/2003
+SPoG
+- Fixed gcc3 build errors, compiled and tested on linux.
+
+08/10/2003
+SPoG
+- Fixed brush snap-to-grid creating huge coordinate values.
+- Fixed minor bug in selection menu.
+
+07/10/2003
+SPoG
+- Cleaned up MainFrame.
+- Added quantisation of plane pts when dragging.
+- Fixed create-empty-brush bug.
+
+06/10/2003
+SPoG
+- Moved control of camera keyboard-accelerators into camera window module.
+
+05/10/2003
+SPoG
+- Separated keyboard-accelerators from menu items, using functors.
+- Completed factoring out HandleCommand.
+
+04/10/2003
+SPoG
+- Changed 4-way-split mode to automatically reposition separators when window size changes.
+- Fixed gtk error in floating-entity/textures/console window.
+- Fixed position of console horizontal pane separator.
+
+03/10/2003
+SPoG
+- Work-in-progress factoring out HandleCommand.
+
+02/10/2003
+SPoG
+- Fixed pink icons on main window on win32.
+- Replaced g_bIgnoreCommands with signal block/unblock.
+- Refactored MainFrame startup.
+
+01/10/2003
+SPoG
+- Fixed entity-window redraw on selection change.
+- Moved control over VFS init/shutdown to module system.
+- Fixed failure to release translucency render-states.
+- Added support for realise/unrealise of all opengl texture objects.
+- Refactored startup/shutdown logic.
+  Changed quit commands to do nothing but call gtk_main_quit().
+  Added code after gtk_main() to destroy stuff.
+- Changed 25ms timeout-handler to an idle-handler for window updates.
+  (reduces redraw-request response time on fast machines)
+- Moved gl-shutdown control to glwidget.
+  Textures are realised/unrealised when the shared context is created/destroyed.
+- Fixed lack of a valid gl context when unrealising gl textures.
+
+30/09/2003
+SPoG
+- Added support for translucent entity rendering.
+
+29/09/2003
+SPoG
+- Changed all global modules to use GlobalModule helper templates.
+- Ported qgl.c to c++.
+- Changed win32 project to dynamic-link with opengl32.lib.
+
+28/09/2003
+SPoG
+- Added new experimental xml preference import/export system.
+- Refactored dialog base class:
+  Moved common dialog-element-creation code into helper functions.
+  Changed UpdateData to use per-element callback functions.
+- Refactored preferences dialog.
+
+26/09/2003
+SPoG
+- Reversed winding order for circle primitives.
+
+25/09/2003
+SPoG
+- Fixed slow selection response in large maps.
+
+21/09/2003
+SPoG
+- Added sharing of global modules within a client.
+- Added quake map module and wal image module.
+- Ported mip image module and hlw image module.
+- Cleaned up imagehl module.
+- Fixed crash in pcx image module.
+- Rewrote md3 model module.
+- Ported mdl, md2 and mdc model modules.
+- Added filtering of q1/q2 clip brushes.
+- Added ati-crash-workaround rendering path.
+- Upgraded to gtk+-2.2.4 on win32:
+  Fixed capslock affecting shortcut-keys.
+- Upgraded to gtkglext-1.0.4 on win32.
+- Fixed copy/paste.
+- Added shortcut-key support to entity treeview.
+
+17/09/2003
+SPoG
+- Fixed failure to call vfsFreeFile on an empty buffer.
+- Fixed calling convention for dlls in new module system.
+- Changed map.cpp to support maps without a worldspawn entity.
+- Fixed crash on attempting to clone a map root.
+- Added filter-update calls after loading or cloning stuff.
+- Fixed reference cache failing to save a file.
+
+16/09/2003
+SPoG
+- Refactored client-side module system code for direct module access.
+- Changed shaders, vfs, model, brush, patch and entity module interfaces
+  to use abstract base class.
+- Removed unused functions from shaders and vfs interfaces.
+
+15/09/2003
+SPoG
+- Removed synapse dependencies for win32 makefiles.
+- Added find-first-module-of-type helper function.
+
+14/09/2003
+SPoG
+- Added new lightweight module system:
+  Initialises each module the first time it is requested.
+  Does not allow configurations with cyclic runtime dependencies.
+  Provides templates for simple type-safe client-side implementation.
+  Requires no client-side linkage.
+- Split radiant API into multiple APIs:
+  core, textures, scenegraph, selection, renderstate, filters, filetypes.
+- Ported radiant, core, mapq3, mapxml, md3model, entity, shaders, image,
+  vfspk3, archivewad, archivepak, archivezip to new module system.
+
+11/09/2003
+SPoG
+- Removed edge and vertex integer-snapping during selection.
+
+10/09/2003
+SPoG
+- Replaced map in referencecache.cpp with a hashtable.
+- Changed ReferenceCache interface to take a path string,
+  which can be either absolute or relative.
+
+08/09/2003
+SPoG
+- Cleaned up qertypes.h - split into multiple files.
+- Moved texdef stuff into itexdef.h.
+- Fixed shutdown destruction order bug. 
+
+07/09/2003
+SPoG
+- Refactored texwindow.cpp.
+  Moved texture management code into textures.cpp.
+  Added textures api.
+  Replaced globals from texwindow.h with accessor functions.
+- Cleaned up shaders module.
+  Removed color-shader stuff.
+  Rewrote shader-activation logic to use textures API.
+  Removed appshaders API.
+- Refactored shutdown logic.
+  Moved non-mainframe shutdown stuff into Radiant_Shutdown().
+  Added deferred render-state realisation.
+- Fixed failure to create gl contexts in 16-bit mode for latest nvidia drivers.
+- Changed hashtable template to use traits parameter
+  for case-insensitive hasher and keyequal functions.
+- Removed unused functions from qerplugin API.
+
+02/09/2003
+SPoG
+- Refactored code to remove global-object accesses:
+  Passing global objects as parameters to functions.
+- Refactored texwindow.
+- Moved synapse server out of pluginmanager.
+  Changed pluginmanager to handle nothing but IPlugin stuff.
+
+01/09/2003
+SPoG
+- Refactored scenelib.h, split into multiple files.
+- Refactored #includes related to scenelib.h.
+- Refactored preferences for xywindow and camwindow.
+- Refactored references to g_pParentWnd in xywindow and camwindow.
+
+30/08/2003
+SPoG
+- Ported changes from trunk since 17/08/2003.
+- Ported all changes from bug800-spog_branch (vfs rewrite and q1 support).
+
+29/08/2003
+SPoG
+- Refactored component-selection stuff.
+- Fixed selection-tracking bug in patches.
+
+28/08/2003
+SPoG
+- Added support for line-strips to Selectors.
+- Fixed selection for entity treeview.
+- Refactored external-resource loading.
+
+20/08/2003
+SPoG
+- Fixed snap-to-grid in edge and vertex modes.
+- Added a default model to use when a model load fails.
+
+19/08/2003
+SPoG
+- Changed snap-to-grid to vastly reduce the possibility of creating an invalid plane.
+
+17/08/2003
+SPoG
+- Ported changes from trunk since 01/08/2003.
+
+12/08/2003
+SPoG
+- Changed entity key/value tracking to only track keys already added to the entity.
+- Fixed bug causing undo system to track scene changes during a queue-flush operation.
+
+12/08/2003
+SPoG
+- Fixed bug in project settings bsp-commands display.
+- Fixed empty undos being created by rotation buttons.
+- Fixed rotation pivot for rotation buttons.
+
+09/08/2003
+SPoG
+- Added property svn:eol-style=native to all text files.
+- Added property evn:eol-style=CRLF to all dsp and dsw files.
+- Partially ported bobtoolz to use new spog_branch module APIs.
+- Removed Sys_UpdateScene.
+- Added Map_Name() for access to currentmap variable.
+- Added initial drag-n-drop support for graph tree-model.
+
+01/08/2003
+SPoG
+- Fixed uninitialised refcount in entity key class.
+- Fixed memory leak in shader parsing.
+- Added reference-counting holder for worldspawn node.
+- Moved string class and utilities into a new header in libs dir.
+- Fixed external-file-resource cache to use case-insensitive name compare on win32.
+- Fixed shaders to use case-insensitive name compare.
+- Fixed shader module to display SHADER_NOT_FOUND when appropriate.
+- Changed the default texture name to "NULL" instead of SHADER_NOT_FOUND.
+- Changed move-into-entity to perform parent-selection-to-last-selected-node.
+- Added a new implementation of GtkTreeModel operating directly on the scenegraph.
+- Fixed disable-screen-updates to queue update requests instead of ignoring them.
+- Merged from trunk (tag head-cvs2svn-2).
+
+22/07/2003
+SPoG
+- Changed scale/flip-selection to use the manipulator as a pivot point.
+- Added OnShutdown callback for CSynapseClient, used in entity module.
+- Fixed console updates when loading maps/models.
+
+20/07/2003
+SPoG
+- Added renderer support for qer_alphatest and qer_cull.
+- Merged 'picomodule' module into 'model' module.
+- Added rendering of area-selection rectangle.
+
+19/07/2003
+SPoG
+- Merged from trunk.
+
+18/07/2003
+SPoG
+- Disabled deleting classname key in entity inspector window.
+- Cleaned up some stuff in selection system.
+- Added basic versions of std::mem_fun and std::bind1st to function-object library.
+
+10/07/2003
+SPoG
+- Implemented connect-entities.
+
+09/07/2003
+SPoG
+- Completed local-space rotation manipulator.
+- Fixed cloning objects within a misc_model subgraph.
+- Fixed crash bug in loading certain models.
+
+06/07/2003
+SPoG
+- Added function-object library header, similar to boost::function.
+- Changed undo system to improve performance.
+- Refactored entity inspector implementation.
+
+22/06/2003
+SPoG
+- Refactored selection observing stuff.
+- Changed shader parsing to use new tokeniser.
+- Changed implementation of entities to use generic container.
+- Refactored entity wrapper system.
+- Fixed undo on delete/reset entity keys.
+
+21/06/2003
+SPoG
+- Added rendering of target/targetname connection lines.
+- Moved entity and eclass stuff out of qertypes.h into ientity and ieclass.
+- Refactored entity_t to hide it behind Entity interface.
+- Removed global project settings entity.
+- Cleaned up bsp-command editing in project settings dialog.
+
+17/06/2003
+SPoG
+- Fixed back-face-culling for selections by working in screen-space.
+
+16/06/2003
+SPoG
+- Added workaround for nvidia driver opengl vertex arrays bug.
+
+15/06/2003
+SPoG
+- Refactored Patch implementation.
+- Refactored scene graph system to allow multiple graph instances.
+
+13/06/2003
+SPoG
+- Added snap-selected-components-to-grid for faces edges and vertices.
+
+11/06/2003
+SPoG
+- Improved normal-quantisation code.
+
+10/06/2003
+SPoG
+- Changed renderer vertex types to be struct instead of typedef'd array.
+- Added experimental quantisation of normals.
+
+05/06/2003
+SPoG
+- Fixed intermittent crash in face-fit-texture.
+- Changed patch rendering to display components only in vertex mode.
+
+02/06/2003
+SPoG
+- Added nameable interface for scene graph nodes.
+- Fixed undo for set-detail and set-structural.
+- Added rendering of arrow for angled entities.
+
+01/06/2003
+SPoG
+- Fixed handling of invalid planes during brush b-rep build.
+- Refactored brush copy-construction/assignment.
+- Fixed lack of rebuild after removing empty faces.
+- Added lightjunior entity display.
+- Fixed display of spawnflags/info for selected entity.
+- Fixed update of entity window on setting spawnflags.
+- Fixed botclip filtering.
+- Fixed uninitialised alpha channel on jpg images by ignoring alpha.
+
+31/05/2003
+SPoG
+- Cleaned up undo calls in brush and patch implementation.
+- Changed brush implementation to defer rebuilds until needed.
+- Fixed undo for find/replace shader.
+- Refactored brush implementation, removed empty-face list.
+- Fixed crash on loading unrecognised entities containing brushes.
+- Fixed crashes in renderer caused by state-stack underflow.
+- Fixed handling of invalid and duplicate planes during brush editing.
+- Fixed failure to save brush faces during save-as.
+- Refactored brush data members.
+
+28/05/2003
+SPoG
+- Fixed crash on selecting stuff from entity list window.
+
+27/05/2003
+SPoG
+- Fixed window title after save-as.
+
+22/05/2003
+SPoG
+- Refactored selection system interface slightly.
+- Removed old brushwrapper stuff.
+- Fixed clipper-split-selection to keep both parts selected.
+
+21/05/2003
+SPoG
+- Added select-faces-by-shader.
+- Fixed find/replace-shader.
+
+19/05/2003
+SPoG
+- Fixed rotation on misc_model.
+
+13/05/2003
+SPoG
+- Fixed lack of undo on create-n-sided-brush.
+
+29/04/2003
+SPoG
+- Fixed per-face find/replace and per-face nudge rotation.
+
+25/04/2003
+SPoG
+- Fixed find-brush.
+- Changed rotation buttons to use perfect precision for 90-degree rotations.
+
+24/04/2003
+SPoG
+- Added find-dir-for-relative-filename and find-dir-for-absolute-filename to vfs.
+- Changed resource manager to handle per-mod resources using vfs.
+- Changed resource manager to allow resources with absolute paths.
+- Fixed selection-test behaving like an ellipse instead of a rectangle.
+
+23/04/2003
+SPoG
+- Changed selection test to choose closest-to-cursor over closest-to-camera.
+
+22/04/2003
+SPoG
+- Fixed reference counting on shaders loaded from a texture directory.
+- Fixed show-in-use and show-all shaders.
+- Fixed undo for patch-set-shader.
+- Changed shaders module to use STL map container instead of CShaderArray.
+- Fixed SelectAllOfType for entities and patches.
+- Cleaned up unused functions in shaders API.
+- Decoupled selecting a texture in texture window from applying a texture to selection.
+
+21/04/2003
+SPoG
+- Fixed memory leaks in image loaders, texdef_t, csg subtract, picomodel module.
+- Fixed uninitialised memory references in renderer, texdef_t, eclass loader, undo system.
+- Refactored tga loader.
+- Cleaned up image module, enabled pcx and bmp loaders.
+
+17/04/2003
+SPoG
+- Fixed shift-texture on selected brush faces.
+- Changed brush b-rep algorithm to have higher tolerance for similar planes.
+- Changed brush b-rep algorithm to always produce a valid connectivity graph.
+- Added setting/getting shader for patches.
+
+16/04/2003
+SPoG
+- Fixed tracking of in-use shaders (though undo queue still keeps shader references).
+- Changed brush faces to store state in undo-system cleanly.
+- Fixed flush & reload shaders and sleep/wake.
+- Ensured that shaders are never leaked.
+- Fixed bool conversion warnings.
+
+15/04/2003
+SPoG
+- Added clamping of planepts on export to nearest 65536th of 1 unit.
+- Changed m4x4 rotation functions to use double-precision for angles in radians.
+- Changed m4x4 quaternion rotation to use double-precision internally.
+- Changed float printing to use %g instead of %f (strips trailing zeros).
+
+13/04/2003
+SPoG
+- Fixed brush import failing to update bounding boxes.
+
+11/04/2003
+SPoG
+- Refactored Brush class into Brush, BrushInstance and BrushNode.
+- Fixed various flaws stopping brush b-rep algorithm from being 100% reliable.
+
+02/04/2003
+SPoG
+- Changed manipulator to move to position of selected brush components.
+
+01/04/2003
+SPoG
+- Fixed xml parser failing to resolve predefined entities.
+
+31/03/2003
+SPoG
+- Fixed asserts in brush manipulation when creating invalid brushes.
+- Removed automatic update of current texdef.
+- Added Get Texture and Set Texture to textures menu.
+
+29/03/2003
+SPoG
+- Fixed array template failing to free zero-sized allocations.
+- Changed clipper mode to behave as a component-editing-mode.
+- Removed right-click-to-drop-clip-point - use X and leftclick instead.
+
+28/03/2003
+SPoG
+- Changed scene graph to sort objects in ascending order of creation time.
+
+27/03/2003
+SPoG
+- Fixed bug in clone-selection causing only first selected brush to be cloned.
+- Optimised select-all for brush/patch components.
+- Changed edge/face/vertex toggles to toggle correctly.
+
+26/03/2003
+SPoG
+- Removed win32/x dependencies from gl interface.
+- Removed win32/glib dependencies from core interface.
+- Replaced void* in gtk helper functions with forward-declared GtkWidget.
+- Changed gtk helper functions to return enumerated values instead of win32 IDOK.
+- Removed WINAPI macro for __stdcall from all interfaces.
+- Removed unnecessary dependencies from core stdafx/qe3 header.
+
+25/03/2003
+SPoG
+- Changed class-level render states to be static for Brush and Patch.
+- Refactored brush implementation - breaking it up into smaller parts.
+- Added refcounted ptr template to track refcounts.
+- Fixed refcount bug introduced by new clone-selection.
+- Fixed warnings in brush implementation.
+- Cleaned up plugin interface header inclusion.
+
+24/03/2003
+SPoG
+- Fixed crash on building unbounded brushes in release build.
+- Changed assertion failures to be non-fatal in release build.
+- Moved OS-specific gl headers into separate files.
+- Moved app-shaders interface into a separate file.
+- Cleaned up dependencies for brush implementation.
+
+23/03/2003
+SPoG
+- Added per-instance selection of patch vertices.
+- Fixed per-instance vertex selection rendering on multiple instances.
+- Refactored patch/brush render code.
+- Changed manipulator transforms to convert to local space before applying.
+- Fixed selection test for picomodule meshes.
+- Fixed selection test winding order for triangles.
+- Fixed update of window title on new-map and load-map.
+- Changed selection to work with exactly side-on faces.
+- Refactored instance implementation to reduce code bloat.
+- Fixed map export always exporting root.
+
+21/03/2003
+SPoG
+- Fixed external resource tracking to preserve uppercase characters in names.
+- Changed clone-selection to not use global copy/paste.
+
+20/03/2003
+SPoG
+- Changed map-save to save all saveable files that the map references.
+
+16/03/2003
+SPoG
+- Moved hashtable and hashfunc into libs.
+- Cleaned up renderer interface and selection interface.
+- Refactored frustum testing class.
+
+12/03/2003
+SPoG
+- Moved winding-specific stuff from brush obj to winding obj.
+- Refactored filter subsystem to remove dependency on entity/brush/patch.
+
+07/03/2003
+SPoG
+- Fixed crash when clicking cancel from patch cap-dialog.
+- Changed selection tests to ignore back-facing faces.
+
+05/03/2003
+SPoG
+- Fixed failure to release cloned scene graph nodes.
+- Fixed selection manager failing to release render states.
+- Fixed eclass system failing to release render states.
+
+04/03/2003
+SPoG
+- Fixed writing-past-end of vertex arrays in brush rendering.
+- Fixed releasing data stored in undo system when deleting undoables.
+- Fixed crash in misc_model when model fails to load.
+- Fixed undo for clone/rotate/flip/nudge/set-texture operations.
+- Cleaned up surface dialog.
+
+01/03/2003
+SPoG
+- Changed clipper split-selection to keep result selected.
+- Cleaned up and finalised picomodule, adding to cvs.
+
+28/02/2003
+SPoG
+- Cleaned up entity list window.
+- Fixed crash on freeing a map while entity list node is selected.
+- Fixed crash on clone/copy of externally referenced brushes.
+- Added multiple-selection support to entity list.
+- Added updating entity list selection display on selection changes.
+
+26/02/2003
+SPoG
+- Added stl_warnings include.
+- Fixed tracking of map-modified-since-last-saved.
+
+24/02/2003
+SPoG
+- Fixed missing map-release when map-load fails.
+- Changed map-rename (save-as) to flush undo queue.
+- Fixed bug in exporting selections.
+
+23/02/2003
+SPoG
+- Fixed redo on changing misc_model "model" key.
+
+22/02/2003
+SPoG
+- Changed undo interface to factor out global undo system.
+
+21/02/2003
+SPoG
+- Started cleaning up Map subsystem.
+
+20/02/2003
+SPoG
+- Added 'clone subgraph' feature to core, using direct xml import/export.
+- Added 'save' feature to reference cache.
+- Added scope timer object.
+- Changed scene graph interface to allow setting scene root.
+- Changed core to use reference cache to track current map.
+- Removed mapmodel module.
+- Fixed relative paths for loading maps as misc_model.
+
+19/02/2003
+SPoG
+- Changed model/map modules to register their file types on load.
+- Added map module manager to support unlimited map loader modules.
+
+18/02/2003
+SPoG
+- Changed vertex buffer template to support resizing.
+- Changed vertex buffer search algorithm to iterate instead of recurse.
+
+17/02/2003
+SPoG
+- Fixed sorting bug with render-states.
+- Fixed colour state when disabling gl_color_array.
+- Fixed unterminated loop in scenegraph traversal.
+- Fixed freeing project entity twice on shutdown (infinite loop).
+- Fixed failing to destroy the scene graph on exit (oops).
+
+07/02/2003
+SPoG
+- Added updating current texdef when a face is selected.
+- Fixed crash when creating a brush with duplicate planes.
+
+06/02/2003
+SPoG
+- Fixed various issues with 'save region'.
+- Changed default current texdef to use game-specific scale.
+- Changed brush creation to use current texdef.
+- Changed clipper to use current texdef.
+- Fixed bug in selection counting for patch control points.
+
+05/02/2003
+SPoG
+- Fixed reversed solid-selection-outline preference.
+- Finished factoring out face_t.
+- Added script token writer interface for map export.
+- Changed map export interface to use script token writer.
+
+04/02/2003
+SPoG
+- Added depth-buffer-write enable/disable feature to renderer.
+- Changed Pointfile class to use renderer.
+- Continued factoring out face_t.
+
+03/02/2003
+SPoG
+- Fixed temporary objects leaving dangling references in the undo system.
+- Changed import-map to not modify existing selection.
+
+02/02/2003
+SPoG
+- Fixed frustum culling for transformed nodes.
+- Fixed hide/filter/region to work independently.
+- Added highlighting of selected brush faces in component mode.
+- Fixed bug detecting thin area-selection if dragged down or left.
+- Renamed brush_type to Brush.
+- Renamed face_type to Face.
+- Started factoring out face_t.
+
+01/02/2003
+SPoG
+- Improved edge and vertex manipulation.
+- Removed unnecessary graph traversals for rendering/selection.
+
+31/01/2003
+SPoG
+- Merged changes since last merge from merge-1_2_10-post to spog_branch.
+- Merged changes since last merge from HEAD to spog_branch.
+- Tagged HEAD after merging as 'merge-spog_branch-post'.
+- Added walker to merge sibling worldspawns.
+- Merged changes to Construct for PPC from trunk.
+- Fixed over-enthusiastic worldspawn merging.
+- Fixed misc_model "angle" key setting pitch instead of yaw.
+- Fixed entity set-key-value changing scene-graph topology.
+
+30/01/2003
+SPoG
+- Added subgraph traversal feature to scenegraph traversal.
+
+29/01/2003
+SPoG
+- Changed scene graph implementation to allow nested traversals.
+
+28/01/2003
+SPoG
+- Fixed angles key order for misc_model.
+
+27/01/2003
+SPoG
+- Fixed typo causing set-texture-of-selection to behave incorrectly.
+
+26/01/2003
+SPoG
+- Replaced all tabs with spaces in CHANGES.
+- Fixed entity bounds updates for 'light'.
+- Fixed code that doesn't conform to c++ standard as enforced by gcc.
+
+24/01/2003
+SPoG
+- Added missing file: icharstream.h.
+- Fixed bug with synchronisation of brush-face instance data.
+- Added .map format import/export interfaces.
+- Removed last remnants of IBrush.
+- Removed IPatch.
+- Moved walkers defined in in mainframe.cpp to appropriate places.
+
+23/01/2003
+SPoG
+- Changed scenegraph traversals to use a compiled graph.
+
+20/01/2003
+SPoG
+- Changed selection interface to hide per-instance data.
+- Added streaming tokeniser for .map format.
+- Changed mapq3 module to use streaming tokeniser.
+- Added xml stream interface for input and output.
+- Added xml stream parser based on libxml2 SAX.
+- Changed mapxml module to use xml stream input.
+- Changed brush and patch to use xml stream input.
+- Added xml stream writer.
+- Changed mapxml module to use stream output.
+- Changed brush and patch to use xml stream output.
+
+
+16/01/2003
+SPoG
+- Disabled pivot updates while selection is being manipulated.
+- Changed pivot calculation to use instanced world-bounding-box.
+- Fixed crash bug in PositionView.
+
+14/01/2003
+SPoG
+- Merged with branch merge-1_2_10-post at tag spog_merge_merge-1_2_10-post
+- Removed 10k+ lines of unused #if 0 code.
+- Removed unused declarations in qe3.h.
+- Removed brush and face types from qertypes.h.
+- Removed plugin API stuff dependant on brush type.
+- Added per-instance selection for brush faces.
+
+08/01/2003
+SPoG
+- Added selection counters for primitive/component modes.
+- Added face-drag mode (default shortcut key = F).
+- Added face-centre-point rendering/selection/editing.
+
+07/01/2003
+SPoG
+- Changed selection to work per-instance.
+
+06/01/2003
+SPoG
+- Changed selector interface to allow per-entity selection tests.
+
+06/12/2002
+SPoG
+- Added selection-test and selector objects to clean up selection system.
+- Unified key modifiers for selection in both primitive and component modes.
+- Added mapmodel module to load .map and .xmap as misc_model.
+
+02/12/2002
+SPoG
+- Added debug rendering of a selection test.
+- Fixed bugs in triangle/line clipper, making selection work properly.
+- Refactored selection system interface.
+- Added undo for texture nudge.
+- Fixed minor render-state bug.
+
+29/11/2002
+SPoG
+- Optimised wireframe drawing of brushes with back-face culling.
+- Optimised brush-winding generation.
+- Changed winding generation to be more robust with large world extents.
+- Fixed crashes with unbounded-face and degenerate-edge cases.
+
+20/11/2002
+SPoG
+- Completed rotation manipulator.
+- Added translation manipulator for the default editing mode.
+- Changed XY mouse-chaser speed to depend on distance mouse moved outside window.
+
+15/11/2002
+SPoG
+- Added initial version of maya-style manipulators - rotation manipulator.
+
+07/11/2002
+SPoG
+- Fixed false asserts in Brush ConstructPrefab.
+- Undo system optimisation - uses binary-sorted container to speed up finding already-added objects.
+- Fixed crash when transforming objects which don't support edit_interface.
+- Fixed clone command to nudge the selection after cloning.
+- Fixed clipper to remove brushes that are completely behind the clip plane.
+
+06/11/2002
+SPoG
+- Brushes: cleaned up per-face operations to use face visitor pattern.
+- Fixed setting brush face texdef, with fully functioning undo on individual brush faces.
+
+04/11/2002
+SPoG
+- Refactored renderer to two objects, camera and XY renderer - XY uses entity shaders.
+- Experimental pivot object.. work-in-progress.
+- Modified scene-graph instance-caching to maintain multiple instances within nodes.
+- Fixed undo bug, deleting a void* doesn't call the destructor.
+- Rewrote filters system to work with scene graph system.
+- Cleaned up quake entity module to provide same functionality as before.
+- Refactored render-state cache to use generic hashtable and reference-cache templates.
+
+19/10/2002
+SPoG - spog_branch - experimental - work-in-progress
+- added scene graph library: defines interfaces, generic graph node types,
+  re-usable systems for traversals, traversal paths, node containers,
+  multiple-instance caching of world-space-transforms/bounding-volumes/visibility.
+- added scene graph traversals to replace all traversals of 'active_brushes',
+  'selected_brushes', 'filtered_brushes' and 'entities' linked-lists.
+- added view module: view-volume-culling system acting on the scene graph,
+  uses scene heirarchy to minimise culling tests per frame.
+- added opengl-state module: sorts opengl-state objects (shaders) to minimise
+  opengl state changes during rendering.
+- added renderer module: culls objects outside the view volume,
+  gathers non-culled renderable objects from the scene graph,
+  keeps track of state during traversal, adds renderable objects to correct opengl-state.
+- added selection module: sets view volume to the selection box/ray, culls
+  objects outside the view volume, gathers non-culled selectable objects
+  from the scene graph (entity/primitive/component),
+  selects gathered objects (select/toggle/cycle) or moves things if already-selected.
+- added patch module: encapsulates a patch as a scene graph node,
+  optimised patch tesselation.
+- added brush module: encapsulates a brush as a scene graph node,
+  adapts multiple-brush operations to use the scene graph.
+- adapted entity module: encapsulates an entity as a scene graph node/subtree,
+  shares common code between different visualised entity types.
+- adapted model module: encapsulates a model as a scene graph node/subtree.
+- added undo module: completely new compact infinite-undo-system,
+  operates on undoable objects, uses minimal-state data to store objects,
+  uses refcounting to undo "deleted" objects.
+
+TODO: cleanup: many simple things are still broken or not functioning in the right way..
+see !\todo items in the code (not all are documented yet though).
+Selection module probably needs refactoring some more - perhaps split off the move-already-selected stuff.
+The dependencies are still pretty bad.. need to refactor stdafx.h/qertypes.h.
+Some of the above modules are not really modules, they're static-linked to the core, but could easily be dynamic-linked.
+The interfaces to brushes and entities still expose brush_t and entity_t for backwards-compatibility.
+NOTE: some todos are #if 0 because their functionality is (or will be) replaced by the new systems.
+
+------ branch point - spog_branch
+
+30/08/2003
+SPoG
+- Ported changes from trunk.
+
+17/08/2003
+SPoG
+- Ported changes from trunk.
+- Added quake pack to win32 setup scripts.
+- Fixed crash in RunBsp.
+
+17/05/2003
+SPoG
+- Renamed stream interfaces with C and I prefix.
+- Shoehorned bytestream into idatastream.
+- Moved member classes out of IArchive, replaced with member typedefs.
+- Renamed filesystem, path, dynamic string, file input stream with C and I prefix.
+- Documented filesystem, path, dynamic string, file input stream.
+- Cleaned up game-specific encapsulation classes a little.
+
+16/05/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=815
+  found out about string_t that slept through my reviews
+
+Updated list of broken stuff on this branch:
+
+- include/bytestream.h: remove this file, extend idatastream.h header
+from the code conventions:
+  include/ directory:
+  This directory is holding the API header files for the synapse modules (plus a few build control and version related headers)
+  All headers that describe synapse APIs should start with an i: ishader.h igl.h 
+
+  The few files in include/ that don't start with a lowercase i are specific files for build control and configuration.
+  Regular developement never creates non i-prefixed files in include/
+  
+the merge with IDataStream goes like this (note the corrected class names):
+class IInputStream
+class IOutputStream
+
+class IDataStream : public IInputStream, IOutputStream
+
+class ISeekableStream
+class ISeekableInputStream : public IInputStream, public ISeekableStream
+class ISeekableOutputStream : public IOutputStream, public ISeekableStream
+
+typedef unsigned int size_type; goes away, use size_t
+
+- include/iarchive.h
+
+renamed VisitorFunc to IArchiveVisitor
+move it out of IArchive class (keep it in iarchive.h though)
+from code conventions:
+  Don't declare classes inside classes. Makes the code harder to read and isn't useful to anything.
+
+- remove libs/bytestreamutils.h
+put that functionality into the IStream stuff / idatastream.h stuff
+anything you retrieve from an IStream should be endian-correct
+
+- libs/filestream.h
+I'd rather see a header without embedded code, and a .cpp file for it
+
+- libs/fs_filesystem.h libs/fs_path.h
+those totally lack documentation about what they are doing
+same as above. way too much embedded code. makes things harder to maintain. implement in a .cpp
+and as usual, name the classes correctly, C and I prefixes
+
+- gamespecific_t: rename correctly to CGameSpecific
+I like the idea of gathering all hardocded game-specific behaviours inside one same class.
+But is it really the topic of bug800?
+
+- gamespecific_executable_t: rename correctly to CGameSpecificExecutable
+shouldn't this be merged with CGameSpecific?
+
+12/05/2003
+SPoG
+- Fixed win32 build error (win32 has no <dirent.h>).
+- Added dir_good() check to handle failure of dir_open() in posix DIR wrapper.
+- Renamed dynamic_string_t and path_t to DynamicString and UnixPath respectively.
+- Removed unnecessary use of 'inline' and 'virtual' keywords in class definitions (bad habit).
+- Documented archive interface.
+
+09/05/2003
+TTimo
+- some easy fixes to get it to startup on Linux
+- tagging the current source as bug800-spog, preparing rollback
+
+
+SPoG
+- Added an implementation of IArchive to do OS filesystem access.
+- Changed vfspk3 to use above implementation for OS filesystem access.
+- Added const qualifiers to vfsGetFullPath and everything dependant on it.
+- Changed vfsGetFileList to use "*" to indicate all-files instead of a NULL pointer.
+- Extended IArchive interface to allow for extra filesystem functionality.
+  Added method to check if a file exists quickly.
+  Added method to traverse the filesystem with control on start-dir and depth of recursion.
+- Defined implementation requirements for IArchive.
+  An archive contains a heirarchy of directories and files, and may contain empty directories.
+  An archive can be traversed in directory order.
+  Directories can be distinguished from files during a traversal.
+  Directory paths will always end with a separator.
+  File entries can be opened as an IArchiveFile.
+  IArchiveFile provides a simple non-seekable input stream which can only be read forwards.
+  Any number of files may be opened and read from an archive simultaneously.
+  An archive may be released while one or more files are still open, the files will remain valid until released.
+- Changed archivepak, archivezip and archivewad to implement all IArchive requirements.
+- Factored common code from archive implementations out into new lib/headers:
+  fs_filesystem.h: a templated filesystem container, with iterators and efficient traversal.
+  fs_path.h: a dynamic filesystem path object, with separator checking and efficient memory management.
+  ibytestream.h: abstract interfaces for input byte streams.
+  bytestream.h: utilities operating on abstract input byte streams.
+  filestream.h: a c++ wrapper for stdc FILE object, implementing a seekable input stream.
+- Added a new pkzip-reader implementation, designed to be orthogonal to the compression library used.
+- Added a zlib input stream object, which decompresses data from an abstract byte stream on the fly.
+- Removed archivezip code copy/pasted/hacked from zlib and unzip.c, replaced by pkzip-reader and zlib input stream.
+- Changed vfsLoadFile to return 0 for a zero-sized file, only returning -1 if it failed to load the file.
+- Removed halflife-specific disabling of shader-loading, thereby allowing common-hydra.shader to work.
+- Added archivezip, archivewad and archivepak to win32 setup scripts.
+- Updated win32 setup scripts for halflife media.
+- Updated cons scripts for archivezip, archivewad and archivepak.
+- Added printing of warnings when vfs functions are given invalid input paths.
+
+
+-------- branchpoint: "bug800-spog_branch"
+
+
+30/08/2003
+SPoG
+- Ported changes from trunk since branch point.
+
+11/08/2003
+SPoG
+- Split qe3.h up into multiple headers.
+- Cleaned up use of win32 symbols:
+  WINAPI macro for module functions removed.
+  GUID for module interfaces replaced by string.
+  boolean replaced by bool.
+  MB_OK etc gui defines replaced by enumerations.
+- Removed plugin stuff deprecated by synapse from qerplugin.h.
+- Cleaned up use of glib symbols:
+  guint32, gdouble, gboolean typedefs removed from non-glib-dependent code.
+  TRUE/FALSE replaced by c++ bool true/false.
+- Removed all "extern" function declarations.
+- Removed dependency on MainFrame from preferences.h.
+- Moved synapse server and pluginmanager instances to pluginmanager.cpp.
+- Split pluginmanager.cpp into three parts:
+  Radiant's synapse client stuff in plugin.cpp.
+  Implementation of brush/entity/patch-handles stuff in pluginapi.cpp.
+  Synapse server init/shutdown in pluginmanager.cpp.
+- Added forward-declarations to avoid including other headers.
+- Replaced CString usage with Str;
+- Removed unused brush-scripts stuff.
+- Cleaned up patch-vertex-area-selection logic.
+- Removed very old code chunks that were commented or #if 0.
+- Replaced project-entity with a dedicated key/value string map.
+
+---- branch point - spog-cleanup
+
+06/12/2003
+SCDS_ReyalP
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=930
+  shortcuts to change texture window scale
+
+02/12/2003
+SCDS_ReyalP
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=913
+  fix for single monitor window positioning save
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=924
+  fixes to CenterXYView shortcut, correctly bound to Shift+Control+Tab now
+TTimo
+- add a 'q3map2' command line to win32_install.py, factorize and remove win32_install_q3map2.py
+
+-- linux 1.3.14 test build 1
+
+29/11/2003
+TTimo
+- heretic2 has no q2map. linux setup tries to install and breaks
+  removed faulty setup line
+- cleaned more Linux setup fuckage caused by q2/her2
+  a tip: rm -rf build install before building and testing a new setup
+
+28/11/2003
+ydnar
+- full SCC purge of the vs.net project files (for real this time)
+- added seperate Q3Map2 build targets
+- added seperate Q3Map2 post-build Python script
+- _skybox entity support
+- _skybox and _decal in entities.def (Q3)
+
+-- win32 1.3.14 test build 1
+
+28/11/2003
+djbob
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=899
+  bobtoolz update (icon functionality is in menu too)
+djbob & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=842
+  migration of the win32 build system to vs.net/VC7
+  new libxml and libpng packages are required:
+  http://zerowing.idsoftware.com/libxml/
+  http://zerowing.idsoftware.com/libpng/
+  updated win32_install.py for new names and paths
+TTimo
+- assraped the vcproj with sed to remove Scc entries
+SCDS_ReyalP
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=88
+  2D background image plugin
+TTimo
+- putting together win32 setup updates for 1.3.14
+  msvcr70.dll goes in core directory
+  bkgrnd2d plugin content
+  changed file paths (libxml/libpng)
+  .xlink for new JA content
+
+27/11/2003
+TTimo
+- using a central scons.signatures file for checksums
+- version bump to 1.3.14
+- a libxml-related build bug in qe3.cpp on Debian sid
+- it looks like Sid no longer has inflate_mask exported from /usr/lib/libz.so
+  switched the mask to be defined in our source
+  this may be a problem on other distros, and on holy box (Woody)
+SCDS_ReyalP
+- bug 921 and 922, Z floating window fixes
+- bug 926, hullcaulk, hintskip, subtlehint
+EvilTypeGuy
+- bug 505 - select all faces with a given texture
+
+19/11/2003
+ydnar
+- clipper tool plane points default to 1st selected patch mesh
+
+17/11/2003
+TTimo
+- upgraded server to subversion 0.33
+
+-- released 1.3.13
+
+10/11/2003
+SCDS_reyalP
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=917
+  floating windows startup crash
+
+09/11/2003
+TTimo
+- fix M4_GAME_ET ( OSX setup )
+AstroCreep
+- cleaned up JA shader scripts
+
+01/11/2003
+ydnar
+- Merged ASE submaterial/subobject code from BirdDawg
+- Made Q2/Heretic2 tools not use precompiled headers to eliminate Win32 compilation errors
+- Added glColor4ubv() support to the GL function table
+- Changed PicoModel rendering to use glColor4ubv() instead of 4 divides and pass-by-value glColor4f()
+- Fixed bug 900 by setting alpha to 255 explicitly in image module, rather than 3 input components,
+  which was borking Q3Map2 jpeg loading, and thus compiles
+
+24/10/2003
+TTimo
+- bump to 1.3.13
+Anders
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
+new osx patch, fixes strip bug in setup. merging setup patches to a single file
+SCDS_reyalP
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=900
+Some jpegs get garbaged alpha channel
+
+22/10/2003
+-- merge https://zerowing.idsoftware.com:666/radiant/GtkRadiant/branches/Release-1.3.12/
+  19/10/2003
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
+    scons BUILD=info to generate a tarball and it's .info
+
+  18/10/2003
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=888
+    patch for 16 bit RGBA support in glwidget
+
+  -- released 1.3.12 Linux
+
+  14/10/2003
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=879
+    fixed hellish dlclose issue only occuring with holy builds
+
+  -- released 1.3.12 win32
+-- end merge
+Arnout
+- added epsilon testing to hashtable compares to eliminate almost-identical vertices
+- pico surfaces now use the normals from LWO vertices
+
+21/10/2003
+Arnout
+- added hashtable for faster vertex matching during LWO surface generation
+- model rendering now uses DrawElements and will use vertex colours in wireframe/flats shade mode 
+
+20/10/2003
+Arnout
+- added LWO support to picomodel.
+    shader names are derived from surface name
+    only geometry from layer 0 is used
+- added support for 'vertical flipped' TGAs
+
+19/10/2003
+Arnout
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=893
+  fixed starton primary monitor
+  fixed mouse pointer setting on win32 to properly translate gdk's offset coordinate system in windows' one
+  
+-- released 1.3.12 win32
+
+11/10/2003
+Spog
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=865
+  fix texture subsets
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=889
+  misc update, missing JA system textures
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=824
+  fixed .pref file trashing
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=881
+  BSP monitoring disabled by default in Q2
+
+09/10/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=883
+  more JA pack: shaders and mapextras.pk3 textures
+- fix Q2 win32_install.py to put the tools at the right spot
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=878
+  correctly support PNG images with an alpha channel
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=885
+  fix console to refresh during a texture directory load
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=739
+  fix weird Shift + Control + Z causing a Redo in non-floating window mode
+
+07/10/2003
+Nurail & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
+  Q2 tools, added -fs_basepath. Need corresponding setup and .proj updates
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=875
+  fixed broken surface properties in Q2 surface plugin
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
+  more fixes, build paths in scons, take out INSTALL config on command line (not functional + not need)
+  added Q2 tools back to Linux setup
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
+  using "*" as the shaders minor in surface plugin
+- updated makeself copy to the latest from icculus.org cvs
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=574
+  sprite plugins, tweak to make it functional for all games
+- updated Q2 tools .dsp
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=876
+  more Jedi Academy setup work and content
+  moving imagepng.dll module to the core, as now both Sof2 and JA need it
+  sample maps reorg, new siege_hoth_sample.map
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=874
+  a lot more models - using a dynamic File Group in IS to cope with that
+- Q2 IS setup fix, was not properly putting stuff in baseq2/
+  IS setup: tweak to Q2 tools stuff
+
+06/10/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=872
+  Q2 setup needs to be cleaned up and unified between win32 and Linux
+  using INSTALL_Q2 and TOOLS_Q2 in SCons script to install the Q2 tools
+  fixed the setup build dependencies to reference the Q2 tools targets
+  moved the Q2 specific modules imagewad and vfspak to q2/modules
+
+05/10/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=871
+  updating the gtk2 version to 2.2.4
+  adding an SVN module with the Gtk2 developer package: checkout gtk2-win32
+  updating IS to the new files
+  sed'ing the .dsp to replace src-gtk2 by gtk2-win32
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=609
+  Q2 tools: comment out dupe strupr on win32
+  update IS setup to missing Q2 stuff ( vfspak and tools )
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=866
+  Fixed Camera inspector window not refreshing. Was a missing top level gtk_widget_show call
+
+03/10/2003
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=609
+  quake2 tools build scripts
+  Linux setup updates - Q2 game pack in Linux setup
+TTimo
+- scan through all URL links in game.xlink to update them
+- added JA links (Raven and MapCenter forums)
+
+30/09/2003
+TTimo
+- update all synapse.config, win32 .dsw and install_win32.py for new surface module
+- Jedi Academy and Quake II game packs in IS setups
+- hardcoded hacks in editor core for JA, copied over from JKII
+- bug #867, disable sleep by default
+- q3map2 bug fix
+
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=862
+  Q2's 'no patch' stuff
+
+29/09/2003
+TTimo
+- OSX: fixup setup.xml.in
+
+-- merge bug856 back into trunk
+16/09/2003
+Nurail
+- new patch + win32 stuff for surface module
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=804
+  refactored the XML synapse.config handling:
+    better detection of invalid XML file
+    less code, factorized to CSynapseClient::ConfigXML
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=828
+  fixing bobtoolz 'shaders' major loading issues
+  added '*' minor. to be used with lots of caution. only if the given major will have a single API such as 'shaders'
+  also, map module was missing a VFS entry in non-HL configs. that's bad karma, using a minor "*" instead
+  NOTE: on a lot of modules we could be using a '*' entry instead of having lines in synapse.config
+- took out obsolete md3model
+
+15/09/2003
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=856
+  quake2 surface module
+
+07/09/2003
+Nurail & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=856
+  a surface inspector module to customize per-game API
+  removing DO_SURFACEPLUGIN define (enabled implicitely)
+  removing bSurfacePropertiesPlugin (true implicitely)
+  remove SI_SetActiveInRadiant, it's always on by default
+  why was USE_UNDOTABLE_DEFINE taken out? - put back in
+  removed DBG_PLUGIN define and related code, that stuff is from way back and no longer relevant
+  cleanup QERApp_FreeShaders in shader module from DO_SURFACEPLUGIN stuff
+  the WINAPI stuff in interfaces is not needed, that's an old remnant. Cleaned up
+-- end merge bug856 back into trunk
+
+19/09/2003
+Justin Blur
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=785
+  fix ~/.radiant permission bug
+Nurail & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=849
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=851
+  win32 updates for the new modules and install_win32.py
+
+16/09/2003
+Nurail & Hydra
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=848
+  q2 map format minor
+
+08/09/2003
+Tr3B
+- imagepng.so / PNG format support in Linux
+  NOTE: atm no official supported Linux game by GtkR uses this
+
+07/09/2003
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=851
+  imagewal.so module / wal image format
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=840
+  md2 support in picomodel
+
+06/09/2003
+Nurail & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=848
+  renaming mapq3.so to map.so
+  added hooks for Q2 map format load/save to single map module (minor mapq2)
+Nurail
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=849
+  vfspak port to synapse and updates
+
+04/09/2003
+SPoG
+- Fixed crash in RunBsp caused by passing an invalid pointer to printf.
+- Changed console to wrap long lines instead of using horizontal scrollbar.
+
+30/08/2003
+Anders & TTimo
+- OSX setup, new patch to make scons SETUP=1 produce a .run
+- don't put bspc Linux binary in the setup
+
+30/08/2003
+Anders & TTimo
+- OSX setup, new patch to make scons SETUP=1 produce a .run
+- don't put bspc Linux binary in the setup
+
+26/08/2003
+Anders
+- more scons OSX, start on setup stuff
+
+25/08/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=855
+  make 'move into worldspawn' work again
+Anders Gudmundson & TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=826
+  OSX scons build system
+
+24/08/2003
+ydnar
+- Removed "test.cpp" from radiant.dsp (merge artifact?)
+- Added ddslib to radiant.dsw
+- Correctly set lib deps for q3map2.dsp for ddslib
+- [bug 852] Increased buffers from 260 bytes on Win32 to 4096 bytes
+
+TTimo
+- bump to ver 1.3.12
+- EnsurePythonVersion broke in 0.91 (commented out)
+
+David Hogue
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=844
+  q3data Linux. q3data can read .ase and turn them into .md3
+
+23/08/2003
+ydnar
+- Added ddslib to repository, based on nvidia sample code, cleaned up a bit
+  straight C, loads DXT1, DXT3 and DXT5 format DDS textures.
+
+22/08/2003
+TTimo
+- https://zerowing.idsoftware.com:666/viewsvn/
+- Arnout's commit email script - try #2
+  the commit script doesn't handle viewsvn root remaps (radiant instead of radiant.svn)
+  adding a prefix to the report
+
+04/08/2003
+TTimo
+- conversion from CVS to Subversion:
+repository convert completed (with revml)
+module repositories glued together in a single one
+hooking email commit scripts and backup scripts
+- Python >= 2.1 required instead of 2.2
+
+01/08/2003
+SPoG
+- Changed gl widget to request maximum available depth buffer precision.
+- Changed all uses of deprecated GtkCList and GtkCTree to use GtkTreeView/Model.
+- Fixed directory handle leakage in synapse module search.
+- Fixed dir_dialog always returning NULL for Textures -> Load Directory.
+
+23/07/2003
+SPoG
+- Ported focus_out_event handlers in gensurf to gtk2 signals system.
+- Fixed failure to load models for entities other than misc_model.
+- Fixed crash in model module shutdown caused by mismatched resource capture/release.
+
+22/07/2003
+TTimo
+- fix q3map2 .dsp for correct glib-2.0 includes (common/vfs.c)
+- camera plugin installs to core now (RTCW and ET)
+- fixups to the merged setup stuff
+- patched cvsreport to provide explicit diff for some files #2
+- fix to work with scons 0.90 / added LIBPREFIX ('lib') where needed
+  https://sourceforge.net/tracker/?func=detail&atid=398971&aid=766975&group_id=30337
+SPoG
+- Fixed crash in cmdlib ExtractFileBase when source filename is an empty string.
+
+20/07/2003
+TTimo
+- SCons scripts for the ported plugins: bobtoolz, camera, prtview, gensurf
+- ET Linux setup script + new plugins
+- q3map2.x86 is installed and wrapped through a q3map2 script (libstdc++ LD_LIBRARY_PATH)
+- update ChangeLog and credits
+- put back the GTKRAD_DIR in .fgl
+
+19/07/2003
+SPoG
+- Tagged trunk before merge as bug537-merge-3.
+- Tagged branch port_gtk2_20030307 as gtk2-merge-final.
+- Merged changes since tag bug537-merge-2 into trunk.
+- Removed gtk dependency from plugin toolbar interface.
+- Ported prtview, bobtoolz and gensurf to gtk2.
+
+18/07/2003
+Anders Gud
+- OSX build fix
+
+16/07/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=814
+  merging ET support code into to trunk
+- cvsreport 0.3.0 - http://www.nongnu.org/cvsreport/
+  rolling out this ver since old cvsreport setup broke
+- fixup to build on Linux (including fixing plugin builds)
+
+-- release-1_3_8-ET
+
+02/07/2003
+TTimo
+- new setup build, with patches and updates from SD
+- local fixing of bobtoolz dependency against libcmd, and itoolbar.h gtk header bustage
+
+19/06/2003
+TTimo
+- missing plugins. add them to .dsw for default build, add them to IS setup:
+  camera, gensurf, bobtoolz, prtview
+- fixup bobtoolz code for VC6. for(int i=0 causing duplicate definition errors
+- removed pk3man from IS (we no longer distribute/maintain it)
+  TODO: cvs remove the IS files for it
+- re-enabled plugins in build by default, disabled curry and textool
+  TODO: following error when bring up About box of bobtoolz:
+  BobToolz::ERROR->Failed To Load Exclusion List: C:\Program Files\GtkRadiant-ET-1.3\plugins\bobtoolz.dllbt\bt-el2.txt
+
+18/06/2003
+TTimo
+- add ET game pack. from Arnout's full dump of editor source + game pack data
+  trunk tagged at ET-tag for this
+- Dlg_SdAskCorePath:
+    szDir   = "C:\\Program Files\\GtkRadiant-ET-1.<<RADIANT_MAJOR>>";
+
+09/06/2003
+ydnar
+- Added Q3Map2 keys/entities to Quake 3 entities.def
+- Removed obsolete vlight keys from Quake 3 entities.def
+- Added MD5 functionality to mathlib, from:
+  http://sourceforge.net/projects/libmd5-rfc/
+
+------- merged changes since tag bug537-merge-2 from branch port_gtk2_20030307 to trunk
+
+TTimo
+- try checkin on branch see if cvsreport 0.3.0 will verbose it
+
+08/07/2003
+SPoG
+- Fixed recent-files list for file names containing underscores.
+
+07/07/2003
+SPoG
+- Fixed crash and file-type bugs in gtk file-dialog.
+TTimo
+- converted the setup code from perl to python
+- added copy over of libgcc_s and libstdc++, and LD_LIBRARY_PATH in the wrapper script
+
+06/07/2003
+SPoG
+- Changed console popup menu to include cut/copy/paste as well as clear.
+
+05/07/2003
+SPoG
+- Fixed the way surface-inspector dialog responds to escape key.
+
+04/07/2003
+TTimo
+- linux building / SCons
+  0.90 is broken, use 0.14 for now. added version check
+  adding scons SETUP=1 option to spawn setup build
+  enable back vfswad in scons
+  TODO: grab Conscript-setup, convert it to python in build_setup function
+
+02/07/2003
+TTimo
+- building a win32 setup, using -gtk2 suffix (game packs in Radiant-1.3-gtk2 and core in GtkRadiant-1.3-gtk2)
+SPoG
+- Ported vfswad to gtk2.
+- Fixed memory leak in vfspk3 directory search.
+- Added vfswad to win32_install.py.
+
+09/06/2003
+TTimo
+- tagging setup/ as gtk2_setup_rollback
+  rolling back trunk setup code to the branch to build an experimental release
+- merge trunk to branch:
+-- tagged HEAD with bug537-merge-2
+-- merge HEAD between bug537 and bug537-merge-2 into the branch --
+  31/05/2003
+  TTimo
+  - grab back vfswad code that I forgot in bug 800 rollback
+  - add prtview back to the project, fix it to build (#817)
+
+  27/05/2003
+  djbob
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=817
+    prtview fixes, upgrade to synapse
+
+  -- release-1_3_8
+-- end merge HEAD between bug537 and bug537-merge-2 into the branch --
+- freshly merged in vfswad is broken
+- freshly merged in prtview is broken
+- q3radiant.dsp -> GtkRadiant.dsp, outputs GtkRadiant.exe
+- removed vc5 dsps
+SPoG
+- Updated win32 setup stuff to use gtk2 dlls.
+- Modified setup.pl to run correctly (tested on cygwin perl 5.6).
+
+08/06/2003
+TTimo
+- Linux:
+  check gcc 3.x, better ldd check
+  add gcc version to about message
+  kill old cons stuff
+- added q3map2.x86 scons build  
+- header conflict libs/cmdlib.h tools/quake3/common/cmdlib.h
+  grepped through q3map2 source to change #include "cmdlib.h" to common/cmdlib.h
+- killed more cons files remnants
+SPoG
+- Improved error reporting for win32 setup system.
+- Fixed errors reported when running setup scripts.
+- Fixed scale of xor selection rectangle in XY window.
+
+07/06/2003
+SPoG
+- Fixed X Window System error when entering freelook on *nix.
+
+06/06/2003
+SPoG
+- Fixed copy/paste on *nix.
+- Changed copy/paste on *nix to use GtkClipboard api.
+- Changed copy/paste on win32 to be non-window-specific.
+- Further cleaned up MainFrame::Create.
+- Changed freelook to use gdk_window_get_origin instead of gdk_window_get_root_origin to place the cursor.
+
+05/06/2003
+SPoG
+- Fixed grey statusbar in 4-way-split mode.
+- Redirected gtk messages before creating main window.
+- Removed unused XYFriend hack from camwindow.
+
+04/06/2003
+TTimo
+- win32_install.py settings loaded/saved from site.conf
+
+02/06/2003
+TTimo
+- fixed python running with no output. Make sure VC6 finds native Python before any cygwin Python
+  look at the Directories settings in Tools > Options to either kill the c:\cygwin\bin path, or have Python path first
+- renamed dupe files to avoid header collision and general confusion between entity and model
+- added win32_install.py to perform post-build install (need to load the configuration paths from a non-cvs stored site.conf file)
+
+01/06/2003
+TTimo
+- bind gen.dsp to makeversion.py
+- added a run_python.bat to check for python presence and execute
+
+27/05/2003
+TTimo
+- write makeversion.py module - hook it up to SCons build - cleaner, easier to use
+- comment out vfswad build lines. source is still not in tree (bug 800 aftermath I think)
+
+18/05/2003
+SPoG
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
+  Changed Sys_FPrintf_VA to immediately process console events during map load.
+  Changed startup to create main window after QE_Init().
+  Fixed loading last map on startup.
+  Fixed crash on exit.
+  Fixed colour dialog.
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
+  have to delay merging back to trunk. 
+  have a behaviour problem between debug and release builds.
+  while debug is fine, release is screwed (see bug item)
+
+-- tagged HEAD with bug537
+-- merge HEAD between merge-gtk2-20030413 and bug537 into the branch -----
+  11/05/2003
+  Dan Olofson & TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
+    workaround for ATI drivers bug (polygon backfaces)
+    use Preferences > 2D Display/rendering > ATI cards with broken drivers
+  Riant
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=806
+    updated synapse.config for SoF2 png
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=805
+    dir_dialog is broken - is only used in prefab path prompt
+
+  -- release-1_3_7
+
+  14/04/2003
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=801
+    moved "ignoring sprite for entity.." to be a _DEBUG only thing
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=802
+    fixed models not drawing on win32. was a setup bug
+  - OSX setup build updates - added dependency against libpng3-shlibs
+  - added openurl.sh to open urls on *nix (with setup updates)
+  Riant  
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=803
+    RTCW - default_project.proj in setup
+
+  13/04/2003
+  Michael Schlueter & EvilTypeGuy
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=684
+    imagepng building under Linux
+  Riant & TTimo  
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=797
+    fixed texture compression support
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=799
+    regen project file from template on version upgrade
+    updated all default_project.proj to have "version" "1"
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=798
+    missing modules/bitmaps/model_reload_entity.bmp from Linux setup
+-- end merge HEAD between merge-gtk2-20030413 and bug537 into the branch -----
+  
+17/05/2003
+TTimo
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=537
+  http://www.qeradiant.com/wikifaq/index.php?Gtk2%20build%20notes
+  went through the new dll dependencies, listed required files preparing for a single zip package
+  updated all the project files to rely on src-gtk2/
+
+13/04/2003
+SPoG
+- Tagged HEAD with 'merge-gtk2-20030413' and merged HEAD --> port_gtk2_20030307.
+
+12/04/2003
+SPoG
+- Added gtk-2.x libraries to win32 setup.
+- Changed win32 setup to use 'dynamic' file-groups, making it possible to add files without
+  modifying installshield scripts.
+- Modified win32/setup.pl to copy setup data to dynamic file-group directories.
+
+30/03/2003
+TTimo
+- added scons scripts. the scons engine is included in the tree. you just need to have python
+  have ldd -r safe check on .so  
+  TODO:
+  - make sure it's gcc3
+  - check OSX
+  - add q3map2 build
+
+29/03/2003
+TTimo
+- tracked and fixed the startup bomb on Debian sid:
+  `pkg-config gtk+-2.0 --libs`
+  -Wl,--export-dynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0 -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
+  http://www.gnu.org/manual/ld-2.9.1/html_chapter/ld_2.html#SEC3
+  --export-dynamic
+    When creating a dynamically linked executable, add all symbols to the dynamic symbol table. 
+    The dynamic symbol table is the set of symbols which are visible from dynamic objects at run time. 
+    If you do not use this option, the dynamic symbol table will normally contain only those symbols 
+    which are referenced by some dynamic object mentioned in the link. If you use dlopen to load 
+    a dynamic object which needs to refer back to the symbols defined by the program, rather than 
+    some other dynamic object, then you will probably need to use this option when linking the program 
+    itself.
+  this causes symbol confusion, shaders.so's g_ShaderTable suddenly resolves to the core's g_ShaderTable
+  one is a 'shaders' API, the other an 'appshaders' .. everything gets badly mixed up
+  added a check in the cons script, using `pkg-config gtk+-2.0 --libs-only-L` `pkg-config gtk+-2.0 --libs-only-l`
+  (same for gtkglext)
+    
+28/03/2003
+TTimo
+- propagate jpeg compile fix from bug750 branch
+- use PKG_CONFIG_PATH when building radiant/ (alternate gtkglext-1.0)
+- on OSX, you need gtk+2-dev package, and pkgconfig, atk1
+  build gtkglext from source http://gtkglext.sourceforge.net
+
+17/03/2003
+TTimo
+- updated the build system to glib2/gtk2/gtkglext
+  atm it compiles and starts on my dev box (Debian Sid)
+  but doesn't reach end of initialization, hangs on
+   q = (qtexture_t*)g_hash_table_lookup (g_ShadersTable.m_pfnQTexmap (), stdName);
+   in shaders.cpp QERApp_Try_Texture_ForName
+  need to have the gtk2 dev packages, and libgtkglext1-dev
+
+12/03/2003
+SPoG
+- Replaced alpha-blended area-selection rect with XOR rect.
+- Fixed YX/XZ/YZ toggle in floating windows layout.
+- Cleaned up xor rectangle code.
+
+11/03/2003
+SPoG
+- Fixed console scroll-to-last-text-inserted.
+- Fixed console error/warning colours.
+- Refactored or removed WIN32-specific gtk-related stuff.
+- Removed win32 SetCapture/ReleaseCapture on GLWindow.
+- Removed win32 gtk_main_iteration calls in glwindow mousemoved.
+- Cleaned up start-on-primary-monitor stuff.
+- Changed main window to use standard save/load window position/size.
+- Replaced deprecated gtk_widget_set_uposition with gtk_window_move.
+- Removed win32/X gl functions from igl.
+- TODO: replace/remove deprecated gtk_widget_usize.
+
+10/03/2003
+SPoG
+- Changed fonts in win32 rc file to 8pt tahoma.
+- Fixed flat-grey gui in Regular layout mode.
+- Changed main-window save/restore maximized to use gtk API.
+- Fixed button_press_event handling on console/entity/entitylist windows.
+
+09/03/2003
+SPoG
+- Fixed crash on shutdown after changing floating-z-window preference.
+- Removed win32_realize_floating hack.
+- Refactored MainFrame::Create to make it more readable.
+- Fixed key_press_event handlers for entity/surface/patch dialogs.
+- Fixed delete_event handlers for dialogs derived from Dialog class.
+
+08/03/2003
+SPoG
+- Fixed viewport for entity window comment text.
+- Fixed x-shrinking for entity window comment text.
+- Fixed menu underscore shortcut hack in MRU list.
+- Changed groupdialog to connect switch_page signal after creating all pages. 
+- Changed gl widget to use gtkglext/pango to create fonts.
+- Cleaned up gtkglext glwidget implementation.
+- Reduced border size on toolbar widgets.
+- Replaced font with font_name in win32 rc file.
+- Added viewports for all scrolled text boxes.
+- Fixed entities/textures/console window title update when page is changed.
+- Fixed floating windows not being transient to main window (don't want them on taskbar).
+
+07/03/2003
+SPoG
+- Created a new branch for the port to gtk 2.x. 
+- Fixed menu underscore shortcuts to use gtk_label_new_with_mnemonic.
+- Fixed global keyboard shortcuts by using mainframe_keypress.
+- Fixed use of deprecated gtk_color_selection_get_color.
+- Removed use of deprecated gtk_paned_set_gutter_size.
+- Replaced deprecated gtk_widget_draw with gtk_widget_queue_draw.
+- Replaced deprecated gtk_object_get/set_data with g_object_get/set_data.
+- Replaced deprecated gdk functions with 2.x equivalents.
+
+
+----- branch port_gtk2_20030307 ------
+
+
+13/04/2003
+Michael Schlueter & EvilTypeGuy
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=684
+  imagepng building under Linux
+Riant & TTimo  
+- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=797
+  broken texture compression support
+
+
+
+31/01/2003
+SPoG
+- bug #752 - Construct fix for ppc, patch applied.
+
+26/01/2003
+TTimo
+- bug #750 - revamp of the setup stuff on Linux
+  (under way, see bug for progress - feel free to help!)
+- reworked the cons scripts, setup is hooked in to cons now
+  also, added gcc version select on command line, using Cons_gcc.pm utility
+
+22/01/2003
+TTimo
+- merged merge-1_2_10-post back to trunk
+
+
+===============================================================
+-- merging release-1_2_9 -> merge-post-1_2_10 into trunk
+   trunk before merge is tagged pre-merge-1_2_10
+===============================================================
+
+22/01/2003
+TTimo
+- finished up the TODO items, turned into bug items or dropped them. branch is ready to move back in to trunk
+
+18/01/2003
+TTimo
+- fixed ID_SELECTION_MERGE
+
+17/01/2003
+TTimo
+- fixups
+  FlushReloadSelectedToolbarButton -> CFlushReloadSelected
+  incorrect naming: RadiantToolbarModuleManager -> CRadiantToolbarModuleManager
+  ToolbarButton -> IToolbarButton, and C* implementations
+  http://www.qeradiant.com/wikifaq/admin.php?Code%20Conventions
+
+14/01/2003
+ydnar
+- Minor Cons fix for OS X (bug 729)
+
+13/01/2003
+ydnar
+- GtkRadiant now builds on OS X, Linux, and Win32 out of the same tree
+- OSX build uses gtkfileselect-linux now, as the Darwin version was broken/old
+  fixme: change this to use OS X open dialog box or something?
+- Minor fixes to a few files to fix gcc warnings
+- Model module now builds on OS X and Linux, using Synapse properly
+- PicoModel change to invert T coordinate on ASE models
+- Q3Map2 change to export ASE models with T coordinate flipped
+- Misc Q3Map2 changes
+
+09/01/2003
+ydnar
+- Updated Construct with Darwin/OS X ld flags for 4MB stack size
+- Misc Q3Map2 updates (2.3.35-dev)
+
+05/01/2003
+ydnar
+- "angles" key now properly ordered, to work with current mathlib
+  (also changed in Q3Map2)
+
+31/12/2002
+ydnar
+- PicoModel: Minor fix to MDC loader (naming/define)
+- Q3Map2: 2.3.34-pre-1 updates
+- MapXML dsp unix->dos newlines
+
+29/12/2002
+SPoG
+- Merged q3map2-texturing prefs key.
+- Merged vfs check for gamemode project key.
+
+27/12/2002
+TTimo
+- fix GetTickCount stuff
+- added q3map2 cons script
+- fixed Linux build
+
+23/12/2002
+SPoG
+- Added model cache API, moved model cache implementation from entity module to core. 
+- Added file-type registry API, replaced core file-type manager with registry.
+- Changed model module to register supported file types with core registry.
+- Removed or #ifdef'd non-functional code from model module.
+- Added support for misc_gamemodel and model_static to entity module.
+- Cleaned up entity module's on-epair-changed API.
+- Moved light-entity-specific code to a seperate file in entity module.
+- Cleaned up file dialog interface - specify file-type-lists with a string.
+
+22/12/2002
+SPoG
+- Ported camera plugin to synapse, adding support for camera and ui APIs.
+
+20/12/2002
+SPoG
+- Fixed default prefs setting for selected-brushes-camera, gridmajor-alt and gridminor-alt.
+- Merged CEntityEclassModel::Draw in entity module.
+- Ported imagepng module to synapse.
+- Fixed warning for CamDragMultiSelect preference bool used as int.
+
+19/12/2002
+SPoG
+- Fixed white-textures bug caused by texture compression preferences.
+- Ported light-radius rendering to 1.3 entity module.
+
+18/12/2002
+SPoG
+- Merged win32 project files, with the exception of camera plugin.
+- Ported model module to synapse API.
+- Redesigned toolbar API to remove gtk-dependency from toolbar plugins.
+- Refactored window-position preference save/load.
+
+17/12/2002
+TTimo
+- kick doxygen generation for branch merge-1_2_10-post
+
+15/12/2002
+TTimo
+- having the linux version compile and start again. took out numerous elements while merging, built a list of TODO stuff
+  the main thing to do being to bring the win32 build back up too, then to go through TODO list and fix stuff
+  until the win32 version runs too, I check this in to a seperate branch merge-1_2_10-post
+- There is quite a massive update in mainframe.cpp switch case for all events.
+  Looks like it's just a reordering of stuff, but it looks bad in the diffs.
+- added m_MapReg pattern
+
+- At some point, I'm thinking that forcing correct TAB/SPACE conversion on the server end would be a good thing to have.
+  Nazisticly forcing the formatting sounds like the only viable solution.
+
+               11/12/2002
+               RR2DO2
+               - #418, mdc load and display (RTCW)
+               - #597, CenterCamera shortcut
+               Use Ctrl+Shift+TAB to center the views onto the current camera location
+               - #714, bitmap loading fixes and speedups
+               - #715, fixed Alt+Shift cycle/drill select to work with brush-based entities
+               EvilTypeGuy
+               - #718, fix compilation warnings
+               Riant
+               - #707, fixed HM mode in STV:EF
+
+               10/12/2002
+               EvilTypeGuy
+               - Fix gcc3 compilation warning
+               EvilTypeGuy and X-Man
+               - Fix OpenURL so browser launching works on XDarwin (Mac) systems.
+
+               8/12/2002
+               RR2DO2
+               - #710, AssignSound pattern
+               - #711, SoF2 model_static drawing
+               - #713, sync 2d and 3d rendering of models
+               - #238, apply 0..1 T range when Fitting a patch (instead of 0..-1 previously)
+               - #633, Add ability to change default color in 3D window Misc > Colors > Camera background
+               ydnar
+               - Q3Map 2.3.33 (see changes.q3map2.txt)
+               - Quake 3 + TA common.shader updates (q3map_terrain, hint)
+
+               3/12/2002
+               TTimo
+               - merging Stable-1_2-Apple into Stable-1_2
+               - why INSTALL.TXT? re-used INSTALL, updated to point to wiki
+               - why the -machinedump test against i386-redhat-linux? removed
+               - using $is_darwin flag instead of $gcc_machine tests in the build scripts:
+               gotta leave some room for a Linux ppc build, and darwin x86
+               exporting it for use in sub scripts
+               - the addition of ccache support broke some Apple SConstruct patches to $ENV{PATH}, fixing
+               merged version is compiling fine on Debian Sid
+               checking in on a branch, need to validate win32 build and OSX build before applying in Stable-1_2
+
+               -- release-1_2_11
+
+               30/11/2002
+               TTimo
+               - added seaw0lf to credits
+               - ydnar's changelog.q3map2, added to global.xlink and Linux setup
+               - 1.2.11 version tag
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=699
+               updated IS setup for q3map_terrain keyword
+               also fixed details in STVEF media
+               Arnout
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=569
+               http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=698
+               fixed drill select, Ctrl bug in vertex mode, and updated changelog.txt
+
+               29/11/2002
+               TTimo
+               - 1.2.11-rc1
+               - update changelog credits links for release
+               - update linux setup, putting EULA and new README instructions  
+
+               28/11/2002
+               ydnar
+               - Removed redundant 'p' from "developers"
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=637 - fixed
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=694 - fixed
+               - Updated to Q3Map 2.3.32
+               - Added epsilon to texture plane choose code to eliminate numerical
+               inconsistencies on brush faces slanted at 45 degree angles (bug 637)
+               - Fixed bug in lightmap export after lighting when map contains 0 BSP lightmaps
+               - Adjusted some light tracing constants to fix certain brush/patch seam shadows
+               - Tinkered with skylight code again
+               - Fixed bug where lightgrid would be black if level was compiled with -nogrid
+               - Fixed -approx code to work in floating-point space, using _minlight
+               - Fixed bug where vertex light code was using invalid pvs data to create
+               light list for surface, leading to incorrect vertex lighting
+               - Fixed related bug in anti-light-leak code that was causing brush faces to go
+               black (bug 694)
+               - New: _minlight sets _minvertexlight and (new) _mingridlight automatically
+               - New: _mingridlight key to set minimum grid lighting
+
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=637
+               added preference setting in Preferences > BSP monitoring
+               added an item on the wiki
+
+               27/11/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
+               picomodel-based model.dll module (new model.dll, removed md3module.dll)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=664
+               media/setup updates for q3map2 support
+               added modified quakev3.qe4, bumped internal version to 4 for all games
+               SOF2 and JKII were forcing BSP monitoring off because of sof2map, now only printing a warning
+               added -rename to SOF2 BSP phase
+               Q3 & RTCW new templates are working
+               haven't tested the STVEF & SOF2 versions
+               updated IS setup scripts to make sure quakev3.qe4 is updated in nightly release
+               (not needed on Linux, we will be doing a full release)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
+               updated win32 setup to provide right model.dll stuff
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=621
+               typo was causing memory error
+
+               RR2DO2 & TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=662
+               more model fixes, fixed the Linux build to build model.so
+               added search path to modules/ for bitmaps
+               model reload, patch and bitmap
+
+               26/11/2002
+               RR2DO2
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=569
+               area select - Alt+Shift for area select (complete tall)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=621
+               broken undo creating ghost undo entities (and trashes memory)
+               partly fixes the issue, it's a memory error still
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=659
+               updates to RTCW camera plugin - works in 4 view mode
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
+               more fixes to plugin API
+
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=638
+               libpng in the core DLLs instead of SoF2 (for q3map2 dependencies)
+               putting q3map2 binary with the Core Binaries
+
+               25/11/2002
+               TTimo
+               - added ccache support to cons build system - http://ccache.samba.org/
+
+               21/11/2002
+               ydnar
+               - minor bugfix to PicoModel ASE material loader
+               - Q3Map2 updated to 2.3.31 (Splash Damage)
+               - Stitching the edges of lightmaps on patches that wrap around (cyls and cones)
+                       so the seam is no longer visible
+               - The -patchmeta switch works better now, the patches are still stored in the
+                       BSP for collision, but are pre-tesselated into nonplanar meta surfaces for
+                       more efficient rendering
+               - Better, more uniform lightmap sample position finding on patch meshes
+               - Moved q3map_tcMod and q3map_alphaMod processing to the final phase
+               - New: q3map_skylight AMOUNT ITERATIONS to replace surfacelight on sky surfaces
+                       for much faster and more uniform sky illumination
+               - Fixed bug in PicoModel ASE material parsing code
+               - Fixed a few seam/lightmap precision/projection errors
+               - Increased MAX_SHADER FILES to 1024 and fixed overrun error when more than that
+                       number of shaders was listed in shaderlist.txt
+               - Increased a few compiler maximums for larger maps
+               - New: -np N switch on BSP phase, works like -shadeangle, in that it forces all
+                       planar shaders to be nonplanar with the shading angle specified
+               - New: -nohint switch on BSP phase, omits hint brushes from compile for testing
+               - New: -debugaxis switch on light mode. Colors lightmaps based on their lightmap
+                       axis (which direction the lightmap was projected on)
+               - New: -debugorigin switch on light mode. Colors lightmaps based on the luxel
+                       origin relative to the raw lightmap's bounding box
+               - New: -debugcluster switch on light mode. Colors lightmaps based on the pvs
+                       cluster the luxel falls into
+               - New: -convert switch to convert BSP to ASE file (experimental)
+               - New: q3map_lightmapmergable directive to allow terrain to be mapped onto a
+                       single lightmap page for seamless terrain shadows    
+
+               18/11/2002
+               TTimo
+                       - fixed pk3man build system to work with new cons layout
+                       - fixing linux setup system to work with new cons layout
+                       Linux 1.2.11 will be a full setup, much easier that way
+                       - update makeself to the latest (and best) version
+                       - add q3map2 to Linux setup. goes in core (g_strAppPath)
+                       NOTE: has a dynamic dependency to libpng
+                       - pk3man still has issues with the zlib code that's been thrown in it
+                       unresolved which I don't have time to look at
+                               since we plan to drop pk3man in 1.3, dropping it now is just as good
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=644
+                       detect GOTY install     from registry and use it as default path
+
+               13/11/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
+               reworked to have the UI in game settings dialog
+               (this is strictly win32 thing, if that broke Linux build, then fix the typos)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=630
+               mouse AngleSpeed setting was getting clobbered. fixed and upped the max values
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=623
+               applied a fix, rolls back the values when the compression formats are not supported
+               fix ain't very clean, if we have to deal with extensions some more, we need to deal with the settings persistance better
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=624
+               updated the setup code for town_*.shader (both in full setup and update)
+               updated files in WolfPack
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=672
+               using a QE4_VERSION define, added a message if there's a project template with wrong version
+
+               12/11/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=671
+               guard junk.txt path between " "
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
+               fix to CommitBrushHandleToEntity stuff
+
+               RR2DO2
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=660
+               previously you could select patch control points when patch selected + vertex edit (V) in 2D view. Works in camera view now
+
+               12/11/2002
+               TTimo
+               - nudging zerowing to trigger Stable-1_2-Apple doxygen generation
+               http://zerowing.idsoftware.com/doxygen/
+
+               11/11/2002
+               TTimo
+               - http://ttimo.net/web/anjuta
+               modified the .prj to work with the cons patches (linked dirs)
+               still way experimental
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
+               fixing linking for radiant.x86
+
+               10/11/2002
+               RR2DO2
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=669
+                       patch inspector bug - fixed
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=663
+                               fucked up change in the plugin API caused breakage of several plugins
+               still have to fix bobtoolz http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=665
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=661
+                       Undolevels not set properly
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=660
+                               drag selection to the camwindow for patches in controlpoint edit mode
+                               (not sure about the actual shortcuts, Ctrl+Alt on my current Linux setup)
+
+               TTimo
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=657
+                       mark map modified on editing entity keys
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
+                       added the correct link and ldflags statements to have static linking everywhere
+                               didn't check gcc 3 build, check correct static on Debian Sid and holy box
+                               has a $staticstdcxx in Construct to toggle On/Off if needed
+
+               09/11/2002
+               TTimo
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=651
+               reworking the cons building. support for gcc2 and gcc3
+                       cons -- gcc=<gcc-name>
+                               read gcc version and configure accordingly
+                               changed _NO_STLPORT to Q_NO_STLPORT
+                               independant BASE_CFLAGS and BASE_CXXFLAGS
+                               correcting usage of CC/CXX for c/cpp source and linking
+                               fixed missing -lz in vfspk3.so
+                               changed the way we build curry.so, works from the GtkRadiant tree now
+                               (NOTE: gcc 3.2 build of curry.so spews quite a few warnings)
+                               tweaked the way we do -fno-rtti -fno-exception
+
+               04/11/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=638
+               .qe4 version 4, udpated q3's .qe4 template, update setup to put q3map2 in the right place
+                       bumped version to 1.2.11-test for test setups
+
+               03/11/2002
+               ydnar
+               - fixed bug in jpeg loading code (4 components instead of 3 for RGB images, mh)
+               - updated PicoModel to 0.8.8 and Q3Map2 sundry fixes (2.3.29):
+               - Merged with latest CVS, fixed minor issues with matrix order
+               - Fixed minor Sys_FPrintf/Sys_Printf substitution typo in Q3Map2
+               - Expanded debug colors to 12 for debugging surface meshes
+               - PicoModel: fixed ASE loader to support > 1 texture coordinate per-vertex,
+               so more models supported correctly, also loading vertex normals
+               - PicoModel: md3 shader names are now cleaned. Suffixes (such as .tga or .jpg)
+               are stripped, and \ path separators are changed to /
+               - New: Add :q3map to the end of any shader name, and it will be interpreted as
+               the named shader minus :q3map. Example:
+               textures/shaderlab/concrete:q3map -> textures/shaderlab/concrete
+               One potential use is the -approx feature to collapse lightmapped  surfaces
+               into vertexlit surfaces, saving lightmap space/memory
+               - New: q3map_clipModel -- does what you think it does, sort of. This code ix
+               really experimental, and should *only* be used on large models such as terrain
+               (not small decorative models). This code will be evolving. Note: the shader's
+               surfaceparms are inherited by the magic clip brush, so if you have nonsolid
+               in your model's shader that uses q3map_clipModel, then the brush will also
+               be nonsolid
+
+               03/11/2002
+               TTimo
+               - cleaning up some cons stuff, checking that the setup building process is still good on Linux
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
+               updated Linux setup to put the bitmap
+
+               02/11/2002
+               ydnar
+               - PicoModel: replaced stricmp with _pico_stricmp
+
+               02/11/2002
+               ydnar
+               - PicoModel: added obj.c and ms3d.c, removed wfobj.c
+
+               02/11/2002
+               ydnar - seaw0lf
+               - Updated Q3Map2 to 2.3.29 sources
+               2.3.29
+                       - Merged with latest CVS, fixed minor issues with matrix order
+               2.3.28
+               - Bug 654 (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=654):
+               Fixed problem where brush faces, drawsurfaces, and surfaceparms weren't living
+               together in perfect harmony (terrain surfaceparms now inherited by brushes)
+               - Nodraw fog works now, albeit when you're underneath, surfaces above don't get
+               fogged properly. Could be good for foggy water where you want the above-water
+               portions to only be occluded by the water surface
+               - Bug 656 (http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=656):
+               Number of lightgrid points displayed (byte size is currently out of proportion
+               due to internal storage format) when Q3Map is called with the -info switch
+               - Fixed wack surface merging bug where code would attempt to merge triangles not
+               adjacent to the current set, causing bad lightmap projections on nonplanar
+               surfaces
+               - Fixed tiny 1-character bug in 2d lightmap texture allocator where adjacent
+               luxels were being checked for occlusion rather than the actual source luxel
+               2.3.27
+               - Fixed minor bug in scriplib bugfix where the last character in a file wasn't
+               being read.
+               - Fixed bug where 0-area or bogus triangles were causing crash in MapRawLightmap
+               if they used a shader with a normalmap (thanks ShadowSpawn)
+               - Fixed bug where lightmaps were getting hosed levelwide on a prerelease version
+               of 2.3.27
+               - Fixed bug where lightmaps were getting knackered on models and certain patches
+               - Merged latest PicoModel version from seaw0lf, adding support for ASE and WF OBJ
+               models (preliminary)
+               - Increased MAX_MAP_PLANES to 0x40000 (~256k)
+               2.3.26
+               - Now using GtkRadiant's libpng and zlib config (linked as DLLs)
+               - Fixed bug in script parser where repeat calls to GetToken() were causing
+               memory corruption
+               - Fixed SOF2 -rename bug
+               - When using -game sof2 or -game jk2, the -flares argument is implied
+               - Added -noflares argument to disable the above behavior
+               - Added support for flares on entities. Use one of the following keys:
+               "_flare" "1" -- use default flare (different for each game)
+               "_flareshader" "path/to/flareshader" -- use a specific flare shader
+               Note: This only matters in SOF2/JK2 now. Make a light targetted (a spotlight)
+               to get it to aim the correct direction, otherwise it defaults to pointing 
+               downward. You cannot have omnidirectional flares
+               - Lightgrid size is automatically increased to accomodate large maps. The
+               MAX_MAP_LIGHTGRID error will never happen again
+               - Update PicoModel to 0.8.7 sources
+               - ASE support
+                       - Alias|Wavefront OBJ support
+                       - <modelname>.remap shader remapping suport
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=655
+               handle grayscale jpegs gracefully
+               - mathlib: fixed VectorClear(), got rid of braces
+               - scriplib: fixed double-free memory corruption bug
+               - radiant: added new color scheme to emulate Lightwave/Maya/3DS Max
+
+               02/11/2002
+               TTimo
+               - too many issues with build system reading system's libjpeg.h instead of libs/libjpeg.h
+               renamed libs/libjpeg.h to libs/radiant_libjpeg.h, updated sources
+
+               29/10/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=639
+               running from a network share - saving prefs per-user
+
+               27/10/2002
+               TTimo
+               - merged in some more m4x4 code for q3map2
+               - fixed unresolved code in picomodel (strlwr / strnicmp)
+               - reworked the tools building to build both q3map and q3map2 without trouble
+
+               25/10/2002
+               ydnar
+               - q3map2 and picomodel source, initial checkin to Stable-1_2 branch (does not compile yet, tweaking to be done)
+
+               23/10/2002
+               TTimo
+               - camera.dll goes into $(RTCWRADIANTDIR)/plugins instead of $(RTCWRADIANTDIR)/modules
+               fixed up camera compile (exports)
+                       added camera bitmap (plugin toolbar)
+
+               21/10/2002
+               TTimo
+               - quickfix to the build (typo)
+               - changed dynamic linking on Linux to look for libGL.so.1 by default
+               fixes "all textures are blank" Linux bug with NVidia cards
+                       (you still have to have a working NVidia GL installation though, xlibmesa-dev on Debian screws things up)
+               - checked in modified q3 .qe4   with q3map2 menu (see bug #638)
+
+               09/10/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
+               reworked the plugin toolbar to rely on interface instead of straight exports
+               cleaned up the botclip monsterclip Brush_Draw filtering, added proper selection filtering (Brush_Ray)
+               merged bug-622 back into Stable-1_2, bug-622 branch is dead now
+
+               06/09/2002  
+               James Monroe - RR2DO2 - TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=619
+               light globes, applying patch by RR2DO2 built from the initial light globe code
+               - note to self: indent -kr -nut -st -ts2 -i2
+
+               RR2DO2 - TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=622
+               massive patch update from SD's GtkRadiant
+               - camera plugin: new bitmap
+               fixed Linux install path for camera plugin to wolf/plugins
+               - fixed various warnings in camera build gcc / Linux  
+               - fixed pref crash if plugin toolbar disabled  
+               - fixed Gtk-WARNING on bad cast in AddPlugInToolbarItem
+               - renamed the new select to 'Use paint-select in camera view:' in prefs
+               (camera paint-select, should be our default name for this)
+
+               NEW: you can 'paint select' in the camera view: 'camera paint-select'
+               press shift and move the mouse over the camera view to paint over brushes you want to select
+               configurable in prefs to enable / use Shift key, or use 'classic mode' ctrl+alt
+
+               NEW: light radius drawing
+               Added in-editor light envelope drawing. Outer circle is max envelope, 
+               inner fullbright radius. Optional classic mode emulates the similar drawing 
+               from Rituals and Ravens tools (not q3map correct, easier for the level designer 
+               to understand/legacy).
+
+               NOTE: 'angles' is q3map2 only
+               NOTE: could manipulate angles directly from the views (2d and 3d with some handles)
+
+               NOTE TO SELF: 
+               <TTimo> hey guys .. just a quick question if you don't mind .. I'm trying to track a Gtk-WARNING .. is there a way to make those apps cause a break to track them easily ?
+               <andersca> just run your app with --g-fatal-warnings
+
+               TODO: add new bitmap to win32 & linux setups
+               TODO: don't use exports for the plugin toolbar, use entry functions
+               do something like CPlugIn::InitBSPFrontendPlugin
+               TODO: botclip is broken with the new Brush_Ray code  
+
+               initial ChangeLog for the patch:
+
+               28-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Added 'angles' support for models (misc_model/misc_gamemodel).
+                       + Prevented pivot drawing of model from scaling and rotating.
+                       + Cleaned up the dropdown boxes in the preferences a bit (all use 
+               tables now, so not multiline).
+                       + Added 'Classic Key Setup' option to camera paint select configuration, this 
+               drag-selects with ctrl+alt instead of shift.
+                       + Changed XYWnd::PositionView to position on the center of the 
+               selection, not on the mins.
+
+               27-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Added in-editor light envelope drawing. Outer circle is max envelope, 
+               inner fullbright radius. Optional classic mode emulates the similar drawing 
+               from Rituals and Ravens tools (not q3map correct, easier for the level designer 
+               to understand/legacy).
+
+               26-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Upped MAX_TEXTUREDIRS to 256 (from 128).
+
+               25-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Fixed patches not being drawn in XY window with colour of parent 
+               entity.
+                       + Made paste to camera snap destination spot snap to grid.
+
+               18-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Changed Select_Reselect to be much faster.
+
+               12-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Fixed curve point drag-selection area not showing properly in XY 
+               views.
+                       + Fixed size info breaking over 9999.9 units.
+                       + Fixed AllocateSelectedPatchHandles not setting patchesmode to 
+               ESelectedPatches.
+                       + Changed the horizontal and vertical tc shift spin control to have a 
+               limit of 8192.
+                       + Moved SPoG's implementation of redisperse cols to a seperate function 
+               and reinstated the old code.
+                       + Added 'Paste to Camera', shortcut Alt+V, which pastes the contents of 
+               the clipboard to the current camera origin.
+                       + Added centerview functionality to 4 window mode. Ctrl+tab will focus 
+               on the selection, or if non existant, on the camera.
+
+               11-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Made sure settings set in savedinfo.bin get initialized to their 
+               proper defaults.
+                       + Added botclip filter (filters *botclip* and *monsterclip*).
+
+               10-09-2002
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Removed .reg from normal map saving, can only save as region 
+               using 'Save region'.
+                       + Added outline style cycling (j) cycle between z buffered outlines and 
+               selected colour rendering.
+                       + Added colour dialog to pick the colour of selected surfaces in the 
+               camwindow.
+                       + Third coordinate for clip points now gets set to the center of the 
+               selection.
+                       + Changed arbitrary rotation dialog to accept negative angles as well.
+                       + Changed texture alignment dialog to accept values up to 2 decimal 
+               points.
+                       + Fixed entity inspector to say 'Textures:' in the window title.
+                       NOTE: still broke in floating window mode
+                       + Changed entity inspector so that tab doesn't clear the epair value 
+               field anymore, so it retains the value while jumping to it.
+                       + Disabling camera paint-select now returns selection behaviour for groups to 
+               the old behaviour as well (shift+click selects whole group).
+                       + Changed load_plugin_bitmap to load bitmaps from g_strAppPath if 
+               g_strGameToolsPath fails.
+                       + Added plugin toolbar and api.
+                       + Fixed m_pfnCommitBrushHandleToEntity, wasn't creating brushes 
+               properly (well, not at all really).
+
+               Older changes:
+                                       Arnout <rr2do2@splashdamage.com>
+                       + Added misc_gamemodel drawing.
+                       + Ported camera paint-select over from 1.3.
+                       + Fixed statusbar display of text (removed a bunch of \n's).
+                       + Added area selection in 3d view for patches.
+
+               30/09/2002
+                       TTimo
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=556
+                               quickfix crash bug
+
+               27/09/2002
+                       TTimo
+                       - more CORERADIANTDIR cleanup (q3data)
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=602
+                               added cascading to the entity submenu (doesn't cascade the main menu, only the sub ones, NPC_* for instance)
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=556
+                               with clip and caulk filtered out, won't be selected anymore in camera view (i.e. selecting invisible faces)
+                               added SF_CAMERA to the flags in the selection process
+                               cleanup up various ugly syntaxes in the selection code:
+                               don't ever do if (flags == SF_SINGLEFACE) on a bitmask and assert that the other flags will always be NULL
+                                       don't do arithmetic on bitmasks:
+                                               if ( (flags & SF_ENTITIES_FIRST) && t.brush == NULL)
+                       return Test_Ray (origin, dir, flags - SF_ENTITIES_FIRST);
+                       is WRONG
+                                               using flags & ~SF_ENTITIES_FIRST is the appropriate way
+
+               23/09/2002
+               Riant
+               - new IS scripts to go with recent media updates
+                       Riant & TTimo
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=615
+                               reworked the fix to use "caulk_shader" in .game
+                               updated IS .rul script to generate special values for Sof2 and JKII
+
+               21/09/2002
+               Riant
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=595
+               more texture compression, dialog and settings
+               Michael Schlueter  
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=592
+               fixes to the Linux build system, exclusive q3 or wolf working now
+
+               22/08/2002
+               EvilTypeGuy
+               - Fix @*$&)@)$$ memory leak of my own doing, yes it's really been in there this long.
+               This should help memory usage drastically, especially when flushing & reloading
+               the same sets of textures, GtkRadiant's memory usage no longer becomes heinous.
+
+               14/08/2002
+               EvilTypeGuy
+               - Fix build on some linux boxen by including qertypes.h for proper boolean type declaration
+
+               -- release-1_2_10
+
+               16/08/2002
+               TTimo
+               - STVEF media update finalized (some .def)
+               - 1_2 Core Update for shader manual update
+               - in JKII, typo with nar_shader? replaced by nar_shaddar, with proper support in update too
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
+               Q3/TA media update with cleaned up shaders
+               - validated the update content by a diff between 1.2.9 + 1.2.10-update and 1.2.10 full  
+               - added a DO_NIGHTLY_BOOL to setup.rul AND a warning during setup about update content for games that are not installed
+               - built 1.2.10-sof2, SoF2 full install
+
+               15/08/2002
+               Michael Schlueter
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=590
+               added the option to build a Linux setup with the debug binaries
+
+               TTimo  
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
+               cleaned up shaders, done nightly setup update on Linux
+               updated Linux nightly for 1.2 to use /usr/local/games/GtkRadiant-1.2 as default base
+               - using version 1.2.10-update. Full Sof2 setup will be 1.2.10-sof2
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=426
+               don't straffe when using Ctrl+Shift(+Alt)
+               - camera.so RTCW plugin in Linux setup
+               - quickfix to non-initialized var in camera code
+               - awfull piece of work that had been completely left out, nightly elements for JK2 and STVEF
+               added JKII media update and STVEF media update (for the DIR_GAME elements)
+               JKII nightly is finalized
+
+               14/08/2002
+               TTimo
+               - fixed a missing file
+                       - Linux build quickfix
+               - fixed silly rendering bug
+               - added pref to force texture compression off (hey why would you do that??)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=466
+               fixed MAX_POINTS_ON_WINDING overflow in q3map (and relevant code to handle in radiant)
+
+               13/08/2002
+               TTimo
+               - cleared up notexture (dead code)
+               - cleaned up QERApp_LoadTextureRGBA gamma table init
+               - having a shot at 1.3 texture compression
+               sees the extension, binds the texture with the currect setting
+               but rendering is fucked .. someone explain?
+
+               08/7/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=586
+               search and destroy Q3Radiant -> Radiant
+
+               07/7/2002
+               SCDS_reyalP
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
+               wolf_entities.def update
+
+               riant
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=548
+               STV:EF updates
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
+               SOF2 updates
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=584
+               JKII updates
+
+               06/7/2002
+               Riant
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
+               Sof2 patches and IS setup    
+               TTimo
+               - game pack prompt asking about STVEF, fixed
+               - mp_examples was leaked and non lighted, fixed
+               - imagepng.dll goes into Sof2 install / modules, and not in DIR_CORE
+               - libpng12.dll needs installed only with Sof2 pack (added 'SOF2 Pogram DLL')
+               default texture scale is 0.125  
+
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=582
+               nomipmap -> nomipmaps in shader manual  
+               - removed libs/pak, this was still being linked in to Radiant, but not used at all  
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=580
+               .PK3 are recognized along .pk3 files (strcmp ->strcasecmp)
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
+               added the RTCW camera plugin to IS setup
+
+               Michael Schlueter
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=581
+               GL warning fix      
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=567
+               GL font display fixes (mostly Linux)
+               applied the changes with some tweaking
+
+               31/6/2002
+               TTimo
+                       - compiling the camera plugin on Linux:
+                       move the GUID and other misc compatibility definitions to include/misc_def.h
+                               GetTickCount being used in camera.so, this is from radiant/missing.cpp (unresolved)
+                               -> use QGetTickCount instead (in main function table)
+
+               30/6/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=530
+               cleaned the .shader from 'light 1' statements
+               updated the IS script for the updated .shader
+
+               17/6/2002
+               TTimo
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=541
+               Sof2 support, PNG format
+               wrote imagepng module, dynamic dependencies to zlib and libpng
+               changes in the core:
+               some hardcoded to "sof2.game" for png interface loading and extensions
+               in GetTextureExtension, killed outdated support for texture plugins
+               if ! "sof2.game", png is not loaded, support disabled
+               http://zerowing.idsoftware.com/libpng/
+               correctly configured for VC build (post build steps and dependencies)
+               is required on win32 to build imagepng
+               - added m_pfnGetGameFileName to the main function table (was needed for png stuff)
+               - cleaned up the QERApp_LoadTextureRGBA path
+               using (unsigned char* pPixels, int nWidth, int nHeight)
+               cleaning up internal access path
+               RR2DO2
+               - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
+               camera plugin for RTCW
+               TTimo: wrote the .dsp, post build steps etc.
+               IMPORTANT: you need to have RTCWRADIANTDIR env variable pointing to the RTCW Radiant files
+               (default C:\Program Files\Return To Castle Wolfenstein\Radiant)
+
+
+               12/6/2002
+               RR2DO2
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=299
+                       MP/SP pk3 filtering in VFS
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=386
+                       .camera support: splines library, camera plugin
+                               TTimo: portability fixups, cons build, guarding pragma, __cdecl BOOL
+                               virtual functions but non-virtual destructor
+                                       declaration with no type
+                                       int idCameraFOV::start - control reaches end of non-void, making it void
+                                       enumeration not handled in switch
+                                       no _MAX_PATH, the portable one is PATH_MAX
+                                       implicit declaration of int _fullpath
+                                       for(int i = 0; ..
+                                       struct _IO_FILE has no member named '_bufsiz'
+                                       stricmp -> Q_stricmp
+                                       attempt at implementation in .h file (InitIglToQgl)
+                               camera stuff still vastly broken (particularly on Linux), need to check in because of new fixes incoming        
+                       djbob   
+                       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=17
+                       quick fix to spawnflags getting corrupted when multiple entities selected
+                               (doesn't completely solve the problems we have with spawnflags yet though)
+
+===============================================================
+END -- merging release-1_2_9 -> merge-post-1_2_10 into trunk - END
+===============================================================
+
+12/12/2002
+  Hydra
+  - #197, HL support update
+
+11/12/2002
+  TTimo
+  - added cmdlib dependency to mapq3.so (fixes unresolved)
+
+25/10/2002
+  Hydra
+  - vfsGetFullPath() can now (optionally) search PK3/WAD files
+  - Half-life map loading is now un-borked (my original patch worked
+    but some conditional code in the patch was incorrectly applied.
+    That, coupled with the missing vfsFileExists and vfsFindFile replacements)
+  - A patch to imagehl/lbmlib.cpp/LoadIDSP() was missed out, causing all sprite
+    models to be reverse-rendered (due to an inverted alphamask)
+  - Renamed HydraToolz to HydraToolz-HL as it's half-life specific
+    changed project files and renamed all appropriate files and directories
+    (for the merge, just delete contrib/hydratoolz and apply the diff)
+
+  - Comments on previous notes:
+
+    - TODO: need to rationalize where the modules are placed and identify HL specific modules
+      (this affects the build system / post build step too)
+      imagehl and spritemodel are halflife specific and can be placed in
+        either $coreradiantdir/modules or $hlradiantdir/modules
+        I've updated the .dsp files so that they are copied to $coreradiantdir/modules
+        spritemodel can actually be used for other engines, not just HL so it makes sense
+        to keep it in $coreradiantdir/modules
+      hydratoolz is a half-life specific plugin and must go in $hlradiantdir/modules as it
+        is NOT to be used for any other engines.  I've also updated the "about text" to
+        reflect this.
+
+14/08/2002
+  EvilTypeGuy
+  - fix build process for textool plugin on some Linux boxen by including qertypes.h
+
+11/06/2002
+  TTimo
+  - spritemodels in build system
+  - applying HL setup patch (att 270, bug 197)
+    - the templating went one filename seperator too far, causing all *.fgl to be modified .. 
+      fixed so that we only have the relevant changes
+    - modules added to main Executable Files, TODO for later will need to identify what is HL specific
+    - .game generation: don't want enginename yet, gamename is ok
+    - updated HL .game generation for eclass_singleload and no_patch   
+    - update hydratoolz location in setup
+    - update maphl in synapse.config
+
+07/06/2002
+  TTimo
+  - realized that \func doesn't work in doxygen, should be \fn (updated everywhere)
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
+    applying the HL patch (see original list of changes below)
+    - ugly eclass API changes
+      eclassfgd/plugin.cpp.rej, eclass API changes involved, a bunch of .rej
+      SupportsMultiple tries to send configuration information from the eclass format file module to the eclass manager
+      dropping it, using a proper configuration node instead (eclass_singleload)
+    - added "no_patch" prop to disable patch support
+      the patch toolbar prompts are only present in prefs if there is patch support
+      otherwise everything is force-disabled
+    - PFN_VFSFINDFILE PFN_VFSFILEEXISTS:
+      one of the problems we have is that the 'manager' code and file format code are in the same module
+      (i.e. vfspk3 / vfswad: two formats, but the manager part is pretty much the same)
+      vfsFindFile(relative filename):
+        this worked by searching through the list of loaded pk3/wad files for the file
+        then trying to search through the search directories
+        - wasn't properly documented about what it does / how is the search performed
+        - not consistent with existing code, duplicate of vfsGetFullPath for the most part
+          can't be added to the VFS API as-is, it would confuse the interface
+        - usage of vfsFindFile in the code doesn't justify the way it proceeds for search
+        foxing it, replacing by calls to vfsGetFullPath
+      vfsFileExists(relative filename):
+        returns wether a file exist, can be flagged to search in pk3/wad or straight filesystem
+        - this is a duplicate / particular case of vfsGetFileCount
+        foxing it too, we need to extend and update vfsGetFileCount instead
+    - mapq3: the changes completely fucked q3 map parsing
+      need reorganization. same module provides parsing for all .map based formats
+      we use wrappers around the actual calls and globals in the module to select formats
+      MAPVERSION_Q2 and MAPVERSION_Q1 don't need to be there yet, they are not supported
+      MAPVERSION_HL means WC >= 2.2
+      (when introduced, MAPVERSION_Q2 would be Q2 or qer+hl plugin (same))
+      MAPVERSION_HL uses "maphl" minor name (instead of mapq2)
+      cleaned up the Q3 read/write code that got broken
+      cleaned up various commenting/hack that deal with Q2!=HL format .. we'll see about Q2 when we actually do it
+      bad cut and paste from cmdlib code, using actual dependency to cmdlib instead (see below for some cmdlib updates)
+    - took out all SafeRead SafeWrite code from cmdlib, removed annoying cmdlib dependency to Error function
+      all file access go through VFS module, the cmdlib 07/06/2002 15:47file code was way old  
+    - radiant/points.cpp pointfile code changes (that's used only for non-monitored compiling now)
+    - applied patch 267 (hydratoolz fixes)
+    - commented out some bworldcraft flagged stuff in mapq3/parse.cpp
+    - updated the .dsw .dsp to compile and copy HL stuff  
+    - TODO: need to rationalize where the modules are placed and identify HL specific modules
+    - TODO: seems to be a synapse crash when unloading plugins (hydratools)
+      (looks like I didn't look at the plugin unload code yet actually)  
+    - TODO: make sure HL setup puts eclass_singleload="1" and no_patch="1" 
+    - TODO: WATCHBSP_KEY and TEXTURE_KEY hardcoded for HL need cleanup
+    - TODO: imagehl duplicates some image functionality
+      imagehl is supposed to be only for HL-specific image formats
+      it 'adds' the required formats to the stuff that image makes available for everyone already
+    - TODO: HL doesn't have a BSP menu!  
+    - TODO: rename mapq3/ into map/, the map module handles all .map formats
+    - TODO: it's likely that we only need a vfs/ module instead of vfspk3/ and vfspak/
+      think about it, see if we really act on this (or do we need to abstract the manager and some file format modules)
+    - TODO: HL synapse.config needs to use maphl
+    - TODO: wtf is enginename="quake2" in hl.game
+    - TODO: I don't have a sample HL map to play with, so I didn't test the changes against
+
+05/06/2002
+  TTimo
+  - fixups to make 1.3 start (Q3 mode)
+  - turned off C++ exception support in the modules/plugins, as we don't use it
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543
+    exit properly if missing chunks in synapse.config, don't crash
+      
+  Hydra
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=558
+    fix for version check in release build
+
+  ======================================================================================
+  -- http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=197
+     HL support patch
+  ======================================================================================
+  04/6/2002
+    Hydra
+    - Patched in some CVS changes and fixed a little issue with the
+      new entity file loader code.
+  
+  28/5/2002
+    Hydra
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=544
+      Selected Entity Bounding Box obscured by brushes fix.
+    - Moved the "wad" keypair creation code from the Map module into
+      a new plugin called HydraToolz, this means that wad keypair is
+      done manually by the user, as in fact it should be.  (as the
+      order of the wads is actually important).
+    - Fixed a problem with the wads in the wad list being re-ordered.
+  
+  27/5/2002
+    Hydra
+    - Created an inital implementation of a sprite model plugin.
+      According to the powers that be, it seems creating a model
+      plugin is hackish.
+      It works ok, but there is no way to attach models (sprites if you will)
+      to non-fixedsize entities (like func_bombtarget)
+      Also, I can't get the alpha map stuff right so I had to invert the alpha
+      mask in the spr loader so that 0xff = not drawn pixel.
+  
+  17/5/2002
+    Hydra
+    - "Wad" keypairs are now used when loading a map and speeds up map loading
+      significantly. This sorts out quite a few issues that could otherwise occur.
+    - Map loader now uses textures from wads listed in the the "wad" keypair first.
+    - Added a texture name mapping cache system to the .map loader
+      this significantly improves load times of maps that don't store texture
+      names along with paths (e.g. "mytexture" not "mytextures/mytexture".)
+    - Added vfsFileExists() to the vfs table (for above) and added it to
+      vfspk3 and vfswad
+    - Map loading and saving times are printed to the console.
+    - Wad file names from the "wad" key pair are logged to the console when
+      a map is loaded
+    - The user is informed if the textures loaded were not found in the
+      wad files in the "wad" keypair.
+    - The user is informed if the textures was not found in any wad file at all
+      (Q2/HL only, the shader module still gives you similar information for other
+      games when a shader activation fails)
+  
+  
+  8/5/2002
+    Hydra
+    - Added basic support in mapq3 for reading maps saved by Worldcraft 2.2+
+      in .map format (It uses [ ]'s round some of the texture co-ordinates)
+      TODO: do we need to be able to save a map in this format too ?
+    - Added support for loading ZHLT style point files (*.lin)
+    - Added wad filename information when loading textures.
+      (This helps take the ambiguity out of which wad files textures come from,
+      so that we can correctly setup the worldspawn "wads" e-pair manually.)
+      Note: This will be removed when the "wads" worldspawn key is built by radiant.
+    - added vfsFindFile() to vfs table.
+    - VFSWAD: vfsLoadFile() no longer ignores paths when loading textures
+      (this was by design, but the design has changed for the better)
+    - When loading a Quake2 map file, vfsFindFile() is used to find the actual path of
+      the shader/texture being loaded.
+      This fixes all the weird issues that crop up when we were able to use non
+      wad-relative texture names (<shader>) and wad-relative(<wadname>/<shader>).
+      (such as having an image loaded twice in memory.)
+      We also now get the correct shader name in the suface inspector too.
+      Note: not sure if this code should stay in the map parser, or wether it should
+      be moved to where shaders are first initialised.
+      Note: maybe this needs to be when a halflife map is loaded, not specifically a
+      quake2 map file.
+    - added EClass_SupportsMultiple to the EClass loader API.
+      Note: this is poop.  FGD files can be additive but radiant makes it so they can't be.
+      This function would not be needed if the eclass loader itself took care of the init,
+      rather then the manager taking care of the init.  Also note that if the loader were
+      to take care of the init then FGD files *CAN* be additive, as it's not down to the
+      format of the FGD files.  However, it'll do for the moment because all the supplied
+      FGD files that come with halflife and it's mods are meant to be used one at a time.
+    - removed support for having an additional (not external) eclass loader.
+      Just ifdef'd for now, grep for USEADDITIONALECLASSLOADER.
+      We never mix entity definition formats and synapse.config allows us to just have the
+      right one and also there is no mechanism for setting g_bHaveEClassExt anymore.
+    - Texture subset on by default for halflife.
+    - default texture scale is now set to 1 instead of 0.5 for halflife.
+      (needs to be 1 for q1/q2 too)
+    - patch toolbar disabled by default for halflife and it's also disabled
+      in the preferences so it can't be turned back on)
+      (needs to be 1 for q1/q2 too)
+    - bsp monitoring disabled by default for halflife
+    - When you drop a light entity the epair "_light" is used instead of "light" (halflife specific)
+    - removed -fs_game additions to the map compiler commands; ZHLT doesn't support it.
+    - saving of contents/flags/values in q2 format maps disabled (ZHLT doesn't like em !#?!)
+      TODO: re-enable for Q2 (but not halflife) format maps when we can
+      can figure out what game/engine combo we're using from within a module
+    - configured mapq3 to have dynamic VFS API too
+    - Added halflife shaderlist.txt parsing back in, it's actually useful
+      afterall (for editor shaders).
+  ======================================================================================
+  -- end HL support patch
+  ======================================================================================
+  
+01/06/2002
+  TTimo
+  - merging 1.2.7 -> 1.2.9 changes into 1.3, merge notes:
+    - the win32 .dsp are a bit different, using the $(CORERADIANTDIR) post build commands now
+    - merged in the JKII/STVEF hardcoded chunks, should probably check that everything is still fine on that end
+      was setting the "dir" epair in project files intead of "gamename" like all other games?
+      (which should really be "fs_game" anyway, I wonder who decided to call it "gamename")
+    - rebuilt a setup. we have a problem with RADIANT_MAJOR RADIANT_MINOR it seems
+    TODO: setup needs to use GtkRadiant-1.<MAJOR> as basename in start menu, and base for installation
+    C:\Program Files\GtkRadiant-1.3 and C:\quake3\Radiant-1.3 etc. for the game packs
+    TODO: add HL setup chunks!
+
+===============================================================
+-- merging release-1_2_7 -> release-1_2_9 into 1.3
+===============================================================
+28/5/2002
+  TTimo
+  - final fixes for Linux 1.2.9 setup
+
+27/5/2002
+  TTimo
+  - bug 521, q3 entities.def trigger_hurt fix
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=542
+  default texture scale is configured in .game
+  defaults to 0.5 (q3/wolf) if nothing specified, under the prop "default_scale"
+  removed the item from the prefs dialog too
+  updated the nightly setup to put the proper param in JKII .game
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=509
+  changing texture window scale changes selected brushes texture
+  re-selecting the previous texture can be done, but is a bit tedious to write
+  made sure we deselect before re-init of the tex window view
+  - fixed linux setup code bug. won't be any update, only a full release on linux
+
+26/5/2002
+  TTimo
+       - parallel cons working at last! was a problem with the targets list ('Default' command)
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=515
+       using the eclass extents for the box if model can't be found
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=435
+       changed the submenu cascading params to avoid the overlap (we fit less stuff now obviously)
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=540
+       that sigchld handler is only used on Linux to report the run times
+       since we are rewriting the whole BSP code stuff, we can drop this for now
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=538
+       removed that prompt and display
+       - we build radiant.x86 in cons scripts, updated the setup code
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
+       updated the setup script to install new wolf_entities.def
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=302
+       added q3map2 URL to global.xlink, updated Linux setup
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=465
+       printing q3map version info through the net stream
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=539
+       fixed various media, some related code, and Linux setup
+  - fixed watchbsp.cpp "jk2.game", was breaking game spawn for wolf (needed else if)
+       
+       SCDS_reyalP
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=504
+       fixed bobtoolz vis viewer to work with RTCW (BSP version)
+       - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=526
+       update of the Wolf entities file
+
+25/5/2002
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=164
+  corruption on exit, tried to look some more. Cleaned up some source, need looking at Gtk code closer
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=536
+  cleaned up SHADER_NOT_FOUND SHADER_NOTEX internals some more
+  added a clean error exit in case this happens, fixed a crash that would happen anyway (Patch_LODMatchAll)
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=394
+  cleanup/sanitize of the pattern filtering code, it was ugly. did some doxygen documentation
+  fixed part of the print XY code, more broken stuff showed up, dropping it
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=503
+  region compiling was indeed fucked, spog b0rkage
+  fixed so that it works again
+  denying compile with camera out of the region
+  reworked SelectBrush to deal with regioning and select the right brushes
+
+24/5/2002
+  TTimo
+  - Linux build fix
+
+23/5/2002
+  Riant & TTimo
+  - STVEF patch and setup scripts
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=516
+  moved error handling code to it's own file radiant/error.cpp
+  compiled with UNICODE define (that's why I had to isolate), and process the error string
+  so that Gtk can print it (that's only relevant to win32)
+
+22/5/2002
+  TTimo
+  - quickfix, cleanup of the console verbosity
+
+11/5/2002
+  TTimo
+  - final IS script updates for JKII game pack, version 1.2.8-jk2
+  - fixed a bad karma #ifdef _DEBUG chunk in Texture_NextPos (causing crash of release build)
+  - added web url support in .xlink files (strstr on http://)
+
+10/5/2002
+  TTimo
+  - cleaned the build step copy from $(QUAKE3RADIANTDIR) to $(CORERADIANTDIR)
+  - system shaders auto-load: display 'system' in the prefs
+  - force BSP monitoring off in jk2 mode
+  - cleaned up web update check, added HL (3) and Jedi Knight II (number 4) (on the web database too)
+  - updated IS setup script for mapextras.pk3
+  Riant
+  - system shaders auto-load in prefs
+  Raven
+  - mapextras.pk3 as replacement for system.pk3 (system editor textures)
+
+8/5/2002
+  Riant
+  - game pack and patches for JKII support
+  TTimo
+  - .game additions to specify .shader path (shaderlist and shader scripts)
+    NOTE: if we ever use q3map for JKII compiles, that would need to be propagated
+  - reworked the shaderlist to list all the included shaders
+  - built a system.pk3 pack for textures/system/ and textures/radiant/ (misses a few pieces still)
+  - MP / SP mapping mode toggle, SP ignores mp_*.def MP ignores sp_*.def
+  - fs_basepath does not get added during BSP command expansion for JKII mode
+  - more verbose on script location and junk.txt location when monitored compile is disabled
+    (the BSP compilation WANTS to be rewritten, it's getting VERY URGENT)
+  - JKII game back IS setup lands
+
+7/5/2002
+  TTimo
+       - using radiant.x86 as Linux target (instead of radiant, didn't fit with the setup procedure)
+       - bumped version tag
+       - TODO: bug #453 code needs backported from 1.3
+
+6/5/2002
+  TTimo
+  - fixed typo in plugins/mapq3/write.cpp Map_Write
+  g_count_entities = 0; instead of g_count_brushes
+  - more fixes which showed up while merging this with 1.3
+
+-- release-1_2_7 ----------- tagged and Stable-1_2 merging into trunk
+
+02/5/2002
+  Gef
+  - added filtering on unselect for newly created brushes/entities (bugzilla: #374)
+  SPoG
+  - added undo for pasted/cloned brushes
+
+============================================================
+-- end release-1_2_7 -> release-1_2_9 merge
+============================================================
+
+15/05/2002
+  TTimo
+  - rewrote the ref count code cleanly, added some elements to design and todo
+  - wrote the core shutdown code of synapse, 1.3 exits cleanly without crashing (well, in most cases it seems)
+
+10/05/2002
+  TTimo
+  - began writing proper unloading and shutdown of synapse (see libs/synapse/docs/unload.txt) 
+    design doc started, non active modules are unloaded after startup
+    need win32 implementation of ReleaseSO
+  - quickfix on win32 (ReleaseSO)
+  
+07/05/2002
+  SPoG
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=512
+  - cleaned up strHomeMaps and strFSBasePath stuff
+    prompts for maps, models, sounds etc are fs_game-dependant
+
+  ===========================================================================
+  -- merging Stable-1_2 between Stable-1_2-tag and release_1_2_7 into trunk
+  merge ChangeLog
+  =============================================================================
+  07/05/2002
+       - using RADIANT_MAJOR_VERSION and RADIANT_MINOR_VERSION for the version info, this was conflicting with synapse
+       
+       - m_strHomeMaps
+       http://zerowing.idsoftware.com/viewcvs/viewcvs.cgi/GtkRadiant/include/qertypes.h.diff?r1=1.27&r2=1.28&only_with_tag=MAIN
+       http://zerowing.idsoftware.com/archives/gtkradiant/2002-February/002170.html
+       posted on the ML, bringing it back in from 1.2
+       
+       setup scripts:
+         easily merged, as the 1.3 scripts have not been touched mostly
+       
+       qe3.cpp conflict:
+         1.2 tweaks stuff in the QE_*Project* functions
+               1.3 has them mostly commented out
+               applying manually where relevant
+               the project settings stuff is very different, and the changes can't be applied as is
+               given the fixes I had to do in 1.2, I'd expect the current 1.3 version to be fairly broken
+               a complete kill and rewrite of the prefs/project stuff might be our option anyway
+               http://zerowing.idsoftware.com/archives/gtkradiant/2002-May/003038.html
+       qe3.cpp QE_InitVFS conflict:
+         1.3 has some changes when creating the files in a new userprefix (ex. ~/.q3a/baseq3/scripts /maps /maps/prefabs etc.)
+               merged by hand, probably needs to be checked
+       qe3.cpp OpenDialog SaveAsDialog conflict:
+         commented out in 1.3, getting rid of it completely
+       
+       preferences.cpp conflict:
+         1.2 adds CUSTOMSHADEREDITOR_KEY pref
+               1.3 uses a completely different syntax for prefs
+       preferences.cpp conflict:
+               prefab path pref changes conflict with 1.3 pref syntax
+               applying changes manually to 1.3 codebase
+       
+       pmesh.cpp conflict:
+               1.2 adds pref to group / not group patch thickening
+               1.3 changes the way we manipulate entities around that code
+               merged manually, would be worth checking that the thicken pref works
+       
+       pluginmanager.cpp conflicts: synapse completely changes that part
+       on relevant 1.2 thing is the removal of pfnRadiant_Free
+       
+  map.cpp Map_ImportEntities conflict
+               1.3 has bug 453 map conversion promt that was not backported to 1.2 (caused merge to conflict a bit)
+               usin 1.3 code and checking 1.2 changes manually
+  
+       using radiant.x86 as Linux target (instead of radiant, didn't fit with the setup procedure)
+  
+       06/05/2002
+       not merging in .dsw .dsp
+       an eclass.cpp fixed moved to eclass_def.cpp
+       mainframe.cpp is always a bitch to merge, sent several mail comments to list about conflicts that arose
+         MainFrame::OnFileSaveas needed some updates that were not in the diff (correct default prompt)
+               (same for MainFrame::OnFileSaveregion)
+               MainFrame::OnFileNewproject conflicts a bit, changes have been made in 1.2 and 1.3
+               changes in 1.2 seem more crucial, using the 1.2 version, and patched the 1.3 manually over it
+                 (might need to be checked, bug #506)
+      
+       TODO: need to check for parasite g_free that I added back from the file dialog    
+  
+  propagated ChangeLog from Stable-1_2
+  =============================================================================
+       02/5/2002
+         Gef
+         - added filtering on unselect for newly created brushes/entities (bugzilla: #374)
+         SPoG
+         - added undo for pasted/cloned brushes
+         TTimo
+         - shift+left click to open shader editor no longer selects the texture on the way
+           (this was unstable, pCurrentShader could become NULL somehow)
+         - editpad bindings were completely broken
+           attempts to make it work again failed
+               taking it out
+               changed the prefs, on win32 you select between internal shader editor or win32 .shader binding
+               we have lost the ability to jump to a given line, if someone has a good solution for line jumping, let me know
+         - one more fix to the MAJOR / MINOR safe checks stuff
+         - bug #500: oooogly, I removed a line which I should not have :)
+
+       01/5/2002
+         TTimo
+         - "Save selected.." load/save in fs_game sensitive directory too
+         - removed a bunch of unused/broken project settings items
+         removed most of them actually .. project settings are .. ahem
+         - added an optional 'go to url' button in gtk_MessageBox
+
+       30/4/2002
+         Gef
+         - fixed lod drawing of selected patches when patches are filtered
+
+       29/4/2002
+         TTimo
+         - bugzilla #467
+           make patch inspector deny space textures
+           make mapq3 write code drop space textures
+         - bugzilla #132
+           removed remotebasepath and texturepath
+               rewrote the Textures > Load Directory (which was kinda relying on texturepath)
+         - bugzilla #355
+           uploading editpad zip to qeradiant.com misc/ in files section, replacing the win32 message about editpad
+           added editpad quote in qer.com totd
+         - fixing the map load/save dialogs to work correctly with mod settings on win32 (was done on Linux and still broken on win32)
+
+
+       26/4/2002
+         Gef
+         - fixed patches losing their shader if outside region when calling flush/reload 
+           (bugzilla: #492)
+         - blocked textures with spaces from loading in Texture_ShowDirectory with a warning
+           (bugzilla: #467)
+         - fixed a dud shader (liquids.shader -> textures/liquids/ripplewater2_back) didn't have
+           the textures/liquids prefix
+
+       25/4/2002
+         Gef
+         - fixed a broken image link in the shader manual (bugzilla: #486)
+         - changed prtview to use ~/.radiant/<version>/prtview.ini instead of 
+           ~/.q3a/radiant/prtview.ini on linux
+         - fixed prtview loading/saving config (bugzilla: #424)
+         TTimo
+         - removed QERApp_RadiantFree from the function table
+         we can malloc and free across modules configured correctly for the CRT (Common Runtime DLLs)
+         cleaned up related broken malloc / free strategy in the plugins (vfsLoadFile uglyness)
+         - added main build date and version to curry / pk3man / prtview
+
+       23/4/2002
+         SmallPileOfGibs
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=229
+         flush and reload was affecting texturing of selected brushes
+         TTimo
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=489
+         File > Check for update menu item, jumps to the website and checks for update
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
+         win32 part, RADIANT_MAJOR RADIANT_MINOR written out by setup
+         - more stuff on File > New Project and common mod setup issues (not finished yet)
+
+       22/4/2002
+         TTimo
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
+         reworking a bit the installer stuff
+         wrote the version checking
+         needs testing on win32 (RADIANT_MAJOR and RADIANT_MINOR are required in the install now)
+
+       21/4/2002
+         TTimo
+         - trying more seriously to get a new nightly out
+         updating the ChangeLog for current 1.2.7 from this file
+         cleanups, browsing through the bugs to close/update/fix
+         - http://zerowing.idsoftware.com/bugzilla/showattachment.cgi?attach_id=197
+         I kinda fixed that myself already, going through the diff and applying the missing stuff
+         creating the prefabs/ dir in QE_InitVFS
+         - added a line about the games dialog / auto-select at startup in the dialog frame
+
+       15/4/2002
+         TTimo
+         - cleaning some old commented out map load code
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=477
+         on Linux:
+           - strHomeMaps was init without taking care of m_strFSGame
+           - SaveAsDialog was not using strHomeMaps
+           NOTE: should strHomeMaps be spcific to Linux, or we will do better if we unify
+         need similar checks on win32
+
+       13/4/2002
+         TTimo
+         - kicking the source to generate new doxygen on zerowing
+
+       09/4/2002
+         Gef
+         - setting the sel_mode accordingly when (i)nverting selection, verts were being drawn when 
+           they shouldn't have been
+
+       05/4/2002
+         Gef
+         - fix File/New Project for mods so it doesn't fail if the dir exists (bugzilla: #459)
+         - add Linux-isms for New Projects & read/write permissions...
+           note: for a total conversion, basepath needs to be manually set
+         - prevent opening multiple internal shader editor dialogs
+         - added preference for using a custom shader editor
+         - set horizontal scrollbar to be automatic instead of never for entity keyval list (bugzilla: #4)
+         - added a call to Select_Reselect() in XYWnd->OnViewEntity() to make sure its modifying the 
+           current selection (bugzilla: #436)
+         - fixed entity dialog passing events through to main window (bugzilla: #454) return values
+           were backwards
+         - patching in the .pfb extension adding stuff (bugzilla: #259)
+         - fixed thickened patches not being grouped (bugzilla: #226). this was supposed to be happening
+           anyway, the entity create code was called before the patches were selected
+
+       02/4/2002
+         EvilTypeGuy
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=457
+         add entity #X and brush #X comments back to saved .map files
+
+       24/3/2002
+         Hydra & TTimo
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=444
+         only show empty alpha channel warning if the tga texture is actually 32 bit
+         (24 bit would always have empty alpha, the warning was useless in this case)
+
+       19/3/2002
+         Gef
+         http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=217
+         - Set show value to true for angle and movement velocity sliders in preferences
+         - Increased the maximum value of angle velocity from 6 to 100
+
+       18/3/2002
+         SPoG
+         - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=419
+               fixed File->Save with region active acts the same as File->SaveRegion for ents
+
+
+  end merge  
+  =============================================================================
+
+16/4/2002
+  SPoG
+  - fixed MDC_XYZ_SCALE value
+
+12/4/2002
+  SPoG
+  - fixed win32 compile error - vc6 being nitpicky
+  - fixed refcount init on CSynapseAPIManager
+  - cleaned up md3model win32 project file
+
+9/4/2002
+  Gef
+  - added nudging for selected brush and patch vertices (bugzilla: #240)
+  - added selected brush vertex highlighting
+  - sorted all the ID_'s in HandleCommand alphabetically to make it easier to track things down
+  - setting the sel_mode accordingly when (i)nverting selection, verts were being drawn when 
+    they shouldn't have been
+
+5/4/2002
+  EvilTypeGuy & djbob
+  - patched in djbob's grid minor/major color settings for gridsize < 1
+    http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=24
+
+1/4/2002
+  TTimo
+  - configured md3model to have dynamic VFS API too
+  - cleaned up texwindow.cpp texture extension loop
+  - updated current HL media with hl's synapse.config
+    http://zerowing.idsoftware.com/stuff/HL-media-0401.zip
+  - checking in new synapse.config for Q3/RTCW
+  - fixed win32 project files, removed hltoggle.h
+  - bumped version to 1.3.3
+  
+31/3/2002
+  TTimo
+  - XML runtime configuration of synapse
+  uses a synapse.config in the gametools path, we can add a line in the .game to specify the file later on
+  - various cleanups and removal of dead code
+  - Linux build system: sanitized CFLAGS, libxml, STLPort and glib include path all in the toplevel Construct file
+  - removed the 'cons -- halflife' option, the binaries are unified again
+  - cleaned up image loading
+
+
+29/3/2002
+  TTimo
+  - patching in Hydra's code for Half-Life, builds and runs on Linux, need to quickfix on win32 now
+  - build system on Linux: some things are still hardcoded into the core, you need a different core
+    for Q3/RTCW or HL for now. do ./cons -- halflife to build HL mode (build trees are seperate)
+  - there is no media / install procedure yet, but a zip with what you may need for install is available:
+    http://zerowing.idsoftware.com/stuff/HL-media-0329.zip
+  - cvs added all the new files
+  - patched various things from the patches, don't have a precise list
+    cleaned up the interface requests, isolated HL specific between TMP_HALFLIFE defines
+    removed 'tga' from imagehl, two modules providing the same API has unexpected results
+    
+  TODO: the image loading is the main problem right now. We should not have any place that scans the 
+  extensions, this is done internally to the image load manager? texwindow.cpp does enumeration of the
+  minors too .. but that may be legal in this case.
+  
+  TODO: synapse config at runtime through XML (rather big piece)
+
+  - fixing build on win32
+  bad coding practices: 'for (GSList *choicelst = ..'
+  added a quick hack include/hltoggle.h for easy switch q3/rtcw or hl compile
+    (remaining hardcoded stuff is temporary)
+
+
+28/3/2002
+  Gef
+  - added linux pthreads support to tools
+  - removed old terrain.c and lightv.c from q3map2 Conscript
+
+27/3/2002
+  Gef
+  - updated cons for q3map 2
+  - minor q3map2 fixes for linux compile errors/warnings
+  - minor warning fix in map.cpp
+  SPoG
+  - changed entity_addtolist to add entities to end of list instead of beginning
+  - added eclass_forname to eclassmanager interface
+  - fixed setting eclass before model-update for entities loaded from map
+  - fixed setting bounding box for models after model-update
+  ydnar - q3map2
+  - fixed crash on -connect and other gremlins related to argument processing
+  - removed flag that prevented Castle's maps from compiling
+
+
+27/3/2002
+
+  Hydra
+
+  Important Changes:
+
+  - Added VFSWAD modules for extracting textures from WAD files.
+  - Added ImageHL for loading textures contained in WAD files
+  - Updated shaders source code so that you can produce ShadersHL.dll
+    (single minor using #ifdefs)
+  - MapQ3 source updated so that it can load and save q2 format maps
+    provides a multiple minors.
+  - Added EClassFGD for loading FGD definition files
+    (I documented this code quite well, if you're interested...)
+  - Added support for iconsprite() settings in the FGD loader, we set
+    eclass_t->skinpath with the name of the sprite
+    TODO: write a sprite model plugin.
+
+  Fixes:
+
+  - Fixed incorrect line numbers being reported when script files had // comments in them
+  - Removed EClass_Create from the EClass manager _EClassManagerTable
+  - Replaced all occurences of "textures/radiant/notex" in shaders.cpp with a define.
+  - Fixed a crash in shaders.cpp when there was no default texture.
+  - Fixed a possible issue with g_bCancel_Map_LoadFile
+  - Added a crash fix for uninitialised patchMesh_t->pSymbiot
+
+  Core Changes Required for HalfLife Support:
+
+  - Set MAX_FLAGS to 16 to support Halflife's extra spawnflags, adjusted
+    entity inspector to display the new spawnflags, updated FGD loader
+    to load them correctly (previously it only loaded the ones with values <8)
+    (Done without breaking the old Q2 code that was commented out)
+  - Added GetTokenExtra to the _ScripLibTable
+  - Kludged texwindow.cpp to allow loading extension other than "tga" and "jpg"
+    TODO: ttimo, we need something in synapse to help with this.
+  - Plugin manager requests different API's depending on .game file used.
+    TODO: this needs to be done on a PER GAME basis, not PER .GAME FILE.
+  - Shaderlist.txt is not parsed on startup if hl.game is used.
+    TODO: this needs to be done on a PER ENGINE basis, not PER GAME.
+
+  Cosmetic Changes:
+
+  - Changed MAPQ3's minor_name from "map" to "mapq3" (also adds "mapq2" as a minor)
+  - Changed XMAP's minor_name from "xmap" to "mapxml"
+  - Changed VFS's minor_name from "quake3" to "pk3", more inline with VFSWAD now.
+  - Changed file/Load to file/Import on the menus
+  - When a shader (Q3/HL) is not found a message is displayed in the console
+    (only once for each shader that is not found).  This is so the user can
+    quickly get a list of missing textures/shaders.
+
+26/3/2002
+  ydnar
+  - initial q3map 2.0 source import
+    new tools/quake3/q3map2 directory
+         common/qfiles.h and common/surfaceflags.h modified
+         affects q3map 1.x too, bumped MAX_MAP_BRUSHSIDES to 0x40000
+         will need to write the build scripts and compile on Linux too
+  SPoG
+  - Re-added dialog prompting user to convert/change-mode/abort when map BP mode
+    conflicts with project settings
+  - large entity/models update
+  +++ include/ientity.h   25 Mar 2002 11:37:54 -0000
+    entity module
+      - interface cleanup
+      - common #defines for easy transition
+  +++ include/igl.h       25 Mar 2002 11:37:55 -0000
+    opengl module
+      - Vertex Arrays support
+  +++ include/imodel.h    25 Mar 2002 11:37:57 -0000
+    model module
+      - interface cleanup
+  +++ libs/mathlib.h      25 Mar 2002 11:37:59 -0000
+    vector macros - cleanup
+    m4x4
+      - documentation of matrix layout
+      - interface for utility functions for axis-angle and quaternion rotations
+      - interface for new utilities for specifically transforming points/normals 
+    aabb
+      - interface for faster aabb-ray test without finding intersection point
+      - interface for utility to calculate an aabb to contain a transformed aabb 
+  +++ libs/mathlib/bbox.c 25 Mar 2002 11:38:01 -0000
+      - cleanup of use of qboolean
+      - implementation of fast aabb-ray-test
+      - implementation of aabb-for-transformed-aabb
+  +++ libs/mathlib/m4x4.c 25 Mar 2002 11:38:02 -0000
+      - implementation of utility for rotation matrix from axis-angle/quaternion
+      - cleanup of implementation of matrix multiplication functions (optimise for in-order array traversal)
+      - implementation of new utilities for specifically transforming points/normals
+  +++ libs/mathlib/ray.c  25 Mar 2002 11:38:02 -0000
+      - replace use of m4x4_transform_vec3 with new point/normal specific utils
+  +++ plugins/mapq3/plugin.cpp    25 Mar 2002 11:38:06 -0000
+      - rename g_EntityTable using #define in ientity.h
+  +++ plugins/mapq3/plugin.h      25 Mar 2002 11:38:06 -0000
+      - rename g_EntityTable using #define in ientity.h
+  +++ plugins/mapxml/xmlparse.cpp 25 Mar 2002 11:38:06 -0000
+      - buffer-safe dtd path construction (without using string class, in case of unknown bugs)
+  +++ plugins/md3model/Conscript  25 Mar 2002 11:38:06 -0000
+      - remove entity-module files from md3model conscript 
+  +++ plugins/md3model/md3model.cpp       25 Mar 2002 11:38:07 -0000
+      - implementation of generic quake-style-model class CModel
+      - implementation of CModel-derived md3/mdc classes
+  +++ plugins/md3model/md3model.dsp       25 Mar 2002 11:38:08 -0000
+      - remove entity-module files from md3model dsp
+  +++ plugins/md3model/md3model.h 25 Mar 2002 11:38:08 -0000
+      - interface for generic quake-style-model class CModel
+      - interface for CModel-derived md3/mdc classes
+  +++ plugins/md3model/md3surface.cpp     25 Mar 2002 11:38:09 -0000
+      - implementation of generic quake-style-model class CSurface
+      - implementation of CSurface-derived md3/md2/mdl/mdc classes
+  +++ plugins/md3model/md3surface.h       25 Mar 2002 11:38:09 -0000
+      - interface for generic quake-style-model class CSurface
+      - interface for CSurface-derived md3/md2/mdl/mdc classes
+  +++ plugins/md3model/plugin.cpp 25 Mar 2002 11:38:10 -0000
+      - provide support to synapse for loading md3/mdc/mdl/md2 models, and mdl images
+  +++ plugins/md3model/plugin.h   25 Mar 2002 11:38:10 -0000
+      - interface for loading md3/mdc/mdl/md2 models, and mdl images 
+  +++ radiant/brush.cpp   25 Mar 2002 11:38:18 -0000
+      - #ifdef remove Group/Brush-Patch-Epair related stuff
+      - const correctness for ValueForKey interface const change
+      - add bounding-box update for models in Brush_Build
+      - remove old brush parsing/writing stuff
+      - remove old eclass-model loading/displaying stuff
+      - enable vertex arrays on light drawing
+      - moved brush is-selected? utility to brush.cpp
+  +++ radiant/brush.h     25 Mar 2002 11:38:18 -0000
+      - comment out interface for old brush parse/write stuff
+      - comment out interface for brush epair stuff
+  +++ radiant/brush_primit.cpp    25 Mar 2002 11:38:20 -0000
+      - remove old brush-primitives parsing/writing stuff
+  +++ radiant/camwindow.cpp       25 Mar 2002 11:38:23 -0000
+      - moved brush-bbox update for models to brush.cpp:Brush_Build
+      - bugfix for material colour setting when drawing models
+  +++ radiant/eclass.cpp  25 Mar 2002 11:38:24 -0000
+      - removed old eclass-model checking/loading stuff
+      - added const checking for Eclass_ForName interface
+  +++ radiant/entity.cpp  25 Mar 2002 11:38:26 -0000
+      - REMOVE THIS FILE
+  +++ radiant/entity.h    25 Mar 2002 11:38:26 -0000
+      - REMOVE THIS FILE
+  +++ radiant/groupdialog.cpp     25 Mar 2002 11:38:29 -0000
+      - change entity creation to not use Entity_Create (function was removed)
+      - commented groups stuff
+  +++ radiant/gtkdlgs.cpp 25 Mar 2002 11:38:36 -0000
+      - const correctness for ValueForKey
+  +++ radiant/gtkmisc.cpp 25 Mar 2002 11:38:39 -0000
+      - added filetype patterns for mdc/mdl/md2
+  +++ radiant/main.cpp    25 Mar 2002 11:38:41 -0000
+      - const correctness fixes
+  +++ radiant/mainframe.cpp       25 Mar 2002 11:38:59 -0000
+      - change selection -> merge entity and selection -> separate from entity to go through mainframe class
+      - implementation of mainframe functions for selection -> merge entity and selection -> separate from entity
+      - made entity grouping and detail/structural settings undoable
+      - commented out old groups stuff
+  +++ radiant/mainframe.h 25 Mar 2002 11:39:01 -0000
+      - interface for mainframe functions for selection -> merge entity and selection -> separate from entity
+  +++ radiant/map.cpp     25 Mar 2002 11:39:04 -0000
+      - const correctness fixes
+  +++ radiant/pluginmanager.cpp   25 Mar 2002 11:39:08 -0000
+      - removed model table
+      - stopped requesting model table from synapse
+      - request undo table from synapse
+      - commented out support for IEpairs stuff - NOTE: to be integrated with entity module
+      - fill interface table for opengl vertex array support 
+      - fill interface table for undo
+  +++ radiant/pmesh.cpp   25 Mar 2002 11:39:18 -0000
+      - cleanup patch cap and patch thicken to create entities using entity module interface (without Entity_Create)
+      - removed old patch parse/write stuff
+      - #ifdef'd out patch epair/groups stuff
+  +++ radiant/qe3.cpp     25 Mar 2002 11:39:21 -0000
+      - const fixes
+      - buffer-safe dtd path construction (without using string class, in case of unknown bugs)
+  +++ radiant/qe3.h       25 Mar 2002 11:39:24 -0000
+      - don't include entity.h, include ientity.h and forward-declare entity-table instead
+      - include imodel.h but don't forward declare model-table
+      - include iundo.h and forward-declare undo table
+      - comment out interface to old patch parse/write stuff
+      - comment out interface to old brush parse/write stuff
+      - comment out iepairs header include.. NOTE: to be integrated with entity module/interface 
+      - include eclass interface (we don't have an eclass.h)
+      - declare interface for CreateEntityFromName (generic useful func)
+      - declare target/targetname utils interface (we don't have a targetname.h)
+  +++ radiant/select.cpp  25 Mar 2002 11:39:27 -0000
+      - cleanup implementation of entity selection-grouping/ungrouping utlities
+  +++ radiant/select.h    25 Mar 2002 11:39:27 -0000
+      - cleanup interface for entity selection-grouping/ungrouping utlities
+  +++ radiant/undo.cpp    25 Mar 2002 11:39:29 -0000
+      - removed workaround for wierd entity_clone behaviour (changed in entity module)
+      - avoid using Entity_FreeEpairs (not exposed by entity module)
+  +++ radiant/xywindow.cpp        25 Mar 2002 11:39:35 -0000
+      - const fixes
+      - cleanup implementation of CreateEntityFromName to be a usful generic utiliy function
+      - enable vertex arrays in XY_Draw
+      - enable undo for right-click dropping entities in XY window
+  TTimo
+  - various fixes to make the above compile on Linux, checkin to cvs
+  - fixing some win32 build stuff
+  
+  Hydra
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=434
+  fixed setSpecialLoad in .def code
+
+19/3/2002
+  Gef
+  - Modified the fix for LoadImage to be more consistent with other code
+  - Applied Hydra's fix for empty alpha channel warnings & cleaned up indentations (tabs) in lbmlib.cpp
+    also added output of the tga type when a tga file fails to load
+  - Reverted my over complex fix (read; mess) for strtok_r to use strtok instead of manual tokenising
+
+17/3/2002
+  Gef
+  - Fixed LoadImage API list not being incremented while trying to find image minors, result was
+    infinite loop when loading images that weren't of the first type (tga)
+  - Fixed cloning giving dtd errors. mapxml/xmlparse.cpp:ParseXMLStream() was using 
+    g_FuncTable.m_pfnGetQERPath() as the dtds path... disabled validation until spog can check 
+    that my fix is the right solution
+  - Added simple formatting to xmap file output so that each node has a new line for readability
+
+13/3/2002
+  TTimo
+  - introduced API List managers
+    we deal with two types of APIManager now, the ones that matching all minors for a given major
+    and the ones that require a fixed list of minors
+  - converted the image loaders to go through a API list manager
+  - fixed various things in synapse (introduced more bugs?)
+  - fixed plugins, realized it was still broken
+
+12/3/2002
+  Hydra & TTimo
+  - EClass_Create in the EClass manager _EClassManagerTable
+  - removed InitFromText from _EClassTable
+
+8/3/2002
+  TTimo
+  - some commented out code cleanups
+  - added eclassfgd/ fgd.so module skeleton
+    loaded up in radiant core as an optional entity format
+    added eclass manager code to deal with the new format if present
+    this still loads .def, the actual .fgd code needs to be written now
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=433
+    added a g_strDTDPath global
+    disabled DTD validation, broken on win32
+  - Str copy constructor (const Str &) working correctly with a __strDup
+
+7/3/2002
+  TTimo
+  - added verbosity in file accesses for CXMLPropertyBag
+  - more fixes to project lookup
+  - dropping dtds/ prefix, this is installation dependent
+  - removed ipluginentities.h, the plugin entities stuff was disabled long time ago already
+  - cleaned up some old commented out stuff
+  - proof of concept synapse builtin module: new class CSynapseClientBuiltin allows to have
+    modules builtin to the application (i.e. statically linked)
+    adding
+      include/ieclass.h (eclass loader API)
+      radiant/eclass_def.cpp (.def class loader, builtin)
+      radiant/eclass_def.h (.def loade, API public to the core)
+
+    NOTE: radiant/eclass_def.cpp needs to be added to the win32 projects  
+  - quickfix to project file loading ("/scripts/")  
+  - introduced an EClass manager, hooked up the .def builtin module through it
+    (not yet possible to push new entity format modules, but .def reading is already fully synapsed)
+
+6/3/2002
+  Gef
+  - Fixed a segfault when getting mUserPathPrefix in CGameDescription::CGameDescription()
+  - added preferences check for fixing target/name collisions
+  - fixed a logical error on my part, where setting g_qeglobals.m_strHomeGame in
+    CGameDescription constructor results in a value from the last file parsed. Moved it
+    to a more appropriate location, where it gets a value from the selected .game file.
+  SPoG
+  - changed g_strGameToolsPath to g_strAppPath in GetQERPath API
+  - fixed mapq3.dtd
+  - enabled DTD validation of xmap files
+  - added mapq3.dtd to setup scripts (not tested)
+  TTimo
+  - added OnActivated() to synapse clients, override to put some init code
+  - fixing default project path lookup and user project increment (again)
+  - fix to linux setup, no trailing slash in basegame items
+    (wolf.game and q3.game)
+  - removed old plugin/modules code, leaving only the synapse implementation
+    recoded image loading and Map_Import/Map_Export  
+    still some temporary solutions and cleanup work to be done
+    removed plugin.cpp from the tree / build system
+
+5/3/2002
+  SPoG
+  - TODO: add default project for wolf to WolfPack CVS module
+  - changed xml project file load to search for DTD "dtds/project.dtd" under radiant path
+  - fixed crash in mapq3 on trying to read uninitialised token ptr
+  - changed .map to be default map format for now
+  - changed runbsp to not hardcode -fs_basepath
+  - added -fs_basepath to quake3 default project
+  - added project.dtd to setup scripts and swapped quakev2.qe4 for default_project.proj (not tested)
+
+4/3/2002
+  TTimo
+  - merged synapse2 branch back into trunk, checked Linux and win32 builds ok
+  - updated the .dsp to work with new libxml2 2.4.16
+  - fixed broken enginepath guessing, and broken project path rotation / saving
+
+28/2/2002
+  Gef
+  - Added extra checks for target/targetname collisions
+  - Find Brush dialog title correction (bugzilla #393)
+
+26/2/2002
+  Gef
+  - Added Entity_Connect() to entity.cpp to avoid duplicating code
+  - Fixed target/targetname collisions - entities being cross-linked when copied
+    Bugzilla #385 : http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=385
+
+16/2/2002
+  Gef
+  - cleaned up the kyro gl_point workaround stuff
+  - taught ClipPoint's (clips & path points) how to draw themselves
+
+8/2/2002
+  Gef
+  - Added mapxml.so to linux setup
+  - strip debug symbols option in setup
+  - removed g_qeglobals.m_strHomeMaps, writing it to project instead
+    fixes a bunch of re-broken path issues. Also uses fs_game now.
+  - Minor grid colour in QER Black & Green theme
+  - Save window's pos/size for all view types in MainFrame::OnDestroy
+
+---------------------------  on branch synapse2
+4/3/2002
+  - modules don't show up in plugins menu, added a dump in console before entering interactive mode
+  - added compile time def for synapse verbosity
+
+3/3/2002
+  - finished converting all the modules to synapse, disabled old ResolveInterface call
+
+24/2/2002
+  - hooked TexTool into Radiant plugin menu through synapse
+  - added iplugin.h which I had forgotten earlier
+  - ported synapse code to compile and run on win32
+
+19/2/2002
+  - SYN_REQUIRE_ANY / multiple API manager code
+    can load multiple interfaces based on a matching pattern
+    converted TexTool to load that way
+
+18/2/2002
+  - added iplugin.h with basic interface for plugins  
+
+13/2/2002
+  - synapse on modules currently disabled,
+    the basics of the code are working fine, need to look at multiple interfaces matches before going further
+  - started converting shaders, requires conversion of a lot more others
+  - image converted to synapse
+  - no longer using GUID in synapse, all done through *_MAJOR strings
+  HOWTO: convert a module to synapse:
+    configure it to link against synapse static lib
+    (+include path to STLPort required)
+    add #include "synapse.h" to the plugin header
+    declare the : public CSynapseClient in plugin header
+    implement it (listing provides and requires, implement the request code)
+
+12/2/2002
+  - vfspk3 converted to synapse
+
+11/2/2002
+  TODO: get rid of all WINAPI crap
+  - debugged the API dependencies solver to actually work  
+  - added newer cons at the head of the tree
+
+10/2/2002
+  TTimo
+  - added the basic code for solving API dependencies and requesting the various tables
+  - more diagnostic printing code fixes
+  - version checkings
+  - some more design work (libs/synapse/doc)
+
+9/2/2002
+  TTimo
+  - some changes to the files layout, cleanup of the diagnostics printing
+  (stuff's mostly broken right now)
+  - reworked the complete Sys_Printf stuff to rely on va_list implementation
+  - include/isynapse.h declared useless and foxed without mercy
+  - added include/irefcount.h
+
+8/2/2002
+  TTimo
+  - adding an experimental Anjuta project file to play around with
+
+7/2/2002
+  TTimo
+  - various fixes to build on linux, listed a bunch of current issues
+  - fixing terrademo.map to remove broken mapobj~1 -> mapobjects
+  -- synapse2 branch --
+  - propagate the code from old synapse branch to a new branch out of 1.3 tree
+    (builds and runs on linux, that's about it for now)
+
+--------------------------- end branch synapse2
+  
+7/2/2002
+  djbob
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=354
+  moved all the preferences code to XML
+
+6/2/2002
+  SPoG
+  - checked all paths conform to: unix dir separators + trailing separator
+  - changed file dialogs for load/save of maps to default to "mapspath"
+  - removed OpenDialog and SaveAsDialog, use file_dialog instead
+  - removed FileSystem paths stored in QEGlobals_t.. replaced by CGameDescription
+  - removed dependence on EnginePath from preferences, replaced by CGameDescription
+  - removed hardcoded g_get_home_dir calls for file dialogs
+  - added validation of project settings entry paths before they are set
+
+5/2/2002
+  EvilTypeGuy
+  - moved filters.cpp related function declarations to filters.h
+    and added #include "filters.h" to brush.cpp, csg.cpp, main.cpp,
+    mainframe.cpp, map.cpp, select.cpp as not all files include
+    qe3.h and qe3.h is a rather monolithic header this seems to be
+    a cleaner solution per SPoG's suggestion...Fixes compilation.
+
+  Gef
+  - contrib/plugins BOOL cleanup (uses qboolean now) fixes X header conflict
+  - cons update for mapxml
+  - SaveAsDialog() changed to match path's used in OpenDialog()
+  - removed radiant/xy.h - moved contents to qe3.h (FilterBrush declaration)
+
+4/2/2002
+  SPoG
+  - changed QE_LoadProject and QE_SaveProject to load/save xml project file format
+  - changed request dialog for project files to loop until a valid file is found
+  - fixed memleaks in CGameDescription constructor for xmlGetProp
+  - added converting gametoolspath unix format when parsed from game file
+
+  - fixed m4x4 lib to use column-major order (more compatible with opengl)
+  - added divergence parameter to ray-point intersection test
+    (now easier to select distant points in perspective views)
+  - cleaned up modelview/projection matrix manipulations in 2d/3d view
+  - cleaned up map modules / interface source files a bit
+
+  - added ability to specify map module version when importing/exporting map
+  - cleaned up file dialog code, returned filename is static and in unix format
+  - save-as dialogs force a file extension depending on filetype selected
+  - added filetype manager to support registering custom file types
+  - fixed loading and cleaning engine path from radiant.ini correctly
+
+3/2/2002
+  EvilTypeGuy
+  - fixed win32 compilation (userpathprefix is Linux specific)
+
+  ETG & Powzer
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=308
+    added preference to allow 'paint drag-select' brushes/faces in 3d camera view
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=389
+    added preference to strafe camera foward/back in 3d view while freelook is active
+
+  ETG & RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=388
+    patch adds ability to strafe up/down/left right while freelook is active
+
+1/2/2002
+  TTimo
+  - bumped to 1.3.1-nightly
+
+-- 1.2 stable branch branched here
+
+  Gef & TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=372
+    http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=376
+    appplied the patch, corrected the mapspath expansion stuff
+  TTimo  
+  - linux nightly setup code
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=384
+    hacked a corrective action in the nightly setup
+
+  SPoG
+  - fixed creating region brushes that fill the entire grid for Save Region
+
+31/1/2002
+
+  Micheal Schlueter
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=375
+  syntax fix to q3map path_init.c
+  
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
+  patch 185 == 186
+  tweaking to config stuff in linux setup
+  patch 187
+  Ensures the games directory exists before trying to create a file there
+  patch 177
+  Adds *.cf files & uses them. I think I have all the files in the right places now... maybe
+  (some additional fixes on top by me)
+  
+  ETG
+  quick fix to shader prefs load
+
+29/1/2002
+
+  EvilTypeGuy
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=345
+  more detachable menus fixes
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=334
+  fixes 'load shaders at startup' preference
+
+  SPoG
+  - fixed misc_model "modelscale" and "modelscale_vec" support
+  
+  TTimo
+  - upgraded setup scripts to support nightly build
+  - last minute fix to the modelscale and modelscale_vec code (md3 module)
+
+  ydnar
+  q3map 1.2.4-y2
+
+    New features:
+    - -nopatchfix argument. This disables lightmap patch fixes and makes a map suitable for lighting with -vlight.
+    - Degenerate patches are treated like broken brushes. They are ignored, warned about, and selected in Radiant if you ran with the -connect option (or from the BSP menu). This was what was causing the "0 valued axis" error some people were experiencing.
+
+    New entity keys:
+    - "_lightmapscale" key for brush entities (worldspawn, func_*). This lets a mapper scale the lightmap samplesize per-entity. For large constructions, 2.0 or 3.0 is a fine value, and keeps BSP size down and compile times low. For those areas you want to have high-detail shadows, make a func_group and use a value of 0.25 or so. It will scale the samplesize value for the surface's shader (default 16) or the -samplesize argument.
+    - "modelscale" and "modelscale_vec" keys for misc_models (1.0 = default). This was for proper RTCW support and is available for Quake 3 maps as well. Lets you scale up map models in the world, getting around the MD3 size limitation. The next build of GtkRadiant has SPoG's code to support this in-editor so you can see what effect a scale has.
+    - Flare surfaces are now supressed from the BSP. They serve no purpose other than add to the vert & surfacecount in a BSP. These surfaces were created silently when a shader has "light 1" or "q3map_flareshader X." Use the new -flares switch when BSPing your map to have them emitted.
+
+    Changes:
+    - GtkRadiant 1.2.4-nightly version increment.
+    - Full WolfSDK style lighting enabled with -game wolf, including lightJuniors. This includes linear lights by default (no angle attenuation) and support for the additional RTCW "fade" and "angle" keys, and spawnflag changes, including q3map_nondynamic on light entities. This may require maps being constructed for RTCW with the current toolset to change their light entities. Sorry. :) Note, Wolf-style lighting only works with -light, and not -vlight.
+    - Vertex light stitching now uses a near-ambient light check for dark vertexes as opposed to lower-than-average fixups. This preserves some shadow detail better while getting the buried verts lit properly. Comments encouraged.
+    - Surfaces' samplesize are now stored in the BSP. This change makes BSPs generated from this version incompatible with all other q3maps. The upside is that -samplesize N is no longer necessary on the -light or -vlight stage. This feature is necessary to support the "_lightmapscale" key.
+    - Additional PVS optimizations in lighting.
+
+    Fixes:
+    - Will compile for RTCW properly (1.2.1-y12 didn't).
+    - No more sparklies where fog meets brush faces. They're split properly now.
+    - Crash bug in vlight fixed.
+    - Vertex light fixups/stitching is considerably faster.
+    - Vertex light fixups ONLY stitch faces with lightmaps. For pointlight surfaces you're on your own.
+    - Better snapping logic when merging nearly-coincident vertexes on complex brush windings.
+    - Bug where the .prt file had some bogus or nearly-borked portals. They're cleaned up like everything else now.
+    - A few stupid bugs in path initialization. Should work better. Also includes TTimo's fixes to my code so it would work properly on Linux.
+    - RR2DO2's PCX loading patch for alphamaps. This bug was manifesting itself in the form of offset or incorrect samples being used on terrain entities.
+    - A ton of other minor little fixes here and there.
+
+28/1/2002
+
+  TTimo
+  - win32 fixes
+  - 1.2.4-nightly
+
+  djbob
+  - EClass_ForName fix if malformed name
+
+---- 1.2.3 linux released
+
+  TTimo
+  - fixed BSP version depending on game mode in q3map
+    (home dir guessing is still fucked, have to fix before release)
+  - fixed q3map init_path.c home path bug on init
+
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=369
+    more fixes to texture paths in gensurf
+
+27/1/2002
+  TTimo
+  - switching to v3 project file, forcing reload of template if non-v3
+  need to distribute quakev3.qe4 in setups now (done for linux setup, will have to in win32)
+  - renamed Main to main in q3map init paths
+  - fixes the ~/. inits and init order in q3map
+  - added m_pfnPathForPluginName to the main function table, returns the directory a plugin is running from
+    used in bobtoolz / curry / pk3man to find various files
+    see also todo: http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=368
+  - some fixes to textures loading paths in curry
+  - linux setup copying correct content for curry (pk3 in wolf media) and bobtoolz (bt/ in plugins/)
+  - building 1.2.2 setups  
+  
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=362
+  gensurf fix
+  
+  djbob
+  - bobtoolz update
+  
+  Hydra
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=361
+  fixes a bug with the texture menu loading, now we see the non-shaderlist directories too
+
+26/1/2002
+  Gef - Michael Schlueter - TTimo 
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
+  applied several patches (to setup code and to the setup scripts)
+  modified makesdk.pl to update with more content
+  added an "enginepath" attribute to the game file, reworked the handling in editor
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=347
+    took out the refresh command from the plugin menu
+  - more linux fixes:
+    bringing all the plugins to compile again on linux
+    polishing the setup code (all the right files in the right places)
+  - for linux release, bumping ver to 1.2.2
+    win32 will have a 1.2.3-nightly after that
+  - added correct init of ~/.q3a or ~/.wolf
+    *nix systems have a 'prefix' attribute in the .game file to specify
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=359
+    identified the mod compiling problems
+    applying back the old fs_basepath fs_game code to the BSP generation
+    
+  ydnar- TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=351
+    cleaner path init code
+    it doesn't init for ~/.q3a and ~/.wolf paths yet
+
+25/1/2002
+  SPoG
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=352
+  using the wrong matrix stack for XY_Draw caused stack overflow error
+  - texture_mode was set to an invalid enum in wireframe/flatshade mode
+  - changed plugin API to expect gamedir-relative texturenames
+  - fixed gensurf to create faces/patches with gamedir-relative textures
+
+24/1/2002
+  SPoG
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=322
+  added modelscale key check to misc_model entity in md3/entity module
+  added angle key check to eclassmodel class in md3/entity module
+  fixed bugs in BP writing and reading in map module
+  TTimo (commited as SPoG)
+  - fixing permissions on cvsreport and doxygen stuff, upgraded dot
+
+23/1/2002
+  SPoG
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=336
+  plugin API bugfix - fixes textures on stuff created by plugins
+
+---- 1.2.1 was released here
+
+22/1/2002
+  Gef
+  - linux build fixes
+  SCDS_reyalP
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=325
+  wrong file packaged in setup
+  RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=327
+  fix to PCX loading  
+  SPoG
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=298
+  cut & paste bugfix
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=332
+  update origin key on entities
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=333
+  made fixedsize entities not scalable
+
+21/1/2002
+  TTimo
+  - scanning in g_strAppPath/modules/ and plugins/ prior to g_strGameToolsPath
+  using the main path to put general plugins and modules
+  - fixed bobtoolz bug, init of epairs table was relying on wrong params
+  - fixed curry to compile again on 1.2
+  - fixed pk3man to compile again on 1.2
+  - updated IS setup:
+    installing the plugins with the core
+    installing the common modules in the core
+  - Compiling manual, more IS stuff, .xlink etc.
+
+  RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=315
+    patches for improved multimonitor support (with some associated pref items)
+
+  ydnar
+  - more q3map: http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=324
+    - radiosity fixes (proper handling of ambient light)
+    - polygonoffset fixes
+    - lightmaps on patches work better (normal calcs adjusted, planar patches are 
+      box projected like brush sides)
+    - double vfs init in bsp stage removed (this needs to be tested on Linux)
+    - lighting is faster again
+    - a couple crash bugs resolved
+    - other tasty nibbles
+
+20/1/2002
+  EvilTypeGuy
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=313
+  detachable menus set as preference (in layout)
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=255
+  path prompt
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=307
+  patch dialog names
+  ETG & RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=306
+  fix 'Natural' texturing crash
+  ETG & TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=291
+  found out the problem, Wolf SP spawn works now
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=144
+  fixed more problems with model loading vfsExtractRelativePath
+  prolly broke the linux build, just a matter of putting a bunch of #idfdef
+  - fixed an additionnal .pid lock situation, cleaning the global prefs on game .pid lock
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=301
+  fixed md3 tris test selection bug
+  djbob
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=219
+  fixed bobtoolz for 1.2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=318
+  filter structural
+  RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=305
+  filter in viewmenu for lightgrid brushes (ydnar's q3map)
+  fixes image lib loading bugs
+  Hydra
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=298
+  copy/clone deselects the copied stuff
+  added a pref to deselect or not, and to nudge pasted stuff or not
+
+19/1/2002
+  djbob
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=311
+  IEpair wrapper to access project entity from plugins
+  RR2DO2
+  - missing IncRef in CShaderArray::AddSingle
+  TTimo
+  - game.xlink files in gametools path, is scanned to build items in the Help menu
+  (and the associated code)
+
+18/1/2002
+  Gef / Michael Schlueter / TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
+  patches 133 and 138 applied, new setup code
+
+14/1/2002
+  TTimo
+  - adding djbob write access for bobtoolz
+
+13/1/2002
+  ydnar
+  - q3map code updates 1.2.1-y8
+    new lightgrid surface flag feature
+       lightgrid shader and editor image for Wolf and Q3/TA: in the common .pk3 and in all common.shader
+       cvs remove setup/data/baseq3/common-q3r.pk3 (unused, we use common-spog.pk3)
+  TTimo
+  - updating setup to use mapq3 module instead of map (both Wolf and Q3 game packs)
+    (also checked the lightgrid option)
+  - fixed setup.pl bug for template gen from WorkDir/
+  - correct spawning between SP and MP mapping mode
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=297
+    .pid check, console logging and prefs cleanup
+  Wolfen
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=294
+    checked in updates to the manual links page and setup instructions
+    (i.e. new prefs dialog)
+
+12/1/2002
+  Gef & Michael Schlueter
+  - bugs #295 and #279, new patches applied
+  EvilTypeGuy & djbob
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=220
+    patch selection crash
+  EvilTypeGuy
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=260
+    Dense and Very Dense Cylinders have wrong number of rows    
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=292
+    latching patch toolbar settings
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=144
+    win32 long/short pathname bugs reappearing, switching back to short paths for project settings
+  - removed obsolete radiant/vfs.cpp radiant/vfs.h
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=291
+    using new .qe4 for Wolf, fixed stuff editor side (long path names and engine spawn)
+  SCDS_reyalP
+  - http://zerowing.idsoftware.com/bugzilla/showattachment.cgi?attach_id=118
+    realloc bug in terrain
+
+11/1/2002
+  SPoG
+  - unpatched bug #239, unintended duplication of brushes, patch #96
+       Note: bug #239 now unresolved
+  EvilTypeGuy
+  - bug #295 fixes for compile under Linux
+
+10/1/2002
+  SPoG
+  - fixed CEntityEclassModel referencing eclass after eclass has been deleted
+  SPoG - map-module branch
+  - new map module, provides current functionality, using new map interface
+  - cleaned up merging/creating of entity array used by map module
+  - implemented MemStream::printf(const char,...) - can't print strings larger than 1024 currently
+  - changed copy/paste to use the map module, via abstraction of FileStream/MemStream as DataStream
+  - fixed Save Region and Save Selected
+  - new xml map module "mapxml"
+  - cleaned up map.cpp
+
+6/1/2002
+  TTimo
+  - removed m_bPak from pref dialogs (it was dead code)
+
+5/1/2002
+  RR2DO2
+  - q3map terrain blending fix for >5 layers
+  EvilTypeGuy
+  - fs_homepath patch on linux
+  Gef
+  - bug #279, linux setup, patch #102
+  - bug #239, unintended duplication of brushes, patch #96
+  TTimo
+  - added Wolf specific project settings dialog:
+    correct fs_game selection and combo names
+    added multiplayer / single player mapping mode selection
+
+4/1/2002
+  TTimo
+  - adding -game wolf switch to q3map (-game quake3 works too, but it's the default anyway)
+    using different bsp version and different fs_basegame on wolf
+  - updated the setup/win32/setup.pl script to generate from a config file instead of hardcoded
+    (added corresponding q3.cf wolf.cf and all.cf config files)
+  - added a default Start Menu shortcut name (RR2DO2 special)
+  - diffing against Id's internal SOS source and merging in new stuff:
+    - bumped MAX_SURFACE_INFO to 4096 in shaders.c
+       - new terrain code (Jim Dose)
+         ParseTerrain() addition in terrain.c
+         Creates a mapDrawSurface_t from the terrain text
+       - VL_SurfaceRadiosity and VL_SurfaceRadiosity
+         MrElusive's vlight radiosity code
+       - speedups to vis.c and visflow.c (MrElusive)
+
+3/1/2002
+  TTimo
+  - merge gameselect branch back into trunk
+  the IS setup scripts have been updated for the new paths layout
+  developement environment needs to be updated to copy binaries to the right places for debug
+  it is recommended to run a 1.2.1 setup on win32 prior to compile and install debug bins
+  - updated the setup to be more templated for inclusion/non inclusion of game packs on demand
+
+  - propagating recent fixes to Alpha into the trunk
+  based on diffing between Merge-1_1_1 and Merge-1_1_2:
+  =====================================================================
+  13/11/2001
+    djbob
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=244
+    reverted again the shader manual and tcMod docs
+
+    TTimo
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=214
+    patched aselib.c, was calling strstr badly (relative path extraction)
+
+  12/11/2001
+    djbob
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=241
+    applied patch, will release in next nightly
+
+    Spog
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=254
+    patch for safe_malloc
+
+    TTimo
+    - fixing STLPort config checks and XML config (CHAR -> xmlChar)
+    - added safe_malloc_info and safe_malloc in the common/ dir
+    - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=179
+    added XML stream version checking between Radiant and q3map
+  ========================================================================  
+  also, manual merge of docs/manual and setup media
+  this merge work is related to bug #280 too:
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=280
+  
+  ydnar
+  - new q3map, radiosity and bug fixes, code merged in with the trunk version
+  (TODO: add more detailed changes log)
+
+  EvilTypeGuy
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=274
+  broken auto caulking fix
+
+  EvilTypeGyu & LordHavoc
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=207
+  (two new files, project settings updated)
+  
+2/1/2002
+  TTimo - branch gameselect
+  - copying over the linux setup binaries (setup, uninstall, setup.gtk)
+  from Alpha branch. Those have the ability to prompt destination path
+  per component.
+  Gef - branch gameselect
+  - patch 101 for bug 279
+  .game files generation by the setup, makesdk.sh and postinstall.sh fixups
+
+1/1/2002
+  Gef - branch gameselect
+  - linux source fix http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=279
+  (we use PATH_MAX as the cross platform define instead of MAX_PATH which only works on win32)
+  
+  TTimo - branch gameselect
+  - cleanup and homogeneisation of the paths for prefs storage
+    m_global_rc_path:
+      win32: g_strAppPath
+      linux: ~/.radiant/<version>/
+    m_rc_path:
+      win32: g_strGameToolsPath
+      linux: ~/.radiant/<version>/<gamename>
+    so that global.pref goes in ~/.radiant/<version>/global.pref
+    and radiant.ini ~/.radiant/<version>/<gamename>/radiant.ini  
+
+27/12/2001
+  TTimo - branch gameselect
+  - global prefs file (global.pref), XML based in core directory
+    stores game selection setting
+       stores autoload setting
+  - dropping 'gameid' from .game file, gonna use a 'gamefile' in global prefs instead
+    (and the .game file name .. thks Gef)
+  - TODO: radiant.log stuff in global prefs?
+
+21/12/2001
+  TTimo - branch gameselect
+  - more Wolf setup tweaking for an experimental build release:
+    quakev2.qe4 project template file
+       using a 'gameid' attribute in the game file to select hardcoded features in the editor binary
+       'basegame' node for lookup of the default project file
+       'engine' node for engine path
+  - added experimental Wolf game pack to IS
+  - added setup/win32/HOWTO with extensive information about the procedure to
+    add new game packs
+  - reading the 'name' attribute in the game node for game selection dialog
+  - TODO: pid files to make safe startup?
+  The .pid stuff should be happening after game selection, since it covers game-specific 
+  preference settings. 
+  - TODO: console logging pref should be a global pref, goes with game autoload?
+
+17/12/2001
+  TTimo - branch gameselect
+  - updating the setup script for experimental 1.2.0 setup:
+  
+  merged some of the docs back into trunk (Radiant manual, some TA docs)
+  will need to perform a complete diffing between Alpha and trunk about docs/manual at some point
+  merged bitmaps from Alpha too
+  
+  added the Q3 modules (image, map, md3model, shaders, vfspk3) to Q3 game pack in setup
+  
+  generating per-game config file q3.game in OnMoved (IS setup)
+  will need equivalent with linux setup of course
+  
+  various other generic fixes to the setup code
+  
+  - multiple games support, list of changes, and TODO:
+  NOTE: this is on a 'gameselect' branch for now
+  Doxygen documentation should be at http://zerowing.idsoftware.com/doxygen
+    for this branch too.
+
+  The installation procedure has changed. The win32 installer is partly ready, linux installer
+  will need to be modified too. The editor binary and the Gtk DLLs are installed in a common
+  location, i.e. 'C:\Program Files\GtkRadiant' typically. The game specific binaries and modules
+  go in the same location as usual, for instance 'C:\Program Files\Quake III Arena\GtkRadiant\'
+  (and also 'C:\Program Files\Quake III Arena\GtkRadiant\modules' 'C:\<..>\plugins')
+
+  The environment variables used by the build system (VC6 project files) have been adapted:
+  $(QUAKE3RADIANTDIR) is still used
+  $(CORERADIANTDIR) is used for the main editor location
+
+  When editor starts, it looks for games/*.game under g_strAppPath and prompts the user for a game
+  Once game is selected, parameters are used for regular startup.
+  You need to write your own q3.game for now, it will be generated by the setup procedure
+  my C:\Program Files\GtkRadiant\games\q3.game looks like that:
+  <?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
+  <!-- Q3 game definition file -->
+  <!-- those are generated -->
+  <game 
+    name="Quake III Arena / Quake III: Team Arena and modifications"
+       gametools="c:/quake3/Radiant/"
+  />
+
+  given that, the editor does a complete startup, and the basics are here for multiple games
+
+  - precise changes:
+
+  g_strToolsPath renamed to g_strGameToolsPath
+  most of former g_strAppPath uses g_strGameToolsPath
+  the name change was also meant for homogeneity with DIR_GAMETOOLS_* variables we use in the setups
+  g_strAppPath still used, points to the main installation path
+
+  added the game selection code in CPrefsDlg::Init
+  using several classes and a dialog box, parsing XML files
+
+  - TODO:
+  
+  the console 'Radiant.log' doesn't catch the game selection stuff as it is now
+  initialize it to the main install, without the game setting
+  (console logging is a debugging tool anyway, no reason it should go to the proper game folder
+  each time)
+
+  the 'preferences reset/cleanup' code is probably broken, specially when used with the .pid checking
+  since we check for .pid even before we know where the GameTools path is
+
+  on linux, we need to sanitize the ~/.q3a dir usage. Switch to ~/.radiant, use the version tag
+  to maintain things independant, and use the game name to isolate per-game settings?
+  ~/.radiant/1.2.0-nightly/quake3/radiant.ini (.pid, .log)
+  ~/.radiant/1.2.0-nightly/wolf/..
+
+  also, when looking for those files (.ini mostly), win32 stores them in a main installation, and
+  linux has them in ~/.radiant/.. (which is the read/write area). This should be homogenized?
+  Maybe by adding a 'Main' to the readonly path and a new variable with 'RW', pointing to 'Main' on
+  win32 and to ~/.radiant on linux
+
+11/12/2001
+  TTimo
+  - replaced setup/win32/setup.sh by setup/win32/setup.pl
+  same functionality level + abiliy to generate back a template from a work version
+  - major rework on the IS scripts, basics of multiple games support installer
+  clean seperation between editor core and game pack
+  design doc and analysis of custom setup generation, setup script UI requierements
+  see setup/win32/TODO for more details
+
+10/12/2001
+  TTimo
+  - new generation of InstallShield setup
+  using a template/ directory instead of a .zip file
+  requires rewrite of the processing script
+  allows easier maintenance of the IS script
+
+23/11/2001
+  TTimo
+  - yet another update to cvsreport script, 
+  catch the branch and forward the info to user commands too
+  able to build doxygen for several branches selectively now:
+  http://zerowing.idsoftware.com/doxygen 
+
+22/11/2001
+  TTimo
+  - new cvsreport script, should send explicit diff of the CHANGES file now
+
+03/12/2001
+  TTimo - md3-module branch
+  - validated the fixes and the build on linux, ready to merge in trunk
+  SPoG - md3-module branch
+  - changed function naming conventions in mathlib for m4x4, ray, bbox, to be consistent
+  - fixed bug in m4x4_invert
+
+29/11/2001
+  TTimo - md3-module branch
+  - flagged all new mathlib functions that need a name change or an argument order change
+  also added various \todo to point out inconsistencies
+
+28/11/2001
+  TTimo - md3-module branch
+  - updated linux build
+  - fixed CEntityMiscModel and CEntityEclassModel destructors
+    (any destructor should be virtual)
+
+27/11/2001
+  Spog - md3-module branch
+  - stopped texturewindow showing shaders without the "textures/" path
+  - made md3 module functionally identical to current radiant md3 code
+
+22/11/2001
+  TTimo - md3-module branch
+  - fixes to the core for linux build
+  - model.so module builds on linux
+  - added plugins/md3model/doc/md3-design.txt
+  - several doxy-friendly \todo chunks about the module model
+
+  Spog - md3-module branch
+  - fixed aabb_add_aabb() algorithm wasn't very reliable
+  - added VectorMid, VectorNegative and CrossProduct macros to mathlib
+  - added bbox_intersect_plane()
+
+21/11/2001
+  Spog & TTimo - md3-module branch
+  - initial code from Spog following a preparatory design work
+  merging in as new 'md3-module' branch
+  geomlib code merged into mathlib
+  some reorganisation of the source layout and cleanup (more stuff in imodel.h, less in qertypes.h)
+
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=261
+  fix applied
+
+20/23/11/2001
+  TTimo
+  - yet another update to cvsreport script, 
+  catch the branch and forward the info to user commands too
+  able to build doxygen for several branches selectively now:
+  http://zerowing.idsoftware.com/doxygen 
+
+22/11/2001
+  TTimo
+  - new cvsreport script, should send explicit diff of the CHANGES file now
+
+11/2001
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=253
+  additional fixes
+  TTimo
+  - renamed tools/quake3/common/threads.h to qthreads.h
+  avoids a collision with system headers
+
+19/11/2001
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=251
+  Fixed "Move into worldspawn" deleting entities with only one brush
+  Fixed Brush_Move using texture lock on fixedsize entity brushes
+  Fixed Textures > Texture Lock > Rotations toggle checkbox
+
+16/11/2001
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=247
+  applied patch 77, using a notebook layout for preferences dialog
+  also patched in some preferences saving that had been forgotten
+  (such as invert mouse in freelook)
+  
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=253
+  patch 84 + additional modifs, bug still open
+
+15/11/2001
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=252
+  rewritten rendering pipeline for cam window - fixes some hacks, improves speed, 
+  makes rendering modes more consistent with each other
+
+07/11/2001
+  TTimo
+  - more IMAP interface, adding a blind data void *pData to entity_t
+    more info about it and why it's done is in map.cpp, should be a small base for next additions to the editor
+
+31/10/2001
+  TTimo
+  - using IDataStream in map module, moved back some of the module code into the trunk
+
+30/10/2001
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=245
+    applied patch 76
+    
+  TTimo
+  - renaming istream.h to idatastream.h, this had nasty conflicts with OS includes
+  already had to IStream -> IDataStream some time ago anyway
+
+27/10/2001
+  TTimo
+  - updated cvsreport, testing new ver
+  - added a static version of texdef (no memory alloc on the texture name)
+    unused for now, was just experimental
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=245
+    applied patch 75
+
+26/01/2001
+  TTimo
+  - various updates:
+  new GtkSDK precompiled binaries
+  updated libxml2 package (to 2.4.3)
+  updated STLPort (to 4.5)
+    now compiling with STLPort and threading (since we are using threading throughout the app)
+  - exposing the data stream API to the modules, renamed some stuff on the way
+    need to update the map module to use it now
+  - cleanup on qtexture_t definition
+    guarding and disabling chunks of the surface plugin code behind DO_SURFACEPLUGIN
+       (see earlier patch on plugin entities)
+
+25/01/2001
+  Hydra
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=202
+  applied patch commenting out plugin entities code
+  might come back in 1.2 under another implementation
+  the code is still there, only commented out for now
+
+17/01/2001
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=93
+  checking in doxygen content, setting up generation on zerowing
+  auto generation on zerowing upon a commit:
+  http://zerowing.idsoftware.com/doxygen
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=231
+  checked in the patch
+  - switching to a new cvs commit script
+
+14/10/2001
+  TTimo
+  - libs/mathlib library
+    unifies mathlib code squattered all over the tree
+    mainly a merge of tools math code and radiant/mathlib.cpp
+    C implementation, using an extern "C" construct for use from C++
+    need to check on linux, win32 builds ok
+    extracted qboolean code into libs/bytebool.h on the way
+
+11/10/2001
+  TTimo
+  merged TmpMerge-1_1_1 branch back in the trunk, the update process from Alpha 1.1.1 is done
+
+  TTimo - branch TmpMerge-1_1_1
+  looking through all remaining .rej files and applying the failed patches accordingly
+  bobtoolz is broken, but it's not due to the merge
+    the plugin API is different and some things need updated
+    (disabled bobtoolz build in contrib/Construct for now)
+  same for gensurf
+  same for prtview
+  same for textool
+  setup: replaced the existing stuff with 1.1.1 code
+  fixed various things for win32 build, checked correct CRT lib config
+
+10/10/2001
+  TTimo - branch TmpMerge-1_1_1
+  building modules, going through all the .rej
+  merging radiant/missing.h and modules/shaders/missing.h into a single one, moving to libs/
+  exposing BuildShaderList PreloadShaders in _QERAppShadersTable
+  have to review all the remaining .rej to finalize the merge now
+
+04/10/2001
+  TTimo - branch TmpMerge-1_1_1
+  using this branch as temporary location for merge process
+  copied over new binary files. mostly .dsp (prolly broken)
+  and setup/linux/setup.data stuff
+
+25/08/2001
+  TTimo
+  map module successfully loaded and saved q3dm1, the saved file was then loaded back into 1.1-TA without problems
+  rebuilt and checked on win32
+  merged IMap back in trunk, fixed some memory conflicts on win32
+  Took me a lot more time than I would have liked to, but there's a script tied to the CVS server now, which will post on this list a diff of the docs/developer/CHANGES file whenever it gets updated. This will probably be very handy for me since I'll only have to put update information in the CHANGES file instead of having to post on the list too.
+  The script is likely to be a bit laggy, or miss some features (for instance I'd like to extract the branch name .. anyone know how I can get the branch name (Alpha/IMap/HEAD) from the version number?
+  PS: I can email this script to anyone who would like to have a look
+
+22/08/2001
+  TTimo
+  did more work on map module, one big chunk of work left: the core should broadcast interface requests to plugins
+    when it doesn't know how to do it by itself..
+  Gef
+  new doxygen patch, generates output from core (libs/ include/ and radiant/)
+
+21/08/2001
+  TTimo
+  removed Makefile, use cons damnit!
+
+18/08/2001
+  Gef
+  automated documentation via doxygen, new scripts and content
+
+18/08/2001
+  EvilTypeGuy
+  patch for CHAR to xmlChar conversion (xml2 consistency)
+
+09/08/2001
+  TTimo
+  the map module starts to look like something, cleaned up the interface stuff
+  started moving the actual code out in the module and removing it from the core
+  lots of issues raised on the way, some structures to export, and the macro scheme to access API functions more easily
+  it compiles right now, but won't run because it's missing a lot of things .. the process simply happens to be "under way"
+
+04/08/2001
+  TTimo
+  patched more path code, to look for stuff in "bitmaps/" and "modules/" instead of "tools/bitmaps" and "tools/modules"
+  modified the Construct files accordingly
+  merged in radiant/ishaders.cpp diff into plugins/shaders/shaders.cpp (PreloadShaders)
+  merged in radiant/lbmlib.cpp diff into plugins/images/lbmlib.cpp (Sys_FPrintf)
+  checked the .rej and patched a few remaining things
+  NOTE
+    the diffs are space/tab sensisitive, and we used the "beautify source" a bunch of times, so it's a bit fucked now
+    next time, generate the diffs not space sensitive..
+  TODO
+    map loading is fucked, "textures/" prefix issue?
+
+27/07/2001
+  TTimo
+  merging recent changes from Alpha branch into the Trunk
+  this could not be done with a regular cvs merge because we already did a cvs merge of Alpha into trunk some time ago
+  manually built a diff between the current Alpha (now tagged Merge-1_1-TA_1-nightly)
+  and the Alpha we had right after the former cvs merge: -r Alpha -D 2000-05-28
+  binary files ignored in the diff, only going for source stuff
+  built with diff -Nru Reference/ Current/
+  then patch -p1 < patchfile
+  next, started rebuilding:
+    big manual updates were in vfs.cpp and texwindow.cpp
+  cleaned up some VFS stuff .. it had an absurd QERAppFileSystem / QERPlugFileSystem scheme
+  TODO:
+    the ISSetup has not been copied over from Alpha
+    OK check the Construct files
+    OK radiant/ishaders.cpp no longer exists .. apply the patch on the shader module
+    OK radiant/lbmlib.cpp no longer exists .. in the image code?
+    OK look at the *.rej files
+
+03/10/2001
+  TTimo
+  - adding a pref to select patches by BBox, fixes
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=212
+
+02/10/2001
+  TTimo
+  - reverting Spog patch 67 to bug #209, starting from scratch
+  applied again, with HasModel returning NULL safe checks
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=211
+  fixed overlays drawing (XY and Cam)
+
+01/10/2001
+  TTimo
+  - building and distributing q3data (.ase -> .md3 conversion utility)
+  updated q3data to show main GtkRadiant version information and build date
+  - generating a new GUID per-setup
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=206
+  Gef
+  - updated credits.html and links.htm, look much better
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=200
+  - update Z-checker view on camera up and down
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=199
+  Spog
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=209
+  Fixed QERApp_ReloadShaders.. PreloadShaders needs a BuildShaderList call 
+  Fixed Flush & Reload Shaders for md3 models
+
+25/09/2001
+  Gef / djbob
+  - several patches to the key handling code, for linux specific issues and sticky keys
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=191
+  TTimo
+  - fixing q3map bug, not processing the argv correctly
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=192
+  - fixed ToggleCubicClip shortcut Ctrl+\ (win32 Gtk source patch)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=15
+
+18/09/2001
+  RR2DO2
+  - discreet movement for camera (prefs setting)
+    fixes texture window bug
+    latching view layout changes until restart
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+  djbob
+  - added back "view > show > show angles" in view filters
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=188
+
+15/09/2001
+  G_Dewan
+  - fixed problems with q3map when not using -connect
+  SPoG
+  - fixed q3map texture projection for brushes belonging to entities with local origin
+  - added SafeOpenRead() check, terminating map->bsp stage if .map file cannot be read
+
+13/09/2001
+  RR2DO2
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=181
+  fixing key handling bug (key pressed with repetition was not properly catched)
+  TTimo
+  - added new Radiant manual elements (GtkRad section) to the win32 full setup
+  - reverting version to nightly, going back to nightly / RC delayed
+  - patched linux setup, now prompting for component path only if at least
+    one of the options is checked. Still need to handle Cancel in dialog though.
+
+12/09/2001
+  TTimo
+  - more fixes to linux script, copy plugins right now
+
+10/09/2001
+  TTimo
+  - patched contrib plugins, using seperate build scheme
+  - fixed textool issues, compiles again
+
+09/09/2001
+  TTimo
+  - sub-menu cascading
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=178
+  - udpated the Q3Radiant manual with some new GtkRadiant stuff
+  - updated the FAQ with 1.1.1 known issues
+  Gef
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=174
+  applied all the patches 
+
+07/09/2001
+  SPoG
+  - fixed qer_editorimages outside "textures/" being ignored
+  - stopped q3map_lightimage being used to set shader image dimensions
+  - changed bsp menu to remove "bsp_", changed menu text in default .qe4
+  - fixed patch LOD update - now always occurs on both cam/xy draw
+
+  djbob
+  - dynamic DEpair class strings in bobtoolz
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=171
+  - decrease VESF verbosity
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=169
+
+  TTimo
+  - fixed Gtk keyboard bug Ctrl + [ and ]
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=15
+
+06/09/2001
+  TTimo
+  - merged FullSetup branch into the trunk, we have basic functionality
+  for a full linux setup (components prompting for path)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=158
+
+  Gef
+  - CapDialog source cleanup patch (got rid of the namespace)
+
+  RR2DO2
+  - more camera fixes, wheel mouse and texture drag drop
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+  - additionnal patch to optimize camera refreshes
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+  
+  djbob
+  - remember last key/pair in entity dialog for easy "apply again"  
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=18
+  - re-enabled texture name edit on PI
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=18
+
+04/09/2001
+  djbob
+  - left pane on status bar
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=166
+  
+  RR2DO2
+  - cam window cursor fix
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+  
+  TTimo (FullSetup branch)
+  patched setupdb and setup to allow for path prompt in install
+  modified the setup script scheme to go towards a solution similar to what
+    we do under win32 (build a full and nightly build)
+  the binaries in setup.data/ (setup and setup.gtk) still need to be updated 
+    with proper binaries built from setup and setupdb cvs source
+
+03/09/2001
+  TTimo
+  - wheel mouse in texture window on win32 (with a pref setting for increment)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=160
+  - not saving prefs while exit on sleep
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=157
+  - fixed select all of type (changed behaviour to something that makes more sense?)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=79
+  
+  Gef
+  - final tweaks to wheel mouse scrolling (locks texwin scrolling and scrollbar update)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=160
+  - prevent multiple color selection dialog for light entity
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=165
+  
+  djbob & TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=137
+  window positions
+  applied patch to store SI and PI positions
+  storing entity info and map info positions
+  reworked the overall position load/save scheme
+  added an enum for the view style, makes things more readable
+
+02/09/2001
+  TTimo
+  - added/cleanup ToggleFreeMode to camwindow.cpp .. stopped working on cam stuff since RR2DO2 has another patch in preparation
+  Gef
+  - patched Conscript to accept 'cons -- release' on the command line to performa a release build
+  djbob
+  - added patch splitting to bobtoolz
+  - fix to patch control points bug in camera
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=159
+  - handling of NWUV errors in q3map
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=147
+  RR2DO2
+  - new patch for camera control
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+
+01/09/2001
+  SPoG
+  - Fixed .wal texture support, searches for .wal extension if .tga and .jpg fail
+    NOTE: requires a "pics/colormap.pcx" file to obtain a palette from
+  - Added variable default texture scale in preferences (ini key: TextureDefaultScale)
+
+01/09/2001
+  djbob
+  - fixed surface inspector "fit" bug
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=161
+  - single face deselection on a selected brush
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=153
+
+31/08/2001
+  TTimo
+  - Moved *.def files to scripts/ in win32 setup
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=116
+  - Applied patch for background position on widgets (win32)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=108
+  - Checked C runtime lib configs
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=135
+  - updating docs (add to CVS, update setups etc.)
+    added TA teams manual to the full setup
+    uploaded on web site
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=97
+  - changed versioning to 1.1.1-nightly, next release will be 1.1.1
+  (the -TA part was removed, since we now support ALL mods)
+  - removed AFX_MANAGE_STATE calls, this is old MFC related code for win32
+  - moved texdef_t::name to private, added const char * GetName()
+  (doesn't fix explosion on exit for win32 debug builds though)
+  - fixed DoTextEdit / EditPad b0rkage (due to recent Q_Exec changes)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=134
+  - added targetShaderName documentation to shader manual
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=102
+  - added "notta" and "notq3a" documentation to the TA Mapping manual
+  - fixed entities.def on shootable doors and buttons
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=101
+
+  djbob
+  - added MAX_POINT_ON_WINDING error handling
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=129
+  - bobtoolz update
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=123
+
+  RR2DO2
+  - noclip-type camera movement
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=23
+
+30/08/2001
+  TTimo
+  - Fixed CHANGES commit script bug
+  - Fixed -onlyents bug in q3map / origin brushes
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=92
+  - added mouse wheel to the texture window
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=81
+  SPoG
+  - Fixed texture rotation not updating correctly on patches
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=136
+  - Fixed long delay on toggling cubic clip by removing call to Map_BuildBrushData()
+  - Added note in entities.def for default worldspawn _color value
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=105
+  - Added IncRef and DecRef to Patch_FindReplaceTexture()
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=95
+  - Fixed misc_model updating on changing model key or with invalid model
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=138
+
+30/08/2001
+  SPoG
+  - Added negative vertical scale on SET and FIT in patch/surface inspector
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=65
+
+27/08/2001
+  Gef
+  - running makeversion.sh from Conscript
+  - a bunch of patches to cleanup compile warnings on linux
+  - added VectorSnap on float grid
+  - IWindowListener modified to pass float values for X Y in click messages
+  TTimo
+  - fixed crash when adding a misc_model if Gtk dialog is on
+  djbob
+  - md3 filtering for misc_model dialog
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=76
+
+26/08/2001
+  Gef
+  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=152
+    Kyro II GL drivers bug
+  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=150
+    using a scrolling textbox for GL extensions in the about list
+  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=150
+    func_group toggle in cap dialog
+    
+  TTimo
+  fixed running BSP commands on linux
+  fixed http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=133
+    VFS        init on linux
+    
+around 15/08/2001
+  TTimo
+  quakecon fixes: switched to long filenames in project and misc_model dialogs,
+    removed all occurences of win32 conversion to old 8.3 filenames
+  NOTE: this might raise some bugs and issues, but it's the way to go for the future,
+    already fixes more issues than it creates
+
+03/08/2001
+  djbob
+  fixed Radiant hijacks win32 copy/paste
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=36
+
+--- merged Alpha into Trunk, see Merge-1_1-TA-nightly tag
+
+25/07/2001
+  TTimo
+  fixed project dialog to behave right
+  proper .def scanning
+  fixed shader loading with VFS and mod stuff
+  added a local to texwindow.cpp GSList *l_shaderfiles
+    holds the names of the active .shader files
+  modified q3map to read "fs_basepath" and "fs_game"
+  TODO:
+    .def files in the media need to move to <fs_game>/scripts/
+    rename entities-TA.def to entities-ta.def
+
+24/07/2001
+  TTimo
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=116
+  updated cmdlib's Q_Exec to be more widely used through Radiant (during watchbsp.cpp cleanup)
+  patching in MarsMattel's code for mod support, and started fixing:
+    added m_strFSBasePath m_strFSMain m_strFSGame to g_qeglobals to match Q3's filesystem
+    reworked the project file dialog
+    changed the way we load and initialize eclass and shaders to work with mod code
+    updated VFS initialisation code, cleaner and better console output
+    the "game" key in the project file is no longer relevant, only "dir" is
+      (if "dir" is not present, then no mod support, vanilla Q3)
+    changed the loading of the .def files to scan in scripts/, you might need to move your entites.def to use
+    TODO:
+      cleanup .. (search where "basepath" is used for instance)
+      using fs_game when calling q3map
+      fixing project dialog to behave right
+      shader loading using VFS functions (seems to work again but I'm not sure)
+      win32 ver. might be slightly broken
+      .def scanning, don't scan ALL .def
+
+23/07/2001
+  TTimo
+  added version and build info to the log file + current timestamp
+
+22/07/2001
+  SPoG
+  fixed selection of misc_model when viewed as a bounding box
+  
+20/07/2001
+  TTimo
+  cons script for q3map building
+  added general GtkRadiant versioning (version.h) to q3map
+  nightly setup on linux:
+    using the right install path (with GtkRadiant's version name)
+    cleaned up options to only the stuff relevant to nightly
+    fixed Radiant and core binaries path in setup
+    added some template processing of setup.xml (similar to what is being done on win32)
+  
+19/07/2001
+  TTimo
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=112
+  applied ^Fishman's path
+  inclusion of version.h and aboutmsg.h moved to qe3.h
+  changed base path location process (in most cases it will prompt)
+  fixed the path construction to initialize according to the new layout
+
+16/07/2001
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=115
+  fixed wake up crash on linux
+
+12/07/2001
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=117
+  fixed
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=120
+  fixed installer bug on win98, was a problem with cygwin config
+
+11/07/2001
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=64
+  cleanup and fixed
+
+06/07/2001
+  TTimo
+  - http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=100
+  can't locate the "textures: in use" problem, has been fixed already?
+  now selecting the right entity in the list, had to go around an inifinite recursion problem
+    (i.e. selection message in the entity class list causes UpdateSel recursion)
+
+04/07/2001
+  TTimo
+  - added botclip to missionpack/common.shader
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=114
+
+01/07/2001
+  TTimo
+  - backported cons scripts to Alpha branch. Type 'cons' at the head to build
+  regular makefiles should soon be outdated..
+
+30/06/2001
+  TTimo
+  - updated the IS script (Gtk changes and and BACK problem)
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=68
+  - bunch of fixed to make it build on win32 against new STLPort
+  http://zerowing.idsoftware.com/STLPort/
+  using an STLPort configured locally in GtkRadiant (with stl_config.h, new file)
+
+29/06/2001
+  TTimo
+  - fixed GDI leak affecting text widgets, specially the console and the entity inspector
+
+18/06/2001
+  TTimo
+  - more win32 project file cleanup, removing libs/libxml2 from the tree
+  - importing back "gtkr_list.h" from 1.2, made Alpha branch STLport compliant too
+    http://www.qeradiant.com/faq/fom-serve/cache/174.html
+
+30/05/2001
+  TTimo
+  - added libxml2 as an external dependency. libxml2 should be installed as a seperate
+  directory on win32. dynamic linking now instead of static previously.
+  - cleaned up q3map win32 project file, removed opengl dependency
+  (the drawflag command line is inoperant now .. I don't think it was used anyway?)
+
+26/07/2001
+  TTimo
+  - checking in Gef's doxygen files
+
+14/06/2001
+  TTimo
+  - added .dsp for map module on win32
+  - fixed several issues with module loading, stability of the debug and release builds
+    http://www.qeradiant.com/faq/index.cgi?file=197
+
+12/06/2001
+  TTimo
+  - got rid of of SysMsg thing, using SysPrintf and SysFPrintf now
+  - got rid of InfoMsg functions (can't remember what it was)
+  - changed the m_pfnError in the plugin API to match Radiant's (void)(char *, ...)
+  - changed Warning to Sys_Warning, as #define to Sys_FPrintf(SYS_WRN,
+  
+11/06/2001
+  TTimo
+  - new map module, in plugins/map, required for execution (linux Makefiles written, win32 needs to be)
+    this is using the imap.h interface
+  - added Sys_ functions to the main table (Sys_BeginWait Sys_EndWait)
+  - got rid of AFX_MANAGE_STATE macros .. those are crappy MFC remnants
+  - reverted Spog's changes to the console logging switches to their original behaviour
+  - removed m_fVersion from the func table .. we use the size of the table to do the checks
+  XMLmap merge from 31/11/2000:
+  - started moving the map loading code into a module
+  
+08/06/2001
+  TTimo
+  - updates to the plugin loading code, verbose a bit more, and more interesting information
+
+05/06/2001
+  TTimo
+  - some fixes to vfspk3 string code, using the proper str implementation
+  http://www.qeradiant.com/faq/index.cgi?file=175
+  - added and tweaked various cons build files, Radiant 1.2 core and required Q3 modules are building now
+  - fixes to image module
+
+04/06/2001
+  TTimo
+  - started using cons for the linux (*NIX) build system
+  see http://www.dsmit.com/cons/
+  
+  SPoG
+  - Fixed drawing too much coordinate text in XY window
+  - Changed grid line drawing in XY window to be more consistent
+  - Fixed clipper-tool-uses-caulk to only apply common/caulk to solid opaque brushes
+    (shaders.dll now parses some new surfaceparms)
+  - Changed shader parsing to pass over layer information in shaders,
+    rather than parsing and ignoring it all
+  - Changed misc_model selection to ignore back-facing triangles
+  - Added axes to show the grid origin in XY window
+  - Changed misc_model rendering and selection to minimise the number of extra
+    transformation calculations
+  - Fixed texture directory listing to allocate and free memory correctly using vfs
+  - Added qglDeleteTextures() to plugin GL API - fixes crash
+  - Fixed image.dll to correctly allocate and free memory for jpgs
+  - Moved modules to /modules from /plugins, updated win32 project files.
+    (linux/mac makefiles will need to be updated)
+  - Changed console logging toggle in main() to automatically disable logging after any successful startup
+  - Changed console logging to only activate when a Release build finds a .pid file
+  - Changed "found .pid" and "logging console output" messageboxes to give a clearer message
+  - Added vfsFreeFile - which is kinda redundant if we use g_free and g_malloc for everything
+  
+31/05/2001
+  TTimo
+  - cleanup of the win32 project file and C++ options.\
+  Turned off exception handling, changed some code generation options and fixed
+  some threaded/non-threaded linking problems
+  - STL in GtkRadiant or a plugin must now use STLPort
+  a custom configured version of STLPort is available at http://zerowing.idsoftware.com/STLPort
+  still need to write some guidelines about it
+  bascially, we are using STL: iostreams disabled, no namespace, no threading, no exceptions
+
+30/05/2001
+  TTimo
+  - removed libxml2 from tree, use a seperate libxml2/ directory next to GtkRadiant/ for win32
+  libxml2 will be distributed seperately as an archive based on official release (same as win32 Gtk SDK)
+  (check on zerowing for the latest archive)
+  libxml2 is now used as dynamic shared object on win32, makes sense since many module will rely on it
+  - cleaned q3map, removed GL dependencies
+  - updated Debug and Release builds on win32, it compiles and runs now
+
+28/05/2001
+  Spog
+  - moved vfsExtractRelativePath and vfsGetFullPath to vfs.cpp in vfspk3,
+    added vfsExtractRelativePath and vfsGetFullPath to IFileSystem. Copied BuildShortPathName() from qe3.cpp to vfs.cpp as a Temp fix.
+  - Changed Error() calls in bmp.cpp as a Temp fix, they relied on definition of Error in qe3.cpp. Should probably use Error() from cmdlib instead.
+  - Fixed unresolved external in jpgload.obj - merged bufsize argument into jpeg_stdio_src from Alpha branch... assuming Alpha is the newer version.
+  - Changed GtkWidget* to void* in image.cpp.. this could be cleaned up more.. i only did enough to make it compile.
+  - Added jpeg.cpp to msvc project for image.dll.. changed declaraction of LoadJPG() in image.cpp to an extern... is this correct?
+  - TODO: update vfs.cpp, vfspak.cpp and vfs.h in plugins/vfspak
+  - fixed unresolved external load_pixmap() - merged load_pixmap declaration from Alpha branch into gtkmisc.cpp
+  - moved vfsBasePromptPath() to qe3.cpp as a Temp fix - not currently required in vfs module, but it will be in future.
+  - two calls to free() in texwindow.cpp freeing memory allocated by vfs module, causing debug assert errors - changed them to g_free()
+  - TODO: Delete vfs.cpp and vfs.h from /radiant
+  TTimo
+  - additional fixes after Spog's merge (linux version), removed messaging.cpp messaging.h (name changed to ui.h ui.cpp)
+    updated linux makefile accordingly
+  - merge of Alpha version into trunk (massive amount of changes and merges, not detailed)
+
+25/05/2001
+  TTimo (Alpha branch)
+  - merged the recent MacOS branch back into Alpha
+  this makes a potential source codebase for a MacOS release
+
+24/05/2001
+  TTimo (Alpha branch)
+  - patching Spog's recent changes to fix linux build
+  using DBL_MAX and FLT_MAX from <limits.h> for float and double max
+
+23/05/2001
+  TTimo (Alpha branch)
+  - testing Spog's write access
+  
+  SPoG (Alpha branch)
+  - Added variable LOD for PatchMeshes based on curvature
+  - Added LOD-matching to eliminate gaps between patches with mismatched LOD
+  - Fixed texture shift/scale on LOD'd PatchMeshes
+  - Added opengl lighting (three infinite light sources)
+  - Added dynamically calculating vertex normals for PatchMeshes, for gl lighting
+  - Added decoding/transforming md3 vertex normals for gl lighting
+  - Changed camera drawing routine to minimise gl state changes
+  - Removed Patch_InsertDelete() - not functional
+  - Added CV lattice to selected patches
+  - Added Per-polygon patch selection
+  - Added Per-polygon misc_model selection
+  - Changed default "patch subdivisions" to 4
+  - Rewrote camwindow drawing to only change opengl state within the camwnd's member functions
+       fixes all rendering modes to be more consistent, speeds up rendering
+
+--------- GtkRadiant 1.1-TA win32 and linux release ----------
+
+13/05/2001
+
+  Spog (patched in TTimo) (Alpha branch)
+  - Fixed "Fix entity-target/targetname collisions" to use next available tN if tN, else use next available name_N
+  - Changed patch point selection to pick already-selected points in preference over non-selected
+  - Changed RemoveCols and RemoveRows to not extrapolate unless a col/row is selected
+
+11/05/2001
+  TTimo (Alpha branch)
+  - final fix pass to the generated version and about message tags
+  - improved texture adjustment code (shift+arrows shortcuts)
+
+  texture adjustment commands now affect the texture relatively to their current orientation
+  they will move along their texture axis, and not along world axis
+  the texture adjustment commands are now interpreted to be more intuitive:
+    Radiant will match the up/down/right/left translation messages to the face that is affected
+       depending on the way the camera is looking at the face, the right move commands will be used
+
+  changes start in Select_ShiftTexture, using new ShiftTextureRelative_Camera
+
+  ShiftTextureRelative_Camera uses several new functions:
+
+  // get the two relative texture axes for the current texturing
+  BrushPrimit_GetRelativeAxes(f, vecS, vecT);
+
+  MatchViewAxes does the matching between up/down/left/right commands and world directions:
+  // vec defines a direction in geometric space and P an origin point
+  // the user is interacting from the camera view
+  // (for example with texture adjustment shortcuts)
+  // and intuitively if he hits left / right / up / down 
+  //   what happens in geometric space should match the left/right/up/down move in camera space
+  // axis = 0: vec is along left/right
+  // axis = 1: vec is along up/down
+  // sgn = +1: same directions
+  // sgn = -1: opposite directions
+  // Implementation:
+  //   typical use case is giving a face center and a normalized vector
+  //   1) compute start and endpoint, project them in camera view, get the direction
+  //     depending on the situation, we might bump into precision issues with that
+  //   2) possible to compute the projected direction independently?
+  //     this solution would be better but right now I don't see how to do it..
+  void CamWnd::MatchViewAxes(const vec3_t P, const vec3_t vec, int &axis, float &sgn)
+
+  // shift a texture (texture adjustments) along it's current texture axes
+  // x and y are geometric values, which we must compute as ST increments
+  // this depends on the texture size and the pixel/texel ratio
+  void ShiftTextureRelative_BrushPrimit( face_t *f, float x, float y)
+
+  those functions are using various new utility functions:
+  
+    // GL matrix product
+    void GLMatMul(vec_t M[4][4], vec_t A[4], vec_t B[4]);
+
+    // project a 3D point onto the camera space
+    // we use the GL viewing matrixes
+    // this is the implementation of a glu function (I realized that afterwards): gluProject
+    void CamWnd::ProjectCamera(const vec3_t A, vec_t B[2])
+
+  - UI abstraction layer (interfaces for Gtk MFC and Q3 UI)
+
+09/05/2001
+  Maj (Alpha branch)
+  - new splash screen
+
+  Spog (patched in by TTimo) (Alpha branch)
+  
+  patcing in changes:
+  - moving void VectorSnap(vec3_t point, int snap); to mathlib
+  - NOTE: STL dependency removed .. leaving this comment
+    this will rely on M$ implementation of STL on win32 and the libstdc++ for linux
+    it should work fine for basic stuff
+      but M$ implementation doesn't follow the standards when it comes to advanced stuff
+    it is probably better to leave the STL header in local files and not go towards including it directly from qe3.h
+
+  Spog's Changelog:
+  
+  rushing this a bit.. make sure you check it doesn't remove anything you 
+  changed. This only contains changes within /radiant .. i'm pretty sure I didn't 
+  change anything else, but i'll check again. Patch below.
+
+  Fixed ctrl+G SnapToGrid, now never creates degenerate face-planes
+  Fixed setting an origin for multiple brushes to use origin point of fixedsize 
+  entities
+  Fixed mirroring and rotation of fixedsize entities including misc_model
+  Fixed undo/redo on multiple entities to link brushes to entities correctly
+  Fixed "view > entities as.." menu to display correct default setting
+  Fixed "view > entities as.." toolbar button to show menu
+  Changed selection-area of edge/vertex control handles to stay constant when 
+  zoomed
+  Fixed undo on ctrl+G SnapToGrid
+  Fixed Selection Invert to set bSelected correctly on patches
+  Fixed XY-window Z selection origin to be g_MaxWorldCoord
+  Changed RotateIcon to draw same size at all zoom levels
+
+  Fixed origin drift on saving misc_model with null md3Class
+  Fixed creation of cap for 'Bevel' type patches
+  Fixed inverted cap being created for 'Endcap' type patches
+  Fixed inverting patches on mirror operations
+  Added snap-selected-to-grid affects only the patch points selected
+  Cleaned up Select_ApplyMatrix and Select_SnapToGrid
+  Added drawing of brush planepts in debug build
+  Fixed texture quality slider adjustment
+  Removed redundant menu items curve > cap > inverted bevel/inverted endcap
+  Fixed texture scrolling not working when scrollbar is disabled
+  Fixed textures with odd dimensions being skewed with texture quality less than 
+  max
+  Changed Patch Inspector Horizontal/Vertical increment to use pixel values 
+  (default 8)
+  Changed Patch Inspector Horizontal increment to subtract from S values but not 
+  T values
+  Changed Patch Inspector Stretch spinner to do something useful
+  Changed Patch Inspector Stretch default amount to 0.5
+  Changed Arbitrary Rotation dialog to reset rotation spinner values to 0 on Apply
+  !! stops output in console window !! - Added sending q3map output 
+  to /temp/junk.txt to bsp commands, in win32 only
+  Fixed Patch_Naturalize to calculate T values backwards, correcting texture 
+  vertical flip
+  Changed patch row/column Insert/Remove to interpolate/extrapolate from existing 
+  curves
+  Fixed point selection on patches when new points are added
+  Fixed redundant edge/vertex handles being created for patch brushes and 
+  fixedsize brushes
+  Fixed refusal to activate brush vertex-drag mode if any patches are selected
+  Partly fixed Undo picking up patch point drags when no points are selected
+  Fixed behaviour of vertex selection on patches
+  Fixed patch point colours in textured mode in cam window
+  Changed patch point selection to update selection pool on each selection click
+
+06/05/2001
+  TTimo (Alpha branch)
+  - more setup script changes, will rely on version information
+    various other fixes in the script file
+
+02/05/2001
+  TTimo (Alpha branch)
+  - added makeversion.sh to the root, will generate version and date files before compilation
+  version.h and date.h
+  - cleanup and fixes to the linux setup scripts
+
+  Spog (CVS add and config by TTimo) (Alpha branch)
+  - win32 setup script, run setup/setup.sh from cygwin to create a working directory for the setup <STILL EXPERIMENTAL>
+
+01/05/2001
+  TTimo (Alpha branch)
+  - fixes to linux version from previous set of patches
+
+19/04/2001
+  Hydra (patched in TTimo) (Alpha branch)
+  http://fenris.lokigames.com/show_bug.cgi?id=3458 :
+  - *.pfb filter
+
+  SpoG (patched in TTimo) (Alpha branch)
+  - updated setup data: entities.def common.shader(Q3) and common-spog.pk3
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=25 :
+  - Patches: Curve > matrix > redisperse > rows/columns
+    I changed this function to treat a patch as multiple 3by3 sections when doing 
+  redispersal of control points. The effect is that green patch points are never 
+  moved. I also removed the call to Patch_Naturalize, so the texture coordinates 
+  are not changed (user can hit ctrl+n to naturalize afterwards if desired).
+  - rewrote the patch_captexture function to be more reliable
+  - Fixed YZ view drawing and selection being mirrored on plane X=0
+  - Fixed X and Z rotation direction to be clockwise as shown on the toolbar button 
+    icons
+  http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=8 :
+  - Fixed: Removed orientation-switching hack to fix 2pt-clip orientation problems, 
+    originally stemming from ass-backwards representation of grid axes. Fixed 
+    clipper to generate 3rd clip point correctly for each axis instead.
+  - Fixed: Stopped clipper-caulker from NOT applying caulk if the first face of a 
+    brush was "common/caulk".
+
+  TTimo (Alpha branch)
+  - removed some unused code in the Gtk file dialog, hopefully stabilizing it
+
+02/04/2001
+  TTimo (Alpha branch)
+  - changed the regular/BP conversion prompt
+
+01/04/2001
+  Spog (patched in by TTimo) (Alpha branch)
+  - Fixed view > show coordinates now affects Z window
+  - Fixed minimum/maximum world coordinates now -65536/65536
+  - Fixed view > show blocks now only draws vertical lines if not XY view
+  - Added variable blocksize (gtkr only displays 1024 < blocksize < 65536)
+  - Changed XY/Z window grid drawing to use floats internally
+  - Fixed broken XY window grid drawing for higher zoom levels
+  - Changed camera and Z-checker icons to stay the same size when zoom level changes
+
+24/03/2001
+  Spog (patched in by TTimo) (Alpha branch)
+  - added filters.cpp to the VC6 Makefile. Linux build needs updating
+  - Changed Filter system to use brush-flags updated only on actions that affect filtering
+  - Changed Filter system to allow further extension and future customisation
+  - Changed show/hide to use brush filter flags
+  - Changed Find/Replace textures to only rebuild brushes that changed.
+  - Changed View > Filter menu shortcuts and behaviour
+  - Fixed various minor spelling errors
+
+  TTimo (Alpha branch)
+  - Fixed the 'Clean' command in preferences, used to remove only Radiant.ini and not SavedInfo.bin
+
+06/03/2001
+  TTimo (Alpha branch)
+  - better parse error information: added the line number of the error in (hopefully) all cases
+
+30/02/2001
+  TTimo (Alpha branch)
+  - texture locking in BP mode for axis flipping and axis rotation (toolbar buttons) (Id bugfix request)
+  - fixed undo in BP mode
+  - MatchToken error message in q3map improved with the script name
+
+27/02/2001
+  TTimo (Alpha branch)
+  - switched linux makefiles to xml2-config instead of xml-config
+  latest version of libxml2 is using xml2-config instead of xml-config now
+
+26/02/2001
+  TTimo (Alpha branch)
+  - fixed a loki_initpath misbehaviour, was overriding the path to the binary with RADIANT_DATA if defined
+
+21/02/2001
+  - Added setup data and a script to build linux setups to the cvs
+  TTimo (Alpha branch)
+  - various printf -> Sys_Printf
+  - added vslick/ directory for Visual Slickedit 6.0 on win32 <- THIS IDE RULES
+
+20/02/2001
+  - Removed "Show Paths" option, already in the filter menu
+
+19/02/2001
+  - Fixed the Enter key handling on the surface inspector (suggested by Spog)
+  - Fixed skewed textures with lower texture quality
+  - Changed the order the include directories are searched under Linux
+
+15/02/2001
+  - Moved the Show Cluster Portals option to the Filter menu
+  - Fixed the rotate and scale toolbar buttons being incorrectly checked
+  - Fixed arbitrary rotation bug (#3073)
+
+14/02/2001
+  - Fixed CreateFont memory leak on glwidget
+
+12/02/2001
+  TTimo (Alpha branch)
+  - fixed save as prefab stuff (right dialog name and overwrite prompt)
+
+10/02/2001
+  TTimo (Alpha branch)
+  - was crashing on win32 boxes where HOME env var was not defined (loading bookmarks)
+
+09/02/2001
+  TTimo (Alpha branch)
+  - change some code in the file dialog to use g_malloc g_free instead of new 
+    for win32 file dialog and malloc for Gtk file dialog. (all of this trying to get rid of
+    some of the crashes)
+
+07/02/2001
+  - Fixed Load command initial path
+  - Fixed some toolbar buttons not being correctly initialized
+
+-----------?
+
+06/02/2001
+  (Alpha branch)
+  - Fixed pk3man file dialog errors
+  - New RC uploaded
+  - Changed conflicting shortcuts: FilterModels = Shift+M, FilterTriggers = Ctrl+Shift+T
+  TTimo (Alpha branch)
+  - fix to hide/show, still selecting hidden brushes
+
+05/02/2001
+  (Alpha branch)
+  - Fixed compile errors (use stat, not _stat)
+  - Removed --nofonts option
+
+04/02/2001
+  TTimo (Alpha branch)
+  - fenris #2866, added a pref to turn on/off name conflicts resolution, rewrote the whole algorithm
+  - fenris #2823, fixed patch and brush dragging in 0.25 0.5 grids (it's an ugly hack btw)
+  - fixed the black squares at end of line in Gtk text boxes
+  RR2DO2 (Alpha branch)
+  - fix to the "entitypath" fixup in QE_CheckProject. might not compile on linux yet (use of _stat?)
+
+03/02/2001
+  TTimo (Alpha branch)
+  - fenris #2867, limiting the amount of "spawnflags" "0" appearing in entities. This bug has work left to do,
+    there are some oddities in the entity inspector behavior described.
+
+02/02/2001
+  (Alpha branch)
+  - Fixed sleep mode not restoring windows correctly
+  - Fixed some minimize/restore issues on floating views mode
+  TTimo (Alpha branch)
+  - fixed more gtkfilesel stuff. pattern filtering works for both Gtk dialogs
+    and win32 native. Also checked on linux that it compiles. Renamed gtkfilesel.h
+    to gtkfilesel-linux.h for consistency.
+
+31/01/2001
+  (Alpha branch)
+  - New file selection widget with filtering, masks and all other shit we need
+  TTimo (Alpha branch)
+  - changed some gtkfilesel API and fixed some bugs on pattern filtering, need to reboot on linux and fix some more
+
+30/01/2001
+  (Alpha branch)
+  - Added an option to keep the Z and XY views on the same window in floating views mode
+  - Did some cleanup
+  TTimo (Alpha branch)
+  - removed the 3 layers in terrain entities limitation, increase version tag to patchlevel 3
+  sent for testing to AstroCreep, bug is still there
+  - fixed one more thing with RC file (get it in the right dir)
+  - worked on file dialog and pattern filtering, still issues left
+
+29/01/2001
+  Jonas (patched in by TTimo) (Alpha branch)
+  - Using RC file to tweak the font size on win32, looks much nicer now!
+  - Fixed fenris #2773: esc key behaviour when group window has focus / dependant on view modes
+
+28/01/2001
+  TTimo (Alpha branch)
+  - Finished fenris #2810 (Snap T to grid), it was a bitch
+  - Fixed fenris #2769: raise the brush max size (it was already big, now it's just not sane)
+  - Fixed fenris #2965: eclass (entities) loading code broken, needs to be checked on linux build before closing
+
+27/01/2001
+  TTimo (Alpha branch)
+  - Fixed vertex edit prefs broken
+  - more fixes in Gtk libs
+  - Fixed clipping + brush primitives bug (#2644)
+  - Fixed clip caulk related issues (#2912)
+  - Added Snap T to grid back (#2810) <- still need to test and validate it, I'm too tired tonight
+
+25/01/2001
+  TTimo (Alpha branch)
+  - New Gtk file selection dialog seems stabilized, built a Gtk SDK for the new Gtk libs.
+
+24/01/2001
+  (Alpha branch)
+  - Fixed elapsed time displayed by q3map
+  - Fixed Radiant loading some TGA files upside down
+  TTimo (Alpha branch)
+  - more work done on the file selector. Added a win32 pref to select between regular win32 file dialog and Gtk one.
+  The advanced file selector is still not stabilized on win32. I am thinking about letting go and sticking to the regular one.
+
+23/01/2001
+  (Alpha branch)
+  - Fixed q3map not finding md3 files under missionpack/
+  - Prompt to save changes when choosing a recent file
+  - Fixed window title when choosing File/Load Map
+  - Don't show hidden brushes in the Z window
+
+22/01/2001
+  (Alpha branch)
+  - More File Dialog fixes
+
+21/01/2001
+  TTimo (Alpha branch)
+  - version first version of the advanced file selector on win32
+  seems to work nicely, but crashes when you actually load something .. needs debugging!
+
+  leo (Alpha branch)
+  - Set correct initial directory for the File/Load command
+
+17/01/2001
+  (Alpha branch)
+  - Fixed q3map is crash if a .shader file is referenced in shaderlist and not found
+
+  TTimo (Alpha branch)
+  - fixed some license headers on gtkfilesel.c, started looking into porting gtkfilesel.c to win32
+
+16/01/2001
+  raistlin
+  - the tree is opened whoooo!
+
+  TTimo (Alpha branch)
+  - replaced the old Id header by the newer version (BIG update, to trunk and Alpha)
+  - switched str.h to BSP
+  - added LGPL license to the sample dll
+
+15/01/2001
+  (Alpha branch)
+  - Added camera window toggle option to all views mode
+
+  TTimo
+  for trunk and Alpha:
+  - renamed TOOL_SOURCE_EULA to LICENSE_ID
+  - renamed CONTRIBUTOR to CONTRIBUTOR_AGREEMENT
+  - added CONTRIBUTORS and LICENSE
+
+14/01/2001
+  (Alpha branch)
+  - plugin SDK is back in setup/ moved the sample dll to be in plugins/, need to rewrite the SDK scripts
+  - built a lightweight plugin SDK with cygwin makefile for the sample plugin
+
+12/01/2001
+  (Alpha branch)
+  - Set map modified flag when deleting a brush
+  - Minimize all windows when the main window is minimized in floating views mode
+
+11/01/2001
+  (Alpha branch)
+  - Cleaned up the View/Show submenu
+  - Fixed texture menu splitting 
+  - Fixed major grid lines on 128 and 256 grids
+  - Load only a single .def file if specified in the project settings
+  - Fixed q3map Makefile
+
+  TTimo
+  (Alpha branch)
+  - Removed plugins/shaders from Alpha branch
+  - got rid of common2/ and code, moved qfiles.h and surfaceflags.h into common/
+  - put the licensing headers in all source files (forgot some? byte me)
+
+10/01/2001
+  leo (Alpha branch)
+  - Added new filter system based on FAKK2 Radiant
+
+  TTimo
+  - fixed whatever could be fixed to make it compile with the new directory layout
+  (Alpha branch)
+  - project files update
+
+09/01/2001
+  (Alpha branch)
+  - Added undo for patch redisperse rows and patch redisperse cols commands
+  - Fixed Show Z Outline menu item
+
+30/11/2000
+  TTimo
+  - removed content flags and value from qtexture_t, these have moved to the IShader
+    (NOTE: qtexture_t != texdef_t, texdef_t still using flags value and content)
+
+  - Rewrote the linux plugins Makefiles
+
+29/11/2000
+  - Improved the way modules are loaded
+  - Added new parameter to QERPlug_RequestInterface
+  - finished VC6 project files conversion for new directory structure
+  - fixed shader blending on terrain maps bug
+08/01/2001
+  - Updated Makefiles for the new directory structure
+  - Fixed View/Show/Entities menu not being checked correctly
+  - Fixed "Invert Selection" command selecting hidden brushes
+  - Fixed "Select All of Type" command not working correctly after the Enitity Window is closed
+  - Fixed grid being drawn even when it's the same color of the background
+  - Fixed "Toggle Size Paint" not turning off
+05/01/2001
+  - Fixed autosave interval being calculated wrong
+  - Fixed autosave path under Linux
+  - Fixed q3map crash when trying to load missing pcx files
+  - Fixed q3map not finding .bmp files for the terrain alpha map
+04/01/2001
+  - Fixed GL stack underflow when loading a misc_model
+03/01/2001
+  - Fixed patches remaining half-selected after "Region set selected" (#2748)
+  - Fixed Surface Inspector spin buttons rate (#2776)
+  - Fixed some shortcuts not appearing on menu items (#2786)
+
+
+================================================================================
+                                  1.1-TA beta
+================================================================================
+
+02/01/2001
+  - Fixed memory problem if a file without extension is entered in the file save dialog.
+  - Fixed double slashes "//" on filenames when saving a map
+  - Fixed pk3man plugin not finding the toolbar bitmaps
+  - Fixed double clicks being considered 2 mouse clicks
+
+  RR2DO2 (applied by TTimo)
+  - Clusterportal filtering ('View > Show > Show clusterportal' toggle)
+
+01/01/2001
+  TTimo
+  - updated Web/ with new stuff, web site ready for release
+  - fixed a crash with multiple edge dragging on win32 (was caused by compiler optimizations,
+    this one was a major pain)
+
+31/12/2000
+  - fixed the file open/save dialogs initial directory
+
+  RR2DO2 (applied by TTimo)
+  - bug fix in the terrain loading speedup
+
+  TTimo
+  - tried to lookup the Z window minimum width problem, added #define DBG_WINDOWPOS code to investigate
+
+30/12/2000
+  RR2DO2 (applied by TTimo)
+  - fix to CSG Merge in the menu drop down (menu was there, command not hooked)
+  - some message formatting fixes
+
+  TTimo
+  - rudimentary pattern matching in file selection, affects the plugin API too
+  - fixed silly bug in the "clipper uses caulk" code
+  - major speedup to the loading code on terrain entities
+  (in mpterra2, from 113s to 4s for the main terrain entity)
+  - patched back the file open/save dialogs initial directory to override in TA mode
+  - fixed Patch output crash in the plugin API
+  - fixed BP conversion in the brush output of the plugin API
+
+  minkey (applied by TTimo)
+  - fix to the m_pfnLoadFile code to use VFS
+
+29/12/2000
+  - Remember main window position in floating views mode
+  - Fixed wake up when running the engine in floating views mode under win32
+
+  TTimo
+  - various fixes and debug hooks for PJ bug reports
+
+28/12/2000
+  - Fixed VFS initialization order
+  - Removed texture menu splitting option from preferences (now it's automatic)
+
+  TTimo
+  - built an initial setup, updated the changelog file for 1.1-TA-beta
+
+27/12/2000
+  - Fixed Q3Map output window being too wide on some errors
+  - Added VFS to q3map
+
+  TTimo
+  - replace a printf in q3map by Sys_Printf (!), which is what should actually be used
+  - added a set of functions to vfs to help with file dialogs, building relative files etc.
+  - reworked the file dialogs so they default in the right location (open/save as/md3 loading/sound loading)
+  - fixed shader editor to work with the right path
+
+26/12/2000
+  TTimo
+  - put the converted HTML manuals (Radiant, shaders and model) in the tree (and the win32 setup)
+  - added the new Terrain and Team Arena mapping manuals (added to the setups too)
+
+  leo
+  - Copy and paste across different instances of Radiant
+  - Fixed wait cursor when copying
+  - Print engine command line to the console
+  - Fix glib warnings when running the engine
+  - Fixed shader files being loaded twice
+  - Texture menu now automatically breaks when it reaches the maximum screen height
+
+24/12/2000
+  - Fixed q3map to compile with the new LoadJPGBuf parameter
+
+  TTimo
+  - added TA paths to the BSP commands and running engine
+  - fixed a bug if running with monitoring disabled (generating the .bat was borked)
+  - changed the -moddir implementation to a global switch in q3map (same as -connect)
+  - moddirparam as a global variable in cmdlib, added a TA_HACK in there
+  - changed the SetQDirFromPath to stick to "baseq3/" when using -moddir
+  TODO: check standalone files
+
+23/12/2000
+  TTimo
+  - fixed some sleep/wake code (crashes and wakeup problems on models)
+  - vfsInitDirectory for TA directory (needs to be checked on linux)
+  - changed my mind on entities.def, if TA is enabled, load entities-TA.def on top of regular entities.def
+
+  mickey (applied by TTimo)
+  - some memory overrun fixes
+
+22/12/2000
+  - Fixed plugin Makefiles to not use private/
+
+  RR2DO2 (applied by leo)
+  - Fixed SetTallBrush undo
+  - Added bug report link to help menu
+
+21/12/2000
+  - Daily Linux compilation fixes
+  - Fixed q3map to read .pk3 files from the directory set by -moddir
+  - Fixed vfs not listing all files correctly
+  - Fixed libjpeg crashing on some jpeg files
+  - Load .def files depending on the current game
+
+20/12/2000
+  - Applied Mickey's patch to fix win32 window position save/load.
+  - removed missing _msize call
+
+  TTimo
+  - cleaned up more g_malloc g_free problems, cleaned a INPUT_BUF_SIZE problem in jpeglib
+
+19/12/2000
+  - More manual updates
+  - Fixed bugs comparing file extensions
+  - Added VFS to the Alpha branch
+
+  TTimo
+  - moved game selection to the project settings
+  - got leo's vfs fixes, started changing the memory allocation scheme to glib
+  - moved 'free' calls to g_free with a #define in cmdlib, Radiant seems to run nicely again
+  - removed calls to _msize .. those were causing heap debug assertion failures
+  - upped more stuff
+
+18/12/2000
+  - Added popup menus with the list of active textures to the find texture dialog
+  - Fixed some menu checkbuttons
+  - Changed max number of shader files parsed by q3map to 128
+  - Updated manual images 
+
+17/12/2000
+  - Fixed bug with the texture window scrollbar range
+
+  Mickey (patched in by TTimo)
+  - fix to the floating windows mode, don't send windows to the desktop when raising something else (#2659)
+
+  TTimo
+  - finalized the merge and move into worldspawn commands by adding the undo stuff
+  - fixed the clamping problems when flipping or mirroring patches
+  - added 0.5 and 0.25 grids
+  - added undo to Select_CompleteTall Select_PartialTall and Select_Inside
+  - added on-the-fly conversion between regular brush coordinates and brush primitives texturing in the plugin API
+
+15/12/2000
+  - Fixed crash on Shift-A (Select all of type)
+  - Save the state of the toolbar buttons
+  - Remember the state of the Show Patch Bounding Box button
+  - Double clicking on an entity on the Entity View tree selects the entity
+  - Sort the list columns of the map info dialog
+  - Fixed a bug that would allow multiple Entity View dialogs
+
+  Mickey (patched in by TTimo)
+  - saving position and size of the entity window between runs and during usage
+
+  TTimo
+  - two new commands in the drop down menu:
+  "move into worldspawn" will move selected brushes to worldspawn and eventually delete entities which end up with no brushes
+  "merge brushes" will merge brushes into an entity (from worldspawn or from another entity)
+  - added cleaned HTML version of the editor manual in the tree
+
+14/12/2000
+  - When pressing a letter key in the entity window list, scroll to the entity starting with the key pressed
+  - Fixed backspace not working on the texture subset entry
+  - Added version check when loading savedinfo.bin
+
+  TTimo
+  - started implementing Select_Merge and Select_Seperate for workflow improvement on terrain maps
+
+13/12/2000
+  - Finished GtkGenSurf
+
+  RR2DO2 (merged in by TTimo)
+  - patch to q3map, added option -custinfoparams for custom surface flags (still need documentation)
+
+  TTimo
+  - zoom out and grid drawing taylored to the world size
+
+12/12/2000
+  TTimo
+  - quick win32 update to gensurf
+  - fixed #2610 (MAX_NETMESSAGE) .. needed a consistent rewrite of the way we parse the stream
+
+11/12/2000
+  - Fixed linux compiler errors from recent changes
+  Not fixed today but I forgot to add those to the Alpha changelog
+  - Fixed multiple Map Info dialogs bug
+  - Fixed texture window not scrolling to the top when a new directory is loaded
+  - Fixed GL Windows grab pointer bug
+  - Fixed crash after map compilation if the map leaked
+  - Fixed q3map crash if MAX_SHADER_FILES is reached
+
+28/11/2000
+  - Fixed sleep mode restoring hidden windows (win32)
+  - Fixed find/replace textures dialog layout and keep it always on top of the main window
+  - Replaced malloc/free calls with g_malloc/g_free to avoid the win32 limitation
+
+27/11/2000
+  - Removed glu.h dependencies
+  - Added new file selection dialog
+  - Removed g_PrefsDlg.m_bDisableAlphaChannel (always FALSE)
+  - Added shortcuts for sleep and simple patch mesh
+  - Fixed crash after sleep mode (no GL context current)
+
+24/11/2000
+  - Rewrote the jpeg functions of the image plugin
+  - Replaced some MFC classes with glib
+  - More shader plugin fixes
+  - Fixed bug with select all entities command
+
+  TTimo
+  - fixed q3map to handle the new LoadJPGBuff length parameter
+
+22/11/2000
+  - Fixed crash in Error() if there's no current GL context
+  - Fixes to the shaders plugin
+
+  TTimo
+  - created VC6 project file for image module
+  - modified the m_pfnError in qerplugin.h to use (char *, ...) construct
+
+21/11/2000
+  - Ensured that the plugins are loaded in the correct order
+  - Added Sys_FPrintf and Sys_Printf to the plugin interfaces
+  - Some VC++ fixes
+
+  TTimo
+  - more fixes to the world size
+  - modified moduleentry_t so it compiles on win32. need to update the code in all modules probably
+  - other minor fixes and updates to get everything building on win32
+
+20/11/2000
+  - Moved image loading code to a plugin
+  - Fixed some bugs in the shader plugin
+  - Now using glGenTextures to set texture ids
+
+19/11/2000
+  TTimo
+  - shader code removed from Radiant core, relies on shader module
+  - added ctrl-alt-LBUTTON = multiple brush select without selecting whole entities (from TA update)
+  - added an XML testing proggy in DevDocs/
+
+18/11/2000
+  TTimo
+  - shader module is compiling
+  - reworked the way we deal with required interfaces,
+  automated the interface request process and added code to check the required modules have been found
+
+17/11/2000
+  - Q1 VFS plugin
+  - Changes to the VFS API to detect the format supported by a plugin
+  - Added checks to PluginManager to load the correct VFS plugin
+
+  TTimo
+  - made a mess with XML MAX_NETMESSAGE error, still not fixed
+  - merged q3map 1.0r (TA update from Id) into the tree - important files modified: surfaceflags.h qfiles.h
+
+08/12/2000
+  TTimo (shit I'm 24 now)
+  - added gtk gensurf, VC6 project files are up to date, linux Makefile not checked
+  - fix some WINAPI stuff on above code
+  - add idata.h for raw access to editor data
+  - new _QERAppShaderTable for shader module -> editor functions
+  - added new entries in various tables (GL, parser etc.)
+  - shader module is well under way
+
+16/11/2000
+  - Added a color selection dialog function to the plugin API
+  - Added profile read/write functions to the plugin API
+
+  TTimo
+  - MAX_NETMESSAGE bug: patched q3map so it sends in several messages if the problem occurs
+  still need to update Radiant to recognize XML nodes split into several messages (using an input buffer)
+  - added a test map for MAX_NETMESSAGE: sput.map
+  - project file for vfspk3and win32 patching
+
+15/11/2000
+  - More plugin cleanup
+  - Added IsEqualGUID() to qerplugin.h
+
+  TTimo
+  - merged Alpha back in (didn't try to merge this CHANGES file)
+  - backported some stuff from the trunk to here, the Sys_Printf, gtk_MessageBox and profile stuff
+  - created VC project file for gtk-based gensurf plugin
+
+14/11/2000
+  - Fixed DumpUnreferencedShaders()
+
+  TTimo
+  - added QE_CheckProjectEntity to check paths are following the right conventions
+
+13/11/2000
+  - Fixed bugs in the vfs plugin
+  - Added support to vfs plugins in Radiant
+
+  TTimo
+  - updated project file to libxml2-2.2.8, use libxml2 as the directory name for whatever version..
+          NOTE: libxml2-2.2.8 needs some patching to compile right..
+
+12/11/2000
+  TTimo
+  - all Radiant functions that might be exported in interfaces need to use the WINAPI calling convention
+  modified the GTK functions code accordingly
+  - started writing the shaders module
+
+10/11/2000
+  - Added new GTK functions to the plugin API
+  - Added 'parent' parameter to MessageBox, file_dialog and dir_dialog
+  - Fixed Help commands (Linux)
+
+09/11/2000
+  - Fixed bug in the Z wnd code
+  - Fixed copy text from the console (win32)
+
+       TTimo
+       - moved the libxml library out of the tree, updated the VC6 project files accordingly
+
+08/11/2000
+       - ZWnd always on top (view #2, win32)
+
+       TTimo
+       - added Escape key to hide the entity inspector
+       - S and Shift+S now act as toggles on the inspectors
+
+07/11/2000
+       - Added ungroup command to right click menu
+       - Fixed message box accelerator bug
+       - Fixed GL error on win32 startup
+
+       TTimo
+       - additions to the BSP interface
+       - fixed DestroyCursor error
+       - clipper caulks faces (and prefs checkbox)
+
+06/11/2000
+       - Cleaned PrtView and TexTool plugins
+       - Fixed bug in texture menu names (#2506)
+       - Added splitters to Entity dialog
+
+       TTimo
+       - started clipper caulk implementation
+       - fix to the pointfile not drawing in 2D views
+       - MAX_BUILD_SIDES in q3map debug stream
+
+05/11/2000
+       - Merged Alpha branch with the trunk
+
+       TTimo
+       - more plugin interface for Q3Build, and plugin SDK additions
+       - merged q3map Realloc back into Alpha branch
+
+04/11/2000
+       - Fixed crash during startup if Zwnd was hidden in views #2 and #3
+       - Fixed ToggleConsole command
+       - Fixed ToggleEntity and ToggleTexture commands in view #2
+       - Fixed plugin Makefiles
+       - Removed -rdynamic from Radiant link options (crashes pk3man plugin)
+
+03/11/2000
+       TTimo
+       - directory reorganisation for the plugin SDK, added an interface/ directory
+
+02/11/2000
+       - Save ZWnd state in views #2 and #3
+       - Entity dlg always on top (linux)
+       - Fixed shortcuts.ini parsing bug
+       - Fixed editpad crash if editpad not present (win32)
+       - Fixed bugs in the internal shader editor
+       - Fixed widget_show if window moved after gtk_widget_set_uposition
+
+================================================================================
+                                    1.1 beta
+================================================================================
+
+31/10/2000
+       - Continue loading if glXGetProcAddressARB is not present (Utah-GLX fix)
+       - Fix BSP commands not working if a map is not in "mapspath" (linux)
+
+30/10/2000
+       - fixed the Region commands, "Region > Set brush" is working
+         Region uses the camera as spawn point.
+       - Fixed view/show menu initialization
+       - Fixed warning when starting view #2
+       - Fixed z wnd in view #3
+       - Fixed win32 sleep mode crashes on views #2 and #3
+       - Added "Restart" message when changing texture quality in the preferences
+       - Cleanup: removed radbsp.cpp (unused) and unzip.cpp (already in pak.a)
+
+29/10/2000
+       - Fixed SIGCHLD handler
+       - Built 1.1b setups
+
+28/10/2000
+       - Fixed q3map bug visbytes > MAX_MAP_VISIBILITY
+       - Fixed clipper display bug
+
+       TTimo
+       - updated quakev2.qe4 with -vlight options
+       - added checks in q3map to prevent crashing on allocating a winding too big
+       will stop with an error now.
+       - added the corresponding editor support for debug messages if MAX_POINTS_ON_WINDING is exceeded
+
+       G_Dewan
+       - improved q3map, reducing minimal memory footprint by about 45Mb
+
+27/10/2000
+       - Fixed crash in BSP debug window
+       - Reorganized the preferences dialog
+       - Fixed q3map Makefile
+       - Fixed +/- bug in win32 (Gtk patch)
+       - Fixed Alt shortcuts bug in win32 (Gtk patch)
+       - Fixed q3map crash when visbytes > MAX_MAP_VISIBILITY
+
+       TTimo
+       - improved snapshots behaviour, doesn't snapshot non-modified maps
+
+26/10/2000
+       - Fixed patch inspector not showing after it has been closed
+       - Added 'Reset' button to entity dialog
+
+25/10/2000
+       - Fixed more grid issues
+       - Fixed load window position bug (saved pos greater than screen resolution)
+       - Fixed selection nudge bug
+       - Improved entity windows layout
+       - Fixed GL font not being recreated when exiting sleep mode
+
+       TTimo
+       - cleaned m_nTextureTweak and m_bSnapTToGrid
+       - improved the CycleCapTexturePatch command, now cycles across the 3 planes only 
+       and works on multiple patches at once
+
+24/10/2000
+       - Added an overwrite prompt when saving files
+       - Fixed 128 and 256 grid display
+       - Commented-out grouping code (not functional yet)
+
+23/10/2000
+       - Fixed q3map to load jpgs under Linux
+       - Fixed wake-up crash when floating windows were closed (#2423)
+
+21/10/2000
+       - More q3map and radiant Makefile fixes
+       - Remember size/position of the entities dialog
+
+20/10/2000
+       - Redirect Gdk warnings
+       - Draw border around active XY wnd
+       - Moved some scripts to the Makefile
+       - Added shift+rclick to zoom in/out
+       - Removed minimize/maximize buttons for z wnd in floating mode under win32
+
+       TTimo
+       - Two new entries in View > Show: Show Outline and Show Axes
+       Show Outline turns on/off colored outline of the current view
+       Show Axes turns on/off display of a small axis base in the 2D view
+       - fix q3map Makefile to use external libxml2 source
+       
+       G_DEWAN
+       - Fix to bogus noshader error message in q3map
+
+19/10/2000
+       - Added new console functions that support colors
+       - Revised linux makefile for debug/release builds
+       - Redirect Gtk warnings to the console
+
+       TTimo
+       - reorganized the entity inspector window, layout depends on the number of flags to get
+       more space in the comment window.
+
+18/10/2000
+       - Fixed add/remove bsp items in project settings dialog
+       - Did some cleanup (removed #define WIN32_CONSOLE)
+       - Fixed console not working in view #3
+       - Fixed warning when exiting in views #2 #3
+
+       TTimo
+       - fix to entity inspector comment window for the eclass_t on win32 (removed the white squares)
+
+17/10/2000
+       - Fixed texwindow not scrolling when last texture is large
+       - Added LOD for patches
+       - Fixed prefab path & user ini in preferences dialog
+
+13/10/2000
+       TTimo (XML branch)
+       - basic architecture for XML feedback is functional
+       see radiant/feedback.cpp radiant/watchbsp.cpp q3tools/common2/inout.c
+       merging back in alpha
+
+04/10/2000
+       TTimo (XML branch)
+       - sax interface is in Radiant, need to add a state machine and proper processing
+
+04/10/2000
+       TTimo (XML branch)
+       - experimental use of SAX interface to parse the stream on the server side, see q3tools/q3map/NetTest
+
+03/10/2000
+       TTimo (XML branch)
+       - adding libxml2 in the repository, based on libxml2-2.2.4 with project files and stuff to build on win32
+
+31/09/2000
+       TTimo (XML branch)
+       - new common2/ dir, output system rewritten through Sys_Printf
+       - experimental use of libxml
+
+28/09/2000
+       TTimo (Inspector branch)
+       - shift+arrows matches the increments from the surface inspector
+       - button 'Match Grid' in the SI to set the increment according to current grid
+
+25/09/2000
+       TTimo (Inspector branch)
+       - fixed crappy bug in SavedInfo.bin upgrade (when the struct sizes don't match)
+       - surface inspector has inc step dialog boxes (+saved in prefs)
+       - face selection is always on (was something weird from the prefs)
+       - undo works better with the surface inspector
+
+25/09/2000
+       - Added ARB_Multitexture support
+
+21/09/2000
+       - Fixed preferences dialog warning
+       - Added new grid sizes
+
+20/09/2000
+       - Fixed small bugs reported from Fenris
+
+17/09/2000
+       TTimo
+       - fixed a bug with template project loading / path to the engine safecheck (a weird hidden one)
+       G_Dewan & TTimo
+       - fixes to the process spawning (Q_Exec in cmdlib) + appropriate warning and error messages
+       Fishman
+       - antialiased drawing in 2D views
+
+14/09/2000 
+       TTimo
+       - radiant.log commandlist.txt and radiant.pid are create in g_strAppPath on win32 and g_strTempPath on linux
+       - moved the splash screen after the .pid code
+       - I suspect a bug in the .pid removal, added a check and message box
+       - help works again on win32, spawning Word with the Q3Rad_Manual.doc (temporary solution of course)
+       - surface inspector: removed all Q2 related stuff, fixed horizontal shift, reorganized the widgets layout
+               hooked the widgets to apply the changes on the fly (the inspectors need a good chunk of work)
+       - fixed a radiant.pid bug
+       - added icon to MSVC6 project (with some help)
+       
+       G_Dewan
+       - fix to BSP menu order getting mixed up
+       - fix to the file dialog
+
+11/09/2000
+       - Added splash screen
+
+25/08/2000 TTimo
+       - launch sleep mode before running game
+       - fixed Map_Snapshot bug
+       - going to sleep works on view n2, raising is still screwed (contexts)
+
+24/08/2000 TTimo
+       - fixed some sleep mode stuff
+       - fixed map snapshot bug
+
+21/08/2000
+       - fixed stuff to build on linux
+       - Merged in q3map 1.0p
+
+18/08/2000
+       - Removed "High Color Textures" option (always on)
+       - Removed "Status Point Size" option
+
+17/08/2000
+       - Fixed win32 console issues
+
+16/08/2000
+       - added g_strTempPath
+       - restore maximized window state
+       - fixed logo.bmp
+
+15/08/2000 TTimo
+       - fixed keyboard shortcuts
+       - fixed engine path in prefs (must use the file dialog to change)
+       - fixed a bug related to engine path and project templates
+
+15/08/2000
+       - Removed QE4 update model option (always on)
+       - Removed Buggy ICD option (always off)
+       - Reorganized the preferences dialog to take a bit less space
+
+14/08/2000 TTimo
+       - using profile.cpp code to read shortcut keys files
+       - moved DevDocs/changelog.txt to data/changelog.txt
+               (data/ should be used for user-side stuff and DevDocs/ for developpers)
+       - added data/quickstart.txt with a beginning of info about the main differences
+               between Q3Radiant 202 and GtkRadiant. to be used as a doc later.
+
+13/08/2000 TTimo
+       - added DevDocs/WIN32SETUP and DevDocs/changelog.txt
+               changelog.txt is end user changes
+               WIN32SETUP the TODO list for install specific stuff
+       - wrapped a first version of the win32 installers (full and patch)
+
+11/08/2000 TTimo
+       - quickfix to put undo/redo back in
+       - added DevDocs/WIN32SETUP, describes what I'm up to with the setup of win32 version
+
+10/08/2000 TTimo
+       - added back the window position saving code that was in earlier tree
+               NOTE: would have rather have it done in prefs than hooked in mainframe_delete and MainFrame::Create
+               (would have been cleaner IMO)
+               NOTE: IT'S STILL BROKEN .. I ADDED THE CODE BUT I MUST BE MISSING SOMETHING
+               NOTE: it doesn't remember the maximized state. It should.
+
+08/08/2000 TTimo
+       - fixed win32 build for GLWidget code, added WINAPI calling convention on all exported stuff
+       - fixed TexTool to compile under win32
+
+07/08/2000 TTimo
+       - fixed some crash with the new jpeg lib
+       - fixed console logging behaviour (was always turned on at startup)
+       - added console logging checkbutton in prefs
+
+07/08/2000
+       - Merged the GLWidget branch
+       - Merged 202 patches
+       - Fixed "clean" button in the preferences dialog
+       - Added pid startup detection
+       - Updated plugin interface with GLWidget functions
+       - Updated TexTool plugin
+
+04/08/2000
+       - Added "errno" string to the Error() message box
+       - More 202 patches
+
+03/08/2000
+       - Merged changes from MFC Radiant 202
+        - Fixed the win32 GLWidget stuff
+02/08/2000
+        - new OpenGL widget to keep all platform specific code in only one file
+
+01/08/2000
+       - Added code to restore the windows when coming out of sleep mode
+       - Rewrote the TexTool plugin
+
+31/07/2000 TTimo
+       - added vc6 projects for PrtView
+       - tested PrtView and Radiant against latest binary release of Gtk (works great)
+
+       Leo:
+       - Updated VC5 projects
+       - Fixed plugin loading under win32
+       - Updated PrtView to compile under win32
+       - Radiant is now iconified when going in sleep mode
+
+30/07/2000 TTimo
+       - prefs dialog for BSP monitoring
+       - Added data/ directory with entities.def and quakev2.qe4
+       - stabilized syntax of v2 project file, same project file for both platforms
+       - added DevDocs/WIN32BETA with a list of stuff to do before going on public beta on win32
+       - added DevDocs/d2u .. handy script to remove linefeeds from DOS files
+       - added radiant/radiant.proj, project file for source navigator (SN rules)
+
+       Leo:
+       - Fixed the logfile crash when ~/.q3a/radiant doesn't exist (fenris #1953)
+
+28/07/2000 TTimo
+       - Fix to the win32 console to use window's default font
+       - Added File > Sleep for experimentation
+               NOTE: we need to keep Radiant minimized when going into sleep mode
+
+28/07/2000
+       - Finished the win32 console replacement
+       - Fixed bug 1952 (map loading segfault)
+       - Added a Makefile to the libs dir
+
+26/07/2000
+       - Added PrtView plugin
+       - Added qvm target to source/Makefile
+       - Another release candidate sent to QA
+
+18/07/2000
+       - Fixed the slow updates issue in the win32 version
+       - Added 3 new variables to fix the paths issue
+
+17/07/2000
+       - Fixed the plugin search directory (broken with the changes to g_strAppPath)
+
+14/07/2000
+       - Increased the timer speed in MainFrame::RoutineProcessing
+       - Added code to release and recreate the contexts to the win32 version
+       - Fixed the mouse capture under win32
+
+13/07/2000
+       - Fixed the new path and bsp problems
+       - Sent new version to QA for testing/release
+
+12/07/2000
+       - Added "tools/" back to g_strAppPath under linux
+
+11/07/2000
+       - Added code to release and the recreate the GL contexts (linux)
+
+10/07/2000
+       - Changed directory structure
+
+09/07/2000
+       - Added CS_OWNDC for win32 with a GDK hack
+
+07/07/2000
+       - Fixed "white textures" bug (gluBuild2DMipmaps bug)
+
+03/07/2000
+TTimo:  - main.cpp l386, removed tools/ appending to g_strAppPath, g_strAppPath is expected to point to the app.. (hope it doesn't break anything)
+
+02/07/2000
+       - Added precompiled headers for faster win32 builds
+
+01/07/2000
+       - Finally got q3asm/lcc working
+
+26/06/2000
+       - 201 patches
+       - Added screenshot option
+       - Added an error message if X is running in 8 bits
+
+23/06/2000
+       - Updated with build 200 source
+
+13/06/2000
+       - Remove --noshare option
+       - Added --nofonts option to workaround a bug using glXUseXFonts in XFree 4.0
+
+04/06/2000
+       - Fixed bug with the Ctrl-X accelerator for the File/Exit menu
+
+02/06/2000
+       - Converting the TexTool plugin
+
+30/05/2000
+       - Changes to the plugin loading code
+
+28/05/2000
+       - Files with an underscore character are now correctly parsed in the MRU menu
+
+25/05/2000
+       - Fixed _exit bugs
+       - Fixed bug in CMapStringToString::SetAt
+       - Fixed copy/paste/clone bug
+
+24/05/2000
+       - Finished applying the 199 patches
+       - Fixed a bug in CShaderArray::SortShaders() that was calling the wrong version of InsertAt()
+       - Added numbers to the MRU menu items
+
+23/05/2000
+       - Fixed the floating point bug in gluBuild2DMipmaps
+       - Fixed the time display after a bsp command is executed
+       - Applied several patches from the 199 version
+       - The console is now visible by default
+
+21/05/2000
+       - Added a replacement for gluBuild2DMipmaps
+
+20/05/2000
+       - Fixed the repeating textures bug when playing a map, "brush_primit" must be set to "1".
+       - Fixed the bug about no current GL context when exiting in computers with 3dfx cards.
+       - Textures in the directory pointed by "texturepath" are now loaded correctly in Radiant.
+       - Fixed bug in q3map where it would require a shaderlist.txt file in ~/.q3a/baseq3/scripts.
+
+19/05/2000
+       - Fixed a bug in the multiple directories hack in libs/pakstuff.cc
+       - Finished the filter in the texture window
+       - The wait cursor is now correctly set in the XY window
+       - Added replacements for gluPerspective and gluLookAt
+       - Textures can now be stored in 2 places:
+       * The path pointed by "texturepath" (defaults to ~/.q3a/baseq3/textures,
+         but can be changed in the project settings)
+       * The base texture path (<install_path>/baseq3/textures)
+       - Radiant and the q3map tool now looks for shaders in ~/.q3a/baseq3/shaderlist.txt
+          and <install_path>/baseq3/scripts/shaderlist.txt
+
+18/05/2000
+       - Plugin menu fixes
+       - Created a simple text editor to edit the shaders (instead of calling an external program)
+       - Copy and paste now work
+       - Fixed some bugs with the MRU menu
+       - Some menu items are now enabled/disabled correctly in MainFrame::RoutineProcessing () 
+       - Added a new command line option (--cdpath) to set the CD-ROM path
+       - Fixed some bugs in the entity window, now it's possible to add/edit/remove properties
+       - New directory paths:
+       * maps now default to ~/.q3a/baseq3/maps
+       * autosave files are saved in ~/.q3a/baseq3/maps
+       * .pk3 files can be in ~/.q3a/baseq3, <install_path>/baseq3 and in the CD-ROM
+
+17/05/2000
+       - Fixed bug deselecting a brush after the surface dialog is open
+       - hide cursor when right-dragging XYWnd
+       - files saved to /tmp are now saved in ~/.q3a/radiant
+       - Disabled undo
+       - Fixed a bug in FillTextureMenu
+       - User can now correctly change the accelerators at run-time
+       - Accelerators are read from ~/.q3a/radiant/radiant.ini
+
+16/05/2000
+       - Finished the patch inspector
+       - Finished the texture toolbar
+       - more small bug fixes
+
+11/05/2000
+       - Finished the GroupDlg stuff
+       - Added support to read pak files from the Quake3 CD-ROM
+       - moved /tmp/paklog.txt to ~/.q3a/radiant/paklog
+       - added functions to replace GetKeyState and SetCursorPos
+       - fixed the command key handlers for the mainwindow
diff --git a/oldstuff/DoxyConfig b/oldstuff/DoxyConfig
new file mode 100644 (file)
index 0000000..b9c0619
--- /dev/null
@@ -0,0 +1,47 @@
+# Included Doxygen Config file
+#---------------------------------------------------------------------------
+# Project name & version number
+#---------------------------------------------------------------------------
+PROJECT_NAME           = 
+PROJECT_NUMBER         = 
+
+#---------------------------------------------------------------------------
+# Where to put the output
+# Note: The images dir should be next to the created html dir within the
+#      output dir.
+#       eg;
+#       [Current Dir]
+#               L__[OUTPUT_DIRECTORY]
+#                      L__[html]
+#                      L__[images]
+#---------------------------------------------------------------------------
+OUTPUT_DIRECTORY       = ../GtkRadiant-doxygen
+
+#---------------------------------------------------------------------------
+# Where to read the sources
+# you can add more than one source...
+# INPUT                   = radiant/ \
+#                           tools/quake3/q3map \
+#                           tools/quake3/q3data
+#
+# Recursive is set on, so setting it to ./ (current dir) would read source
+# files recursively from the current dir down. (which would take a while)
+#
+# eg: To document just include, if the current directory is ../GtkRadiant/ 
+# then...
+#---------------------------------------------------------------------------
+INPUT                  = radiant/
+
+#---------------------------------------------------------------------------
+# Misc settings
+# TAB_SIZE     - sets the indenting for the inline source and the source 
+#                browser
+# INCLUDE_PATH - will include documentation for included files from other
+#                packages. You can specify more than one path the same as
+#                shown in the INPUT example Leave it blank if you don't want 
+#                this.
+# PERL_PATH    - path to the perl executable
+#
+#---------------------------------------------------------------------------
+PERL_PATH              = /usr/bin/perl
+
diff --git a/oldstuff/Doxyfile b/oldstuff/Doxyfile
new file mode 100644 (file)
index 0000000..b87c164
--- /dev/null
@@ -0,0 +1,1117 @@
+# Doxyfile 1.3.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = GtkRadiant
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 1.5.0
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doxygen-out
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, 
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en 
+# (Japanese with English messages), Korean, Korean-en, Norwegian, Polish, Portuguese, 
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# This tag can be used to specify the encoding used in the generated output. 
+# The encoding is not always determined by the language that is chosen, 
+# but also whether or not the output is meant for Windows or non-Windows users. 
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
+# forces the Windows encoding (this is the default for the Windows binary), 
+# whereas setting the tag to NO uses a Unix-style encoding (the default for 
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING   = YES
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is used 
+# as the annotated text. Otherwise, the brief description is used as-is. If left 
+# blank, the following values are used ("$name" is automatically replaced with the 
+# name of the entity): "The $name class" "The $name widget" "The $name file" 
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited 
+# members of a class in the documentation of that class as if those members were 
+# ordinary class members. Constructors, destructors and assignment operators of 
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. It is allowed to use relative paths in the argument list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like the Qt-style comments (thus requiring an 
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF      = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources 
+# only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
+# only. Doxygen will then generate output that is more tailored for Java. 
+# For instance, namespaces will be presented as packages, qualified scopes 
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = NO
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = radiant/ plugins/ libs/ include/
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp 
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories 
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories.
+
+EXCLUDE_PATTERNS       = */.svn/*
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = radiant/ plugins/ libs/ include/
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = YES
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = doxygen-xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = NO
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse the 
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. Note that this 
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is 
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# generate a call dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable call graphs for selected 
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes that 
+# lay further from the root node will be omitted. Note that setting this option to 
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also 
+# note that a graph may be further truncated if the graph's image dimensions are 
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). 
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/oldstuff/branch-manager b/oldstuff/branch-manager
new file mode 100755 (executable)
index 0000000..2fd5a8f
--- /dev/null
@@ -0,0 +1,344 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+sub OutputOf($@)
+{
+       my ($cmd, @args) = @_;
+       $cmd =~ s/#(\d)/"\$ARG$1"/g;
+       $ENV{"ARG$_"} = $args[$_-1]
+               for 1..@args;
+
+       open my $fh, '-|', $cmd
+               or die "popen $cmd: $!";
+
+       $ENV{"ARG$_"} = ''
+               for 1..@args;
+
+       undef local $/;
+       my $ret = <$fh>;
+       close $fh;
+
+       return $ret;
+}
+
+my %conf = 
+(
+       master => '',
+       revisions_applied => ''
+);
+my @revisions_applied = (); # array of [first, last] ranges
+
+sub LoadSettings()
+{
+       open my $fh, '<', ".patchsets"
+               or return;
+       while(<$fh>)
+       {
+               chomp;
+               /^([^=]*?)\s*=\s*(.*?)$/s
+                       or next;
+               die "Invalid config item: $1 (allowed: @{[sort keys %conf]})"
+                       if not exists $conf{$1};
+               $conf{$1} = $2;
+       }
+
+       @revisions_applied = map { /^(\d+)-(\d+)$/s or die "Invalid revision spec $_"; [$1, $2]; } split /,/, $conf{revisions_applied};
+}
+
+sub WriteSettings()
+{
+       $conf{revisions_applied} = join ',', map { "$_->[0]-$_->[1]" } @revisions_applied;
+
+       open my $fh, '>', ".patchsets"
+               or die "writing settings: $!";
+       for(sort keys %conf)
+       {
+               print $fh "$_ = $conf{$_}\n";
+       }
+}
+
+sub AddPatch($$)
+{
+       my ($first, $last) = @_;
+       die "Invalid range" if $first > $last;
+
+       my @rev = sort { $a->[0] <=> $b->[0] } (@revisions_applied, [$first, $last]);
+
+       my $i = 0;
+       while($i < @rev - 1)
+       {
+               my $a = $rev[$i][0];
+               my $b = $rev[$i][1];
+               my $c = $rev[$i+1][0];
+               my $d = $rev[$i+1][1];
+
+               if($b >= $c)
+               {
+                       die "overlapping patch: $a-$b overlaps $c-$d";
+               }
+               if($b == $c - 1)
+               {
+                       splice @rev, $i, 2, [$a, $d];
+                       next;
+               }
+               ++$i;
+       }
+
+       @revisions_applied = @rev;
+}
+
+sub RemovePatch($$)
+{
+       my ($first, $last) = @_;
+       die "Invalid range" if $first > $last;
+
+       my @rev = sort { $a->[0] <=> $b->[0] } (@revisions_applied);
+
+       my $i = 0;
+       while($i < @rev)
+       {
+               my $a = $rev[$i][0];
+               my $b = $rev[$i][1];
+
+               if($first >= $a && $last <= $b)
+               {
+                       # this is the range
+                       my @replacement;
+
+                       if($first == $a && $last == $b)
+                       {
+                               @replacement = ();
+                       }
+                       elsif($first == $a)
+                       {
+                               @replacement = ([$last + 1, $b]);
+                       }
+                       elsif($last == $b)
+                       {
+                               @replacement = ([$a, $first - 1]);
+                       }
+                       else
+                       {
+                               @replacement = ([$a, $first - 1], [$last + 1, $b]);
+                       }
+                       splice @rev, $i, 1, @replacement;
+                       @revisions_applied = @rev;
+                       return;
+               }
+       }
+
+       die "could not remove range: not in set";
+}
+
+sub GetUnappliedRanges($)
+{
+       my ($lastrev) = @_;
+       my @unapplied = ();
+
+       my $cur = 0;
+       for(@revisions_applied)
+       {
+               my ($a, $b) = @$_;
+               if($a - 1 >= $cur + 1)
+               {
+                       push @unapplied, [$cur + 1, $a - 1];
+               }
+               $cur = $b;
+       }
+       if($lastrev >= $cur + 1)
+       {
+               push @unapplied, [$cur + 1, $lastrev];
+       }
+       return @unapplied;
+}
+
+sub GetMasterRev()
+{
+       my $svninfo = OutputOf 'svn info #1', $conf{master};
+       $svninfo =~ /^Last Changed Rev: (\d+)$/m
+               or die "could not get svn info";
+       return $1;
+}
+
+sub GetLog($$)
+{
+       my ($first, $last) = @_;
+       my $log = OutputOf 'svn log -r#1:#2 #3', $first, $last, $conf{master};
+       $log =~ s/^-*$//gm;
+       $log =~ s/\n+/\n/gs;
+       $log =~ s/^\n//s;
+       $log =~ s/\n$//s;
+       return $log;
+}
+
+sub GetDiff($$)
+{
+       my ($first, $last) = @_;
+       return OutputOf 'svn diff -r#1:#2 #3', $first-1, $last, $conf{master};
+}
+
+my ($cmd, @args) = @ARGV;
+$cmd = 'help' if not defined $cmd;
+
+if($cmd eq 'info')
+{
+       LoadSettings();
+       for(@revisions_applied)
+       {
+               my ($a, $b) = @$_;
+               print "Applied: $a to $b\n";
+       }
+       for(GetUnappliedRanges(GetMasterRev()))
+       {
+               my ($a, $b) = @$_;
+               print "Unapplied: $a to $b\n";
+       }
+}
+elsif($cmd eq 'unmerged-diff')
+{
+       LoadSettings();
+       my @autoadd = ();
+       for(GetUnappliedRanges(GetMasterRev()))
+       {
+               my ($a, $b) = @$_;
+               my $log = GetLog $a, $b;
+               if($log eq '')
+               {
+                       push @autoadd, [$a, $b];
+                       next;
+               }
+               $log =~ s/^/  /gm;
+               print "Unapplied: $a to $b\n";
+               print "$log\n";
+               print GetDiff $a, $b;
+               print "\n";
+       }
+       for(@autoadd)
+       {
+               my ($a, $b) = @$_;
+               print "Autofilled revision hole $a to $b\n";
+               AddPatch $a, $b;
+       }
+       WriteSettings() if @autoadd;
+}
+elsif($cmd eq 'unmerged')
+{
+       LoadSettings();
+       my @autoadd = ();
+       for(GetUnappliedRanges(GetMasterRev()))
+       {
+               my ($a, $b) = @$_;
+               my $log = GetLog $a, $b;
+               if($log eq '')
+               {
+                       push @autoadd, [$a, $b];
+                       next;
+               }
+               $log =~ s/^/  /gm;
+               print "Unapplied: $a to $b\n";
+               print "$log\n\n";
+       }
+       for(@autoadd)
+       {
+               my ($a, $b) = @$_;
+               print "Autofilled revision hole $a to $b\n";
+               AddPatch $a, $b;
+       }
+       WriteSettings() if @autoadd;
+}
+elsif($cmd eq 'merge')
+{
+       my ($first, $last, $force) = @args;
+       die "Usage: $0 merge first last [--force]"
+               if not defined $first;
+       $last = $first if not defined $last;
+
+       die "Usage: $0 merge first last"
+               if "$first$last" =~ /[^0-9]/;
+
+       die "There is an uncommitted merge"
+               if -f '.commitmsg' and $force ne '--force';
+
+       LoadSettings();
+       AddPatch $first, $last;
+
+       print OutputOf 'svn merge -r#1:#2 #3', ($first - 1), $last, $conf{master};
+       print "You may also want to run $0 unmerged to fill possible revision holes\n";
+       print "Make sure there are no conflicts, then run $0 commit\n";
+       print "To abort, use $0 revert\n";
+       
+       open my $fh, '>>', '.commitmsg'
+               or die "open .commitmsg";
+       print $fh GetLog $first, $last;
+       print $fh "\n";
+       close $fh;
+
+       WriteSettings();
+}
+elsif($cmd eq 'undo')
+{
+       my ($first, $last, $force) = @args;
+       die "Usage: $0 undo first last"
+               if not defined $first;
+       $last = $first if not defined $last;
+
+       die "Usage: $0 merge first last"
+               if "$first$last" =~ /[^0-9]/;
+
+       die "There is an uncommitted merge"
+               if -f '.commitmsg' and $force ne '--force';
+
+       LoadSettings();
+       RemovePatch $first, $last;
+
+       print OutputOf 'svn merge -r#2:#1 #3', ($first - 1), $last, $conf{master};
+       print "Make sure there are no conflicts, then run $0 commit\n";
+       print "To abort, use $0 revert\n";
+
+       open my $fh, '>>', '.commitmsg'
+               or die "open .commitmsg";
+       print $fh "undo the following merge:\n", GetLog $first, $last;
+       close $fh;
+
+       WriteSettings();
+}
+elsif($cmd eq 'commit')
+{
+       system 'vim .commitmsg';
+       print "Hit Enter if OK to commit, Ctrl-C otherwise...\n";
+       my $ok = <STDIN>;
+       if(!system 'svn commit -F .commitmsg')
+       {
+               unlink '.commitmsg';
+       }
+}
+elsif($cmd eq 'revert')
+{
+       if(!system 'svn revert -R .')
+       {
+               unlink '.commitmsg';
+       }
+}
+elsif($cmd eq 'init')
+{
+       my ($master, $rev) = @args;
+       $conf{master} = $master;
+       @revisions_applied = [1, $rev];
+       WriteSettings();
+}
+else
+{
+       print <<EOF;
+Usage:
+  $0 init masterrepo rev
+  $0 info
+  $0 unmerged
+  $0 unmerged-diff
+  $0 merge rev1 [rev2] [--force]
+  $0 undo rev1 [rev2] [--force]
+  $0 commit
+  $0 revert
+EOF
+}
diff --git a/oldstuff/cross-Makefile.conf b/oldstuff/cross-Makefile.conf
new file mode 100644 (file)
index 0000000..caba2e6
--- /dev/null
@@ -0,0 +1,10 @@
+# Usage:
+# copy this file to Makefile.conf
+# edit the paths in here
+
+# how to call the mingw tools
+MINGW_EXEC_PREFIX = i486-mingw32-
+
+# use mingw32
+include mingw-Makefile.inc
+include mingw-radiantdeps-Makefile.inc
diff --git a/oldstuff/generic_cpp.py b/oldstuff/generic_cpp.py
new file mode 100644 (file)
index 0000000..62d51ed
--- /dev/null
@@ -0,0 +1,40 @@
+# Copyright (C) 2001-2006 William Joseph.
+# For a list of contributors, see the accompanying CONTRIBUTORS file.
+# 
+# This file is part of GtkRadiant.
+# 
+# GtkRadiant is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# GtkRadiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GtkRadiant; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+import os
+import sys
+
+def svnAddText(filename):
+  os.system("svn add " + filename);
+  os.system("svn ps svn:eol-style native " + filename);
+
+def createCPPTemplate(filename, name):
+  file = open(filename, "wt")
+  file.write("\n")
+  file.write("#include \"" + name + ".h\"\n")
+  file.write("\n")
+  file.close()
+
+if __name__ == "__main__":
+  name = sys.argv[1]
+  location = sys.argv[2]
+  filename = os.path.join(location, name + ".cpp")
+  createCPPTemplate(filename, name)
+  svnAddText(filename)
diff --git a/oldstuff/generic_h.py b/oldstuff/generic_h.py
new file mode 100644 (file)
index 0000000..9f8b7e9
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright (C) 2001-2006 William Joseph.
+# For a list of contributors, see the accompanying CONTRIBUTORS file.
+# 
+# This file is part of GtkRadiant.
+# 
+# GtkRadiant is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# GtkRadiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GtkRadiant; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+import os
+import sys
+
+def svnAddText(filename):
+  os.system("svn add " + filename);
+  os.system("svn ps svn:eol-style native " + filename);
+
+def createHeaderTemplate(filename, name):
+  file = open(filename, "wt")
+  file.write("\n")
+  file.write("#if !defined(_INCLUDED_" + name.upper() + "_H_)\n")
+  file.write("#define _INCLUDED_" + name.upper() + "_H_\n")
+  file.write("\n")
+  file.write("#endif\n")
+
+if __name__ == "__main__":
+  name = sys.argv[1]
+  location = sys.argv[2]
+  filename = os.path.join(location, name + ".h")
+  createHeaderTemplate(filename, name)
+  svnAddText(filename)
diff --git a/oldstuff/generic_module.py b/oldstuff/generic_module.py
new file mode 100644 (file)
index 0000000..e055e8f
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright (C) 2001-2006 William Joseph.
+# For a list of contributors, see the accompanying CONTRIBUTORS file.
+# 
+# This file is part of GtkRadiant.
+# 
+# GtkRadiant is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# GtkRadiant is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with GtkRadiant; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+import os
+import sys
+
+def svnAddText(filename):
+  os.system("svn add " + filename);
+  os.system("svn ps svn:eol-style native " + filename);
+
+def createHeaderTemplate(filename, name):
+  file = open(filename, "wt")
+  file.write("\n")
+  file.write("#if !defined(INCLUDED_" + name.upper() + "_H)\n")
+  file.write("#define INCLUDED_" + name.upper() + "_H\n")
+  file.write("\n")
+  file.write("#endif\n")
+
+def createCPPTemplate(filename, name):
+  file = open(filename, "wt")
+  file.write("\n")
+  file.write("#include \"" + name + ".h\"\n")
+  file.write("\n")
+  file.close()
+
+if __name__ == "__main__":
+  if not len(sys.argv) == 2:
+    print "usage: " + sys.argv[0] + " <module-path>"
+    
+  path = sys.argv[1]
+  name = os.path.split(path)[1];
+  
+  h = os.path.normpath(path + ".h")
+  print "writing " + h;
+  createHeaderTemplate(h, name)
+  svnAddText(h)
+
+  cpp = os.path.normpath(path + ".cpp")
+  print "writing " + cpp;
+  createCPPTemplate(cpp, name)
+  svnAddText(cpp)
+  
diff --git a/oldstuff/install-dlls-fedora.sh b/oldstuff/install-dlls-fedora.sh
new file mode 100755 (executable)
index 0000000..5f88229
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+set -x
+
+DLL_PATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
+
+cd install
+
+STARTDIR=`pwd`
+
+COPYDEPS() 
+{
+       FILE=$1
+       if [ -e "$FILE" ] ;then
+               DEPS=`objdump -p "$FILE" 2>/dev/null |grep -i "DLL Name"|sort |uniq|cut -d\  -f3 |egrep -vi '(GDI32.dll|KERNEL32.dll|USER32.dll|msvcrt.dll|MSIMG32.DLL|ole32.dll|OPENGL32.DLL|SHELL32.DLL|WS2_32.dll)' || true`
+                               
+               for DEP in $DEPS; do
+                       basename -a "$STARTDIR"/*.dll | grep -v "*.dll"|sort >  "$STARTDIR"/.HAVES
+                       if ! cat "$STARTDIR"/.HAVES | grep "$DEP" >/dev/null ;then
+                               cp -v "$DLL_PATH"/"$DEP" "$STARTDIR" 2>/dev/null
+                               COPYDEPS "$DLL_PATH"/"$DEP"
+                       fi
+                       rm -f "$STARTDIR"/.HAVES
+               done
+       fi
+}
+
+for i in *.exe;do
+       COPYDEPS "$i";
+done
+
diff --git a/oldstuff/install-dlls.sh b/oldstuff/install-dlls.sh
new file mode 100755 (executable)
index 0000000..60ca8db
--- /dev/null
@@ -0,0 +1,196 @@
+#!/bin/sh
+
+set -ex
+
+: ${WHICHDLL:=which}
+: ${GTKDIR:=/gtk}
+: ${CP:=cp}
+: ${CAT:=cat}
+: ${MKDIR:=mkdir -p}
+: ${INSTALLDIR:=.}
+
+for DLL in \
+       freetype6.dll \
+       intl.dll \
+       libatk-1.0-0.dll \
+       libcairo-2.dll \
+       libexpat-1.dll \
+       libfontconfig-1.dll \
+       libgdkglext-win32-1.0-0.dll \
+       libgdk_pixbuf-2.0-0.dll \
+       libgdk-win32-2.0-0.dll \
+       libgio-2.0-0.dll \
+       libglib-2.0-0.dll \
+       libgmodule-2.0-0.dll \
+       libgobject-2.0-0.dll \
+       libgthread-2.0-0.dll \
+       libgtkglext-win32-1.0-0.dll \
+       libgtk-win32-2.0-0.dll \
+       libjpeg-8.dll \
+       libpango-1.0-0.dll \
+       libpangocairo-1.0-0.dll \
+       libpangoft2-1.0-0.dll \
+       libpangowin32-1.0-0.dll \
+       libpng14-14.dll \
+       libxml2-2.dll \
+       zlib1.dll \
+       libgcc_s_sjlj-1.dll \
+       libstdc++-6.dll \
+; do
+       $CP "`$WHICHDLL $DLL`" $INSTALLDIR/
+done
+
+$MKDIR $INSTALLDIR/etc/fonts
+$CAT > $INSTALLDIR/etc/fonts/fonts.conf <<EOF
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<!-- /etc/fonts/fonts.conf file to configure system font access -->
+<fontconfig>
+
+<!--
+       DO NOT EDIT THIS FILE.
+       IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
+       LOCAL CHANGES BELONG IN 'local.conf'.
+
+       The intent of this standard configuration file is to be adequate for
+       most environments.  If you have a reasonably normal environment and
+       have found problems with this configuration, they are probably
+       things that others will also want fixed.  Please submit any
+       problems to the fontconfig bugzilla system located at fontconfig.org
+
+       Note that the normal 'make install' procedure for fontconfig is to
+       replace any existing fonts.conf file with the new version.  Place
+       any local customizations in local.conf which this file references.
+
+       Keith Packard
+-->
+
+<!-- Font directory list -->
+
+       <dir>WINDOWSFONTDIR</dir>
+       
+       <dir>~/.fonts</dir>
+
+<!--
+  Accept deprecated 'mono' alias, replacing it with 'monospace'
+-->
+       <match target="pattern">
+               <test qual="any" name="family">
+                       <string>mono</string>
+               </test>
+               <edit name="family" mode="assign">
+                       <string>monospace</string>
+               </edit>
+       </match>
+
+<!--
+  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
+-->
+       <match target="pattern">
+               <test qual="any" name="family">
+                       <string>sans serif</string>
+               </test>
+               <edit name="family" mode="assign">
+                       <string>sans-serif</string>
+               </edit>
+       </match>
+
+<!--
+  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
+-->
+       <match target="pattern">
+               <test qual="any" name="family">
+                       <string>sans</string>
+               </test>
+               <edit name="family" mode="assign">
+                       <string>sans-serif</string>
+               </edit>
+       </match>
+
+<!--
+  Load local system customization file
+-->
+       <include ignore_missing="yes">conf.d</include>
+
+<!-- Font cache directory list -->
+
+       <cachedir>WINDOWSTEMPDIR_FONTCONFIG_CACHE</cachedir>
+       <cachedir>~/.fontconfig</cachedir>
+
+       <config>
+<!--
+  These are the default Unicode chars that are expected to be blank
+  in fonts.  All other blank chars are assumed to be broken and
+  won't appear in the resulting charsets
+ -->
+               <blank>
+                       <int>0x0020</int>       <!-- SPACE -->
+                       <int>0x00A0</int>       <!-- NO-BREAK SPACE -->
+                       <int>0x00AD</int>       <!-- SOFT HYPHEN -->
+                       <int>0x034F</int>       <!-- COMBINING GRAPHEME JOINER -->
+                       <int>0x0600</int>       <!-- ARABIC NUMBER SIGN -->
+                       <int>0x0601</int>       <!-- ARABIC SIGN SANAH -->
+                       <int>0x0602</int>       <!-- ARABIC FOOTNOTE MARKER -->
+                       <int>0x0603</int>       <!-- ARABIC SIGN SAFHA -->
+                       <int>0x06DD</int>       <!-- ARABIC END OF AYAH -->
+                       <int>0x070F</int>       <!-- SYRIAC ABBREVIATION MARK -->
+                       <int>0x115F</int>       <!-- HANGUL CHOSEONG FILLER -->
+                       <int>0x1160</int>       <!-- HANGUL JUNGSEONG FILLER -->
+                       <int>0x1680</int>       <!-- OGHAM SPACE MARK -->
+                       <int>0x17B4</int>       <!-- KHMER VOWEL INHERENT AQ -->
+                       <int>0x17B5</int>       <!-- KHMER VOWEL INHERENT AA -->
+                       <int>0x180E</int>       <!-- MONGOLIAN VOWEL SEPARATOR -->
+                       <int>0x2000</int>       <!-- EN QUAD -->
+                       <int>0x2001</int>       <!-- EM QUAD -->
+                       <int>0x2002</int>       <!-- EN SPACE -->
+                       <int>0x2003</int>       <!-- EM SPACE -->
+                       <int>0x2004</int>       <!-- THREE-PER-EM SPACE -->
+                       <int>0x2005</int>       <!-- FOUR-PER-EM SPACE -->
+                       <int>0x2006</int>       <!-- SIX-PER-EM SPACE -->
+                       <int>0x2007</int>       <!-- FIGURE SPACE -->
+                       <int>0x2008</int>       <!-- PUNCTUATION SPACE -->
+                       <int>0x2009</int>       <!-- THIN SPACE -->
+                       <int>0x200A</int>       <!-- HAIR SPACE -->
+                       <int>0x200B</int>       <!-- ZERO WIDTH SPACE -->
+                       <int>0x200C</int>       <!-- ZERO WIDTH NON-JOINER -->
+                       <int>0x200D</int>       <!-- ZERO WIDTH JOINER -->
+                       <int>0x200E</int>       <!-- LEFT-TO-RIGHT MARK -->
+                       <int>0x200F</int>       <!-- RIGHT-TO-LEFT MARK -->
+                       <int>0x2028</int>       <!-- LINE SEPARATOR -->
+                       <int>0x2029</int>       <!-- PARAGRAPH SEPARATOR -->
+                       <int>0x202A</int>       <!-- LEFT-TO-RIGHT EMBEDDING -->
+                       <int>0x202B</int>       <!-- RIGHT-TO-LEFT EMBEDDING -->
+                       <int>0x202C</int>       <!-- POP DIRECTIONAL FORMATTING -->
+                       <int>0x202D</int>       <!-- LEFT-TO-RIGHT OVERRIDE -->
+                       <int>0x202E</int>       <!-- RIGHT-TO-LEFT OVERRIDE -->
+                       <int>0x202F</int>       <!-- NARROW NO-BREAK SPACE -->
+                       <int>0x205F</int>       <!-- MEDIUM MATHEMATICAL SPACE -->
+                       <int>0x2060</int>       <!-- WORD JOINER -->
+                       <int>0x2061</int>       <!-- FUNCTION APPLICATION -->
+                       <int>0x2062</int>       <!-- INVISIBLE TIMES -->
+                       <int>0x2063</int>       <!-- INVISIBLE SEPARATOR -->
+                       <int>0x206A</int>       <!-- INHIBIT SYMMETRIC SWAPPING -->
+                       <int>0x206B</int>       <!-- ACTIVATE SYMMETRIC SWAPPING -->
+                       <int>0x206C</int>       <!-- INHIBIT ARABIC FORM SHAPING -->
+                       <int>0x206D</int>       <!-- ACTIVATE ARABIC FORM SHAPING -->
+                       <int>0x206E</int>       <!-- NATIONAL DIGIT SHAPES -->
+                       <int>0x206F</int>       <!-- NOMINAL DIGIT SHAPES -->
+                       <int>0x2800</int>       <!-- BRAILLE PATTERN BLANK -->
+                       <int>0x3000</int>       <!-- IDEOGRAPHIC SPACE -->
+                       <int>0x3164</int>       <!-- HANGUL FILLER -->
+                       <int>0xFEFF</int>       <!-- ZERO WIDTH NO-BREAK SPACE -->
+                       <int>0xFFA0</int>       <!-- HALFWIDTH HANGUL FILLER -->
+                       <int>0xFFF9</int>       <!-- INTERLINEAR ANNOTATION ANCHOR -->
+                       <int>0xFFFA</int>       <!-- INTERLINEAR ANNOTATION SEPARATOR -->
+                       <int>0xFFFB</int>       <!-- INTERLINEAR ANNOTATION TERMINATOR -->
+               </blank>
+<!--
+  Rescan configuration every 30 seconds when FcFontSetList is called
+ -->
+               <rescan>
+                       <int>30</int>
+               </rescan>
+       </config>
+
+</fontconfig>
+EOF
diff --git a/oldstuff/install-dylibs.sh b/oldstuff/install-dylibs.sh
new file mode 100755 (executable)
index 0000000..6b9e530
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+set -ex
+
+: ${OTOOL:=otool}
+: ${CP:=cp}
+: ${INSTALLDIR:=.}
+: ${EXE:=ppc}
+: ${MACLIBDIR:=/sw/lib}
+: ${CAT:=cat}
+
+
+finkgetdeps()
+{
+       otool -L "$1" | grep "$MACLIBDIR" | while read -r LIB STUFF; do
+               [ -z "${LIB##*:}" ] && continue # first line
+               [ -f "$INSTALLDIR/${LIB##*/}" ] && continue
+               cp -vL "$LIB" "$INSTALLDIR"
+               finkgetdeps "$LIB"
+       done
+}
+
+
+finkgetdeps "$INSTALLDIR/radiant.$EXE"
+echo Warning: this only works if only ONE version of gtk-2.0 and pango is installed
+
+getlib()
+{
+       LAST=
+       for LIB in "$@"; do
+               [ -f "$LIB" ] || continue
+               LAST=$LIB
+       done
+       cp -L "$LAST" "$INSTALLDIR"
+       finkgetdeps "$LAST"
+}
+
+getlib "$MACLIBDIR"/gtk-2.0/*/loaders/libpixbufloader-bmp.so "$MACLIBDIR"/gdk-pixbuf-2.0/*/loaders/libpixbufloader-bmp.so
+getlib "$MACLIBDIR"/pango/*/modules/pango-basic-fc.so
+getlib "$MACLIBDIR"/pango/*/modules/pango-basic-x.so
+
+#cp -L "$MACLIBDIR"/../etc/fonts/fonts.conf "$INSTALLDIR"
+#cp -L "$MACLIBDIR"/../etc/fonts/fonts.dtd "$INSTALLDIR"
+#cp -L "$MACLIBDIR"/../etc/gtk-2.0/gdk-pixbuf.loaders "$INSTALLDIR"
+#cp -L "$MACLIBDIR"/../etc/pango/pangorc "$INSTALLDIR"
+
+$CAT > "$INSTALLDIR/../netradiant.sh" <<EOF
+#!/bin/sh
+
+MY_DIRECTORY="\${0%/*}" # cut off the script name
+MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off MacOS
+MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off Contents
+
+export DYLD_LIBRARY_PATH="\$MY_DIRECTORY/Contents/MacOS/install"
+export PANGO_RC_FILE="\$MY_DIRECTORY/Contents/MacOS/install/pangorc"
+export GDK_PIXBUF_MODULE_FILE="\$MY_DIRECTORY/Contents/MacOS/install/gdk-pixbuf.loaders"
+export FONTCONFIG_FILE="\$MY_DIRECTORY/Contents/MacOS/install/fonts.conf"
+
+cd "\$MY_DIRECTORY/Contents/MacOS/install"
+if [ -x /usr/bin/open-x11 ]; then
+       env LC_ALL="en_US.UTF-8" /usr/bin/open-x11 ./radiant.$EXE "$@" &
+else
+       env LC_ALL="en_US.UTF-8" ./radiant.$EXE "$@" &
+fi
+EOF
+
+chmod 755 "$INSTALLDIR/../netradiant.sh"
+
diff --git a/oldstuff/merge-from-zerowing.sh b/oldstuff/merge-from-zerowing.sh
new file mode 100755 (executable)
index 0000000..e8dc07e
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+basecommit=`git log --pretty=format:%H --grep=::zerowing-base`
+baserev=`git log --pretty=format:%s --grep=::zerowing-base | cut -d = -f 2 | cut -d ' ' -f 1`
+
+newbaserev=`svn info https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/ | grep ^Revision | cut -d ' ' -f 2`
+
+echo "$baserev -> $newbaserev"
+
+merge()
+{
+       if ! svn diff -r"$baserev":"$newbaserev" "$1" | git apply --reject --ignore-space-change --directory="$2"; then
+               if find . -name \*.rej | grep .; then
+                       echo "you have to fix these conflicts"
+                       bash
+                       echo "succeeded?"
+                       read -r LINE
+                       if [ x"$LINE" != x"y" ]; then
+                               exit 1
+                       fi
+               fi
+       fi
+}
+
+# GtkRadiant 1.5 changes
+git clean  -xdf
+
+# ZeroRadiant's q3map2 changes
+merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/branches/1.5 /
+merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk/tools/quake3 tools/quake3
+merge https://zerowing.idsoftware.com/svn/radiant/GtkRadiant/trunk/libs/picomodel libs/picomodel
+
+git commit -a -m"::zerowing-base=$newbaserev" -e
diff --git a/oldstuff/mingw-Makefile.conf b/oldstuff/mingw-Makefile.conf
new file mode 100644 (file)
index 0000000..a128182
--- /dev/null
@@ -0,0 +1,18 @@
+# Usage:
+# copy this file to Makefile.conf
+# edit the paths in here
+
+# how to get pkg-config
+PKGCONFIG ?= $(RADIANT_DEPENDENCIES_PREFIX)/gtk/bin/pkg-config.exe
+
+# extra utils
+GIT ?= $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/git
+SVN ?= $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/svn
+
+# these two need the "start" workaround, or they seem to crash (TODO figure out why)
+WGET ?= start $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/wget
+UNZIPPER ?= start $(RADIANT_DEPENDENCIES_PREFIX)/util/bin/unzip
+
+# use mingw32
+include mingw-Makefile.inc
+include mingw-radiantdeps-Makefile.inc
diff --git a/oldstuff/mingw-Makefile.inc b/oldstuff/mingw-Makefile.inc
new file mode 100644 (file)
index 0000000..d72cfe2
--- /dev/null
@@ -0,0 +1,15 @@
+# how to call the mingw tools
+MINGW_EXEC_PREFIX ?=
+
+# set the environment for make
+OS = Win32
+
+#CPPFLAGS_XML =
+#LIBS_XML = -lxml2
+
+CC = $(MINGW_EXEC_PREFIX)gcc
+CXX = $(MINGW_EXEC_PREFIX)g++
+LDD =
+RANLIB = $(MINGW_EXEC_PREFIX)ranlib
+AR = $(MINGW_EXEC_PREFIX)ar
+WINDRES = $(MINGW_EXEC_PREFIX)windres
diff --git a/oldstuff/mingw-fedora-Makefile.conf b/oldstuff/mingw-fedora-Makefile.conf
new file mode 100644 (file)
index 0000000..d957d4d
--- /dev/null
@@ -0,0 +1,17 @@
+# Usage:
+# copy this file to Makefile.conf
+# edit the paths in here
+
+# how to call the mingw tools
+MINGW_TARGET_ARCH=i686
+#MINGW_TARGET_ARCH=x86_64
+MINGW_EXEC_PREFIX = $(MINGW_TARGET_ARCH)-w64-mingw32-
+
+# use custom pkg-config
+PKGCONFIG = $(MINGW_EXEC_PREFIX)pkg-config
+
+# use custom dll install script
+DLLINSTALL = install-dlls-fedora.sh
+
+# use mingw32
+include mingw-Makefile.inc
diff --git a/oldstuff/mingw-radiantdeps-Makefile.inc b/oldstuff/mingw-radiantdeps-Makefile.inc
new file mode 100644 (file)
index 0000000..82e750e
--- /dev/null
@@ -0,0 +1,15 @@
+# where the dependencies package is extracted
+RADIANT_DEPENDENCIES_PREFIX = $(HOME)/netradiant-dependencies-mingw32/
+
+# run the prefix fixing tool
+IGNORETHIS := $(shell cd $(RADIANT_DEPENDENCIES_PREFIX) && ./fixprefix.sh)
+
+# set the environment for make
+CFLAGS +=
+CXXFLAGS +=
+CPPFLAGS += -I$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/include
+LDFLAGS += -L$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/lib
+CPPFLAGS += -I$(RADIANT_DEPENDENCIES_PREFIX)/gtk/include
+LDFLAGS += -L$(RADIANT_DEPENDENCIES_PREFIX)/gtk/lib
+PKG_CONFIG_PATH := $(RADIANT_DEPENDENCIES_PREFIX)/gtk/lib/pkgconfig:$(RADIANT_DEPENDENCIES_PREFIX)/radiantdeps/lib/pkgconfig:$(PKG_CONFIG_PATH)
+WHICHDLL = $(RADIANT_DEPENDENCIES_PREFIX)/whichdll.sh
diff --git a/oldstuff/uncrustify.cfg b/oldstuff/uncrustify.cfg
new file mode 100644 (file)
index 0000000..4951686
--- /dev/null
@@ -0,0 +1,925 @@
+# Uncrustify 0.44
+
+#
+# General options
+#
+
+# The type of line endings
+newlines                                 = lf       # auto/lf/crlf/cr
+
+# The original size of tabs in the input
+input_tab_size                           = 4        # number
+
+# The size of tabs in the output (only used if align_with_tabs=true)
+output_tab_size                          = 4        # number
+
+# The ascii value of the string escape char, usually 92 (\) or 94 (^). (Pawn)
+string_escape_char                       = 92       # number
+
+# Alternate string escape char for Pawn. Only works right before the quote char.
+string_escape_char2                      = 0        # number
+
+#
+# Indenting
+#
+
+# The number of columns to indent per level.
+# Usually 2, 3, 4, or 8.
+indent_columns                           = 4        # number
+
+# How to use tabs when indenting code
+# 0=spaces only
+# 1=indent with tabs, align with spaces
+# 2=indent and align with tabs
+indent_with_tabs                         = 2        # number
+
+# Whether to indent strings broken by '\' so that they line up
+indent_align_string                      = true    # false/true
+
+# The number of spaces to indent multi-line XML strings.
+# Requires indent_align_string=True
+indent_xml_string                        = 0        # number
+
+# Spaces to indent '{' from level
+indent_brace                             = 0        # number
+
+# Whether braces are indented to the body level
+indent_braces                            = false    # false/true
+
+# Disabled indenting function braces if indent_braces is true
+indent_braces_no_func                    = false    # false/true
+
+# Indent based on the size of the brace parent, ie 'if' => 3 spaces, 'for' => 4 spaces, etc.
+indent_brace_parent                      = false    # false/true
+
+# Whether the 'namespace' body is indented
+indent_namespace                         = false    # false/true
+
+# Whether the 'class' body is indented
+indent_class                             = false    # false/true
+
+# Whether to indent the stuff after a leading class colon
+indent_class_colon                       = false    # false/true
+
+# True:  indent continued function call parameters one indent level
+# False: align parameters under the open paren
+indent_func_call_param                   = false    # false/true
+
+# Same as indent_func_call_param, but for function defs
+indent_func_def_param                    = false    # false/true
+
+# Same as indent_func_call_param, but for function protos
+indent_func_proto_param                  = false    # false/true
+
+# Same as indent_func_call_param, but for class declarations
+indent_func_class_param                  = false    # false/true
+
+# Same as indent_func_call_param, but for class variable constructors
+indent_func_ctor_var_param               = false    # false/true
+
+# Double the indent for indent_func_xxx_param options
+indent_func_param_double                 = false    # false/true
+
+# The number of spaces to indent a continued '->' or '.'
+# Usually set to 0, 1, or indent_columns.
+indent_member                            = 0        # number
+
+# Spaces to indent single line ('//') comments on lines before code
+indent_sing_line_comments                = 0        # number
+
+# Spaces to indent 'case' from 'switch'
+# Usually 0 or indent_columns.
+indent_switch_case                       = 0        # number
+
+# Spaces to shift the 'case' line, without affecting any other lines
+# Usually 0.
+indent_case_shift                        = 0        # number
+
+# Spaces to indent '{' from 'case'.
+# By default, the brace will appear under the 'c' in case.
+# Usually set to 0 or indent_columns.
+indent_case_brace                        = 0        # number
+
+# Whether to indent comments found in first column
+indent_col1_comment                      = false    # false/true
+
+# How to indent goto labels
+#  >0 : absolute column where 1 is the leftmost column
+#  <=0 : subtract from brace indent
+indent_label                             = 1        # number
+
+# Same as indent_label, but for access specifiers that are followed by a colon
+indent_access_spec                       = 1        # number
+
+# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)
+indent_paren_nl                          = false    # false/true
+
+# Controls the indent of a close paren after a newline.
+# 0: Indent to body level
+# 1: Align under the open paren
+# 2: Indent to the brace level
+indent_paren_close                       = 0        # number
+
+# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren
+indent_comma_paren                       = false    # false/true
+
+# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren
+indent_bool_paren                        = false    # false/true
+
+# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)
+indent_square_nl                         = false    # false/true
+
+# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies
+indent_preserve_sql                      = false    # false/true
+
+#
+# Spacing options
+#
+
+# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
+sp_arith                                 = add     # ignore/add/remove/force
+
+# Add or remove space around assignment operator '=', '+=', etc
+sp_assign                                = add     # ignore/add/remove/force
+
+# Add or remove space around boolean operators '&&' and '||'
+sp_bool                                  = add         # ignore/add/remove/force
+
+# Add or remove space around compare operator '<', '>', '==', etc
+sp_compare                               = add     # ignore/add/remove/force
+
+# Add or remove space inside '(' and ')'
+sp_inside_paren                          = add         # ignore/add/remove/force
+
+# Add or remove space between nested parens
+sp_paren_paren                           = add      # ignore/add/remove/force
+
+# Whether to balance spaces inside nested parens
+sp_balance_nested_parens                 = false    # false/true
+
+# Add or remove space between ')' and '{'
+sp_paren_brace                           = add         # ignore/add/remove/force
+
+# Add or remove space before pointer star '*'
+sp_before_ptr_star                       = ignore   # ignore/add/remove/force
+
+# Add or remove space between pointer stars '*'
+sp_between_ptr_star                      = ignore   # ignore/add/remove/force
+
+# Add or remove space after pointer star '*', if followed by a word.
+sp_after_ptr_star                        = ignore   # ignore/add/remove/force
+
+# Add or remove space before reference sign '&'
+sp_before_byref                          = ignore   # ignore/add/remove/force
+
+# Add or remove space after reference sign '&', if followed by a word.
+sp_after_byref                           = ignore   # ignore/add/remove/force
+
+# Add or remove space before '<>'
+sp_before_angle                          = ignore   # ignore/add/remove/force
+
+# Add or remove space after '<>'
+sp_after_angle                           = ignore   # ignore/add/remove/force
+
+# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
+sp_angle_paren                           = ignore   # ignore/add/remove/force
+
+# Add or remove space between '<>' and a word as in 'List<byte> m;'
+sp_angle_word                            = ignore   # ignore/add/remove/force
+
+# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
+sp_before_sparen                         = add   # ignore/add/remove/force
+
+# Add or remove space inside if-condition '(' and ')'
+sp_inside_sparen                         = add   # ignore/add/remove/force
+
+# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
+sp_after_sparen                          = ignore   # ignore/add/remove/force
+
+# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
+sp_sparen_brace                          = add   # ignore/add/remove/force
+
+# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
+sp_special_semi                          = ignore   # ignore/add/remove/force
+
+# Add or remove space before ';'
+sp_before_semi                           = ignore   # ignore/add/remove/force
+
+# Add or remove space before ';' in non-empty 'for' statements
+sp_before_semi_for                       = ignore   # ignore/add/remove/force
+
+# Add or remove space before a semicolon of an empty part of a for statment.
+sp_before_semi_for_empty                 = ignore   # ignore/add/remove/force
+
+# Add or remove space after the final semicolon of an empty part of a for statment: for ( ; ; <here> ).
+sp_after_semi_for_empty                  = ignore   # ignore/add/remove/force
+
+# Add or remove space before '[' (except '[]')
+sp_before_square                         = ignore   # ignore/add/remove/force
+
+# Add or remove space before '[]'
+sp_before_squares                        = ignore   # ignore/add/remove/force
+
+# Add or remove space inside '[' and ']'
+sp_inside_square                         = ignore   # ignore/add/remove/force
+
+# Add or remove space after ','
+sp_after_comma                           = ignore   # ignore/add/remove/force
+
+# Add or remove space before ','
+sp_before_comma                          = remove   # ignore/add/remove/force
+
+# Add or remove space between 'operator' and operator sign
+sp_after_operator                        = ignore   # ignore/add/remove/force
+
+# Add or remove space after cast
+sp_after_cast                            = ignore   # ignore/add/remove/force
+
+# Add or remove spaces inside cast parens
+sp_inside_paren_cast                     = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'sizeof' and '('
+sp_sizeof_paren                          = remove   # ignore/add/remove/force
+
+# Add or remove space after the tag keyword (Pawn)
+sp_after_tag                             = ignore   # ignore/add/remove/force
+
+# Add or remove space inside enum '{' and '}'
+sp_inside_braces_enum                    = ignore   # ignore/add/remove/force
+
+# Add or remove space inside struct/union '{' and '}'
+sp_inside_braces_struct                  = ignore   # ignore/add/remove/force
+
+# Add or remove space inside '{' and '}'
+sp_inside_braces                         = ignore   # ignore/add/remove/force
+
+# Add or remove space inside '<' and '>'
+sp_inside_angle                          = ignore   # ignore/add/remove/force
+
+# Add or remove space between return type and function name
+# A minimum of 1 is forced except for pointer return types.
+sp_type_func                             = ignore   # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function declaration
+sp_func_proto_paren                      = remove   # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function definition
+sp_func_def_paren                        = remove   # ignore/add/remove/force
+
+# Add or remove space inside empty function '()'
+sp_inside_fparens                        = remove   # ignore/add/remove/force
+
+# Add or remove space inside function '(' and ')'
+sp_inside_fparen                         = add         # ignore/add/remove/force
+
+# Add or remove space between ']' and '(' when part of a function call.
+sp_square_fparen                         = ignore   # ignore/add/remove/force
+
+# Add or remove space between ')' and '{' of function
+sp_fparen_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove space between function name and '(' on function calls
+sp_func_call_paren                       = remove   # ignore/add/remove/force
+
+# Add or remove space between a constructor/destructor and the open paren
+sp_func_class_paren                      = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'return' and '('
+sp_return_paren                          = ignore   # ignore/add/remove/force
+
+# Add or remove space between '__attribute__' and '('
+sp_attribute_paren                       = ignore   # ignore/add/remove/force
+
+# Add or remove space between macro and value
+sp_macro                                 = ignore   # ignore/add/remove/force
+
+# Add or remove space between macro function ')' and value
+sp_macro_func                            = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'else' and '{' if on the same line
+sp_else_brace                            = ignore   # ignore/add/remove/force
+
+# Add or remove space between '}' and 'else' if on the same line
+sp_brace_else                            = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'catch' and '{' if on the same line
+sp_catch_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove space between '}' and 'catch' if on the same line
+sp_brace_catch                           = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'finally' and '{' if on the same line
+sp_finally_brace                         = ignore   # ignore/add/remove/force
+
+# Add or remove space between '}' and 'finally' if on the same line
+sp_brace_finally                         = ignore   # ignore/add/remove/force
+
+# Add or remove space between 'try' and '{' if on the same line
+sp_try_brace                             = ignore   # ignore/add/remove/force
+
+# Add or remove space between get/set and '{' if on the same line
+sp_getset_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove space before the '::' operator
+sp_before_dc                             = ignore   # ignore/add/remove/force
+
+# Add or remove space after the '::' operator
+sp_after_dc                              = ignore   # ignore/add/remove/force
+
+# Add or remove around the D named array initializer ':' operator
+sp_d_array_colon                         = ignore   # ignore/add/remove/force
+
+# Add or remove space after the '!' (not) operator.
+sp_not                                   = remove   # ignore/add/remove/force
+
+# Add or remove space after the '~' (invert) operator.
+sp_inv                                   = remove   # ignore/add/remove/force
+
+# Add or remove space after the '&' (address-of) operator.
+# This does not affect the spacing after a '&' that is part of a type.
+sp_addr                                  = remove   # ignore/add/remove/force
+
+# Add or remove space around the '.' or '->' operators
+sp_member                                = remove   # ignore/add/remove/force
+
+# Add or remove space after the '*' (dereference) operator.
+# This does not affect the spacing after a '*' that is part of a type.
+sp_deref                                 = remove   # ignore/add/remove/force
+
+# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'
+sp_sign                                  = remove   # ignore/add/remove/force
+
+# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'
+sp_incdec                                = remove   # ignore/add/remove/force
+
+# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
+sp_after_oc_scope                        = ignore   # ignore/add/remove/force
+
+# Add or remove space after the colon in message specs
+# '-(int) f: (int) x;' vs '+(int) f : (int) x;'
+sp_before_oc_colon                       = ignore   # ignore/add/remove/force
+
+# Add or remove space after the (type) in message specs
+# '-(int) f: (int) x;' vs '+(int)f : (int)x;'
+sp_after_oc_type                         = ignore   # ignore/add/remove/force
+
+#
+# Code alignment (not left column spaces/tabs)
+#
+
+# Whether to keep non-indenting tabs
+align_keep_tabs                          = false    # false/true
+
+# Whether to use tabs for alinging
+align_with_tabs                          = true            # false/true
+
+# Whether to bump out to the next tab when aligning
+align_on_tabstop                         = false    # false/true
+
+# Whether to left-align numbers
+align_number_left                        = false    # false/true
+
+# Align variable definitions in prototypes and functions
+align_func_params                        = false    # false/true
+
+# The span for aligning variable definitions (0=don't align)
+align_var_def_span                       = 0        # number
+
+# How to align the star in variable definitions.
+#  0=Part of the type
+#  1=Part of the variable
+#  2=Dangling
+align_var_def_star_style                 = 0        # number
+
+# How to align the '&' in variable definitions.
+#  0=Part of the type
+#  1=Part of the variable
+#  2=Dangling
+align_var_def_amp_style                  = 0        # number
+
+# The threshold for aligning variable definitions (0=no limit)
+align_var_def_thresh                     = 0        # number
+
+# Whether to align the colon in struct bit fields
+align_var_def_colon                      = false    # false/true
+
+# Whether to align inline struct/enum/union variable definitions
+align_var_def_inline                     = false    # false/true
+
+# The span for aligning on '=' in assignments (0=don't align)
+align_assign_span                        = 0        # number
+
+# The threshold for aligning on '=' in assignments (0=no limit)
+align_assign_thresh                      = 0        # number
+
+# The span for aligning on '=' in enums (0=don't align)
+align_enum_equ_span                      = 0        # number
+
+# The threshold for aligning on '=' in enums (0=no limit)
+align_enum_equ_thresh                    = 0        # number
+
+# The span for aligning struct/union (0=don't align)
+align_var_struct_span                    = 0        # number
+
+# The threshold for aligning struct/union member definitions (0=no limit)
+align_var_struct_thresh                  = 0        # number
+
+# The span for aligning struct initializer values (0=don't align)
+align_struct_init_span                   = 0        # number
+
+# The minimum space between the type and the synonym of a typedef
+align_typedef_gap                        = 0        # number
+
+# The span for aligning single-line typedefs (0=don't align)
+align_typedef_span                       = 0        # number
+
+# How to align typedef'd functions with other typedefs
+# 0: Don't mix them at all
+# 1: align the open paren with the types
+# 2: align the function type name with the other type names
+align_typedef_func                       = 0        # number
+
+# Controls the positioning of the '*' in typedefs. Just try it.
+# 0: Align on typdef type, ignore '*'
+# 1: The '*' is part of type name: typedef int  *pint;
+# 2: The '*' is part of the type, but dangling: typedef int *pint;
+align_typedef_star_style                 = 0        # number
+
+# Controls the positioning of the '&' in typedefs. Just try it.
+# 0: Align on typdef type, ignore '&'
+# 1: The '&' is part of type name: typedef int  &pint;
+# 2: The '&' is part of the type, but dangling: typedef int &pint;
+align_typedef_amp_style                  = 0        # number
+
+# The span for aligning comments that end lines (0=don't align)
+align_right_cmt_span                     = 0        # number
+
+# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment
+align_right_cmt_mix                      = false    # false/true
+
+# The span for aligning function prototypes (0=don't align)
+align_func_proto_span                    = 0        # number
+
+# The span for aligning function prototypes (0=don't align)
+align_oc_msg_spec_span                   = 0        # number
+
+# Whether to align macros wrapped with a backslash and a newline.
+# This will not work right if the macro contains a multi-line comment.
+align_nl_cont                            = false    # false/true
+
+# The minimum space between label and value of a preprocessor define
+align_pp_define_gap                      = 0        # number
+
+# The span for aligning on '#define' bodies (0=don't align)
+align_pp_define_span                     = 0        # number
+
+#
+# Newline adding and removing options
+#
+
+# Whether to collapse empty blocks between '{' and '}'
+nl_collapse_empty_body                   = false    # false/true
+
+# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'
+nl_assign_leave_one_liners               = true    # false/true
+
+# Don't split one-line braced statements inside a class xx { } body
+nl_class_leave_one_liners                = false    # false/true
+
+# Don't split one-line enums: 'enum foo { BAR = 15 };'
+nl_enum_leave_one_liners                 = true    # false/true
+
+# Don't split one-line get or set functions
+nl_getset_leave_one_liners               = true    # false/true
+
+# Don't split one-line function definitions - 'int foo() { return 0; }'
+nl_func_leave_one_liners                 = true    # false/true
+
+# Don't split one-line if/else statements - 'if(a) b++;'
+nl_if_leave_one_liners                   = false    # false/true
+
+# Add or remove newlines at the start of the file
+nl_start_of_file                         = ignore   # ignore/add/remove/force
+
+# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'
+nl_start_of_file_min                     = 0        # number
+
+# Add or remove newline at the end of the file
+nl_end_of_file                           = add   # ignore/add/remove/force
+
+# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')
+nl_end_of_file_min                       = 0        # number
+
+# Add or remove newline between '=' and '{'
+nl_assign_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline between '=' and '[' (D only)
+nl_assign_square                         = ignore   # ignore/add/remove/force
+
+# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'
+nl_after_square_assign                   = ignore   # ignore/add/remove/force
+
+# The number of newlines after a block of variable definitions
+nl_func_var_def_blk                      = 0        # number
+
+# Add or remove newline between a function call's ')' and '{', as in:
+# list_for_each(item, &list) { }
+nl_fcall_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'enum' and '{'
+nl_enum_brace                            = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'struct and '{'
+nl_struct_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'union' and '{'
+nl_union_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'if' and '{'
+nl_if_brace                              = remove   # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'else'
+nl_brace_else                            = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'else if' and '{'
+# If set to ignore, nl_if_brace is used instead
+nl_elseif_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'else' and '{'
+nl_else_brace                            = ignore   # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'finally'
+nl_brace_finally                         = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'finally' and '{'
+nl_finally_brace                         = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'try' and '{'
+nl_try_brace                             = ignore   # ignore/add/remove/force
+
+# Add or remove newline between get/set and '{'
+nl_getset_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'for' and '{'
+nl_for_brace                             = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'catch' and '{'
+nl_catch_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'catch'
+nl_brace_catch                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'while' and '{'
+nl_while_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'do' and '{'
+nl_do_brace                              = ignore   # ignore/add/remove/force
+
+# Add or remove newline between '}' and 'while' of 'do' statement
+nl_brace_while                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'switch' and '{'
+nl_switch_brace                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline when condition spans two or more lines
+nl_multi_line_cond                       = false    # false/true
+
+# Force a newline in a define after the macro name for multi-line defines.
+nl_multi_line_define                     = false    # false/true
+
+# Whether to put a newline before 'case' statement
+nl_before_case                           = false    # false/true
+
+# Whether to put a newline after 'case' statement
+nl_after_case                            = false    # false/true
+
+# Newline between namespace and {
+nl_namespace_brace                       = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'template<>' and 'class'
+nl_template_class                        = ignore   # ignore/add/remove/force
+
+# Add or remove newline between 'class' and '{'
+nl_class_brace                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline after each ',' in the constructor member initialization
+nl_class_init_args                       = ignore   # ignore/add/remove/force
+
+# Add or remove newline between return type and function name in definition
+nl_func_type_name                        = ignore   # ignore/add/remove/force
+
+# Add or remove newline between return type and function name in a prototype
+nl_func_proto_type_name                  = ignore   # ignore/add/remove/force
+
+# Add or remove newline between a function name and the opening '('
+nl_func_paren                            = ignore   # ignore/add/remove/force
+
+# Add or remove newline after '(' in a function declaration
+nl_func_decl_start                       = ignore   # ignore/add/remove/force
+
+# Add or remove newline after each ',' in a function declaration
+nl_func_decl_args                        = ignore   # ignore/add/remove/force
+
+# Add or remove newline before the ')' in a function declaration
+nl_func_decl_end                         = ignore   # ignore/add/remove/force
+
+# Add or remove newline between function signature and '{'
+nl_fdef_brace                            = remove   # ignore/add/remove/force
+
+# Whether to put a newline after 'return' statement
+nl_after_return                          = false    # false/true
+
+# Whether to put a newline after semicolons, except in 'for' statements
+nl_after_semicolon                       = false    # false/true
+
+# Whether to put a newline after brace open.
+# This also adds a newline before the matching brace close.
+nl_after_brace_open                      = false    # false/true
+
+# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is
+# placed between the open brace and a trailing single-line comment.
+nl_after_brace_open_cmt                  = false    # false/true
+
+# Whether to put a newline after a virtual brace open.
+# These occur in un-braced if/while/do/for statement bodies.
+nl_after_vbrace_open                     = false    # false/true
+
+# Whether to alter newlines in '#define' macros
+nl_define_macro                          = false    # false/true
+
+# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'
+nl_squeeze_ifdef                         = false    # false/true
+
+# Add or remove newline before 'if'
+nl_before_if                             = ignore   # ignore/add/remove/force
+
+# Add or remove newline after 'if'
+nl_after_if                              = ignore   # ignore/add/remove/force
+
+# Add or remove newline before 'for'
+nl_before_for                            = ignore   # ignore/add/remove/force
+
+# Add or remove newline after 'for'
+nl_after_for                             = ignore   # ignore/add/remove/force
+
+# Add or remove newline before 'while'
+nl_before_while                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline after 'while'
+nl_after_while                           = ignore   # ignore/add/remove/force
+
+# Add or remove newline before 'switch'
+nl_before_switch                         = ignore   # ignore/add/remove/force
+
+# Add or remove newline after 'switch'
+nl_after_switch                          = ignore   # ignore/add/remove/force
+
+# Add or remove newline before 'do'
+nl_before_do                             = ignore   # ignore/add/remove/force
+
+# Add or remove newline after 'do'
+nl_after_do                              = ignore   # ignore/add/remove/force
+
+# Whether to double-space commented-entries in struct/enum
+nl_ds_struct_enum_cmt                    = false    # false/true
+
+# Whether to double-space before the close brace of a struct/union/enum
+nl_ds_struct_enum_close_brace            = false    # false/true
+
+# Add or remove a newline around a class colon.
+# Related to pos_class_colon, nl_class_init_args, and pos_comma.
+nl_class_colon                           = ignore   # ignore/add/remove/force
+
+# Change simple unbraced if statements into a one-liner
+# 'if(b)\n i++;' => 'if(b) i++;'
+nl_create_if_one_liner                   = true    # false/true
+
+# Change simple unbraced for statements into a one-liner
+# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'
+nl_create_for_one_liner                  = false    # false/true
+
+# Change simple unbraced while statements into a one-liner
+# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'
+nl_create_while_one_liner                = false    # false/true
+
+#
+# Positioning options
+#
+
+# The position of boolean operators in wrapped expressions
+pos_bool                                 = ignore   # ignore/lead/trail
+
+# The position of the comma in wrapped expressions
+pos_comma                                = ignore   # ignore/lead/trail
+
+# The position of the comma in the constructor initialization list
+pos_class_comma                          = ignore   # ignore/lead/trail
+
+# The position of colons between constructor and member initialization
+pos_class_colon                          = ignore   # ignore/lead/trail
+
+#
+# Line Splitting options
+#
+
+# Try to limit code width to N number of columns
+code_width                               = 0        # number
+
+# Whether to fully split long 'for' statements at semi-colons
+ls_for_split_full                        = false    # false/true
+
+# Whether to fully split long function protos/calls at commas
+ls_func_split_full                       = false    # false/true
+
+#
+# Blank line options
+#
+
+# The maximum consecutive newlines
+nl_max                                   = 0        # number
+
+# The number of newlines after a function prototype, if followed by another function prototype
+nl_after_func_proto                      = 0        # number
+
+# The number of newlines after a function prototype, if not followed by another function prototype
+nl_after_func_proto_group                = 0        # number
+
+# The number of newlines after '}' of a multi-line function body
+nl_after_func_body                       = 0        # number
+
+# The number of newlines after '}' of a single line function body
+nl_after_func_body_one_liner             = 0        # number
+
+# The minimum number of newlines before a multi-line comment.
+# Doesn't apply if after a brace open or another multi-line comment.
+nl_before_block_comment                  = 0        # number
+
+# The minimum number of newlines before a single-line C comment.
+# Doesn't apply if after a brace open or other single-line C comments.
+nl_before_c_comment                      = 0        # number
+
+# The minimum number of newlines before a CPP comment.
+# Doesn't apply if after a brace open or other CPP comments.
+nl_before_cpp_comment                    = 0        # number
+
+# Whether to force a newline after a mulit-line comment.
+nl_after_multiline_comment               = false    # false/true
+
+# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
+# Will not change the newline count if after a brace open.
+# 0 = No change.
+nl_before_access_spec                    = 0        # number
+
+# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
+# 0 = No change.
+nl_after_access_spec                     = 0        # number
+
+# Whether to remove blank lines after '{'
+eat_blanks_after_open_brace              = false    # false/true
+
+# Whether to remove blank lines before '}'
+eat_blanks_before_close_brace            = false    # false/true
+
+#
+# Code modifying options (non-whitespace)
+#
+
+# Add or remove braces on single-line 'do' statement
+mod_full_brace_do                        = ignore   # ignore/add/remove/force
+
+# Add or remove braces on single-line 'for' statement
+mod_full_brace_for                       = ignore   # ignore/add/remove/force
+
+# Add or remove braces on single-line function defintions. (Pawn)
+mod_full_brace_function                  = ignore   # ignore/add/remove/force
+
+# Add or remove braces on single-line 'if' statement
+mod_full_brace_if                        = add      # ignore/add/remove/force
+
+# Don't remove braces around statements that span N newlines
+mod_full_brace_nl                        = 0        # number
+
+# Add or remove braces on single-line 'while' statement
+mod_full_brace_while                     = ignore   # ignore/add/remove/force
+
+# Add or remove unnecessary paren on 'return' statement
+mod_paren_on_return                      = ignore   # ignore/add/remove/force
+
+# Whether to change optional semicolons to real semicolons
+mod_pawn_semicolon                       = false    # false/true
+
+# Add parens on 'while' and 'if' statement around bools
+mod_full_paren_if_bool                   = false    # false/true
+
+# Whether to remove superfluous semicolons
+mod_remove_extra_semicolon               = false    # false/true
+
+# If a function body exceeds the specified number of newlines and doesn't have a comment after
+# the close brace, a comment will be added.
+mod_add_long_function_closebrace_comment = 0        # number
+
+# If a switch body exceeds the specified number of newlines and doesn't have a comment after
+# the close brace, a comment will be added.
+mod_add_long_switch_closebrace_comment   = 0        # number
+
+# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
+mod_sort_import                          = false    # false/true
+
+# If TRUE, will sort consecutive single-line 'using' statements [C#]
+mod_sort_using                           = false    # false/true
+
+# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
+# This is generally a bad idea, as it may break your code.
+mod_sort_include                         = false    # false/true
+
+#
+# Comment modifications
+#
+
+# Try to wrap comments at cmt_witdth columns
+cmt_width                                = 0        # number
+
+# Whether to group c-comments that look like they are in a block
+cmt_c_group                              = false    # false/true
+
+# Whether to put an empty '/*' on the first line of the combined c-comment
+cmt_c_nl_start                           = false    # false/true
+
+# Whether to put a newline before the closing '*/' of the combined c-comment
+cmt_c_nl_end                             = false    # false/true
+
+# Whether to group cpp-comments that look like they are in a block
+cmt_cpp_group                            = false    # false/true
+
+# Whether to put an empty '/*' on the first line of the combined cpp-comment
+cmt_cpp_nl_start                         = false    # false/true
+
+# Whether to put a newline before the closing '*/' of the combined cpp-comment
+cmt_cpp_nl_end                           = false    # false/true
+
+# Whether to change cpp-comments into c-comments
+cmt_cpp_to_c                             = false    # false/true
+
+# Whether to put a star on subsequent comment lines
+cmt_star_cont                            = false    # false/true
+
+# The number of spaces to insert at the start of subsequent comment lines
+cmt_sp_before_star_cont                  = 0        # number
+
+# The number of spaces to insert after the star on subsequent comment lines
+cmt_sp_after_star_cont                   = 0        # number
+
+# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.
+# Will substitue $(filename) with the current file's name.
+cmt_insert_file_header                   = ""         # string
+
+# The filename that contains text to insert before a function implementation if the function isn't preceeded with a C/C++ comment.
+# Will substitue $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.
+# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }
+cmt_insert_func_header                   = ""         # string
+
+# The filename that contains text to insert before a class if the class isn't preceeded with a C/C++ comment.
+# Will substitue $(class) with the class name.
+cmt_insert_class_header                  = ""         # string
+
+#
+# Preprocessor options
+#
+
+# Control indent of preprocessors inside #if blocks at brace level 0
+pp_indent                                = ignore   # ignore/add/remove/force
+
+# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
+pp_indent_at_level                       = false    # false/true
+
+# Add or remove space after # based on pp_level of #if blocks
+pp_space                                 = ignore   # ignore/add/remove/force
+
+# Sets the number of spaces added with pp_space
+pp_space_count                           = 0        # number
+
+# The indent for #region and #endregion in C# and '#pragma region' in C/C++
+pp_indent_region                         = 0        # number
+
+# Whether to indent the code between #region and #endregion
+pp_region_indent_code                    = false    # false/true
+
+# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
+pp_indent_if                             = 0        # number
+
+# Control whether to indent the code between #if, #else and #endif when not at file-level
+pp_if_indent_code                        = false    # false/true
+
+# Whether to indent '#define' at the brace level (true) or from column 1 (false)
+pp_define_at_level                       = false    # false/true
+
+# You can force a token to be a type with the 'type' option.
+# Example:
+# type myfoo1 myfoo2
+#
+# You can create custom macro-based indentation using macro-open, 
+# macro-else and macro-close.
+# Example:
+# macro-open  BEGIN_TEMPLATE_MESSAGE_MAP
+# macro-open  BEGIN_MESSAGE_MAP
+# macro-close END_MESSAGE_MAP
index 80f45f1fc638a3b8417709d78ee91544635a95c8..d3e4ce374a11f5b21ae584b9170366e9b76ca353 100644 (file)
@@ -8,7 +8,7 @@ macro(radiant_plugin name)
     copy_dlls(${name})
     install(
             TARGETS ${name}
-            LIBRARY DESTINATION modules
+            LIBRARY DESTINATION ${RADIANT_ADDONS_DIR}/modules
     )
 endmacro()
 
@@ -26,7 +26,6 @@ add_subdirectory(imagehl)
 add_subdirectory(imagepng)
 add_subdirectory(imageq2)
 add_subdirectory(imagewebp)
-add_subdirectory(iqmmodel)
 add_subdirectory(mapq3)
 add_subdirectory(mapxml)
 add_subdirectory(md3model)
index 7ed025d8078d768274a074bfc33a9f3724b0dbc4..eaf3bf2a5c112a971524f71626bdbd59f354b45c 100644 (file)
@@ -5,6 +5,10 @@ radiant_plugin(archivezip
         zlibstream.h
         )
 
+find_package(GLIB REQUIRED)
+target_include_directories(archivezip PRIVATE ${GLIB_INCLUDE_DIRS})
+target_link_libraries(archivezip PRIVATE ${GLIB_LIBRARIES})
+
 find_package(ZLIB REQUIRED)
 target_include_directories(archivezip PRIVATE ${ZLIB_INCLUDE_DIRS})
 target_link_libraries(archivezip PRIVATE ${ZLIB_LIBRARIES})
index a8616e626daafdb51a6e76c932f5a90d4ffc9bdc..98ac6a67f4126692dcd55e5bdb5fc6f6d7b8a5af 100644 (file)
 #include "iarchive.h"
 
 #include <algorithm>
+#include <glib.h>
 #include "stream/filestream.h"
 #include "container/array.h"
 #include "archivelib.h"
 #include "zlibstream.h"
+#include "imagelib.h"
 
 class DeflatedArchiveFile : public ArchiveFile
 {
@@ -50,12 +52,15 @@ DeflatedArchiveFile( const char* name, const char* archiveName, position_type po
 void release(){
        delete this;
 }
+
 size_type size() const {
        return m_size;
 }
+
 const char* getName() const {
        return m_name.c_str();
 }
+
 InputStream& getInputStream(){
        return m_zipstream;
 }
@@ -68,6 +73,7 @@ FileInputStream m_istream;
 SubFileInputStream m_substream;
 DeflatedInputStream m_zipstream;
 BinaryToTextInputStream<DeflatedInputStream> m_textStream;
+
 public:
 typedef FileInputStream::size_type size_type;
 typedef FileInputStream::position_type position_type;
@@ -79,6 +85,7 @@ DeflatedArchiveTextFile( const char* name, const char* archiveName, position_typ
 void release(){
        delete this;
 }
+
 TextInputStream& getInputStream(){
        return m_textStream;
 }
@@ -90,7 +97,6 @@ TextInputStream& getInputStream(){
 #include "string/string.h"
 #include "fs_filesystem.h"
 
-
 class ZipArchive : public Archive
 {
 class ZipRecord
@@ -101,13 +107,19 @@ enum ECompressionMode
        eStored,
        eDeflated,
 };
-ZipRecord( unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, ECompressionMode mode )
-       : m_position( position ), m_stream_size( compressed_size ), m_file_size( uncompressed_size ), m_mode( mode ){
+
+ZipRecord( unsigned int position, unsigned int compressed_size, unsigned int uncompressed_size, ECompressionMode mode, bool is_symlink )
+       : m_position( position ), m_stream_size( compressed_size ), m_file_size( uncompressed_size ), m_mode( mode ), m_is_symlink( is_symlink ){
 }
+
 unsigned int m_position;
 unsigned int m_stream_size;
 unsigned int m_file_size;
 ECompressionMode m_mode;
+bool m_is_symlink;
+// Do not resolve more than 5 recursive symbolic links to
+// prevent circular symbolic links.
+int m_max_symlink_depth = 5;
 };
 
 typedef GenericFileSystem<ZipRecord> ZipFileSystem;
@@ -115,6 +127,17 @@ ZipFileSystem m_filesystem;
 CopiedString m_name;
 FileInputStream m_istream;
 
+bool is_file_symlink( unsigned int filemode ){
+       // see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h
+       // redefine so it works outside of Unices
+       constexpr int RADIANT_S_IFMT = 00170000;
+       constexpr int RADIANT_S_IFLNK = 0120000;
+       // see https://trac.edgewall.org/attachment/ticket/8919/ZipDownload.patch
+       constexpr int PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT = 16;
+       unsigned long attr = filemode >> PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT;
+       return (attr & RADIANT_S_IFMT) == RADIANT_S_IFLNK;
+}
+
 bool read_record(){
        zip_magic magic;
        istream_read_zip_magic( m_istream, magic );
@@ -144,14 +167,19 @@ bool read_record(){
        istream_read_int16_le( m_istream );
        //unsigned short filetype =
        istream_read_int16_le( m_istream );
-       //unsigned int filemode =
-       istream_read_int32_le( m_istream );
+       unsigned int filemode = istream_read_int32_le( m_istream );
        unsigned int position = istream_read_int32_le( m_istream );
 
        Array<char> filename( namelength + 1 );
        m_istream.read( reinterpret_cast<FileInputStream::byte_type*>( filename.data() ), namelength );
        filename[namelength] = '\0';
 
+       bool is_symlink = is_file_symlink( filemode );
+
+//     if ( is_symlink ) {
+//             globalOutputStream() << "Warning: zip archive " << makeQuoted( m_name.c_str() ) << " contains symlink file: " << makeQuoted( filename.data() ) << "\n";
+//     }
+
        m_istream.seek( extras + comment, FileInputStream::cur );
 
        if ( path_is_directory( filename.data() ) ) {
@@ -165,7 +193,7 @@ bool read_record(){
                }
                else
                {
-                       file = new ZipRecord( position, compressed_size, uncompressed_size, ( compression_mode == Z_DEFLATED ) ? ZipRecord::eDeflated : ZipRecord::eStored );
+                       file = new ZipRecord( position, compressed_size, uncompressed_size, ( compression_mode == Z_DEFLATED ) ? ZipRecord::eDeflated : ZipRecord::eStored, is_symlink );
                }
        }
 
@@ -193,15 +221,17 @@ bool read_pkzip(){
        }
        return false;
 }
+
 public:
 ZipArchive( const char* name )
        : m_name( name ), m_istream( name ){
        if ( !m_istream.failed() ) {
                if ( !read_pkzip() ) {
-                       globalErrorStream() << "ERROR: invalid zip-file " << makeQuoted( name ) << '\n';
+                       globalErrorStream() << "ERROR: invalid zip file " << makeQuoted( name ) << '\n';
                }
        }
 }
+
 ~ZipArchive(){
        for ( ZipFileSystem::iterator i = m_filesystem.begin(); i != m_filesystem.end(); ++i )
        {
@@ -216,59 +246,156 @@ bool failed(){
 void release(){
        delete this;
 }
+
+// The zip format has a maximum filename size of 64K
+static const int MAX_FILENAME_BUF = 65537;
+
+/* The symlink implementation is ported from Dæmon engine implementation by slipher which was a complete rewrite of one illwieckz did on Dæmon by taking inspiration from Darkplaces engine.
+
+See:
+
+- https://github.com/DaemonEngine/Daemon/blob/master/src/common/FileSystem.cpp
+- https://gitlab.com/xonotic/darkplaces/-/blob/div0-stable/fs.c
+
+Some words by slipher:
+
+> Symlinks are a bad feature which you should not use. Therefore, the implementation is as
+> slow as possible with a full iteration of the archive performed for each symlink.
+
+> The symlink path `relative` must be relative to the symlink's location.
+> Only supports paths consisting of "../" 0 or more times, followed by non-magical path components.
+*/
+
+static void resolveSymlinkPath( const char* base, const char* relative, char* resolved ){
+
+       base = g_path_get_dirname( base );
+
+       while( g_str_has_prefix( relative, "../" ) )
+       {
+               if ( base[0] == '\0' )
+               {
+                       globalErrorStream() << "Error while reading symbolic link " << makeQuoted( base ) << ": no such directory\n";
+                       resolved[0] = '\0';
+                       return;
+               }
+
+               base = g_path_get_dirname( base );
+               relative += 3;
+       }
+
+       snprintf( resolved, MAX_FILENAME_BUF, "%s/%s", base, relative);
+}
+
+ArchiveFile* readFile( const char* name, ZipRecord* file ){
+       switch ( file->m_mode )
+       {
+               case ZipRecord::eStored:
+                       return StoredArchiveFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
+               case ZipRecord::eDeflated:
+               default: // silence warning about function not returning
+                       return new DeflatedArchiveFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
+       }
+}
+
+void readSymlink( const char* name, ZipRecord* file, char* resolved ){
+               globalOutputStream() << "Found symbolic link: " << makeQuoted( name ) << "\n";
+
+               if ( file->m_max_symlink_depth == 0 ) {
+               globalErrorStream() << "Maximum symbolic link depth reached\n";
+                       return;
+               }
+
+               file->m_max_symlink_depth--;
+
+               ArchiveFile* symlink_file = readFile( name, file );
+               ScopedArchiveBuffer buffer( *symlink_file );
+               const char* relative = (const char*) buffer.buffer;
+
+               resolveSymlinkPath( name, relative, resolved );
+               globalOutputStream() << "Resolved symbolic link: " << makeQuoted( resolved ) << "\n";
+}
+
 ArchiveFile* openFile( const char* name ){
        ZipFileSystem::iterator i = m_filesystem.find( name );
+
        if ( i != m_filesystem.end() && !i->second.is_directory() ) {
                ZipRecord* file = i->second.file();
 
                m_istream.seek( file->m_position );
                zip_file_header file_header;
                istream_read_zip_file_header( m_istream, file_header );
+
                if ( file_header.z_magic != zip_file_header_magic ) {
                        globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() );
                        return 0;
                }
 
-               switch ( file->m_mode )
-               {
-               case ZipRecord::eStored:
-                       return StoredArchiveFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
-               case ZipRecord::eDeflated:
-                       return new DeflatedArchiveFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size, file->m_file_size );
+               if ( file->m_is_symlink ) {
+                       char resolved[MAX_FILENAME_BUF];
+
+                       readSymlink( name, file, resolved );
+
+                       // slow as possible full iteration of the archive
+                       return openFile( resolved );
                }
+
+               return readFile( name, file );
        }
+
        return 0;
 }
+
+ArchiveTextFile* readTextFile( const char* name, ZipRecord* file ){
+       switch ( file->m_mode )
+       {
+               case ZipRecord::eStored:
+                       return StoredArchiveTextFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
+               case ZipRecord::eDeflated:
+               default: // silence warning about function not returning
+                       return new DeflatedArchiveTextFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
+       }
+}
+
 ArchiveTextFile* openTextFile( const char* name ){
        ZipFileSystem::iterator i = m_filesystem.find( name );
+
        if ( i != m_filesystem.end() && !i->second.is_directory() ) {
                ZipRecord* file = i->second.file();
 
                m_istream.seek( file->m_position );
                zip_file_header file_header;
                istream_read_zip_file_header( m_istream, file_header );
+
                if ( file_header.z_magic != zip_file_header_magic ) {
                        globalErrorStream() << "error reading zip file " << makeQuoted( m_name.c_str() );
                        return 0;
                }
 
-               switch ( file->m_mode )
-               {
-               case ZipRecord::eStored:
-                       return StoredArchiveTextFile::create( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
-               case ZipRecord::eDeflated:
-                       return new DeflatedArchiveTextFile( name, m_name.c_str(), m_istream.tell(), file->m_stream_size );
+               if ( file->m_is_symlink ) {
+                       char resolved[MAX_FILENAME_BUF];
+
+                       readSymlink( name, file, resolved );
+
+                       // slow as possible full iteration of the archive
+                       return openTextFile( resolved );
                }
+
+               return readTextFile( name, file );
        }
+
        return 0;
+
 }
+
 bool containsFile( const char* name ){
        ZipFileSystem::iterator i = m_filesystem.find( name );
        return i != m_filesystem.end() && !i->second.is_directory();
+
 }
 void forEachFile( VisitorFunc visitor, const char* root ){
        m_filesystem.traverse( visitor, root );
 }
+
 };
 
 Archive* OpenArchive( const char* name ){
index 4c566d96f420dd5264a6f509b3920160543c791f..d6b00d71853072879643059ec8592a852721bebf 100644 (file)
 
 #include "ientity.h"
 
-#include "stream/stringstream.h"
 #include "math/quaternion.h"
 #include "generic/callback.h"
 #include "stringio.h"
 
+#include <sstream>
+
 #include "angle.h"
 
 typedef float Float9[9];
@@ -58,7 +59,7 @@ inline void write_rotation( const Float9 rotation, Entity* entity, const char* k
        }
        else
        {
-               StringOutputStream value( 256 );
+               std::ostringstream value;
                value << rotation[0] << ' '
                          << rotation[1] << ' '
                          << rotation[2] << ' '
@@ -68,7 +69,7 @@ inline void write_rotation( const Float9 rotation, Entity* entity, const char* k
                          << rotation[6] << ' '
                          << rotation[7] << ' '
                          << rotation[8];
-               entity->setKeyValue( key, value.c_str() );
+               entity->setKeyValue( key, value.str().c_str() );
        }
 }
 inline void read_rotation( Float9 rotation, const char* value ){
index 281193fd63afd1208a1d37128912da151b687f77..449bbf1bca9d689fa810bf09c63f114b1baecc7a 100644 (file)
@@ -40,7 +40,7 @@ void user_error_fn( png_structp png_ptr, png_const_charp error_msg ){
        longjmp( png_jmpbuf(png_ptr), 0 );
 }
 
-void user_read_data( png_structp png_ptr, png_bytep data, png_uint_32 length ){
+void user_read_data( png_structp png_ptr, png_bytep data, png_size_t length ){
        png_bytep *p_p_fbuffer = (png_bytep*)png_get_io_ptr( png_ptr );
        memcpy( data, *p_p_fbuffer, length );
        *p_p_fbuffer += length;
@@ -80,7 +80,7 @@ Image* LoadPNGBuff( unsigned char* fbuffer ){
        }
 
        // configure the read function
-       png_set_read_fn( png_ptr, ( png_voidp ) & p_fbuffer, ( png_rw_ptr ) & user_read_data );
+       png_set_read_fn( png_ptr, (png_voidp) &p_fbuffer, &user_read_data );
 
        if ( setjmp( png_jmpbuf(png_ptr) ) ) {
                png_destroy_read_struct( &png_ptr, &info_ptr,
@@ -113,7 +113,7 @@ Image* LoadPNGBuff( unsigned char* fbuffer ){
                png_set_tRNS_to_alpha( png_ptr );
        }
 
-       if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) {
+       else if ( !( color_type & PNG_COLOR_MASK_ALPHA ) ) {
                // Set the background color to draw transparent and alpha images over.
                png_color_16 my_background, *image_background;
 
diff --git a/plugins/iqmmodel/CMakeLists.txt b/plugins/iqmmodel/CMakeLists.txt
deleted file mode 100644 (file)
index e371ae7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-radiant_plugin(iqmmodel
-        iqm.cpp iqm.h
-        plugin.cpp plugin.h
-        )
diff --git a/plugins/iqmmodel/iqm.cpp b/plugins/iqmmodel/iqm.cpp
deleted file mode 100644 (file)
index 466effc..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   Copyright (C) 2010-2014 COR Entertainment, LLC.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "iqm.h"
-
-#include "ifilesystem.h"
-#include "imodel.h"
-
-#include "imagelib.h"
-#include "bytestreamutils.h"
-
-#include "../md3model/model.h"
-
-typedef unsigned char byte;
-
-/*
-   ========================================================================
-
-   .IQM triangle model file format
-
-   ========================================================================
- */
-
-typedef struct {
-       float s;
-       float t;
-} iqmSt_t;
-
-void istream_read_iqmSt( PointerInputStream &inputStream, iqmSt_t &st ){
-       st.s = istream_read_float32_le( inputStream );
-       st.t = istream_read_float32_le( inputStream );
-}
-
-typedef struct {
-       unsigned int indices[3];
-} iqmTriangle_t;
-
-void istream_read_iqmTriangle( PointerInputStream &inputStream, iqmTriangle_t &triangle ){
-       triangle.indices[0] = istream_read_int32_le( inputStream );
-       triangle.indices[1] = istream_read_int32_le( inputStream );
-       triangle.indices[2] = istream_read_int32_le( inputStream );
-}
-
-typedef struct {
-       float v[3];
-} iqmPos_t;
-
-void istream_read_iqmPos( PointerInputStream &inputStream, iqmPos_t &iqmPos ){
-       iqmPos.v[0] = istream_read_float32_le( inputStream );
-       iqmPos.v[1] = istream_read_float32_le( inputStream );
-       iqmPos.v[2] = istream_read_float32_le( inputStream );
-}
-
-const int IQM_POSITION = 0;
-const int IQM_TEXCOORD = 1;
-const int IQM_NORMAL = 2;
-const int IQM_TANGENT = 3;
-const int IQM_BLENDINDEXES = 4;
-const int IQM_BLENDWEIGHTS = 5;
-const int IQM_COLOR = 6;
-const int IQM_CUSTOM = 0x10;
-
-const int IQM_BYTE = 0;
-const int IQM_UBYTE = 1;
-const int IQM_SHORT = 2;
-const int IQM_USHORT = 3;
-const int IQM_INT = 4;
-const int IQM_UINT = 5;
-const int IQM_HALF = 6;
-const int IQM_FLOAT = 7;
-const int IQM_DOUBLE = 8;
-
-// animflags
-const int IQM_LOOP = 1;
-
-typedef struct iqmHeader_s {
-       byte id[16];
-       unsigned int version;
-       unsigned int filesize;
-       unsigned int flags;
-       unsigned int num_text, ofs_text;
-       unsigned int num_meshes, ofs_meshes;
-       unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
-       unsigned int num_triangles, ofs_triangles, ofs_neighbors;
-       unsigned int num_joints, ofs_joints;
-       unsigned int num_poses, ofs_poses;
-       unsigned int num_anims, ofs_anims;
-       unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
-       unsigned int num_comment, ofs_comment;
-       unsigned int num_extensions, ofs_extensions;
-} iqmHeader_t;
-
-void istream_read_iqmHeader( PointerInputStream &inputStream, iqmHeader_t &header ){
-       inputStream.read( header.id, 16 );
-#define READINT( x ) header.x = istream_read_int32_le( inputStream );
-       READINT( version )
-       READINT( filesize )
-       READINT( flags )
-       READINT( num_text )
-       READINT( ofs_text )
-       READINT( num_meshes )
-       READINT( ofs_meshes )
-       READINT( num_vertexarrays )
-       READINT( num_vertexes )
-       READINT( ofs_vertexarrays )
-       READINT( num_triangles )
-       READINT( ofs_triangles )
-       READINT( ofs_neighbors )
-       READINT( num_joints )
-       READINT( ofs_joints )
-       READINT( num_frames )
-       READINT( num_framechannels )
-       READINT( ofs_frames )
-       READINT( ofs_bounds )
-       READINT( num_comment )
-       READINT( ofs_comment )
-       READINT( num_extensions )
-       READINT( ofs_extensions )
-#undef READINT
-}
-
-typedef struct iqmmesh_s {
-       unsigned int name;
-       unsigned int material;
-       unsigned int first_vertex;
-       unsigned int num_vertexes;
-       unsigned int first_triangle;
-       unsigned int num_triangles;
-} iqmmesh_t;
-
-void istream_read_iqmMesh( PointerInputStream &inputStream, iqmmesh_t &iqmmesh ){
-#define READUINT( x ) iqmmesh.x = istream_read_uint32_le( inputStream );
-       READUINT( name )
-       READUINT( material )
-       READUINT( first_vertex )
-       READUINT( num_vertexes )
-       READUINT( first_triangle )
-       READUINT( num_triangles )
-#undef READUINT
-}
-
-typedef struct iqmvertexarray_s {
-       unsigned int type;
-       unsigned int flags;
-       unsigned int format;
-       unsigned int size;
-       unsigned int offset;
-} iqmvertexarray_t;
-
-void istream_read_iqmVertexarray( PointerInputStream &inputStream, iqmvertexarray_t &vertexarray ){
-#define READINT( x ) vertexarray.x = istream_read_int32_le( inputStream );
-       READINT( type )
-       READINT( flags )
-       READINT( format )
-       READINT( size )
-       READINT( offset )
-#undef READINT
-}
-
-ArbitraryMeshVertex IQMVertex_construct( const iqmPos_t *pos, const iqmPos_t *norm, const iqmSt_t *st ){
-       return ArbitraryMeshVertex(
-               Vertex3f( pos->v[0], pos->v[1], pos->v[2] ),
-               Normal3f( norm->v[0], norm->v[1], norm->v[2] ),
-               TexCoord2f( st->s, st->t )
-               );
-}
-
-void IQMSurface_read( Model &model, const byte *buffer, ArchiveFile &file ){
-       iqmHeader_t header;
-       {
-               PointerInputStream inputStream( buffer );
-               istream_read_iqmHeader( inputStream, header );
-       }
-
-       int ofs_position = -1, ofs_st = -1, ofs_normal = -1;
-       PointerInputStream vaStream( buffer + header.ofs_vertexarrays );
-       for ( unsigned int i = 0; i < header.num_vertexarrays; i++ ) {
-               iqmvertexarray_t va;
-               istream_read_iqmVertexarray( vaStream, va );
-
-               switch ( va.type ) {
-               case IQM_POSITION:
-                       if ( va.format == IQM_FLOAT && va.size == 3 ) {
-                               ofs_position = va.offset;
-                       }
-                       break;
-               case IQM_TEXCOORD:
-                       if ( va.format == IQM_FLOAT && va.size == 2 ) {
-                               ofs_st = va.offset;
-                       }
-                       break;
-               case IQM_NORMAL:
-                       if ( va.format == IQM_FLOAT && va.size == 3 ) {
-                               ofs_normal = va.offset;
-                       }
-                       break;
-               }
-       }
-
-       PointerInputStream posStream( buffer + ofs_position );
-       Array<iqmPos_t> iqmPos( header.num_vertexes );
-       for ( Array<iqmPos_t>::iterator i = iqmPos.begin(); i != iqmPos.end(); ++i ) {
-               istream_read_iqmPos( posStream, *i );
-       }
-
-       PointerInputStream normStream( buffer + ofs_normal );
-       Array<iqmPos_t> iqmNorm( header.num_vertexes );
-       for ( Array<iqmPos_t>::iterator i = iqmNorm.begin(); i != iqmNorm.end(); ++i ) {
-               istream_read_iqmPos( normStream, *i );
-       }
-
-       Array<iqmSt_t> iqmSt( header.num_vertexes );
-       PointerInputStream stStream( buffer + ofs_st );
-       for ( Array<iqmSt_t>::iterator i = iqmSt.begin(); i != iqmSt.end(); ++i ) {
-               istream_read_iqmSt( stStream, *i );
-       }
-
-       PointerInputStream iqmMesh( buffer + header.ofs_meshes );
-       for ( unsigned int m = 0; m < header.num_meshes; m++ ) {
-               Surface &surface = model.newSurface();
-
-               iqmmesh_t iqmmesh;
-               istream_read_iqmMesh( iqmMesh, iqmmesh );
-
-               bool material_found = false;
-               // if not malformed data neither missing string
-               if ( iqmmesh.material <= header.num_text && iqmmesh.material > 0 ) {
-                       char *material;
-                       material = (char*) buffer + header.ofs_text + iqmmesh.material;
-
-                       if ( material[0] != '\0' ) {
-                               surface.setShader( material );
-                               material_found = true;
-                       }
-               }
-
-               if ( !material_found ) {
-                       // empty string will trigger "textures/shader/notex" on display
-                       surface.setShader( "" );
-               }
-
-               UniqueVertexBuffer<ArbitraryMeshVertex> inserter( surface.vertices() );
-               inserter.reserve( iqmmesh.num_vertexes );
-
-               surface.indices().reserve( iqmmesh.num_vertexes );
-
-               unsigned int triangle_offset = header.ofs_triangles + iqmmesh.first_triangle * sizeof( iqmTriangle_t );
-               PointerInputStream triangleStream( buffer + triangle_offset );
-               for ( unsigned int i = 0; i < iqmmesh.num_triangles; ++i ) {
-                       iqmTriangle_t triangle;
-                       istream_read_iqmTriangle( triangleStream, triangle );
-                       for ( int j = 0; j < 3; j++ ) {
-                               surface.indices().insert( inserter.insert( IQMVertex_construct(
-                                                                                                                          &iqmPos[triangle.indices[j]],
-                                                                                                                          &iqmNorm[triangle.indices[j]],
-                                                                                                                          &iqmSt[triangle.indices[j]] ) ) );
-                       }
-               }
-
-               surface.updateAABB();
-       }
-}
-
-void IQMModel_read( Model &model, const byte *buffer, ArchiveFile &file ){
-       IQMSurface_read( model, buffer, file );
-       model.updateAABB();
-}
-
-scene::Node &IQMModel_new( const byte *buffer, ArchiveFile &file ){
-       ModelNode *modelNode = new ModelNode();
-       IQMModel_read( modelNode->model(), buffer, file );
-       return modelNode->node();
-}
-
-scene::Node &IQMModel_default(){
-       ModelNode *modelNode = new ModelNode();
-       Model_constructNull( modelNode->model() );
-       return modelNode->node();
-}
-
-scene::Node &IQMModel_fromBuffer( unsigned char *buffer, ArchiveFile &file ){
-       if ( memcmp( buffer, "INTERQUAKEMODEL", 16 ) ) {
-               globalErrorStream() << "IQM read error: incorrect ident\n";
-               return IQMModel_default();
-       }
-       else {
-               return IQMModel_new( buffer, file );
-       }
-}
-
-scene::Node &loadIQMModel( ArchiveFile &file ){
-       ScopedArchiveBuffer buffer( file );
-       return IQMModel_fromBuffer( buffer.buffer, file );
-}
diff --git a/plugins/iqmmodel/iqm.h b/plugins/iqmmodel/iqm.h
deleted file mode 100644 (file)
index 5e6a014..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#if !defined( INCLUDED_IQM_H )
-#define INCLUDED_IQM_H
-
-namespace scene { class Node; }
-class ArchiveFile;
-
-scene::Node &loadIQMModel( ArchiveFile &file );
-
-#endif
diff --git a/plugins/iqmmodel/modeliqm.def b/plugins/iqmmodel/modeliqm.def
deleted file mode 100644 (file)
index 5791cd7..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-; modeliqm.def : Declares the module parameters for the DLL.
-
-LIBRARY      "MODELIQM"
-
-EXPORTS
-    ; Explicit exports can go here
-       Radiant_RegisterModules @1
diff --git a/plugins/iqmmodel/plugin.cpp b/plugins/iqmmodel/plugin.cpp
deleted file mode 100644 (file)
index b6d896e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "plugin.h"
-
-#include "iscenegraph.h"
-#include "irender.h"
-#include "iselection.h"
-#include "iimage.h"
-#include "imodel.h"
-#include "igl.h"
-#include "ifilesystem.h"
-#include "iundo.h"
-#include "ifiletypes.h"
-#include "iscriplib.h"
-
-#include "modulesystem/singletonmodule.h"
-#include "typesystem.h"
-
-#include "iqm.h"
-
-
-class IQMModelLoader : public ModelLoader {
-public:
-scene::Node &loadModel( ArchiveFile &file ){
-       return loadIQMModel( file );
-}
-};
-
-class ModelDependencies :
-       public GlobalFileSystemModuleRef,
-       public GlobalOpenGLModuleRef,
-       public GlobalUndoModuleRef,
-       public GlobalSceneGraphModuleRef,
-       public GlobalShaderCacheModuleRef,
-       public GlobalSelectionModuleRef,
-       public GlobalFiletypesModuleRef {
-};
-
-class ModelIQMAPI : public TypeSystemRef {
-IQMModelLoader m_modeliqm;
-public:
-typedef ModelLoader Type;
-
-STRING_CONSTANT( Name, "iqm" );
-
-ModelIQMAPI(){
-       GlobalFiletypesModule::getTable().addType( Type::Name(), Name(), filetype_t( "InterQuake Models", "*.iqm" ) );
-}
-
-ModelLoader *getTable(){
-       return &m_modeliqm;
-}
-};
-
-typedef SingletonModule<ModelIQMAPI, ModelDependencies> ModelIQMModule;
-
-ModelIQMModule g_ModelIQMModule;
-
-extern "C" void RADIANT_DLLEXPORT Radiant_RegisterModules( ModuleServer &server ){
-       initialiseModule( server );
-
-       g_ModelIQMModule.selfRegister();
-}
diff --git a/plugins/iqmmodel/plugin.h b/plugins/iqmmodel/plugin.h
deleted file mode 100644 (file)
index c94ee67..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#if !defined( INCLUDED_SAMPLE_H )
-#define INCLUDED_SAMPLE_H
-#endif
index e18ef2f6ca68016edf5dccd31f2fda6eb57caaef..a347c5f4909f2b7e20909cd56cd2a6bab781dc46 100644 (file)
@@ -233,7 +233,8 @@ void MD2Surface_read( Model& model, const byte* buffer, ArchiveFile& file ){
 
        char skinname[MD2_MAX_SKINNAME];
        char skinnameRelative[MD2_MAX_SKINNAME];
-       char path[MD2_MAX_SKINNAME];
+       char path[MD2_MAX_SKINNAME + 1];
+       path[MD2_MAX_SKINNAME] = '\0';
        int i = MD2_MAX_SKINNAME;
        PointerInputStream inputStream( buffer + header.ofs_skins );
        inputStream.read( reinterpret_cast<byte*>( skinnameRelative ), MD2_MAX_SKINNAME );
@@ -255,7 +256,8 @@ void MD2Surface_read( Model& model, const byte* buffer, ArchiveFile& file ){
        }
        else
        {
-               strcpy( skinname, skinnameRelative );
+               strncpy( skinname, skinnameRelative, MD2_MAX_SKINNAME - 1 );
+               skinname[MD2_MAX_SKINNAME - 1] = '\0';
        }
        surface.setShader( skinname );
        surface.updateAABB();
index 4099a11e3bb51ecb30300840d4e7ad13cd8f7713..14308bad3b10beb8a005cdfe677bb7b64e066d82 100644 (file)
@@ -93,9 +93,6 @@ void FreeShaders();
 
 void LoadShaderFile( const char *filename );
 
-qtexture_t *Texture_ForName( const char *filename );
-
-
 /*!
    NOTE TTimo: there is an important distinction between SHADER_NOT_FOUND and SHADER_NOTEX:
    SHADER_NOT_FOUND means we didn't find the raw texture or the shader for this
@@ -273,6 +270,7 @@ class ShaderTemplate
 {
 std::size_t m_refcount;
 CopiedString m_Name;
+CopiedString m_WadName;
 public:
 
 ShaderParameters m_params;
@@ -844,6 +842,7 @@ const ShaderArguments& m_args;
 const char* m_filename;
 // name is shader-name, otherwise texture-name ( if not a real shader )
 CopiedString m_Name;
+CopiedString m_WadName;
 
 qtexture_t* m_pTexture;
 qtexture_t* m_notfound;
@@ -921,6 +920,10 @@ const char* getName() const {
        return m_Name.c_str();
 }
 
+const char* getWadName() const {
+       return m_WadName.c_str();
+}
+
 bool IsInUse() const {
        return m_bInUse;
 }
@@ -1056,6 +1059,10 @@ void setName( const char* name ){
        m_Name = name;
 }
 
+void setWadName( const char* name ){
+       m_WadName = name;
+}
+
 class MapLayer : public ShaderLayer
 {
 qtexture_t* m_texture;
@@ -1105,12 +1112,6 @@ const ShaderLayer* firstLayer() const {
        }
        return &m_layers.front();
 }
-void forEachLayer( const ShaderLayerCallback& callback ) const {
-       for ( MapLayers::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i )
-       {
-               callback( *i );
-       }
-}
 
 qtexture_t* lightFalloffImage() const {
        if ( !string_empty( m_template.m_lightFalloffImage.c_str() ) ) {
index fd881ecf1edbec876618855fd1d56faa2eb28751..098de4993a280b67b28baffab1d0b8d32881dcdf 100644 (file)
@@ -200,8 +200,6 @@ bool CSynapseClientModel::RequestAPI( APIDescriptor_t *pAPI ){
        return false;
 }
 
-#include "version.h"
-
 const char* CSynapseClientModel::GetInfo(){
        return "Sprite Model module built " __DATE__ " " RADIANT_VERSION;
 }
index 2ebd1b012c10209066a116a7a8db9778738bd6ab..aee23c538b6e938777239c077da82cfbbb966edb 100644 (file)
@@ -29,7 +29,6 @@
 #include <stdlib.h>
 
 #if !GDEF_OS_WINDOWS
-
 // Necessary for proper boolean type declaration
 #include "qertypes.h"
 
@@ -77,8 +76,7 @@ typedef struct tagRECT
        long right;
        long bottom;
 } RECT, *PRECT, *LPRECT;
-
-#endif // __linux__
+#endif // !GDEF_OS_WINDOWS
 
 // plugin
 // FIXME TTimo: drop this
index 7d5eba90ff55354369f0bac8c9ff4e0e6350d579..e328bdb08cc73adaf20dc47a19c8ca2973432500 100644 (file)
@@ -892,8 +892,6 @@ bool CSynapseClientTexTool::RequestAPI( APIDescriptor_t *pAPI ){
        return false;
 }
 
-#include "version.h"
-
 const char* CSynapseClientTexTool::GetInfo(){
        return "Texture Tools plugin built " __DATE__ " " RADIANT_VERSION;
 }
index 1cd50a31bd9cf7ed852e6a9f2a7477d0c4ee38da..703a956e15246afa5854a276fb5f692eef52f658 100644 (file)
@@ -129,8 +129,8 @@ static void FixDOSName( char *src ){
 }
 
 const _QERArchiveTable* GetArchiveTable( ArchiveModules& archiveModules, const char* ext ){
-       StringOutputStream tmp( 16 );
-       tmp << LowerCase( ext );
+       std::string tmp = ext;
+       transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
        return archiveModules.findModule( tmp.c_str() );
 }
 
@@ -144,7 +144,7 @@ static Archive* InitPakFile( ArchiveModules& archiveModules, const char *filenam
                entry.archive = table->m_pfnOpenArchive( filename );
                entry.is_pakfile = true;
                g_archives.push_back( entry );
-               globalOutputStream() << "  pak file: " << filename << "\n";
+               globalOutputStream() << "pak file: " << filename << "\n";
 
                return entry.archive;
        }
@@ -282,9 +282,10 @@ bool operator()( const CopiedString& self, const CopiedString& other ) const {
 
 typedef std::set<CopiedString, PakLess> Archives;
 
-Archive* AddPk3Dir( const char* fullpath ){
+Archive* AddPakDir( const char* fullpath ){
        if ( g_numDirs == VFS_MAXDIRS ) return 0;
 
+       globalOutputStream() << "pak directory: " << fullpath << "\n";
        strncpy( g_strDirs[g_numDirs], fullpath, PATH_MAX );
        g_strDirs[g_numDirs][PATH_MAX] = '\0';
        g_numDirs++;
@@ -300,16 +301,16 @@ Archive* AddPk3Dir( const char* fullpath ){
        }
 }
 
-// for Daemon DPK vfs
+// for Daemon DPK VFS
 
 Archive* AddDpkDir( const char* fullpath ){
-       return AddPk3Dir( fullpath );
+       return AddPakDir( fullpath );
 }
 
 struct pakfile_path_t
 {
        CopiedString fullpath;  // full pak dir or pk3dir name
-       bool is_pakfile;  // defines is it .pk3dir or .pk3 file
+       bool is_pakfile;  // tells it is .pk3dir or .pk3 file
 };
 
 typedef std::pair<CopiedString, pakfile_path_t> PakfilePathsKV;
@@ -346,6 +347,9 @@ static const char* GetLatestDpkPakVersion( const char* name ){
 }
 
 // release string after using
+// Note: it also contains the version string,
+// for …/src/map-castle_src.dpkdir/maps/castle.map
+// it will return map-castle_src
 static char* GetCurrentMapDpkPakName(){
        char* mapdir;
        char* mapname;
@@ -355,21 +359,27 @@ static char* GetCurrentMapDpkPakName(){
        mapname = string_clone( GlobalRadiant().getMapName() );
        mapnamelen = string_length( mapname );
 
-       mapdir = strrchr( mapname, '/' );
-       if ( mapdir ) {
-               mapdir -= 12;
-               if ( strncmp( mapdir, ".dpkdir/maps/", 13 ) == 0 ) {
-                       *mapdir = '\0';
-                       mapdir = strrchr( mapname, '/' );
-                       if ( mapdir ) mapdir++;
-                       else mapdir = mapname;
-                       result = string_clone( mapdir );
+       char pattern[] = ".dpkdir/";
+       char* end = strstr( mapname, ".dpkdir/" );
+       if ( end )
+       {
+               end[ 0 ] = '\0';
+
+               mapdir = strrchr( mapname, '/' );
+               if ( mapdir )
+               {
+                       mapdir++;
+               }
+               else
+               {
+                       mapdir = mapname;
                }
+
+               result = string_clone( mapdir );
        }
 
        string_release( mapname, mapnamelen );
        return result;
-
 }
 
 // prevent loading duplicates or circular references
@@ -383,9 +393,9 @@ static void LoadDpkPakWithDeps( const char* pakname ){
 
        if (pakname == NULL) {
                // load DEPS from game pack
-               StringOutputStream baseDirectory( 256 );
-               const char* basegame = GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" );
-               baseDirectory << GlobalRadiant().getGameToolsPath() << basegame << '/';
+               std::string baseDirectory( GlobalRadiant().getGameToolsPath() );
+               baseDirectory += GlobalRadiant().getRequiredGameDescriptionKeyValue( "basegame" );
+               baseDirectory += '/';
                arc = AddDpkDir( baseDirectory.c_str() );
                depsFile = arc->openTextFile( "DEPS" );
        } else {
@@ -453,6 +463,7 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
 
        g_numForbiddenDirs = 0;
        StringTokeniser st( GlobalRadiant().getGameDescriptionKeyValue( "forbidden_paths" ), " " );
+
        for ( j = 0; j < VFS_MAXDIRS; ++j )
        {
                const char *t = st.getToken();
@@ -478,6 +489,7 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                }
                g_free( dbuf );
        }
+
        if ( j < g_numForbiddenDirs ) {
                printf( "Directory %s matched by forbidden dirs, removed\n", directory );
                return;
@@ -508,20 +520,22 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
 
                GDir* dir = g_dir_open( path, 0, 0 );
 
-               if ( dir != 0 ) {
+               if ( dir != NULL ) {
                        globalOutputStream() << "vfs directory: " << path << "\n";
 
                        Archives archives;
                        Archives archivesOverride;
                        const char* ignore_prefix = "";
                        const char* override_prefix = "";
-                       bool is_pk3_vfs, is_pk4_vfs, is_dpk_vfs;
+                       bool is_wad_vfs, is_pak_vfs, is_pk3_vfs, is_pk4_vfs, is_dpk_vfs;
 
-                       is_pk3_vfs = GetArchiveTable( archiveModules, "pk3" );
-                       is_pk4_vfs = GetArchiveTable( archiveModules, "pk4" );
-                       is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" );
+                       is_wad_vfs = !!GetArchiveTable( archiveModules, "wad" );
+                       is_pak_vfs = !!GetArchiveTable( archiveModules, "pak" );
+                       is_pk3_vfs = !!GetArchiveTable( archiveModules, "pk3" );
+                       is_pk4_vfs = !!GetArchiveTable( archiveModules, "pk4" );
+                       is_dpk_vfs = !!GetArchiveTable( archiveModules, "dpk" );
 
-                       if ( !is_dpk_vfs ) {
+                       if ( is_dpk_vfs ) {
                                // See if we are in "sp" or "mp" mapping mode
                                const char* gamemode = gamemode_get();
 
@@ -535,10 +549,11 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                                }
                        }
 
-                       for (;; )
+                       while ( true )
                        {
                                const char* name = g_dir_read_name( dir );
-                               if ( name == 0 ) {
+
+                               if ( name == nullptr ) {
                                        break;
                                }
 
@@ -550,36 +565,36 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                                                break;
                                        }
                                }
+
                                if ( j < g_numForbiddenDirs ) {
                                        continue;
                                }
 
                                const char *ext = strrchr( name, '.' );
-                               char tmppath[PATH_MAX];
+                               char tmppath[PATH_MAX + 1];
 
-                               if ( is_dpk_vfs ) {
-                                       if ( !!ext && !string_compare_nocase_upper( ext, ".dpkdir" ) ) {
+                               if ( ext != nullptr ) {
+                                       if ( is_dpk_vfs && !string_compare_nocase_upper( ext, ".dpkdir" ) ) {
                                                snprintf( tmppath, PATH_MAX, "%s%s/", path, name );
                                                tmppath[PATH_MAX] = '\0';
                                                FixDOSName( tmppath );
                                                AddSlash( tmppath );
                                                AddDpkPak( CopiedString( StringRange( name, ext ) ).c_str(), tmppath, false );
                                        }
-                               }
 
-                               if ( is_pk3_vfs || is_pk4_vfs ) {
-                                       if ( !!ext && ( !string_compare_nocase_upper( ext, ".pk3dir" )
-                                               || !string_compare_nocase_upper( ext, ".pk4dir" ) ) ) {
+                                       else if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".pakdir" ) )
+                                               || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3dir" ) )
+                                               || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4dir" ) ) ) {
                                                snprintf( tmppath, PATH_MAX, "%s%s/", path, name );
                                                tmppath[PATH_MAX] = '\0';
                                                FixDOSName( tmppath );
                                                AddSlash( tmppath );
-                                               AddPk3Dir( tmppath );
+                                               AddPakDir( tmppath );
                                        }
                                }
 
                                // GetArchiveTable() needs "pk3" if ext is ".pk3"
-                               if ( ( ext == 0 ) || *( ext + 1 ) == '\0' || GetArchiveTable( archiveModules, ext + 1 ) == 0 ) {
+                               if ( ( ext == nullptr ) || *( ext + 1 ) == '\0' || GetArchiveTable( archiveModules, ext + 1 ) == 0 ) {
                                        continue;
                                }
 
@@ -587,16 +602,18 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                                if ( !string_empty( ignore_prefix ) && strncmp( name, ignore_prefix, strlen( ignore_prefix ) ) == 0 ) {
                                        continue;
                                }
+
                                if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) {
                                        if ( !string_compare_nocase_upper( ext, ".dpk" ) ) {
                                                if ( is_dpk_vfs ) {
                                                        archives.insert( name );
+                                                       continue;
                                                }
                                        }
                                        else {
                                                archivesOverride.insert( name );
+                                               continue;
                                        }
-                                       continue;
                                }
 
                                archives.insert( name );
@@ -610,7 +627,8 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                                for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i ) {
                                        const char* name = i->c_str();
                                        const char* ext = strrchr( name, '.' );
-                                       if ( !string_compare_nocase_upper( ext, ".dpk" ) ) {
+                                       if ( !string_compare_nocase_upper( ext, ".dpk" ) )
+                                       {
                                                CopiedString name_final = CopiedString( StringRange( name, ext ) );
                                                fullpath = string_new_concat( path, name );
                                                AddDpkPak( name_final.c_str(), fullpath, true );
@@ -618,24 +636,30 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){
                                        }
                                }
                        }
-                       if ( is_pk3_vfs || is_pk4_vfs ) {
+                       else
+                       {
                                for ( Archives::iterator i = archivesOverride.begin(); i != archivesOverride.end(); ++i )
                                {
                                        const char* name = i->c_str();
                                        const char* ext = strrchr( name, '.' );
-                                       if ( !string_compare_nocase_upper( ext, ".pk3" )
-                                               || !string_compare_nocase_upper( ext, ".pk4" ) ) {
+                                       if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".wad" ) )
+                                               || ( is_pak_vfs && !string_compare_nocase_upper( ext, ".pak" ) )
+                                               || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3" ) )
+                                               || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4" ) ) ) {
                                                fullpath = string_new_concat( path, i->c_str() );
                                                InitPakFile( archiveModules, fullpath );
                                                string_release( fullpath, string_length( fullpath ) );
                                        }
                                }
+
                                for ( Archives::iterator i = archives.begin(); i != archives.end(); ++i )
                                {
                                        const char* name = i->c_str();
                                        const char* ext = strrchr( name, '.' );
-                                       if ( !string_compare_nocase_upper( ext, ".pk3" )
-                                               || !string_compare_nocase_upper( ext, ".pk4" ) ) {
+                                       if ( ( is_wad_vfs && !string_compare_nocase_upper( ext, ".wad" ) )
+                                               || ( is_pak_vfs && !string_compare_nocase_upper( ext, ".pak" ) )
+                                               || ( is_pk3_vfs && !string_compare_nocase_upper( ext, ".pk3" ) )
+                                               || ( is_pk4_vfs && !string_compare_nocase_upper( ext, ".pk4" ) ) ) {
                                                fullpath = string_new_concat( path, i->c_str() );
                                                InitPakFile( archiveModules, fullpath );
                                                string_release( fullpath, string_length( fullpath ) );
@@ -805,7 +829,7 @@ void initialise(){
 
 void load(){
        ArchiveModules& archiveModules = FileSystemQ3API_getArchiveModules();
-       bool is_dpk_vfs = GetArchiveTable( archiveModules, "dpk" );
+       bool is_dpk_vfs = !!GetArchiveTable( archiveModules, "dpk" );
 
        if ( is_dpk_vfs ) {
                const char* pakname;
@@ -919,6 +943,9 @@ Archive* getArchive( const char* archiveName, bool pakonly ){
                if ( path_equal( ( *i ).name.c_str(), archiveName ) ) {
                        return ( *i ).archive;
                }
+               else if ( path_equal( path_get_filename_start( ( *i ).name.c_str() ), archiveName ) ) {
+                       return ( *i ).archive;
+               }
        }
        return 0;
 }
index 6f0a250a175a58da2f8b87fc3eb73b8dfff1c17f..ae33bcea7dd884f5b0babe17e55691a6b323517b 100644 (file)
@@ -37,7 +37,6 @@ set(RADIANTLIST
     filterbar.cpp filterbar.h
     filters.cpp filters.h
     findtexturedialog.cpp findtexturedialog.h
-    glwidget.cpp glwidget.h
     grid.cpp grid.h
     groupdialog.cpp groupdialog.h
     gtkdlgs.cpp gtkdlgs.h
@@ -92,13 +91,14 @@ set(RADIANTLIST
     xmlstuff.cpp xmlstuff.h
     xywindow.cpp xywindow.h
 )
+
 if (WIN32)
     list(APPEND RADIANTLIST multimon.cpp multimon.h)
-endif()
+endif ()
 
-radiant_tool(radiant WIN32 radiant.rc ${RADIANTLIST})
-add_dependencies(radiant modules)
-target_link_libraries(radiant
+radiant_tool(${RADIANT_BASENAME} WIN32 radiant.rc ${RADIANTLIST})
+add_dependencies(${RADIANT_BASENAME} modules)
+target_link_libraries(${RADIANT_BASENAME}
     ${CMAKE_DL_LIBS}
     ${LIBXML2_LIBRARIES}
     ${OPENGL_gl_LIBRARY}
@@ -125,11 +125,35 @@ target_link_libraries(radiant
     splines
     stream
     string
+    transformpath
     uilib
     xmllib
 )
+
 if (X11_LIBRARIES)
-    target_link_libraries(radiant ${X11_LIBRARIES})
+    target_link_libraries(${RADIANT_BASENAME} ${X11_LIBRARIES})
 endif ()
 
-copy_dlls(radiant)
+# PIE executables were wrongly recognized as shared libraries on Linux
+# because of a mistake in the mime-type library.
+# Because of that it was not possible to launch such executables from
+# the file browser.
+#
+# While the problem is fixed upstream, most distributions still ship
+# with a faulty mime-type library and may do for a long time.
+#
+# See: https://gitlab.freedesktop.org/xdg/shared-mime-info/-/issues/11
+#
+# It may produce such warning though at strip time:
+#   warning: allocated section `.dynstr' not in segment
+# and produce an unusable binary, better not strip when using this hack.
+#
+# This hack is only wanted for release build and
+# when NetRadiant is not installed system-wide.
+if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux"
+    AND "${CMAKE_BUILD_TYPE}" STREQUAL "Release"
+    AND NOT FHS_INSTALL)
+    target_link_libraries(${RADIANT_BASENAME} -no-pie)
+endif()
+
+copy_dlls(${RADIANT_BASENAME})
index 56a2ec4a86d5764fca50d118f62c5d99ed41747a..3249cda0f2d994c4ff0f8aa3eaef260e5238db97 100644 (file)
@@ -307,7 +307,6 @@ class FaceShaderObserver
 {
 public:
 virtual void realiseShader() = 0;
-
 virtual void unrealiseShader() = 0;
 };
 
@@ -362,7 +361,7 @@ SavedState( const FaceShader& faceShader ){
 
 void exportState( FaceShader& faceShader ) const {
        faceShader.setShader( m_shader.c_str() );
-       faceShader.setFlags( m_flags );
+                       faceShader.m_flags = m_flags;
 }
 };
 
@@ -655,6 +654,8 @@ static bool isDoom3Plane(){
        return FacePlane::m_type == eBrushTypeDoom3 || FacePlane::m_type == eBrushTypeQuake4;
 }
 
+       FacePlane& operator=(const FacePlane&) = default;
+
 class SavedState
 {
 public:
@@ -868,11 +869,8 @@ class FaceObserver
 {
 public:
 virtual void planeChanged() = 0;
-
 virtual void connectivityChanged() = 0;
-
 virtual void shaderChanged() = 0;
-
 virtual void evaluateTransform() = 0;
 };
 
@@ -1410,8 +1408,7 @@ inline bool plane3_inside( const Plane3& self, const Plane3& other, bool selfIsL
        return true;
 }
 
-typedef SmartPointer<Face> FaceSmartPointer;
-typedef std::vector<FaceSmartPointer> Faces;
+typedef std::vector<std::shared_ptr<Face>> Faces;
 
 /// \brief Returns the unique-id of the edge adjacent to \p faceVertex in the edge-pair for the set of \p faces.
 inline FaceVertexId next_edge( const Faces& faces, FaceVertexId faceVertex ){
@@ -1493,25 +1490,15 @@ class BrushObserver
 {
 public:
 virtual void reserve( std::size_t size ) = 0;
-
 virtual void clear() = 0;
-
 virtual void push_back( Face& face ) = 0;
-
 virtual void pop_back() = 0;
-
 virtual void erase( std::size_t index ) = 0;
-
 virtual void connectivityChanged() = 0;
-
 virtual void edge_clear() = 0;
-
 virtual void edge_push_back( SelectableEdge& edge ) = 0;
-
 virtual void vertex_clear() = 0;
-
 virtual void vertex_push_back( SelectableVertex& vertex ) = 0;
-
 virtual void DEBUG_verify() const = 0;
 };
 
@@ -1900,24 +1887,24 @@ bool isDetail(){
 }
 
 /// \brief Appends a copy of \p face to the end of the face list.
-Face* addFace( const Face& face ){
+       std::shared_ptr<Face> addFace( const Face& face ){
        if ( m_faces.size() == c_brush_maxFaces ) {
                return 0;
        }
        undoSave();
-       push_back( FaceSmartPointer( new Face( face, this ) ) );
+               push_back( std::make_shared<Face>( face, this ) );
        m_faces.back()->setDetail( isDetail() );
        planeChanged();
        return m_faces.back();
 }
 
 /// \brief Appends a new face constructed from the parameters to the end of the face list.
-Face* addPlane( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection ){
+       std::shared_ptr<Face> addPlane( const Vector3& p0, const Vector3& p1, const Vector3& p2, const char* shader, const TextureProjection& projection ){
        if ( m_faces.size() == c_brush_maxFaces ) {
                return 0;
        }
        undoSave();
-       push_back( FaceSmartPointer( new Face( p0, p1, p2, shader, projection, this ) ) );
+               push_back( std::make_shared<Face>( p0, p1, p2, shader, projection, this ) );
        m_faces.back()->setDetail( isDetail() );
        planeChanged();
        return m_faces.back();
@@ -1961,11 +1948,11 @@ const_iterator end() const {
        return m_faces.end();
 }
 
-Face* back(){
+       std::shared_ptr<Face> back(){
        return m_faces.back();
 }
 
-const Face* back() const {
+       const std::shared_ptr<Face> back() const {
        return m_faces.back();
 }
 
@@ -3171,6 +3158,7 @@ TransformModifier m_transform;
 
 BrushInstance( const BrushInstance& other ); // NOT COPYABLE
 BrushInstance& operator=( const BrushInstance& other ); // NOT ASSIGNABLE
+
 public:
 static Counter* m_counter;
 
index 79fde7b931ca55b59dacb817b651272933347640..549e6e87da1ebf6cddc0d5a0cc927d6dbcccfebe 100644 (file)
@@ -868,6 +868,9 @@ filter_brush_any_face g_filter_brush_hint_q2( &g_filter_face_hint_q2 );
 filter_face_shader g_filter_face_hint_ja( "textures/system/hint" );
 filter_brush_any_face g_filter_brush_hint_ja( &g_filter_face_hint_ja );
 
+filter_face_shader g_filter_face_subtlehint( "textures/common/subtlehint" );
+filter_brush_any_face g_filter_brush_subtlehint( &g_filter_face_subtlehint );
+
 filter_face_shader g_filter_face_areaportal( "textures/common/areaportal" );
 filter_brush_any_face g_filter_brush_areaportal( &g_filter_face_areaportal );
 
@@ -907,6 +910,7 @@ void BrushFilters_construct(){
        add_brush_filter( g_filter_brush_hintlocal, EXCLUDE_HINTSSKIPS );
        add_brush_filter( g_filter_brush_hint_q2, EXCLUDE_HINTSSKIPS );
        add_brush_filter( g_filter_brush_hint_ja, EXCLUDE_HINTSSKIPS );
+       add_brush_filter( g_filter_brush_subtlehint, EXCLUDE_HINTSSKIPS );
        add_brush_filter( g_filter_brush_clusterportal, EXCLUDE_CLUSTERPORTALS );
        add_brush_filter( g_filter_brush_visportal, EXCLUDE_VISPORTALS );
        add_brush_filter( g_filter_brush_areaportal, EXCLUDE_AREAPORTALS );
index 2ab573e514601c7d8b451eca7a8caa448b1e1ae3..6a9565df8906a24823573a8ff180c288d3be49bb 100644 (file)
@@ -100,6 +100,16 @@ int Brush_toggleFormatCount(){
        return 1;
 }
 
+void Brush_switchFormat( bool switch_format ){
+       if ( switch_format )
+       {
+               g_useAlternativeTextureProjection.m_latched = g_useAlternativeTextureProjection.m_value;
+               g_useAlternativeTextureProjection.m_value = !g_useAlternativeTextureProjection.m_value;
+               PreferencesDialog_restartRequired( g_useAlternativeTextureProjection.m_description );
+               PreferencesDialog_restartIfRequired();
+       }
+}
+
 void Brush_Construct( EBrushType type ){
        if ( type == eBrushTypeQuake3 ) {
                g_showAlternativeTextureProjectionOption = true;
@@ -113,6 +123,7 @@ void Brush_Construct( EBrushType type ){
                        "AlternativeTextureProjection",
                        make_property_string( g_useAlternativeTextureProjection.m_latched )
                        );
+
                g_useAlternativeTextureProjection.useLatched();
 
                if ( g_useAlternativeTextureProjection.m_value ) {
index a5c67e3c88d65819779499089974e173000ec0e1..5d8deee836967a8b113e7033b9a5c90311cb7cd4 100644 (file)
@@ -26,5 +26,6 @@ void Brush_clipperColourChanged();
 void Brush_unlatchPreferences();
 int Brush_toggleFormatCount();
 void Brush_toggleFormat( int i );
+void Brush_switchFormat( bool switch_format );
 
 #endif
index 9b4d4fab05caaf3b63f87c66666eda79894cdf9a..af95360ae874f09d5aa41e2182fb51313696c5a5 100644 (file)
@@ -509,59 +509,58 @@ bool importTokens( Tokeniser& tokeniser ){
 
                tokeniser.ungetToken();
 
-               m_brush.push_back( FaceSmartPointer( new Face( &m_brush ) ) );
+               std::shared_ptr<Face> face = std::make_shared<Face>( &m_brush );
+               m_brush.push_back( face );
 
                //!todo BP support
                tokeniser.nextLine();
 
-               Face& face = *m_brush.back();
-
                switch ( Brush::m_type )
                {
                case eBrushTypeDoom3:
                {
-                       Doom3FaceTokenImporter importer( face );
+                       Doom3FaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeQuake4:
                {
-                       Quake4FaceTokenImporter importer( face );
+                       Quake4FaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeQuake2:
                {
-                       Quake2FaceTokenImporter importer( face );
+                       Quake2FaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeQuake3:
                {
-                       Quake3FaceTokenImporter importer( face );
+                       Quake3FaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeQuake3BP:
                {
-                       Quake3BPFaceTokenImporter importer( face );
+                       Quake3BPFaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeQuake:
                {
-                       QuakeFaceTokenImporter importer( face );
+                       QuakeFaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                case eBrushTypeHalfLife:
                {
-                       HalfLifeFaceTokenImporter importer( face );
+                       HalfLifeFaceTokenImporter importer( *face );
                        RETURN_FALSE_IF_FAIL( importer.importTokens( tokeniser ) );
                }
                break;
                }
-               face.planeChanged();
+               face->planeChanged();
        }
        if ( Brush::m_type == eBrushTypeQuake3BP || Brush::m_type == eBrushTypeDoom3 || Brush::m_type == eBrushTypeQuake4 ) {
                tokeniser.nextLine();
index c1fac55bccc0cdaced23d17a5cb3ebc5a9b0e590..d7add40832f583dda5d9ebcf1effe9c91627f714 100644 (file)
@@ -351,7 +351,7 @@ void pushElement( const XMLElement& element ){
        case xml_state_t::eBrush:
                ASSERT_MESSAGE( strcmp( element.name(), "plane" ) == 0, "parse error" );
                m_xml_state.push_back( xml_state_t::eFace );
-               m_brush.push_back( FaceSmartPointer( new Face( &m_brush ) ) );
+               m_brush.push_back( std::make_shared<Face>( &m_brush ) );
                constructor( faceImporter(), makeReference( *m_brush.back() ) );
                m_brush.planeChanged();
                m_brush.shaderChanged();
index 5e86dc85037db67a52d44290298e23984dd1eb50..179ae632342194b3148c7c78b90930845afb7e67 100644 (file)
@@ -41,12 +41,12 @@ void build_set_variable( const char* name, const char* value ){
        g_build_variables[name] = value;
 }
 
-const char* build_get_variable( const char* name ){
-       Variables::iterator i = g_build_variables.find( name );
+const char* build_get_variable( const std::string& name ){
+       Variables::iterator i = g_build_variables.find( name.c_str() );
        if ( i != g_build_variables.end() ) {
                return ( *i ).second.c_str();
        }
-       globalErrorStream() << "undefined build variable: " << makeQuoted( name ) << "\n";
+       globalErrorStream() << "undefined build variable: " << makeQuoted( name.c_str() ) << "\n";
        return "";
 }
 
@@ -57,55 +57,80 @@ class Evaluatable
 {
 public:
 virtual ~Evaluatable() = default;
-virtual void evaluate( StringBuffer& output ) = 0;
+virtual std::string evaluate() = 0;
 virtual void exportXML( XMLImporter& importer ) = 0;
 };
 
 class VariableString : public Evaluatable
 {
-CopiedString m_string;
+std::string m_string;
 public:
 VariableString() : m_string(){
 }
-VariableString( const char* string ) : m_string( string ){
+VariableString( std::string string ) : m_string( std::move(string) ){
 }
 const char* c_str() const {
        return m_string.c_str();
 }
-void setString( const char* string ){
+void setString( const std::string& string ){
        m_string = string;
 }
-void evaluate( StringBuffer& output ){
-       StringBuffer variable;
+std::string evaluate(){
+       // replace ".[ExecutableType]" with "[ExecutableExt]"
+       {
+               size_t pos;
+               const std::string pattern = ".[ExecutableType]";
+               while ( ( pos = m_string.find(pattern) ) != std::string::npos ) {
+                       m_string.replace(pos, pattern.length(), "[ExecutableExt]");
+               }
+       }
+
+       // add missing [ExtraQ3map2Args] if "[RadiantPath]q3map2[ExecutableExt]"
+       {
+               size_t pos;
+               const std::string pattern = "\"[RadiantPath]q3map2[ExecutableExt]\"";
+               const std::string extra = "[ExtraQ3map2Args]";
+               if ( ( pos = m_string.find(pattern) ) != std::string::npos
+                               && m_string.find(extra) == std::string::npos )
+               {
+                       m_string.insert(pos + pattern.size(), " ");
+                       m_string.insert(pos + pattern.size() + 1, extra);
+               }
+       }
+
+       std::string output;
+       std::string variable_name;
        bool in_variable = false;
-       for ( const char* i = m_string.c_str(); *i != '\0'; ++i )
+       for ( const char c : m_string )
        {
                if ( !in_variable ) {
-                       switch ( *i )
+                       switch ( c )
                        {
                        case '[':
                                in_variable = true;
                                break;
                        default:
-                               output.push_back( *i );
+                               output += c;
                                break;
                        }
                }
                else
                {
-                       switch ( *i )
+                       switch ( c )
                        {
                        case ']':
                                in_variable = false;
-                               output.push_string( build_get_variable( variable.c_str() ) );
-                               variable.clear();
+                               output += build_get_variable( variable_name );
+                               variable_name.clear();
                                break;
                        default:
-                               variable.push_back( *i );
+                               variable_name += c;
                                break;
                        }
                }
        }
+
+       return output;
 }
 void exportXML( XMLImporter& importer ){
        importer << c_str();
@@ -123,12 +148,12 @@ Conditional( VariableString* test ) : m_test( test ){
        delete m_test;
        delete m_result;
 }
-void evaluate( StringBuffer& output ){
-       StringBuffer buffer;
-       m_test->evaluate( buffer );
-       if ( !string_empty( buffer.c_str() ) ) {
-               m_result->evaluate( output );
+std::string evaluate(){
+       std::string result = m_test->evaluate();
+       if ( result.empty() ) {
+               return result;
        }
+       return m_result->evaluate();
 }
 void exportXML( XMLImporter& importer ){
        StaticElement conditionElement( "cond" );
@@ -154,11 +179,13 @@ public:
 void push_back( Evaluatable* evaluatable ){
        m_evaluatables.push_back( evaluatable );
 }
-void evaluate( StringBuffer& output ){
+std::string evaluate(){
+       std::string result;
        for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i )
        {
-               ( *i )->evaluate( output );
+               result += ( *i )->evaluate();
        }
+       return result;
 }
 void exportXML( XMLImporter& importer ){
        for ( Evaluatables::iterator i = m_evaluatables.begin(); i != m_evaluatables.end(); ++i )
@@ -180,16 +207,16 @@ virtual void popElement( const char* name ) = 0;
 
 class VariableStringXMLConstructor : public XMLElementParser
 {
-StringBuffer m_buffer;
+std::string m_buffer;
 VariableString& m_variableString;
 public:
 VariableStringXMLConstructor( VariableString& variableString ) : m_variableString( variableString ){
 }
 ~VariableStringXMLConstructor(){
-       m_variableString.setString( m_buffer.c_str() );
+       m_variableString.setString( std::move(m_buffer) );
 }
 std::size_t write( const char* buffer, std::size_t length ){
-       m_buffer.push_range( buffer, buffer + length );
+       m_buffer.append( buffer, length );
        return length;
 }
 XMLElementParser& pushElement( const XMLElement& element ){
@@ -202,16 +229,16 @@ void popElement( const char* name ){
 
 class ConditionalXMLConstructor : public XMLElementParser
 {
-StringBuffer m_buffer;
+std::string m_buffer;
 Conditional& m_conditional;
 public:
 ConditionalXMLConstructor( Conditional& conditional ) : m_conditional( conditional ){
 }
 ~ConditionalXMLConstructor(){
-       m_conditional.m_result = new VariableString( m_buffer.c_str() );
+       m_conditional.m_result = new VariableString( std::move( m_buffer ) );
 }
 std::size_t write( const char* buffer, std::size_t length ){
-       m_buffer.push_range( buffer, buffer + length );
+       m_buffer.append( buffer, length );
        return length;
 }
 XMLElementParser& pushElement( const XMLElement& element ){
@@ -224,7 +251,7 @@ void popElement( const char* name ){
 
 class ToolXMLConstructor : public XMLElementParser
 {
-StringBuffer m_buffer;
+std::string m_buffer;
 Tool& m_tool;
 ConditionalXMLConstructor* m_conditional;
 public:
@@ -234,7 +261,7 @@ ToolXMLConstructor( Tool& tool ) : m_tool( tool ){
        flush();
 }
 std::size_t write( const char* buffer, std::size_t length ){
-       m_buffer.push_range( buffer, buffer + length );
+       m_buffer.append( buffer, length );
        return length;
 }
 XMLElementParser& pushElement( const XMLElement& element ){
@@ -259,7 +286,7 @@ void popElement( const char* name ){
 
 void flush(){
        if ( !m_buffer.empty() ) {
-               m_tool.push_back( new VariableString( m_buffer.c_str() ) );
+               m_tool.push_back( new VariableString( std::move( m_buffer ) ) );
                m_buffer.clear();
        }
 }
@@ -474,8 +501,7 @@ void project_verify( Project& project, Tools& tools ){
 void build_run( const char* name, CommandListener& listener ){
        for ( Tools::iterator i = g_build_tools.begin(); i != g_build_tools.end(); ++i )
        {
-               StringBuffer output;
-               ( *i ).second.evaluate( output );
+               std::string output = ( *i ).second.evaluate();
                build_set_variable( ( *i ).first.c_str(), output.c_str() );
        }
 
@@ -485,8 +511,7 @@ void build_run( const char* name, CommandListener& listener ){
                        Build& build = ( *i ).second;
                        for ( Build::iterator j = build.begin(); j != build.end(); ++j )
                        {
-                               StringBuffer output;
-                               ( *j ).evaluate( output );
+                               std::string output = ( *j ).evaluate();
                                listener.execute( output.c_str() );
                        }
                }
@@ -760,7 +785,7 @@ gboolean project_selection_changed( ui::TreeSelection selection, ui::ListStore s
        return FALSE;
 }
 
-gboolean commands_cell_edited(ui::CellRendererText cell, gchar* path_string, gchar* new_text, ui::ListStore store ){
+gboolean commands_cell_edited(ui::CellRendererText cell, const gchar* path_string, const gchar* new_text, ui::ListStore store ){
        if ( g_current_build == 0 ) {
                return FALSE;
        }
@@ -826,6 +851,12 @@ gboolean commands_key_press( ui::TreeView widget, GdkEventKey* event, ui::ListSt
 ui::Window BuildMenuDialog_construct( ModalDialog& modal, ProjectList& projectList ){
        ui::Window window = MainFrame_getWindow().create_dialog_window("Build Menu", G_CALLBACK(dialog_delete_callback ), &modal, -1, 400 );
 
+       // FIXME: GTK_WIN_POS_CENTER_ON_PARENT must be used instead but does not work
+       // for unknown reason.
+       // It's possible MaingFrame_getWindow() does not return the main window.
+       // It's known the preferences window has same issue when using MaingFrame_getWindow().
+       gtk_window_set_position( window, GTK_WIN_POS_CENTER_ALWAYS );
+
        {
                auto table1 = create_dialog_table( 2, 2, 4, 4, 4 );
                window.add(table1);
@@ -878,7 +909,7 @@ ui::Window BuildMenuDialog_construct( ModalDialog& modal, ProjectList& projectLi
                        }
                }
                {
-                       auto frame = create_dialog_frame( "Commandline" );
+                       auto frame = create_dialog_frame( "Command line" );
             table1.attach(frame, {0, 1, 1, 2});
                        {
                                auto scr = create_scrolled_window( ui::Policy::NEVER, ui::Policy::AUTOMATIC, 4 );
index 804d6461a71c16a759e8fe004e420cfad688982b..accdb30ae9dd2a1aef910ede359fecdacf7459b2 100644 (file)
@@ -76,6 +76,7 @@ void CameraMovedNotify(){
 
 struct camwindow_globals_private_t
 {
+       int m_nFOV;
        int m_nMoveSpeed;
        bool m_bCamLinkSpeed;
        int m_nAngleSpeed;
@@ -86,6 +87,7 @@ struct camwindow_globals_private_t
        int m_nStrafeMode;
 
        camwindow_globals_private_t() :
+               m_nFOV( 110 ),
                m_nMoveSpeed( 100 ),
                m_bCamLinkSpeed( true ),
                m_nAngleSpeed( 3 ),
@@ -151,8 +153,6 @@ struct camera_t
        guint m_keymove_handler;
 
 
-       float fieldOfView;
-
        DeferredMotionDelta m_mouseMove;
 
        static void motionDelta( int x, int y, void* data ){
@@ -171,9 +171,11 @@ struct camera_t
                origin( 0, 0, 0 ),
                angles( 0, 0, 0 ),
                color( 0, 0, 0 ),
+               projection( g_matrix4_identity ),
+               modelview( g_matrix4_identity ),
                movementflags( 0 ),
+               m_keycontrol_timer(),
                m_keymove_handler( 0 ),
-               fieldOfView( 110.0f ),
                m_mouseMove( motionDelta, this ),
                m_view( view ),
                m_update( update ){
@@ -202,7 +204,7 @@ float Camera_getFarClipPlane( camera_t& camera ){
 
 void Camera_updateProjection( camera_t& camera ){
        float farClip = Camera_getFarClipPlane( camera );
-       camera.projection = projection_for_camera( farClip / 4096.0f, farClip, camera.fieldOfView, camera.width, camera.height );
+       camera.projection = projection_for_camera( farClip / 4096.0f, farClip, (float)g_camwindow_globals_private.m_nFOV, camera.width, camera.height );
 
        camera.m_view->Construct( camera.projection, camera.modelview, camera.width, camera.height );
 }
@@ -527,6 +529,9 @@ typedef ReferenceCaller<camera_t, void(), &Camera_MoveDown_KeyDown> FreeMoveCame
 typedef ReferenceCaller<camera_t, void(), &Camera_MoveDown_KeyUp> FreeMoveCameraMoveDownKeyUpCaller;
 
 
+const float MIN_FOV = 60;
+const float MAX_FOV = 179;
+const float FOV_STEP = 10;
 const float SPEED_MOVE = 32;
 const float SPEED_TURN = 22.5;
 const float MIN_CAM_SPEED = 10;
@@ -1297,7 +1302,7 @@ void CamWnd::Cam_PositionDrag(){
                CamWnd_Update( camwnd );
                CameraMovedNotify();
 
-               Sys_SetCursorPos( m_parent, m_PositionDragCursorX, m_PositionDragCursorY );
+               Sys_SetCursorPos( m_gl_widget, m_PositionDragCursorX, m_PositionDragCursorY );
        }
 }
 #endif
@@ -1322,7 +1327,9 @@ void CamWnd::EnableFreeMove(){
 
        gtk_window_set_focus( m_parent, m_gl_widget );
        m_freemove_handle_focusout = m_gl_widget.connect( "focus_out_event", G_CALLBACK( camwindow_freemove_focusout ), this );
-       m_freezePointer.freeze_pointer( m_parent, m_gl_widget, Camera_motionDelta, &m_Camera );
+       /* We chose to replace m_parent by m_gl_widget but NetRadiantCustom does:
+       m_freezePointer.freeze_pointer( m_parent, m_gl_widget, Camera_motionDelta, &m_Camera ); */
+       m_freezePointer.freeze_pointer( m_gl_widget, Camera_motionDelta, &m_Camera );
 
        CamWnd_Update( *this );
 }
@@ -1337,7 +1344,7 @@ void CamWnd::DisableFreeMove(){
        CamWnd_Remove_Handlers_FreeMove( *this );
        CamWnd_Add_Handlers_Move( *this );
 
-       m_freezePointer.unfreeze_pointer( m_parent );
+       m_freezePointer.unfreeze_pointer( m_gl_widget );
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_freemove_handle_focusout );
 
        CamWnd_Update( *this );
@@ -1391,9 +1398,11 @@ void PopState(){
        m_state_stack.pop_back();
 }
 void Highlight( EHighlightMode mode, bool bEnable = true ){
-       ( bEnable )
-       ? m_state_stack.back().m_highlight |= mode
-                                                                                 : m_state_stack.back().m_highlight &= ~mode;
+       if ( bEnable ) {
+               m_state_stack.back().m_highlight |= mode;
+       } else {
+               m_state_stack.back().m_highlight &= ~mode;
+       }
 }
 void setLights( const LightList& lights ){
        m_state_stack.back().m_lights = &lights;
@@ -1616,7 +1625,7 @@ void CamWnd::BenchMark(){
                Vector3 angles;
                angles[CAMERA_ROLL] = 0;
                angles[CAMERA_PITCH] = 0;
-               angles[CAMERA_YAW] = static_cast<float>( i * ( 360.0 / 100.0 ) );
+               angles[CAMERA_YAW] = i * 360.0f / 100.0f;
                Camera_setAngles( *this, angles );
        }
        double dEnd = Sys_DoubleTime();
@@ -1632,7 +1641,7 @@ void GlobalCamera_ResetAngles(){
        CamWnd& camwnd = *g_camwnd;
        Vector3 angles;
        angles[CAMERA_ROLL] = angles[CAMERA_PITCH] = 0;
-       angles[CAMERA_YAW] = static_cast<float>( 22.5 * floor( ( Camera_getAngles( camwnd )[CAMERA_YAW] + 11 ) / 22.5 ) );
+       angles[CAMERA_YAW] = 22.5f * floorf( ( Camera_getAngles( camwnd )[CAMERA_YAW] + 11 ) / 22.5f );
        Camera_setAngles( camwnd, angles );
 }
 
@@ -1660,8 +1669,8 @@ void Camera_CubeIn(){
 void Camera_CubeOut(){
        CamWnd& camwnd = *g_camwnd;
        g_camwindow_globals.m_nCubicScale++;
-       if ( g_camwindow_globals.m_nCubicScale > 23 ) {
-               g_camwindow_globals.m_nCubicScale = 23;
+       if ( g_camwindow_globals.m_nCubicScale > 46 ) {
+               g_camwindow_globals.m_nCubicScale = 46;
        }
        Camera_updateProjection( camwnd.getCamera() );
        CamWnd_Update( camwnd );
@@ -1709,6 +1718,8 @@ void CamWnd_registerShortcuts(){
                command_connect_accelerator( "TogglePreview" );
        }
 
+       command_connect_accelerator( "FOVInc" );
+       command_connect_accelerator( "FOVDec" );
        command_connect_accelerator( "CameraSpeedInc" );
        command_connect_accelerator( "CameraSpeedDec" );
 }
@@ -1826,6 +1837,7 @@ struct RenderMode {
 };
 
 void Camera_constructPreferences( PreferencesPage& page ){
+       page.appendSlider( "FOV", g_camwindow_globals_private.m_nFOV, TRUE, 0, 0, 100, MIN_FOV, MAX_FOV, 1, 10 );
        page.appendSlider( "Movement Speed", g_camwindow_globals_private.m_nMoveSpeed, TRUE, 0, 0, 100, MIN_CAM_SPEED, MAX_CAM_SPEED, 1, 10 );
        page.appendCheckBox( "", "Link strafe speed to movement speed", g_camwindow_globals_private.m_bCamLinkSpeed );
        page.appendSlider( "Rotation Speed", g_camwindow_globals_private.m_nAngleSpeed, TRUE, 0, 0, 3, 1, 180, 1, 10 );
@@ -1879,6 +1891,31 @@ void Camera_registerPreferencesPage(){
 #include "stringio.h"
 #include "dialog.h"
 
+void FOV_increase(){
+       CamWnd& camwnd = *g_camwnd;
+       if ( g_camwindow_globals_private.m_nFOV <= ( MAX_FOV - FOV_STEP - 10 ) ) {
+               g_camwindow_globals_private.m_nFOV += FOV_STEP;
+       }
+       else {
+               g_camwindow_globals_private.m_nFOV = MAX_FOV - 10;
+       }
+       Camera_updateProjection( camwnd.getCamera() );
+       CamWnd_Update( camwnd );
+}
+
+void FOV_decrease(){
+       CamWnd& camwnd = *g_camwnd;
+       if ( g_camwindow_globals_private.m_nFOV >= ( MIN_FOV + FOV_STEP ) ) {
+               g_camwindow_globals_private.m_nFOV -= FOV_STEP;
+       }
+       else {
+               g_camwindow_globals_private.m_nFOV = MIN_FOV;
+       }
+       Camera_updateProjection( camwnd.getCamera() );
+       CamWnd_Update( camwnd );
+}
+
+
 void CameraSpeed_increase(){
        if ( g_camwindow_globals_private.m_nMoveSpeed <= ( MAX_CAM_SPEED - CAM_SPEED_STEP - 10 ) ) {
                g_camwindow_globals_private.m_nMoveSpeed += CAM_SPEED_STEP;
@@ -1916,6 +1953,9 @@ void CamWnd_Construct(){
                GlobalCommands_insert( "TogglePreview", makeCallbackF(CamWnd_TogglePreview), Accelerator( GDK_KEY_F3 ) );
        }
 
+       GlobalCommands_insert( "FOVInc", makeCallbackF(FOV_increase), Accelerator( GDK_KEY_KP_Multiply, (GdkModifierType)GDK_SHIFT_MASK ) );
+       GlobalCommands_insert( "FOVDec", makeCallbackF(FOV_decrease), Accelerator( GDK_KEY_KP_Divide, (GdkModifierType)GDK_SHIFT_MASK ) );
+
        GlobalCommands_insert( "CameraSpeedInc", makeCallbackF(CameraSpeed_increase), Accelerator( GDK_KEY_KP_Add, (GdkModifierType)GDK_SHIFT_MASK ) );
        GlobalCommands_insert( "CameraSpeedDec", makeCallbackF(CameraSpeed_decrease), Accelerator( GDK_KEY_KP_Subtract, (GdkModifierType)GDK_SHIFT_MASK ) );
 
@@ -1944,6 +1984,7 @@ void CamWnd_Construct(){
        GlobalToggles_insert( "ShowStats", makeCallbackF(ShowStatsToggle), ToggleItem::AddCallbackCaller( g_show_stats ) );
 
        GlobalPreferenceSystem().registerPreference( "ShowStats", make_property_string( g_camwindow_globals_private.m_showStats ) );
+       GlobalPreferenceSystem().registerPreference( "FOV", make_property_string( g_camwindow_globals_private.m_nFOV ) );
        GlobalPreferenceSystem().registerPreference( "MoveSpeed", make_property_string( g_camwindow_globals_private.m_nMoveSpeed ) );
        GlobalPreferenceSystem().registerPreference( "CamLinkSpeed", make_property_string( g_camwindow_globals_private.m_bCamLinkSpeed ) );
        GlobalPreferenceSystem().registerPreference( "AngleSpeed", make_property_string( g_camwindow_globals_private.m_nAngleSpeed ) );
index ded8aefcba9456471890a6b1af02b647965a9b3e..9ed6d24260d0013dc149e906ba91473948d7ceea 100644 (file)
@@ -69,7 +69,7 @@ struct camwindow_globals_t
        camwindow_globals_t() :
                color_cameraback( 0.25f, 0.25f, 0.25f ),
                color_selbrushes3d( 1.0f, 0.f, 0.f ),
-               m_nCubicScale( 14 ){
+               m_nCubicScale( 26 ){
        }
 
 };
index ea837329831319bb94c23af6f0840d847e3e85ba..489f8d61f4773dcae99d991ffab2c7d6d7236ed8 100644 (file)
@@ -24,6 +24,7 @@
 #include <time.h>
 #include <uilib/uilib.h>
 #include <gtk/gtk.h>
+#include <mutex>
 
 #include "gtkutil/accelerator.h"
 #include "gtkutil/messagebox.h"
@@ -33,7 +34,6 @@
 #include "stream/stringstream.h"
 #include "convert.h"
 
-#include "version.h"
 #include "aboutmsg.h"
 #include "gtkmisc.h"
 #include "mainframe.h"
@@ -46,8 +46,15 @@ FILE* g_hLogFile;
 
 bool g_Console_enableLogging = false;
 
+struct Gtk_Idle_Print_Data {
+       int level;
+       char *buf;
+       std::size_t length;
+       bool contains_newline;
+};
+
 // called whenever we need to open/close/check the console log file
-void Sys_LogFile( bool enable ){
+void Sys_EnableLogFile( bool enable ){
        if ( enable && !g_hLogFile ) {
                // settings say we should be logging and we don't have a log file .. so create it
                if ( !SettingsPath_get()[0] ) {
@@ -64,10 +71,10 @@ void Sys_LogFile( bool enable ){
                        time_t localtime;
                        time( &localtime );
                        globalOutputStream() << "Today is: " << ctime( &localtime )
-                                                                << "This is NetRadiant '" RADIANT_VERSION "' compiled " __DATE__ "\n" RADIANT_ABOUTMSG "\n";
+                                                                << "This is " RADIANT_NAME " " RADIANT_VERSION " compiled " __DATE__ "\n" RADIANT_ABOUTMSG "\n";
                }
                else{
-                       ui::alert( ui::root, "Failed to create log file, check write permissions in Radiant directory.\n",
+                       ui::alert( ui::root, "Failed to create log file, check write permissions in " RADIANT_NAME " directory.\n",
                                                        "Console logging", ui::alert_type::OK, ui::alert_icon::Error );
                }
        }
@@ -152,22 +159,11 @@ std::size_t __attribute__((optimize("O0"))) write( const char* buffer, std::size
 
 //#pragma GCC pop_options
 
-std::size_t Sys_Print( int level, const char* buf, std::size_t length ){
-       bool contains_newline = std::find( buf, buf + length, '\n' ) != buf + length;
+// This function is meant to be used with gtk_idle_add. It will free its argument.
+static gboolean Gtk_Idle_Print( gpointer data ){
+       Gtk_Idle_Print_Data *args = reinterpret_cast<Gtk_Idle_Print_Data *>(data);
+       g_assert(g_console);
 
-       if ( level == SYS_ERR ) {
-               Sys_LogFile( true );
-       }
-
-       if ( g_hLogFile != 0 ) {
-               fwrite( buf, 1, length, g_hLogFile );
-               if ( contains_newline ) {
-                       fflush( g_hLogFile );
-               }
-       }
-
-       if ( level != SYS_NOCON ) {
-               if ( g_console ) {
                        auto buffer = gtk_text_view_get_buffer( g_console );
 
                        GtkTextIter iter;
@@ -182,7 +178,7 @@ std::size_t Sys_Print( int level, const char* buf, std::size_t length ){
                        static auto warning_tag = gtk_text_buffer_create_tag( buffer, "yellow_foreground", "foreground-gdk", &yellow, NULL );
                        static auto standard_tag = gtk_text_buffer_create_tag( buffer, "black_foreground", NULL );
                        GtkTextTag* tag;
-                       switch ( level )
+       switch ( args->level )
                        {
                        case SYS_WRN:
                                tag = warning_tag;
@@ -197,29 +193,61 @@ std::size_t Sys_Print( int level, const char* buf, std::size_t length ){
                                break;
                        }
 
-
                        {
                                GtkTextBufferOutputStream textBuffer( buffer, &iter, tag );
                                if ( !globalCharacterSet().isUTF8() ) {
                                        BufferedTextOutputStream<GtkTextBufferOutputStream> buffered( textBuffer );
-                                       buffered << StringRange( buf, buf + length );
+                       buffered << StringRange( args->buf, args->buf + args->length );
                                }
                                else
                                {
-                                       textBuffer << StringRange( buf, buf + length );
+                       textBuffer << StringRange( args->buf, args->buf + args->length );
                                }
                        }
 
                        // update console widget immediatly if we're doing something time-consuming
-                       if ( contains_newline ) {
+       if ( args->contains_newline ) {
                                gtk_text_view_scroll_mark_onscreen( g_console, end );
 
                                if ( !ScreenUpdates_Enabled() && gtk_widget_get_realized( g_console ) ) {
                                        ScreenUpdates_process();
                                }
                        }
+
+       free( args->buf );
+       free( args );
+
+       return FALSE; // call this once, not repeatedly
                }
+
+// Print logs to the in-game console and/or to the log file.
+// This function is thread safe.
+std::size_t Sys_Print( int level, const char* buf, std::size_t length ){
+       bool contains_newline = std::find( buf, buf + length, '\n' ) != buf + length;
+
+       if ( level == SYS_ERR ) {
+               Sys_EnableLogFile( true );
        }
+
+       if ( g_hLogFile != 0 ) {
+               // prevent parallel write
+               static std::mutex log_file_mutex;
+               std::lock_guard<std::mutex> guard(log_file_mutex);
+
+               fwrite( buf, 1, length, g_hLogFile );
+               if ( contains_newline ) {
+                       fflush( g_hLogFile );
+               }
+       }
+
+       if ( level != SYS_NOCON && g_console ) {
+               auto data = reinterpret_cast<Gtk_Idle_Print_Data *>( malloc( sizeof(struct Gtk_Idle_Print_Data) ) );
+               if (data != nullptr) {
+                       *data = { level, g_strndup(buf, length), length, contains_newline };
+                       gdk_threads_add_idle(Gtk_Idle_Print, (gpointer)data);
+               }
+       }
+
        return length;
 }
 
index 8bbe71e1c512ab05777f8e64de01a444892c7b49..e7c703ed5aea377969fbdb2a0b4a0d61c68c3419 100644 (file)
 #define SYS_ERR 3 ///< error
 #define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
 
-std::size_t Sys_Print( int level, const char* buf, std::size_t length );
 class TextOutputStream;
 TextOutputStream& getSysPrintOutputStream();
 TextOutputStream& getSysPrintErrorStream();
 
 ui::Widget Console_constructWindow( ui::Window toplevel );
 
+std::size_t Sys_Print( int level, const char* buf, std::size_t length );
+
 // will open/close the log file based on the parameter
-void Sys_LogFile( bool enable );
+void Sys_EnableLogFile( bool enable );
 extern bool g_Console_enableLogging;
 
 
index 374384b35608c1dc5c84088c176727c1374ede37..59ea7e9c1b902cb40d64c368099f1287c13ad070 100644 (file)
@@ -34,7 +34,7 @@
 void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){
        if ( face.contributes() ) {
                out.push_back( new Brush( brush ) );
-               Face* newFace = out.back()->addFace( face );
+               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                face.getPlane().offset( -offset );
                face.planeChanged();
                if ( newFace != 0 ) {
@@ -50,7 +50,7 @@ void Face_extrude( Face& face, const Brush& brush, brush_vector_t& out, float of
                face.getPlane().offset( offset );
                out.push_back( new Brush( brush ) );
                face.getPlane().offset( -offset );
-               Face* newFace = out.back()->addFace( face );
+               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                if ( newFace != 0 ) {
                        newFace->flipWinding();
                        newFace->planeChanged();
@@ -143,7 +143,7 @@ void operator()( Face& face ) const {
                                if( caulk ){
                                        Brush_forEachFace( *out.back(), CaulkFace( ExclusionAxis, mindot, maxdot ) );
                                }
-                               Face* newFace = out.back()->addFace( face );
+                               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                                if ( newFace != 0 ) {
                                        newFace->flipWinding();
                                }
@@ -156,7 +156,7 @@ void operator()( Face& face ) const {
                                out.push_back( new Brush( brush ) );
                                if( !RemoveInner && caulk )
                                        face.SetShader( getCaulkShader() );
-                               Face* newFace = out.back()->addFace( face );
+                               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                                face.getPlane().offset( -offset );
                                face.planeChanged();
                                if( caulk )
@@ -174,7 +174,7 @@ void operator()( Face& face ) const {
                                out.push_back( new Brush( brush ) );
                                out.back()->clear();
 
-                               Face* newFace = out.back()->addFace( face );
+                               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                                if ( newFace != 0 ) {
                                        newFace->getPlane().offset( offset );
                                        newFace->planeChanged();
@@ -202,7 +202,7 @@ void operator()( Face& face ) const {
                                out.push_back( new Brush( brush ) );
                                out.back()->clear();
 
-                               Face* newFace = out.back()->addFace( face );
+                               std::shared_ptr<Face> newFace = out.back()->addFace( face );
                                if ( newFace != 0 ) {
 
                                        newFace->planeChanged();
@@ -344,10 +344,10 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
                        {
                                ( *i )->removeEmptyFaces();
                                if( ( *i )->hasContributingFaces() ){
-                                       NodeSmartReference node( ( new BrushNode() )->node() );
-                                       Node_getBrush( node )->copy( *( *i ) );
-                                       delete ( *i );
-                                       Node_getTraversable( path.parent() )->insert( node );
+                               NodeSmartReference node( ( new BrushNode() )->node() );
+                               Node_getBrush( node )->copy( *( *i ) );
+                               delete ( *i );
+                               Node_getTraversable( path.parent() )->insert( node );
                                        //path.push( makeReference( node.get() ) );
                                        //selectPath( path, true );
                                        //Instance_getSelectable( *GlobalSceneGraph().find( path ) )->setSelected( true );
@@ -484,15 +484,6 @@ inline Dereference<Functor> makeDereference( const Functor& functor ){
        return Dereference<Functor>( functor );
 }
 
-typedef Face* FacePointer;
-const FacePointer c_nullFacePointer = 0;
-
-template<typename Predicate>
-Face* Brush_findIf( const Brush& brush, const Predicate& predicate ){
-       Brush::const_iterator i = std::find_if( brush.begin(), brush.end(), makeDereference( predicate ) );
-       return i == brush.end() ? c_nullFacePointer : *i; // uses c_nullFacePointer instead of 0 because otherwise gcc 4.1 attempts conversion to int
-}
-
 template<typename Caller>
 class BindArguments1
 {
@@ -542,7 +533,6 @@ typedef Function<bool ( const Face &, const Plane3 &, bool ), Face_testPlane> Fa
 /// \li flipped && brush is FRONT or ON
 bool Brush_testPlane( const Brush& brush, const Plane3& plane, bool flipped ){
        brush.evaluateBRep();
-#if 1
        for ( Brush::const_iterator i( brush.begin() ); i != brush.end(); ++i )
        {
                if ( Face_testPlane( *( *i ), plane, flipped ) ) {
@@ -550,9 +540,6 @@ bool Brush_testPlane( const Brush& brush, const Plane3& plane, bool flipped ){
                }
        }
        return true;
-#else
-       return Brush_findIf( brush, bindArguments( FaceTestPlane(), makeReference( plane ), flipped ) ) == 0;
-#endif
 }
 
 brushsplit_t Brush_classifyPlane( const Brush& brush, const Plane3& plane ){
@@ -573,24 +560,24 @@ bool Brush_subtract( const Brush& brush, const Brush& other, brush_vector_t& ret
                fragments.reserve( other.size() );
                Brush back( brush );
 
-               for ( Brush::const_iterator i( other.begin() ); i != other.end(); ++i )
+               for ( const std::shared_ptr<Face>& b : other )
                {
-                       if ( ( *i )->contributes() ) {
-                               brushsplit_t split = Brush_classifyPlane( back, ( *i )->plane3() );
+                       if ( b->contributes() ) {
+                               brushsplit_t split = Brush_classifyPlane( back, b->plane3() );
                                if ( split.counts[ePlaneFront] != 0
                                         && split.counts[ePlaneBack] != 0 ) {
                                        fragments.push_back( new Brush( back ) );
-                                       Face* newFace = fragments.back()->addFace( *( *i ) );
-                                       if ( newFace != 0 ) {
+                                       std::shared_ptr<Face> newFace = fragments.back()->addFace( *b );
+                                       if ( newFace != nullptr ) {
                                                newFace->flipWinding();
                                        }
-                                       back.addFace( *( *i ) );
+                                       back.addFace( *b );
                                }
                                else if ( split.counts[ePlaneBack] == 0 ) {
-                                       for ( brush_vector_t::iterator i = fragments.begin(); i != fragments.end(); ++i )
-                                       {
-                                               delete( *i );
+                                       for ( Brush *i : fragments ) {
+                                               delete( i );
                                        }
+                                       fragments.clear();
                                        return false;
                                }
                        }
@@ -655,19 +642,15 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
                        else
                        {
                                ++m_before;
-                               for ( brush_vector_t::const_iterator i = out.begin(); i != out.end(); ++i )
-                               {
+                               for ( Brush *b : out ) {
                                        ++m_after;
-                                       ( *i )->removeEmptyFaces();
-                                       if ( !( *i )->empty() ) {
+                                       b->removeEmptyFaces();
+                                       if ( !b->empty() ) {
                                                NodeSmartReference node( ( new BrushNode() )->node() );
-                                               Node_getBrush( node )->copy( *( *i ) );
-                                               delete ( *i );
+                                               Node_getBrush( node )->copy( *b );
                                                Node_getTraversable( path.parent() )->insert( node );
                                        }
-                                       else{
-                                               delete ( *i );
-                                       }
+                                       delete b;
                                }
                                Path_deleteTop( path );
                                if( Node_getTraversable( path.parent() )->empty() ){
@@ -693,9 +676,7 @@ void CSG_Subtract(){
 
        if ( selected_brushes.empty() ) {
                globalOutputStream() << "CSG Subtract: No brushes selected.\n";
-       }
-       else
-       {
+       } else {
                globalOutputStream() << "CSG Subtract: Subtracting " << Unsigned( selected_brushes.size() ) << " brushes.\n";
 
                UndoableCommand undo( "brushSubtract" );
@@ -730,12 +711,20 @@ bool pre( const scene::Path& path, scene::Instance& instance ) const {
 }
 
 void post( const scene::Path& path, scene::Instance& instance ) const {
-       if ( path.top().get().visible() ) {
+       if ( !path.top().get().visible() ) {
+               return;
+       }
+
                Brush* brush = Node_getBrush( path.top() );
-               if ( brush != 0
-                        && Instance_getSelectable( instance )->isSelected() ) {
+       if ( brush == nullptr || !Instance_getSelectable( instance )->isSelected() ) {
+               return;
+       }
+
                        Plane3 plane( plane3_for_points( m_p0, m_p1, m_p2 ) );
-                       if ( plane3_valid( plane ) ) {
+       if ( !plane3_valid( plane ) ) {
+               return;
+       }
+
                                brushsplit_t split = Brush_classifyPlane( *brush, m_split == eFront ? plane3_flipped( plane ) : plane );
                                if ( split.counts[ePlaneBack] && split.counts[ePlaneFront] ) {
                                        // the plane intersects this brush
@@ -743,7 +732,8 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
                                                NodeSmartReference node( ( new BrushNode() )->node() );
                                                Brush* fragment = Node_getBrush( node );
                                                fragment->copy( *brush );
-                                               Face* newFace = fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection );
+                       std::shared_ptr<Face> newFace =
+                               fragment->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection );
                                                if ( newFace != 0 && m_split != eFront ) {
                                                        newFace->flipWinding();
                                                }
@@ -758,7 +748,7 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
                                                }
                                        }
 
-                                       Face* newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection );
+               std::shared_ptr<Face> newFace = brush->addPlane( m_p0, m_p1, m_p2, m_shader, m_projection );
                                        if ( newFace != 0 && m_split == eFront ) {
                                                newFace->flipWinding();
                                        }
@@ -770,9 +760,6 @@ void post( const scene::Path& path, scene::Instance& instance ) const {
                                if ( m_split != eFrontAndBack && split.counts[ePlaneBack] != 0 ) {
                                        // the brush is "behind" the plane
                                        Path_deleteTop( path );
-                               }
-                       }
-               }
        }
 }
 };
index 1c628ff17a3ee3c33c7e4cc856a18deae791fd74..0323161b4dcb32682ef048502972a17926c7d4f2 100644 (file)
@@ -256,24 +256,28 @@ public:
        }
 };
 
+template<class Widget, class Self, class T, class native>
+struct AddDataCustom_Wrapper {
+    static void Export(const native &self, const Callback<void(T)> &returnz) {
+        native *p = &const_cast<native &>(self);
+        auto widget = Self::from(p);
+        Widget::Get::thunk_(widget, returnz);
+    }
+
+    static void Import(native &self, T value) {
+        native *p = &self;
+        auto widget = Self::from(p);
+        Widget::Set::thunk_(widget, value);
+    }
+};
+
 template<class Widget>
 void AddDataCustom(DialogDataList &self, typename Widget::Type widget, Property<typename Widget::Other> const &property) {
     using Self = typename Widget::Type;
     using T = typename Widget::Other;
     using native = typename std::remove_pointer<typename Self::native>::type;
-    struct Wrapper {
-        static void Export(const native &self, const Callback<void(T)> &returnz) {
-                       native *p = &const_cast<native &>(self);
-                       auto widget = Self::from(p);
-                       Widget::Get::thunk_(widget, returnz);
-        }
-
-        static void Import(native &self, T value) {
-                       native *p = &self;
-                       auto widget = Self::from(p);
-                       Widget::Set::thunk_(widget, value);
-        }
-    };
+    using Wrapper = AddDataCustom_Wrapper<Widget, Self, T, native>;
+    
     self.push_back(new CallbackDialogData<typename Widget::Other>(
             make_property<PropertyAdaptor<native, T, Wrapper>>(*static_cast<native *>(widget)),
             property
@@ -442,6 +446,23 @@ EMessageBoxReturn Dialog::DoModal(){
        return m_modal.ret;
 }
 
+ui::VBox Dialog::addSpacer( ui::VBox vbox, int dimension ){
+       auto spacer = ui::VBox( FALSE, 0 );
+       gtk_widget_set_size_request( GTK_WIDGET( spacer ), dimension, dimension );
+       spacer.show();
+
+       DialogVBox_packRow( vbox, spacer );
+       return spacer;
+}
+
+ui::Label Dialog::addLabel( ui::VBox vbox, const char* name, const char* text ){
+       auto label = ui::Label( text );
+       gtk_misc_set_alignment( GTK_MISC( label ), 0.0, 0.5 );
+       label.show();
+
+       DialogVBox_packRow( vbox, ui::Widget(DialogRow_new( name, label ) ));
+       return label;
+}
 
 ui::CheckButton Dialog::addCheckBox( ui::VBox vbox, const char* name, const char* flag, Property<bool> const &cb ){
        auto check = ui::CheckButton( flag );
index 78efa830ee541861c87063bba78054b84fa0d2ab..dac38d9b84be984f7e6f5fe7539c9defb5718546 100644 (file)
@@ -90,6 +90,10 @@ public:
                return m_window;
        }
 
+       ui::VBox addSpacer(ui::VBox vbox, int size);
+
+       ui::Label addLabel(ui::VBox vbox, const char *name, const char *text);
+
        ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, Property<bool> const &cb);
 
        ui::CheckButton addCheckBox(ui::VBox vbox, const char *name, const char *flag, bool &data);
index 8637b4800c186e1ff3c23d260fe904779ca4fc7f..b2ab48ce704bdca5b5ffdfefac53299b41ae2cfb 100644 (file)
@@ -313,7 +313,7 @@ void Eclass_ScanFile( EntityClassCollector& collector, const char *filename ){
        } state = eParseDefault;
        const char* quakeEd = "QUAKED";
        const char* p = 0;
-       StringBuffer buffer;
+       std::string buffer;
        SingleCharacterInputStream<TextFileInputStream> bufferedInput( inputFile );
        for (;; )
        {
index a84a7d42bc7ba0b10fc25b465aa2098fbff582ae..bd07533a6825ab1f06178d02ab57d606830f8194 100644 (file)
@@ -140,8 +140,10 @@ void gamedetect(){
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz.exe", buf, p - buf ) )
 #elif GDEF_OS_MACOS
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "Nexuiz.app/Contents/Info.plist", buf, p - buf ) )
-#else
+#elif GDEF_OS_LINUX
                        if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", "nexuiz-linux-glx.sh", buf, p - buf ) )
+#else
+                       if ( gamedetect_check_game( "nexuiz.game", "data/common-spog.pk3", NULL, buf, p - buf ) )
 #endif
                        { return; }
 
@@ -166,8 +168,17 @@ void gamedetect(){
 
 namespace
 {
-CopiedString home_path;
-CopiedString app_path;
+       // executable file path
+       CopiedString app_filepath;
+       // directory paths
+       CopiedString home_path;
+       CopiedString app_path;
+       CopiedString lib_path;
+       CopiedString data_path;
+}
+
+const char* environment_get_app_filepath(){
+       return app_filepath.c_str();
 }
 
 const char* environment_get_home_path(){
@@ -178,10 +189,20 @@ const char* environment_get_app_path(){
        return app_path.c_str();
 }
 
+const char *environment_get_lib_path()
+{
+       return lib_path.c_str();
+}
+
+const char *environment_get_data_path()
+{
+       return data_path.c_str();
+}
+
 bool portable_app_setup(){
        StringOutputStream confdir( 256 );
        confdir << app_path.c_str() << "settings/";
-       if ( file_exists( confdir.c_str() ) ) {
+       if ( file_is_directory( confdir.c_str() ) ) {
                home_path = confdir.c_str();
                return true;
        }
@@ -199,28 +220,32 @@ bool portable_app_setup(){
 const char* LINK_NAME =
 #if GDEF_OS_LINUX
        "/proc/self/exe"
-#else // FreeBSD and OSX
+#else // FreeBSD and macOS
        "/proc/curproc/file"
 #endif
 ;
 
-/// brief Returns the filename of the executable belonging to the current process, or 0 if not found.
+/// brief Returns the filename of the executable belonging to the current process, or empty string if not found.
 char const* getexename( char *buf ){
        /* Now read the symbolic link */
-       int ret = readlink( LINK_NAME, buf, PATH_MAX );
+       const int ret = readlink( LINK_NAME, buf, PATH_MAX );
 
        if ( ret == -1 ) {
                globalOutputStream() << "getexename: falling back to argv[0]: " << makeQuoted( g_argv[0] );
-               const char* path = realpath( g_argv[0], buf );
-               if ( path == 0 ) {
+               if( realpath( g_argv[0], buf ) == 0 ) {
                        /* In case of an error, leave the handling up to the caller */
-                       return "";
+                       *buf = '\0';
                }
        }
+       else {
+               /* Ensure proper NUL termination */
+               buf[ret] = 0;
+       }
 
-       /* Ensure proper NUL termination */
-       buf[ret] = 0;
+       return buf;
+}
 
+char const* getexepath( char *buf ) {
        /* delete the program name */
        *( strrchr( buf, '/' ) ) = '\0';
 
@@ -248,16 +273,69 @@ void environment_init( int argc, char const* argv[] ){
 
        {
                char real[PATH_MAX];
-               app_path = getexename( real );
-               ASSERT_MESSAGE( !string_empty( app_path.c_str() ), "failed to deduce app path" );
+               app_filepath = getexename( real );
+               ASSERT_MESSAGE( !string_empty( app_filepath.c_str() ), "failed to deduce app path" );
+
+               strncpy( real, app_filepath.c_str(), strlen( app_filepath.c_str() ) );
+               app_path = getexepath( real );
+       }
+
+       {
+#if defined(RADIANT_FHS_INSTALL)
+               StringOutputStream buffer;
+       #if defined(RADIANT_ADDONS_DIR)
+               buffer << RADIANT_ADDONS_DIR << "/";
+       #else
+               buffer << app_path.c_str() << "../lib/";
+               buffer << RADIANT_LIB_ARCH << "/";
+               buffer << RADIANT_BASENAME << "/";
+       #endif
+               lib_path = buffer.c_str();
+#else
+               lib_path = app_path.c_str();
+#endif
+       }
+
+       {
+#if defined(RADIANT_FHS_INSTALL)
+               StringOutputStream buffer;
+       #if defined(RADIANT_DATA_DIR)
+               buffer << RADIANT_DATA_DIR << "/";
+       #else
+               buffer << app_path.c_str() << "../share/";
+               buffer << RADIANT_BASENAME << "/";
+       #endif
+               data_path = buffer.c_str();
+#else
+               data_path = app_path.c_str();
+#endif
        }
 
        if ( !portable_app_setup() ) {
                StringOutputStream home( 256 );
-               home << DirectoryCleaned( g_get_user_config_dir() ) << "netradiant/";
+#if GDEF_OS_MACOS
+               /* This is used on macOS, this will produce
+               ~/Library/Application Support/NetRadiant folder. */
+               home << DirectoryCleaned( g_get_home_dir() );
+               Q_mkdir( home.c_str() );
+               home << "Library/";
+               Q_mkdir( home.c_str() );
+               home << "Application Support/";
+               Q_mkdir( home.c_str() );
+               home << RADIANT_NAME << "/";
+#else // if GDEF_OS_XDG
+               /* This is used on both Linux and FreeBSD,
+               this will produce ~/.config/netradiant folder
+               when environment has default settings, the
+               XDG_CONFIG_HOME variable modifies it. */
+               home << DirectoryCleaned( g_get_user_config_dir() );
+               Q_mkdir( home.c_str() );
+               home << RADIANT_BASENAME << "/";
+#endif // ! GDEF_OS_MACOS
                Q_mkdir( home.c_str() );
                home_path = home.c_str();
        }
+
        gamedetect();
 }
 
@@ -283,7 +361,14 @@ void environment_init( int argc, char const* argv[] ){
        {
                // get path to the editor
                char filename[MAX_PATH + 1];
+               StringOutputStream app_filepath_stream( 256 );
+               StringOutputStream app_path_stream( 256 );
+
                GetModuleFileName( 0, filename, MAX_PATH );
+               
+               app_filepath_stream << PathCleaned( filename );
+               app_filepath = app_filepath_stream.c_str();
+
                char* last_separator = strrchr( filename, '\\' );
                if ( last_separator != 0 ) {
                        *( last_separator + 1 ) = '\0';
@@ -292,16 +377,23 @@ void environment_init( int argc, char const* argv[] ){
                {
                        filename[0] = '\0';
                }
-               StringOutputStream app( 256 );
-               app << PathCleaned( filename );
-               app_path = app.c_str();
+
+               app_path_stream << PathCleaned( filename );
+               app_path = app_path_stream.c_str();
+
+               lib_path = app_path;
+               data_path = app_path;
        }
 
        if ( !portable_app_setup() ) {
                char *appdata = getenv( "APPDATA" );
+
                StringOutputStream home( 256 );
                home << PathCleaned( appdata );
-               home << "/NetRadiantSettings/";
+               home << "/";
+               home << RADIANT_NAME;
+               home << "/";
+
                Q_mkdir( home.c_str() );
                home_path = home.c_str();
        }
index 98c33ab94568a90d726896e0298ac94db8f97969..2e57fb123c677ea1cf3fe0025f999ee591f20c2f 100644 (file)
 #define INCLUDED_ENVIRONMENT_H
 
 void environment_init( int argc, char const* argv[] );
+
+const char* environment_get_app_filepath();
+
 const char* environment_get_home_path();
 const char* environment_get_app_path();
+const char *environment_get_lib_path();
+const char *environment_get_data_path();
 
 extern int g_argc;
 extern char const** g_argv;
index 50a089645b43140b52fe2c8a311123dfdc34d98f..fbb77c2933b3c79fc6b0b53e2151d7a873933a71 100644 (file)
@@ -130,7 +130,7 @@ void Error( const char *error, ... ){
        ERROR_MESSAGE( text );
 
        // force close logging if necessary
-       Sys_LogFile( false );
+       Sys_EnableLogFile( false );
 
        _exit( 1 );
 }
diff --git a/radiant/glwidget.cpp b/radiant/glwidget.cpp
deleted file mode 100644 (file)
index 0820d78..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "glwidget.h"
-
-#include "igtkgl.h"
-#include "modulesystem.h"
-#include "gtkutil/glwidget.h"
-
-class GtkGLAPI
-{
-_QERGtkGLTable m_gtkgl;
-public:
-typedef _QERGtkGLTable Type;
-STRING_CONSTANT( Name, "*" );
-
-GtkGLAPI(){
-       m_gtkgl.glwidget_new = &glwidget_new;
-       m_gtkgl.glwidget_swap_buffers = &glwidget_swap_buffers;
-       m_gtkgl.glwidget_make_current = &glwidget_make_current;
-       m_gtkgl.glwidget_destroy_context = &glwidget_destroy_context;
-       m_gtkgl.glwidget_create_context = &glwidget_create_context;
-}
-_QERGtkGLTable* getTable(){
-       return &m_gtkgl;
-}
-};
-
-#include "modulesystem/singletonmodule.h"
-#include "modulesystem/moduleregistry.h"
-
-typedef SingletonModule<GtkGLAPI> GtkGLModule;
-typedef Static<GtkGLModule> StaticGtkGLModule;
-StaticRegisterModule staticRegisterGtkGL( StaticGtkGLModule::instance() );
diff --git a/radiant/glwidget.h b/radiant/glwidget.h
deleted file mode 100644 (file)
index 0adad26..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-   Copyright (C) 2001-2006, William Joseph.
-   All Rights Reserved.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#if !defined( INCLUDED_GLWIDGET_H )
-#define INCLUDED_GLWIDGET_H
-
-#endif
index ad64793f6ef4e34ab423bfcc9b6afdb6e877efbe..b7054e2b54a53e7bb56d4f917ebfafeab3da9f4f 100644 (file)
 #include "multimon.h"
 #include "console.h"
 #include "commands.h"
-
-
 #include "gtkutil/window.h"
 
+#if defined(WORKAROUND_WINDOWS_GTK2_GLWIDGET) || defined(WORKAROUND_MACOS_GTK2_GLWIDGET)
+#include "texwindow.h"
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET || WORKAROUND_MACOS_GTK2_GLWIDGET
+
 class GroupDlg
 {
 public:
@@ -85,16 +87,30 @@ std::size_t g_current_page;
 std::vector<Callback<void(const Callback<void(const char *)> &)>> g_pages;
 }
 
+static void workaround_macos_show_hide(){
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+       if ( g_current_page == 2 )
+       {
+               TextureBrowser_showGLWidget();
+       }
+       else
+       {
+               TextureBrowser_hideGLWidget();
+       }
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
+}
+
 void GroupDialog_updatePageTitle( ui::Window window, std::size_t pageIndex ){
        if ( pageIndex < g_pages.size() ) {
                g_pages[pageIndex]( PointerCaller<GtkWindow, void(const char*), gtk_window_set_title>( window ) );
        }
+
+       workaround_macos_show_hide();
 }
 
 static gboolean switch_page( GtkNotebook *notebook, gpointer page, guint page_num, gpointer data ){
-       GroupDialog_updatePageTitle( ui::Window::from(data), page_num );
        g_current_page = page_num;
-
+       GroupDialog_updatePageTitle( ui::Window::from(data), page_num );
        return FALSE;
 }
 
@@ -133,7 +149,6 @@ void GroupDlg::Create( ui::Window parent ){
        }
 }
 
-
 ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const Callback<void(const Callback<void(const char *)> &)>& title ){
        ui::Widget w = ui::Label( tabLabel );
        w.show();
@@ -143,7 +158,6 @@ ui::Widget GroupDialog_addPage( const char* tabLabel, ui::Widget widget, const C
        return page;
 }
 
-
 bool GroupDialog_isShown(){
        return g_GroupDlg.m_window.visible();
 }
@@ -163,7 +177,6 @@ void GroupDialog_destroyWindow(){
        g_GroupDlg.m_window = ui::Window{ui::null};
 }
 
-
 ui::Window GroupDialog_getWindow(){
        return ui::Window(g_GroupDlg.m_window);
 }
@@ -172,28 +185,46 @@ void GroupDialog_show(){
 }
 
 ui::Widget GroupDialog_getPage(){
-       return ui::Widget::from(gtk_notebook_get_nth_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) ));
+       return ui::Widget::from(gtk_notebook_get_nth_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) ) );
 }
 
 void GroupDialog_setPage( ui::Widget page ){
        g_current_page = gtk_notebook_page_num( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), page );
        gtk_notebook_set_current_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) );
+
+       workaround_macos_show_hide();
+}
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+void GroupDialog_cycle(){
+       g_current_page = ( g_current_page + 1 ) % g_pages.size();
+       gtk_notebook_set_current_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) );
 }
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
 
 void GroupDialog_showPage( ui::Widget page ){
+
        if ( GroupDialog_getPage() == page ) {
                GroupDialog_ToggleShow();
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+               /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+               /* this is very ugly: cycle to next tab then return to current tab immediately to force the refresh
+                * this fixes the drawing of texture tab when window is restored and current tab is texture tab
+                * this is called for nothing when windows is minimized and called for nothing when current tab
+                * is not texture tab, hopefully it's a workaround that would disappear with gtk 3 */
+               GroupDialog_cycle();
+               GroupDialog_setPage( page );
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
+
        }
        else
        {
                g_GroupDlg.m_window.show();
                GroupDialog_setPage( page );
        }
-}
 
-void GroupDialog_cycle(){
-       g_current_page = ( g_current_page + 1 ) % g_pages.size();
-       gtk_notebook_set_current_page( GTK_NOTEBOOK( g_GroupDlg.m_pNotebook ), gint( g_current_page ) );
+       workaround_macos_show_hide();
 }
 
 void GroupDialog_updatePageTitle( ui::Widget page ){
@@ -202,7 +233,6 @@ void GroupDialog_updatePageTitle( ui::Widget page ){
        }
 }
 
-
 #include "preferencesystem.h"
 
 void GroupDialog_Construct(){
index 1deceec8b1f756d6c478f58967293b214be8500c..d052ff125a7eb75b2121027f73e55440baba65b1 100644 (file)
@@ -40,7 +40,6 @@
 #include <gtk/gtk.h>
 
 #include "debugging/debugging.h"
-#include "version.h"
 #include "aboutmsg.h"
 
 #include "igl.h"
@@ -424,11 +423,24 @@ void about_button_issues( ui::Widget widget, gpointer data ){
        OpenURL( cred.c_str() );
 }
 
+static void AddParagraph( ui::VBox vbox, const char* text, bool use_markup ){
+       auto label = ui::Label( text );
+       gtk_label_set_use_markup( GTK_LABEL( label ), use_markup );
+       gtk_misc_set_alignment( GTK_MISC( label ), 0, 0 );
+       gtk_label_set_justify( label, GTK_JUSTIFY_LEFT );
+       label.show();
+       vbox.pack_start( label, TRUE, TRUE, 0 );
+}
+
+static void AddParagraph( ui::VBox vbox, const char* text ){
+       AddParagraph( vbox, text, false );
+}
+
 void DoAbout(){
        ModalDialog dialog;
        ModalDialogButton ok_button( dialog, eIDOK );
 
-       auto window = MainFrame_getWindow().create_modal_dialog_window("About NetRadiant", dialog );
+       auto window = MainFrame_getWindow().create_modal_dialog_window("About " RADIANT_NAME, dialog );
 
        {
                auto vbox = create_dialog_vbox( 4, 4 );
@@ -436,11 +448,11 @@ void DoAbout(){
 
                {
             auto hbox = create_dialog_hbox( 4 );
-                       vbox.pack_start( hbox, FALSE, TRUE, 0 );
+                       vbox.pack_start( hbox, FALSE, FALSE, 0 );
 
                        {
                 auto vbox2 = create_dialog_vbox( 4 );
-                               hbox.pack_start( vbox2, TRUE, FALSE, 0 );
+                               hbox.pack_start( vbox2, FALSE, FALSE, 5 );
                                {
                                        auto frame = create_dialog_frame( 0, ui::Shadow::IN );
                                        vbox2.pack_start( frame, FALSE, FALSE, 0 );
@@ -453,29 +465,44 @@ void DoAbout(){
                        }
 
                        {
-                               char const *label_text = "NetRadiant " RADIANT_VERSION "\n"
-                                                                               __DATE__ "\n\n"
-                                        RADIANT_ABOUTMSG "\n\n"
-                                                                               "This program is free software\n"
-                                                                               "licensed under the GNU GPL.\n\n"
-                                                                               "NetRadiant is unsupported, however\n"
-                                                                               "you may report your problems at\n"
-                                                                               "https://gitlab.com/xonotic/netradiant/issues";
-
-                               auto label = ui::Label( label_text );
-
-                               label.show();
-                               hbox.pack_start( label, FALSE, FALSE, 0 );
-                               gtk_misc_set_alignment( GTK_MISC( label ), 1, 0.5 );
-                               gtk_label_set_justify( label, GTK_JUSTIFY_LEFT );
+                               // HACK: that may not be related to font size
+                               auto about_vbox = ui::VBox( FALSE, 5 );
+                               about_vbox.show();
+                               hbox.pack_start( about_vbox, FALSE, FALSE, 0 );
+
+                               AddParagraph( about_vbox,
+                                       RADIANT_NAME " " RADIANT_VERSION_STRING " (" __DATE__ ")\n"
+                                       RADIANT_ABOUTMSG );
+                               AddParagraph( about_vbox,
+                                       "Get news and latest build at "
+                                       "<a href='https://netradiant.gitlab.io/'>"
+                                               "netradiant.gitlab.io"
+                                       "</a>\n"
+                                       "Please report your issues at "
+                                       "<a href='https://gitlab.com/xonotic/netradiant/issues'>"
+                                               "gitlab.com/xonotic/netradiant/issues"
+                                       "</a>\n"
+                                       "The team cannot provide support for custom builds.", true );
+                               AddParagraph( about_vbox,
+                                       RADIANT_NAME " is a community project maintained by "
+                                       "<a href='https://xonotic.org'>"
+                                               "Xonotic"
+                                       "</a>\n"
+                                       "and developed with help from "
+                                       "<a href='https://netradiant.gitlab.io/page/about/'>"
+                                               "other game projects"
+                                       "</a> and individuals. ", true );
+                               AddParagraph( about_vbox,
+                                       "This program is free software licensed under the GNU GPL." );
                        }
 
                        {
                 auto vbox2 = create_dialog_vbox( 4 );
-                               hbox.pack_start( vbox2, FALSE, TRUE, 0 );
+                               hbox.pack_start( vbox2, TRUE, TRUE, 0 );
                                {
                     auto button = create_modal_dialog_button( "OK", ok_button );
                                        vbox2.pack_start( button, FALSE, FALSE, 0 );
+                                       gtk_widget_grab_focus( GTK_WIDGET( button ) );
                                }
                                {
                     auto button = create_dialog_button( "Credits", G_CALLBACK( about_button_credits ), 0 );
index b11743d69319a9af587cf71b2302ec9330e4fb7e..0b6bf2974161f2eced040cfc619920c6a2264e21 100644 (file)
@@ -115,8 +115,8 @@ void process_xlink( const char* filename, const char *menu_name, const char *bas
 
 void create_game_help_menu( ui::Menu menu ){
        StringOutputStream filename( 256 );
-       filename << AppPath_get() << "global.xlink";
-       process_xlink( filename.c_str(), "General", AppPath_get(), menu );
+       filename << DataPath_get() << "global.xlink";
+       process_xlink(filename.c_str(), "General", DataPath_get(), menu);
 
 #if 1
        filename.clear();
index c81b3617ab7fe5527d9c8c45ac2fc6c83623db2b..9d74d348fd637ebdfb16b578fddf335213fcdd94 100644 (file)
@@ -30,9 +30,9 @@
 #include "os/path.h"
 #include "stream/stringstream.h"
 
-
 typedef Modules<_QERPlugImageTable> ImageModules;
 ImageModules& Textures_getImageModules();
+ImageModules& Textures_getFallbackImageModules();
 
 /// \brief Returns a new image for the first file matching \p name in one of the available texture formats, or 0 if no file is found.
 Image* QERApp_LoadImage( void* environment, const char* name ){
@@ -50,7 +50,19 @@ public:
                        StringOutputStream fullname( 256 );
                        fullname << m_name << '.' << name;
                        ArchiveFile* file = GlobalFileSystem().openFile( fullname.c_str() );
+
+                       // also look for .dds image in dds/ prefix like Doom3 or DarkPlaces
+                       if ( file == 0 && !string_compare( name, "dds" ) )
+                       {
+                               fullname.clear();
+                               fullname << name << '/' << m_name << '.' << name;
+                               file = GlobalFileSystem().openFile( fullname.c_str() );
+                       }
+
                        if ( file != 0 ) {
+                               // tell user which image file is found for the given texture path
+                               globalOutputStream() << "Found image file: " << makeQuoted( fullname.c_str() ) << "\n";
+
                                m_image = table.loadImage( *file );
                                file->release();
                        }
@@ -60,5 +72,12 @@ public:
 
        Textures_getImageModules().foreachModule( LoadImageVisitor( name, image ) );
 
+       // Games can provide their own fallback, so only do this when previous
+       // loading attempt did not work.
+       if ( image == 0 && !!string_compare_nocase( name, "textures/radiant" ) )
+       {
+               Textures_getFallbackImageModules().foreachModule( LoadImageVisitor( name, image ) );
+       }
+
        return image;
 }
index 88cd0cad4fd89e7a774ca8941be1a9fbd5b60144..a2d288f15eff91315e794a5a14f8ed1419ce370a 100644 (file)
@@ -64,8 +64,6 @@
 #include "main.h"
 #include "globaldefs.h"
 
-#include "version.h"
-
 #include "debugging/debugging.h"
 
 #include "iundo.h"
@@ -304,12 +302,12 @@ bool handleMessage(){
                ScopedLock lock( m_lock );
         if (GDEF_DEBUG) {
             m_buffer << "Break into the debugger?\n";
-            bool handled = ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::YESNO, ui::alert_icon::Error) == ui::alert_response::NO;
+            bool handled = ui::alert(ui::root, m_buffer.c_str(), RADIANT_NAME " - Runtime Error", ui::alert_type::YESNO, ui::alert_icon::Error) == ui::alert_response::NO;
             m_buffer.clear();
             return handled;
         } else {
             m_buffer << "Please report this error to the developers\n";
-            ui::alert(ui::root, m_buffer.c_str(), "Radiant - Runtime Error", ui::alert_type::OK, ui::alert_icon::Error);
+            ui::alert(ui::root, m_buffer.c_str(), RADIANT_NAME " - Runtime Error", ui::alert_type::OK, ui::alert_icon::Error);
             m_buffer.clear();
         }
        }
@@ -329,7 +327,10 @@ void paths_init(){
 
        Q_mkdir( g_strSettingsPath.c_str() );
 
+       g_strAppFilePath = environment_get_app_filepath();
        g_strAppPath = environment_get_app_path();
+       g_strLibPath = environment_get_lib_path();
+       g_strDataPath = environment_get_data_path();
 
        // radiant is installed in the parent dir of "tools/"
        // NOTE: this is not very easy for debugging
@@ -337,12 +338,12 @@ void paths_init(){
        // (for now I had to create symlinks)
        {
                StringOutputStream path( 256 );
-               path << g_strAppPath.c_str() << "bitmaps/";
+               path << g_strDataPath.c_str() << "bitmaps/";
                BitmapsPath_set( path.c_str() );
        }
 
        // we will set this right after the game selection is done
-       g_strGameToolsPath = g_strAppPath;
+       g_strGameToolsPath = g_strDataPath;
 }
 
 bool check_version_file( const char* filename, const char* version ){
@@ -362,39 +363,6 @@ bool check_version_file( const char* filename, const char* version ){
        return false;
 }
 
-bool check_version(){
-       // a safe check to avoid people running broken installations
-       // (otherwise, they run it, crash it, and blame us for not forcing them hard enough to pay attention while installing)
-       // make something idiot proof and someone will make better idiots, this may be overkill
-       // let's leave it disabled in debug mode in any case
-       // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=431
-    if (GDEF_DEBUG) {
-        return true;
-    }
-    // locate and open RADIANT_MAJOR and RADIANT_MINOR
-    bool bVerIsGood = true;
-    {
-        StringOutputStream ver_file_name(256);
-        ver_file_name << AppPath_get() << "RADIANT_MAJOR";
-        bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MAJOR_VERSION);
-    }
-    {
-        StringOutputStream ver_file_name(256);
-        ver_file_name << AppPath_get() << "RADIANT_MINOR";
-        bVerIsGood = check_version_file(ver_file_name.c_str(), RADIANT_MINOR_VERSION);
-    }
-
-    if (!bVerIsGood) {
-        StringOutputStream msg(256);
-        msg
-                << "This editor binary (" RADIANT_VERSION ") doesn't match what the latest setup has configured in this directory\n"
-                        "Make sure you run the right/latest editor binary you installed\n"
-                << AppPath_get();
-        ui::alert(ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Default);
-    }
-    return bVerIsGood;
-}
-
 void create_global_pid(){
        /*!
           the global prefs loading / game selection dialog might fail for any reason we don't know about
@@ -415,31 +383,31 @@ void create_global_pid(){
                if ( remove( g_pidFile.c_str() ) == -1 ) {
                        StringOutputStream msg( 256 );
                        msg << "WARNING: Could not delete " << g_pidFile.c_str();
-                       ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error );
+                       ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error );
                }
 
                // in debug, never prompt to clean registry, turn console logging auto after a failed start
                if (!GDEF_DEBUG) {
                        StringOutputStream msg(256);
-                       msg << "Radiant failed to start properly the last time it was run.\n"
+                       msg << RADIANT_NAME " failed to start properly the last time it was run.\n"
                                        "The failure may be related to current global preferences.\n"
                                        "Do you want to reset global preferences to defaults?";
 
-                       if (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) {
+                       if (ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) {
                                g_GamesDialog.Reset();
                        }
 
                        msg.clear();
                        msg << "Logging console output to " << SettingsPath_get()
-                               << "radiant.log\nRefer to the log if Radiant fails to start again.";
+                               << "radiant.log\nRefer to the log if " RADIANT_NAME " fails to start again.";
 
-                       ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK);
+                       ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Console Log", ui::alert_type::OK);
                }
 
                // set without saving, the class is not in a coherent state yet
                // just do the value change and call to start logging, CGamesDialog will pickup when relevant
                g_GamesDialog.m_bForceLogConsole = true;
-               Sys_LogFile( true );
+               Sys_EnableLogFile( true );
        }
 
        // create a primary .pid for global init run
@@ -457,7 +425,7 @@ void remove_global_pid(){
        if ( remove( g_pidFile.c_str() ) == -1 ) {
                StringOutputStream msg( 256 );
                msg << "WARNING: Could not delete " << g_pidFile.c_str();
-               ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error );
+               ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error );
        }
 }
 
@@ -475,30 +443,30 @@ void create_local_pid(){
                if ( remove( g_pidGameFile.c_str() ) == -1 ) {
                        StringOutputStream msg;
                        msg << "WARNING: Could not delete " << g_pidGameFile.c_str();
-                       ui::alert( ui::root, msg.c_str(), "Radiant", ui::alert_type::OK, ui::alert_icon::Error );
+                       ui::alert( ui::root, msg.c_str(), RADIANT_NAME, ui::alert_type::OK, ui::alert_icon::Error );
                }
 
                // in debug, never prompt to clean registry, turn console logging auto after a failed start
                if (!GDEF_DEBUG) {
                        StringOutputStream msg;
-                       msg << "Radiant failed to start properly the last time it was run.\n"
+                       msg << RADIANT_NAME " failed to start properly the last time it was run.\n"
                                        "The failure may be caused by current preferences.\n"
                                        "Do you want to reset all preferences to defaults?";
 
-                       if (ui::alert(ui::root, msg.c_str(), "Radiant - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) {
+                       if (ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Startup Failure", ui::alert_type::YESNO, ui::alert_icon::Question) == ui::alert_response::YES) {
                                Preferences_Reset();
                        }
 
                        msg.clear();
                        msg << "Logging console output to " << SettingsPath_get()
-                               << "radiant.log\nRefer to the log if Radiant fails to start again.";
+                               << "radiant.log\nRefer to the log if " RADIANT_NAME " fails to start again.";
 
-                       ui::alert(ui::root, msg.c_str(), "Radiant - Console Log", ui::alert_type::OK);
+                       ui::alert(ui::root, msg.c_str(), RADIANT_NAME " - Console Log", ui::alert_type::OK);
                }
 
                // force console logging on! (will go in prefs too)
                g_GamesDialog.m_bForceLogConsole = true;
-               Sys_LogFile( true );
+               Sys_EnableLogFile( true );
        }
        else
        {
@@ -559,7 +527,23 @@ void add_local_rc_files(){
 #endif // GARUX_DISABLE_GTKTHEME
 }
 
+/* HACK: If ui::main is not called yet,
+gtk_main_quit will not quit, so tell main
+to not call ui::main. This happens when a
+map is loaded from command line and require
+a restart because of wrong format.
+Delete this when the code to not have to
+restart to load another format is merged. */
+bool g_dontStart = false;
+
 int main( int argc, char* argv[] ){
+#if GTK_TARGET == 3
+       // HACK: force legacy GL backend as we don't support GL3 yet
+       setenv("GDK_GL", "LEGACY", 0);
+#if GDEF_OS_LINUX || GDEF_OS_BSD
+       setenv("GDK_BACKEND", "x11", 0);
+#endif
+#endif // GTK_TARGET == 3
        crt_init();
 
        streams_init();
@@ -589,7 +573,13 @@ int main( int argc, char* argv[] ){
 #endif
 
        const char* mapname = NULL;
+
+#if GDEF_OS_WINDOWS
+       StringOutputStream mapname_buffer( 256 );
+#endif
+
     char const *error = NULL;
+
        if ( !ui::init( &argc, &argv, "<filename.map>", &error) ) {
                g_print( "%s\n", error );
                return -1;
@@ -598,16 +588,21 @@ int main( int argc, char* argv[] ){
        // Gtk already removed parsed `--options`
        if (argc == 2) {
                if ( strlen( argv[1] ) > 1 ) {
-                       if ( g_str_has_suffix( argv[1], ".map" ) ) {
-                               if ( g_path_is_absolute( argv[1] ) ) {
                                        mapname = argv[1];
+
+                       if ( g_str_has_suffix( mapname, ".map" ) ) {
+                               if ( !g_path_is_absolute( mapname ) ) {
+                                       mapname = g_build_filename( g_get_current_dir(), mapname, NULL );
                                }
-                               else {
-                                       mapname = g_build_filename( g_get_current_dir(), argv[1], NULL );
-                               }
+
+#if GDEF_OS_WINDOWS
+                               mapname_buffer << PathCleaned( mapname );
+                               mapname = mapname_buffer.c_str();
+#endif
                        }
                        else {
-                               g_print( "bad file name, will not load: %s\n", argv[1] );
+                               g_print( "bad file name, will not load: %s\n", mapname );
+                               mapname = NULL;
                        }
                }
        }
@@ -636,10 +631,6 @@ int main( int argc, char* argv[] ){
 
        add_local_rc_files();
 
-       if ( !check_version() ) {
-               return EXIT_FAILURE;
-       }
-
        show_splash();
 
        create_global_pid();
@@ -660,7 +651,7 @@ int main( int argc, char* argv[] ){
        // we may have the console turned on and want to keep it that way
        // so we use a latching system
        if ( g_GamesDialog.m_bForceLogConsole ) {
-               Sys_LogFile( true );
+               Sys_EnableLogFile( true );
                g_Console_enableLogging = true;
                g_GamesDialog.m_bForceLogConsole = false;
        }
@@ -699,7 +690,17 @@ int main( int argc, char* argv[] ){
 
        remove_local_pid();
 
+       /* HACK: If ui::main is not called yet,
+       gtk_main_quit will not quit, so tell main
+       to not call ui::main. This happens when a
+       map is loaded from command line and require
+       a restart because of wrong format.
+       Delete this when the code to not have to
+       restart to load another format is merged. */
+       if ( !g_dontStart )
+       {
        ui::main();
+       }
 
        // avoid saving prefs when the app is minimized
        if ( g_pParentWnd->IsSleeping() ) {
@@ -720,7 +721,7 @@ int main( int argc, char* argv[] ){
        Radiant_Shutdown();
 
        // close the log file if any
-       Sys_LogFile( false );
+       Sys_EnableLogFile( false );
 
        return EXIT_SUCCESS;
 }
index eb6561027c6d38df771204ae5d216edd7baa6f77..7d9057b1cedc56174fcbccf870d34d6844d99e7c 100644 (file)
 #include "texwindow.h"
 #include "filterbar.h"
 
+#if GDEF_OS_WINDOWS
+#include <process.h>
+#else
+#include <spawn.h>
+#endif
+
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+/* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget) g_object_set_data( G_OBJECT( window ), "glwidget", G_OBJECT( widget ) )
+#else
+#define WORKAROUND_GOBJECT_SET_GLWIDGET(window, widget)
+#endif
+
 #define GARUX_DISABLE_GTKTHEME
 #ifndef GARUX_DISABLE_GTKTHEME
 #include "gtktheme.h"
 #endif
 
-
 struct layout_globals_t
 {
        WindowPosition m_position;
@@ -161,6 +173,8 @@ void VFS_Refresh(){
        RefreshReferences();
        // also refresh texture browser
        TextureBrowser_RefreshShaders();
+       // also show textures (all or common)
+       TextureBrowser_ShowStartupShaders( GlobalTextureBrowser() );
 }
 
 void VFS_Restart(){
@@ -219,9 +233,7 @@ void HomePaths_Realise(){
                        }
                        path.clear();
                        path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
-#endif
-
-#if GDEF_OS_WINDOWS
+#elif GDEF_OS_WINDOWS
                        TCHAR mydocsdir[MAX_PATH + 1];
                        wchar_t *mydocsdirw;
                        HMODULE shfolder = LoadLibrary( "shfolder.dll" );
@@ -258,13 +270,19 @@ void HomePaths_Realise(){
                                        break;
                                }
                        }
-#endif
-
-#if GDEF_OS_POSIX
+#elif GDEF_OS_XDG
+                       path.clear();
+                       path << DirectoryCleaned( g_get_user_data_dir() ) << ( prefix + 1 ) << "/";
+                       if ( file_exists( path.c_str() ) && file_is_directory( path.c_str() ) ) {
+                               g_qeglobals.m_userEnginePath = path.c_str();
+                               break;
+                       }
+                       else {
                        path.clear();
                        path << DirectoryCleaned( g_get_home_dir() ) << prefix << "/";
                        g_qeglobals.m_userEnginePath = path.c_str();
                        break;
+                       }
 #endif
                }
 
@@ -440,14 +458,32 @@ void setPakPath( int num, const char* path ){
 }
 
 
-// App Path
+// executable file path (full path)
+CopiedString g_strAppFilePath;
+
+// directory paths
+CopiedString g_strAppPath; 
+CopiedString g_strLibPath;
+CopiedString g_strDataPath;
 
-CopiedString g_strAppPath;                 ///< holds the full path of the executable
+const char* AppFilePath_get(){
+       return g_strAppFilePath.c_str();
+}
 
 const char* AppPath_get(){
        return g_strAppPath.c_str();
 }
 
+const char *LibPath_get()
+{
+    return g_strLibPath.c_str();
+}
+
+const char *DataPath_get()
+{
+    return g_strDataPath.c_str();
+}
+
 /// the path to the local rc-dir
 const char* LocalRcPath_get( void ){
        static CopiedString rc_path;
@@ -546,39 +582,28 @@ struct PakPath4 {
 bool g_disableEnginePath = false;
 bool g_disableHomePath = false;
 
-void Paths_constructPreferences( PreferencesPage& page ){
+void Paths_constructBasicPreferences(  PreferencesPage& page ) {
        page.appendPathEntry( "Engine Path", true, make_property<EnginePath>(g_strEnginePath) );
+}
 
-       page.appendCheckBox(
-               "", "Do not use Engine Path",
-               g_disableEnginePath
-                                                 );
+void Paths_constructPreferences( PreferencesPage& page ){
+       Paths_constructBasicPreferences( page );
 
-       page.appendCheckBox(
-               "", "Do not use Home Path",
-               g_disableHomePath
-               );
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Advanced options" );
+       page.appendCheckBox( "", "Do not use Engine Path", g_disableEnginePath );
+       page.appendCheckBox( "", "Do not use Home Path", g_disableHomePath );
 
-       for ( int i = 0; i < g_pakPathCount; i++ ) {
-               std::string label = "Pak Path " + std::to_string(i);
-               switch (i) {
-                       case 0:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath0>( g_strPakPath[i] ) );
-                       break;
-                       case 1:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath1>( g_strPakPath[i] ) );
-                       break;
-                       case 2:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath2>( g_strPakPath[i] ) );
-                       break;
-                       case 3:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath3>( g_strPakPath[i] ) );
-                       break;
-                       case 4:
-                       page.appendPathEntry( label.c_str(), true, make_property<PakPath4>( g_strPakPath[i] ) );
-                       break;
-}
-       }
+       page.appendSpacer( 4 );
+       page.appendLabel( "", "Only a very few games support Pak Paths," );
+       page.appendLabel( "", "if you don't know what it is, leave this blank." );
+
+       const char *label = "Pak Path ";
+       page.appendPathEntry( label, true, make_property<PakPath0>( g_strPakPath[0] ) );
+       page.appendPathEntry( label, true, make_property<PakPath1>( g_strPakPath[1] ) );
+       page.appendPathEntry( label, true, make_property<PakPath2>( g_strPakPath[2] ) );
+       page.appendPathEntry( label, true, make_property<PakPath3>( g_strPakPath[3] ) );
+       page.appendPathEntry( label, true, make_property<PakPath4>( g_strPakPath[4] ) );
 }
 
 void Paths_constructPage( PreferenceGroup& group ){
@@ -595,14 +620,14 @@ class PathsDialog : public Dialog
 {
 public:
 ui::Window BuildDialog(){
-       auto frame = create_dialog_frame( "Path settings", ui::Shadow::ETCHED_IN );
+       auto frame = create_dialog_frame( "Path Settings", ui::Shadow::ETCHED_IN );
 
        auto vbox2 = create_dialog_vbox( 0, 4 );
        frame.add(vbox2);
 
        {
-               PreferencesPage preferencesPage( *this, vbox2 );
-               Paths_constructPreferences( preferencesPage );
+               PreferencesPage page( *this, vbox2 );
+               Paths_constructBasicPreferences( page );
        }
 
        return ui::Window(create_simple_modal_dialog_window( "Engine Path Not Found", m_modal, frame ));
@@ -761,7 +786,7 @@ void Radiant_detachGameToolsPathObserver( ModuleObserver& observer ){
 void Radiant_Initialise(){
        GlobalModuleServer_Initialise();
 
-       Radiant_loadModulesFromRoot( AppPath_get() );
+       Radiant_loadModulesFromRoot( LibPath_get() );
 
        Preferences_Load();
 
@@ -790,7 +815,7 @@ void Radiant_Shutdown(){
 }
 
 void Exit(){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 }
@@ -951,6 +976,53 @@ void ColorScheme_Ydnar(){
        XY_UpdateAllWindows();
 }
 
+/* color scheme to fit the GTK Adwaita Dark theme */
+void ColorScheme_AdwaitaDark()
+{
+       // SI_Colors0
+       // GlobalTextureBrowser().color_textureback
+       TextureBrowser_setBackgroundColour(GlobalTextureBrowser(), Vector3(0.25f, 0.25f, 0.25f));
+
+       // SI_Colors4
+       g_camwindow_globals.color_cameraback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors12
+       g_camwindow_globals.color_selbrushes3d = Vector3(1.0f, 0.0f, 0.0f);
+       CamWnd_Update(*g_pParentWnd->GetCamWnd());
+
+       // SI_Colors1
+       g_xywindow_globals.color_gridback = Vector3(0.25f, 0.25f, 0.25f);
+       // SI_Colors2
+       g_xywindow_globals.color_gridminor = Vector3(0.21f, 0.23f, 0.23f);
+       // SI_Colors3
+       g_xywindow_globals.color_gridmajor = Vector3(0.14f, 0.15f, 0.15f);
+       // SI_Colors14
+       g_xywindow_globals.color_gridmajor_alt = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_Colors6
+       g_xywindow_globals.color_gridblock = Vector3(1.0f, 1.0f, 1.0f);
+       // SI_Colors7
+       g_xywindow_globals.color_gridtext = Vector3(0.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_selbrushes = Vector3(1.0f, 0.0f, 0.0f);
+       // ??
+       g_xywindow_globals.color_clipper = Vector3(0.0f, 0.0f, 1.0f);
+       // SI_Colors8
+       g_xywindow_globals.color_brushes = Vector3(0.73f, 0.73f, 0.73f);
+
+       // SI_AxisColors0
+       g_xywindow_globals.AxisColorX = Vector3(1.0f, 0.0f, 0.0f);
+       // SI_AxisColors1
+       g_xywindow_globals.AxisColorY = Vector3(0.0f, 1.0f, 0.0f);
+       // SI_AxisColors2
+       g_xywindow_globals.AxisColorZ = Vector3(0.0f, 0.0f, 1.0f);
+       SetWorldspawnColour(g_xywindow_globals.color_brushes);
+       // ??
+       g_xywindow_globals.color_viewname = Vector3(0.5f, 0.0f, 0.75f);
+       XY_UpdateAllWindows();
+
+       // SI_Colors5
+       // g_entity_globals.color_entity = Vector3(0.0f, 0.0f, 0.0f);
+}
+
 typedef Callback<void(Vector3&)> GetColourCallback;
 typedef Callback<void(const Vector3&)> SetColourCallback;
 
@@ -1068,6 +1140,7 @@ ui::MenuItem create_colours_menu(){
        create_menu_item_with_mnemonic( menu_3, "Q3Radiant Original", "ColorSchemeQER" );
        create_menu_item_with_mnemonic( menu_3, "Black and Green", "ColorSchemeBlackAndGreen" );
        create_menu_item_with_mnemonic( menu_3, "Maya/Max/Lightwave Emulation", "ColorSchemeYdnar" );
+       create_menu_item_with_mnemonic(menu_3, "Adwaita Dark", "ColorSchemeAdwaitaDark");
 
 #ifndef GARUX_DISABLE_GTKTHEME
        create_menu_item_with_mnemonic( menu_in_menu, "GTK Theme...", "gtkThemeDlg" );
@@ -1745,9 +1818,11 @@ void Selection_SnapToGrid(){
 
 
 static gint qe_every_second( gpointer data ){
-       GdkModifierType mask;
+       if (g_pParentWnd == nullptr)
+               return TRUE;
 
-       gdk_window_get_pointer( 0, 0, 0, &mask );
+       GdkModifierType mask;
+       gdk_window_get_pointer( gtk_widget_get_window(g_pParentWnd->m_window), nullptr, nullptr, &mask );
 
        if ( ( mask & ( GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK ) ) == 0 ) {
                QE_CheckAutoSave();
@@ -1859,15 +1934,18 @@ void ScreenUpdates_Disable( const char* message, const char* title ){
                bool isActiveApp = MainFrame_isActiveApp();
 
                g_wait = create_wait_dialog( title, message );
-               gtk_grab_add( g_wait.m_window  );
 
                if ( isActiveApp ) {
                        g_wait.m_window.show();
+                       gtk_grab_add( g_wait.m_window  );
                        ScreenUpdates_process();
                }
        }
        else if ( g_wait.m_window.visible() ) {
                g_wait.m_label.text(message);
+               if ( GTK_IS_WINDOW(g_wait.m_window) ) {
+                       gtk_grab_add(g_wait.m_window);
+               }
                ScreenUpdates_process();
        }
        g_wait_stack.push_back( message );
@@ -2092,6 +2170,9 @@ ui::MenuItem create_view_menu( MainFrame::EViewStyle style ){
                create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane In", "CubicClipZoomIn" );
                create_menu_item_with_mnemonic( camera_menu, "Far Clip Plane Out", "CubicClipZoomOut" );
                menu_separator( camera_menu );
+               create_menu_item_with_mnemonic( camera_menu, "Decrease FOV", "FOVDec" );
+               create_menu_item_with_mnemonic( camera_menu, "Increase FOV", "FOVInc" );
+               menu_separator( camera_menu );
                create_menu_item_with_mnemonic( camera_menu, "Next leak spot", "NextLeakSpot" );
                create_menu_item_with_mnemonic( camera_menu, "Previous leak spot", "PrevLeakSpot" );
                menu_separator( camera_menu );
@@ -2344,7 +2425,7 @@ ui::MenuItem create_help_menu(){
 
        create_menu_item_with_mnemonic( menu, "Bug report", makeCallbackF(OpenBugReportURL) );
        create_menu_item_with_mnemonic( menu, "Shortcuts list", makeCallbackF(DoCommandListDlg) );
-       create_menu_item_with_mnemonic( menu, "_About", makeCallbackF(DoAbout) );
+       create_menu_item_with_mnemonic( menu, "_About...", makeCallbackF(DoAbout) );
 
        return help_menu_item;
 }
@@ -2728,10 +2809,14 @@ MainFrame::~MainFrame(){
 
        for ( std::vector<ui::Widget>::iterator i = g_floating_windows.begin(); i != g_floating_windows.end(); ++i )
        {
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
                i->destroy();
+#endif
        }
 
+#ifndef WORKAROUND_MACOS_GTK2_DESTROY
        m_window.destroy();
+#endif
 }
 
 void MainFrame::SetActiveXY( XYWnd* p ){
@@ -2888,13 +2973,16 @@ WindowPositionTracker g_posXZWnd;
 WindowPositionTracker g_posYZWnd;
 
 static gint mainframe_delete( ui::Widget widget, GdkEvent *event, gpointer data ){
-       if ( ConfirmModified( "Exit Radiant" ) ) {
+       if ( ConfirmModified( "Exit " RADIANT_NAME ) ) {
                gtk_main_quit();
        }
 
        return TRUE;
 }
 
+PanedState g_single_hpaned = { 0.75f, -1, };
+PanedState g_single_vpaned = { 0.75f, -1, };
+
 void MainFrame::Create(){
        ui::Window window = ui::Window( ui::window_type::TOP );
 
@@ -3002,7 +3090,8 @@ void MainFrame::Create(){
 
        window.show();
 
-       if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft ) {
+       if ( CurrentStyle() == eRegular || CurrentStyle() == eRegularLeft )
+       {
                {
                        ui::Widget hsplit = ui::HPaned(ui::New);
                        m_hSplit = hsplit;
@@ -3067,7 +3156,8 @@ void MainFrame::Create(){
 
                gtk_paned_set_position( GTK_PANED( m_vSplit2 ), g_layout_globals.nCamHeight );
        }
-       else if ( CurrentStyle() == eFloating ) {
+       else if ( CurrentStyle() == eFloating )
+       {
                {
                        ui::Window window = ui::Window(create_persistent_floating_window( "Camera", m_window ));
                        global_accel_connect_window( window );
@@ -3083,11 +3173,8 @@ void MainFrame::Create(){
                                window.add(frame);
                        }
                        CamWnd_setParent( *m_pCamWnd, window );
-#define GARUX_GTK_WORKAROUND
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( window ), "glwidget", CamWnd_getWidget( *m_pCamWnd ) );
-#endif
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, CamWnd_getWidget( *m_pCamWnd ) );
 
                        g_floating_windows.push_back( window );
                }
@@ -3107,10 +3194,8 @@ void MainFrame::Create(){
                                window.add(frame);
                        }
                        XY_Top_Shown_Construct( window );
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( window ), "glwidget", m_pXYWnd->GetWidget() );
-#endif
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXYWnd->GetWidget() );
 
                        g_floating_windows.push_back( window );
                }
@@ -3130,10 +3215,8 @@ void MainFrame::Create(){
                        }
 
                        XZ_Front_Shown_Construct( window );
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( window ), "glwidget", m_pXZWnd->GetWidget() );
-#endif
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pXZWnd->GetWidget() );
 
                        g_floating_windows.push_back( window );
                }
@@ -3153,10 +3236,8 @@ void MainFrame::Create(){
                        }
 
                        YZ_Side_Shown_Construct( window );
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( window ), "glwidget", m_pYZWnd->GetWidget() );
-#endif
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, m_pYZWnd->GetWidget() );
 
                        g_floating_windows.push_back( window );
                }
@@ -3164,16 +3245,13 @@ void MainFrame::Create(){
                {
                        auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( GroupDialog_getWindow() ), "glwidget", TextureBrowser_getGLWidget() );
-#endif
 
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( GroupDialog_getWindow(), TextureBrowser_getGLWidget() );
                }
 
                GroupDialog_show();
        }
-       else // 4 way
+       else if ( CurrentStyle() == eSplit )
        {
                m_pCamWnd = NewCamWnd();
                GlobalCamera_setCamWnd( *m_pCamWnd );
@@ -3202,12 +3280,60 @@ void MainFrame::Create(){
                {
             auto frame = create_framed_widget( TextureBrowser_constructWindow( GroupDialog_getWindow() ) );
                        g_page_textures = GroupDialog_addPage( "Textures", frame, TextureBrowserExportTitleCaller() );
-#ifndef GARUX_GTK_WORKAROUND
-                       /* workaround for gtk 2.24 issue: not displayed glwidget after toggle */
-                       g_object_set_data( G_OBJECT( GroupDialog_getWindow() ), "glwidget", TextureBrowser_getGLWidget() );
-#endif
+
+                       WORKAROUND_GOBJECT_SET_GLWIDGET( window, TextureBrowser_getGLWidget() );
                }
        }
+       else // single window
+       {
+               m_pCamWnd = NewCamWnd();
+               GlobalCamera_setCamWnd( *m_pCamWnd );
+               CamWnd_setParent( *m_pCamWnd, window );
+
+               ui::Widget camera = CamWnd_getWidget( *m_pCamWnd );
+
+               m_pYZWnd = new XYWnd();
+               m_pYZWnd->SetViewType( YZ );
+
+               ui::Widget yz = m_pYZWnd->GetWidget();
+
+               m_pXYWnd = new XYWnd();
+               m_pXYWnd->SetViewType( XY );
+
+               ui::Widget xy = m_pXYWnd->GetWidget();
+
+               m_pXZWnd = new XYWnd();
+               m_pXZWnd->SetViewType( XZ );
+
+               ui::Widget xz = m_pXZWnd->GetWidget();
+
+               ui::Widget hsplit = ui::HPaned(ui::New);
+               vbox.pack_start( hsplit, TRUE, TRUE, 0 );
+               hsplit.show();
+
+               ui::Widget split = create_split_views( camera, yz, xy, xz );
+
+               ui::Widget vsplit = ui::VPaned(ui::New);
+               vsplit.show();
+
+               // textures
+               ui::Widget texture_window = create_framed_widget( TextureBrowser_constructWindow( window ) );
+
+               // console
+               ui::Widget console_window = create_framed_widget( Console_constructWindow( window ) );
+
+               gtk_paned_add1( GTK_PANED( hsplit ), split );
+               gtk_paned_add2( GTK_PANED( hsplit ), vsplit );
+
+               gtk_paned_add1( GTK_PANED( vsplit ), texture_window  );
+               gtk_paned_add2( GTK_PANED( vsplit ), console_window  );
+
+               hsplit.connect( "size_allocate", G_CALLBACK( hpaned_allocate ), &g_single_hpaned );
+               hsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_hpaned );
+
+               vsplit.connect( "size_allocate", G_CALLBACK( vpaned_allocate ), &g_single_vpaned );
+               vsplit.connect( "notify::position", G_CALLBACK( paned_position ), &g_single_vpaned );
+       }
 
        EntityList_constructWindow( window );
        PreferencesDialog_constructWindow( window );
@@ -3295,7 +3421,7 @@ void MainFrame::SetStatusText( CopiedString& status_text, const char* pText ){
 }
 
 void Sys_Status( const char* status ){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetStatusText( g_pParentWnd->m_command_status, status );
        }
 }
@@ -3327,7 +3453,7 @@ void MainFrame::SetGridStatus(){
 }
 
 void GridStatus_onTextureLockEnabledChanged(){
-       if ( g_pParentWnd != 0 ) {
+       if ( g_pParentWnd != nullptr ) {
                g_pParentWnd->SetGridStatus();
        }
 }
@@ -3372,7 +3498,7 @@ void GlobalGL_sharedContextDestroyed(){
 
 void Layout_constructPreferences( PreferencesPage& page ){
        {
-               const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png" };
+               const char* layouts[] = { "window1.png", "window2.png", "window3.png", "window4.png", "window5.png" };
                page.appendRadioIcons(
                        "Window Layout",
                        STRING_ARRAY_RANGE( layouts ),
@@ -3408,9 +3534,9 @@ void Layout_registerPreferencesPage(){
        PreferencesDialog_addInterfacePage( makeCallbackF(Layout_constructPage) );
 }
 
-
 #include "preferencesystem.h"
 #include "stringio.h"
+#include "transformpath/transformpath.h"
 
 void MainFrame_Construct(){
        GlobalCommands_insert( "OpenManual", makeCallbackF(OpenHelpURL), Accelerator( GDK_KEY_F1 ) );
@@ -3489,6 +3615,7 @@ void MainFrame_Construct(){
        GlobalCommands_insert( "ColorSchemeQER", makeCallbackF(ColorScheme_QER) );
        GlobalCommands_insert( "ColorSchemeBlackAndGreen", makeCallbackF(ColorScheme_Black) );
        GlobalCommands_insert( "ColorSchemeYdnar", makeCallbackF(ColorScheme_Ydnar) );
+       GlobalCommands_insert("ColorSchemeAdwaitaDark", makeCallbackF(ColorScheme_AdwaitaDark));
        GlobalCommands_insert( "ChooseTextureBackgroundColor", makeCallback( g_ColoursMenu.m_textureback ) );
        GlobalCommands_insert( "ChooseGridBackgroundColor", makeCallback( g_ColoursMenu.m_xyback ) );
        GlobalCommands_insert( "ChooseGridMajorColor", makeCallback( g_ColoursMenu.m_gridmajor ) );
@@ -3577,9 +3704,11 @@ void MainFrame_Construct(){
 #error "unknown platform"
 #endif
                ;
+
                StringOutputStream path( 256 );
                path << DirectoryCleaned( g_pGameDescription->getRequiredKeyValue( ENGINEPATH_ATTRIBUTE ) );
-               g_strEnginePath = path.c_str();
+
+               g_strEnginePath = transformPath( path.c_str() ).c_str();
                GlobalPreferenceSystem().registerPreference( "EnginePath", make_property_string( g_strEnginePath ) );
        }
 
@@ -3604,8 +3733,7 @@ void MainFrame_Construct(){
        g_entityCount.setCountChangedCallback( makeCallbackF(QE_entityCountChanged) );
        GlobalEntityCreator().setCounter( &g_entityCount );
 
-       GLWidget_sharedContextCreated = GlobalGL_sharedContextCreated;
-       GLWidget_sharedContextDestroyed = GlobalGL_sharedContextDestroyed;
+       glwidget_set_shared_context_constructors( GlobalGL_sharedContextCreated, GlobalGL_sharedContextDestroyed);
 
        GlobalEntityClassManager().attach( g_WorldspawnColourEntityClassObserver );
 }
@@ -3625,3 +3753,61 @@ void GLWindow_Construct(){
 
 void GLWindow_Destroy(){
 }
+
+/* HACK: If ui::main is not called yet,
+gtk_main_quit will not quit, so tell main
+to not call ui::main. This happens when a
+map is loaded from command line and require
+a restart because of wrong format.
+Delete this when the code to not have to
+restart to load another format is merged. */
+extern bool g_dontStart;
+
+void Radiant_Restart(){
+       // preferences are expected to be already saved in any way
+       // this is just to be sure and be future proof
+       Preferences_Save();
+
+       // this asks user for saving if map is modified
+       // user can chose to not save, it's ok
+       ConfirmModified( "Restart " RADIANT_NAME );
+
+       int status;
+
+       char *argv[ 3 ];
+       char exe_file[ 256 ];
+       char map_file[ 256 ];
+       bool with_map = false;
+
+       strncpy( exe_file, g_strAppFilePath.c_str(), 256 );
+
+       if ( !Map_Unnamed( g_map ) ) {
+               strncpy( map_file, Map_Name( g_map ), 256 );
+               with_map = true;
+       }
+
+       argv[ 0 ] = exe_file;
+       argv[ 1 ] = with_map ? map_file : NULL;
+       argv[ 2 ] = NULL;
+
+#if GDEF_OS_WINDOWS
+       status = !_spawnvpe( P_NOWAIT, exe_file, argv, environ );
+#else
+       pid_t pid;
+
+       status = posix_spawn( &pid, exe_file, NULL, NULL, argv, environ );
+#endif
+
+       // quit if radiant successfully started
+       if ( status == 0 ) {
+               gtk_main_quit();
+               /* HACK: If ui::main is not called yet,
+               gtk_main_quit will not quit, so tell main
+               to not call ui::main. This happens when a
+               map is loaded from command line and require
+               a restart because of wrong format.
+               Delete this when the code to not have to
+               restart to load another format is merged. */
+               g_dontStart = true;
+       }
+}
index ca8c79c64e6fc641afc03e387e6188c4d40fd8ea..00eccd7c5ba5c3b06fc1baebec7ac599ee336956 100644 (file)
@@ -54,6 +54,7 @@ enum EViewStyle
        eFloating = 1,
        eSplit = 2,
        eRegularLeft = 3,
+       eSingle = 4,
 };
 
 MainFrame();
@@ -212,8 +213,15 @@ const int g_pakPathCount = 5;
 extern CopiedString g_strPakPath[g_pakPathCount];
 const char* PakPath_get( int num );
 
+extern CopiedString g_strAppFilePath;
 extern CopiedString g_strAppPath;
+extern CopiedString g_strLibPath;
+extern CopiedString g_strDataPath;
+
+const char* AppFilePath_get();
 const char* AppPath_get();
+const char *LibPath_get();
+const char *DataPath_get();
 
 extern CopiedString g_strSettingsPath;
 const char* SettingsPath_get();
@@ -265,6 +273,8 @@ void Radiant_detachHomePathsObserver( ModuleObserver& observer );
 void MainFrame_Construct();
 void MainFrame_Destroy();
 
+extern char **environ;
+void Radiant_Restart();
 
 extern float ( *GridStatus_getGridSize )();
 extern int ( *GridStatus_getRotateIncrement )();
index 0d2e5b331badd23a0a21037486fe0113c8ee297d..e1e6a727bca7fad9cc8d51ffbc6fa9523edc3320 100644 (file)
@@ -966,6 +966,8 @@ void Map_LoadFile( const char *filename ){
        MRU_AddFile( filename );
        g_strLastMapFolder = g_path_get_dirname( filename );
 
+       bool switch_format = false;
+
        {
                ScopeTimer timer( "map load" );
 
@@ -992,6 +994,7 @@ void Map_LoadFile( const char *filename ){
                                if ( !format->wrongFormat ) {
                                        break;
                                }
+                               switch_format = !switch_format;
                        }
                }
 
@@ -1012,6 +1015,8 @@ void Map_LoadFile( const char *filename ){
        Map_StartPosition();
 
        g_currentMap = &g_map;
+
+       Brush_switchFormat( switch_format );
 }
 
 class Excluder
@@ -1578,54 +1583,55 @@ tryDecompile:
        const char *type = GlobalRadiant().getGameDescriptionKeyValue( "q3map2_type" );
        int n = string_length( path_get_extension( filename ) );
        if ( n && ( extension_equal( path_get_extension( filename ), "bsp" ) || extension_equal( path_get_extension( filename ), "map" ) ) ) {
-               StringBuffer output;
-               output.push_string( AppPath_get() );
-               output.push_string( "q3map2." );
-               output.push_string( RADIANT_EXECUTABLE );
-               output.push_string( " -v -game " );
-               output.push_string( ( type && *type ) ? type : "quake3" );
-               output.push_string( " -fs_basepath \"" );
-               output.push_string( EnginePath_get() );
-               output.push_string( "\" -fs_homepath \"" );
-               output.push_string( g_qeglobals.m_userEnginePath.c_str() );
-               output.push_string( "\"" );
+               std::string output;
+               output += AppPath_get();
+               output += "q3map2";
+               output += GDEF_OS_EXE_EXT;
+
+               output += " -v -game ";
+               output += ( type && *type ) ? type : "quake3";
+               output += " -fs_basepath \"";
+               output += EnginePath_get();
+               output += "\" -fs_homepath \"";
+               output += g_qeglobals.m_userEnginePath.c_str();
+               output += "\"";
 
                // extra pakpaths
                for ( int i = 0; i < g_pakPathCount; i++ ) {
                        if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) {
-                               output.push_string( " -fs_pakpath \"" );
-                               output.push_string( g_strPakPath[i].c_str() );
-                               output.push_string( "\"" );
+                               output += " -fs_pakpath \"";
+                               output += g_strPakPath[i].c_str();
+                               output += "\"";
                        }
                }
 
                // extra switches
                if ( g_disableEnginePath ) {
-                       output.push_string( " -fs_nobasepath " );
+                       output += " -fs_nobasepath ";
                }
 
                if ( g_disableHomePath ) {
-                       output.push_string( " -fs_nohomepath " );
+                       output += " -fs_nohomepath ";
                }
 
-               output.push_string( " -fs_game " );
-               output.push_string( gamename_get() );
-               output.push_string( " -convert -format " );
-               output.push_string( Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map" );
+               output += " -fs_game ";
+               output += gamename_get();
+               output += " -convert -format ";
+               output += Brush::m_type == eBrushTypeQuake3BP ? "map_bp" : "map";
                if ( extension_equal( path_get_extension( filename ), "map" ) ) {
-                       output.push_string( " -readmap " );
+                       output += " -readmap ";
                }
-               output.push_string( " \"" );
-               output.push_string( filename );
-               output.push_string( "\"" );
+               output += " \"";
+               output += filename;
+               output += "\"";
 
                // run
                Q_Exec( NULL, output.c_str(), NULL, false, true );
 
                // rebuild filename as "filenamewithoutext_converted.map"
-               output.clear();
-               output.push_range( filename, filename + string_length( filename ) - ( n + 1 ) );
-               output.push_string( "_converted.map" );
+               output = "";
+               output.append( filename, string_length( filename ) - ( n + 1 ) );
+               output += "_converted.map";
                filename = output.c_str();
 
                // open
index dc0525029b1d87ffd28b797fc5ac218e1ba72008..452feaf69f6c08e6242a4d55b76a69405e4f4032 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "os/file.h"
 #include "generic/callback.h"
-#include "stream/stringstream.h"
 #include "convert.h"
 
 #include "gtkutil/menu.h"
@@ -50,9 +49,11 @@ inline const char* MRU_GetText( std::size_t index ){
 
 class EscapedMnemonic
 {
-StringBuffer m_buffer;
+private:
+       std::string m_buffer;
+
 public:
-EscapedMnemonic( std::size_t capacity ) : m_buffer( capacity ){
+       EscapedMnemonic() : m_buffer(){
        m_buffer.push_back( '_' );
 }
 const char* c_str() const {
@@ -81,7 +82,7 @@ inline EscapedMnemonic& operator<<( EscapedMnemonic& ostream, const T& t ){
 
 
 void MRU_updateWidget( std::size_t index, const char *filename ){
-       EscapedMnemonic mnemonic( 64 );
+       EscapedMnemonic mnemonic;
        mnemonic << Unsigned( index + 1 ) << "- " << filename;
        gtk_label_set_text_with_mnemonic( GTK_LABEL( gtk_bin_get_child( GTK_BIN( MRU_items[index] ) ) ), mnemonic.c_str() );
 }
@@ -173,7 +174,9 @@ void MRU_Activate( std::size_t index ){
 
 class LoadMRU
 {
+private:
 std::size_t m_number;
+
 public:
 LoadMRU( std::size_t number )
        : m_number( number ){
index 9a4a4f22a2d572bd9bcf15ffb041c4866554e09e..869bc1d86690b28c1eb9d723fe0a9d8cdefaa6ab 100644 (file)
@@ -35,7 +35,7 @@ void MultiMonitor_constructPreferences( PreferencesPage& page ){
        ui::CheckButton primary_monitor = page.appendCheckBox( "Multi Monitor", "Start on Primary Monitor", g_multimon_globals.m_bStartOnPrimMon );
        ui::CheckButton popup = page.appendCheckBox(
                "", "Disable system menu on popup windows",
-               mkImportExportCallback( g_Multimon_enableSysMenuPopups )
+               make_property( g_Multimon_enableSysMenuPopups )
                );
        Widget_connectToggleDependency( popup, primary_monitor );
 }
index 9d55cf3b4a5126afe5d54d8da82ce96097d762ea..2c3d6dd0cc5e05570c302caa3231f32e76589683 100644 (file)
@@ -128,6 +128,7 @@ RadiantCoreAPI(){
        m_radiantcore.getEnginePath = &EnginePath_get;
        m_radiantcore.getLocalRcPath = &LocalRcPath_get;
        m_radiantcore.getAppPath = &AppPath_get;
+       m_radiantcore.getDataPath = &DataPath_get;
        m_radiantcore.getGameToolsPath = &GameToolsPath_get;
        m_radiantcore.getSettingsPath = &SettingsPath_get;
        m_radiantcore.getMapsPath = &getMapsPath;
index 6e24976d212c3a1eef45a14e0d9896b25e1b13bf..25ff2cd49fc8fbd7ee714e8931bcc99e11cf9aa7 100644 (file)
@@ -42,13 +42,13 @@ ui::Image new_plugin_image( const char* filename ){
 
        {
                StringOutputStream fullpath( 256 );
-               fullpath << AppPath_get() << g_pluginsDir << "bitmaps/" << filename;
+               fullpath << DataPath_get() << g_pluginsDir << "bitmaps/" << filename;
                if ( auto image = image_new_from_file_with_mask(fullpath.c_str()) ) return image;
        }
 
        {
                StringOutputStream fullpath( 256 );
-               fullpath << AppPath_get() << g_modulesDir << "bitmaps/" << filename;
+               fullpath << DataPath_get() << g_modulesDir << "bitmaps/" << filename;
                if ( auto image = image_new_from_file_with_mask(fullpath.c_str()) ) return image;
        }
 
index 4c00125e70fd472b43ffa4d64abce37c770a94c3..a689f71c63f11f2b9497ca2e605f05a7b6a6dc9b 100644 (file)
@@ -122,7 +122,7 @@ CGameDescription::CGameDescription( xmlDocPtr pDoc, const CopiedString& gameFile
 
        {
                StringOutputStream path( 256 );
-               path << AppPath_get() << gameFile.c_str() << "/";
+               path << DataPath_get() << "gamepacks/" << gameFile.c_str() << "/";
                mGameToolsPath = path.c_str();
        }
 
@@ -205,13 +205,10 @@ bool Preferences_Save( PreferenceDictionary& preferences, const char* filename )
 }
 
 bool Preferences_Save_Safe( PreferenceDictionary& preferences, const char* filename ){
-       Array<char> tmpName( filename, filename + strlen( filename ) + 1 + 3 );
-       *( tmpName.end() - 4 ) = 'T';
-       *( tmpName.end() - 3 ) = 'M';
-       *( tmpName.end() - 2 ) = 'P';
-       *( tmpName.end() - 1 ) = '\0';
+       std::string tmpName( filename );
+       tmpName += "TMP";
 
-       return Preferences_Save( preferences, tmpName.data() )
+       return Preferences_Save( preferences, tmpName.c_str() )
                   && ( !file_exists( filename ) || file_remove( filename ) )
                   && file_move( tmpName.data(), filename );
 }
@@ -224,7 +221,7 @@ struct LogConsole {
 
        static void Import(bool value) {
                g_Console_enableLogging = value;
-               Sys_LogFile(g_Console_enableLogging);
+               Sys_EnableLogFile(g_Console_enableLogging);
        }
 };
 
@@ -232,6 +229,7 @@ struct LogConsole {
 void RegisterGlobalPreferences( PreferenceSystem& preferences ){
        preferences.registerPreference( "gamefile", make_property_string( g_GamesDialog.m_sGameFile ) );
        preferences.registerPreference( "gamePrompt", make_property_string( g_GamesDialog.m_bGamePrompt ) );
+       preferences.registerPreference( "skipGamePromptOnce", make_property_string( g_GamesDialog.m_bSkipGamePromptOnce ) );
        preferences.registerPreference( "log console", make_property_string<LogConsole>() );
 }
 
@@ -282,7 +280,18 @@ void CGameDialog::GameFileImport( int value ){
        {
                ++iGame;
        }
+
+       if ( ( *iGame )->mGameFile != m_sGameFile ) {
        m_sGameFile = ( *iGame )->mGameFile;
+
+               // do not trigger radiant restart when switching game on startup using Global Preferences dialog
+               if ( !onStartup ) {
+                       PreferencesDialog_restartRequired( "Selected Game" );
+               }
+       }
+
+       // onStartup can only be true once, when Global Preferences are displayed at startup
+       onStartup = false;
 }
 
 void CGameDialog::GameFileExport( const Callback<void(int)> & importCallback ) const {
@@ -340,9 +349,33 @@ ui::Window CGameDialog::BuildDialog(){
        return create_simple_modal_dialog_window( "Global Preferences", m_modal, frame );
 }
 
+static void StringReplace( std::string& input, const std::string& first, const std::string& second )
+{
+       size_t found = 0;
+       while ( ( found = input.find(first, found) ) != std::string::npos )
+       {
+               input.replace( found, first.length(), second );
+       }
+}
+
+// FIXME, for some unknown reason it sorts “Quake 3” after “Quake 4”.
+static bool CompareGameName( CGameDescription *first, CGameDescription *second )
+{
+       std::string string1( first->getRequiredKeyValue( "name" ) );
+       std::string string2( second->getRequiredKeyValue( "name" ) );
+
+       // HACK: Replace some roman numerals.
+       StringReplace( string1, " III", " 3" );
+       StringReplace( string2, " III", " 3" );
+       StringReplace( string1, " II", " 2" );
+       StringReplace( string2, " II", " 2" );
+
+       return string1 < string2;
+}
+
 void CGameDialog::ScanForGames(){
        StringOutputStream strGamesPath( 256 );
-       strGamesPath << AppPath_get() << "games/";
+       strGamesPath << DataPath_get() << "gamepacks/games/";
        const char *path = strGamesPath.c_str();
 
        globalOutputStream() << "Scanning for game description files: " << path << '\n';
@@ -371,6 +404,8 @@ void CGameDialog::ScanForGames(){
                } else {
                        globalErrorStream() << "XML parser failed on '" << strPath.c_str() << "'\n";
                }
+
+               mGames.sort(CompareGameName);
        });
 }
 
@@ -400,9 +435,12 @@ void CGameDialog::Reset(){
 }
 
 void CGameDialog::Init(){
+       bool gamePrompt = false;
+
        InitGlobalPrefPath();
        LoadPrefs();
        ScanForGames();
+
        if ( mGames.empty() ) {
                Error( "Didn't find any valid game file descriptions, aborting\n" );
        }
@@ -423,7 +461,15 @@ void CGameDialog::Init(){
 
        CGameDescription* currentGameDescription = 0;
 
-       if ( !m_bGamePrompt ) {
+       // m_bSkipGamePromptOnce is used to not prompt for game on restart, only on fresh startup
+       if ( m_bGamePrompt && !m_bSkipGamePromptOnce ) {
+               gamePrompt = true;
+       }
+
+       m_bSkipGamePromptOnce = false;
+       g_GamesDialog.SavePrefs();
+
+       if ( !gamePrompt ) {
                // search by .game name
                std::list<CGameDescription *>::iterator iGame;
                for ( iGame = mGames.begin(); iGame != mGames.end(); ++iGame )
@@ -434,13 +480,19 @@ void CGameDialog::Init(){
                        }
                }
        }
-       if ( m_bGamePrompt || !currentGameDescription ) {
+
+       if ( gamePrompt || !currentGameDescription ) {
+               onStartup = true;
                Create();
                DoGameDialog();
                // use m_nComboSelect to identify the game to run as and set the globals
                currentGameDescription = GameDescriptionForComboItem();
                ASSERT_NOTNULL( currentGameDescription );
        }
+       else {
+               onStartup = false;
+       }
+
        g_pGameDescription = currentGameDescription;
 
        g_pGameDescription->Dump();
@@ -476,8 +528,8 @@ CGameDialog g_GamesDialog;
 
 static void OnButtonClean( ui::Widget widget, gpointer data ){
        // make sure this is what the user wants
-       if ( ui::alert( g_Preferences.GetWidget(), "This will close Radiant and clean the corresponding registry entries.\n"
-                                                                                                                                 "Next time you start Radiant it will be good as new. Do you wish to continue?",
+       if ( ui::alert( g_Preferences.GetWidget(), "This will close " RADIANT_NAME " and clean the corresponding registry entries.\n"
+                                                                                                                                 "Next time you start " RADIANT_NAME " it will be good as new. Do you wish to continue?",
                                                 "Reset Registry", ui::alert_type::YESNO, ui::alert_icon::Asterisk ) == ui::alert_response::YES ) {
                PrefsDlg *dlg = (PrefsDlg*)data;
                dlg->EndModal( eIDCANCEL );
@@ -677,7 +729,10 @@ ui::Window PrefsDlg::BuildDialog(){
        PreferencesDialog_addInterfacePreferences( makeCallbackF(Interface_constructPreferences) );
        Mouse_registerPreferencesPage();
 
-       ui::Window dialog = ui::Window(create_floating_window( "NetRadiant Preferences", m_parent ));
+       ui::Window dialog = ui::Window(create_floating_window( RADIANT_NAME " Preferences", m_parent ));
+
+       gtk_window_set_transient_for( dialog, m_parent );
+       gtk_window_set_position( dialog, GTK_WIN_POS_CENTER_ON_PARENT );
 
        {
                auto mainvbox = ui::VBox( FALSE, 5 );
@@ -878,6 +933,7 @@ void Preferences_Save(){
                return;
        }
 
+       // save global preferences
        g_GamesDialog.SavePrefs();
 
        globalOutputStream() << "saving local preferences to " << g_Preferences.m_inipath->str << "\n";
@@ -905,22 +961,39 @@ void PreferencesDialog_restartRequired( const char* staticName ){
        g_restart_required.push_back( staticName );
 }
 
-void PreferencesDialog_showDialog(){
-       //if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) {
-       if ( g_Preferences.DoModal() == eIDOK ) {
-               if ( !g_restart_required.empty() ) {
-                       StringOutputStream message( 256 );
-                       message << "Preference changes require a restart:\n";
-                       for ( std::vector<const char*>::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i )
-                       {
-                               message << ( *i ) << '\n';
-                       }
-                       ui::alert( MainFrame_getWindow(), message.c_str() );
-                       g_restart_required.clear();
+bool PreferencesDialog_isRestartRequired(){
+       return !g_restart_required.empty();
+}
+
+void PreferencesDialog_restartIfRequired(){
+       if ( !g_restart_required.empty() ) {
+               StringOutputStream message( 256 );
+               message << "Preference changes require a restart:\n\n";
+
+               for ( std::vector<const char*>::iterator i = g_restart_required.begin(); i != g_restart_required.end(); ++i )
+               {
+                       message << ( *i ) << '\n';
+               }
+
+               message << "\nRestart now?";
+
+               auto ret = ui::alert( MainFrame_getWindow(), message.c_str(), "Restart " RADIANT_NAME "?", ui::alert_type::YESNO, ui::alert_icon::Question );
+
+               g_restart_required.clear();
+
+               if ( ret == ui::alert_response::YES ) {
+                       g_GamesDialog.m_bSkipGamePromptOnce = true;
+                       Radiant_Restart();
                }
        }
 }
 
+void PreferencesDialog_showDialog(){
+       if ( ConfirmModified( "Edit Preferences" ) && g_Preferences.DoModal() == eIDOK ) {
+               PreferencesDialog_restartIfRequired();
+       }
+}
+
 struct GameName {
        static void Export(const Callback<void(const char *)> &returnz) {
                returnz(gamename_get());
index 59dd60daaa0c6e42633932892511d91fa594429c..a7739d4dce474fa6bdae9165e85422097c68d153 100644 (file)
@@ -71,6 +71,12 @@ void appendRadioIcons( const char* name, StringArrayRange icons, Property<int> c
 void appendRadioIcons( const char* name, int& data, StringArrayRange icons ){
        m_dialog.addRadioIcons( m_vbox, name, data, icons );
 }
+ui::Widget appendSpacer( int dimension ){
+       return m_dialog.addSpacer( m_vbox, dimension );
+}
+ui::Widget appendLabel( const char* name, const char* text ){
+       return m_dialog.addLabel( m_vbox, name, text );
+}
 ui::Widget appendEntry( const char* name, Property<int> const &cb ){
        return m_dialog.addIntEntry( m_vbox, name, cb );
 }
@@ -123,6 +129,7 @@ void PreferencesDialog_addDisplayPage( const PreferenceGroupCallback& callback )
 void PreferencesDialog_addSettingsPreferences( const PreferencesPageCallback& callback );
 void PreferencesDialog_addSettingsPage( const PreferenceGroupCallback& callback );
 
+bool PreferencesDialog_isRestartRequired();
 void PreferencesDialog_restartRequired( const char* staticName );
 
 template<typename Value>
@@ -222,6 +229,11 @@ mutable int m_nComboSelect;   ///< intermediate int value for combo in dialog bo
 
 public:
 
+/*!
+  used to no ask for restart when switching game from Gobal Preferences window displayed on startup
+*/
+
+bool onStartup;
 /*!
    those settings are saved in the global prefs file
    I'm too lazy to wrap behind protected access, not sure this needs to be public
@@ -238,6 +250,12 @@ CopiedString m_sGameFile;
    prompt which game to load on startup
  */
 bool m_bGamePrompt;
+/*!
+   when if m_bGamePrompt is true
+   do not prompt at startup which game to load this time, but prompt the next times
+   this is used to not uselessly prompt game after having restarted because user switched game
+ */
+bool m_bSkipGamePromptOnce;
 /*!
    log console to radiant.log
    m_bForceLogConsole is an obscure forced latching situation
@@ -253,6 +271,7 @@ std::list<CGameDescription*> mGames;
 CGameDialog() :
        m_sGameFile( "" ),
        m_bGamePrompt( true ),
+       m_bSkipGamePromptOnce( false ),
        m_bForceLogConsole( false ){
 }
 virtual ~CGameDialog();
@@ -338,9 +357,13 @@ public:
 
 ui::Widget m_notebook{ui::null};
 
-virtual ~PrefsDlg(){
-       g_string_free( m_rc_path, true );
-       g_string_free( m_inipath, true );
+virtual ~PrefsDlg() {
+       if (m_rc_path) {
+               g_string_free( m_rc_path, true );
+       }
+       if (m_inipath) {
+               g_string_free( m_inipath, true );
+       }
 }
 
 /*!
@@ -392,6 +415,8 @@ extern preferences_globals_t g_preferences_globals;
 void PreferencesDialog_constructWindow( ui::Window main_window );
 void PreferencesDialog_destroyWindow();
 
+
+void PreferencesDialog_restartIfRequired();
 void PreferencesDialog_showDialog();
 
 void GlobalPreferences_Init();
index efae51c42438df2c94ea4dbb88e260a618814f8c..ab62a9190bc28f35d1307ad04e8dcf2686ea4531 100644 (file)
@@ -79,44 +79,58 @@ void QE_InitVFS(){
        // we need to call in order, the mod ones first, then the base ones .. they will be searched in this order
        // *nix systems have a dual filesystem in ~/.q3a, which is searched first .. so we need to add that too
 
-       const char* gamename = gamename_get();
+       const char* enginepath = EnginePath_get();
+       const char* homepath = g_qeglobals.m_userEnginePath.c_str(); // returns enginepath if not homepath is not set
+
        const char* basegame = basegame_get();
-       const char* userRoot = g_qeglobals.m_userEnginePath.c_str();
-       const char* globalRoot = EnginePath_get();
+       const char* gamename = gamename_get(); // returns basegame if gamename is not set
 
        // editor builtin VFS
        StringOutputStream editorGamePath( 256 );
-       editorGamePath << GlobalRadiant().getAppPath() << DEFAULT_EDITORVFS_DIRNAME;
+       editorGamePath << GlobalRadiant().getDataPath() << DEFAULT_EDITORVFS_DIRNAME;
        GlobalFileSystem().initDirectory( editorGamePath.c_str() );
 
+       globalOutputStream() << "engine path: " << enginepath << "\n";
+       globalOutputStream() << "home path: " << homepath << "\n";
+       globalOutputStream() << "base game: " << basegame << "\n";
+       globalOutputStream() << "game name: " << gamename << "\n";
+
        // if we have a mod dir
        if ( !string_equal( gamename, basegame ) ) {
+               // if we have a home dir
+               if ( !string_equal( homepath, enginepath ) )
+               {
                // ~/.<gameprefix>/<fs_game>
-               if ( userRoot && !string_equal( globalRoot, userRoot ) && !g_disableHomePath ) {
+               if ( homepath && !string_equal( enginepath, homepath ) && !g_disableHomePath ) {
                        StringOutputStream userGamePath( 256 );
-                       userGamePath << userRoot << gamename << '/';
+                               userGamePath << homepath << gamename << '/';
                        GlobalFileSystem().initDirectory( userGamePath.c_str() );
                }
+               }
 
                // <fs_basepath>/<fs_game>
                if ( !g_disableEnginePath ) {
                        StringOutputStream globalGamePath( 256 );
-                       globalGamePath << globalRoot << gamename << '/';
+                       globalGamePath << enginepath << gamename << '/';
                        GlobalFileSystem().initDirectory( globalGamePath.c_str() );
                }
        }
 
+       // if we have a home dir
+       if ( !string_equal( homepath, enginepath ) )
+       {
        // ~/.<gameprefix>/<fs_main>
-       if ( userRoot && !string_equal( globalRoot, userRoot ) && !g_disableHomePath ) {
+       if ( homepath && !string_equal( enginepath, homepath ) && !g_disableHomePath ) {
                StringOutputStream userBasePath( 256 );
-               userBasePath << userRoot << basegame << '/';
+                       userBasePath << homepath << basegame << '/';
                GlobalFileSystem().initDirectory( userBasePath.c_str() );
        }
+       }
 
        // <fs_basepath>/<fs_main>
        if ( !g_disableEnginePath ) {
                StringOutputStream globalBasePath( 256 );
-               globalBasePath << globalRoot << basegame << '/';
+               globalBasePath << enginepath << basegame << '/';
                GlobalFileSystem().initDirectory( globalBasePath.c_str() );
        }
 
@@ -173,37 +187,45 @@ bool ConfirmModified( const char* title ){
 }
 
 void bsp_init(){
+       // this is expected to not be used since
+       // ".[ExecutableType]" is replaced by "[ExecutableExt]"
+       const char *exe_ext = GDEF_OS_EXE_EXT;
+       build_set_variable( "ExecutableType", exe_ext[0] == '\0' ? exe_ext : exe_ext + 1 );
+
+       build_set_variable( "ExecutableExt", GDEF_OS_EXE_EXT );
        build_set_variable( "RadiantPath", AppPath_get() );
-       build_set_variable( "ExecutableType", RADIANT_EXECUTABLE );
        build_set_variable( "EnginePath", EnginePath_get() );
        build_set_variable( "UserEnginePath", g_qeglobals.m_userEnginePath.c_str() );
+
        build_set_variable( "MonitorAddress", ( g_WatchBSP_Enabled ) ? "127.0.0.1:39000" : "" );
+
        build_set_variable( "GameName", gamename_get() );
 
-       StringBuffer ExtraQ3map2Args;
+       std::string ExtraQ3map2Args;
        // extra pakpaths
        for ( int i = 0; i < g_pakPathCount; i++ ) {
                if ( g_strcmp0( g_strPakPath[i].c_str(), "") ) {
-                       ExtraQ3map2Args.push_string( " -fs_pakpath \"" );
-                       ExtraQ3map2Args.push_string( g_strPakPath[i].c_str() );
-                       ExtraQ3map2Args.push_string( "\"" );
+                       ExtraQ3map2Args += " -fs_pakpath \"";
+                       ExtraQ3map2Args += g_strPakPath[i].c_str();
+                       ExtraQ3map2Args += "\"";
                }
        }
 
        // extra switches
        if ( g_disableEnginePath ) {
-               ExtraQ3map2Args.push_string( " -fs_nobasepath " );
+               ExtraQ3map2Args += " -fs_nobasepath ";
        }
 
        if ( g_disableHomePath ) {
-               ExtraQ3map2Args.push_string( " -fs_nohomepath " );
+               ExtraQ3map2Args += " -fs_nohomepath ";
        }
 
        build_set_variable( "ExtraQ3map2Args", ExtraQ3map2Args.c_str() );
 
        const char* mapname = Map_Name( g_map );
-       StringOutputStream name( 256 );
-       name << StringRange( mapname, path_get_filename_base_end( mapname ) ) << ".bsp";
+       std::string name;
+       name.append( mapname, path_get_filename_base_end( mapname ) - mapname );
+       name += ".bsp";
 
        build_set_variable( "MapFile", mapname );
        build_set_variable( "BspFile", name.c_str() );
diff --git a/radiant/radiant.ico b/radiant/radiant.ico
deleted file mode 100644 (file)
index 45e8258..0000000
Binary files a/radiant/radiant.ico and /dev/null differ
index 51087c04cca3deddff4099013dca23ce771ce3f4..8380a5222e9f5f6bb83fb34853216792529c031f 100644 (file)
@@ -28,7 +28,7 @@
 
 // Icon with lowest ID value placed first to ensure application icon
 // remains consistent on all systems.
-IDI_RADIANT             ICON    DISCARDABLE     "radiant.ico"
+IDI_RADIANT             ICON    DISCARDABLE     "..\\icons\\netradiant.ico"
 
 #ifdef APSTUDIO_INVOKED
 /////////////////////////////////////////////////////////////////////////////
diff --git a/radiant/radiant_old.ico b/radiant/radiant_old.ico
deleted file mode 100644 (file)
index b45ef36..0000000
Binary files a/radiant/radiant_old.ico and /dev/null differ
index 9ceeba1bc78fe0e0578d2d3ec97dca2459afa951..88f3fb3afbe0b4ac3f7375a76eeb068087ae9395 100644 (file)
@@ -124,8 +124,14 @@ bool file_saveBackup( const char* path ){
                StringOutputStream backup( 256 );
                backup << StringRange( path, path_get_extension( path ) ) << "bak";
 
+#if GDEF_OS_WINDOWS
+               // NT symlinks are not supported yet.
                return ( !file_exists( backup.c_str() ) || file_remove( backup.c_str() ) ) // remove backup
                           && file_move( path, backup.c_str() ); // rename current to backup
+#else
+               // POSIX symlinks are supported.
+               return file_move( path, backup.c_str() ); // rename current to backup
+#endif
        }
 
        globalErrorStream() << "map path is not writeable: " << makeQuoted( path ) << "\n";
@@ -137,7 +143,27 @@ bool MapResource_save( const MapFormat& format, scene::Node& root, const char* p
        fullpath << path << name;
 
        if ( path_is_absolute( fullpath.c_str() ) ) {
+#if GDEF_OS_WINDOWS
+               // NT symlinks are not supported yet.
                if ( !file_exists( fullpath.c_str() ) || file_saveBackup( fullpath.c_str() ) ) {
+#else
+               // POSIX symlinks are supported.
+               /* We don't want a backup + rename operation if the .map file is
+                * a symlink. Otherwise we'll break the user's careful symlink setup.
+                * Just overwrite the original file. Assume the user has versioning. */
+               bool make_backup;
+               struct stat st;
+               if ( lstat(fullpath.c_str(), &st) == 0 ) {
+                       make_backup = true;             // file exists
+                       if ( (st.st_mode & S_IFMT) == S_IFLNK ) {
+                               make_backup = false;    // .. but it is a symlink
+                       }
+               } else {
+                       make_backup = false;            // nothing to move
+               }
+
+               if ( !make_backup || file_saveBackup( fullpath.c_str() ) ) {
+#endif
                        return MapResource_saveFile( format, root, Map_Traverse, fullpath.c_str() );
                }
 
index 6fc44a3656138ed4cabcd22f220a1def04700fa1..f5a4469021147a5b483a5e752af58084cd37307a 100644 (file)
@@ -224,10 +224,10 @@ void create(){
        // create shader
        {
                StringOutputStream filename( 256 );
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glsl";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_vp.glsl";
                createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB );
                filename.clear();
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glsl";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_fp.glsl";
                createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB );
        }
 
@@ -333,10 +333,10 @@ void create(){
        // create shader
        {
                StringOutputStream filename( 256 );
-               filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glsl";
+               filename << GlobalRadiant().getDataPath() << "gl/zfill_vp.glsl";
                createShader( m_program, filename.c_str(), GL_VERTEX_SHADER_ARB );
                filename.clear();
-               filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glsl";
+               filename << GlobalRadiant().getDataPath() << "gl/zfill_fp.glsl";
                createShader( m_program, filename.c_str(), GL_FRAGMENT_SHADER_ARB );
        }
 
@@ -407,13 +407,13 @@ void create(){
                glGenProgramsARB( 1, &m_vertex_program );
                glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program );
                StringOutputStream filename( 256 );
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.glp";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_vp.glp";
                createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB );
 
                glGenProgramsARB( 1, &m_fragment_program );
                glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program );
                filename.clear();
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.glp";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_fp.glp";
                createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB );
        }
 
@@ -509,13 +509,13 @@ void create(){
                glGenProgramsARB( 1, &m_vertex_program );
                glBindProgramARB( GL_VERTEX_PROGRAM_ARB, m_vertex_program );
                StringOutputStream filename( 256 );
-               filename << GlobalRadiant().getAppPath() << "gl/zfill_vp.glp";
+               filename << GlobalRadiant().getDataPath() << "gl/zfill_vp.glp";
                createProgram( filename.c_str(), GL_VERTEX_PROGRAM_ARB );
 
                glGenProgramsARB( 1, &m_fragment_program );
                glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, m_fragment_program );
                filename.clear();
-               filename << GlobalRadiant().getAppPath() << "gl/zfill_fp.glp";
+               filename << GlobalRadiant().getDataPath() << "gl/zfill_fp.glp";
                createProgram( filename.c_str(), GL_FRAGMENT_PROGRAM_ARB );
        }
 
@@ -590,13 +590,13 @@ void createVertexProgram(){
                glGenProgramsNV( 1, &m_vertex_program );
                glBindProgramNV( GL_VERTEX_PROGRAM_NV, m_vertex_program );
                StringOutputStream filename( 256 );
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_vp.nv30";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_vp.nv30";
                createProgram( m_vertex_program, filename.c_str(), GL_VERTEX_PROGRAM_NV );
 
                glGenProgramsNV( 1, &m_fragment_program );
                glBindProgramNV( GL_FRAGMENT_PROGRAM_NV, m_fragment_program );
                filename.clear();
-               filename << GlobalRadiant().getAppPath() << "gl/lighting_DBS_omni_fp.nv30";
+               filename << GlobalRadiant().getDataPath() << "gl/lighting_DBS_omni_fp.nv30";
                createProgram( m_fragment_program, filename.c_str(), GL_FRAGMENT_PROGRAM_NV );
        }
 
@@ -2150,13 +2150,15 @@ void OpenGLShader::construct( const char* name ){
                break;
 
        case '$':
-       {
-               OpenGLStateMap::iterator i = g_openglStates->find( name );
-               if ( i != g_openglStates->end() ) {
-                       state = ( *i ).second;
-                       break;
+               {
+                       OpenGLStateMap::iterator i = g_openglStates->find( name );
+                       if ( i != g_openglStates->end() )
+                       {
+                               state = ( *i ).second;
+                               break;
+                       }
                }
-       }
+
                if ( string_equal( name + 1, "POINT" ) ) {
                        state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
                        state.m_sort = OpenGLState::eSortControlFirst;
index 48fb08b31caac7d6676c2e2c434ff812005bf363..759c34c08db1285d1b67cd4a16784543d88ac1bf 100644 (file)
@@ -19,7 +19,7 @@
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#if !defined( INCLUDEDE_SCENEGRAPH_H )
+#if !defined( INCLUDED_SCENEGRAPH_H )
 #define INCLUDED_SCENEGRAPH_H
 
 #endif
index 2a264e6dcd14ede2803c2ee7e3789f5dff3aa416..879770c5e341f169e656f41d30d2a15ee199b43d 100644 (file)
@@ -144,6 +144,12 @@ FunctionPointer findSymbol( const char* symbol ){
 
 #include <dlfcn.h>
 
+#if GDEF_OS_MACOS
+#ifndef RTLD_DEEPBIND
+#define RTLD_DEEPBIND 0
+#endif // RTLD_DEEPBIND
+#endif // GDEF_OS_MACOS
+
 class DynamicLibrary {
        void *m_library;
 public:
@@ -172,9 +178,9 @@ FunctionPointer findSymbol( const char* symbol ){
 }
 };
 
-#else
+#else // !GDEF_OS_POSIX
 #error "unsupported platform"
-#endif
+#endif // !GDEF_OS_POSIX
 
 class DynamicLibraryModule
 {
index 70d25f7599b885b2f26d6b4f29019eee5fda3b8d..51d497ad78e5def5cbfaeebdc50889faf021436c 100644 (file)
@@ -1355,21 +1355,20 @@ void TextureClipboard_textureSelected( const char* shader ){
 }
 
 class TextureBrowser;
-extern TextureBrowser g_TextureBrowser;
 void TextureBrowser_SetSelectedShader( TextureBrowser& textureBrowser, const char* shader );
 const char* TextureBrowser_GetSelectedShader( TextureBrowser& textureBrowser );
 
 void Scene_copyClosestTexture( SelectionTest& test ){
        CopiedString shader;
        if ( Scene_getClosestTexture( GlobalSceneGraph(), test, shader, g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags ) ) {
-               TextureBrowser_SetSelectedShader( g_TextureBrowser, shader.c_str() );
+               TextureBrowser_SetSelectedShader( GlobalTextureBrowser(), shader.c_str() );
        }
 }
 
 void Scene_applyClosestTexture( SelectionTest& test ){
        UndoableCommand command( "facePaintTexture" );
 
-       Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( g_TextureBrowser ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags );
+       Scene_setClosestTexture( GlobalSceneGraph(), test, TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ), g_faceTextureClipboard.m_projection, g_faceTextureClipboard.m_flags );
 
        SceneChangeNotify();
 }
@@ -1384,13 +1383,13 @@ void SelectedFaces_copyTexture(){
                face.GetTexdef( g_faceTextureClipboard.m_projection );
                g_faceTextureClipboard.m_flags = face.getShader().m_flags;
 
-               TextureBrowser_SetSelectedShader( g_TextureBrowser, face.getShader().getShader() );
+               TextureBrowser_SetSelectedShader( GlobalTextureBrowser(), face.getShader().getShader() );
        }
 }
 
 void FaceInstance_pasteTexture( FaceInstance& faceInstance ){
        faceInstance.getFace().SetTexdef( g_faceTextureClipboard.m_projection );
-       faceInstance.getFace().SetShader( TextureBrowser_GetSelectedShader( g_TextureBrowser ) );
+       faceInstance.getFace().SetShader( TextureBrowser_GetSelectedShader( GlobalTextureBrowser() ) );
        faceInstance.getFace().SetFlags( g_faceTextureClipboard.m_flags );
        SceneChangeNotify();
 }
index 02f706b90e0629d6df7808ea62f3f88067abcba7..afa8d4e05c1d180b5c3f9b2e48d0e365edc60c67 100644 (file)
@@ -815,13 +815,18 @@ class TexturesDependencies :
        public GlobalPreferenceSystemModuleRef
 {
 ImageModulesRef m_image_modules;
+ImageModulesRef m_fallback_image_modules;
 public:
 TexturesDependencies() :
-       m_image_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "texturetypes" ) ){
+       m_image_modules( GlobalRadiant().getRequiredGameDescriptionKeyValue( "texturetypes" ) ),
+       m_fallback_image_modules( "png" ){
 }
 ImageModules& getImageModules(){
        return m_image_modules.get();
 }
+ImageModules& getFallbackImageModules(){
+       return m_fallback_image_modules.get();
+}
 };
 
 class TexturesAPI
@@ -851,3 +856,6 @@ StaticRegisterModule staticRegisterTextures( StaticTexturesModule::instance() );
 ImageModules& Textures_getImageModules(){
        return StaticTexturesModule::instance().getDependencies().getImageModules();
 }
+ImageModules& Textures_getFallbackImageModules(){
+       return StaticTexturesModule::instance().getDependencies().getFallbackImageModules();
+}
index 416d31789184d02b77e4c610fdbd282296918f86..34a31b1efb008b84d9d77aba657a7b3fe955d8a9 100644 (file)
@@ -101,12 +101,7 @@ typedef std::set<CopiedString> TextureGroups;
 
 void TextureGroups_addWad( TextureGroups& groups, const char* archive ){
        if ( extension_equal( path_get_extension( archive ), "wad" ) ) {
-#if 1
                groups.insert( archive );
-#else
-               CopiedString archiveBaseName( path_get_filename_start( archive ), path_get_filename_base_end( archive ) );
-               groups.insert( archiveBaseName );
-#endif
        }
 }
 
@@ -276,6 +271,14 @@ int m_nTotalHeight;
 CopiedString shader;
 
 ui::Window m_parent{ui::null};
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+ui::VBox m_vframe{ui::null};
+ui::VBox m_vfiller{ui::null};
+ui::HBox m_hframe{ui::null};
+ui::HBox m_hfiller{ui::null};
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+ui::VBox m_frame{ui::null};
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
 ui::GLArea m_gl_widget{ui::null};
 ui::Widget m_texture_scroll{ui::null};
 ui::TreeView m_treeViewTree{ui::New};
@@ -404,7 +407,7 @@ void ( *TextureBrowser_textureSelected )( const char* shader );
 void TextureBrowser_updateScroll( TextureBrowser& textureBrowser );
 
 
-const char* TextureBrowser_getComonShadersName(){
+const char* TextureBrowser_getCommonShadersName(){
        const char* value = g_pGameDescription->getKeyValue( "common_shaders_name" );
        if ( !string_empty( value ) ) {
                return value;
@@ -412,7 +415,7 @@ const char* TextureBrowser_getComonShadersName(){
        return "Common";
 }
 
-const char* TextureBrowser_getComonShadersDir(){
+const char* TextureBrowser_getCommonShadersDir(){
        const char* value = g_pGameDescription->getKeyValue( "common_shaders_dir" );
        if ( !string_empty( value ) ) {
                return value;
@@ -588,7 +591,15 @@ bool Texture_IsShown( IShader* shader, bool show_shaders, bool show_textures, bo
                }
        }
        else {
-               if ( !shader_equal_prefix( shader_get_textureName( shader->getName() ), g_TextureBrowser_currentDirectory.c_str() ) ) {
+               if ( TextureBrowser_showWads() )
+               {
+                       if ( g_TextureBrowser_currentDirectory != ""
+                               && !string_equal( shader->getWadName(), g_TextureBrowser_currentDirectory.c_str() ) )
+                       {
+                               return false;
+                       }
+               }
+               else if ( !shader_equal_prefix( shader_get_textureName( shader->getName() ), g_TextureBrowser_currentDirectory.c_str() ) ) {
                        return false;
                }
        }
@@ -786,6 +797,7 @@ public:
 void visit( const char* name ){
        IShader* shader = QERApp_Shader_ForName( CopiedString( StringRange( name, path_get_filename_base_end( name ) ) ).c_str() );
        shader->DecRef();
+       shader->setWadName( g_TextureBrowser_currentDirectory.c_str() );
 }
 };
 
@@ -828,6 +840,14 @@ void operator()( const char* name ) const {
 };
 
 void TextureDirectory_loadTexture( const char* directory, const char* texture ){
+       // Doom3-like dds/ prefix (used by DarkPlaces).
+       // When we list dds/textures/ folder,
+       // store the texture names without dds/ prefix.
+       if ( !strncmp( "dds/", directory, 4 ) )
+       {
+               directory = &directory[ 4 ];
+       }
+
        StringOutputStream name( 256 );
        name << directory << StringRange( texture, path_get_filename_base_end( texture ) );
 
@@ -862,10 +882,22 @@ void visit( const char* minor, const _QERPlugImageTable& table ) const {
 
 void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* directory ){
        if ( TextureBrowser_showWads() ) {
+               g_TextureBrowser_currentDirectory = directory;
+               TextureBrowser_heightChanged( textureBrowser );
+
                Archive* archive = GlobalFileSystem().getArchive( directory );
-               ASSERT_NOTNULL( archive );
+               if ( archive != nullptr )
+               {
                LoadShaderVisitor visitor;
                archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "textures/" );
+
+                       // Doom3-like dds/ prefix (used by DarkPlaces).
+                       archive->forEachFile( Archive::VisitorFunc( visitor, Archive::eFiles, 0 ), "dds/textures/" );
+               }
+               else if ( extension_equal_i( path_get_extension( directory ), "wad" ) )
+               {
+                       globalErrorStream() << "Failed to load " << directory << "\n";
+               }
        }
        else
        {
@@ -882,7 +914,19 @@ void TextureBrowser_ShowDirectory( TextureBrowser& textureBrowser, const char* d
                        StringOutputStream dirstring( 64 );
                        dirstring << "textures/" << directory;
 
-                       Radiant_getImageModules().foreachModule( LoadTexturesByTypeVisitor( dirstring.c_str() ) );
+                       {
+                               LoadTexturesByTypeVisitor visitor( dirstring.c_str() );
+                               Radiant_getImageModules().foreachModule( visitor );
+                       }
+
+                       // Doom3-like dds/ prefix (used by DarkPlaces).
+                       dirstring.clear();
+                       dirstring << "dds/textures/" << directory;
+
+                       {
+                               LoadTexturesByTypeVisitor visitor( dirstring.c_str() );
+                               Radiant_getImageModules().foreachModule( visitor );
+                       }
                }
        }
 
@@ -909,6 +953,15 @@ void TextureBrowser_ShowTagSearchResult( TextureBrowser& textureBrowser, const c
                        LoadTexturesByTypeVisitor visitor( dirstring.c_str() );
                        Radiant_getImageModules().foreachModule( visitor );
                }
+
+               // Doom3-like dds/ prefix (used by DarkPlaces).
+               dirstring.clear();
+               dirstring << "dds/textures/" << directory;
+
+               {
+                       LoadTexturesByTypeVisitor visitor( dirstring.c_str() );
+                       Radiant_getImageModules().foreachModule( visitor );
+               }
        }
 
        // we'll display the newly loaded textures + all the ones already in use
@@ -983,7 +1036,7 @@ void TextureBrowser_SetHideUnused( TextureBrowser& textureBrowser, bool hideUnus
 
 void TextureBrowser_ShowStartupShaders( TextureBrowser& textureBrowser ){
        if ( textureBrowser.m_startupShaders == STARTUPSHADERS_COMMON ) {
-               TextureBrowser_ShowDirectory( textureBrowser, TextureBrowser_getComonShadersDir() );
+               TextureBrowser_ShowDirectory( textureBrowser, TextureBrowser_getCommonShadersDir() );
        }
 }
 
@@ -1123,7 +1176,10 @@ void TextureBrowser_trackingDelta( int x, int y, unsigned int state, void* data
 
 void TextureBrowser_Tracking_MouseUp( TextureBrowser& textureBrowser ){
        textureBrowser.m_move_started = false;
-       textureBrowser.m_freezePointer.unfreeze_pointer( textureBrowser.m_parent );
+       /* NetRadiantCustom did this instead:
+       textureBrowser.m_freezePointer.unfreeze_pointer( textureBrowser.m_gl_widget ); */
+
+       textureBrowser.m_freezePointer.unfreeze_pointer( textureBrowser.m_gl_widget );
 }
 
 void TextureBrowser_Tracking_MouseDown( TextureBrowser& textureBrowser ){
@@ -1131,7 +1187,9 @@ void TextureBrowser_Tracking_MouseDown( TextureBrowser& textureBrowser ){
                TextureBrowser_Tracking_MouseUp( textureBrowser );
        }
        textureBrowser.m_move_started = true;
-       textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_parent, textureBrowser.m_gl_widget, TextureBrowser_trackingDelta, &textureBrowser );
+       /* NetRadiantCustom did this instead:
+       textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_parent, textureBrowser.m_gl_widget, TextureBrowser_trackingDelta, &textureBrowser ); */
+       textureBrowser.m_freezePointer.freeze_pointer( textureBrowser.m_gl_widget, TextureBrowser_trackingDelta, &textureBrowser );
 }
 
 void TextureBrowser_Selection_MouseDown( TextureBrowser& textureBrowser, guint32 flags, int pointx, int pointy ){
@@ -1161,6 +1219,7 @@ void Texture_Draw( TextureBrowser& textureBrowser ){
                                  textureBrowser.color_textureback[1],
                                  textureBrowser.color_textureback[2],
                                  0 );
+
        glViewport( 0, 0, textureBrowser.width, textureBrowser.height );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity();
@@ -1472,7 +1531,7 @@ void BuildStoreAvailableTags(   ui::ListStore storeAvailable,
 gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){
        if ( event->type == GDK_BUTTON_PRESS ) {
                if ( event->button == 3 ) {
-                       if ( GlobalTextureBrowser().m_tags ) {
+                       if ( textureBrowser->m_tags ) {
                                textureBrowser->m_rmbSelected = true;
                                TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ) );
 
@@ -1493,7 +1552,7 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
                else if ( event->button == 1 ) {
                        TextureBrowser_Selection_MouseDown( *textureBrowser, event->state, static_cast<int>( event->x ), static_cast<int>( event->y ) );
 
-                       if ( GlobalTextureBrowser().m_tags ) {
+                       if ( textureBrowser->m_tags ) {
                                textureBrowser->m_rmbSelected = false;
                                textureBrowser->m_tag_frame.hide();
                        }
@@ -1521,8 +1580,8 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
                #endif
        }
        else if ( event->type == GDK_2BUTTON_PRESS && event->button == 3 ) {
-               ScopeDisableScreenUpdates disableScreenUpdates( TextureBrowser_getComonShadersDir(), "Loading Textures" );
-               TextureBrowser_ShowDirectory( *textureBrowser, TextureBrowser_getComonShadersDir() );
+               ScopeDisableScreenUpdates disableScreenUpdates( TextureBrowser_getCommonShadersDir(), "Loading Textures" );
+               TextureBrowser_ShowDirectory( *textureBrowser, TextureBrowser_getCommonShadersDir() );
                TextureBrowser_queueDraw( *textureBrowser );
        }
        return FALSE;
@@ -1531,7 +1590,7 @@ gboolean TextureBrowser_button_press( ui::Widget widget, GdkEventButton* event,
 gboolean TextureBrowser_button_release( ui::Widget widget, GdkEventButton* event, TextureBrowser* textureBrowser ){
        if ( event->type == GDK_BUTTON_RELEASE ) {
                if ( event->button == 3 ) {
-                       if ( !GlobalTextureBrowser().m_tags ) {
+                       if ( !textureBrowser->m_tags ) {
                                TextureBrowser_Tracking_MouseUp( *textureBrowser );
                        }
                }
@@ -1590,7 +1649,7 @@ gboolean TextureBrowser_size_allocate( ui::Widget widget, GtkAllocation* allocat
        return FALSE;
 }
 
-gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, TextureBrowser* textureBrowser ){
+void TextureBrowser_redraw( TextureBrowser* textureBrowser ){
        if ( glwidget_make_current( textureBrowser->m_gl_widget ) != FALSE ) {
                GlobalOpenGL_debugAssertNoErrors();
                TextureBrowser_evaluateHeight( *textureBrowser );
@@ -1598,28 +1657,42 @@ gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, Textur
                GlobalOpenGL_debugAssertNoErrors();
                glwidget_swap_buffers( textureBrowser->m_gl_widget );
        }
-       return FALSE;
 }
 
-
-TextureBrowser g_TextureBrowser;
+gboolean TextureBrowser_expose( ui::Widget widget, GdkEventExpose* event, TextureBrowser* textureBrowser ){
+       TextureBrowser_redraw( textureBrowser );
+       return FALSE;
+}
 
 TextureBrowser& GlobalTextureBrowser(){
-       return g_TextureBrowser;
+       static TextureBrowser textureBrowser;
+       return textureBrowser;
 }
 
 bool TextureBrowser_hideUnused(){
-       return g_TextureBrowser.m_hideUnused;
+       return GlobalTextureBrowser().m_hideUnused;
 }
 
 void TextureBrowser_ToggleHideUnused(){
-       if ( g_TextureBrowser.m_hideUnused ) {
-               TextureBrowser_SetHideUnused( g_TextureBrowser, false );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       if ( textureBrowser.m_hideUnused ) {
+               TextureBrowser_SetHideUnused( textureBrowser, false );
        }
        else
        {
-               TextureBrowser_SetHideUnused( g_TextureBrowser, true );
+               TextureBrowser_SetHideUnused( textureBrowser, true );
+       }
+}
+
+const char* TextureGroups_transformDirName( const char* dirName, StringOutputStream *archiveName )
+{
+       if ( TextureBrowser_showWads() ) {
+               archiveName->clear();
+               *archiveName << StringRange( path_get_filename_start( dirName ), path_get_filename_base_end( dirName ) ) \
+                       << "." << path_get_extension( dirName );
+               return archiveName->c_str();
        }
+       return dirName;
 }
 
 void TextureGroups_constructTreeModel( TextureGroups groups, ui::TreeStore store ){
@@ -1629,23 +1702,27 @@ void TextureGroups_constructTreeModel( TextureGroups groups, ui::TreeStore store
        TextureGroups::const_iterator i = groups.begin();
        while ( i != groups.end() )
        {
-               const char* dirName = ( *i ).c_str();
+               StringOutputStream archiveName;
+               StringOutputStream nextArchiveName;
+               const char* dirName = TextureGroups_transformDirName( ( *i ).c_str(), &archiveName );
+
                const char* firstUnderscore = strchr( dirName, '_' );
                StringRange dirRoot( dirName, ( firstUnderscore == 0 ) ? dirName : firstUnderscore + 1 );
 
                TextureGroups::const_iterator next = i;
                ++next;
+
                if ( firstUnderscore != 0
                         && next != groups.end()
-                        && string_equal_start( ( *next ).c_str(), dirRoot ) ) {
+                        && string_equal_start( TextureGroups_transformDirName( ( *next ).c_str(), &nextArchiveName ), dirRoot ) ) {
                        gtk_tree_store_append( store, &iter, NULL );
                        gtk_tree_store_set( store, &iter, 0, CopiedString( StringRange( dirName, firstUnderscore ) ).c_str(), -1 );
 
                        // keep going...
-                       while ( i != groups.end() && string_equal_start( ( *i ).c_str(), dirRoot ) )
+                       while ( i != groups.end() && string_equal_start( TextureGroups_transformDirName( ( *i ).c_str(), &nextArchiveName ), dirRoot ) )
                        {
                                gtk_tree_store_append( store, &child, &iter );
-                               gtk_tree_store_set( store, &child, 0, ( *i ).c_str(), -1 );
+                               gtk_tree_store_set( store, &child, 0, TextureGroups_transformDirName( ( *i ).c_str(), &nextArchiveName ), -1 );
                                ++i;
                        }
                }
@@ -1683,17 +1760,18 @@ void TextureBrowser_constructTreeStore(){
        TextureGroups_constructTreeModel( groups, store );
        std::set<CopiedString>::iterator iter;
 
-       gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTree, store);
+       gtk_tree_view_set_model(GlobalTextureBrowser().m_treeViewTree, store);
 
        g_object_unref( G_OBJECT( store ) );
 }
 
 void TextureBrowser_constructTreeStoreTags(){
        //TextureGroups groups;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
        auto store = ui::TreeStore::from(gtk_tree_store_new( 1, G_TYPE_STRING ));
-    auto model = g_TextureBrowser.m_all_tags_list;
+       auto model = GlobalTextureBrowser().m_all_tags_list;
 
-       gtk_tree_view_set_model(g_TextureBrowser.m_treeViewTags, model );
+       gtk_tree_view_set_model(GlobalTextureBrowser().m_treeViewTags, model );
 
        g_object_unref( G_OBJECT( store ) );
 }
@@ -1711,7 +1789,7 @@ void TreeView_onRowActivated( ui::TreeView treeview, ui::TreePath path, ui::Tree
                strcpy( dirName, buffer );
                g_free( buffer );
 
-               g_TextureBrowser.m_searchedTags = false;
+               GlobalTextureBrowser().m_searchedTags = false;
 
                if ( !TextureBrowser_showWads() ) {
                        strcat( dirName, "/" );
@@ -1726,13 +1804,14 @@ void TreeView_onRowActivated( ui::TreeView treeview, ui::TreePath path, ui::Tree
 }
 
 void TextureBrowser_createTreeViewTree(){
-       gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTree, FALSE );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       gtk_tree_view_set_enable_search(textureBrowser.m_treeViewTree, FALSE );
 
-       gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTree, FALSE );
-       g_TextureBrowser.m_treeViewTree.connect( "row-activated", (GCallback) TreeView_onRowActivated, NULL );
+       gtk_tree_view_set_headers_visible(textureBrowser.m_treeViewTree, FALSE );
+       textureBrowser.m_treeViewTree.connect( "row-activated", (GCallback) TreeView_onRowActivated, NULL );
 
        auto renderer = ui::CellRendererText(ui::New);
-       gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL );
+       gtk_tree_view_insert_column_with_attributes(textureBrowser.m_treeViewTree, -1, "", renderer, "text", 0, NULL );
 
        TextureBrowser_constructTreeStore();
 }
@@ -1783,20 +1862,22 @@ gboolean TreeViewTags_onButtonPressed( ui::TreeView treeview, GdkEventButton *ev
 }
 
 void TextureBrowser_createTreeViewTags(){
-       g_TextureBrowser.m_treeViewTags = ui::TreeView(ui::New);
-       gtk_tree_view_set_enable_search(g_TextureBrowser.m_treeViewTags, FALSE );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_treeViewTags = ui::TreeView(ui::New);
+       gtk_tree_view_set_enable_search(textureBrowser.m_treeViewTags, FALSE );
 
-       g_TextureBrowser.m_treeViewTags.connect( "button-press-event", (GCallback)TreeViewTags_onButtonPressed, NULL );
+       textureBrowser.m_treeViewTags.connect( "button-press-event", (GCallback)TreeViewTags_onButtonPressed, NULL );
 
-       gtk_tree_view_set_headers_visible(g_TextureBrowser.m_treeViewTags, FALSE );
+       gtk_tree_view_set_headers_visible(textureBrowser.m_treeViewTags, FALSE );
 
        auto renderer = ui::CellRendererText(ui::New);
-       gtk_tree_view_insert_column_with_attributes(g_TextureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL );
+       gtk_tree_view_insert_column_with_attributes(textureBrowser.m_treeViewTags, -1, "", renderer, "text", 0, NULL );
 
        TextureBrowser_constructTreeStoreTags();
 }
 
 ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
        ui::MenuItem textures_menu_item = ui::MenuItem(new_sub_menu_item_with_mnemonic( "_View" ));
 
        if ( g_Layout_enableDetachableMenus.m_value ) {
@@ -1815,8 +1896,8 @@ ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){
 
 
        // we always want to show shaders but don't want a "Show Shaders" menu for doom3 and .wad file games
-       if ( g_pGameDescription->mGameType == "doom3" || !string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) {
-               g_TextureBrowser.m_showShaders = true;
+       if ( g_pGameDescription->mGameType == "doom3" || TextureBrowser_showWads() ) {
+               textureBrowser.m_showShaders = true;
        }
        else
        {
@@ -1825,7 +1906,7 @@ ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){
                menu_separator( menu );
        }
 
-       if ( g_TextureBrowser.m_tags ) {
+       if ( textureBrowser.m_tags ) {
                create_menu_item_with_mnemonic( menu, "Show Untagged", "ShowUntagged" );
        }
        if ( g_pGameDescription->mGameType != "doom3" && string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) {
@@ -1838,8 +1919,8 @@ ui::MenuItem TextureBrowser_constructViewMenu( ui::Menu menu ){
 
        if ( string_empty( g_pGameDescription->getKeyValue( "show_wads" ) ) ) {
                menu_separator( menu );
-               g_TextureBrowser.m_shader_info_item = ui::Widget(create_menu_item_with_mnemonic( menu, "Shader Info", "ShaderInfo"  ));
-               gtk_widget_set_sensitive( g_TextureBrowser.m_shader_info_item, FALSE );
+               textureBrowser.m_shader_info_item = ui::Widget(create_menu_item_with_mnemonic( menu, "Shader Info", "ShaderInfo"  ));
+               gtk_widget_set_sensitive( textureBrowser.m_shader_info_item, FALSE );
        }
 
 
@@ -1880,7 +1961,7 @@ ui::MenuItem TextureBrowser_constructTagsMenu( ui::Menu menu ){
        return textures_menu_item;
 }
 
-gboolean TextureBrowser_tagMoveHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter iter, GSList** selected ){
+gboolean TextureBrowser_tagMoveHelper( ui::TreeModel model, ui::TreePath path, GtkTreeIter* iter, GSList** selected ){
        g_assert( selected != NULL );
 
     auto rowref = gtk_tree_row_reference_new( model, path );
@@ -1893,8 +1974,9 @@ void TextureBrowser_assignTags(){
        GSList* selected = NULL;
        GSList* node;
        gchar* tag_assigned;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
-    auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree );
+       auto selection = gtk_tree_view_get_selection(textureBrowser.m_available_tree );
 
        gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected );
 
@@ -1906,27 +1988,27 @@ void TextureBrowser_assignTags(){
                        if ( path ) {
                                GtkTreeIter iter;
 
-                               if ( gtk_tree_model_get_iter(g_TextureBrowser.m_available_store, &iter, path ) ) {
-                                       gtk_tree_model_get(g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1 );
-                                       if ( !TagBuilder.CheckShaderTag( g_TextureBrowser.shader.c_str() ) ) {
+                               if ( gtk_tree_model_get_iter(textureBrowser.m_available_store, &iter, path ) ) {
+                                       gtk_tree_model_get(textureBrowser.m_available_store, &iter, TAG_COLUMN, &tag_assigned, -1 );
+                                       if ( !TagBuilder.CheckShaderTag( textureBrowser.shader.c_str() ) ) {
                                                // create a custom shader/texture entry
-                                               IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() );
+                                               IShader* ishader = QERApp_Shader_ForName( textureBrowser.shader.c_str() );
                                                CopiedString filename = ishader->getShaderFileName();
 
                                                if ( filename.empty() ) {
                                                        // it's a texture
-                                                       TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, TEXTURE );
+                                                       TagBuilder.AddShaderNode( textureBrowser.shader.c_str(), CUSTOM, TEXTURE );
                                                }
                                                else {
                                                        // it's a shader
-                                                       TagBuilder.AddShaderNode( g_TextureBrowser.shader.c_str(), CUSTOM, SHADER );
+                                                       TagBuilder.AddShaderNode( textureBrowser.shader.c_str(), CUSTOM, SHADER );
                                                }
                                                ishader->DecRef();
                                        }
-                                       TagBuilder.AddShaderTag( g_TextureBrowser.shader.c_str(), (char*)tag_assigned, TAG );
+                                       TagBuilder.AddShaderTag( textureBrowser.shader.c_str(), (char*)tag_assigned, TAG );
 
-                                       gtk_list_store_remove( g_TextureBrowser.m_available_store, &iter );
-                                       g_TextureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned);
+                                       gtk_list_store_remove( textureBrowser.m_available_store, &iter );
+                                       textureBrowser.m_assigned_store.append(TAG_COLUMN, tag_assigned);
                                }
                        }
                }
@@ -1943,8 +2025,9 @@ void TextureBrowser_removeTags(){
        GSList* selected = NULL;
        GSList* node;
        gchar* tag;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
-    auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree );
+       auto selection = gtk_tree_view_get_selection(textureBrowser.m_assigned_tree );
 
        gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected );
 
@@ -1956,10 +2039,10 @@ void TextureBrowser_removeTags(){
                        if ( path ) {
                                GtkTreeIter iter;
 
-                               if ( gtk_tree_model_get_iter(g_TextureBrowser.m_assigned_store, &iter, path ) ) {
-                                       gtk_tree_model_get(g_TextureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1 );
-                                       TagBuilder.DeleteShaderTag( g_TextureBrowser.shader.c_str(), tag );
-                                       gtk_list_store_remove( g_TextureBrowser.m_assigned_store, &iter );
+                               if ( gtk_tree_model_get_iter(textureBrowser.m_assigned_store, &iter, path ) ) {
+                                       gtk_tree_model_get(textureBrowser.m_assigned_store, &iter, TAG_COLUMN, &tag, -1 );
+                                       TagBuilder.DeleteShaderTag( textureBrowser.shader.c_str(), tag );
+                                       gtk_list_store_remove( textureBrowser.m_assigned_store, &iter );
                                }
                        }
                }
@@ -1967,7 +2050,7 @@ void TextureBrowser_removeTags(){
                g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL );
 
                // Update the "available tags list"
-               BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser );
+               BuildStoreAvailableTags( textureBrowser.m_available_store, textureBrowser.m_assigned_store, textureBrowser.m_all_tags, &textureBrowser );
 
                // Save changes
                TagBuilder.SaveXmlDoc();
@@ -1976,13 +2059,14 @@ void TextureBrowser_removeTags(){
 }
 
 void TextureBrowser_buildTagList(){
-       g_TextureBrowser.m_all_tags_list.clear();
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_all_tags_list.clear();
 
        std::set<CopiedString>::iterator iter;
 
-       for ( iter = g_TextureBrowser.m_all_tags.begin(); iter != g_TextureBrowser.m_all_tags.end(); ++iter )
+       for ( iter = textureBrowser.m_all_tags.begin(); iter != textureBrowser.m_all_tags.end(); ++iter )
        {
-               g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str());
+               textureBrowser.m_all_tags_list.append(TAG_COLUMN, (*iter).c_str());
        }
 }
 
@@ -1992,8 +2076,9 @@ void TextureBrowser_searchTags(){
        gchar* tag;
        char buffer[256];
        char tags_searched[256];
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
-    auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags );
+       auto selection = gtk_tree_view_get_selection(textureBrowser.m_treeViewTags );
 
        gtk_tree_selection_selected_foreach( selection, (GtkTreeSelectionForeachFunc)TextureBrowser_tagMoveHelper, &selected );
 
@@ -2008,8 +2093,8 @@ void TextureBrowser_searchTags(){
                        if ( path ) {
                                GtkTreeIter iter;
 
-                               if ( gtk_tree_model_get_iter(g_TextureBrowser.m_all_tags_list, &iter, path ) ) {
-                                       gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1 );
+                               if ( gtk_tree_model_get_iter(textureBrowser.m_all_tags_list, &iter, path ) ) {
+                                       gtk_tree_model_get(textureBrowser.m_all_tags_list, &iter, TAG_COLUMN, &tag, -1 );
 
                                        strcat( buffer, tag );
                                        strcat( tags_searched, tag );
@@ -2025,18 +2110,18 @@ void TextureBrowser_searchTags(){
 
                g_slist_foreach( selected, (GFunc)gtk_tree_row_reference_free, NULL );
 
-               g_TextureBrowser.m_found_shaders.clear(); // delete old list
-               TagBuilder.TagSearch( buffer, g_TextureBrowser.m_found_shaders );
+               textureBrowser.m_found_shaders.clear(); // delete old list
+               TagBuilder.TagSearch( buffer, textureBrowser.m_found_shaders );
 
-               if ( !g_TextureBrowser.m_found_shaders.empty() ) { // found something
-                       size_t shaders_found = g_TextureBrowser.m_found_shaders.size();
+               if ( !textureBrowser.m_found_shaders.empty() ) { // found something
+                       size_t shaders_found = textureBrowser.m_found_shaders.size();
 
                        globalOutputStream() << "Found " << (unsigned int)shaders_found << " textures and shaders with " << tags_searched << "\n";
                        ScopeDisableScreenUpdates disableScreenUpdates( "Searching...", "Loading Textures" );
 
                        std::set<CopiedString>::iterator iter;
 
-                       for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ )
+                       for ( iter = textureBrowser.m_found_shaders.begin(); iter != textureBrowser.m_found_shaders.end(); iter++ )
                        {
                                std::string path = ( *iter ).c_str();
                                size_t pos = path.find_last_of( "/", path.size() );
@@ -2045,62 +2130,66 @@ void TextureBrowser_searchTags(){
                                TextureDirectory_loadTexture( path.c_str(), name.c_str() );
                        }
                }
-               g_TextureBrowser.m_searchedTags = true;
+               textureBrowser.m_searchedTags = true;
                g_TextureBrowser_currentDirectory = tags_searched;
 
-               g_TextureBrowser.m_nTotalHeight = 0;
-               TextureBrowser_setOriginY( g_TextureBrowser, 0 );
-               TextureBrowser_heightChanged( g_TextureBrowser );
+               textureBrowser.m_nTotalHeight = 0;
+               TextureBrowser_setOriginY( textureBrowser, 0 );
+               TextureBrowser_heightChanged( textureBrowser );
                TextureBrowser_updateTitle();
        }
        g_slist_free( selected );
 }
 
 void TextureBrowser_toggleSearchButton(){
-       gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ) );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       gint page = gtk_notebook_get_current_page( GTK_NOTEBOOK( textureBrowser.m_tag_notebook ) );
 
        if ( page == 0 ) { // tag page
-               gtk_widget_show_all( g_TextureBrowser.m_search_button );
+               gtk_widget_show_all( textureBrowser.m_search_button );
        }
        else {
-               g_TextureBrowser.m_search_button.hide();
+               textureBrowser.m_search_button.hide();
        }
 }
 
 void TextureBrowser_constructTagNotebook(){
-       g_TextureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new());
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_tag_notebook = ui::Widget::from(gtk_notebook_new());
        ui::Widget labelTags = ui::Label( "Tags" );
        ui::Widget labelTextures = ui::Label( "Textures" );
 
-       gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tree, labelTextures );
-       gtk_notebook_append_page( GTK_NOTEBOOK( g_TextureBrowser.m_tag_notebook ), g_TextureBrowser.m_scr_win_tags, labelTags );
+       gtk_notebook_append_page( GTK_NOTEBOOK( textureBrowser.m_tag_notebook ), textureBrowser.m_scr_win_tree, labelTextures );
+       gtk_notebook_append_page( GTK_NOTEBOOK( textureBrowser.m_tag_notebook ), textureBrowser.m_scr_win_tags, labelTags );
 
-       g_TextureBrowser.m_tag_notebook.connect( "switch-page", G_CALLBACK( TextureBrowser_toggleSearchButton ), NULL );
+       textureBrowser.m_tag_notebook.connect( "switch-page", G_CALLBACK( TextureBrowser_toggleSearchButton ), NULL );
 
-       gtk_widget_show_all( g_TextureBrowser.m_tag_notebook );
+       gtk_widget_show_all( textureBrowser.m_tag_notebook );
 }
 
 void TextureBrowser_constructSearchButton(){
        auto image = ui::Widget::from(gtk_image_new_from_stock( GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR ));
-       g_TextureBrowser.m_search_button = ui::Button(ui::New);
-       g_TextureBrowser.m_search_button.connect( "clicked", G_CALLBACK( TextureBrowser_searchTags ), NULL );
-       gtk_widget_set_tooltip_text(g_TextureBrowser.m_search_button, "Search with selected tags");
-       g_TextureBrowser.m_search_button.add(image);
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_search_button = ui::Button(ui::New);
+       textureBrowser.m_search_button.connect( "clicked", G_CALLBACK( TextureBrowser_searchTags ), NULL );
+       gtk_widget_set_tooltip_text(textureBrowser.m_search_button, "Search with selected tags");
+       textureBrowser.m_search_button.add(image);
 }
 
 void TextureBrowser_checkTagFile(){
        const char SHADERTAG_FILE[] = "shadertags.xml";
        CopiedString default_filename, rc_filename;
        StringOutputStream stream( 256 );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
        stream << LocalRcPath_get();
        stream << SHADERTAG_FILE;
        rc_filename = stream.c_str();
 
        if ( file_exists( rc_filename.c_str() ) ) {
-               g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( rc_filename.c_str() );
+               textureBrowser.m_tags = TagBuilder.OpenXmlDoc( rc_filename.c_str() );
 
-               if ( g_TextureBrowser.m_tags ) {
+               if ( textureBrowser.m_tags ) {
                        globalOutputStream() << "Loading tag file " << rc_filename.c_str() << ".\n";
                }
        }
@@ -2113,9 +2202,9 @@ void TextureBrowser_checkTagFile(){
                default_filename = stream.c_str();
 
                if ( file_exists( default_filename.c_str() ) ) {
-                       g_TextureBrowser.m_tags = TagBuilder.OpenXmlDoc( default_filename.c_str(), rc_filename.c_str() );
+                       textureBrowser.m_tags = TagBuilder.OpenXmlDoc( default_filename.c_str(), rc_filename.c_str() );
 
-                       if ( g_TextureBrowser.m_tags ) {
+                       if ( textureBrowser.m_tags ) {
                                globalOutputStream() << "Loading default tag file " << default_filename.c_str() << ".\n";
                        }
                }
@@ -2131,24 +2220,56 @@ void TextureBrowser_SetNotex(){
        IShader* shadernotex = QERApp_Shader_ForName( DEFAULT_SHADERNOTEX_NAME );
 
        g_notex = notex->getTexture()->name;
+
        g_shadernotex = shadernotex->getTexture()->name;
 
        notex->DecRef();
        shadernotex->DecRef();
 }
 
+static bool isGLWidgetConstructed = false;
+static bool isWindowConstructed = false;
+
+void TextureBrowser_constructGLWidget(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_gl_widget = glwidget_new( FALSE );
+       g_object_ref( textureBrowser.m_gl_widget._handle );
+
+       gtk_widget_set_events( textureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
+       gtk_widget_set_can_focus( textureBrowser.m_gl_widget, true );
+
+       textureBrowser.m_sizeHandler = textureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &textureBrowser );
+       textureBrowser.m_exposeHandler = textureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &textureBrowser );
+
+       textureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &textureBrowser );
+       textureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &textureBrowser );
+       textureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &textureBrowser );
+       textureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &textureBrowser );
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+       textureBrowser.m_hframe.pack_start( textureBrowser.m_gl_widget, TRUE, TRUE, 0 );
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+       textureBrowser.m_frame.pack_start( textureBrowser.m_gl_widget, TRUE, TRUE, 0 );
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
+
+       textureBrowser.m_gl_widget.show();
+
+       isGLWidgetConstructed = true;
+}
+
 ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
        // The gl_widget and the tag assignment frame should be packed into a GtkVPaned with the slider
        // position stored in local.pref. gtk_paned_get_position() and gtk_paned_set_position() don't
        // seem to work in gtk 2.4 and the arrow buttons don't handle GTK_FILL, so here's another thing
        // for the "once-the-gtk-libs-are-updated-TODO-list" :x
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
        TextureBrowser_checkTagFile();
        TextureBrowser_SetNotex();
 
-       GlobalShaderSystem().setActiveShadersChangedNotify( ReferenceCaller<TextureBrowser, void(), TextureBrowser_activeShadersChanged>( g_TextureBrowser ) );
+       GlobalShaderSystem().setActiveShadersChangedNotify( ReferenceCaller<TextureBrowser, void(), TextureBrowser_activeShadersChanged>( textureBrowser ) );
 
-       g_TextureBrowser.m_parent = toplevel;
+       textureBrowser.m_parent = toplevel;
 
        auto table = ui::Table(3, 3, FALSE);
        auto vbox = ui::VBox(FALSE, 0);
@@ -2199,57 +2320,65 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
                // menu_bar.show();
        }
        { // Texture TreeView
-               g_TextureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New);
-               gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tree ), 0 );
+               textureBrowser.m_scr_win_tree = ui::ScrolledWindow(ui::New);
+               gtk_container_set_border_width( GTK_CONTAINER( textureBrowser.m_scr_win_tree ), 0 );
 
                // vertical only scrolling for treeview
-               gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
+               gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( textureBrowser.m_scr_win_tree ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
 
-               g_TextureBrowser.m_scr_win_tree.show();
+               textureBrowser.m_scr_win_tree.show();
 
                TextureBrowser_createTreeViewTree();
 
-               gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tree ), g_TextureBrowser.m_treeViewTree  );
-               g_TextureBrowser.m_treeViewTree.show();
+               gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( textureBrowser.m_scr_win_tree ), textureBrowser.m_treeViewTree  );
+               textureBrowser.m_treeViewTree.show();
        }
        { // gl_widget scrollbar
                auto w = ui::Widget::from(gtk_vscrollbar_new( ui::Adjustment( 0,0,0,1,1,0 ) ));
                table.attach(w, {2, 3, 1, 2}, {GTK_SHRINK, GTK_FILL});
                w.show();
-               g_TextureBrowser.m_texture_scroll = w;
+               textureBrowser.m_texture_scroll = w;
 
-               auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment( GTK_RANGE( g_TextureBrowser.m_texture_scroll ) ));
-               vadjustment.connect( "value_changed", G_CALLBACK( TextureBrowser_verticalScroll ), &g_TextureBrowser );
+               auto vadjustment = ui::Adjustment::from(gtk_range_get_adjustment( GTK_RANGE( textureBrowser.m_texture_scroll ) ));
+               vadjustment.connect( "value_changed", G_CALLBACK( TextureBrowser_verticalScroll ), &textureBrowser );
 
-               g_TextureBrowser.m_texture_scroll.visible(g_TextureBrowser.m_showTextureScrollbar);
+               textureBrowser.m_texture_scroll.visible(textureBrowser.m_showTextureScrollbar);
        }
        { // gl_widget
-               g_TextureBrowser.m_gl_widget = glwidget_new( FALSE );
-               g_object_ref( g_TextureBrowser.m_gl_widget._handle );
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+               textureBrowser.m_vframe = ui::VBox( FALSE, 0 );
+               table.attach(textureBrowser.m_vframe, {1, 2, 1, 2});
 
-               gtk_widget_set_events( g_TextureBrowser.m_gl_widget, GDK_DESTROY | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK );
-               gtk_widget_set_can_focus( g_TextureBrowser.m_gl_widget, true );
+               textureBrowser.m_vfiller = ui::VBox( FALSE, 0 );
+               textureBrowser.m_vframe.pack_start( textureBrowser.m_vfiller, FALSE, FALSE, 0 );
 
-               table.attach(g_TextureBrowser.m_gl_widget, {1, 2, 1, 2});
-               g_TextureBrowser.m_gl_widget.show();
+               textureBrowser.m_hframe = ui::HBox( FALSE, 0 );
+               textureBrowser.m_vframe.pack_start( textureBrowser.m_hframe, TRUE, TRUE, 0 );
 
-               g_TextureBrowser.m_sizeHandler = g_TextureBrowser.m_gl_widget.connect( "size_allocate", G_CALLBACK( TextureBrowser_size_allocate ), &g_TextureBrowser );
-               g_TextureBrowser.m_exposeHandler = g_TextureBrowser.m_gl_widget.on_render( G_CALLBACK( TextureBrowser_expose ), &g_TextureBrowser );
+               textureBrowser.m_hfiller = ui::HBox( FALSE, 0 );
+               textureBrowser.m_hframe.pack_start( textureBrowser.m_hfiller, FALSE, FALSE, 0 );
 
-               g_TextureBrowser.m_gl_widget.connect( "button_press_event", G_CALLBACK( TextureBrowser_button_press ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "button_release_event", G_CALLBACK( TextureBrowser_button_release ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "motion_notify_event", G_CALLBACK( TextureBrowser_motion ), &g_TextureBrowser );
-               g_TextureBrowser.m_gl_widget.connect( "scroll_event", G_CALLBACK( TextureBrowser_scroll ), &g_TextureBrowser );
+               textureBrowser.m_vframe.show();
+               textureBrowser.m_vfiller.show();
+               textureBrowser.m_hframe.show(),
+               textureBrowser.m_hfiller.show();
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+               textureBrowser.m_frame = ui::VBox( FALSE, 0 );
+               table.attach(textureBrowser.m_frame, {1, 2, 1, 2});
+               textureBrowser.m_frame.show();
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
+
+               TextureBrowser_constructGLWidget();
        }
 
        // tag stuff
-       if ( g_TextureBrowser.m_tags ) {
+       if ( textureBrowser.m_tags ) {
                { // fill tag GtkListStore
-                       g_TextureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
-            auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_all_tags_list );
+                       textureBrowser.m_all_tags_list = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
+            auto sortable = GTK_TREE_SORTABLE( textureBrowser.m_all_tags_list );
                        gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING );
 
-                       TagBuilder.GetAllTags( g_TextureBrowser.m_all_tags );
+                       TagBuilder.GetAllTags( textureBrowser.m_all_tags );
                        TextureBrowser_buildTagList();
                }
                { // tag menu bar
@@ -2264,67 +2393,67 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
                        button.connect( "clicked", G_CALLBACK( Popup_View_Menu ), menu_tags );
                }
                { // Tag TreeView
-                       g_TextureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New);
-                       gtk_container_set_border_width( GTK_CONTAINER( g_TextureBrowser.m_scr_win_tags ), 0 );
+                       textureBrowser.m_scr_win_tags = ui::ScrolledWindow(ui::New);
+                       gtk_container_set_border_width( GTK_CONTAINER( textureBrowser.m_scr_win_tags ), 0 );
 
                        // vertical only scrolling for treeview
-                       gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
+                       gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( textureBrowser.m_scr_win_tags ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
 
                        TextureBrowser_createTreeViewTags();
 
-            auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags );
+            auto selection = gtk_tree_view_get_selection(textureBrowser.m_treeViewTags );
                        gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
 
-                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( g_TextureBrowser.m_scr_win_tags ), g_TextureBrowser.m_treeViewTags  );
-                       g_TextureBrowser.m_treeViewTags.show();
+                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( textureBrowser.m_scr_win_tags ), textureBrowser.m_treeViewTags  );
+                       textureBrowser.m_treeViewTags.show();
                }
                { // Texture/Tag notebook
                        TextureBrowser_constructTagNotebook();
-                       vbox.pack_start( g_TextureBrowser.m_tag_notebook, TRUE, TRUE, 0 );
+                       vbox.pack_start( textureBrowser.m_tag_notebook, TRUE, TRUE, 0 );
                }
                { // Tag search button
                        TextureBrowser_constructSearchButton();
-                       vbox.pack_end(g_TextureBrowser.m_search_button, FALSE, FALSE, 0);
+                       vbox.pack_end(textureBrowser.m_search_button, FALSE, FALSE, 0);
                }
                auto frame_table = ui::Table(3, 3, FALSE);
                { // Tag frame
 
-                       g_TextureBrowser.m_tag_frame = ui::Frame( "Tag assignment" );
-                       gtk_frame_set_label_align( GTK_FRAME( g_TextureBrowser.m_tag_frame ), 0.5, 0.5 );
-                       gtk_frame_set_shadow_type( GTK_FRAME( g_TextureBrowser.m_tag_frame ), GTK_SHADOW_NONE );
+                       textureBrowser.m_tag_frame = ui::Frame( "Tag assignment" );
+                       gtk_frame_set_label_align( GTK_FRAME( textureBrowser.m_tag_frame ), 0.5, 0.5 );
+                       gtk_frame_set_shadow_type( GTK_FRAME( textureBrowser.m_tag_frame ), GTK_SHADOW_NONE );
 
-                       table.attach(g_TextureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK});
+                       table.attach(textureBrowser.m_tag_frame, {1, 3, 2, 3}, {GTK_FILL, GTK_SHRINK});
 
                        frame_table.show();
 
-                       g_TextureBrowser.m_tag_frame.add(frame_table);
+                       textureBrowser.m_tag_frame.add(frame_table);
                }
                { // assigned tag list
                        ui::Widget scrolled_win = ui::ScrolledWindow(ui::New);
                        gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 );
                        gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
 
-                       g_TextureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
+                       textureBrowser.m_assigned_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
 
-            auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_assigned_store );
+            auto sortable = GTK_TREE_SORTABLE( textureBrowser.m_assigned_store );
                        gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING );
 
                        auto renderer = ui::CellRendererText(ui::New);
 
-                       g_TextureBrowser.m_assigned_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_assigned_store._handle));
-                       g_TextureBrowser.m_assigned_store.unref();
-                       g_TextureBrowser.m_assigned_tree.connect( "row-activated", (GCallback) TextureBrowser_removeTags, NULL );
-                       gtk_tree_view_set_headers_visible(g_TextureBrowser.m_assigned_tree, FALSE );
+                       textureBrowser.m_assigned_tree = ui::TreeView(ui::TreeModel::from(textureBrowser.m_assigned_store._handle));
+                       textureBrowser.m_assigned_store.unref();
+                       textureBrowser.m_assigned_tree.connect( "row-activated", (GCallback) TextureBrowser_removeTags, NULL );
+                       gtk_tree_view_set_headers_visible(textureBrowser.m_assigned_tree, FALSE );
 
-            auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_assigned_tree );
+            auto selection = gtk_tree_view_get_selection(textureBrowser.m_assigned_tree );
                        gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
 
             auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} );
-                       gtk_tree_view_append_column(g_TextureBrowser.m_assigned_tree, column );
-                       g_TextureBrowser.m_assigned_tree.show();
+                       gtk_tree_view_append_column(textureBrowser.m_assigned_tree, column );
+                       textureBrowser.m_assigned_tree.show();
 
                        scrolled_win.show();
-                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_assigned_tree  );
+                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), textureBrowser.m_assigned_tree  );
 
                        frame_table.attach(scrolled_win, {0, 1, 1, 3}, {GTK_FILL, GTK_FILL});
                }
@@ -2333,26 +2462,26 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
                        gtk_container_set_border_width( GTK_CONTAINER( scrolled_win ), 0 );
                        gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW( scrolled_win ), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS );
 
-                       g_TextureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
-            auto sortable = GTK_TREE_SORTABLE( g_TextureBrowser.m_available_store );
+                       textureBrowser.m_available_store = ui::ListStore::from(gtk_list_store_new( N_COLUMNS, G_TYPE_STRING ));
+            auto sortable = GTK_TREE_SORTABLE( textureBrowser.m_available_store );
                        gtk_tree_sortable_set_sort_column_id( sortable, TAG_COLUMN, GTK_SORT_ASCENDING );
 
                        auto renderer = ui::CellRendererText(ui::New);
 
-                       g_TextureBrowser.m_available_tree = ui::TreeView(ui::TreeModel::from(g_TextureBrowser.m_available_store._handle));
-                       g_TextureBrowser.m_available_store.unref();
-                       g_TextureBrowser.m_available_tree.connect( "row-activated", (GCallback) TextureBrowser_assignTags, NULL );
-                       gtk_tree_view_set_headers_visible(g_TextureBrowser.m_available_tree, FALSE );
+                       textureBrowser.m_available_tree = ui::TreeView(ui::TreeModel::from(textureBrowser.m_available_store._handle));
+                       textureBrowser.m_available_store.unref();
+                       textureBrowser.m_available_tree.connect( "row-activated", (GCallback) TextureBrowser_assignTags, NULL );
+                       gtk_tree_view_set_headers_visible(textureBrowser.m_available_tree, FALSE );
 
-            auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree );
+            auto selection = gtk_tree_view_get_selection(textureBrowser.m_available_tree );
                        gtk_tree_selection_set_mode( selection, GTK_SELECTION_MULTIPLE );
 
             auto column = ui::TreeViewColumn( "", renderer, {{"text", TAG_COLUMN}} );
-                       gtk_tree_view_append_column(g_TextureBrowser.m_available_tree, column );
-                       g_TextureBrowser.m_available_tree.show();
+                       gtk_tree_view_append_column(textureBrowser.m_available_tree, column );
+                       textureBrowser.m_available_tree.show();
 
                        scrolled_win.show();
-                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), g_TextureBrowser.m_available_tree  );
+                       gtk_scrolled_window_add_with_viewport( GTK_SCROLLED_WINDOW( scrolled_win ), textureBrowser.m_available_tree  );
 
                        frame_table.attach(scrolled_win, {2, 3, 1, 3}, {GTK_FILL, GTK_FILL});
                }
@@ -2391,24 +2520,82 @@ ui::Widget TextureBrowser_constructWindow( ui::Window toplevel ){
                }
        }
        else { // no tag support, show the texture tree only
-               vbox.pack_start( g_TextureBrowser.m_scr_win_tree, TRUE, TRUE, 0 );
+               vbox.pack_start( textureBrowser.m_scr_win_tree, TRUE, TRUE, 0 );
        }
 
        // TODO do we need this?
        //gtk_container_set_focus_chain(GTK_CONTAINER(hbox_table), NULL);
 
+       isWindowConstructed = true;
+
        return table;
 }
 
+void TextureBrowser_destroyGLWidget(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       if ( isGLWidgetConstructed )
+       {
+               g_signal_handler_disconnect( G_OBJECT( textureBrowser.m_gl_widget ), textureBrowser.m_sizeHandler );
+               g_signal_handler_disconnect( G_OBJECT( textureBrowser.m_gl_widget ), textureBrowser.m_exposeHandler );
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+               textureBrowser.m_hframe.remove( textureBrowser.m_gl_widget );
+#else // !WORKAROUND_MACOS_GTK2_GLWIDGET
+               textureBrowser.m_frame.remove( textureBrowser.m_gl_widget );
+#endif // !WORKAROUND_MACOS_GTK2_GLWIDGET
+
+               textureBrowser.m_gl_widget.unref();
+
+               isGLWidgetConstructed = false;
+       }
+}
+
 void TextureBrowser_destroyWindow(){
        GlobalShaderSystem().setActiveShadersChangedNotify( Callback<void()>() );
 
-       g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_sizeHandler );
-       g_signal_handler_disconnect( G_OBJECT( g_TextureBrowser.m_gl_widget ), g_TextureBrowser.m_exposeHandler );
+       TextureBrowser_destroyGLWidget();
+}
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+/* workaround for gtkglext on gtk 2 issue: OpenGL texture viewport being drawn over the other pages */
+/* this is very ugly: force the resizing of the viewport to a single bottom line by forcing the
+ * resizing of the gl widget by expanding some empty boxes, so the widget area size is reduced
+ * while covered by another page, so the texture viewport is still rendered over the other page
+ * but does not annoy the user that much because it's just a line on the bottom that may even
+ * be printed over existing bottom frame or very close to it. */
+void TextureBrowser_showGLWidget(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       if ( isWindowConstructed && isGLWidgetConstructed )
+       {
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_vfiller, FALSE, FALSE, 0, ui::Packing::START );
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_hframe, TRUE, TRUE, 0, ui::Packing::START );
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_hfiller, FALSE, FALSE, 0, ui::Packing::START );
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_gl_widget, TRUE, TRUE, 0, ui::Packing::START );
 
-       g_TextureBrowser.m_gl_widget.unref();
+               textureBrowser.m_gl_widget.show();
+}
 }
 
+void TextureBrowser_hideGLWidget(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       if ( isWindowConstructed && isGLWidgetConstructed )
+       {
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_vfiller, TRUE, TRUE, 0, ui::Packing::START);
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_hframe, FALSE, FALSE, 0, ui::Packing::END );
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_hfiller, TRUE, TRUE, 0, ui::Packing::START);
+               textureBrowser.m_vframe.set_child_packing( textureBrowser.m_gl_widget, FALSE, FALSE, 0, ui::Packing::END );
+
+               // The hack needs the GL widget to not be hidden to work,
+               // so resizing it triggers the redraw of it with the new size.
+               // GlobalTextureBrowser().m_gl_widget.hide();
+
+               // Trigger the redraw.
+               TextureBrowser_redraw( &GlobalTextureBrowser() );
+               ui::process();
+       }
+}
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
+
 const Vector3& TextureBrowser_getBackgroundColour( TextureBrowser& textureBrowser ){
        return textureBrowser.color_textureback;
 }
@@ -2427,7 +2614,7 @@ void TextureBrowser_selectionHelper( ui::TreeModel model, ui::TreePath path, Gtk
 }
 
 void TextureBrowser_shaderInfo(){
-       const char* name = TextureBrowser_GetSelectedShader( g_TextureBrowser );
+       const char* name = TextureBrowser_GetSelectedShader( GlobalTextureBrowser() );
        IShader* shader = QERApp_Shader_ForName( name );
 
        DoShaderInfoDlg( name, shader->getShaderFileName(), "Shader Info" );
@@ -2437,20 +2624,21 @@ void TextureBrowser_shaderInfo(){
 
 void TextureBrowser_addTag(){
        CopiedString tag;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
        EMessageBoxReturn result = DoShaderTagDlg( &tag, "Add shader tag" );
 
        if ( result == eIDOK && !tag.empty() ) {
                GtkTreeIter iter;
-               g_TextureBrowser.m_all_tags.insert( tag.c_str() );
-               gtk_list_store_append( g_TextureBrowser.m_available_store, &iter );
-               gtk_list_store_set( g_TextureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1 );
+               textureBrowser.m_all_tags.insert( tag.c_str() );
+               gtk_list_store_append( textureBrowser.m_available_store, &iter );
+               gtk_list_store_set( textureBrowser.m_available_store, &iter, TAG_COLUMN, tag.c_str(), -1 );
 
                // Select the currently added tag in the available list
-        auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_available_tree );
+        auto selection = gtk_tree_view_get_selection(textureBrowser.m_available_tree );
                gtk_tree_selection_select_iter( selection, &iter );
 
-               g_TextureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str());
+               textureBrowser.m_all_tags_list.append(TAG_COLUMN, tag.c_str());
        }
 }
 
@@ -2463,8 +2651,9 @@ void TextureBrowser_renameTag(){
         */
 
        GSList* selected = NULL;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
-    auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags );
+       auto selection = gtk_tree_view_get_selection(textureBrowser.m_treeViewTags );
        gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected );
 
        if ( g_slist_length( selected ) == 1 ) { // we only rename a single tag
@@ -2476,41 +2665,42 @@ void TextureBrowser_renameTag(){
                        gchar* rowTag;
                        gchar* oldTag = (char*)selected->data;
 
-                       bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterList ) != 0;
+                       bool row = gtk_tree_model_get_iter_first(textureBrowser.m_all_tags_list, &iterList ) != 0;
 
                        while ( row )
                        {
-                               gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1 );
+                               gtk_tree_model_get(textureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, &rowTag, -1 );
 
                                if ( strcmp( rowTag, oldTag ) == 0 ) {
-                                       gtk_list_store_set( g_TextureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1 );
+                                       gtk_list_store_set( textureBrowser.m_all_tags_list, &iterList, TAG_COLUMN, newTag.c_str(), -1 );
                                }
-                               row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterList ) != 0;
+                               row = gtk_tree_model_iter_next(textureBrowser.m_all_tags_list, &iterList ) != 0;
                        }
 
                        TagBuilder.RenameShaderTag( oldTag, newTag.c_str() );
 
-                       g_TextureBrowser.m_all_tags.erase( (CopiedString)oldTag );
-                       g_TextureBrowser.m_all_tags.insert( newTag );
+                       textureBrowser.m_all_tags.erase( (CopiedString)oldTag );
+                       textureBrowser.m_all_tags.insert( newTag );
 
-                       BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser );
-                       BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser );
+                       BuildStoreAssignedTags( textureBrowser.m_assigned_store, textureBrowser.shader.c_str(), &textureBrowser );
+                       BuildStoreAvailableTags( textureBrowser.m_available_store, textureBrowser.m_assigned_store, textureBrowser.m_all_tags, &textureBrowser );
                }
        }
        else
        {
-               ui::alert( g_TextureBrowser.m_parent, "Select a single tag for renaming." );
+               ui::alert( textureBrowser.m_parent, "Select a single tag for renaming." );
        }
 }
 
 void TextureBrowser_deleteTag(){
        GSList* selected = NULL;
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
-    auto selection = gtk_tree_view_get_selection(g_TextureBrowser.m_treeViewTags );
+       auto selection = gtk_tree_view_get_selection(textureBrowser.m_treeViewTags );
        gtk_tree_selection_selected_foreach( selection, GtkTreeSelectionForeachFunc( TextureBrowser_selectionHelper ), &selected );
 
        if ( g_slist_length( selected ) == 1 ) { // we only delete a single tag
-               auto result = ui::alert( g_TextureBrowser.m_parent, "Are you sure you want to delete the selected tag?", "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question );
+               auto result = ui::alert( textureBrowser.m_parent, "Are you sure you want to delete the selected tag?", "Delete Tag", ui::alert_type::YESNO, ui::alert_icon::Question );
 
                if ( result == ui::alert_response::YES ) {
                        GtkTreeIter iterSelected;
@@ -2518,39 +2708,41 @@ void TextureBrowser_deleteTag(){
 
                        gchar* tagSelected = (char*)selected->data;
 
-                       bool row = gtk_tree_model_get_iter_first(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0;
+                       bool row = gtk_tree_model_get_iter_first(textureBrowser.m_all_tags_list, &iterSelected ) != 0;
 
                        while ( row )
                        {
-                               gtk_tree_model_get(g_TextureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1 );
+                               gtk_tree_model_get(textureBrowser.m_all_tags_list, &iterSelected, TAG_COLUMN, &rowTag, -1 );
 
                                if ( strcmp( rowTag, tagSelected ) == 0 ) {
-                                       gtk_list_store_remove( g_TextureBrowser.m_all_tags_list, &iterSelected );
+                                       gtk_list_store_remove( textureBrowser.m_all_tags_list, &iterSelected );
                                        break;
                                }
-                               row = gtk_tree_model_iter_next(g_TextureBrowser.m_all_tags_list, &iterSelected ) != 0;
+                               row = gtk_tree_model_iter_next(textureBrowser.m_all_tags_list, &iterSelected ) != 0;
                        }
 
                        TagBuilder.DeleteTag( tagSelected );
-                       g_TextureBrowser.m_all_tags.erase( (CopiedString)tagSelected );
+                       textureBrowser.m_all_tags.erase( (CopiedString)tagSelected );
 
-                       BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, g_TextureBrowser.shader.c_str(), &g_TextureBrowser );
-                       BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser );
+                       BuildStoreAssignedTags( textureBrowser.m_assigned_store, textureBrowser.shader.c_str(), &textureBrowser );
+                       BuildStoreAvailableTags( textureBrowser.m_available_store, textureBrowser.m_assigned_store, textureBrowser.m_all_tags, &textureBrowser );
                }
        }
        else {
-               ui::alert( g_TextureBrowser.m_parent, "Select a single tag for deletion." );
+               ui::alert( textureBrowser.m_parent, "Select a single tag for deletion." );
        }
 }
 
 void TextureBrowser_copyTag(){
-       g_TextureBrowser.m_copied_tags.clear();
-       TagBuilder.GetShaderTags( g_TextureBrowser.shader.c_str(), g_TextureBrowser.m_copied_tags );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       textureBrowser.m_copied_tags.clear();
+       TagBuilder.GetShaderTags( textureBrowser.shader.c_str(), textureBrowser.m_copied_tags );
 }
 
 void TextureBrowser_pasteTag(){
-       IShader* ishader = QERApp_Shader_ForName( g_TextureBrowser.shader.c_str() );
-       CopiedString shader = g_TextureBrowser.shader.c_str();
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       IShader* ishader = QERApp_Shader_ForName( textureBrowser.shader.c_str() );
+       CopiedString shader = textureBrowser.shader.c_str();
 
        if ( !TagBuilder.CheckShaderTag( shader.c_str() ) ) {
                CopiedString shaderFile = ishader->getShaderFileName();
@@ -2564,18 +2756,18 @@ void TextureBrowser_pasteTag(){
                        TagBuilder.AddShaderNode( shader.c_str(), CUSTOM, SHADER );
                }
 
-               for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i )
+               for ( size_t i = 0; i < textureBrowser.m_copied_tags.size(); ++i )
                {
-                       TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG );
+                       TagBuilder.AddShaderTag( shader.c_str(), textureBrowser.m_copied_tags[i].c_str(), TAG );
                }
        }
        else
        {
-               for ( size_t i = 0; i < g_TextureBrowser.m_copied_tags.size(); ++i )
+               for ( size_t i = 0; i < textureBrowser.m_copied_tags.size(); ++i )
                {
-                       if ( !TagBuilder.CheckShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str() ) ) {
+                       if ( !TagBuilder.CheckShaderTag( shader.c_str(), textureBrowser.m_copied_tags[i].c_str() ) ) {
                                // the tag doesn't exist - let's add it
-                               TagBuilder.AddShaderTag( shader.c_str(), g_TextureBrowser.m_copied_tags[i].c_str(), TAG );
+                               TagBuilder.AddShaderTag( shader.c_str(), textureBrowser.m_copied_tags[i].c_str(), TAG );
                        }
                }
        }
@@ -2583,11 +2775,12 @@ void TextureBrowser_pasteTag(){
        ishader->DecRef();
 
        TagBuilder.SaveXmlDoc();
-       BuildStoreAssignedTags( g_TextureBrowser.m_assigned_store, shader.c_str(), &g_TextureBrowser );
-       BuildStoreAvailableTags( g_TextureBrowser.m_available_store, g_TextureBrowser.m_assigned_store, g_TextureBrowser.m_all_tags, &g_TextureBrowser );
+       BuildStoreAssignedTags( textureBrowser.m_assigned_store, shader.c_str(), &textureBrowser );
+       BuildStoreAvailableTags( textureBrowser.m_available_store, textureBrowser.m_assigned_store, textureBrowser.m_all_tags, &textureBrowser );
 }
 
 void TextureBrowser_RefreshShaders(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
 
        /* When shaders are refreshed, forces reloading the textures as well.
        Previously it would at best only display shaders, at worst mess up some textured objects. */
@@ -2627,54 +2820,55 @@ void TextureBrowser_RefreshShaders(){
 }
 
 void TextureBrowser_ToggleShowShaders(){
-       g_TextureBrowser.m_showShaders ^= 1;
-       g_TextureBrowser.m_showshaders_item.update();
+       GlobalTextureBrowser().m_showShaders ^= 1;
+       GlobalTextureBrowser().m_showshaders_item.update();
 
-       g_TextureBrowser.m_heightChanged = true;
-       g_TextureBrowser.m_originInvalid = true;
+       GlobalTextureBrowser().m_heightChanged = true;
+       GlobalTextureBrowser().m_originInvalid = true;
        g_activeShadersChangedCallbacks();
 
-       TextureBrowser_queueDraw( g_TextureBrowser );
+       TextureBrowser_queueDraw( GlobalTextureBrowser() );
 }
 
 void TextureBrowser_ToggleShowTextures(){
-       g_TextureBrowser.m_showTextures ^= 1;
-       g_TextureBrowser.m_showtextures_item.update();
+       GlobalTextureBrowser().m_showTextures ^= 1;
+       GlobalTextureBrowser().m_showtextures_item.update();
 
-       g_TextureBrowser.m_heightChanged = true;
-       g_TextureBrowser.m_originInvalid = true;
+       GlobalTextureBrowser().m_heightChanged = true;
+       GlobalTextureBrowser().m_originInvalid = true;
        g_activeShadersChangedCallbacks();
 
-       TextureBrowser_queueDraw( g_TextureBrowser );
+       TextureBrowser_queueDraw( GlobalTextureBrowser() );
 }
 
 void TextureBrowser_ToggleShowShaderListOnly(){
        g_TextureBrowser_shaderlistOnly ^= 1;
-       g_TextureBrowser.m_showshaderlistonly_item.update();
+       GlobalTextureBrowser().m_showshaderlistonly_item.update();
 
        TextureBrowser_constructTreeStore();
 }
 
 void TextureBrowser_showAll(){
        g_TextureBrowser_currentDirectory = "";
-       g_TextureBrowser.m_searchedTags = false;
-//     TextureBrowser_SetHideUnused( g_TextureBrowser, false );
+       GlobalTextureBrowser().m_searchedTags = false;
+//     TextureBrowser_SetHideUnused( GlobalTextureBrowser(), false );
        TextureBrowser_ToggleHideUnused();
-       //TextureBrowser_heightChanged( g_TextureBrowser );
+       //TextureBrowser_heightChanged( GlobalTextureBrowser() );
        TextureBrowser_updateTitle();
 }
 
 void TextureBrowser_showUntagged(){
-       auto result = ui::alert( g_TextureBrowser.m_parent, "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning );
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+       auto result = ui::alert( textureBrowser.m_parent, "WARNING! This function might need a lot of memory and time. Are you sure you want to use it?", "Show Untagged", ui::alert_type::YESNO, ui::alert_icon::Warning );
 
        if ( result == ui::alert_response::YES ) {
-               g_TextureBrowser.m_found_shaders.clear();
-               TagBuilder.GetUntagged( g_TextureBrowser.m_found_shaders );
+               textureBrowser.m_found_shaders.clear();
+               TagBuilder.GetUntagged( textureBrowser.m_found_shaders );
                std::set<CopiedString>::iterator iter;
 
                ScopeDisableScreenUpdates disableScreenUpdates( "Searching untagged textures...", "Loading Textures" );
 
-               for ( iter = g_TextureBrowser.m_found_shaders.begin(); iter != g_TextureBrowser.m_found_shaders.end(); iter++ )
+               for ( iter = textureBrowser.m_found_shaders.begin(); iter != textureBrowser.m_found_shaders.end(); iter++ )
                {
                        std::string path = ( *iter ).c_str();
                        size_t pos = path.find_last_of( "/", path.size() );
@@ -2686,7 +2880,7 @@ void TextureBrowser_showUntagged(){
 
                g_TextureBrowser_currentDirectory = "Untagged";
                TextureBrowser_queueDraw( GlobalTextureBrowser() );
-               TextureBrowser_heightChanged( g_TextureBrowser );
+               TextureBrowser_heightChanged( textureBrowser );
                TextureBrowser_updateTitle();
        }
 }
@@ -2774,7 +2968,7 @@ struct TextureScale {
 
 struct UniformTextureSize {
        static void Export(const TextureBrowser &self, const Callback<void(int)> &returnz) {
-               returnz(g_TextureBrowser.m_uniformTextureSize);
+               returnz(GlobalTextureBrowser().m_uniformTextureSize);
        }
 
        static void Import(TextureBrowser &self, int value) {
@@ -2785,7 +2979,7 @@ struct UniformTextureSize {
 
 struct UniformTextureMinSize {
        static void Export(const TextureBrowser &self, const Callback<void(int)> &returnz) {
-               returnz(g_TextureBrowser.m_uniformTextureMinSize);
+               returnz(GlobalTextureBrowser().m_uniformTextureMinSize);
        }
 
        static void Import(TextureBrowser &self, int value) {
@@ -2811,7 +3005,7 @@ void TextureBrowser_constructPreferences( PreferencesPage& page ){
        page.appendSpinner( "Thumbnails Min Size", GlobalTextureBrowser().m_uniformTextureMinSize, GlobalTextureBrowser().m_uniformTextureMinSize, 16, 8192 );
        page.appendEntry( "Mousewheel Increment", GlobalTextureBrowser().m_mouseWheelScrollIncrement );
        {
-               const char* startup_shaders[] = { "None", TextureBrowser_getComonShadersName() };
+               const char* startup_shaders[] = { "None", TextureBrowser_getCommonShadersName() };
                page.appendCombo( "Load Shaders at Startup", reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ), STRING_ARRAY_RANGE( startup_shaders ) );
        }
 }
@@ -2833,6 +3027,8 @@ void TextureBrowser_registerPreferencesPage(){
 void TextureClipboard_textureSelected( const char* shader );
 
 void TextureBrowser_Construct(){
+       TextureBrowser &textureBrowser = GlobalTextureBrowser();
+
        GlobalCommands_insert( "ShaderInfo", makeCallbackF(TextureBrowser_shaderInfo) );
        GlobalCommands_insert( "ShowUntagged", makeCallbackF(TextureBrowser_showUntagged) );
        GlobalCommands_insert( "AddTag", makeCallbackF(TextureBrowser_addTag) );
@@ -2841,35 +3037,35 @@ void TextureBrowser_Construct(){
        GlobalCommands_insert( "CopyTag", makeCallbackF(TextureBrowser_copyTag) );
        GlobalCommands_insert( "PasteTag", makeCallbackF(TextureBrowser_pasteTag) );
        GlobalCommands_insert( "RefreshShaders", makeCallbackF(VFS_Refresh) );
-       GlobalToggles_insert( "ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hideunused_item ), Accelerator( 'U' ) );
+       GlobalToggles_insert( "ShowInUse", makeCallbackF(TextureBrowser_ToggleHideUnused), ToggleItem::AddCallbackCaller( textureBrowser.m_hideunused_item ), Accelerator( 'U' ) );
        GlobalCommands_insert( "ShowAllTextures", makeCallbackF(TextureBrowser_showAll), Accelerator( 'A', (GdkModifierType)GDK_CONTROL_MASK ) );
        GlobalCommands_insert( "ToggleTextures", makeCallbackF(TextureBrowser_toggleShow), Accelerator( 'T' ) );
-       GlobalToggles_insert( "ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaders_item ) );
-       GlobalToggles_insert( "ToggleShowTextures", makeCallbackF(TextureBrowser_ToggleShowTextures), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showtextures_item ) );
+       GlobalToggles_insert( "ToggleShowShaders", makeCallbackF(TextureBrowser_ToggleShowShaders), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_showshaders_item ) );
+       GlobalToggles_insert( "ToggleShowTextures", makeCallbackF(TextureBrowser_ToggleShowTextures), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_showtextures_item ) );
        GlobalToggles_insert( "ToggleShowShaderlistOnly", makeCallbackF(TextureBrowser_ToggleShowShaderListOnly),
- ToggleItem::AddCallbackCaller( g_TextureBrowser.m_showshaderlistonly_item ) );
-       GlobalToggles_insert( "FixedSize", makeCallbackF(TextureBrowser_FixedSize), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_fixedsize_item ) );
-       GlobalToggles_insert( "FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_filternotex_item ) );
-       GlobalToggles_insert( "FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_hidenotex_item ) );
-       GlobalToggles_insert( "EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), ToggleItem::AddCallbackCaller( g_TextureBrowser.m_enablealpha_item ) );
-
-       GlobalPreferenceSystem().registerPreference( "TextureScale", make_property_string<TextureScale>(g_TextureBrowser) );
-       GlobalPreferenceSystem().registerPreference( "UniformTextureSize", make_property_string<UniformTextureSize>(g_TextureBrowser) );
-       GlobalPreferenceSystem().registerPreference( "UniformTextureMinSize", make_property_string<UniformTextureMinSize>(g_TextureBrowser) );
-       GlobalPreferenceSystem().registerPreference( "TextureScrollbar", make_property_string<TextureBrowser_ShowScrollbar>(GlobalTextureBrowser()));
-       GlobalPreferenceSystem().registerPreference( "ShowShaders", make_property_string( GlobalTextureBrowser().m_showShaders ) );
+ ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_showshaderlistonly_item ) );
+       GlobalToggles_insert( "FixedSize", makeCallbackF(TextureBrowser_FixedSize), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_fixedsize_item ) );
+       GlobalToggles_insert( "FilterMissing", makeCallbackF(TextureBrowser_FilterMissing), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_filternotex_item ) );
+       GlobalToggles_insert( "FilterFallback", makeCallbackF(TextureBrowser_FilterFallback), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_hidenotex_item ) );
+       GlobalToggles_insert( "EnableAlpha", makeCallbackF(TextureBrowser_EnableAlpha), ToggleItem::AddCallbackCaller( GlobalTextureBrowser().m_enablealpha_item ) );
+
+       GlobalPreferenceSystem().registerPreference( "TextureScale", make_property_string<TextureScale>(textureBrowser) );
+       GlobalPreferenceSystem().registerPreference( "UniformTextureSize", make_property_string<UniformTextureSize>(textureBrowser) );
+       GlobalPreferenceSystem().registerPreference( "UniformTextureMinSize", make_property_string<UniformTextureMinSize>(textureBrowser) );
+       GlobalPreferenceSystem().registerPreference( "TextureScrollbar", make_property_string<TextureBrowser_ShowScrollbar>(textureBrowser));
+       GlobalPreferenceSystem().registerPreference( "ShowShaders", make_property_string( textureBrowser.m_showShaders ) );
        GlobalPreferenceSystem().registerPreference( "ShowTextures", make_property_string( GlobalTextureBrowser().m_showTextures ) );
        GlobalPreferenceSystem().registerPreference( "ShowShaderlistOnly", make_property_string( g_TextureBrowser_shaderlistOnly ) );
        GlobalPreferenceSystem().registerPreference( "FixedSize", make_property_string( g_TextureBrowser_fixedSize ) );
        GlobalPreferenceSystem().registerPreference( "FilterMissing", make_property_string( g_TextureBrowser_filterMissing ) );
        GlobalPreferenceSystem().registerPreference( "EnableAlpha", make_property_string( g_TextureBrowser_enableAlpha ) );
-       GlobalPreferenceSystem().registerPreference( "LoadShaders", make_property_string( reinterpret_cast<int&>( GlobalTextureBrowser().m_startupShaders ) ) );
-       GlobalPreferenceSystem().registerPreference( "WheelMouseInc", make_property_string( GlobalTextureBrowser().m_mouseWheelScrollIncrement ) );
-       GlobalPreferenceSystem().registerPreference( "SI_Colors0", make_property_string( GlobalTextureBrowser().color_textureback ) );
+       GlobalPreferenceSystem().registerPreference( "LoadShaders", make_property_string( reinterpret_cast<int&>( textureBrowser.m_startupShaders ) ) );
+       GlobalPreferenceSystem().registerPreference( "WheelMouseInc", make_property_string( textureBrowser.m_mouseWheelScrollIncrement ) );
+       GlobalPreferenceSystem().registerPreference( "SI_Colors0", make_property_string( textureBrowser.color_textureback ) );
 
-       g_TextureBrowser.shader = texdef_name_default();
+       textureBrowser.shader = texdef_name_default();
 
-       Textures_setModeChangedNotify( ReferenceCaller<TextureBrowser, void(), TextureBrowser_queueDraw>( g_TextureBrowser ) );
+       Textures_setModeChangedNotify( ReferenceCaller<TextureBrowser, void(), TextureBrowser_queueDraw>( textureBrowser ) );
 
        TextureBrowser_registerPreferencesPage();
 
@@ -2887,3 +3083,9 @@ void TextureBrowser_Destroy(){
 ui::Widget TextureBrowser_getGLWidget(){
        return GlobalTextureBrowser().m_gl_widget;
 }
+
+#if WORKAROUND_WINDOWS_GTK2_GLWIDGET
+ui::GLArea TextureBrowser_getGLWidget(){
+       return GlobalTextureBrowser().m_gl_widget;
+}
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
index d354c9dfd00f4dbfc26c67fd240b2fba813e5fb9..f17a980d73b224aadece0e9e313ad13911456f2f 100644 (file)
@@ -56,6 +56,13 @@ void TextureBrowser_addShadersRealiseCallback( const SignalHandler& handler );
 
 void TextureBrowser_RefreshShaders();
 
-ui::Widget TextureBrowser_getGLWidget();
+#ifdef WORKAROUND_WINDOWS_GTK2_GLWIDGET
+ui::GLArea TextureBrowser_getGLWidget();
+#endif // WORKAROUND_WINDOWS_GTK2_GLWIDGET
+
+#ifdef WORKAROUND_MACOS_GTK2_GLWIDGET
+void TextureBrowser_showGLWidget();
+void TextureBrowser_hideGLWidget();
+#endif // WORKAROUND_MACOS_GTK2_GLWIDGET
 
 #endif
index 12441f0e7ee0f5523f005c79dc8c8c1642902011..cbd529d4a5b6290ee58bde0a666d9db73408c451 100644 (file)
@@ -984,7 +984,7 @@ static gboolean graph_tree_model_iter_parent( GraphTreeModel *tree_model, GtkTre
        return FALSE;
 }
 
-static GObjectClass *g_parent_class = 0;
+static GObjectClass *g_parent_class = nullptr;
 
 namespace
 {
index 118d37f47ab950e98812c74b2b44599103d9e00f..33fbdfd5e7f68ff108525b2dddd583841ae65032 100644 (file)
@@ -274,8 +274,8 @@ static void saxStartElement( message_info_t *data, const xmlChar *name, const xm
                                else if ( strcmp( reinterpret_cast<const char*>( attrs[1] ), Q3MAP_STREAM_VERSION ) != 0 ) {
                                        message_flush( data );
                                        globalErrorStream() <<
-                                       "This version of Radiant reads version " Q3MAP_STREAM_VERSION " debug streams, I got an incoming connection with version " << reinterpret_cast<const char*>( attrs[1] ) << "\n"
-                                                                                                                                                                                                                                                                                                                                                                                          "Please make sure your versions of Radiant and q3map are matching.\n";
+                                       "This version of " RADIANT_NAME " reads version " Q3MAP_STREAM_VERSION " debug streams, I got an incoming connection with version " << reinterpret_cast<const char*>( attrs[1] ) << "\n"
+                                                                                                                                                                                                                                                                                                                                                                                          "Please make sure your versions of " RADIANT_NAME " and q3map are matching.\n";
                                        abortStream( data );
                                        return;
                                }
index f1cb57fdbf8a47203516ebe0294d1bf850f1b915..db3802bd90e5d2b97fb983b5d7ba727ccbd0740b 100644 (file)
@@ -58,6 +58,7 @@
 #include "gtkutil/widget.h"
 #include "gtkutil/glwidget.h"
 #include "gtkutil/filechooser.h"
+#include "gtkutil/cursor.h"
 #include "gtkmisc.h"
 #include "select.h"
 #include "csg.h"
@@ -555,6 +556,19 @@ void XYWnd::ZoomInWithMouse( int pointx, int pointy ){
        }
 }
 
+void XYWnd::Redraw() {
+       if ( glwidget_make_current( m_gl_widget ) != FALSE ) {
+               if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
+                       GlobalOpenGL_debugAssertNoErrors();
+                       XY_Draw();
+                       GlobalOpenGL_debugAssertNoErrors();
+
+                       m_XORRectangle.set( rectangle_t() );
+               }
+               glwidget_swap_buffers( m_gl_widget );
+       }
+}
+
 VIEWTYPE GlobalXYWnd_getCurrentViewType(){
        ASSERT_NOTNULL( g_pParentWnd );
        ASSERT_NOTNULL( g_pParentWnd->ActiveXY() );
@@ -802,20 +816,10 @@ gboolean xywnd_size_allocate( ui::Widget widget, GtkAllocation* allocation, XYWn
 }
 
 gboolean xywnd_expose( ui::Widget widget, GdkEventExpose* event, XYWnd* xywnd ){
-       if ( glwidget_make_current( xywnd->GetWidget() ) != FALSE ) {
-               if ( Map_Valid( g_map ) && ScreenUpdates_Enabled() ) {
-                       GlobalOpenGL_debugAssertNoErrors();
-                       xywnd->XY_Draw();
-                       GlobalOpenGL_debugAssertNoErrors();
-
-                       xywnd->m_XORRectangle.set( rectangle_t() );
-               }
-               glwidget_swap_buffers( xywnd->GetWidget() );
-       }
+       xywnd->Redraw();
        return FALSE;
 }
 
-
 void XYWnd_CameraMoved( XYWnd& xywnd ){
        if ( g_xywindow_globals_private.m_bCamXYUpdate ) {
                XYWnd_Update( xywnd );
@@ -830,6 +834,7 @@ XYWnd::XYWnd() :
        m_window_observer( NewWindowObserver() ),
        m_XORRectangle( m_gl_widget ),
        m_chasemouse_handler( 0 ){
+
        m_bActive = false;
        m_buttonstate = 0;
 
@@ -880,8 +885,11 @@ XYWnd::XYWnd() :
 
        Map_addValidCallback( g_map, DeferredDrawOnMapValidChangedCaller( m_deferredDraw ) );
 
-       updateProjection();
-       updateModelview();
+       // This reconstruct=false argument is used to avoid a circular dependency
+       // between modelview and projection initialization and a valgrind complaint
+       updateProjection( false );
+       updateModelview( false );
+       m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight );
 
        AddSceneChangeCallback( ReferenceCaller<XYWnd, void(), &XYWnd_Update>( *this ) );
        AddCameraMovedCallback( ReferenceCaller<XYWnd, void(), &XYWnd_CameraMoved>( *this ) );
@@ -983,14 +991,11 @@ void XYWnd::Clipper_Crosshair_OnMouseMoved( int x, int y ){
        Vector3 mousePosition;
        XY_ToPoint( x, y, mousePosition );
        if ( ClipMode() && GlobalClipPoints_Find( mousePosition, (VIEWTYPE)m_viewType, m_fScale ) != 0 ) {
-               GdkCursor *cursor;
-               cursor = gdk_cursor_new( GDK_CROSSHAIR );
-               gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), cursor );
-               gdk_cursor_unref( cursor );
+               set_cursor ( m_gl_widget, GDK_CROSSHAIR );
        }
        else
        {
-               gdk_window_set_cursor( gtk_widget_get_window(m_gl_widget), 0 );
+               default_cursor( m_gl_widget );
        }
 }
 
@@ -1107,8 +1112,8 @@ void entitycreate_activated( ui::Widget item ){
                g_pParentWnd->ActiveXY()->OnEntityCreate( entity_name );
        }
        else {
-               GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(), "There's already a worldspawn in your map!"
-                                                                                                                                                         "",
+               GlobalRadiant().m_pfnMessageBox( MainFrame_getWindow(),
+                       "There's already a worldspawn in your map!",
                                                                                 "Info",
                                                                                 eMB_OK,
                                                                                 eMB_ICONDEFAULT );
@@ -1223,13 +1228,15 @@ void XYWnd::Move_Begin(){
                Move_End();
        }
        m_move_started = true;
-       g_xywnd_freezePointer.freeze_pointer( m_parent  ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_moveDelta, this );
+       /* NetRadiantCustom did this instead:
+       g_xywnd_freezePointer.freeze_pointer( m_parent  ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_moveDelta, this ); */
+       g_xywnd_freezePointer.freeze_pointer( m_gl_widget, XYWnd_moveDelta, this );
        m_move_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Move_focusOut ), this );
 }
 
 void XYWnd::Move_End(){
        m_move_started = false;
-       g_xywnd_freezePointer.unfreeze_pointer( m_parent ? m_parent : MainFrame_getWindow() );
+       g_xywnd_freezePointer.unfreeze_pointer( m_gl_widget );
        g_signal_handler_disconnect( G_OBJECT( m_gl_widget ), m_move_focusOut );
 }
 
@@ -1268,7 +1275,9 @@ void XYWnd::Zoom_Begin(){
        }
        m_zoom_started = true;
        g_dragZoom = 0;
-       g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_zoomDelta, this );
+       /* NetRadiantCustom did this instead:
+       g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), m_gl_widget, XYWnd_zoomDelta, this ); */
+       g_xywnd_freezePointer.freeze_pointer( m_parent ? m_parent : MainFrame_getWindow(), XYWnd_zoomDelta, this );
        m_zoom_focusOut = m_gl_widget.connect( "focus_out_event", G_CALLBACK( XYWnd_Zoom_focusOut ), this );
 }
 
@@ -1533,17 +1542,25 @@ void XYWnd::XY_DisableBackground( void ){
 
 void WXY_BackgroundSelect( void ){
        bool brushesSelected = Scene_countSelectedBrushes( GlobalSceneGraph() ) != 0;
+
+       ui::Window main_window = MainFrame_getWindow();
+
        if ( !brushesSelected ) {
-               ui::alert( ui::root, "You have to select some brushes to get the bounding box for.\n",
+               ui::alert( main_window, "You have to select some brushes to get the bounding box for.\n",
                                                "No selection", ui::alert_type::OK, ui::alert_icon::Error );
                return;
        }
 
-       const char *filename = MainFrame_getWindow().file_dialog( TRUE, "Background Image", NULL, NULL );
+       const char *filename = main_window.file_dialog( TRUE, "Background Image", NULL, NULL );
+
        g_pParentWnd->ActiveXY()->XY_DisableBackground();
+
        if ( filename ) {
                g_pParentWnd->ActiveXY()->XY_LoadBackgroundImage( filename );
        }
+
+       // Draw the background image immediately (do not wait for user input).
+       g_pParentWnd->ActiveXY()->Redraw();
 }
 
 /*
@@ -2147,7 +2164,7 @@ RenderStateFlags m_globalstate;
 Shader* m_state_selected;
 };
 
-void XYWnd::updateProjection(){
+void XYWnd::updateProjection( bool reconstruct ){
        m_projection[0] = 1.0f / static_cast<float>( m_nWidth / 2 );
        m_projection[5] = 1.0f / static_cast<float>( m_nHeight / 2 );
        m_projection[10] = 1.0f / ( g_MaxWorldCoord * m_fScale );
@@ -2170,11 +2187,13 @@ void XYWnd::updateProjection(){
 
        m_projection[15] = 1.0f;
 
-       m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight );
+       if (reconstruct) {
+               m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight );
+       }
 }
 
 // note: modelview matrix must have a uniform scale, otherwise strange things happen when rendering the rotation manipulator.
-void XYWnd::updateModelview(){
+void XYWnd::updateModelview( bool reconstruct ){
        int nDim1 = ( m_viewType == YZ ) ? 1 : 0;
        int nDim2 = ( m_viewType == XY ) ? 1 : 2;
 
@@ -2230,7 +2249,9 @@ void XYWnd::updateModelview(){
        m_modelview[3] = m_modelview[7] = m_modelview[11] = 0;
        m_modelview[15] = 1;
 
-       m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight );
+       if (reconstruct) {
+               m_view.Construct( m_projection, m_modelview, m_nWidth, m_nHeight );
+       }
 }
 
 /*
index 3842e8f66f1f2d0602c848f96c78e9013c06c6bd..bb9e92ddc8f271613219ba735682d13af48f9856 100644 (file)
@@ -128,6 +128,8 @@ void ZoomIn();
 void ZoomOut();
 void ZoomInWithMouse( int pointx, int pointy );
 
+void Redraw();
+
 void SetActive( bool b ){
        m_bActive = b;
 };
@@ -154,8 +156,8 @@ guint m_chasemouse_handler;
 void ChaseMouse();
 bool chaseMouseMotion( int pointx, int pointy );
 
-void updateModelview();
-void updateProjection();
+void updateModelview(bool reconstruct = true);
+void updateProjection(bool reconstruct = true);
 Matrix4 m_projection;
 Matrix4 m_modelview;
 
diff --git a/setup/apple/.gitignore b/setup/apple/.gitignore
deleted file mode 100644 (file)
index e420ee4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-target/*
diff --git a/setup/apple/Makefile b/setup/apple/Makefile
deleted file mode 100644 (file)
index cf85d97..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-# Makefile for NetRadiant.app, requires http://macdylibbundler.sourceforge.net/
-
-INSTALL = ../../install
-TARGET = target
-RESOURCES = $(TARGET)/NetRadiant.app/Contents/Resources
-BINDIR = $(RESOURCES)/install
-CONFDIR = $(RESOURCES)/etc
-DATADIR = $(RESOURCES)/share
-LIBDIR = $(RESOURCES)/lib
-VERSION = 1.5.0
-DMG = $(TARGET)/NetRadiant-$(VERSION).dmg
-VOLUME_NAME = "NetRadiant $(VERSION)"
-
-# We must rewrite some Gtk configuration files, which vary from environment to
-# environment depending on where you've installed MacPorts. Fun!
-
-MACPORTS_PREFIX := $(shell which port | sed 's:/bin/port::')
-PREFIX_SED_EXPR = "s:$(MACPORTS_PREFIX):@executable_path/..:g"
-
-all: install bundle
-
--pre-install:
-       install -d $(TARGET)
-       cp -r NetRadiant.app $(TARGET)
-       find $(TARGET) -name .turd -delete
-       
--gtk-runtime-gdk-pixbuf-2.0:
-       cp -r $(MACPORTS_PREFIX)/lib/gdk-pixbuf-2.0 $(LIBDIR)
-       find $(LIBDIR)/gdk-pixbuf-2.0 -type f ! -name "*.so" -delete
-       
-       gdk-pixbuf-query-loaders | sed $(PREFIX_SED_EXPR) > \
-               $(CONFDIR)/gtk-2.0/gdk-pixbuf.loaders
-
--gtk-runtime-pango:
-       cp -r $(MACPORTS_PREFIX)/lib/pango $(LIBDIR)
-       find $(LIBDIR)/pango -type f ! -name "*.so" -delete
-       
-       pango-querymodules | sed $(PREFIX_SED_EXPR) > \
-               $(CONFDIR)/pango/pango.modules
-       
--gtk-runtime: -gtk-runtime-gdk-pixbuf-2.0 -gtk-runtime-pango
-       cp -r $(MACPORTS_PREFIX)/lib/gtk-2.0 $(LIBDIR)
-       find $(LIBDIR)/gtk-2.0 -type f ! -name "*.so" -delete   
-       
-       rm -rf $(LIBDIR)/gtk-2.0/{includes,modules}
-       rm -rf $(LIBDIR)/gtk-2.0/*/printbackends
-       
-       cp -r $(MACPORTS_PREFIX)/share/themes/Default $(RESOURCES)/share
-       
-       gtk-query-immodules-2.0 | sed $(PREFIX_SED_EXPR) > \
-               $(CONFDIR)/gtk-2.0/gtk.immodules
-
-install: -pre-install -gtk-runtime
-       cp -r $(INSTALL) $(RESOURCES)
-       #rm -rf `find $(INSTDIR)/installs -type d -name .svn`
-
-bundle:
-       
-       # The Radiant plugins (modules) are a little funky
-       # Some of them are actually linked against the build directory
-       
-       test -L install || ln -s $(INSTALL)
-       
-       dylibbundler -b \
-               -x $(BINDIR)/radiant \
-               -x $(BINDIR)/q2map \
-               -x $(BINDIR)/q3data \
-               -x $(BINDIR)/q3map2 \
-               -x $(BINDIR)/qdata3 \
-               `find $(BINDIR)/modules -name "*.dylib" | xargs -I {} echo -x {}` \
-               `find $(LIBDIR) -name "*.dylib" | xargs -I {} echo -x {}` \
-       -d $(LIBDIR) -of -p @executable_path/../lib
-       
-       rm -f install
-
-image:
-       find $(TARGET) -name .DS_Store -delete
-       ln -f -s /Applications $(TARGET)/Applications
-       hdiutil create -ov $(DMG) -srcfolder $(TARGET) -volname $(VOLUME_NAME)
-       rm $(TARGET)/Applications
-
-clean:
-       rm -rf $(TARGET)/*
diff --git a/setup/apple/NetRadiant.app/Contents/Info.plist b/setup/apple/NetRadiant.app/Contents/Info.plist
deleted file mode 100644 (file)
index 75796b1..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-        <key>CFBundleDevelopmentRegion</key>
-        <string>English</string>
-        <key>CFBundleDisplayName</key>
-        <string>NetRadiant</string>
-        <key>CFBundleExecutable</key>
-        <string>radiant</string>
-        <key>CFBundleIconFile</key>
-        <string>radiant.icns</string>
-        <key>CFBundleIdentifier</key>
-        <string>org.xonotic.netradiant</string>
-        <key>CFBundleName</key>
-        <string>NetRadiant</string>
-        <key>CFBundlePackageType</key>
-        <string>APPL</string>
-        <key>CFBundleShortVersionString</key>
-        <string>1.5.0</string>
-        <key>CFBundleSignature</key>
-        <string>????</string>
-        <key>CFBundleVersion</key>
-        <string>1.5.0</string>
-        <key>LSMinimumSystemVersion</key>
-        <string>10.7</string>
-</dict>
-</plist>
diff --git a/setup/apple/NetRadiant.app/Contents/MacOS/radiant b/setup/apple/NetRadiant.app/Contents/MacOS/radiant
deleted file mode 100755 (executable)
index 701a7fe..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-RADIANT_HOME=$(dirname "$0")
-RADIANT_HOME=${RADIANT_HOME/NetRadiant.app*/NetRadiant.app}
-
-echo
-echo "Starting NetRadiant in ${RADIANT_HOME}"
-echo
-
-set -x
-
-resources="${RADIANT_HOME}/Contents/Resources"
-
-export FONTCONFIG_PATH="${resources}/etc/fonts"
-export FC_DEBUG=1024
-
-export GDK_GL_LIBGL_PATH="${resources}/lib/libGL.1.dylib"
-export GDK_GL_LIBGLU_PATH="${resources}/lib/libGLU.1.dylib"
-
-export GDK_PATH="${resources}"
-export GDK_PIXBUF_MODULE_FILE="${resources}/etc/gtk-2.0/gdk-pixbuf.loaders"
-
-export GOBJECT_PATH="${resources}"
-
-export GTK_DATA_PREFIX="${resources}"
-export GTK_EXE_PREFIX="${resources}"
-export GTK_PATH="${resources}"
-
-export PANGO_SYSCONFDIR="${resources}/etc"
-export PANGO_LIBDIR="${resources}/lib"
-
-cd "${resources}/install"
-./radiant &
-
-set +x
\ No newline at end of file
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/etc/fonts/fonts.conf b/setup/apple/NetRadiant.app/Contents/Resources/etc/fonts/fonts.conf
deleted file mode 100644 (file)
index 7183a4b..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
-<fontconfig>
-
-<!--
-  Adjusted FontConfig for GtkRadiant.app. Include only paths which Mac users
-  will more than likely have.
--->
-
-<!--
-  Font directory list
--->
-       <dir>/usr/X11/lib/X11/fonts</dir>
-       <dir>/Library/Fonts</dir>
-       <dir>/System/Library/Fonts</dir>
-       <dir prefix="xdg">fonts</dir>
-
-<!--
-  Accept deprecated 'mono' alias, replacing it with 'monospace'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>mono</string>
-               </test>
-               <edit name="family" mode="assign" binding="same">
-                       <string>monospace</string>
-               </edit>
-       </match>
-
-<!--
-  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>sans serif</string>
-               </test>
-               <edit name="family" mode="assign" binding="same">
-                       <string>sans-serif</string>
-               </edit>
-       </match>
-
-<!--
-  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
--->
-       <match target="pattern">
-               <test qual="any" name="family">
-                       <string>sans</string>
-               </test>
-               <edit name="family" mode="assign" binding="same">
-                       <string>sans-serif</string>
-               </edit>
-       </match>
-
-<!-- Font cache directory list -->
-       <cachedir prefix="xdg">fontconfig</cachedir>
-
-       <config>
-<!--
-  These are the default Unicode chars that are expected to be blank
-  in fonts.  All other blank chars are assumed to be broken and
-  won't appear in the resulting charsets
- -->
-               <blank>
-                       <int>0x0020</int>       <!-- SPACE -->
-                       <int>0x00A0</int>       <!-- NO-BREAK SPACE -->
-                       <int>0x00AD</int>       <!-- SOFT HYPHEN -->
-                       <int>0x034F</int>       <!-- COMBINING GRAPHEME JOINER -->
-                       <int>0x0600</int>       <!-- ARABIC NUMBER SIGN -->
-                       <int>0x0601</int>       <!-- ARABIC SIGN SANAH -->
-                       <int>0x0602</int>       <!-- ARABIC FOOTNOTE MARKER -->
-                       <int>0x0603</int>       <!-- ARABIC SIGN SAFHA -->
-                       <int>0x06DD</int>       <!-- ARABIC END OF AYAH -->
-                       <int>0x070F</int>       <!-- SYRIAC ABBREVIATION MARK -->
-                       <int>0x115F</int>       <!-- HANGUL CHOSEONG FILLER -->
-                       <int>0x1160</int>       <!-- HANGUL JUNGSEONG FILLER -->
-                       <int>0x1680</int>       <!-- OGHAM SPACE MARK -->
-                       <int>0x17B4</int>       <!-- KHMER VOWEL INHERENT AQ -->
-                       <int>0x17B5</int>       <!-- KHMER VOWEL INHERENT AA -->
-                       <int>0x180E</int>       <!-- MONGOLIAN VOWEL SEPARATOR -->
-                       <int>0x2000</int>       <!-- EN QUAD -->
-                       <int>0x2001</int>       <!-- EM QUAD -->
-                       <int>0x2002</int>       <!-- EN SPACE -->
-                       <int>0x2003</int>       <!-- EM SPACE -->
-                       <int>0x2004</int>       <!-- THREE-PER-EM SPACE -->
-                       <int>0x2005</int>       <!-- FOUR-PER-EM SPACE -->
-                       <int>0x2006</int>       <!-- SIX-PER-EM SPACE -->
-                       <int>0x2007</int>       <!-- FIGURE SPACE -->
-                       <int>0x2008</int>       <!-- PUNCTUATION SPACE -->
-                       <int>0x2009</int>       <!-- THIN SPACE -->
-                       <int>0x200A</int>       <!-- HAIR SPACE -->
-                       <int>0x200B</int>       <!-- ZERO WIDTH SPACE -->
-                       <int>0x200C</int>       <!-- ZERO WIDTH NON-JOINER -->
-                       <int>0x200D</int>       <!-- ZERO WIDTH JOINER -->
-                       <int>0x200E</int>       <!-- LEFT-TO-RIGHT MARK -->
-                       <int>0x200F</int>       <!-- RIGHT-TO-LEFT MARK -->
-                       <int>0x2028</int>       <!-- LINE SEPARATOR -->
-                       <int>0x2029</int>       <!-- PARAGRAPH SEPARATOR -->
-                       <int>0x202A</int>       <!-- LEFT-TO-RIGHT EMBEDDING -->
-                       <int>0x202B</int>       <!-- RIGHT-TO-LEFT EMBEDDING -->
-                       <int>0x202C</int>       <!-- POP DIRECTIONAL FORMATTING -->
-                       <int>0x202D</int>       <!-- LEFT-TO-RIGHT OVERRIDE -->
-                       <int>0x202E</int>       <!-- RIGHT-TO-LEFT OVERRIDE -->
-                       <int>0x202F</int>       <!-- NARROW NO-BREAK SPACE -->
-                       <int>0x205F</int>       <!-- MEDIUM MATHEMATICAL SPACE -->
-                       <int>0x2060</int>       <!-- WORD JOINER -->
-                       <int>0x2061</int>       <!-- FUNCTION APPLICATION -->
-                       <int>0x2062</int>       <!-- INVISIBLE TIMES -->
-                       <int>0x2063</int>       <!-- INVISIBLE SEPARATOR -->
-                       <int>0x206A</int>       <!-- INHIBIT SYMMETRIC SWAPPING -->
-                       <int>0x206B</int>       <!-- ACTIVATE SYMMETRIC SWAPPING -->
-                       <int>0x206C</int>       <!-- INHIBIT ARABIC FORM SHAPING -->
-                       <int>0x206D</int>       <!-- ACTIVATE ARABIC FORM SHAPING -->
-                       <int>0x206E</int>       <!-- NATIONAL DIGIT SHAPES -->
-                       <int>0x206F</int>       <!-- NOMINAL DIGIT SHAPES -->
-                       <int>0x2800</int>       <!-- BRAILLE PATTERN BLANK -->
-                       <int>0x3000</int>       <!-- IDEOGRAPHIC SPACE -->
-                       <int>0x3164</int>       <!-- HANGUL FILLER -->
-                       <int>0xFEFF</int>       <!-- ZERO WIDTH NO-BREAK SPACE -->
-                       <int>0xFFA0</int>       <!-- HALFWIDTH HANGUL FILLER -->
-                       <int>0xFFF9</int>       <!-- INTERLINEAR ANNOTATION ANCHOR -->
-                       <int>0xFFFA</int>       <!-- INTERLINEAR ANNOTATION SEPARATOR -->
-                       <int>0xFFFB</int>       <!-- INTERLINEAR ANNOTATION TERMINATOR -->
-               </blank>
-<!--
-  Rescan configuration every 30 seconds when FcFontSetList is called
- -->
-               <rescan>
-                       <int>30</int>
-               </rescan>
-       </config>
-
-</fontconfig>
-
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/etc/gtk-2.0/gtkrc b/setup/apple/NetRadiant.app/Contents/Resources/etc/gtk-2.0/gtkrc
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/etc/pango/pangorc b/setup/apple/NetRadiant.app/Contents/Resources/etc/pango/pangorc
deleted file mode 100644 (file)
index f56d343..0000000
+++ /dev/null
@@ -1 +0,0 @@
-[Pango]
\ No newline at end of file
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/lib/.turd b/setup/apple/NetRadiant.app/Contents/Resources/lib/.turd
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/radiant.icns b/setup/apple/NetRadiant.app/Contents/Resources/radiant.icns
deleted file mode 100644 (file)
index 339e718..0000000
Binary files a/setup/apple/NetRadiant.app/Contents/Resources/radiant.icns and /dev/null differ
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/icons/.turd b/setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/icons/.turd
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/themes/.turd b/setup/apple/NetRadiant.app/Contents/Resources/share/gtk-2.0/themes/.turd
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/setup/apple/README.md b/setup/apple/README.md
deleted file mode 100644 (file)
index 069cf3d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-NetRadiant for Apple OS X
-========================
-
-This directory provides packaging steps for NetRadiant for OS X. This document describes compiling the application on OSX as well as generating distributable bundles using the framework provided in this directory.
-
-Dependencies & Compilation
---------------------------
-
-Directions for OS X Yosemite 10.10 - your mileage may vary:
-
-- Install [MacPorts](http://macports.org).
-- Install [XQuartz](http://xquartz.macosforge.org/)
-
-- Install dependencies with MacPorts:
-
-```
-sudo port install dylibbundler pkgconfig gtkglext
-```
-
-- Get the NetRadiant code and compile:
-
-```
-git clone https://gitlab.com/xonotic/netradiant.git
-cd netradiant/
-make
-```
-
-- Run the build:
-
-(from the netradiant/ directory)
-```
-./install/radiant
-```
-
-XQuartz note: on my configuration XQuartz doesn't automatically start for some reason. I have to open another terminal, and run the following command: `/Applications/Utilities/XQuartz.app/Contents/MacOS/X11.bin`, then start radiant. 
-    
-Building NetRadiant.app
------------------------
-
-The `Makefile` in the 'setup/apple/' directory will produce a distributable .app bundle for NetRadiant using `dylibbundler`:
-
-```
-make
-make image
-```
-
-Getting help
-------------
-
-IRC: Quakenet #xonotic, or post something on the issue tracker..
diff --git a/setup/data/tools/bitmaps/window5.png b/setup/data/tools/bitmaps/window5.png
new file mode 100644 (file)
index 0000000..24335a5
Binary files /dev/null and b/setup/data/tools/bitmaps/window5.png differ
index 4b6d0343f124f42a2b7ec31e315865a1f3b84ce7..f4dcd469b913230152982c41c5a2c2405ba26858 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
 <!-- generated by Radiant setup, modify at your own risks -->
 <links>
-<item name="NetRadiant website" url="https://gitlab.com/xonotic/netradiant"/>
-<item name="q3map2 handbook" url="http://q3map2.everyonelookbusy.net/shader_manual/"/>
+<item name="NetRadiant website" url="https://netradiant.gitlab.io"/>
+<item name="q3map2 handbook" url="http://q3map2.robotrenegade.com/docs/shader_manual/"/>
 <item name="q3map2 wikibook" url="https://en.wikibooks.org/wiki/Q3Map2"/>
 </links>
diff --git a/setup/macos/Contents/Info.plist b/setup/macos/Contents/Info.plist
new file mode 100644 (file)
index 0000000..0f6066e
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundlePackageType</key>
+       <string>APPL</string>
+       <key>CFBundleName</key>
+       <string>NetRadiant</string>
+       <key>CFBundleDisplayName</key>
+       <string>NetRadiant</string>
+       <key>CFBundleIdentifier</key>
+       <string>org.xonotic.netradiant</string>
+       <key>CFBundleExecutable</key>
+       <string>NetRadiant</string>
+       <key>CFBundleIconFile</key>
+       <string>netradiant.icns</string>
+       <key>CFBundleShortVersionString</key>
+       <string>1.5.0</string>
+       <key>CFBundleVersion</key>
+       <string>1.5.0</string>
+       <key>CFBundleDevelopmentRegion</key>
+       <string>English</string>
+       <key>CFBundleSignature</key>
+       <string>????</string>
+       <key>CFBundleTypeExtensions</key>
+       <array>
+               <string>map</string>
+       </array>
+       <key>NSHighResolutionCapable</key>
+       <true/>
+       <key>LSMinimumSystemVersion</key>
+       <string>10.7</string>
+</dict>
+</plist>
diff --git a/setup/macos/Contents/Resources/netradiant.icns b/setup/macos/Contents/Resources/netradiant.icns
new file mode 100644 (file)
index 0000000..339e718
Binary files /dev/null and b/setup/macos/Contents/Resources/netradiant.icns differ
diff --git a/setup/macos/NetRadiant b/setup/macos/NetRadiant
new file mode 100755 (executable)
index 0000000..21933a1
--- /dev/null
@@ -0,0 +1,57 @@
+#! /usr/bin/env bash
+
+set -o physical
+
+script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+
+bundle_dir="$(cd "${script_dir}/../Prefix"; pwd)"
+
+echo "Starting NetRadiant in ${bundle_dir}"
+
+cd "${bundle_dir}"
+
+export FC_DEBUG=1024
+
+# if bundled
+if [ -d "${bundle_dir}/share/icons/hicolor" ]
+then
+       export FONTCONFIG_PATH="${bundle_dir}/etc/fonts"
+
+       # export GDK_GL_LIBGL_PATH="${bundle_dir}/lib/libGL.1.dylib"
+       # export GDK_GL_LIBGLU_PATH="${bundle_dir}/lib/libGLU.1.dylib"
+
+       export GDK_PATH="${bundle_dir}"
+
+       export GDK_PIXBUF_MODULE_FILE="${bundle_dir}/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
+
+       export GTK_IM_MODULE_FILE="${bundle_dir}/lib/gtk-2.0/2.10.0/immodules.cache"
+
+       export GOBJECT_PATH="${bundle_dir}"
+
+       export GTK_DATA_PREFIX="${bundle_dir}"
+       export GTK_EXE_PREFIX="${bundle_dir}"
+       export GTK_PATH="${bundle_dir}"
+fi
+
+if [ "$(defaults read -g AppleInterfaceStyle 2>/dev/null)" = 'Dark' ]
+then
+       color='dark'
+else
+       color='light'
+fi
+
+gtkrc_file="${bundle_dir}/share/themes/Mojave-${color}/gtk-2.0/gtkrc"
+
+if [ -f "${gtkrc_file}" ]
+then
+       export GTK2_RC_FILES="${gtkrc_file}"
+fi
+
+if [ "${1}" = '--debug' ]
+then
+       shift
+       export PATH="/usr/bin:${PATH}"
+       exec lldb ./netradiant "${@}"
+else
+       exec ./netradiant "${@}"
+fi
index 1fcce20fdd8c4161d8d12cb67b355c0846637b45..6e30389c35107adcb53c9e16d403b8fc51868aa2 100644 (file)
@@ -1,3 +1,10 @@
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
 
+add_subdirectory(quake2)
+add_subdirectory(heretic2)
 add_subdirectory(quake3)
+
+add_custom_target(tools)
+add_dependencies(tools quake2 heretic2 quake3)
+
+add_subdirectory(unvanquished)
diff --git a/tools/heretic2/CMakeLists.txt b/tools/heretic2/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2a9f098
--- /dev/null
@@ -0,0 +1,73 @@
+include_directories(BEFORE h2data common qcommon)
+
+find_package(OpenGL REQUIRED)
+
+find_package(LibXml2 REQUIRED)
+include_directories(${LIBXML2_INCLUDE_DIR})
+
+radiant_tool(h2data
+    h2data/h2data.rc
+
+    common/bspfile.c common/bspfile.h
+    common/cmdlib.c common/cmdlib.h
+    common/inout.c common/inout.h
+    common/l3dslib.c common/l3dslib.h
+    common/lbmlib.c common/lbmlib.h
+    common/mathlib.c common/mathlib.h
+    common/md4.c common/md4.h
+    common/path_init.c
+    common/polylib.c common/polylib.h
+    common/qfiles.c common/qfiles.h
+    common/scriplib.c common/scriplib.h
+    common/threads.c common/her2_threads.h
+    common/token.c common/token.h
+    common/trilib.c common/trilib.h
+
+    qcommon/angles.h
+    qcommon/arrayedlist.h
+    qcommon/flex.h
+    qcommon/fmodel.h
+    qcommon/h2common.h
+    qcommon/placement.h
+    qcommon/qfiles.h
+    qcommon/q_typedef.h
+    qcommon/reference.c qcommon/reference.h
+    qcommon/resourcemanager.c qcommon/resourcemanager.h
+    qcommon/skeletons.c qcommon/skeletons.h
+
+    h2data/adpcm.h
+    h2data/animcomp.c h2data/animcomp.h 
+    h2data/anorms.h
+    h2data/book.c
+    h2data/fmodels.c h2data/qd_fmodel.h
+    h2data/images.c
+    h2data/jointed.c
+    h2data/jointed.h
+    h2data/joints.h
+    h2data/models.c
+    h2data/pics.c
+    h2data/qdata.c h2data/qdata.h
+    h2data/qd_skeletons.c h2data/qd_skeletons.h
+    h2data/resource.h
+    h2data/sprites.c
+    h2data/svdcmp.c
+    h2data/tables.c
+    h2data/tmix.c
+    h2data/video.c
+)
+
+target_compile_definitions(h2data
+    PRIVATE
+)
+
+target_link_libraries(h2data
+    ${LIBXML2_LIBRARIES}
+    l_net
+)
+
+add_custom_target(heretic2)
+add_dependencies(heretic2 h2data q2map)
+
+if (UNIX)
+    target_link_libraries(h2data pthread m)
+endif ()
diff --git a/tools/heretic2/common/bspfile.c b/tools/heretic2/common/bspfile.c
new file mode 100644 (file)
index 0000000..add0ef3
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "bspfile.h"
+#include "scriplib.h"
+
+void GetLeafNums( void );
+
+//=============================================================================
+
+int nummodels;
+dmodel_t dmodels[MAX_MAP_MODELS];
+
+int visdatasize;
+byte dvisdata[MAX_MAP_VISIBILITY];
+dvis_t      *dvis = (dvis_t *)dvisdata;
+
+int lightdatasize;
+byte dlightdata[MAX_MAP_LIGHTING];
+
+int entdatasize;
+char dentdata[MAX_MAP_ENTSTRING];
+
+int numleafs;
+dleaf_t dleafs[MAX_MAP_LEAFS];
+
+int numplanes;
+dplane_t dplanes[MAX_MAP_PLANES];
+
+int numvertexes;
+dvertex_t dvertexes[MAX_MAP_VERTS];
+
+int numnodes;
+dnode_t dnodes[MAX_MAP_NODES];
+
+int numtexinfo;
+texinfo_t texinfo[MAX_MAP_TEXINFO];
+
+int numfaces;
+dface_t dfaces[MAX_MAP_FACES];
+
+int numedges;
+dedge_t dedges[MAX_MAP_EDGES];
+
+int numleaffaces;
+unsigned short dleaffaces[MAX_MAP_LEAFFACES];
+
+int numleafbrushes;
+unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+int numsurfedges;
+int dsurfedges[MAX_MAP_SURFEDGES];
+
+int numbrushes;
+dbrush_t dbrushes[MAX_MAP_BRUSHES];
+
+int numbrushsides;
+dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
+
+int numareas;
+darea_t dareas[MAX_MAP_AREAS];
+
+int numareaportals;
+dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
+
+byte dpop[256];
+
+/*
+   ===============
+   CompressVis
+
+   ===============
+ */
+int CompressVis( byte *vis, byte *dest ){
+       int j;
+       int rep;
+       int visrow;
+       byte    *dest_p;
+
+       dest_p = dest;
+//     visrow = (r_numvisleafs + 7)>>3;
+       visrow = ( dvis->numclusters + 7 ) >> 3;
+
+       for ( j = 0 ; j < visrow ; j++ )
+       {
+               *dest_p++ = vis[j];
+               if ( vis[j] ) {
+                       continue;
+               }
+
+               rep = 1;
+               for ( j++; j < visrow ; j++ )
+                       if ( vis[j] || rep == 255 ) {
+                               break;
+                       }
+                       else{
+                               rep++;
+                       }
+               *dest_p++ = rep;
+               j--;
+       }
+
+       return dest_p - dest;
+}
+
+
+/*
+   ===================
+   DecompressVis
+   ===================
+ */
+void DecompressVis( byte *in, byte *decompressed ){
+       int c;
+       byte    *out;
+       int row;
+
+//     row = (r_numvisleafs+7)>>3;
+       row = ( dvis->numclusters + 7 ) >> 3;
+       out = decompressed;
+
+       do
+       {
+               if ( *in ) {
+                       *out++ = *in++;
+                       continue;
+               }
+
+               c = in[1];
+               if ( !c ) {
+                       Error( "DecompressVis: 0 repeat" );
+               }
+               in += 2;
+               while ( c )
+               {
+                       *out++ = 0;
+                       c--;
+               }
+       } while ( out - decompressed < row );
+}
+
+//=============================================================================
+
+/*
+   =============
+   SwapBSPFile
+
+   Byte swaps all data in a bsp file.
+   =============
+ */
+void SwapBSPFile( qboolean todisk ){
+       int i, j;
+       dmodel_t        *d;
+
+
+// models
+       for ( i = 0 ; i < nummodels ; i++ )
+       {
+               d = &dmodels[i];
+
+               d->firstface = LittleLong( d->firstface );
+               d->numfaces = LittleLong( d->numfaces );
+               d->headnode = LittleLong( d->headnode );
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       d->mins[j] = LittleFloat( d->mins[j] );
+                       d->maxs[j] = LittleFloat( d->maxs[j] );
+                       d->origin[j] = LittleFloat( d->origin[j] );
+               }
+       }
+
+//
+// vertexes
+//
+       for ( i = 0 ; i < numvertexes ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+                       dvertexes[i].point[j] = LittleFloat( dvertexes[i].point[j] );
+       }
+
+//
+// planes
+//
+       for ( i = 0 ; i < numplanes ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+                       dplanes[i].normal[j] = LittleFloat( dplanes[i].normal[j] );
+               dplanes[i].dist = LittleFloat( dplanes[i].dist );
+               dplanes[i].type = LittleLong( dplanes[i].type );
+       }
+
+//
+// texinfos
+//
+       for ( i = 0 ; i < numtexinfo ; i++ )
+       {
+               for ( j = 0 ; j < 8 ; j++ )
+                       texinfo[i].vecs[0][j] = LittleFloat( texinfo[i].vecs[0][j] );
+               texinfo[i].flags = LittleLong( texinfo[i].flags );
+               texinfo[i].value = LittleLong( texinfo[i].value );
+               texinfo[i].nexttexinfo = LittleLong( texinfo[i].nexttexinfo );
+       }
+
+//
+// faces
+//
+       for ( i = 0 ; i < numfaces ; i++ )
+       {
+               dfaces[i].texinfo = LittleShort( dfaces[i].texinfo );
+               dfaces[i].planenum = LittleShort( dfaces[i].planenum );
+               dfaces[i].side = LittleShort( dfaces[i].side );
+               dfaces[i].lighting.c = LittleLong( dfaces[i].lighting.c );
+               dfaces[i].lightofs = LittleLong( dfaces[i].lightofs );
+               dfaces[i].firstedge = LittleLong( dfaces[i].firstedge );
+               dfaces[i].numedges = LittleShort( dfaces[i].numedges );
+       }
+
+//
+// nodes
+//
+       for ( i = 0 ; i < numnodes ; i++ )
+       {
+               dnodes[i].planenum = LittleLong( dnodes[i].planenum );
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       dnodes[i].mins[j] = LittleShort( dnodes[i].mins[j] );
+                       dnodes[i].maxs[j] = LittleShort( dnodes[i].maxs[j] );
+               }
+               dnodes[i].children[0] = LittleLong( dnodes[i].children[0] );
+               dnodes[i].children[1] = LittleLong( dnodes[i].children[1] );
+               dnodes[i].firstface = LittleShort( dnodes[i].firstface );
+               dnodes[i].numfaces = LittleShort( dnodes[i].numfaces );
+       }
+
+//
+// leafs
+//
+       for ( i = 0 ; i < numleafs ; i++ )
+       {
+               dleafs[i].contents = LittleLong( dleafs[i].contents );
+               dleafs[i].cluster = LittleShort( dleafs[i].cluster );
+               dleafs[i].area = LittleShort( dleafs[i].area );
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       dleafs[i].mins[j] = LittleShort( dleafs[i].mins[j] );
+                       dleafs[i].maxs[j] = LittleShort( dleafs[i].maxs[j] );
+               }
+
+               dleafs[i].firstleafface = LittleShort( dleafs[i].firstleafface );
+               dleafs[i].numleaffaces = LittleShort( dleafs[i].numleaffaces );
+               dleafs[i].firstleafbrush = LittleShort( dleafs[i].firstleafbrush );
+               dleafs[i].numleafbrushes = LittleShort( dleafs[i].numleafbrushes );
+       }
+
+//
+// leaffaces
+//
+       for ( i = 0 ; i < numleaffaces ; i++ )
+               dleaffaces[i] = LittleShort( dleaffaces[i] );
+
+//
+// leafbrushes
+//
+       for ( i = 0 ; i < numleafbrushes ; i++ )
+               dleafbrushes[i] = LittleShort( dleafbrushes[i] );
+
+//
+// surfedges
+//
+       for ( i = 0 ; i < numsurfedges ; i++ )
+               dsurfedges[i] = LittleLong( dsurfedges[i] );
+
+//
+// edges
+//
+       for ( i = 0 ; i < numedges ; i++ )
+       {
+               dedges[i].v[0] = LittleShort( dedges[i].v[0] );
+               dedges[i].v[1] = LittleShort( dedges[i].v[1] );
+       }
+
+//
+// brushes
+//
+       for ( i = 0 ; i < numbrushes ; i++ )
+       {
+               dbrushes[i].firstside = LittleLong( dbrushes[i].firstside );
+               dbrushes[i].numsides = LittleLong( dbrushes[i].numsides );
+               dbrushes[i].contents = LittleLong( dbrushes[i].contents );
+       }
+
+//
+// areas
+//
+       for ( i = 0 ; i < numareas ; i++ )
+       {
+               dareas[i].numareaportals = LittleLong( dareas[i].numareaportals );
+               dareas[i].firstareaportal = LittleLong( dareas[i].firstareaportal );
+       }
+
+//
+// areasportals
+//
+       for ( i = 0 ; i < numareaportals ; i++ )
+       {
+               dareaportals[i].portalnum = LittleLong( dareaportals[i].portalnum );
+               dareaportals[i].otherarea = LittleLong( dareaportals[i].otherarea );
+       }
+
+//
+// brushsides
+//
+       for ( i = 0 ; i < numbrushsides ; i++ )
+       {
+               dbrushsides[i].planenum = LittleShort( dbrushsides[i].planenum );
+               dbrushsides[i].texinfo = LittleShort( dbrushsides[i].texinfo );
+       }
+
+//
+// visibility
+//
+       if ( todisk ) {
+               j = dvis->numclusters;
+       }
+       else{
+               j = LittleLong( dvis->numclusters );
+       }
+       dvis->numclusters = LittleLong( dvis->numclusters );
+       for ( i = 0 ; i < j ; i++ )
+       {
+               dvis->bitofs[i][0] = LittleLong( dvis->bitofs[i][0] );
+               dvis->bitofs[i][1] = LittleLong( dvis->bitofs[i][1] );
+       }
+}
+
+
+dheader_t   *header;
+
+int CopyLump( int lump, void *dest, int size ){
+       int length, ofs;
+
+       length = header->lumps[lump].filelen;
+       ofs = header->lumps[lump].fileofs;
+
+       if ( length % size ) {
+               Error( "LoadBSPFile: odd lump size" );
+       }
+
+       memcpy( dest, (byte *)header + ofs, length );
+
+       return length / size;
+}
+
+/*
+   =============
+   LoadBSPFile
+   =============
+ */
+void    LoadBSPFile( char *filename ){
+       int i;
+
+//
+// load the file header
+//
+       LoadFile( filename, (void **)&header );
+
+// swap the header
+       for ( i = 0 ; i < sizeof( dheader_t ) / 4 ; i++ )
+               ( (int *)header )[i] = LittleLong( ( (int *)header )[i] );
+
+       if ( header->ident != IDBSPHEADER ) {
+               Error( "%s is not a IBSP file", filename );
+       }
+       if ( header->version != BSPVERSION ) {
+               Error( "%s is version %i, not %i", filename, header->version, BSPVERSION );
+       }
+
+       nummodels = CopyLump( LUMP_MODELS, dmodels, sizeof( dmodel_t ) );
+       numvertexes = CopyLump( LUMP_VERTEXES, dvertexes, sizeof( dvertex_t ) );
+       numplanes = CopyLump( LUMP_PLANES, dplanes, sizeof( dplane_t ) );
+       numleafs = CopyLump( LUMP_LEAFS, dleafs, sizeof( dleaf_t ) );
+       numnodes = CopyLump( LUMP_NODES, dnodes, sizeof( dnode_t ) );
+       numtexinfo = CopyLump( LUMP_TEXINFO, texinfo, sizeof( texinfo_t ) );
+       numfaces = CopyLump( LUMP_FACES, dfaces, sizeof( dface_t ) );
+       numleaffaces = CopyLump( LUMP_LEAFFACES, dleaffaces, sizeof( dleaffaces[0] ) );
+       numleafbrushes = CopyLump( LUMP_LEAFBRUSHES, dleafbrushes, sizeof( dleafbrushes[0] ) );
+       numsurfedges = CopyLump( LUMP_SURFEDGES, dsurfedges, sizeof( dsurfedges[0] ) );
+       numedges = CopyLump( LUMP_EDGES, dedges, sizeof( dedge_t ) );
+       numbrushes = CopyLump( LUMP_BRUSHES, dbrushes, sizeof( dbrush_t ) );
+       numbrushsides = CopyLump( LUMP_BRUSHSIDES, dbrushsides, sizeof( dbrushside_t ) );
+       numareas = CopyLump( LUMP_AREAS, dareas, sizeof( darea_t ) );
+       numareaportals = CopyLump( LUMP_AREAPORTALS, dareaportals, sizeof( dareaportal_t ) );
+
+       visdatasize = CopyLump( LUMP_VISIBILITY, dvisdata, 1 );
+       lightdatasize = CopyLump( LUMP_LIGHTING, dlightdata, 1 );
+       entdatasize = CopyLump( LUMP_ENTITIES, dentdata, 1 );
+
+       CopyLump( LUMP_POP, dpop, 1 );
+
+       free( header );      // everything has been copied out
+
+//
+// swap everything
+//
+       SwapBSPFile( false );
+}
+
+
+/*
+   =============
+   LoadBSPFileTexinfo
+
+   Only loads the texinfo lump, so qdata can scan for textures
+   =============
+ */
+void    LoadBSPFileTexinfo( char *filename ){
+       int i;
+       FILE        *f;
+       int length, ofs;
+
+       header = malloc( sizeof( dheader_t ) );
+
+       f = fopen( filename, "rb" );
+       fread( header, sizeof( dheader_t ), 1, f );
+
+// swap the header
+       for ( i = 0 ; i < sizeof( dheader_t ) / 4 ; i++ )
+               ( (int *)header )[i] = LittleLong( ( (int *)header )[i] );
+
+       if ( header->ident != IDBSPHEADER ) {
+               Error( "%s is not a IBSP file", filename );
+       }
+       if ( header->version != BSPVERSION ) {
+               Error( "%s is version %i, not %i", filename, header->version, BSPVERSION );
+       }
+
+
+       length = header->lumps[LUMP_TEXINFO].filelen;
+       ofs = header->lumps[LUMP_TEXINFO].fileofs;
+
+       fseek( f, ofs, SEEK_SET );
+       fread( texinfo, length, 1, f );
+       fclose( f );
+
+       numtexinfo = length / sizeof( texinfo_t );
+
+       free( header );      // everything has been copied out
+
+       SwapBSPFile( false );
+}
+
+
+//============================================================================
+
+FILE        *wadfile;
+dheader_t outheader;
+
+void AddLump( int lumpnum, void *data, int len ){
+       lump_t *lump;
+
+       lump = &header->lumps[lumpnum];
+
+       lump->fileofs = LittleLong( ftell( wadfile ) );
+       lump->filelen = LittleLong( len );
+       SafeWrite( wadfile, data, ( len + 3 ) & ~3 );
+}
+
+/*
+   =============
+   WriteBSPFile
+
+   Swaps the bsp file in place, so it should not be referenced again
+   =============
+ */
+void    WriteBSPFile( char *filename ){
+       header = &outheader;
+       memset( header, 0, sizeof( dheader_t ) );
+
+       SwapBSPFile( true );
+
+       header->ident = LittleLong( IDBSPHEADER );
+       header->version = LittleLong( BSPVERSION );
+
+       wadfile = SafeOpenWrite( filename );
+       SafeWrite( wadfile, header, sizeof( dheader_t ) ); // overwritten later
+
+       AddLump( LUMP_PLANES, dplanes, numplanes * sizeof( dplane_t ) );
+       AddLump( LUMP_LEAFS, dleafs, numleafs * sizeof( dleaf_t ) );
+       AddLump( LUMP_VERTEXES, dvertexes, numvertexes * sizeof( dvertex_t ) );
+       AddLump( LUMP_NODES, dnodes, numnodes * sizeof( dnode_t ) );
+       AddLump( LUMP_TEXINFO, texinfo, numtexinfo * sizeof( texinfo_t ) );
+       AddLump( LUMP_FACES, dfaces, numfaces * sizeof( dface_t ) );
+       AddLump( LUMP_BRUSHES, dbrushes, numbrushes * sizeof( dbrush_t ) );
+       AddLump( LUMP_BRUSHSIDES, dbrushsides, numbrushsides * sizeof( dbrushside_t ) );
+       AddLump( LUMP_LEAFFACES, dleaffaces, numleaffaces * sizeof( dleaffaces[0] ) );
+       AddLump( LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
+       AddLump( LUMP_SURFEDGES, dsurfedges, numsurfedges * sizeof( dsurfedges[0] ) );
+       AddLump( LUMP_EDGES, dedges, numedges * sizeof( dedge_t ) );
+       AddLump( LUMP_MODELS, dmodels, nummodels * sizeof( dmodel_t ) );
+       AddLump( LUMP_AREAS, dareas, numareas * sizeof( darea_t ) );
+       AddLump( LUMP_AREAPORTALS, dareaportals, numareaportals * sizeof( dareaportal_t ) );
+
+       AddLump( LUMP_LIGHTING, dlightdata, lightdatasize );
+       AddLump( LUMP_VISIBILITY, dvisdata, visdatasize );
+       AddLump( LUMP_ENTITIES, dentdata, entdatasize );
+       AddLump( LUMP_POP, dpop, sizeof( dpop ) );
+
+       fseek( wadfile, 0, SEEK_SET );
+       SafeWrite( wadfile, header, sizeof( dheader_t ) );
+       fclose( wadfile );
+}
+
+//============================================================================
+
+/*
+   =============
+   PrintBSPFileSizes
+
+   Dumps info about current file
+   =============
+ */
+void PrintBSPFileSizes( void ){
+       if ( !num_entities ) {
+               ParseEntities();
+       }
+
+       printf( "%5i models       %7i\n"
+                       ,nummodels, (int)( nummodels * sizeof( dmodel_t ) ) );
+       printf( "%5i brushes      %7i\n"
+                       ,numbrushes, (int)( numbrushes * sizeof( dbrush_t ) ) );
+       printf( "%5i brushsides   %7i\n"
+                       ,numbrushsides, (int)( numbrushsides * sizeof( dbrushside_t ) ) );
+       printf( "%5i planes       %7i\n"
+                       ,numplanes, (int)( numplanes * sizeof( dplane_t ) ) );
+       printf( "%5i texinfo      %7i\n"
+                       ,numtexinfo, (int)( numtexinfo * sizeof( texinfo_t ) ) );
+       printf( "%5i entdata      %7i\n", num_entities, entdatasize );
+
+       printf( "\n" );
+
+       printf( "%5i vertexes     %7i\n"
+                       ,numvertexes, (int)( numvertexes * sizeof( dvertex_t ) ) );
+       printf( "%5i nodes        %7i\n"
+                       ,numnodes, (int)( numnodes * sizeof( dnode_t ) ) );
+       printf( "%5i faces        %7i\n"
+                       ,numfaces, (int)( numfaces * sizeof( dface_t ) ) );
+       printf( "%5i leafs        %7i\n"
+                       ,numleafs, (int)( numleafs * sizeof( dleaf_t ) ) );
+       printf( "%5i leaffaces    %7i\n"
+                       ,numleaffaces, (int)( numleaffaces * sizeof( dleaffaces[0] ) ) );
+       printf( "%5i leafbrushes  %7i\n"
+                       ,numleafbrushes, (int)( numleafbrushes * sizeof( dleafbrushes[0] ) ) );
+       printf( "%5i surfedges    %7i\n"
+                       ,numsurfedges, (int)( numsurfedges * sizeof( dsurfedges[0] ) ) );
+       printf( "%5i edges        %7i\n"
+                       ,numedges, (int)( numedges * sizeof( dedge_t ) ) );
+       printf( "      lightdata    %7i\n", lightdatasize );
+       printf( "      visdata      %7i\n", visdatasize );
+}
+
+
+//============================================
+
+int num_entities;
+entity_t entities[MAX_MAP_ENTITIES];
+
+void StripTrailing( char *e ){
+       char    *s;
+
+       s = e + strlen( e ) - 1;
+       while ( s >= e && *s <= 32 )
+       {
+               *s = 0;
+               s--;
+       }
+}
+
+/*
+   =================
+   ParseEpair
+   =================
+ */
+epair_t *ParseEpair( void ){
+       epair_t *e;
+
+       e = malloc( sizeof( epair_t ) );
+       memset( e, 0, sizeof( epair_t ) );
+
+       if ( strlen( token ) >= MAX_KEY - 1 ) {
+               Error( "ParseEpar: token too long" );
+       }
+       e->key = copystring( token );
+       GetScriptToken( false );
+       if ( strlen( token ) >= MAX_VALUE - 1 ) {
+               Error( "ParseEpar: token too long" );
+       }
+       e->value = copystring( token );
+
+       // strip trailing spaces
+       StripTrailing( e->key );
+       StripTrailing( e->value );
+
+       return e;
+}
+
+
+/*
+   ================
+   ParseEntity
+   ================
+ */
+qboolean    ParseEntity( void ){
+       epair_t     *e;
+       entity_t    *mapent;
+
+       if ( !GetScriptToken( true ) ) {
+               return false;
+       }
+
+       if ( strcmp( token, "{" ) ) {
+               Error( "ParseEntity: { not found" );
+       }
+
+       if ( num_entities == MAX_MAP_ENTITIES ) {
+               Error( "num_entities == MAX_MAP_ENTITIES" );
+       }
+
+       mapent = &entities[num_entities];
+       num_entities++;
+
+       do
+       {
+               if ( !GetScriptToken( true ) ) {
+                       Error( "ParseEntity: EOF without closing brace" );
+               }
+               if ( !strcmp( token, "}" ) ) {
+                       break;
+               }
+               e = ParseEpair();
+               e->next = mapent->epairs;
+               mapent->epairs = e;
+       } while ( 1 );
+
+       return true;
+}
+
+/*
+   ================
+   ParseEntities
+
+   Parses the dentdata string into entities
+   ================
+ */
+void ParseEntities( void ){
+       num_entities = 0;
+       ParseFromMemory( dentdata, entdatasize );
+
+       while ( ParseEntity() )
+       {
+       }
+}
+
+
+/*
+   ================
+   UnparseEntities
+
+   Generates the dentdata string from all the entities
+   ================
+ */
+void UnparseEntities( void ){
+       char    *buf, *end;
+       epair_t *ep;
+       char line[2048];
+       int i;
+       char key[1024], value[1024];
+
+       buf = dentdata;
+       end = buf;
+       *end = 0;
+
+       for ( i = 0 ; i < num_entities ; i++ )
+       {
+               ep = entities[i].epairs;
+               if ( !ep ) {
+                       continue;   // ent got removed
+
+               }
+               strcat( end,"{\n" );
+               end += 2;
+
+               for ( ep = entities[i].epairs ; ep ; ep = ep->next )
+               {
+                       strcpy( key, ep->key );
+                       StripTrailing( key );
+                       strcpy( value, ep->value );
+                       StripTrailing( value );
+
+                       sprintf( line, "\"%s\" \"%s\"\n", key, value );
+                       strcat( end, line );
+                       end += strlen( line );
+               }
+               strcat( end,"}\n" );
+               end += 2;
+
+               if ( end > buf + MAX_MAP_ENTSTRING ) {
+                       Error( "Entity text too long" );
+               }
+       }
+       entdatasize = end - buf + 1;
+}
+
+void PrintEntity( entity_t *ent ){
+       epair_t *ep;
+
+       printf( "------- entity %p -------\n", ent );
+       for ( ep = ent->epairs ; ep ; ep = ep->next )
+       {
+               printf( "%s = %s\n", ep->key, ep->value );
+       }
+
+}
+
+void    SetKeyValue( entity_t *ent, char *key, char *value ){
+       epair_t *ep;
+
+       for ( ep = ent->epairs ; ep ; ep = ep->next )
+               if ( !strcmp( ep->key, key ) ) {
+                       free( ep->value );
+                       ep->value = copystring( value );
+                       return;
+               }
+       ep = malloc( sizeof( *ep ) );
+       if ( !ep ) {
+               Error( "SetKeyValue MALLOC failed!  Could not allocate %s bytes.", sizeof( *ep ) );
+       }
+       ep->next = ent->epairs;
+       ent->epairs = ep;
+       ep->key = copystring( key );
+       ep->value = copystring( value );
+}
+
+char    *ValueForKey( entity_t *ent, char *key ){
+       epair_t *ep;
+
+       for ( ep = ent->epairs ; ep ; ep = ep->next )
+               if ( !strcmp( ep->key, key ) ) {
+                       return ep->value;
+               }
+       return "";
+}
+
+vec_t   FloatForKey( entity_t *ent, char *key ){
+       char    *k;
+
+       k = ValueForKey( ent, key );
+       return atof( k );
+}
+
+void    GetVectorForKey( entity_t *ent, char *key, vec3_t vec ){
+       char    *k;
+       double v1, v2, v3;
+
+       k = ValueForKey( ent, key );
+// scanf into doubles, then assign, so it is vec_t size independent
+       v1 = v2 = v3 = 0;
+       sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
+       vec[0] = v1;
+       vec[1] = v2;
+       vec[2] = v3;
+}
diff --git a/tools/heretic2/common/bspfile.h b/tools/heretic2/common/bspfile.h
new file mode 100644 (file)
index 0000000..f66659b
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _QBSP3_H
+#define _QBSP3_H
+
+
+#include "qfiles.h"
+
+
+extern int nummodels;
+extern dmodel_t dmodels[MAX_MAP_MODELS];
+
+extern int visdatasize;
+extern byte dvisdata[MAX_MAP_VISIBILITY];
+extern dvis_t      *dvis;
+
+extern int lightdatasize;
+extern byte dlightdata[MAX_MAP_LIGHTING];
+
+extern int entdatasize;
+extern char dentdata[MAX_MAP_ENTSTRING];
+
+extern int numleafs;
+extern dleaf_t dleafs[MAX_MAP_LEAFS];
+
+extern int numplanes;
+extern dplane_t dplanes[MAX_MAP_PLANES];
+
+extern int numvertexes;
+extern dvertex_t dvertexes[MAX_MAP_VERTS];
+
+extern int numnodes;
+extern dnode_t dnodes[MAX_MAP_NODES];
+
+extern int numtexinfo;
+extern texinfo_t texinfo[MAX_MAP_TEXINFO];
+
+extern int numfaces;
+extern dface_t dfaces[MAX_MAP_FACES];
+
+extern int numedges;
+extern dedge_t dedges[MAX_MAP_EDGES];
+
+extern int numleaffaces;
+extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
+
+extern int numleafbrushes;
+extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+extern int numsurfedges;
+extern int dsurfedges[MAX_MAP_SURFEDGES];
+
+extern int numareas;
+extern darea_t dareas[MAX_MAP_AREAS];
+
+extern int numareaportals;
+extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
+
+extern int numbrushes;
+extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
+
+extern int numbrushsides;
+extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
+
+extern byte dpop[256];
+
+void DecompressVis( byte *in, byte *decompressed );
+int CompressVis( byte *vis, byte *dest );
+
+void    LoadBSPFile( char *filename );
+void    LoadBSPFileTexinfo( char *filename );    // just for qdata
+void    WriteBSPFile( char *filename );
+void    PrintBSPFileSizes( void );
+
+//===============
+
+
+typedef struct epair_s
+{
+       struct epair_s  *next;
+       char    *key;
+       char    *value;
+} epair_t;
+
+typedef struct
+{
+       vec3_t origin;
+       int firstbrush;
+       int numbrushes;
+       epair_t     *epairs;
+
+// only valid for func_areaportals
+       int areaportalnum;
+       int portalareas[2];
+} entity_t;
+
+extern int num_entities;
+extern entity_t entities[MAX_MAP_ENTITIES];
+
+void    ParseEntities( void );
+void    UnparseEntities( void );
+
+void    SetKeyValue( entity_t *ent, char *key, char *value );
+char    *ValueForKey( entity_t *ent, char *key );
+// will return "" if not present
+
+vec_t   FloatForKey( entity_t *ent, char *key );
+void    GetVectorForKey( entity_t *ent, char *key, vec3_t vec );
+
+epair_t *ParseEpair( void );
+
+void PrintEntity( entity_t *ent );
+
+#endif //_QBSP3_H
diff --git a/tools/heretic2/common/cmdlib.c b/tools/heretic2/common/cmdlib.c
new file mode 100644 (file)
index 0000000..9852623
--- /dev/null
@@ -0,0 +1,1181 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// Nurail: Swiped from quake3/common
+
+#include "cmdlib.h"
+#include "globaldefs.h"
+#include "mathlib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if GDEF_OS_WINDOWS
+#include <direct.h>
+#include <windows.h>
+#elif GDEF_OS_NEXT
+#include <libc.h>
+#else // OTHER OSES
+#include <unistd.h>
+#endif // OTHER OSES
+
+#if !GDEF_OS_WINDOWS
+#define strlwr strlower
+#endif // !GDEF_OS_WINDOWS
+
+#define BASEDIRNAME "h"
+#define PATHSEPERATOR '/'
+
+extern qboolean verbose;
+
+qboolean g_dokeypress = false;
+
+qboolean g_nomkdir = false;
+
+void *safe_malloc( size_t size ){
+       void *p;
+
+       p = malloc( size );
+       if ( !p ) {
+               Error( "safe_malloc failed on allocation of %i bytes", size );
+       }
+
+       return p;
+}
+
+void *safe_malloc_info( size_t size, char* info ){
+       void *p;
+
+       p = malloc( size );
+       if ( !p ) {
+               Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
+       }
+
+       return p;
+}
+
+void *SafeMalloc( size_t n, char *desc ){
+       void *p;
+
+       if ( ( p = malloc( n ) ) == NULL ) {
+               Error( "Failed to allocate %d bytes for '%s'.\n", n, desc );
+       }
+       memset( p, 0, n );
+       return p;
+}
+
+// set these before calling CheckParm
+int myargc;
+char **myargv;
+
+char com_token[1024];
+qboolean com_eof;
+
+qboolean archive;
+char archivedir[1024];
+
+
+/*
+   ===================
+   ExpandWildcards
+
+   Mimic unix command line expansion
+   ===================
+ */
+#define MAX_EX_ARGC 1024
+
+int ex_argc;
+char    *ex_argv[MAX_EX_ARGC];
+
+#if GDEF_OS_WINDOWS
+#include "io.h"
+void ExpandWildcards( int *argc, char ***argv ){
+       struct _finddata_t fileinfo;
+       int handle;
+       int i;
+       char filename[1024];
+       char filebase[1024];
+       char    *path;
+
+       ex_argc = 0;
+       for ( i = 0 ; i < *argc ; i++ )
+       {
+               path = ( *argv )[i];
+               if ( path[0] == '-'
+                        || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
+                       ex_argv[ex_argc++] = path;
+                       continue;
+               }
+
+               handle = _findfirst( path, &fileinfo );
+               if ( handle == -1 ) {
+                       return;
+               }
+
+               ExtractFilePath( path, filebase );
+
+               do
+               {
+                       sprintf( filename, "%s%s", filebase, fileinfo.name );
+                       ex_argv[ex_argc++] = copystring( filename );
+               } while ( _findnext( handle, &fileinfo ) != -1 );
+
+               _findclose( handle );
+       }
+
+       *argc = ex_argc;
+       *argv = ex_argv;
+}
+#else // !GDEF_OS_WINDOWS
+void ExpandWildcards( int *argc, char ***argv ){
+}
+#endif // !GDEF_OS_WINDOWS
+
+/*
+
+   qdir will hold the path up to the quake directory, including the slash
+
+   f:\quake\
+   /raid/quake/
+
+   gamedir will hold qdir + the game directory (id1, id2, etc)
+
+ */
+
+char qdir[1024];
+char gamedir[1024];
+char writedir[1024];
+
+void SetQdirFromPath( const char *path ){
+       char temp[1024];
+       const char  *c;
+       const char *sep;
+       int len, count;
+
+       if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
+               Q_getwd( temp );
+               strcat( temp, path );
+               path = temp;
+       }
+
+       // search for "quake2" in path
+
+       len = strlen( BASEDIRNAME );
+       for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
+       {
+               int i;
+
+               if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
+                       //
+                       //strncpy (qdir, path, c+len+2-path);
+                       // the +2 assumes a 2 or 3 following quake which is not the
+                       // case with a retail install
+                       // so we need to add up how much to the next separator
+                       sep = c + len;
+                       count = 1;
+                       while ( *sep && *sep != '/' && *sep != '\\' )
+                       {
+                               sep++;
+                               count++;
+                       }
+                       strncpy( qdir, path, c + len + count - path );
+                       Sys_Printf( "qdir: %s\n", qdir );
+                       for ( i = 0; i < strlen( qdir ); i++ )
+                       {
+                               if ( qdir[i] == '\\' ) {
+                                       qdir[i] = '/';
+                               }
+                       }
+
+                       c += len + count;
+                       while ( *c )
+                       {
+                               if ( *c == '/' || *c == '\\' ) {
+                                       strncpy( gamedir, path, c + 1 - path );
+
+                                       for ( i = 0; i < strlen( gamedir ); i++ )
+                                       {
+                                               if ( gamedir[i] == '\\' ) {
+                                                       gamedir[i] = '/';
+                                               }
+                                       }
+
+                                       Sys_Printf( "gamedir: %s\n", gamedir );
+
+                                       if ( !writedir[0] ) {
+                                               strcpy( writedir, gamedir );
+                                       }
+                                       else if ( writedir[strlen( writedir ) - 1] != '/' ) {
+                                               writedir[strlen( writedir )] = '/';
+                                               writedir[strlen( writedir ) + 1] = 0;
+                                       }
+
+                                       return;
+                               }
+                               c++;
+                       }
+                       Error( "No gamedir in %s", path );
+                       return;
+               }
+       }
+       Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
+}
+
+char *ExpandArg( const char *path ){
+       static char full[1024];
+
+       if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
+               Q_getwd( full );
+               strcat( full, path );
+       }
+       else{
+               strcpy( full, path );
+       }
+       return full;
+}
+
+char *ExpandPath( const char *path ){
+       static char full[1024];
+       if ( !qdir ) {
+               Error( "ExpandPath called without qdir set" );
+       }
+       if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
+               strcpy( full, path );
+               return full;
+       }
+       sprintf( full, "%s%s", qdir, path );
+       return full;
+}
+
+char *ExpandGamePath( const char *path ){
+       static char full[1024];
+       if ( !qdir ) {
+               Error( "ExpandGamePath called without qdir set" );
+       }
+       if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
+               strcpy( full, path );
+               return full;
+       }
+       sprintf( full, "%s%s", gamedir, path );
+       return full;
+}
+
+char *ExpandPathAndArchive( const char *path ){
+       char    *expanded;
+       char archivename[1024];
+
+       expanded = ExpandPath( path );
+
+       if ( archive ) {
+               sprintf( archivename, "%s/%s", archivedir, path );
+               QCopyFile( expanded, archivename );
+       }
+       return expanded;
+}
+
+
+char *copystring( const char *s ){
+       char    *b;
+       b = safe_malloc( strlen( s ) + 1 );
+       strcpy( b, s );
+       return b;
+}
+
+
+
+/*
+   ================
+   I_FloatTime
+   ================
+ */
+double I_FloatTime( void ){
+       time_t t;
+
+       time( &t );
+
+       return t;
+#if 0
+// more precise, less portable
+       struct timeval tp;
+       struct timezone tzp;
+       static int secbase;
+
+       gettimeofday( &tp, &tzp );
+
+       if ( !secbase ) {
+               secbase = tp.tv_sec;
+               return tp.tv_usec / 1000000.0;
+       }
+
+       return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
+#endif
+}
+
+void Q_getwd( char *out ){
+       int i = 0;
+
+#if GDEF_OS_WINDOWS
+       _getcwd( out, 256 );
+       strcat( out, "\\" );
+#else // !GDEF_OS_WINDOWS
+       // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
+       getcwd( out, 256 );
+       strcat( out, "/" );
+#endif // !GDEF_OS_WINDOWS
+       while ( out[i] != 0 )
+       {
+               if ( out[i] == '\\' ) {
+                       out[i] = '/';
+               }
+               i++;
+       }
+}
+
+
+void Q_mkdir( const char *path ){
+#if GDEF_OS_WINDOWS
+       if ( _mkdir( path ) != -1 ) {
+               return;
+       }
+#else // !GDEF_OS_WINDOWS
+       if ( mkdir( path, 0777 ) != -1 ) {
+               return;
+       }
+#endif // !GDEF_OS_WINDOWS
+       if ( errno != EEXIST ) {
+               Error( "mkdir %s: %s",path, strerror( errno ) );
+       }
+}
+
+/*
+   ============
+   FileTime
+
+   returns -1 if not present
+   ============
+ */
+int FileTime( const char *path ){
+       struct  stat buf;
+
+       if ( stat( path,&buf ) == -1 ) {
+               return -1;
+       }
+
+       return buf.st_mtime;
+}
+
+
+
+/*
+   ==============
+   COM_Parse
+
+   Parse a token out of a string
+   ==============
+ */
+char *COM_Parse( char *data ){
+       int c;
+       int len;
+
+       len = 0;
+       com_token[0] = 0;
+
+       if ( !data ) {
+               return NULL;
+       }
+
+// skip whitespace
+skipwhite:
+       while ( ( c = *data ) <= ' ' )
+       {
+               if ( c == 0 ) {
+                       com_eof = true;
+                       return NULL;            // end of file;
+               }
+               data++;
+       }
+
+// skip // comments
+       if ( c == '/' && data[1] == '/' ) {
+               while ( *data && *data != '\n' )
+                       data++;
+               goto skipwhite;
+       }
+
+
+// handle quoted strings specially
+       if ( c == '\"' ) {
+               data++;
+               do
+               {
+                       c = *data++;
+                       if ( c == '\"' ) {
+                               com_token[len] = 0;
+                               return data;
+                       }
+                       com_token[len] = c;
+                       len++;
+               } while ( 1 );
+       }
+
+// parse single characters
+       if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
+               com_token[len] = c;
+               len++;
+               com_token[len] = 0;
+               return data + 1;
+       }
+
+// parse a regular word
+       do
+       {
+               com_token[len] = c;
+               data++;
+               len++;
+               c = *data;
+               if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
+                       break;
+               }
+       } while ( c > 32 );
+
+       com_token[len] = 0;
+       return data;
+}
+
+int Q_strncasecmp( const char *s1, const char *s2, int n ){
+       int c1, c2;
+
+       do
+       {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if ( !n-- ) {
+                       return 0;       // strings are equal until end point
+
+               }
+               if ( c1 != c2 ) {
+                       if ( c1 >= 'a' && c1 <= 'z' ) {
+                               c1 -= ( 'a' - 'A' );
+                       }
+                       if ( c2 >= 'a' && c2 <= 'z' ) {
+                               c2 -= ( 'a' - 'A' );
+                       }
+                       if ( c1 != c2 ) {
+                               return -1;      // strings not equal
+                       }
+               }
+       } while ( c1 );
+
+       return 0;       // strings are equal
+}
+
+int Q_stricmp( const char *s1, const char *s2 ){
+       return Q_strncasecmp( s1, s2, 99999 );
+}
+
+int Q_strcasecmp( const char *s1, const char *s2 ){
+       return Q_strncasecmp( s1, s2, 99999 );
+}
+
+// May be already defined with some compilers on Windows
+#ifndef strupr
+char *strupr (char *start)
+{
+       char    *in;
+       in = start;
+       while (*in)
+       {
+               *in = toupper(*in);
+               in++;
+       }
+       return start;
+}
+#endif
+
+char *strlower( char *start ){
+       char    *in;
+       in = start;
+       while ( *in )
+       {
+               *in = tolower( *in );
+               in++;
+       }
+       return start;
+}
+
+
+/*
+   =============================================================================
+
+                        MISC FUNCTIONS
+
+   =============================================================================
+ */
+
+
+/*
+   =================
+   CheckParm
+
+   Checks for the given parameter in the program's command line arguments
+   Returns the argument number (1 to argc-1) or 0 if not present
+   =================
+ */
+int CheckParm( const char *check ){
+       int i;
+
+       for ( i = 1; i < myargc; i++ )
+       {
+               if ( !Q_stricmp( check, myargv[i] ) ) {
+                       return i;
+               }
+       }
+
+       return 0;
+}
+
+
+
+/*
+   ================
+   Q_filelength
+   ================
+ */
+int Q_filelength( FILE *f ){
+       int pos;
+       int end;
+
+       pos = ftell( f );
+       fseek( f, 0, SEEK_END );
+       end = ftell( f );
+       fseek( f, pos, SEEK_SET );
+
+       return end;
+}
+
+
+FILE *SafeOpenWrite( const char *filename ){
+       FILE    *f;
+
+       f = fopen( filename, "wb" );
+
+       if ( !f ) {
+               Error( "Error opening %s: %s",filename,strerror( errno ) );
+       }
+
+       return f;
+}
+
+FILE *SafeOpenRead( const char *filename ){
+       FILE    *f;
+
+       f = fopen( filename, "rb" );
+
+       if ( !f ) {
+               Error( "Error opening %s: %s",filename,strerror( errno ) );
+       }
+
+       return f;
+}
+
+
+void SafeRead( FILE *f, void *buffer, int count ){
+       if ( fread( buffer, 1, count, f ) != (size_t)count ) {
+               Error( "File read failure" );
+       }
+}
+
+
+void SafeWrite( FILE *f, const void *buffer, int count ){
+       if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
+               Error( "File write failure" );
+       }
+}
+
+
+/*
+   ==============
+   FileExists
+   ==============
+ */
+qboolean    FileExists( const char *filename ){
+       FILE    *f;
+
+       f = fopen( filename, "r" );
+       if ( !f ) {
+               return false;
+       }
+       fclose( f );
+       return true;
+}
+
+/*
+   ==============
+   LoadFile
+   ==============
+ */
+int    LoadFile( const char *filename, void **bufferptr ){
+       FILE    *f;
+       int length;
+       void    *buffer;
+
+       f = SafeOpenRead( filename );
+       length = Q_filelength( f );
+       buffer = safe_malloc( length + 1 );
+       ( (char *)buffer )[length] = 0;
+       SafeRead( f, buffer, length );
+       fclose( f );
+
+       *bufferptr = buffer;
+       return length;
+}
+
+
+/*
+   ==============
+   LoadFileBlock
+   -
+   rounds up memory allocation to 4K boundry
+   -
+   ==============
+ */
+int    LoadFileBlock( const char *filename, void **bufferptr ){
+       FILE    *f;
+       int length, nBlock, nAllocSize;
+       void    *buffer;
+
+       f = SafeOpenRead( filename );
+       length = Q_filelength( f );
+       nAllocSize = length;
+       nBlock = nAllocSize % MEM_BLOCKSIZE;
+       if ( nBlock > 0 ) {
+               nAllocSize += MEM_BLOCKSIZE - nBlock;
+       }
+       buffer = safe_malloc( nAllocSize + 1 );
+       memset( buffer, 0, nAllocSize + 1 );
+       SafeRead( f, buffer, length );
+       fclose( f );
+
+       *bufferptr = buffer;
+       return length;
+}
+
+
+/*
+   ==============
+   TryLoadFile
+
+   Allows failure
+   ==============
+ */
+int    TryLoadFile( const char *filename, void **bufferptr ){
+       FILE    *f;
+       int length;
+       void    *buffer;
+
+       *bufferptr = NULL;
+
+       f = fopen( filename, "rb" );
+       if ( !f ) {
+               return -1;
+       }
+       length = Q_filelength( f );
+       buffer = safe_malloc( length + 1 );
+       ( (char *)buffer )[length] = 0;
+       SafeRead( f, buffer, length );
+       fclose( f );
+
+       *bufferptr = buffer;
+       return length;
+}
+
+
+/*
+   ==============
+   SaveFile
+   ==============
+ */
+void    SaveFile( const char *filename, const void *buffer, int count ){
+       FILE    *f;
+
+       f = SafeOpenWrite( filename );
+       SafeWrite( f, buffer, count );
+       fclose( f );
+}
+
+
+
+void DefaultExtension( char *path, const char *extension ){
+       char    *src;
+//
+// if path doesnt have a .EXT, append extension
+// (extension should include the .)
+//
+       src = path + strlen( path ) - 1;
+
+       while ( *src != '/' && *src != '\\' && src != path )
+       {
+               if ( *src == '.' ) {
+                       return;                 // it has an extension
+               }
+               src--;
+       }
+
+       strcat( path, extension );
+}
+
+
+void DefaultPath( char *path, const char *basepath ){
+       char temp[128];
+
+       if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
+               return;                   // absolute path location
+       }
+       strcpy( temp,path );
+       strcpy( path,basepath );
+       strcat( path,temp );
+}
+
+
+void    StripFilename( char *path ){
+       int length;
+
+       length = strlen( path ) - 1;
+       while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
+               length--;
+       path[length] = 0;
+}
+
+void    StripExtension( char *path ){
+       int length;
+
+       length = strlen( path ) - 1;
+       while ( length > 0 && path[length] != '.' )
+       {
+               length--;
+               if ( path[length] == '/' || path[ length ] == '\\' ) {
+                       return;     // no extension
+               }
+       }
+       if ( length ) {
+               path[length] = 0;
+       }
+}
+
+
+/*
+   ====================
+   Extract file parts
+   ====================
+ */
+
+// FIXME: should include the slash, otherwise
+// backing to an empty path will be wrong when appending a slash
+void ExtractFilePath( const char *path, char *dest ){
+       const char    *src;
+
+       src = path + strlen( path ) - 1;
+
+//
+// back up until a \ or the start
+//
+       while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
+               src--;
+
+       memcpy( dest, path, src - path );
+       dest[src - path] = 0;
+}
+
+void ExtractFileBase( const char *path, char *dest ){
+       const char    *src;
+
+       src = path + strlen( path ) - 1;
+
+//
+// back up until a \ or the start
+//
+       while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
+               src--;
+
+       while ( *src && *src != '.' )
+       {
+               *dest++ = *src++;
+       }
+       *dest = 0;
+}
+
+void ExtractFileExtension( const char *path, char *dest ){
+       const char    *src;
+
+       src = path + strlen( path ) - 1;
+
+//
+// back up until a . or the start
+//
+       while ( src != path && *( src - 1 ) != '.' )
+               src--;
+       if ( src == path ) {
+               *dest = 0;  // no extension
+               return;
+       }
+
+       strcpy( dest,src );
+}
+
+
+/*
+   ==============
+   ParseNum / ParseHex
+   ==============
+ */
+int ParseHex( const char *hex ){
+       const char    *str;
+       int num;
+
+       num = 0;
+       str = hex;
+
+       while ( *str )
+       {
+               num <<= 4;
+               if ( *str >= '0' && *str <= '9' ) {
+                       num += *str - '0';
+               }
+               else if ( *str >= 'a' && *str <= 'f' ) {
+                       num += 10 + *str - 'a';
+               }
+               else if ( *str >= 'A' && *str <= 'F' ) {
+                       num += 10 + *str - 'A';
+               }
+               else{
+                       Error( "Bad hex number: %s",hex );
+               }
+               str++;
+       }
+
+       return num;
+}
+
+
+int ParseNum( const char *str ){
+       if ( str[0] == '$' ) {
+               return ParseHex( str + 1 );
+       }
+       if ( str[0] == '0' && str[1] == 'x' ) {
+               return ParseHex( str + 2 );
+       }
+       return atol( str );
+}
+/*
+   // all output ends up through here
+   void FPrintf (int flag, char *buf)
+   {
+   printf( "%s", buf );
+
+   }
+
+   void Sys_FPrintf (int flag, const char *format, ...)
+   {
+   char out_buffer[4096];
+    va_list argptr;
+
+   if ((flag == SYS_VRB) && (verbose == false))
+    return;
+
+   va_start (argptr, format);
+    vsprintf (out_buffer, format, argptr);
+    va_end (argptr);
+
+   FPrintf (flag, out_buffer);
+   }
+
+   void Sys_Printf (const char *format, ...)
+   {
+   char out_buffer[4096];
+    va_list argptr;
+
+   va_start (argptr, format);
+    vsprintf (out_buffer, format, argptr);
+    va_end (argptr);
+
+   FPrintf (SYS_STD, out_buffer);
+   }
+
+   //=================
+   //Error
+   //
+   //For abnormal program terminations
+   //=================
+
+   void Error( const char *error, ...)
+   {
+   char out_buffer[4096];
+   char tmp[4096];
+    va_list argptr;
+
+    va_start (argptr,error);
+    vsprintf (tmp, error, argptr);
+    va_end (argptr);
+
+   sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+   FPrintf( SYS_ERR, out_buffer );
+
+    exit (1);
+   }
+
+ */
+
+/*
+   ============================================================================
+
+                    BYTE ORDER FUNCTIONS
+
+   ============================================================================
+ */
+
+#if GDEF_ARCH_ENDIAN_BIG
+
+short   LittleShort( short l ){
+       byte b1,b2;
+
+       b1 = l & 255;
+       b2 = ( l >> 8 ) & 255;
+
+       return ( b1 << 8 ) + b2;
+}
+
+short   BigShort( short l ){
+       return l;
+}
+
+
+int    LittleLong( int l ){
+       byte b1,b2,b3,b4;
+
+       b1 = l & 255;
+       b2 = ( l >> 8 ) & 255;
+       b3 = ( l >> 16 ) & 255;
+       b4 = ( l >> 24 ) & 255;
+
+       return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
+}
+
+int    BigLong( int l ){
+       return l;
+}
+
+
+float   LittleFloat( float l ){
+       union {byte b[4]; float f; } in, out;
+
+       in.f = l;
+       out.b[0] = in.b[3];
+       out.b[1] = in.b[2];
+       out.b[2] = in.b[1];
+       out.b[3] = in.b[0];
+
+       return out.f;
+}
+
+float   BigFloat( float l ){
+       return l;
+}
+
+
+#else // !GDEF_ARCH_ENDIAN_BIG
+
+
+short   BigShort( short l ){
+       byte b1,b2;
+
+       b1 = l & 255;
+       b2 = ( l >> 8 ) & 255;
+
+       return ( b1 << 8 ) + b2;
+}
+
+short   LittleShort( short l ){
+       return l;
+}
+
+
+int    BigLong( int l ){
+       byte b1,b2,b3,b4;
+
+       b1 = l & 255;
+       b2 = ( l >> 8 ) & 255;
+       b3 = ( l >> 16 ) & 255;
+       b4 = ( l >> 24 ) & 255;
+
+       return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
+}
+
+int    LittleLong( int l ){
+       return l;
+}
+
+float   BigFloat( float l ){
+       union {byte b[4]; float f; } in, out;
+
+       in.f = l;
+       out.b[0] = in.b[3];
+       out.b[1] = in.b[2];
+       out.b[2] = in.b[1];
+       out.b[3] = in.b[0];
+
+       return out.f;
+}
+
+float   LittleFloat( float l ){
+       return l;
+}
+
+#endif // ! GDEF_ARCH_ENDIAN_BIG
+
+
+//=======================================================
+
+
+// FIXME: byte swap?
+
+// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
+// and the initial and final xor values shown below...  in other words, the
+// CCITT standard CRC used by XMODEM
+
+#define CRC_INIT_VALUE  0xffff
+#define CRC_XOR_VALUE   0x0000
+
+static unsigned short crctable[256] =
+{
+       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+       0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+       0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+       0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+       0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+       0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+       0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+       0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+       0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+       0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+       0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+       0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+       0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+       0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+       0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+       0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+       0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+       0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+       0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+       0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+       0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+       0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+       0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+       0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+       0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+       0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+       0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+       0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+       0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+       0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+       0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+       0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+void CRC_Init( unsigned short *crcvalue ){
+       *crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
+       *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
+}
+
+unsigned short CRC_Value( unsigned short crcvalue ){
+       return crcvalue ^ CRC_XOR_VALUE;
+}
+//=============================================================================
+
+/*
+   ============
+   CreatePath
+   ============
+ */
+void    CreatePath( const char *path ){
+       const char  *ofs;
+       char c;
+       char dir[1024];
+
+#if GDEF_OS_WINDOWS
+       int olddrive = -1;
+
+       if ( path[1] == ':' ) {
+               olddrive = _getdrive();
+               _chdrive( toupper( path[0] ) - 'A' + 1 );
+       }
+#endif // !GDEF_OS_WINDOWS
+
+       if ( path[1] == ':' ) {
+               path += 2;
+       }
+
+       for ( ofs = path + 1 ; *ofs ; ofs++ )
+       {
+               c = *ofs;
+               if ( c == '/' || c == '\\' ) { // create the directory
+                       memcpy( dir, path, ofs - path );
+                       dir[ ofs - path ] = 0;
+                       Q_mkdir( dir );
+               }
+       }
+
+#if GDEF_OS_WINDOWS
+       if ( olddrive != -1 ) {
+               _chdrive( olddrive );
+       }
+#endif // !GDEF_OS_WINDOWS
+}
+
+
+/*
+   ============
+   QCopyFile
+
+   Used to archive source files
+   ============
+ */
+void QCopyFile( const char *from, const char *to ){
+       void    *buffer;
+       int length;
+
+       length = LoadFile( from, &buffer );
+       CreatePath( to );
+       SaveFile( to, buffer, length );
+       free( buffer );
+}
+
+void Sys_Sleep( int n ){
+#if GDEF_OS_WINDOWS
+       Sleep( n );
+#else // !GDEF_OS_WINDOWS
+       usleep( n * 1000 );
+#endif // !GDEF_OS_WINDOWS
+}
diff --git a/tools/heretic2/common/cmdlib.h b/tools/heretic2/common/cmdlib.h
new file mode 100644 (file)
index 0000000..b9c7de9
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#if GDEF_COMPILER_MSVC
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+
+#pragma warning(disable : 4018)     // signed/unsigned mismatch
+#pragma warning(disable : 4305)     // truncate from double to float
+
+#pragma check_stack(off)
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#if GDEF_COMPILER_MSVC
+
+#pragma intrinsic( memset, memcpy )
+
+#endif
+
+#ifndef __BYTEBOOL__
+  #define __BYTEBOOL__
+//typedef enum {false, true} qboolean;
+//typedef unsigned char byte;
+  #include "q_typedef.h"
+#endif
+
+#ifdef PATH_MAX
+#define MAX_OS_PATH     PATH_MAX
+#else
+#define MAX_OS_PATH     1024
+#endif
+#define MEM_BLOCKSIZE 4096
+/*
+   extern      qboolean verbose;
+   #define SYS_VRB 0 // verbose support (on/off)
+   #define SYS_STD 1 // standard print level
+   #define SYS_WRN 2 // warnings
+   #define SYS_ERR 3 // error
+ */
+// the dec offsetof macro doesnt work very well...
+#define myoffsetof( type,identifier ) ( (size_t)& ( (type *)0 )->identifier )
+
+void *safe_malloc( size_t size );
+void *safe_malloc_info( size_t size, char* info );
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+// May be already defined with some compilers on Windows
+#ifndef strupr
+char *strupr (char *start);
+#endif
+
+char *strlower( char *start );
+int Q_strncasecmp( const char *s1, const char *s2, int n );
+int Q_stricmp( const char *s1, const char *s2 );
+int Q_strcasecmp( const char *s1, const char *s2 );
+void Q_getwd( char *out );
+
+int Q_filelength( FILE *f );
+int FileTime( const char *path );
+
+void    Q_mkdir( const char *path );
+
+extern char qdir[1024];
+extern char gamedir[1024];
+extern char writedir[1024];
+extern char    *moddirparam;
+void SetQdirFromPath( const char *path );
+char *ExpandArg( const char *path );    // from cmd line
+char *ExpandPath( const char *path );   // from scripts
+char *ExpandGamePath( const char *path );
+char *ExpandPathAndArchive( const char *path );
+void ExpandWildcards( int *argc, char ***argv );
+
+
+double I_FloatTime( void );
+
+int     CheckParm( const char *check );
+
+void    *SafeMalloc( size_t n, char *desc );
+FILE    *SafeOpenWrite( const char *filename );
+FILE    *SafeOpenRead( const char *filename );
+void    SafeRead( FILE *f, void *buffer, int count );
+void    SafeWrite( FILE *f, const void *buffer, int count );
+
+int     LoadFile( const char *filename, void **bufferptr );
+int   LoadFileBlock( const char *filename, void **bufferptr );
+int     TryLoadFile( const char *filename, void **bufferptr );
+void    SaveFile( const char *filename, const void *buffer, int count );
+qboolean    FileExists( const char *filename );
+
+void    DefaultExtension( char *path, const char *extension );
+void    DefaultPath( char *path, const char *basepath );
+void    StripFilename( char *path );
+void    StripExtension( char *path );
+
+void    ExtractFilePath( const char *path, char *dest );
+void    ExtractFileBase( const char *path, char *dest );
+void    ExtractFileExtension( const char *path, char *dest );
+
+int     ParseNum( const char *str );
+/*
+   void Sys_Printf (const char *text, ...);
+   void Sys_FPrintf (int flag, const char *text, ...);
+   void        Error( const char *error, ... );
+ */
+short   BigShort( short l );
+short   LittleShort( short l );
+int     BigLong( int l );
+int     LittleLong( int l );
+float   BigFloat( float l );
+float   LittleFloat( float l );
+
+
+char *COM_Parse( char *data );
+
+extern char com_token[1024];
+extern qboolean com_eof;
+
+char *copystring( const char *s );
+
+
+void CRC_Init( unsigned short *crcvalue );
+void CRC_ProcessByte( unsigned short *crcvalue, byte data );
+unsigned short CRC_Value( unsigned short crcvalue );
+
+void    CreatePath( const char *path );
+void    QCopyFile( const char *from, const char *to );
+
+extern qboolean archive;
+extern char archivedir[1024];
+
+extern qboolean g_dokeypress;
+
+// sleep for the given amount of milliseconds
+void Sys_Sleep( int n );
+
+// for compression routines
+typedef struct
+{
+       byte    *data;
+       int count;
+} cblock_t;
+
+
+#endif
diff --git a/tools/heretic2/common/her2_threads.h b/tools/heretic2/common/her2_threads.h
new file mode 100644 (file)
index 0000000..6027a69
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef _THREADS_H
+
+#define _THREADS_H
+
+
+extern int numthreads;
+
+void ThreadSetDefault( void );
+int GetThreadWork( void );
+void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )( int ) );
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) );
+void ThreadLock( void );
+void ThreadUnlock( void );
+
+#endif //_THREADS_H
diff --git a/tools/heretic2/common/inout.c b/tools/heretic2/common/inout.c
new file mode 100644 (file)
index 0000000..b6d272f
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// deal with in/out tasks, for either stdin/stdout or network/XML stream
+//
+
+#include "globaldefs.h"
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "polylib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if GDEF_OS_WINDOWS
+#include <direct.h>
+#include <windows.h>
+#endif
+
+// network broadcasting
+#include "l_net/l_net.h"
+#include "libxml/tree.h"
+
+#if GDEF_OS_WINDOWS
+HWND hwndOut = NULL;
+qboolean lookedForServer = false;
+UINT wm_BroadcastCommand = -1;
+#endif
+
+socket_t *brdcst_socket;
+netmessage_t msg;
+
+qboolean verbose = false;
+
+// our main document
+// is streamed through the network to Radiant
+// possibly written to disk at the end of the run
+//++timo FIXME: need to be global, required when creating nodes?
+xmlDocPtr doc;
+xmlNodePtr tree;
+
+// some useful stuff
+xmlNodePtr xml_NodeForVec( vec3_t v ){
+       xmlNodePtr ret;
+       char buf[1024];
+
+       sprintf( buf, "%f %f %f", v[0], v[1], v[2] );
+       ret = xmlNewNode( NULL, "point" );
+       xmlNodeAddContent( ret, buf );
+       return ret;
+}
+
+// send a node down the stream, add it to the document
+void xml_SendNode( xmlNodePtr node ){
+       xmlBufferPtr xml_buf;
+       char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
+       // this index loops through the node buffer
+       int pos = 0;
+       int size;
+
+       xmlAddChild( doc->children, node );
+
+       if ( brdcst_socket ) {
+               xml_buf = xmlBufferCreate();
+               xmlNodeDump( xml_buf, doc, node, 0, 0 );
+
+               // the XML node might be too big to fit in a single network message
+               // l_net library defines an upper limit of MAX_NETMESSAGE
+               // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
+               // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
+               while ( pos < xml_buf->use )
+               {
+                       // what size are we gonna send now?
+                       ( xml_buf->use - pos < MAX_NETMESSAGE - 10 ) ? ( size = xml_buf->use - pos ) : ( size = MAX_NETMESSAGE - 10 );
+                       //++timo just a debug thing
+                       if ( size == MAX_NETMESSAGE - 10 ) {
+                               Sys_FPrintf( SYS_NOXML, "Got to split the buffer\n" );
+                       }
+                       memcpy( xmlbuf, xml_buf->content + pos, size );
+                       xmlbuf[size] = '\0';
+                       NMSG_Clear( &msg );
+                       NMSG_WriteString( &msg, xmlbuf );
+                       Net_Send( brdcst_socket, &msg );
+                       // now that the thing is sent prepare to loop again
+                       pos += size;
+               }
+
+#if 0
+               // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
+               // we will need to split into chunks
+               // (we could also go lower level, in the end it's using send and receiv which are not size limited)
+               //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
+               //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
+
+               //++timo we need to handle the case of a buffer too big to fit in a single message
+               // try without checks for now
+               if ( xml_buf->use > MAX_NETMESSAGE - 10 ) {
+                       // if we send that we are probably gonna break the stream at the other end..
+                       // and Error will call right there
+                       //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+                       Sys_FPrintf( SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use );
+                       xml_buf->content[xml_buf->use] = '\0'; //++timo this corrupts the buffer but we don't care it's for printing
+                       Sys_FPrintf( SYS_NOXML, xml_buf->content );
+
+               }
+
+               size = xml_buf->use;
+               memcpy( xmlbuf, xml_buf->content, size );
+               xmlbuf[size] = '\0';
+               NMSG_Clear( &msg );
+               NMSG_WriteString( &msg, xmlbuf );
+               Net_Send( brdcst_socket, &msg );
+#endif
+
+               xmlBufferFree( xml_buf );
+       }
+}
+
+void xml_Select( char *msg, int entitynum, int brushnum, qboolean bError ){
+       xmlNodePtr node, select;
+       char buf[1024];
+       char level[2];
+
+       // now build a proper "select" XML node
+       sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
+       node = xmlNewNode( NULL, "select" );
+       xmlNodeAddContent( node, buf );
+       level[0] = (int)'0' + ( bError ? SYS_ERR : SYS_WRN )  ;
+       level[1] = 0;
+       xmlSetProp( node, "level", (char *)&level );
+       // a 'select' information
+       sprintf( buf, "%i %i", entitynum, brushnum );
+       select = xmlNewNode( NULL, "brush" );
+       xmlNodeAddContent( select, buf );
+       xmlAddChild( node, select );
+       xml_SendNode( node );
+
+       sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
+       if ( bError ) {
+               Error( buf );
+       }
+       else{
+               Sys_FPrintf( SYS_NOXML, "%s\n", buf );
+       }
+
+}
+
+void xml_Point( char *msg, vec3_t pt ){
+       xmlNodePtr node, point;
+       char buf[1024];
+       char level[2];
+
+       node = xmlNewNode( NULL, "pointmsg" );
+       xmlNodeAddContent( node, msg );
+       level[0] = (int)'0' + SYS_ERR;
+       level[1] = 0;
+       xmlSetProp( node, "level", (char *)&level );
+       // a 'point' node
+       sprintf( buf, "%g %g %g", pt[0], pt[1], pt[2] );
+       point = xmlNewNode( NULL, "point" );
+       xmlNodeAddContent( point, buf );
+       xmlAddChild( node, point );
+       xml_SendNode( node );
+
+       sprintf( buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2] );
+       Error( buf );
+}
+
+#define WINDING_BUFSIZE 2048
+void xml_Winding( char *msg, vec3_t p[], int numpoints, qboolean die ){
+       xmlNodePtr node, winding;
+       char buf[WINDING_BUFSIZE];
+       char smlbuf[128];
+       char level[2];
+       int i;
+
+       node = xmlNewNode( NULL, "windingmsg" );
+       xmlNodeAddContent( node, msg );
+       level[0] = (int)'0' + SYS_ERR;
+       level[1] = 0;
+       xmlSetProp( node, "level", (char *)&level );
+       // a 'winding' node
+       sprintf( buf, "%i ", numpoints );
+       for ( i = 0; i < numpoints; i++ )
+       {
+               sprintf( smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2] );
+               // don't overflow
+               if ( strlen( buf ) + strlen( smlbuf ) > WINDING_BUFSIZE ) {
+                       break;
+               }
+               strcat( buf, smlbuf );
+       }
+
+       winding = xmlNewNode( NULL, "winding" );
+       xmlNodeAddContent( winding, buf );
+       xmlAddChild( node, winding );
+       xml_SendNode( node );
+
+       if ( die ) {
+               Error( msg );
+       }
+       else
+       {
+               Sys_Printf( msg );
+               Sys_Printf( "\n" );
+       }
+}
+
+// in include
+#include "stream_version.h"
+
+void Broadcast_Setup( const char *dest ){
+       address_t address;
+       char sMsg[1024];
+
+       Net_Setup();
+       Net_StringToAddress( (char *)dest, &address );
+       brdcst_socket = Net_Connect( &address, 0 );
+       if ( brdcst_socket ) {
+               // send in a header
+               sprintf( sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">" );
+               NMSG_Clear( &msg );
+               NMSG_WriteString( &msg, sMsg );
+               Net_Send( brdcst_socket, &msg );
+       }
+}
+
+void Broadcast_Shutdown(){
+       if ( brdcst_socket ) {
+               Sys_Printf( "Disconnecting\n" );
+               Net_Disconnect( brdcst_socket );
+               brdcst_socket = NULL;
+       }
+}
+
+// all output ends up through here
+void FPrintf( int flag, char *buf ){
+       xmlNodePtr node;
+       static qboolean bGotXML = false;
+       char level[2];
+
+       printf( "%s", buf );
+
+       // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
+       if ( flag == SYS_NOXML ) {
+               return;
+       }
+
+       // ouput an XML file of the run
+       // use the DOM interface to build a tree
+       /*
+          <message level='flag'>
+          message string
+          .. various nodes to describe corresponding geometry ..
+          </message>
+        */
+       if ( !bGotXML ) {
+               // initialize
+               doc = xmlNewDoc( "1.0" );
+               doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
+               bGotXML = true;
+       }
+       node = xmlNewNode( NULL, "message" );
+       xmlNodeAddContent( node, buf );
+       level[0] = (int)'0' + flag;
+       level[1] = 0;
+       xmlSetProp( node, "level", (char *)&level );
+
+       xml_SendNode( node );
+}
+
+#ifdef DBG_XML
+void DumpXML(){
+       xmlSaveFile( "XMLDump.xml", doc );
+}
+#endif
+
+void Sys_FPrintf( int flag, const char *format, ... ){
+       char out_buffer[4096];
+       va_list argptr;
+
+       if ( ( flag == SYS_VRB ) && ( verbose == false ) ) {
+               return;
+       }
+
+       va_start( argptr, format );
+       vsprintf( out_buffer, format, argptr );
+       va_end( argptr );
+
+       FPrintf( flag, out_buffer );
+}
+
+void Sys_Printf( const char *format, ... ){
+       char out_buffer[4096];
+       va_list argptr;
+
+       va_start( argptr, format );
+       vsprintf( out_buffer, format, argptr );
+       va_end( argptr );
+
+       FPrintf( SYS_STD, out_buffer );
+}
+
+/*
+   =================
+   Error
+
+   For abnormal program terminations
+   =================
+ */
+void Error( const char *error, ... ){
+       char out_buffer[4096];
+       char tmp[4096];
+       va_list argptr;
+
+       va_start( argptr,error );
+       vsprintf( tmp, error, argptr );
+       va_end( argptr );
+
+       sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+       FPrintf( SYS_ERR, out_buffer );
+
+#ifdef DBG_XML
+       DumpXML();
+#endif
+
+       //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
+       // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
+       Sys_Sleep( 1000 );
+
+       Broadcast_Shutdown();
+
+       exit( 1 );
+}
diff --git a/tools/heretic2/common/inout.h b/tools/heretic2/common/inout.h
new file mode 100644 (file)
index 0000000..934189f
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __INOUT__
+#define __INOUT__
+
+#include "globaldefs.h"
+// inout is the only stuff relying on xml, include the headers there
+#include "libxml/tree.h"
+#include "mathlib.h"
+
+// some useful xml routines
+xmlNodePtr xml_NodeForVec( vec3_t v );
+void xml_SendNode( xmlNodePtr node );
+// print a message in q3map output and send the corresponding select information down the xml stream
+// bError: do we end with an error on this one or do we go ahead?
+void xml_Select( char *msg, int entitynum, int brushnum, qboolean bError );
+// end q3map with an error message and send a point information in the xml stream
+// note: we might want to add a boolean to use this as a warning or an error thing..
+void xml_Winding( char *msg, vec3_t p[], int numpoints, qboolean die );
+void xml_Point( char *msg, vec3_t pt );
+
+extern qboolean bNetworkBroadcast;
+void Broadcast_Setup( const char *dest );
+void Broadcast_Shutdown();
+
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+#define SYS_NOXML 4 // don't send that down the XML stream
+
+extern qboolean verbose;
+void Sys_Printf( const char *text, ... );
+void Sys_FPrintf( int flag, const char *text, ... );
+void Error( const char *error, ... );
+
+#if GDEF_DEBUG
+#define DBG_XML 1
+#endif
+
+#ifdef DBG_XML
+void DumpXML();
+#endif
+
+#endif
diff --git a/tools/heretic2/common/l3dslib.c b/tools/heretic2/common/l3dslib.c
new file mode 100644 (file)
index 0000000..708577a
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// l3dslib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "l3dslib.h"
+#include "token.h"
+#include "fmodel.h"
+#include "bspfile.h"
+
+#define MAIN3DS       0x4D4D
+#define EDIT3DS       0x3D3D  // this is the start of the editor config
+#define EDIT_OBJECT   0x4000
+#define OBJ_TRIMESH   0x4100
+#define TRI_VERTEXL   0x4110
+#define TRI_FACEL1    0x4120
+
+#define MAXVERTS    2000
+
+typedef struct {
+       int v[4];
+} tri;
+
+float fverts[MAXVERTS][3];
+tri tris[MAXTRIANGLES];
+
+int bytesread, level, numtris, totaltris;
+int vertsfound, trisfound;
+
+triangle_t  *ptri;
+
+
+
+void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles ){
+       int pos, bit, i;
+
+       if ( nodesList ) {
+               *num_mesh_nodes = 1;
+               memset( &( *nodesList )[0], 0, sizeof( mesh_node_t ) );
+               strcpy( ( *nodesList )[0].name, "default" );
+
+               // set all of the tris to be used for the top node
+               for ( i = 0; i < ( *numtriangles ); i++ )
+               {
+                       pos = ( i ) >> 3;
+                       bit = 1 << ( ( i ) & 7 );
+
+                       ( *nodesList )[0].tris[pos] |= bit;
+               }
+       }
+}
+
+
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
+// start out with a vertex pool and vertex indices for triangles, we have to convert
+// to raw, explicit triangles
+void StoreAliasTriangles( void ){
+       int i, j, k;
+
+       if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
+               Error( "Error: Too many triangles" );
+       }
+
+       for ( i = 0; i < numtris ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
+                       }
+               }
+       }
+
+       totaltris += numtris;
+       numtris = 0;
+       vertsfound = 0;
+       trisfound = 0;
+}
+
+
+int ParseVertexL( FILE *input ){
+       int i, j, startbytesread, numverts;
+       unsigned short tshort;
+
+       if ( vertsfound ) {
+               Error( "Error: Multiple vertex chunks" );
+       }
+
+       vertsfound = 1;
+       startbytesread = bytesread;
+
+       if ( feof( input ) ) {
+               Error( "Error: unexpected end of file" );
+       }
+
+       fread( &tshort, sizeof( tshort ), 1, input );
+       bytesread += sizeof( tshort );
+       numverts = (int)tshort;
+
+       if ( numverts > MAXVERTS ) {
+               Error( "Error: Too many vertices" );
+       }
+
+       for ( i = 0 ; i < numverts ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       if ( feof( input ) ) {
+                               Error( "Error: unexpected end of file" );
+                       }
+
+                       fread( &fverts[i][j], sizeof( float ), 1, input );
+                       bytesread += sizeof( float );
+               }
+       }
+
+       if ( vertsfound && trisfound ) {
+               StoreAliasTriangles();
+       }
+
+       return bytesread - startbytesread;
+}
+
+
+int ParseFaceL1( FILE *input ){
+
+       int i, j, startbytesread;
+       unsigned short tshort;
+
+       if ( trisfound ) {
+               Error( "Error: Multiple face chunks" );
+       }
+
+       trisfound = 1;
+       startbytesread = bytesread;
+
+       if ( feof( input ) ) {
+               Error( "Error: unexpected end of file" );
+       }
+
+       fread( &tshort, sizeof( tshort ), 1, input );
+       bytesread += sizeof( tshort );
+       numtris = (int)tshort;
+
+       if ( numtris > MAXTRIANGLES ) {
+               Error( "Error: Too many triangles" );
+       }
+
+       for ( i = 0 ; i < numtris ; i++ )
+       {
+               for ( j = 0 ; j < 4 ; j++ )
+               {
+                       if ( feof( input ) ) {
+                               Error( "Error: unexpected end of file" );
+                       }
+
+                       fread( &tshort, sizeof( tshort ), 1, input );
+                       bytesread += sizeof( tshort );
+                       tris[i].v[j] = (int)tshort;
+               }
+       }
+
+       if ( vertsfound && trisfound ) {
+               StoreAliasTriangles();
+       }
+
+       return bytesread - startbytesread;
+}
+
+
+int ParseChunk( FILE *input ){
+#define BLOCK_SIZE  4096
+       char temp[BLOCK_SIZE];
+       unsigned short type;
+       int i, length, w, t, retval;
+
+       level++;
+       retval = 0;
+
+// chunk type
+       if ( feof( input ) ) {
+               Error( "Error: unexpected end of file" );
+       }
+
+       fread( &type, sizeof( type ), 1, input );
+       bytesread += sizeof( type );
+
+// chunk length
+       if ( feof( input ) ) {
+               Error( "Error: unexpected end of file" );
+       }
+
+       fread( &length, sizeof( length ), 1, input );
+       bytesread += sizeof( length );
+       w = length - 6;
+
+// process chunk if we care about it, otherwise skip it
+       switch ( type )
+       {
+       case TRI_VERTEXL:
+               w -= ParseVertexL( input );
+               goto ParseSubchunk;
+
+       case TRI_FACEL1:
+               w -= ParseFaceL1( input );
+               goto ParseSubchunk;
+
+       case EDIT_OBJECT:
+               // read the name
+               i = 0;
+
+               do
+               {
+                       if ( feof( input ) ) {
+                               Error( "Error: unexpected end of file" );
+                       }
+
+                       fread( &temp[i], 1, 1, input );
+                       i++;
+                       w--;
+                       bytesread++;
+               } while ( temp[i - 1] );
+
+       case MAIN3DS:
+       case OBJ_TRIMESH:
+       case EDIT3DS:
+               // parse through subchunks
+ParseSubchunk:
+               while ( w > 0 )
+               {
+                       w -= ParseChunk( input );
+               }
+
+               retval = length;
+               goto Done;
+
+       default:
+               // skip other chunks
+               while ( w > 0 )
+               {
+                       t = w;
+
+                       if ( t > BLOCK_SIZE ) {
+                               t = BLOCK_SIZE;
+                       }
+
+                       if ( feof( input ) ) {
+                               Error( "Error: unexpected end of file" );
+                       }
+
+                       fread( &temp, t, 1, input );
+                       bytesread += t;
+
+                       w -= t;
+               }
+
+               retval = length;
+               goto Done;
+       }
+
+Done:
+       level--;
+       return retval;
+}
+
+
+void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
+       FILE        *input;
+       short int tshort;
+
+       if ( nodesList ) {
+               *num_mesh_nodes = 0;
+               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+       }
+
+       bytesread = 0;
+       level = 0;
+       numtris = 0;
+       totaltris = 0;
+       vertsfound = 0;
+       trisfound = 0;
+
+       if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
+               fprintf( stderr,"reader: could not open file '%s'\n", filename );
+               exit( 0 );
+       }
+
+       fread( &tshort, sizeof( tshort ), 1, input );
+
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
+// no MAIN3DS
+       if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
+               fprintf( stderr,"File is not a 3DS file.\n" );
+               exit( 0 );
+       }
+
+// back to top of file so we can parse the first chunk descriptor
+       fseek( input, 0, SEEK_SET );
+
+       ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
+
+       *pptri = ptri;
+
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
+       ParseChunk( input );
+
+       if ( vertsfound || trisfound ) {
+               Error( "Incomplete triangle set" );
+       }
+
+       *numtriangles = totaltris;
+
+       fclose( input );
+
+       DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
+}
+
+//==========================================================================
+//
+// LoadASC
+//
+//==========================================================================
+
+void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
+       int i, j;
+       int vertexCount;
+       struct
+       {
+               float v[3];
+       }           *vList;
+       int triCount;
+       triangle_t  *tList;
+       float x, y, z;
+//     float           x2, y2, z2;
+//     float           rx, ry, rz;
+       qboolean goodObject;
+
+       if ( nodesList ) {
+               *num_mesh_nodes = 0;
+               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+       }
+
+       TK_OpenSource( fileName );
+
+       goodObject = false;
+       while ( goodObject == false )
+       {
+               TK_Beyond( TK_C_NAMED );
+               TK_Beyond( TK_OBJECT );
+               TK_Beyond( TK_C_TRI );
+               TK_Beyond( TK_MESH );
+               TK_BeyondRequire( TK_C_VERTICES, TK_COLON );
+               TK_FetchRequire( TK_INTNUMBER );
+               vertexCount = tk_IntNumber;
+               if ( vertexCount > 0 ) {
+                       goodObject = true;
+               }
+       }
+       TK_BeyondRequire( TK_C_FACES, TK_COLON );
+       TK_FetchRequire( TK_INTNUMBER );
+       triCount = tk_IntNumber;
+       if ( triCount >= MAXTRIANGLES ) {
+               Error( "Too many triangles in file %s\n", fileName );
+       }
+       *triangleCount = triCount;
+       tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
+       *triList = tList;
+
+       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
+       TK_BeyondRequire( TK_C_VERTEX, TK_LIST );
+
+/*     rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
+    //rx = (rotation[0]/360.0)*2.0*M_PI;
+    ry = (rotation[1]/360.0)*2.0*M_PI;
+    rz = (rotation[2]/360.0)*2.0*M_PI;
+ */
+       vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
+       for ( i = 0; i < vertexCount; i++ )
+       {
+               TK_BeyondRequire( TK_C_VERTEX, TK_INTNUMBER );
+               if ( tk_IntNumber != i ) {
+                       Error( "File '%s', line %d:\nVertex index mismatch.\n",
+                                  tk_SourceName, tk_Line );
+               }
+               TK_FetchRequireFetch( TK_COLON );
+
+               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+               x = tk_FloatNumber;
+               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+               y = tk_FloatNumber;
+               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
+               z = tk_FloatNumber;
+
+/*             x2 = x*cos(rz)+y*sin(rz);
+        y2 = -x*sin(rz)+y*cos(rz);
+        x = x2;
+        y = y2;
+        y2 = y*cos(rx)+z*sin(rx);
+        z2 = -y*sin(rx)+z*cos(rx);
+        y = y2;
+        z = z2;
+        x2 = x*cos(ry)-z*sin(ry);
+        z2 = x*sin(ry)+z*cos(ry);
+        x = x2;
+        z = z2;
+ */
+               vList[i].v[0] = x;
+               vList[i].v[1] = y;
+               vList[i].v[2] = z;
+       }
+       TK_BeyondRequire( TK_C_FACE, TK_LIST );
+       for ( i = 0; i < triCount; i++ )
+       {
+               TK_BeyondRequire( TK_C_FACE, TK_INTNUMBER );
+               if ( tk_IntNumber != i ) {
+                       Error( "File '%s', line %d:\nTriangle index mismatch.\n",
+                                  tk_SourceName, tk_Line );
+               }
+               for ( j = 0; j < 3; j++ )
+               {
+                       TK_BeyondRequire( TK_IDENTIFIER, TK_COLON );
+                       TK_FetchRequire( TK_INTNUMBER );
+                       if ( tk_IntNumber >= vertexCount ) {
+                               Error( "File '%s', line %d:\nVertex number"
+                                          " > vertexCount: %d\n", tk_SourceName, tk_Line,
+                                          tk_IntNumber );
+                       }
+                       tList[i].verts[2 - j][0] = vList[tk_IntNumber].v[0];
+                       tList[i].verts[2 - j][1] = vList[tk_IntNumber].v[1];
+                       tList[i].verts[2 - j][2] = vList[tk_IntNumber].v[2];
+#ifdef _QDATA
+                       tList[i].indicies[2 - j] = tk_IntNumber;
+#endif
+               }
+
+/*             printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+            "  v2: %f, %f, %f\n", i,
+            tList[i].verts[0][0],
+            tList[i].verts[0][1],
+            tList[i].verts[0][2],
+            tList[i].verts[1][0],
+            tList[i].verts[1][1],
+            tList[i].verts[1][2],
+            tList[i].verts[2][0],
+            tList[i].verts[2][1],
+            tList[i].verts[2][2]);
+ */
+       }
+
+       DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
+}
diff --git a/tools/heretic2/common/l3dslib.h b/tools/heretic2/common/l3dslib.h
new file mode 100644 (file)
index 0000000..0b1b537
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// l3dslib.h: header file for loading triangles from a 3DS triangle file
+//
+void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles );
+
+void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes );
+void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes );
diff --git a/tools/heretic2/common/lbmlib.c b/tools/heretic2/common/lbmlib.c
new file mode 100644 (file)
index 0000000..7eabd19
--- /dev/null
@@ -0,0 +1,1043 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// lbmlib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "lbmlib.h"
+
+// Ups the palette values so no pixels except 0 appear transparent
+// Need a value of 8 to cater for 16bit renderers
+
+typedef struct
+{
+       byte r;
+       byte g;
+       byte b;
+} paletteRGB_t;
+
+
+void CorrectPalette( byte *pal ){
+       paletteRGB_t    *p;
+
+       p = (paletteRGB_t *)pal;
+       // Color 0 always transparent
+       p->r = 0;
+       p->g = 0;
+       p->b = 0;
+}
+
+/*
+   ============================================================================
+
+                        LBM STUFF
+
+   ============================================================================
+ */
+
+
+typedef unsigned char UBYTE;
+//conflicts with windows typedef short                 WORD;
+typedef unsigned short UWORD;
+typedef long LONG;
+
+typedef enum
+{
+       ms_none,
+       ms_mask,
+       ms_transcolor,
+       ms_lasso
+} mask_t;
+
+typedef enum
+{
+       cm_none,
+       cm_rle1
+} compress_t;
+
+typedef struct
+{
+       UWORD w,h;
+       short x,y;
+       UBYTE nPlanes;
+       UBYTE masking;
+       UBYTE compression;
+       UBYTE pad1;
+       UWORD transparentColor;
+       UBYTE xAspect,yAspect;
+       short pageWidth,pageHeight;
+} bmhd_t;
+
+extern bmhd_t bmhd;                         // will be in native byte order
+
+
+
+#define FORMID ( 'F' + ( 'O' << 8 ) + ( (int)'R' << 16 ) + ( (int)'M' << 24 ) )
+#define ILBMID ( 'I' + ( 'L' << 8 ) + ( (int)'B' << 16 ) + ( (int)'M' << 24 ) )
+#define PBMID  ( 'P' + ( 'B' << 8 ) + ( (int)'M' << 16 ) + ( (int)' ' << 24 ) )
+#define BMHDID ( 'B' + ( 'M' << 8 ) + ( (int)'H' << 16 ) + ( (int)'D' << 24 ) )
+#define BODYID ( 'B' + ( 'O' << 8 ) + ( (int)'D' << 16 ) + ( (int)'Y' << 24 ) )
+#define CMAPID ( 'C' + ( 'M' << 8 ) + ( (int)'A' << 16 ) + ( (int)'P' << 24 ) )
+
+
+bmhd_t bmhd;
+
+int    Align( int l ){
+       if ( l & 1 ) {
+               return l + 1;
+       }
+       return l;
+}
+
+
+
+/*
+   ================
+   LBMRLEdecompress
+
+   Source must be evenly aligned!
+   ================
+ */
+byte  *LBMRLEDecompress( byte *source,byte *unpacked, int bpwidth ){
+       int count;
+       byte b,rept;
+
+       count = 0;
+
+       do
+       {
+               rept = *source++;
+
+               if ( rept > 0x80 ) {
+                       rept = ( rept ^ 0xff ) + 2;
+                       b = *source++;
+                       memset( unpacked,b,rept );
+                       unpacked += rept;
+               }
+               else if ( rept < 0x80 ) {
+                       rept++;
+                       memcpy( unpacked,source,rept );
+                       unpacked += rept;
+                       source += rept;
+               }
+               else{
+                       rept = 0;               // rept of 0x80 is NOP
+
+               }
+               count += rept;
+
+       } while ( count < bpwidth );
+
+       if ( count > bpwidth ) {
+               Error( "Decompression exceeded width!\n" );
+       }
+
+
+       return source;
+}
+
+
+/*
+   =================
+   LoadLBM
+   =================
+ */
+void LoadLBM( char *filename, byte **picture, byte **palette ){
+       byte    *LBMbuffer, *picbuffer, *cmapbuffer;
+       int y;
+       byte    *LBM_P, *LBMEND_P;
+       byte    *pic_p;
+       byte    *body_p;
+
+       int formtype,formlength;
+       int chunktype,chunklength;
+
+// qiet compiler warnings
+       picbuffer = NULL;
+       cmapbuffer = NULL;
+
+//
+// load the LBM
+//
+       LoadFile( filename, (void **)&LBMbuffer );
+
+//
+// parse the LBM header
+//
+       LBM_P = LBMbuffer;
+       if ( *(int *)LBMbuffer != LittleLong( FORMID ) ) {
+               Error( "No FORM ID at start of file!\n" );
+       }
+
+       LBM_P += 4;
+       formlength = BigLong( *(int *)LBM_P );
+       LBM_P += 4;
+       LBMEND_P = LBM_P + Align( formlength );
+
+       formtype = LittleLong( *(int *)LBM_P );
+
+       if ( formtype != ILBMID && formtype != PBMID ) {
+               Error( "Unrecognized form type: %c%c%c%c\n", formtype & 0xff
+                          ,( formtype >> 8 ) & 0xff,( formtype >> 16 ) & 0xff,( formtype >> 24 ) & 0xff );
+       }
+
+       LBM_P += 4;
+
+//
+// parse chunks
+//
+
+       while ( LBM_P < LBMEND_P )
+       {
+               chunktype = LBM_P[0] + ( LBM_P[1] << 8 ) + ( LBM_P[2] << 16 ) + ( LBM_P[3] << 24 );
+               LBM_P += 4;
+               chunklength = LBM_P[3] + ( LBM_P[2] << 8 ) + ( LBM_P[1] << 16 ) + ( LBM_P[0] << 24 );
+               LBM_P += 4;
+
+               switch ( chunktype )
+               {
+               case BMHDID:
+                       memcpy( &bmhd,LBM_P,sizeof( bmhd ) );
+                       bmhd.w = BigShort( bmhd.w );
+                       bmhd.h = BigShort( bmhd.h );
+                       bmhd.x = BigShort( bmhd.x );
+                       bmhd.y = BigShort( bmhd.y );
+                       bmhd.pageWidth = BigShort( bmhd.pageWidth );
+                       bmhd.pageHeight = BigShort( bmhd.pageHeight );
+                       break;
+
+               case CMAPID:
+                       cmapbuffer = malloc( 768 );
+                       memset( cmapbuffer, 0, 768 );
+                       memcpy( cmapbuffer, LBM_P, chunklength );
+                       CorrectPalette( cmapbuffer );
+                       break;
+
+               case BODYID:
+                       body_p = LBM_P;
+
+                       pic_p = picbuffer = malloc( bmhd.w * bmhd.h );
+                       if ( formtype == PBMID ) {
+                               //
+                               // unpack PBM
+                               //
+                               for ( y = 0 ; y < bmhd.h ; y++, pic_p += bmhd.w )
+                               {
+                                       if ( bmhd.compression == cm_rle1 ) {
+                                               body_p = LBMRLEDecompress( (byte *)body_p
+                                                                                                  , pic_p, bmhd.w );
+                                       }
+                                       else if ( bmhd.compression == cm_none ) {
+                                               memcpy( pic_p,body_p,bmhd.w );
+                                               body_p += Align( bmhd.w );
+                                       }
+                               }
+
+                       }
+                       else
+                       {
+                               //
+                               // unpack ILBM
+                               //
+                               Error( "%s is an interlaced LBM, not packed", filename );
+                       }
+                       break;
+               }
+
+               LBM_P += Align( chunklength );
+       }
+
+       free( LBMbuffer );
+
+       *picture = picbuffer;
+
+       if ( palette ) {
+               *palette = cmapbuffer;
+       }
+}
+
+
+/*
+   ============================================================================
+
+                            WRITE LBM
+
+   ============================================================================
+ */
+
+/*
+   ==============
+   WriteLBMfile
+   ==============
+ */
+void WriteLBMfile( char *filename, byte *data,
+                                  int width, int height, byte *palette ){
+       byte    *lbm, *lbmptr;
+       int    *formlength, *bmhdlength, *cmaplength, *bodylength;
+       int length;
+       bmhd_t basebmhd;
+
+       lbm = lbmptr = malloc( width * height + 1000 );
+
+//
+// start FORM
+//
+       *lbmptr++ = 'F';
+       *lbmptr++ = 'O';
+       *lbmptr++ = 'R';
+       *lbmptr++ = 'M';
+
+       formlength = (int*)lbmptr;
+       lbmptr += 4;                      // leave space for length
+
+       *lbmptr++ = 'P';
+       *lbmptr++ = 'B';
+       *lbmptr++ = 'M';
+       *lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+       *lbmptr++ = 'B';
+       *lbmptr++ = 'M';
+       *lbmptr++ = 'H';
+       *lbmptr++ = 'D';
+
+       bmhdlength = (int *)lbmptr;
+       lbmptr += 4;                      // leave space for length
+
+       memset( &basebmhd,0,sizeof( basebmhd ) );
+       basebmhd.w = BigShort( (short)width );
+       basebmhd.h = BigShort( (short)height );
+       basebmhd.nPlanes = BigShort( 8 );
+       basebmhd.xAspect = BigShort( 5 );
+       basebmhd.yAspect = BigShort( 6 );
+       basebmhd.pageWidth = BigShort( (short)width );
+       basebmhd.pageHeight = BigShort( (short)height );
+
+       memcpy( lbmptr,&basebmhd,sizeof( basebmhd ) );
+       lbmptr += sizeof( basebmhd );
+
+       length = lbmptr - (byte *)bmhdlength - 4;
+       *bmhdlength = BigLong( length );
+       if ( length & 1 ) {
+               *lbmptr++ = 0;          // pad chunk to even offset
+
+       }
+//
+// write CMAP
+//
+       *lbmptr++ = 'C';
+       *lbmptr++ = 'M';
+       *lbmptr++ = 'A';
+       *lbmptr++ = 'P';
+
+       cmaplength = (int *)lbmptr;
+       lbmptr += 4;                      // leave space for length
+
+       memcpy( lbmptr,palette,768 );
+       lbmptr += 768;
+
+       length = lbmptr - (byte *)cmaplength - 4;
+       *cmaplength = BigLong( length );
+       if ( length & 1 ) {
+               *lbmptr++ = 0;          // pad chunk to even offset
+
+       }
+//
+// write BODY
+//
+       *lbmptr++ = 'B';
+       *lbmptr++ = 'O';
+       *lbmptr++ = 'D';
+       *lbmptr++ = 'Y';
+
+       bodylength = (int *)lbmptr;
+       lbmptr += 4;                      // leave space for length
+
+       memcpy( lbmptr,data,width * height );
+       lbmptr += width * height;
+
+       length = lbmptr - (byte *)bodylength - 4;
+       *bodylength = BigLong( length );
+       if ( length & 1 ) {
+               *lbmptr++ = 0;          // pad chunk to even offset
+
+       }
+//
+// done
+//
+       length = lbmptr - (byte *)formlength - 4;
+       *formlength = BigLong( length );
+       if ( length & 1 ) {
+               *lbmptr++ = 0;          // pad chunk to even offset
+
+       }
+//
+// write output file
+//
+       SaveFile( filename, lbm, lbmptr - lbm );
+       free( lbm );
+}
+
+
+/*
+   ============================================================================
+
+   LOAD PCX
+
+   ============================================================================
+ */
+
+typedef struct
+{
+       char manufacturer;
+       char version;
+       char encoding;
+       char bits_per_pixel;
+       unsigned short xmin,ymin,xmax,ymax;
+       unsigned short hres,vres;
+       unsigned char palette[48];
+       char reserved;
+       char color_planes;
+       unsigned short bytes_per_line;
+       unsigned short palette_type;
+       char filler[58];
+       unsigned char data;             // unbounded
+} pcx_t;
+
+/*
+   ==============
+   LoadPCX
+   ==============
+ */
+void LoadPCX( char *filename, byte **pic, byte **palette, int *width, int *height ){
+       byte    *raw;
+       pcx_t   *pcx;
+       int x, y;
+       int len;
+       int dataByte, runLength;
+       byte    *out, *pix;
+
+       //
+       // load the file
+       //
+       len = LoadFile( filename, (void **)&raw );
+
+       //
+       // parse the PCX file
+       //
+       pcx = (pcx_t *)raw;
+       raw = &pcx->data;
+
+       pcx->xmin = LittleShort( pcx->xmin );
+       pcx->ymin = LittleShort( pcx->ymin );
+       pcx->xmax = LittleShort( pcx->xmax );
+       pcx->ymax = LittleShort( pcx->ymax );
+       pcx->hres = LittleShort( pcx->hres );
+       pcx->vres = LittleShort( pcx->vres );
+       pcx->bytes_per_line = LittleShort( pcx->bytes_per_line );
+       pcx->palette_type = LittleShort( pcx->palette_type );
+
+       if ( pcx->manufacturer != 0x0a
+                || pcx->version != 5
+                || pcx->encoding != 1
+                || pcx->bits_per_pixel != 8
+                || pcx->xmax >= 640
+                || pcx->ymax >= 480 ) {
+               Error( "Bad pcx file %s", filename );
+       }
+
+       if ( palette ) {
+               *palette = malloc( 768 );
+               memcpy( *palette, (byte *)pcx + len - 768, 768 );
+               CorrectPalette( *palette );
+       }
+
+       if ( width ) {
+               *width = pcx->xmax + 1;
+       }
+       if ( height ) {
+               *height = pcx->ymax + 1;
+       }
+
+       if ( !pic ) {
+               return;
+       }
+
+       out = malloc( ( pcx->ymax + 1 ) * ( pcx->xmax + 1 ) );
+       if ( !out ) {
+               Error( "Skin_Cache: couldn't allocate" );
+       }
+
+       *pic = out;
+
+       pix = out;
+
+       for ( y = 0 ; y <= pcx->ymax ; y++, pix += pcx->xmax + 1 )
+       {
+               for ( x = 0 ; x <= pcx->xmax ; )
+               {
+                       dataByte = *raw++;
+
+                       if ( ( dataByte & 0xC0 ) == 0xC0 ) {
+                               runLength = dataByte & 0x3F;
+                               dataByte = *raw++;
+                       }
+                       else{
+                               runLength = 1;
+                       }
+
+                       while ( runLength-- > 0 )
+                               pix[x++] = dataByte;
+               }
+
+       }
+
+       if ( raw - (byte *)pcx > len ) {
+               Error( "PCX file %s was malformed", filename );
+       }
+
+       free( pcx );
+}
+
+/*
+   ==============
+   WritePCXfile
+   ==============
+ */
+
+void StuffPackedByte( int curRepCount, byte curByte, byte** packPtr ){
+       byte* pack;
+
+       pack = *packPtr;
+
+       while ( curRepCount > 0 )
+       {
+               if ( curRepCount == 1 ) {
+                       if ( ( curByte & 0xc0 ) != 0xc0 ) {
+                               *pack++ = curByte;
+                       }
+                       else
+                       {
+                               *pack++ = 0xc1;
+                               *pack++ = curByte;
+                       }
+                       break;
+               }
+               if ( curRepCount < 0x0040 ) {
+                       *pack++ = ( 0x00c0 | curRepCount );
+                       curRepCount = 0;
+               }
+               else
+               {
+                       *pack++ = 0xff;
+                       curRepCount -= 0x003f;
+               }
+               *pack++ = curByte;
+       }
+       *packPtr = pack;
+}
+
+void WritePCXfile( char *filename, byte *data,
+                                  int width, int height, byte *palette ){
+       int i, j, length;
+       pcx_t       *pcx;
+       byte        *pack;
+       byte curByte;
+       int curRepCount;
+
+       pcx = malloc( width * height * 2 + 1000 );
+       memset( pcx, 0, sizeof( *pcx ) );
+
+       pcx->manufacturer = 0x0a;   // PCX id
+       pcx->version = 5;           // 256 color
+       pcx->encoding = 1;      // RLE
+       pcx->bits_per_pixel = 8;        // 256 color
+       pcx->xmin = 0;
+       pcx->ymin = 0;
+       pcx->xmax = LittleShort( (short)( width - 1 ) );
+       pcx->ymax = LittleShort( (short)( height - 1 ) );
+       pcx->hres = LittleShort( (short)width );
+       pcx->vres = LittleShort( (short)height );
+       pcx->color_planes = 1;      // chunky image
+       pcx->bytes_per_line = LittleShort( (short)width );
+       pcx->palette_type = LittleShort( 1 );     // not a grey scale
+
+       // pack the image
+       pack = &pcx->data;
+
+/*     for (i=0 ; i<height ; i++)
+    {
+        for (j=0 ; j<width ; j++)
+        {
+            if ( (*data & 0xc0) != 0xc0)
+   *pack++ = *data++;
+            else
+            {
+   *pack++ = 0xc1;
+   *pack++ = *data++;
+            }
+        }
+    }
+ */
+       for ( i = 0 ; i < height ; i++ )
+       {
+               curByte = *data;
+               curRepCount = 0;
+               for ( j = 0 ; j < width ; j++ )
+               {
+                       if ( *data == curByte ) {
+                               curRepCount++;
+                               data++;
+                               continue;
+                       }
+                       StuffPackedByte( curRepCount, curByte, &pack );
+                       curByte = *data++;
+                       curRepCount = 1;
+               }
+               StuffPackedByte( curRepCount, curByte, &pack );
+       }
+       // write the palette
+       *pack++ = 0x0c; // palette ID byte
+       for ( i = 0 ; i < 768 ; i++ )
+               *pack++ = *palette++;
+
+// write output file
+       length = pack - (byte *)pcx;
+       SaveFile( filename, pcx, length );
+
+       free( pcx );
+}
+
+
+/*
+   ============================================================================
+
+   LOAD IMAGE
+
+   ============================================================================
+ */
+
+/*
+   ==============
+   Load256Image
+
+   Will load either an lbm or pcx, depending on extension.
+   Any of the return pointers can be NULL if you don't want them.
+   ==============
+ */
+void Load256Image( char *name, byte **pixels, byte **palette,
+                                  int *width, int *height ){
+       char ext[128];
+
+       ExtractFileExtension( name, ext );
+       if ( !Q_strcasecmp( ext, "lbm" ) ) {
+               LoadLBM( name, pixels, palette );
+               if ( width ) {
+                       *width = bmhd.w;
+               }
+               if ( height ) {
+                       *height = bmhd.h;
+               }
+       }
+       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
+               LoadPCX( name, pixels, palette, width, height );
+       }
+       else{
+               Error( "%s doesn't have a known image extension", name );
+       }
+}
+
+
+/*
+   ==============
+   Save256Image
+
+   Will save either an lbm or pcx, depending on extension.
+   ==============
+ */
+void Save256Image( char *name, byte *pixels, byte *palette,
+                                  int width, int height ){
+       char ext[128];
+
+       ExtractFileExtension( name, ext );
+       if ( !Q_strcasecmp( ext, "lbm" ) ) {
+               WriteLBMfile( name, pixels, width, height, palette );
+       }
+       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
+               WritePCXfile( name, pixels, width, height, palette );
+       }
+       else{
+               Error( "%s doesn't have a known image extension", name );
+       }
+}
+
+
+
+
+/*
+   ============================================================================
+
+   TARGA IMAGE
+
+   ============================================================================
+ */
+
+typedef struct _TargaHeader
+{
+       unsigned char id_length, colormap_type, image_type;
+       unsigned short colormap_index, colormap_length;
+       unsigned char colormap_size;
+       unsigned short x_origin, y_origin, width, height;
+       unsigned char pixel_size, attributes;
+} TargaHeader;
+
+int fgetLittleShort( FILE *f ){
+       byte b1, b2;
+
+       b1 = fgetc( f );
+       b2 = fgetc( f );
+
+       return( (short)( b1 + ( b2 << 8 ) ) );
+}
+
+int fgetLittleLong( FILE *f ){
+       byte b1, b2, b3, b4;
+
+       b1 = fgetc( f );
+       b2 = fgetc( f );
+       b3 = fgetc( f );
+       b4 = fgetc( f );
+
+       return( b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 ) );
+}
+
+
+/*
+   =============
+   LoadTGA
+   =============
+ */
+void LoadTGA( char *name, byte **pixels, int *width, int *height ){
+       int columns, rows, numPixels;
+       byte            *pixbuf;
+       byte            *rowBuf;
+       int row, column;
+       FILE            *fin;
+       byte            *targa_rgba;
+       TargaHeader targa_header;
+       unsigned char red, green, blue, alphabyte;
+       unsigned char packetHeader, packetSize, j;
+       int flip;
+       int mirror;
+       int rowOffset;
+       int pixDirection;
+
+       fin = fopen( name, "rb" );
+       if ( !fin ) {
+               Error( "Couldn't read %s", name );
+       }
+
+       targa_header.id_length = fgetc( fin );
+       targa_header.colormap_type = fgetc( fin );
+       targa_header.image_type = fgetc( fin );
+
+       targa_header.colormap_index = fgetLittleShort( fin );
+       targa_header.colormap_length = fgetLittleShort( fin );
+       targa_header.colormap_size = fgetc( fin );
+       targa_header.x_origin = fgetLittleShort( fin );
+       targa_header.y_origin = fgetLittleShort( fin );
+       targa_header.width = fgetLittleShort( fin );
+       targa_header.height = fgetLittleShort( fin );
+       targa_header.pixel_size = fgetc( fin );
+       targa_header.attributes = fgetc( fin );
+       flip = ( targa_header.attributes & 0x020 ) == 0;
+       mirror = ( targa_header.attributes & 0x010 ) != 0;
+
+       if ( ( targa_header.image_type != 2 ) && ( targa_header.image_type != 10 ) ) {
+               Error( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
+       }
+
+       if ( targa_header.colormap_type || ( ( targa_header.pixel_size != 32 ) && ( targa_header.pixel_size != 24 ) ) ) {
+               Error( "Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
+       }
+
+       columns = targa_header.width;
+       rows = targa_header.height;
+       numPixels = columns * rows;
+
+       if ( width ) {
+               *width = columns;
+       }
+       if ( height ) {
+               *height = rows;
+       }
+
+       if ( !pixels ) {
+               return;
+       }
+
+       targa_rgba = malloc( numPixels * 4 );
+       *pixels = targa_rgba;
+
+       if ( flip ) {
+               pixbuf = targa_rgba + ( ( rows - 1 ) * columns * 4 );
+               rowOffset = -columns * 4;
+       }
+       else
+       {
+               pixbuf = targa_rgba;
+               rowOffset = columns * 4;
+       }
+       if ( mirror ) {
+               pixDirection = -4;
+               pixbuf += ( ( columns - 1 ) * 4 );
+       }
+       else
+       {
+               pixDirection = 4;
+       }
+
+       if ( targa_header.id_length ) {
+               fseek( fin, targa_header.id_length, SEEK_CUR );  // skip TARGA image comment
+
+       }
+       if ( targa_header.image_type == 2 ) {                 // Uncompressed, RGB images
+               for ( row = 0; row < rows; row++ )
+               {
+                       rowBuf = pixbuf;
+                       for ( column = 0; column < columns; column++ )
+                       {
+                               switch ( targa_header.pixel_size )
+                               {
+                               case 24:
+                                       blue = getc( fin );
+                                       green = getc( fin );
+                                       red = getc( fin );
+                                       rowBuf[0] = red;
+                                       rowBuf[1] = green;
+                                       rowBuf[2] = blue;
+                                       rowBuf[3] = 255;
+                                       rowBuf += pixDirection;
+                                       break;
+                               case 32:
+                                       blue = getc( fin );
+                                       green = getc( fin );
+                                       red = getc( fin );
+                                       alphabyte = getc( fin );
+                                       rowBuf[0] = red;
+                                       rowBuf[1] = green;
+                                       rowBuf[2] = blue;
+                                       rowBuf[3] = alphabyte;
+                                       rowBuf += pixDirection;
+                                       break;
+                               }
+                       }
+                       pixbuf += rowOffset;
+               }
+       }
+       else if ( targa_header.image_type == 10 ) {        // Runlength encoded RGB images
+               for ( row = 0; row < rows; row++ )
+               {
+                       rowBuf = pixbuf;
+                       for ( column = 0; column < columns; )
+                       {
+                               packetHeader = getc( fin );
+                               packetSize = 1 + ( packetHeader & 0x7f );
+                               if ( packetHeader & 0x80 ) {          // run-length packet
+                                       switch ( targa_header.pixel_size )
+                                       {
+                                       case 24:
+                                               blue = getc( fin );
+                                               green = getc( fin );
+                                               red = getc( fin );
+                                               alphabyte = 255;
+                                               break;
+                                       case 32:
+                                               blue = getc( fin );
+                                               green = getc( fin );
+                                               red = getc( fin );
+                                               alphabyte = getc( fin );
+                                               break;
+                                       }
+
+                                       for ( j = 0; j < packetSize; j++ )
+                                       {
+                                               rowBuf[0] = red;
+                                               rowBuf[1] = green;
+                                               rowBuf[2] = blue;
+                                               rowBuf[3] = alphabyte;
+                                               rowBuf += pixDirection;
+                                               column++;
+                                               if ( column == columns ) {             // run spans across rows
+                                                       column = 0;
+                                                       row++;
+                                                       if ( row >= rows ) {
+                                                               goto breakOut;
+                                                       }
+                                                       pixbuf += rowOffset;
+                                                       rowBuf = pixbuf;
+                                               }
+                                       }
+                               }
+                               else
+                               {                                       // non run-length packet
+                                       for ( j = 0; j < packetSize; j++ )
+                                       {
+                                               switch ( targa_header.pixel_size )
+                                               {
+                                               case 24:
+                                                       blue = getc( fin );
+                                                       green = getc( fin );
+                                                       red = getc( fin );
+                                                       rowBuf[0] = red;
+                                                       rowBuf[1] = green;
+                                                       rowBuf[2] = blue;
+                                                       rowBuf[3] = 255;
+                                                       rowBuf += pixDirection;
+                                                       break;
+                                               case 32:
+                                                       blue = getc( fin );
+                                                       green = getc( fin );
+                                                       red = getc( fin );
+                                                       alphabyte = getc( fin );
+                                                       rowBuf[0] = red;
+                                                       rowBuf[1] = green;
+                                                       rowBuf[2] = blue;
+                                                       rowBuf[3] = alphabyte;
+                                                       rowBuf += pixDirection;
+                                                       break;
+                                               }
+                                               column++;
+                                               if ( column == columns ) {    // pixel packet run spans across rows
+                                                       column = 0;
+                                                       row++;
+                                                       if ( row >= rows ) {
+                                                               goto breakOut;
+                                                       }
+                                                       pixbuf += rowOffset;
+                                                       rowBuf = pixbuf;
+                                               }
+                                       }
+                               }
+                       }
+breakOut:;
+                       pixbuf += rowOffset;
+               }
+       }
+       fclose( fin );
+}
+
+void MergeAlpha( byte *pix, byte *alpha, byte *pal, byte **out, int width, int height ){
+       int size, i;
+       byte    *data, *src, *srca;
+
+       size = width * height;
+       data = malloc( size * 4 );
+       if ( !data ) {
+               Error( "Could not allocate memory for true color image" );
+       }
+
+       *out = data;
+       src = pix;
+       srca = alpha;
+
+       for ( i = 0; i < size; i++, src++, srca++ )
+       {
+               *data++ = pal[*src * 3 + 0];      // r
+               *data++ = pal[*src * 3 + 1];      // g
+               *data++ = pal[*src * 3 + 2];      // b
+               *data++ = *srca;                  // a
+       }
+       free( pix );
+       free( alpha );
+       free( pal );
+}
+
+/*
+   ==============
+   LoadAnyImage
+
+   Return Value:
+    false: paletted texture
+    true:  true color RGBA image (no palette)
+   ==============
+ */
+qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height ){
+       char ext[128];
+       int len;
+       int alpha_width, alpha_height;
+       char alpha_name[128];
+       byte    *alpha_pixels;
+
+       ExtractFileExtension( name, ext );
+
+       if ( palette ) {
+               *palette = NULL;
+       }
+
+       if ( !Q_strcasecmp( ext, "lbm" ) ) {
+               LoadLBM( name, pixels, palette );
+               if ( width ) {
+                       *width = bmhd.w;
+               }
+               if ( height ) {
+                       *height = bmhd.h;
+               }
+               return false;
+       }
+       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
+               len = strlen( name );
+               strcpy( alpha_name, name );
+               strcpy( &alpha_name[len - 4], "_a.pcx" );                 // Alpha map name (may not exist)
+
+               if ( FileExists( alpha_name ) ) {
+                       LoadPCX( name, pixels, palette, width, height );                         // Load in image
+                       LoadPCX( alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height ); // Load in alpha map
+                       if ( ( *width != alpha_width ) || ( *height != alpha_height ) ) {
+                               Error( "Alpha image dimensions not equal to graphic image dimensions" );
+                       }
+                       MergeAlpha( *pixels, alpha_pixels, *palette, pixels, *width, *height );
+                       *palette = NULL; //Merge Frees pal
+                       return true;
+               }
+               else
+               {
+                       LoadPCX( name, pixels, palette, width, height );         // Load in image
+                       return false;
+               }
+       }
+       else if ( !Q_strcasecmp( ext, "tga" ) ) {
+               LoadTGA( name, pixels, width, height );
+               if ( palette ) {
+                       *palette = NULL;
+               }
+
+               return true;
+       }
+       else{
+               Error( "%s doesn't have a known image extension", name );
+       }
+
+       return false;
+}
diff --git a/tools/heretic2/common/lbmlib.h b/tools/heretic2/common/lbmlib.h
new file mode 100644 (file)
index 0000000..5ee2909
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// piclib.h
+
+
+void LoadLBM( char *filename, byte **picture, byte **palette );
+void WriteLBMfile( char *filename, byte *data, int width, int height
+                                  , byte *palette );
+void LoadPCX( char *filename, byte **picture, byte **palette, int *width, int *height );
+void WritePCXfile( char *filename, byte *data, int width, int height
+                                  , byte *palette );
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image( char *name, byte **pixels, byte **palette,
+                                  int *width, int *height );
+void Save256Image( char *name, byte *pixels, byte *palette,
+                                  int width, int height );
+
+
+void LoadTGA( char *filename, byte **pixels, int *width, int *height );
+
+qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height );
diff --git a/tools/heretic2/common/mathlib.c b/tools/heretic2/common/mathlib.c
new file mode 100644 (file)
index 0000000..8243d86
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// mathlib.c -- math primitives
+
+#include "cmdlib.h"
+#include "mathlib.h"
+
+vec3_t vec3_origin = {0,0,0};
+
+
+double VectorLength( vec3_t v ){
+       int i;
+       double length;
+
+       length = 0;
+       for ( i = 0 ; i < 3 ; i++ )
+               length += v[i] * v[i];
+       length = sqrt( length );     // FIXME
+
+       return length;
+}
+
+qboolean VectorCompare( vec3_t v1, vec3_t v2 ){
+       int i;
+
+       for ( i = 0 ; i < 3 ; i++ )
+               if ( fabs( v1[i] - v2[i] ) > EQUAL_EPSILON ) {
+                       return false;
+               }
+
+       return true;
+}
+
+vec_t Q_rint( vec_t in ){
+       return floor( in + 0.5 );
+}
+
+void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc ){
+       vc[0] = va[0] + scale * vb[0];
+       vc[1] = va[1] + scale * vb[1];
+       vc[2] = va[2] + scale * vb[2];
+}
+
+void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross ){
+       cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
+       cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
+       cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
+}
+
+vec_t _DotProduct( vec3_t v1, vec3_t v2 ){
+       return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
+}
+
+void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out ){
+       out[0] = va[0] - vb[0];
+       out[1] = va[1] - vb[1];
+       out[2] = va[2] - vb[2];
+}
+
+void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out ){
+       out[0] = va[0] + vb[0];
+       out[1] = va[1] + vb[1];
+       out[2] = va[2] + vb[2];
+}
+
+void _VectorCopy( vec3_t in, vec3_t out ){
+       out[0] = in[0];
+       out[1] = in[1];
+       out[2] = in[2];
+}
+
+void _VectorScale( vec3_t v, vec_t scale, vec3_t out ){
+       out[0] = v[0] * scale;
+       out[1] = v[1] * scale;
+       out[2] = v[2] * scale;
+}
+
+#if GDEF_COMPILER_MSVC
+#pragma optimize("g", off)  // went back to turning optimization off,
+                            // the bug_fix thing stopped working
+#endif
+
+vec_t VectorNormalize( vec3_t in, vec3_t out ){
+       vec_t length, ilength;
+
+       length = sqrt( in[0] * in[0] + in[1] * in[1] + in[2] * in[2] );
+       if ( length == 0 ) {
+               VectorClear( out );
+               return 0;
+       }
+
+       ilength = 1.0 / length;
+       out[0] = in[0] * ilength;
+       out[1] = in[1] * ilength;
+       out[2] = in[2] * ilength;
+
+       return length;
+}
+
+vec_t ColorNormalize( vec3_t in, vec3_t out ){
+       float max, scale;
+
+       max = in[0];
+       if ( in[1] > max ) {
+               max = in[1];
+       }
+       if ( in[2] > max ) {
+               max = in[2];
+       }
+
+       if ( max == 0 ) {
+               return 0;
+       }
+
+       scale = 1.0 / max;
+
+       VectorScale( in, scale, out );
+
+       return max;
+}
+
+#if GDEF_COMPILER_MSVC
+#pragma optimize("", on)
+#endif
+
+void VectorInverse( vec3_t v ){
+       v[0] = -v[0];
+       v[1] = -v[1];
+       v[2] = -v[2];
+}
+
+void ClearBounds( vec3_t mins, vec3_t maxs ){
+       mins[0] = mins[1] = mins[2] = 99999;
+       maxs[0] = maxs[1] = maxs[2] = -99999;
+}
+
+void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs ){
+       int i;
+       vec_t val;
+
+       for ( i = 0 ; i < 3 ; i++ )
+       {
+               val = v[i];
+               if ( val < mins[i] ) {
+                       mins[i] = val;
+               }
+               if ( val > maxs[i] ) {
+                       maxs[i] = val;
+               }
+       }
+}
diff --git a/tools/heretic2/common/mathlib.h b/tools/heretic2/common/mathlib.h
new file mode 100644 (file)
index 0000000..cd989ea
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+
+#include <math.h>
+/*
+   #ifdef DOUBLEVEC_T
+   typedef double vec_t;
+   #else
+   typedef float vec_t;
+   #endif
+   typedef vec_t vec3_t[3];
+ */
+#define SIDE_FRONT      0
+#define SIDE_ON         2
+#define SIDE_BACK       1
+#define SIDE_CROSS      -2
+
+#define Q_PI    3.14159265358979323846
+
+extern vec3_t vec3_origin;
+
+#define EQUAL_EPSILON   0.001
+
+qboolean VectorCompare( vec3_t v1, vec3_t v2 );
+
+#define DotProduct( x,y ) ( x[0] * y[0] + x[1] * y[1] + x[2] * y[2] )
+#define VectorSubtract( a,b,c ) {c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; }
+#define VectorAdd( a,b,c ) {c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; }
+#define VectorCopy( a,b ) {b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
+#define VectorScale( a,b,c ) {c[0] = b * a[0]; c[1] = b * a[1]; c[2] = b * a[2]; }
+#define VectorClear( x ) {x[0] = x[1] = x[2] = 0; }
+#define VectorNegate( x ) {x[0] = -x[0]; x[1] = -x[1]; x[2] = -x[2]; }
+
+vec_t Q_rint( vec_t in );
+vec_t _DotProduct( vec3_t v1, vec3_t v2 );
+void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out );
+void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out );
+void _VectorCopy( vec3_t in, vec3_t out );
+void _VectorScale( vec3_t v, vec_t scale, vec3_t out );
+
+double VectorLength( vec3_t v );
+
+void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc );
+
+void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross );
+vec_t VectorNormalize( vec3_t in, vec3_t out );
+vec_t ColorNormalize( vec3_t in, vec3_t out );
+void VectorInverse( vec3_t v );
+
+void ClearBounds( vec3_t mins, vec3_t maxs );
+void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs );
+
+#endif
diff --git a/tools/heretic2/common/md4.c b/tools/heretic2/common/md4.c
new file mode 100644 (file)
index 0000000..f503422
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+    mdfour.c
+
+    An implementation of MD4 designed for use in the samba SMB
+    authentication protocol
+
+    Copyright (C) 1997-1998  Andrew Tridgell
+
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version 2
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+    See the GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to:
+
+        Free Software Foundation, Inc.
+        59 Temple Place - Suite 330
+        Boston, MA  02111-1307, USA
+
+    $Id: mdfour.c 7689 2007-11-12 14:28:40Z divverent $
+ */
+
+#include <string.h>     /* XoXus: needed for memset call */
+#include "md4.h"
+
+/* NOTE: This code makes no attempt to be fast!
+
+   It assumes that a int is at least 32 bits long
+ */
+
+static struct mdfour *m;
+
+#define F( X,Y,Z ) ( ( (X)&( Y ) ) | ( ( ~( X ) ) & ( Z ) ) )
+#define G( X,Y,Z ) ( ( (X)&( Y ) ) | ( (X)&( Z ) ) | ( (Y)&( Z ) ) )
+#define H( X,Y,Z ) ( ( X ) ^ ( Y ) ^ ( Z ) )
+#ifdef LARGE_INT32
+#define lshift( x,s ) ( ( ( ( x ) << ( s ) ) & 0xFFFFFFFF ) | ( ( ( x ) >> ( 32 - ( s ) ) ) & 0xFFFFFFFF ) )
+#else
+#define lshift( x,s ) ( ( ( x ) << ( s ) ) | ( ( x ) >> ( 32 - ( s ) ) ) )
+#endif
+
+#define ROUND1( a,b,c,d,k,s ) a = lshift( a + F( b,c,d ) + X[k], s )
+#define ROUND2( a,b,c,d,k,s ) a = lshift( a + G( b,c,d ) + X[k] + 0x5A827999,s )
+#define ROUND3( a,b,c,d,k,s ) a = lshift( a + H( b,c,d ) + X[k] + 0x6ED9EBA1,s )
+
+/* this applies md4 to 64 byte chunks */
+static void mdfour64( uint32 *M ){
+       int j;
+       uint32 AA, BB, CC, DD;
+       uint32 X[16];
+       uint32 A,B,C,D;
+
+       for ( j = 0; j < 16; j++ )
+               X[j] = M[j];
+
+       A = m->A; B = m->B; C = m->C; D = m->D;
+       AA = A; BB = B; CC = C; DD = D;
+
+       ROUND1( A,B,C,D,  0,  3 );  ROUND1( D,A,B,C,  1,  7 );
+       ROUND1( C,D,A,B,  2, 11 );  ROUND1( B,C,D,A,  3, 19 );
+       ROUND1( A,B,C,D,  4,  3 );  ROUND1( D,A,B,C,  5,  7 );
+       ROUND1( C,D,A,B,  6, 11 );  ROUND1( B,C,D,A,  7, 19 );
+       ROUND1( A,B,C,D,  8,  3 );  ROUND1( D,A,B,C,  9,  7 );
+       ROUND1( C,D,A,B, 10, 11 );  ROUND1( B,C,D,A, 11, 19 );
+       ROUND1( A,B,C,D, 12,  3 );  ROUND1( D,A,B,C, 13,  7 );
+       ROUND1( C,D,A,B, 14, 11 );  ROUND1( B,C,D,A, 15, 19 );
+
+       ROUND2( A,B,C,D,  0,  3 );  ROUND2( D,A,B,C,  4,  5 );
+       ROUND2( C,D,A,B,  8,  9 );  ROUND2( B,C,D,A, 12, 13 );
+       ROUND2( A,B,C,D,  1,  3 );  ROUND2( D,A,B,C,  5,  5 );
+       ROUND2( C,D,A,B,  9,  9 );  ROUND2( B,C,D,A, 13, 13 );
+       ROUND2( A,B,C,D,  2,  3 );  ROUND2( D,A,B,C,  6,  5 );
+       ROUND2( C,D,A,B, 10,  9 );  ROUND2( B,C,D,A, 14, 13 );
+       ROUND2( A,B,C,D,  3,  3 );  ROUND2( D,A,B,C,  7,  5 );
+       ROUND2( C,D,A,B, 11,  9 );  ROUND2( B,C,D,A, 15, 13 );
+
+       ROUND3( A,B,C,D,  0,  3 );  ROUND3( D,A,B,C,  8,  9 );
+       ROUND3( C,D,A,B,  4, 11 );  ROUND3( B,C,D,A, 12, 15 );
+       ROUND3( A,B,C,D,  2,  3 );  ROUND3( D,A,B,C, 10,  9 );
+       ROUND3( C,D,A,B,  6, 11 );  ROUND3( B,C,D,A, 14, 15 );
+       ROUND3( A,B,C,D,  1,  3 );  ROUND3( D,A,B,C,  9,  9 );
+       ROUND3( C,D,A,B,  5, 11 );  ROUND3( B,C,D,A, 13, 15 );
+       ROUND3( A,B,C,D,  3,  3 );  ROUND3( D,A,B,C, 11,  9 );
+       ROUND3( C,D,A,B,  7, 11 );  ROUND3( B,C,D,A, 15, 15 );
+
+       A += AA; B += BB; C += CC; D += DD;
+
+#ifdef LARGE_INT32
+       A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
+       C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
+#endif
+
+       for ( j = 0; j < 16; j++ )
+               X[j] = 0;
+
+       m->A = A; m->B = B; m->C = C; m->D = D;
+}
+
+static void copy64( uint32 *M, unsigned char *in ){
+       int i;
+
+       for ( i = 0; i < 16; i++ )
+               M[i] = ( in[i * 4 + 3] << 24 ) | ( in[i * 4 + 2] << 16 ) |
+                          ( in[i * 4 + 1] << 8 ) | ( in[i * 4 + 0] << 0 );
+}
+
+static void copy4( unsigned char *out,uint32 x ){
+       out[0] = x & 0xFF;
+       out[1] = ( x >> 8 ) & 0xFF;
+       out[2] = ( x >> 16 ) & 0xFF;
+       out[3] = ( x >> 24 ) & 0xFF;
+}
+
+void mdfour_begin( struct mdfour *md ){
+       md->A = 0x67452301;
+       md->B = 0xefcdab89;
+       md->C = 0x98badcfe;
+       md->D = 0x10325476;
+       md->totalN = 0;
+}
+
+
+static void mdfour_tail( unsigned char *in, int n ){
+       unsigned char buf[128];
+       uint32 M[16];
+       uint32 b;
+
+       m->totalN += n;
+
+       b = m->totalN * 8;
+
+       memset( buf, 0, 128 );
+       if ( n ) {
+               memcpy( buf, in, n );
+       }
+       buf[n] = 0x80;
+
+       if ( n <= 55 ) {
+               copy4( buf + 56, b );
+               copy64( M, buf );
+               mdfour64( M );
+       }
+       else {
+               copy4( buf + 120, b );
+               copy64( M, buf );
+               mdfour64( M );
+               copy64( M, buf + 64 );
+               mdfour64( M );
+       }
+}
+
+void mdfour_update( struct mdfour *md, unsigned char *in, int n ){
+       uint32 M[16];
+
+// start of edit by Forest 'LordHavoc' Hale
+// commented out to prevent crashing when length is 0
+//     if (n == 0) mdfour_tail(in, n);
+// end of edit by Forest 'LordHavoc' Hale
+
+       m = md;
+
+       while ( n >= 64 ) {
+               copy64( M, in );
+               mdfour64( M );
+               in += 64;
+               n -= 64;
+               m->totalN += 64;
+       }
+
+       mdfour_tail( in, n );
+}
+
+
+void mdfour_result( struct mdfour *md, unsigned char *out ){
+       m = md;
+
+       copy4( out, m->A );
+       copy4( out + 4, m->B );
+       copy4( out + 8, m->C );
+       copy4( out + 12, m->D );
+}
+
+
+void mdfour( unsigned char *out, unsigned char *in, int n ){
+       struct mdfour md;
+       mdfour_begin( &md );
+       mdfour_update( &md, in, n );
+       mdfour_result( &md, out );
+}
+
+///////////////////////////////////////////////////////////////
+//     MD4-based checksum utility functions
+//
+//     Copyright (C) 2000       Jeff Teunissen <d2deek@pmail.net>
+//
+//     Author: Jeff Teunissen  <d2deek@pmail.net>
+//     Date: 01 Jan 2000
+
+unsigned Com_BlockChecksum( void *buffer, int length ){
+       int digest[4];
+       unsigned val;
+
+       mdfour( (unsigned char *) digest, (unsigned char *) buffer, length );
+
+       val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
+
+       return val;
+}
+
+void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ){
+       mdfour( outbuf, (unsigned char *) buffer, len );
+}
diff --git a/tools/heretic2/common/md4.h b/tools/heretic2/common/md4.h
new file mode 100644 (file)
index 0000000..6f64c28
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    mdfour.h
+
+    an implementation of MD4 designed for use in the SMB authentication
+    protocol
+
+    Copyright (C) Andrew Tridgell 1997-1998
+
+    This program is free software; you can redistribute it and/or
+    modify it under the terms of the GNU General Public License
+    as published by the Free Software Foundation; either version 2
+    of the License, or (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+    See the GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to:
+
+        Free Software Foundation, Inc.
+        59 Temple Place - Suite 330
+        Boston, MA  02111-1307, USA
+ */
+
+#ifndef _MDFOUR_H
+#define _MDFOUR_H
+
+#ifndef int32
+#define int32 int
+#endif
+
+#if SIZEOF_INT > 4
+#define LARGE_INT32
+#endif
+
+#ifndef uint32
+#define uint32 unsigned int32
+#endif
+
+struct mdfour {
+       uint32 A, B, C, D;
+       uint32 totalN;
+};
+
+void mdfour_begin( struct mdfour *md ); // old: MD4Init
+void mdfour_update( struct mdfour *md, unsigned char *in, int n ); //old: MD4Update
+void mdfour_result( struct mdfour *md, unsigned char *out ); // old: MD4Final
+void mdfour( unsigned char *out, unsigned char *in, int n );
+
+unsigned Com_BlockChecksum( void *buffer, int length );
+void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf );
+
+#endif  // _MDFOUR_H
diff --git a/tools/heretic2/common/path_init.c b/tools/heretic2/common/path_init.c
new file mode 100644 (file)
index 0000000..254977b
--- /dev/null
@@ -0,0 +1,391 @@
+/* -------------------------------------------------------------------------------
+
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+   Nurail: Swiped from Q3Map2
+ */
+
+#include "globaldefs.h"
+
+#if !GDEF_OS_WINDOWS
+       #include <unistd.h>
+       #include <pwd.h>
+       #include <limits.h>
+#endif // !GDEF_OS_WINDOWS
+
+/* dependencies */
+#include "cmdlib.h"
+#include "inout.h"
+
+/* path support */
+#define MAX_BASE_PATHS  10
+#define MAX_GAME_PATHS  10
+
+char                    *homePath;
+char installPath[ MAX_OS_PATH ];
+
+int numBasePaths;
+char                    *basePaths[ MAX_BASE_PATHS ];
+int numGamePaths;
+char                    *gamePaths[ MAX_GAME_PATHS ];
+
+/*
+   some of this code is based off the original q3map port from loki
+   and finds various paths. moved here from bsp.c for clarity.
+ */
+
+/*
+   PathLokiGetHomeDir()
+   gets the user's home dir (for ~/.q3a)
+ */
+
+char *LokiGetHomeDir( void ){
+       #if GDEF_OS_WINDOWS
+       return NULL;
+       #else // !GDEF_OS_WINDOWS
+       char            *home;
+       uid_t id;
+       struct passwd   *pwd;
+
+
+       /* get the home environment variable */
+       home = getenv( "HOME" );
+       if ( home == NULL ) {
+               /* do some more digging */
+               id = getuid();
+               setpwent();
+               while ( ( pwd = getpwent() ) != NULL )
+               {
+                       if ( pwd->pw_uid == id ) {
+                               home = pwd->pw_dir;
+                               break;
+                       }
+               }
+               endpwent();
+       }
+
+       /* return it */
+       return home;
+       #endif // !GDEF_OS_WINDOWS
+}
+
+
+
+/*
+   PathLokiInitPaths()
+   initializes some paths on linux/os x
+ */
+
+void LokiInitPaths( char *argv0 ){
+       #if GDEF_OS_WINDOWS
+       /* this is kinda crap, but hey */
+       strcpy( installPath, "../" );
+       #else // !GDEF_OS_WINDOWS
+       char temp[ MAX_OS_PATH ];
+       char        *home;
+       char        *path;
+       char        *last;
+       qboolean found;
+
+
+       /* get home dir */
+       home = LokiGetHomeDir();
+       if ( home == NULL ) {
+               home = ".";
+       }
+
+       /* do some path divining */
+       strcpy( temp, argv0 );
+       if ( strrchr( temp, '/' ) ) {
+               argv0 = strrchr( argv0, '/' ) + 1;
+       }
+       else
+       {
+               /* get path environment variable */
+               path = getenv( "PATH" );
+
+               /* minor setup */
+               last[ 0 ] = path[ 0 ];
+               last[ 1 ] = '\0';
+               found = false;
+
+               /* go through each : segment of path */
+               while ( last[ 0 ] != '\0' && found == false )
+               {
+                       /* null out temp */
+                       temp[ 0 ] = '\0';
+
+                       /* find next chunk */
+                       last = strchr( path, ':' );
+                       if ( last == NULL ) {
+                               last = path + strlen( path );
+                       }
+
+                       /* found home dir candidate */
+                       if ( *path == '~' ) {
+                               strcpy( temp, home );
+                               path++;
+                       }
+
+                       /* concatenate */
+                       if ( last > ( path + 1 ) ) {
+                               strncat( temp, path, ( last - path ) );
+                               strcat( temp, "/" );
+                       }
+                       strcat( temp, "./" );
+                       strcat( temp, argv0 );
+
+                       /* verify the path */
+                       if ( access( temp, X_OK ) == 0 ) {
+                               found++;
+                       }
+                       path = last + 1;
+               }
+       }
+
+       /* flake */
+       if ( realpath( temp, installPath ) ) {
+               /* q3map is in "tools/" */
+               *( strrchr( installPath, '/' ) ) = '\0';
+               *( strrchr( installPath, '/' ) + 1 ) = '\0';
+       }
+
+       /* set home path */
+       homePath = home;
+       #endif // !GDEF_OS_WINDOWS
+}
+
+
+
+/*
+   CleanPath() - ydnar
+   cleans a dos path \ -> /
+ */
+
+void CleanPath( char *path ){
+       while ( *path )
+       {
+               if ( *path == '\\' ) {
+                       *path = '/';
+               }
+               path++;
+       }
+}
+
+/*
+   AddBasePath() - ydnar
+   adds a base path to the list
+ */
+
+void AddBasePath( char *path ){
+       /* dummy check */
+       if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
+               return;
+       }
+
+       /* add it to the list */
+       basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
+       strcpy( basePaths[ numBasePaths ], path );
+       CleanPath( basePaths[ numBasePaths ] );
+       numBasePaths++;
+}
+
+
+
+/*
+   AddHomeBasePath() - ydnar
+   adds a base path to the beginning of the list, prefixed by ~/
+ */
+
+void AddHomeBasePath( char *path ){
+       #if !GDEF_OS_WINDOWS
+       int i;
+       char temp[ MAX_OS_PATH ];
+
+
+       /* dummy check */
+       if ( path == NULL || path[ 0 ] == '\0' ) {
+               return;
+       }
+
+       /* make a hole */
+       for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
+               basePaths[ i + 1 ] = basePaths[ i ];
+
+       /* concatenate home dir and path */
+       sprintf( temp, "%s/%s", homePath, path );
+
+       /* add it to the list */
+       basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
+       strcpy( basePaths[ 0 ], temp );
+       CleanPath( basePaths[ 0 ] );
+       numBasePaths++;
+       #endif // !GDEF_OS_WINDOWS
+}
+
+
+
+/*
+   AddGamePath() - ydnar
+   adds a game path to the list
+ */
+
+void AddGamePath( char *path ){
+       /* dummy check */
+       if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
+               return;
+       }
+
+       /* add it to the list */
+       gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
+       strcpy( gamePaths[ numGamePaths ], path );
+       CleanPath( gamePaths[ numGamePaths ] );
+       numGamePaths++;
+}
+
+
+
+
+/*
+   InitPaths() - ydnar
+   cleaned up some of the path initialization code from bsp.c
+   will remove any arguments it uses
+ */
+
+void InitPaths( int *argc, char **argv ){
+       int i, j, k, len, len2;
+       char temp[ MAX_OS_PATH ];
+       char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
+
+       strcpy( gamePath, "base" );
+       strcpy( game_magic, "h" );
+       strcpy( homeBasePath, ".heretic2" );
+
+       /* note it */
+       Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
+
+       /* get the install path for backup */
+       LokiInitPaths( argv[ 0 ] );
+
+       /* set game to default (q3a) */
+       numBasePaths = 0;
+       numGamePaths = 0;
+
+       /* parse through the arguments and extract those relevant to paths */
+       for ( i = 0; i < *argc; i++ )
+       {
+               /* check for null */
+               if ( argv[ i ] == NULL ) {
+                       continue;
+               }
+
+               /* -fs_basepath */
+               if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
+                       if ( ++i >= *argc ) {
+                               Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+                       }
+                       argv[ i - 1 ] = NULL;
+                       AddBasePath( argv[ i ] );
+                       argv[ i ] = NULL;
+               }
+
+       }
+
+       /* remove processed arguments */
+       for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
+       {
+               for ( j; j < *argc && argv[ j ] == NULL; j++ ) ;
+               argv[ i ] = argv[ j ];
+               if ( argv[ i ] != NULL ) {
+                       k++;
+               }
+       }
+       *argc = k;
+
+       /* add standard game path */
+       AddGamePath( gamePath );
+
+       /* if there is no base path set, figure it out */
+       if ( numBasePaths == 0 ) {
+               /* this is another crappy replacement for SetQdirFromPath() */
+               len2 = strlen( game_magic );
+               for ( i = 0; i < *argc && numBasePaths == 0; i++ )
+               {
+                       /* extract the arg */
+                       strcpy( temp, argv[ i ] );
+                       CleanPath( temp );
+                       len = strlen( temp );
+                       Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
+
+                       /* this is slow, but only done once */
+                       for ( j = 0; j < ( len - len2 ); j++ )
+                       {
+                               /* check for the game's magic word */
+                               if ( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 ) {
+                                       /* now find the next slash and nuke everything after it */
+                                       while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
+                                       temp[ j ] = '\0';
+
+                                       /* add this as a base path */
+                                       AddBasePath( temp );
+                                       break;
+                               }
+                       }
+               }
+
+               /* add install path */
+               if ( numBasePaths == 0 ) {
+                       AddBasePath( installPath );
+               }
+
+               /* check again */
+               if ( numBasePaths == 0 ) {
+                       Error( "Failed to find a valid base path." );
+               }
+       }
+
+       /* this only affects unix */
+       AddHomeBasePath( homeBasePath );
+
+       /* initialize vfs paths */
+       if ( numBasePaths > MAX_BASE_PATHS ) {
+               numBasePaths = MAX_BASE_PATHS;
+       }
+       if ( numGamePaths > MAX_GAME_PATHS ) {
+               numGamePaths = MAX_GAME_PATHS;
+       }
+
+       /* walk the list of game paths */
+       //for( j = 0; j < numGamePaths; j++ )
+       //{
+       /* walk the list of base paths */
+       //      for( i = 0; i < numBasePaths; i++ )
+       //      {
+       /* create a full path and initialize it */
+       //              sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
+       //              vfsInitDirectory( temp );
+       //      }
+       //}
+
+       /* done */
+       Sys_Printf( "\n" );
+}
diff --git a/tools/heretic2/common/polylib.c b/tools/heretic2/common/polylib.c
new file mode 100644 (file)
index 0000000..af5df49
--- /dev/null
@@ -0,0 +1,665 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "polylib.h"
+
+
+extern int numthreads;
+
+// counters are only bumped when running single threaded,
+// because they are an awefull coherence problem
+int c_active_windings;
+int c_peak_windings;
+int c_winding_allocs;
+int c_winding_points;
+
+#define BOGUS_RANGE 8192
+
+void pw( winding_t *w ){
+       int i;
+       for ( i = 0 ; i < w->numpoints ; i++ )
+               printf( "(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2] );
+}
+
+
+/*
+   =============
+   AllocWinding
+   =============
+ */
+winding_t   *AllocWinding( int points ){
+       winding_t   *w;
+       int s;
+
+       if ( numthreads == 1 ) {
+               c_winding_allocs++;
+               c_winding_points += points;
+               c_active_windings++;
+               if ( c_active_windings > c_peak_windings ) {
+                       c_peak_windings = c_active_windings;
+               }
+       }
+       s = sizeof( vec_t ) * 3 * points + sizeof( int );
+       w = malloc( s );
+       if ( !w ) {
+               Error( "AllocWinding MALLOC failed!  Could not allocate %s bytes.", s );
+       }
+       memset( w, 0, s );
+       return w;
+}
+
+void FreeWinding( winding_t *w ){
+       if ( *(unsigned *)w == 0xdeaddead ) {
+               Error( "FreeWinding: freed a freed winding" );
+       }
+       *(unsigned *)w = 0xdeaddead;
+
+       if ( numthreads == 1 ) {
+               c_active_windings--;
+       }
+       free( w );
+}
+
+/*
+   ============
+   RemoveColinearPoints
+   ============
+ */
+int c_removed;
+
+void    RemoveColinearPoints( winding_t *w ){
+       int i, j, k;
+       vec3_t v1, v2;
+       int nump;
+       vec3_t p[MAX_POINTS_ON_WINDING];
+
+       nump = 0;
+       for ( i = 0 ; i < w->numpoints ; i++ )
+       {
+               j = ( i + 1 ) % w->numpoints;
+               k = ( i + w->numpoints - 1 ) % w->numpoints;
+               VectorSubtract( w->p[j], w->p[i], v1 );
+               VectorSubtract( w->p[i], w->p[k], v2 );
+               VectorNormalize( v1,v1 );
+               VectorNormalize( v2,v2 );
+               if ( DotProduct( v1, v2 ) < 0.999 ) {
+                       VectorCopy( w->p[i], p[nump] );
+                       nump++;
+               }
+       }
+
+       if ( nump == w->numpoints ) {
+               return;
+       }
+
+       if ( numthreads == 1 ) {
+               c_removed += w->numpoints - nump;
+       }
+       w->numpoints = nump;
+       memcpy( w->p, p, nump * sizeof( p[0] ) );
+}
+
+/*
+   ============
+   WindingPlane
+   ============
+ */
+void WindingPlane( winding_t *w, vec3_t normal, vec_t *dist ){
+       vec3_t v1, v2;
+
+       VectorSubtract( w->p[1], w->p[0], v1 );
+       VectorSubtract( w->p[2], w->p[0], v2 );
+       CrossProduct( v2, v1, normal );
+       VectorNormalize( normal, normal );
+       *dist = DotProduct( w->p[0], normal );
+
+}
+
+/*
+   =============
+   WindingArea
+   =============
+ */
+vec_t   WindingArea( winding_t *w ){
+       int i;
+       vec3_t d1, d2, cross;
+       vec_t total;
+
+       total = 0;
+       for ( i = 2 ; i < w->numpoints ; i++ )
+       {
+               VectorSubtract( w->p[i - 1], w->p[0], d1 );
+               VectorSubtract( w->p[i], w->p[0], d2 );
+               CrossProduct( d1, d2, cross );
+               total += 0.5 * VectorLength( cross );
+       }
+       return total;
+}
+
+void    WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs ){
+       vec_t v;
+       int i,j;
+
+       mins[0] = mins[1] = mins[2] = 99999;
+       maxs[0] = maxs[1] = maxs[2] = -99999;
+
+       for ( i = 0 ; i < w->numpoints ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       v = w->p[i][j];
+                       if ( v < mins[j] ) {
+                               mins[j] = v;
+                       }
+                       if ( v > maxs[j] ) {
+                               maxs[j] = v;
+                       }
+               }
+       }
+}
+
+/*
+   =============
+   WindingCenter
+   =============
+ */
+void    WindingCenter( winding_t *w, vec3_t center ){
+       int i;
+       float scale;
+
+       VectorCopy( vec3_origin, center );
+       for ( i = 0 ; i < w->numpoints ; i++ )
+               VectorAdd( w->p[i], center, center );
+
+       scale = 1.0 / w->numpoints;
+       VectorScale( center, scale, center );
+}
+
+/*
+   =================
+   BaseWindingForPlane
+   =================
+ */
+winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
+       int i, x;
+       vec_t max, v;
+       vec3_t org, vright, vup;
+       winding_t   *w;
+
+// find the major axis
+
+       max = -BOGUS_RANGE;
+       x = -1;
+       for ( i = 0 ; i < 3; i++ )
+       {
+               v = fabs( normal[i] );
+               if ( v > max ) {
+                       x = i;
+                       max = v;
+               }
+       }
+       if ( x == -1 ) {
+               Error( "BaseWindingForPlane: no axis found" );
+       }
+
+       VectorCopy( vec3_origin, vup );
+       switch ( x )
+       {
+       case 0:
+       case 1:
+               vup[2] = 1;
+               break;
+       case 2:
+               vup[0] = 1;
+               break;
+       }
+
+       v = DotProduct( vup, normal );
+       VectorMA( vup, -v, normal, vup );
+       VectorNormalize( vup, vup );
+
+       VectorScale( normal, dist, org );
+
+       CrossProduct( vup, normal, vright );
+
+       VectorScale( vup, 8192, vup );
+       VectorScale( vright, 8192, vright );
+
+// project a really big        axis aligned box onto the plane
+       w = AllocWinding( 4 );
+
+       VectorSubtract( org, vright, w->p[0] );
+       VectorAdd( w->p[0], vup, w->p[0] );
+
+       VectorAdd( org, vright, w->p[1] );
+       VectorAdd( w->p[1], vup, w->p[1] );
+
+       VectorAdd( org, vright, w->p[2] );
+       VectorSubtract( w->p[2], vup, w->p[2] );
+
+       VectorSubtract( org, vright, w->p[3] );
+       VectorSubtract( w->p[3], vup, w->p[3] );
+
+       w->numpoints = 4;
+
+       return w;
+}
+
+/*
+   ==================
+   CopyWinding
+   ==================
+ */
+winding_t   *CopyWinding( winding_t *w ){
+       int size;
+       winding_t   *c;
+
+       c = AllocWinding( w->numpoints );
+       size = (int)( (winding_t *)0 )->p[w->numpoints];
+       memcpy( c, w, size );
+       return c;
+}
+
+/*
+   ==================
+   ReverseWinding
+   ==================
+ */
+winding_t   *ReverseWinding( winding_t *w ){
+       int i;
+       winding_t   *c;
+
+       c = AllocWinding( w->numpoints );
+       for ( i = 0 ; i < w->numpoints ; i++ )
+       {
+               VectorCopy( w->p[w->numpoints - 1 - i], c->p[i] );
+       }
+       c->numpoints = w->numpoints;
+       return c;
+}
+
+
+/*
+   =============
+   ClipWindingEpsilon
+   =============
+ */
+void    ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
+                                                       vec_t epsilon, winding_t **front, winding_t **back ){
+       vec_t dists[MAX_POINTS_ON_WINDING + 4];
+       int sides[MAX_POINTS_ON_WINDING + 4];
+       int counts[3];
+       vec_t dot;          // VC 4.2 optimizer bug if not static
+       int i, j;
+       vec_t   *p1, *p2;
+       vec3_t mid;
+       winding_t   *f, *b;
+       int maxpts;
+
+       if ( in->numpoints >= MAX_POINTS_ON_WINDING - 4 ) {
+               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
+       }
+
+       counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+       for ( i = 0 ; i < in->numpoints ; i++ )
+       {
+               dot = DotProduct( in->p[i], normal );
+               dot -= dist;
+               dists[i] = dot;
+               if ( dot > epsilon ) {
+                       sides[i] = SIDE_FRONT;
+               }
+               else if ( dot < -epsilon ) {
+                       sides[i] = SIDE_BACK;
+               }
+               else
+               {
+                       sides[i] = SIDE_ON;
+               }
+               counts[sides[i]]++;
+       }
+       sides[i] = sides[0];
+       dists[i] = dists[0];
+
+       *front = *back = NULL;
+
+       if ( !counts[0] ) {
+               *back = CopyWinding( in );
+               return;
+       }
+       if ( !counts[1] ) {
+               *front = CopyWinding( in );
+               return;
+       }
+
+       maxpts = in->numpoints + 4;   // cant use counts[0]+2 because
+                                     // of fp grouping errors
+
+       *front = f = AllocWinding( maxpts );
+       *back = b = AllocWinding( maxpts );
+
+       for ( i = 0 ; i < in->numpoints ; i++ )
+       {
+               p1 = in->p[i];
+
+               if ( sides[i] == SIDE_ON ) {
+                       VectorCopy( p1, f->p[f->numpoints] );
+                       f->numpoints++;
+                       VectorCopy( p1, b->p[b->numpoints] );
+                       b->numpoints++;
+                       continue;
+               }
+
+               if ( sides[i] == SIDE_FRONT ) {
+                       VectorCopy( p1, f->p[f->numpoints] );
+                       f->numpoints++;
+               }
+               if ( sides[i] == SIDE_BACK ) {
+                       VectorCopy( p1, b->p[b->numpoints] );
+                       b->numpoints++;
+               }
+
+               if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
+                       continue;
+               }
+
+               // generate a split point
+               p2 = in->p[( i + 1 ) % in->numpoints];
+
+               dot = dists[i] / ( dists[i] - dists[i + 1] );
+               for ( j = 0 ; j < 3 ; j++ )
+               {   // avoid round off error when possible
+                       if ( normal[j] == 1 ) {
+                               mid[j] = dist;
+                       }
+                       else if ( normal[j] == -1 ) {
+                               mid[j] = -dist;
+                       }
+                       else{
+                               mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
+                       }
+               }
+
+               VectorCopy( mid, f->p[f->numpoints] );
+               f->numpoints++;
+               VectorCopy( mid, b->p[b->numpoints] );
+               b->numpoints++;
+       }
+
+       if ( f->numpoints > maxpts || b->numpoints > maxpts ) {
+               Error( "ClipWinding: points exceeded estimate" );
+       }
+       if ( f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING ) {
+               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
+       }
+}
+
+
+/*
+   =============
+   ChopWindingInPlace
+   =============
+ */
+void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon ){
+       winding_t   *in;
+       vec_t dists[MAX_POINTS_ON_WINDING + 4];
+       int sides[MAX_POINTS_ON_WINDING + 4];
+       int counts[3];
+       vec_t dot;          // VC 4.2 optimizer bug if not static
+       int i, j;
+       vec_t   *p1, *p2;
+       vec3_t mid;
+       winding_t   *f;
+       int maxpts;
+
+       in = *inout;
+       counts[0] = counts[1] = counts[2] = 0;
+
+       if ( !in ) {
+               printf( "Warning: NULL passed to ChopWindingInPlace\n" );
+               return;
+       }
+       if ( in->numpoints >= MAX_POINTS_ON_WINDING - 4 ) {
+               Error( "ChopWinding: MAX_POINTS_ON_WINDING" );
+       }
+
+// determine sides for each point
+       for ( i = 0 ; i < in->numpoints ; i++ )
+       {
+               dot = DotProduct( in->p[i], normal );
+               dot -= dist;
+               dists[i] = dot;
+               if ( dot > epsilon ) {
+                       sides[i] = SIDE_FRONT;
+               }
+               else if ( dot < -epsilon ) {
+                       sides[i] = SIDE_BACK;
+               }
+               else
+               {
+                       sides[i] = SIDE_ON;
+               }
+               counts[sides[i]]++;
+       }
+       sides[i] = sides[0];
+       dists[i] = dists[0];
+
+       if ( !counts[0] ) {
+               FreeWinding( in );
+               *inout = NULL;
+               return;
+       }
+       if ( !counts[1] ) {
+               return;     // inout stays the same
+
+       }
+       maxpts = in->numpoints + 4;   // cant use counts[0]+2 because
+                                     // of fp grouping errors
+
+       f = AllocWinding( maxpts );
+
+       for ( i = 0 ; i < in->numpoints ; i++ )
+       {
+               p1 = in->p[i];
+
+               if ( sides[i] == SIDE_ON ) {
+                       VectorCopy( p1, f->p[f->numpoints] );
+                       f->numpoints++;
+                       continue;
+               }
+
+               if ( sides[i] == SIDE_FRONT ) {
+                       VectorCopy( p1, f->p[f->numpoints] );
+                       f->numpoints++;
+               }
+
+               if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
+                       continue;
+               }
+
+               // generate a split point
+               p2 = in->p[( i + 1 ) % in->numpoints];
+
+               dot = dists[i] / ( dists[i] - dists[i + 1] );
+               for ( j = 0 ; j < 3 ; j++ )
+               {   // avoid round off error when possible
+                       if ( normal[j] == 1 ) {
+                               mid[j] = dist;
+                       }
+                       else if ( normal[j] == -1 ) {
+                               mid[j] = -dist;
+                       }
+                       else{
+                               mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
+                       }
+               }
+
+               VectorCopy( mid, f->p[f->numpoints] );
+               f->numpoints++;
+       }
+
+       if ( f->numpoints > maxpts ) {
+               Error( "ClipWinding: points exceeded estimate" );
+       }
+       if ( f->numpoints > MAX_POINTS_ON_WINDING ) {
+               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
+       }
+
+       FreeWinding( in );
+       *inout = f;
+}
+
+
+/*
+   =================
+   ChopWinding
+
+   Returns the fragment of in that is on the front side
+   of the cliping plane.  The original is freed.
+   =================
+ */
+winding_t   *ChopWinding( winding_t *in, vec3_t normal, vec_t dist ){
+       winding_t   *f, *b;
+
+       ClipWindingEpsilon( in, normal, dist, ON_EPSILON, &f, &b );
+       FreeWinding( in );
+       if ( b ) {
+               FreeWinding( b );
+       }
+       return f;
+}
+
+
+/*
+   =================
+   CheckWinding
+
+   =================
+ */
+void CheckWinding( winding_t *w ){
+       int i, j;
+       vec_t   *p1, *p2;
+       vec_t d, edgedist;
+       vec3_t dir, edgenormal, facenormal;
+       vec_t area;
+       vec_t facedist;
+
+       if ( w->numpoints < 3 ) {
+               Error( "CheckWinding: %i points",w->numpoints );
+       }
+
+       area = WindingArea( w );
+       if ( area < 1 ) {
+               Error( "CheckWinding: %f area", area );
+       }
+
+       WindingPlane( w, facenormal, &facedist );
+
+       for ( i = 0 ; i < w->numpoints ; i++ )
+       {
+               p1 = w->p[i];
+
+               for ( j = 0 ; j < 3 ; j++ )
+                       if ( p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE ) {
+                               Error( "CheckFace: BUGUS_RANGE: %f",p1[j] );
+                       }
+
+               j = i + 1 == w->numpoints ? 0 : i + 1;
+
+               // check the point is on the face plane
+               d = DotProduct( p1, facenormal ) - facedist;
+               if ( d < -ON_EPSILON || d > ON_EPSILON ) {
+                       Error( "CheckWinding: point off plane" );
+               }
+
+               // check the edge isnt degenerate
+               p2 = w->p[j];
+               VectorSubtract( p2, p1, dir );
+
+               if ( VectorLength( dir ) < ON_EPSILON ) {
+                       Error( "CheckWinding: degenerate edge" );
+               }
+
+               CrossProduct( facenormal, dir, edgenormal );
+               VectorNormalize( edgenormal, edgenormal );
+               edgedist = DotProduct( p1, edgenormal );
+               edgedist += ON_EPSILON;
+
+               // all other points must be on front side
+               for ( j = 0 ; j < w->numpoints ; j++ )
+               {
+                       if ( j == i ) {
+                               continue;
+                       }
+                       d = DotProduct( w->p[j], edgenormal );
+                       if ( d > edgedist ) {
+                               Error( "CheckWinding: non-convex" );
+                       }
+               }
+       }
+}
+
+
+/*
+   ============
+   WindingOnPlaneSide
+   ============
+ */
+int     WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist ){
+       qboolean front, back;
+       int i;
+       vec_t d;
+
+       front = false;
+       back = false;
+       for ( i = 0 ; i < w->numpoints ; i++ )
+       {
+               d = DotProduct( w->p[i], normal ) - dist;
+               if ( d < -ON_EPSILON ) {
+                       if ( front ) {
+                               return SIDE_CROSS;
+                       }
+                       back = true;
+                       continue;
+               }
+               if ( d > ON_EPSILON ) {
+                       if ( back ) {
+                               return SIDE_CROSS;
+                       }
+                       front = true;
+                       continue;
+               }
+       }
+
+       if ( back ) {
+               return SIDE_BACK;
+       }
+       if ( front ) {
+               return SIDE_FRONT;
+       }
+       return SIDE_ON;
+}
diff --git a/tools/heretic2/common/polylib.h b/tools/heretic2/common/polylib.h
new file mode 100644 (file)
index 0000000..00b7b39
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+typedef struct
+{
+       int numpoints;
+       vec3_t p[4];        // variable sized
+} winding_t;
+
+#define MAX_POINTS_ON_WINDING   64
+
+// you can define on_epsilon in the makefile as tighter
+#ifndef ON_EPSILON
+#define ON_EPSILON  0.1
+#endif
+
+winding_t   *AllocWinding( int points );
+vec_t   WindingArea( winding_t *w );
+void    WindingCenter( winding_t *w, vec3_t center );
+void    ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
+                                                       vec_t epsilon, winding_t **front, winding_t **back );
+winding_t   *ChopWinding( winding_t *in, vec3_t normal, vec_t dist );
+winding_t   *CopyWinding( winding_t *w );
+winding_t   *ReverseWinding( winding_t *w );
+winding_t   *BaseWindingForPlane( vec3_t normal, vec_t dist );
+void    CheckWinding( winding_t *w );
+void    WindingPlane( winding_t *w, vec3_t normal, vec_t *dist );
+void    RemoveColinearPoints( winding_t *w );
+int     WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist );
+void    FreeWinding( winding_t *w );
+void    WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs );
+
+void    ChopWindingInPlace( winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon );
+// frees the original if clipped
+
+void pw( winding_t *w );
diff --git a/tools/heretic2/common/qfiles.c b/tools/heretic2/common/qfiles.c
new file mode 100644 (file)
index 0000000..53452f3
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qfiles.h"
+#include "scriplib.h"
+//#include <windows.h>
+
+materialtype_t defaultmaterialtypes[] =
+{
+       {"gravel",  MATERIAL_GRAVEL},
+       {"metal",   MATERIAL_METAL},
+       {"stone",   MATERIAL_STONE},
+       {"wood",    MATERIAL_WOOD},
+       {NULL,      0}
+};
+
+materialtype_t  *materialtypes;
+
+void QFile_ReadMaterialTypes( char* filename ){
+       int i;
+       FILE    *f;
+
+       f = fopen( filename, "rb" );
+       if ( !f ) {
+               materialtypes = defaultmaterialtypes;
+               return;
+       }
+       fclose( f );
+
+       free( materialtypes );
+       materialtypes = (materialtype_t*)malloc( 256 * sizeof( materialtype_t ) );
+
+       LoadScriptFile( filename );
+       i = 0;
+
+       while ( i < 255 )
+       {
+               GetScriptToken( true );
+               if ( endofscript ) {
+                       break;
+               }
+               if ( strcmp( token, "material" ) != 0 ) {
+                       while ( ScriptTokenAvailable() )
+                       {
+                               GetScriptToken( false );
+                       }
+               }
+               else
+               {
+                       GetScriptToken( false );
+                       materialtypes[i].name = (char*)malloc( strlen( token ) + 1 );
+                       strcpy( materialtypes[i].name, token );
+                       GetScriptToken( false );
+                       materialtypes[i].value = atoi( token );
+               }
+               i++;
+       }
+       materialtypes[i].name = NULL;
+       materialtypes[i].value = 0;
+}
diff --git a/tools/heretic2/common/qfiles.h b/tools/heretic2/common/qfiles.h
new file mode 100644 (file)
index 0000000..7ed4b47
--- /dev/null
@@ -0,0 +1,619 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _QFILES_H
+#define _QFILES_H
+
+#include "q_typedef.h"
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+   ========================================================================
+
+   The .pak files are just a linear collapse of a directory tree
+
+   ========================================================================
+ */
+
+#define IDPAKHEADER     ( ( 'K' << 24 ) + ( 'C' << 16 ) + ( 'A' << 8 ) + 'P' )
+
+typedef struct
+{
+       char name[56];
+       int filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+       int ident;          // == IDPAKHEADER
+       int dirofs;
+       int dirlen;
+} dpackheader_t;
+
+#define MAX_FILES_IN_PACK   4096
+
+
+/*
+   ========================================================================
+
+   PCX files are used for as many images as possible
+
+   ========================================================================
+ */
+
+typedef struct
+{
+       char manufacturer;
+       char version;
+       char encoding;
+       char bits_per_pixel;
+       unsigned short xmin,ymin,xmax,ymax;
+       unsigned short hres,vres;
+       unsigned char palette[48];
+       char reserved;
+       char color_planes;
+       unsigned short bytes_per_line;
+       unsigned short palette_type;
+       char filler[58];
+       unsigned char data;             // unbounded
+} pcx_t;
+
+
+/*
+   ========================================================================
+
+   .MD2 compressed triangle model file format
+
+   ========================================================================
+ */
+#define IDJOINTEDALIASHEADER    ( ( '2' << 24 ) + ( 'J' << 16 ) + ( 'D' << 8 ) + 'I' )
+
+/*
+   ========================================================================
+
+   .MD2 triangle model file format
+
+   ========================================================================
+ */
+
+#define IDALIASHEADER       ( ( '2' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
+#define ALIAS_VERSION   8
+
+#define MAX_TRIANGLES   2048
+#define MAX_VERTS       2048
+#define MAX_FRAMES      512
+#define MAX_MD2SKINS    64
+#define MAX_SKINNAME    64
+
+typedef struct
+{
+       short s;
+       short t;
+} dstvert_t;
+
+typedef struct
+{
+       short index_xyz[3];
+       short index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+       byte v[3];              // scaled byte to fit in frame mins/maxs
+       byte lightnormalindex;
+} dtrivertx_t;
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+typedef struct
+{
+       float scale[3];         // multiply byte verts by this
+       float translate[3];         // then add this
+       char name[16];          // frame name from grabbing
+       dtrivertx_t verts[1];   // variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+       int ident;
+       int version;
+
+       int skinwidth;
+       int skinheight;
+       int framesize;              // byte size of each frame
+
+       int num_skins;
+       int num_xyz;
+       int num_st;                 // greater than num_xyz for seams
+       int num_tris;
+       int num_glcmds;             // dwords in strip/fan command list
+       int num_frames;
+
+       int ofs_skins;              // each skin is a MAX_SKINNAME string
+       int ofs_st;                 // byte offset from start for stverts
+       int ofs_tris;               // offset for dtriangles
+       int ofs_frames;             // offset for first frame
+       int ofs_glcmds;
+       int ofs_end;                // end of file
+
+} dmdl_t;
+
+/*
+   ========================================================================
+
+   .BK file format
+
+   ========================================================================
+ */
+
+#define IDBOOKHEADER    ( ( 'K' << 24 ) + ( 'O' << 16 ) + ( 'O' << 8 ) + 'B' )
+#define BOOK_VERSION    2
+
+typedef struct bookframe_s
+{
+       int x;
+       int y;
+       int w;
+       int h;
+       char name[MAX_SKINNAME];            // name of gfx file
+} bookframe_t;
+
+typedef struct bookheader_s
+{
+       unsigned int ident;
+       unsigned int version;
+       int num_segments;
+       int total_w;
+       int total_h;
+} bookheader_t;
+
+typedef struct book_s
+{
+       bookheader_t bheader;
+       bookframe_t bframes[MAX_MD2SKINS];
+} book_t;
+
+/*
+   ========================================================================
+
+   .SP2 sprite file format
+
+   ========================================================================
+ */
+
+#define IDSPRITEHEADER  ( ( '2' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' )
+// little-endian "IDS2"
+#define SPRITE_VERSION  2
+
+typedef struct
+{
+       int width, height;
+       int origin_x, origin_y;         // raster coordinates inside pic
+       char name[MAX_SKINNAME];        // name of pcx file
+} dsprframe_t;
+
+typedef struct {
+       int ident;
+       int version;
+       int numframes;
+       dsprframe_t frames[1];          // variable sized
+} dsprite_t;
+
+/*
+   ==============================================================================
+
+   .M8 texture file format
+
+   ==============================================================================
+ */
+
+typedef struct palette_s
+{
+       union
+       {
+               struct
+               {
+                       byte r,g,b;
+               };
+       };
+} palette_t;
+
+#define MIP_VERSION     2
+#define PAL_SIZE        256
+#define MIPLEVELS       16
+
+typedef struct miptex_s
+{
+       int version;
+       char name[32];
+       unsigned width[MIPLEVELS], height[MIPLEVELS];
+       unsigned offsets[MIPLEVELS];        // four mip maps stored
+       char animname[32];                  // next frame in animation chain
+       palette_t palette[PAL_SIZE];
+       int flags;
+       int contents;
+       int value;
+} miptex_t;
+
+
+#define MIP32_VERSION   4
+
+#define MIP32_NOMIP_FLAG2           0x00000001
+#define MIP32_DETAILER_FLAG2        0x00000002
+
+typedef struct miptex32_s
+{
+       int version;
+       char name[128];
+       char altname[128];                  // texture substitution
+       char animname[128];                 // next frame in animation chain
+       char damagename[128];               // image that should be shown when damaged
+       unsigned width[MIPLEVELS], height[MIPLEVELS];
+       unsigned offsets[MIPLEVELS];
+       int flags;
+       int contents;
+       int value;
+       float scale_x, scale_y;
+       int mip_scale;
+
+       // detail texturing info
+       char dt_name[128];              // detailed texture name
+       float dt_scale_x, dt_scale_y;
+       float dt_u, dt_v;
+       float dt_alpha;
+       int dt_src_blend_mode, dt_dst_blend_mode;
+
+       int flags2;
+       int unused[19];                     // future expansion to maintain compatibility with h2
+} miptex32_t;
+
+
+
+/*
+   ==============================================================================
+
+   .BSP file format
+
+   ==============================================================================
+ */
+
+#define IDBSPHEADER ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' )
+// little-endian "IBSP"
+
+#define BSPVERSION  38
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define MAX_MAP_MODELS      1024
+#define MAX_MAP_BRUSHES     8192
+#define MAX_MAP_ENTITIES    2048
+#define MAX_MAP_ENTSTRING   0x40000
+#define MAX_MAP_TEXINFO     8192
+
+#define MAX_MAP_AREAS       256
+#define MAX_MAP_AREAPORTALS 1024
+#define MAX_MAP_PLANES      65536
+#define MAX_MAP_NODES       65536
+#define MAX_MAP_BRUSHSIDES  65536
+#define MAX_MAP_LEAFS       65536
+#define MAX_MAP_VERTS       65536
+#define MAX_MAP_FACES       65536
+#define MAX_MAP_LEAFFACES   65536
+#define MAX_MAP_LEAFBRUSHES 65536
+#define MAX_MAP_PORTALS     65536
+#define MAX_MAP_EDGES       128000
+#define MAX_MAP_SURFEDGES   256000
+#define MAX_MAP_LIGHTING    0x200000
+#define MAX_MAP_VISIBILITY  0x180000
+
+// key / value pair sizes
+
+#define MAX_KEY     32
+#define MAX_VALUE   1024
+
+//=============================================================================
+
+typedef struct
+{
+       int fileofs, filelen;
+} lump_t;
+
+#define LUMP_ENTITIES       0
+#define LUMP_PLANES         1
+#define LUMP_VERTEXES       2
+#define LUMP_VISIBILITY     3
+#define LUMP_NODES          4
+#define LUMP_TEXINFO        5
+#define LUMP_FACES          6
+#define LUMP_LIGHTING       7
+#define LUMP_LEAFS          8
+#define LUMP_LEAFFACES      9
+#define LUMP_LEAFBRUSHES    10
+#define LUMP_EDGES          11
+#define LUMP_SURFEDGES      12
+#define LUMP_MODELS         13
+#define LUMP_BRUSHES        14
+#define LUMP_BRUSHSIDES     15
+#define LUMP_POP            16
+#define LUMP_AREAS          17
+#define LUMP_AREAPORTALS    18
+#define HEADER_LUMPS        19
+
+typedef struct
+{
+       int ident;
+       int version;
+       lump_t lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+       float mins[3], maxs[3];
+       float origin[3];            // for sounds or lights
+       int headnode;
+       int firstface, numfaces;            // submodels just draw faces
+                                           // without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+       float point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define PLANE_X         0
+#define PLANE_Y         1
+#define PLANE_Z         2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define PLANE_ANYX      3
+#define PLANE_ANYY      4
+#define PLANE_ANYZ      5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+       float normal[3];
+       float dist;
+       int type;           // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// these definitions also need to be in q_shared.h!
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define CONTENTS_SOLID          0x00000001      // an eye is never valid in a solid
+#define CONTENTS_WINDOW         0x00000002      // translucent, but not watery
+#define CONTENTS_PUSHPULL       0x00000004
+#define CONTENTS_LAVA           0x00000008
+#define CONTENTS_SLIME          0x00000010
+#define CONTENTS_WATER          0x00000020
+#define CONTENTS_MIST           0x00000040      // 64
+#define LAST_VISIBLE_CONTENTS   64              // this one worries me a bit JKH
+
+// remaining contents are non-visible, and don't eat brushes
+
+#define CONTENTS_AREAPORTAL     0x00008000
+
+#define CONTENTS_PLAYERCLIP     0x00010000
+#define CONTENTS_MONSTERCLIP    0x00020000
+
+// currents can be added to any other contents, and may be mixed
+#define CONTENTS_CURRENT_0      0x00040000
+#define CONTENTS_CURRENT_90     0x00080000
+#define CONTENTS_CURRENT_180    0x00100000
+#define CONTENTS_CURRENT_270    0x00200000
+#define CONTENTS_CURRENT_UP     0x00400000
+#define CONTENTS_CURRENT_DOWN   0x00800000
+
+#define CONTENTS_ORIGIN         0x01000000  // removed before bsping an entity
+
+#define CONTENTS_MONSTER        0x02000000  // should never be on a brush, only in game
+#define CONTENTS_DEADMONSTER    0x04000000
+#define CONTENTS_DETAIL         0x08000000  // brushes to be added after vis leafs
+#define CONTENTS_TRANSLUCENT    0x10000000  // auto set if any surface has trans
+#define CONTENTS_LADDER         0x20000000
+
+
+
+#define SURF_LIGHT              0x00000001      // value will hold the light strength
+
+#define SURF_SLICK              0x00000002      // effects game physics
+
+#define SURF_SKY                0x00000004      // don't draw, but add to skybox
+#define SURF_WARP               0x00000008      // turbulent water warp
+#define SURF_TRANS33            0x00000010
+#define SURF_TRANS66            0x00000020
+#define SURF_FLOWING            0x00000040  // scroll towards angle
+#define SURF_NODRAW             0x00000080  // don't bother referencing the texture
+
+#define SURF_HINT               0x00000100  // make a primary bsp splitter
+#define SURF_SKIP               0x00000200  // completely ignore, allowing non-closed brushes
+#define SURF_TALL_WALL          0x00000400  // face doesn't get broken up as normal
+
+#define SURF_ALPHA_TEXTURE      0x00000800  // texture has alpha in it, and should show through in bsp process
+#define SURF_ANIMSPEED          0x00001000      // value will hold the anim speed in fps
+
+#define SURF_UNDULATE           0x00002000  // rock surface up and down...
+#define SURF_SKYREFLECT         0x00004000  // liquid will somewhat reflect the sky - not quite finished....
+
+#define SURF_TYPE_GRAVEL        0x00000000
+#define SURF_TYPE_METAL         0x01000000
+#define SURF_TYPE_STONE         0x02000000
+#define SURF_TYPE_WOOD          0x03000000
+#define SURF_MATERIAL           0xFF000000
+
+
+
+typedef struct
+{
+       int planenum;
+       int children[2];            // negative numbers are -(leafs+1), not nodes
+       short mins[3];              // for frustom culling
+       short maxs[3];
+       unsigned short firstface;
+       unsigned short numfaces;    // counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+       float vecs[2][4];           // [s/t][xyz offset]
+       int flags;                  // miptex flags + overrides
+       int value;                  // light emission, etc
+       char texture[32];           // texture name (textures/*.wal)
+       int nexttexinfo;            // for animations, -1 = end of chain
+} texinfo_t;
+
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+       unsigned short v[2];        // vertex numbers
+} dedge_t;
+
+#define MAXLIGHTMAPS    4
+typedef struct
+{
+       unsigned short planenum;
+       short side;
+
+       int firstedge;              // we must support > 64k edges
+       short numedges;
+       short texinfo;
+
+// lighting info
+       union {
+               byte styles[MAXLIGHTMAPS];
+               paletteRGBA_t lighting;
+       };
+       int lightofs;               // start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+       int contents;                       // OR of all brushes (not needed?)
+
+       short cluster;
+       short area;
+
+       short mins[3];                      // for frustum culling
+       short maxs[3];
+
+       unsigned short firstleafface;
+       unsigned short numleaffaces;
+
+       unsigned short firstleafbrush;
+       unsigned short numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+       unsigned short planenum;        // facing out of the leaf
+       short texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+       int firstside;
+       int numsides;
+       int contents;
+} dbrush_t;
+
+#define ANGLE_UP    -1
+#define ANGLE_DOWN  -2
+
+
+// the visibility lump consists of a header with a count, then
+// byte offsets for the PVS and PHS of each cluster, then the raw
+// compressed bit vectors
+#define DVIS_PVS    0
+#define DVIS_PHS    1
+typedef struct
+{
+       int numclusters;
+       int bitofs[8][2];           // bitofs[numclusters][2]
+} dvis_t;
+
+// each area has a list of portals that lead into other areas
+// when portals are closed, other areas may not be visible or
+// hearable even if the vis info says that it should be
+typedef struct
+{
+       int portalnum;
+       int otherarea;
+} dareaportal_t;
+
+
+typedef struct
+{
+       int numareaportals;
+       int firstareaportal;
+} darea_t;
+
+typedef struct
+{
+       char    *name;
+       int value;
+} materialtype_t;
+
+enum
+{
+       MATERIAL_GRAVEL,
+       MATERIAL_METAL,
+       MATERIAL_STONE,
+       MATERIAL_WOOD,
+};
+
+extern materialtype_t  *materialtypes;
+
+void QFile_ReadMaterialTypes( char* filename );
+
+
+#endif //_QFILES_H
diff --git a/tools/heretic2/common/scriplib.c b/tools/heretic2/common/scriplib.c
new file mode 100644 (file)
index 0000000..af5e571
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// scriplib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "scriplib.h"
+
+/*
+   =============================================================================
+
+                        PARSING STUFF
+
+   =============================================================================
+ */
+
+typedef struct
+{
+       char filename[1024];
+       char    *buffer,*script_p,*end_p;
+       int line;
+} script_t;
+
+#define MAX_INCLUDES    8
+script_t scriptstack[MAX_INCLUDES];
+script_t    *script;
+int scriptline;
+
+char token[MAXTOKEN];
+qboolean endofscript;
+qboolean tokenready;                     // only true if UnGetScriptToken was just called
+
+/*
+   ==============
+   AddScriptToStack
+   ==============
+ */
+void AddScriptToStack( char *filename ){
+       int size;
+
+       script++;
+       if ( script == &scriptstack[MAX_INCLUDES] ) {
+               Error( "script file exceeded MAX_INCLUDES" );
+       }
+       strcpy( script->filename, ExpandPath( filename ) );
+
+       size = LoadFile( script->filename, (void **)&script->buffer );
+
+       printf( "entering %s\n", script->filename );
+
+       script->line = 1;
+
+       script->script_p = script->buffer;
+       script->end_p = script->buffer + size;
+}
+
+
+/*
+   ==============
+   LoadScriptFile
+   ==============
+ */
+void LoadScriptFile( char *filename ){
+       script = scriptstack;
+       AddScriptToStack( filename );
+
+       endofscript = false;
+       tokenready = false;
+}
+
+
+/*
+   ==============
+   ParseFromMemory
+   ==============
+ */
+void ParseFromMemory( char *buffer, int size ){
+       script = scriptstack;
+       script++;
+       if ( script == &scriptstack[MAX_INCLUDES] ) {
+               Error( "script file exceeded MAX_INCLUDES" );
+       }
+       strcpy( script->filename, "memory buffer" );
+
+       script->buffer = buffer;
+       script->line = 1;
+       script->script_p = script->buffer;
+       script->end_p = script->buffer + size;
+
+       endofscript = false;
+       tokenready = false;
+}
+
+
+/*
+   ==============
+   UnGetScriptToken
+
+   Signals that the current token was not used, and should be reported
+   for the next GetScriptToken.  Note that
+
+   GetScriptToken (true);
+   UnGetScriptToken ();
+   GetScriptToken (false);
+
+   could cross a line boundary.
+   ==============
+ */
+void UnGetScriptToken( void ){
+       tokenready = true;
+}
+
+
+qboolean EndOfScript( qboolean crossline ){
+       if ( !crossline ) {
+               Error( "Line %i is incomplete\n",scriptline );
+       }
+
+       if ( !strcmp( script->filename, "memory buffer" ) ) {
+               endofscript = true;
+               return false;
+       }
+
+       free( script->buffer );
+       if ( script == scriptstack + 1 ) {
+               endofscript = true;
+               return false;
+       }
+       script--;
+       scriptline = script->line;
+       printf( "returning to %s\n", script->filename );
+       return GetScriptToken( crossline );
+}
+
+/*
+   ==============
+   GetScriptToken
+   ==============
+ */
+qboolean GetScriptToken( qboolean crossline ){
+       char    *token_p;
+
+       if ( tokenready ) {                       // is a token allready waiting?
+               tokenready = false;
+               return true;
+       }
+
+       if ( script->script_p >= script->end_p ) {
+               return EndOfScript( crossline );
+       }
+
+//
+// skip space
+//
+skipspace:
+       while ( *script->script_p <= 32 )
+       {
+               if ( script->script_p >= script->end_p ) {
+                       return EndOfScript( crossline );
+               }
+               if ( *script->script_p++ == '\n' ) {
+                       if ( !crossline ) {
+                               Error( "Line %i is incomplete\n",scriptline );
+                       }
+                       scriptline = script->line++;
+               }
+       }
+
+       if ( script->script_p >= script->end_p ) {
+               return EndOfScript( crossline );
+       }
+
+       // ; # // comments
+       if ( *script->script_p == ';' || *script->script_p == '#'
+                || ( script->script_p[0] == '/' && script->script_p[1] == '/' ) ) {
+               if ( !crossline ) {
+                       Error( "Line %i is incomplete\n",scriptline );
+               }
+               while ( *script->script_p++ != '\n' )
+                       if ( script->script_p >= script->end_p ) {
+                               return EndOfScript( crossline );
+                       }
+               goto skipspace;
+       }
+
+       // /* */ comments
+       if ( script->script_p[0] == '/' && script->script_p[1] == '*' ) {
+               if ( !crossline ) {
+                       Error( "Line %i is incomplete\n",scriptline );
+               }
+               script->script_p += 2;
+               while ( script->script_p[0] != '*' && script->script_p[1] != '/' )
+               {
+                       script->script_p++;
+                       if ( script->script_p >= script->end_p ) {
+                               return EndOfScript( crossline );
+                       }
+               }
+               script->script_p += 2;
+               goto skipspace;
+       }
+
+//
+// copy token
+//
+       token_p = token;
+
+       if ( *script->script_p == '"' ) {
+               // quoted token
+               script->script_p++;
+               while ( *script->script_p != '"' )
+               {
+                       *token_p++ = *script->script_p++;
+                       if ( script->script_p == script->end_p ) {
+                               break;
+                       }
+                       if ( token_p == &token[MAXTOKEN] ) {
+                               Error( "Token too large on line %i\n",scriptline );
+                       }
+               }
+               script->script_p++;
+       }
+       else{   // regular token
+               while ( *script->script_p > 32 && *script->script_p != ';' )
+               {
+                       *token_p++ = *script->script_p++;
+                       if ( script->script_p == script->end_p ) {
+                               break;
+                       }
+                       if ( token_p == &token[MAXTOKEN] ) {
+                               Error( "Token too large on line %i\n",scriptline );
+                       }
+               }
+       }
+
+       *token_p = 0;
+
+       if ( !strcmp( token, "$include" ) ) {
+               GetScriptToken( false );
+               AddScriptToStack( token );
+               return GetScriptToken( crossline );
+       }
+
+       return true;
+}
+
+
+/*
+   ==============
+   ScriptTokenAvailable
+
+   Returns true if there is another token on the line
+   ==============
+ */
+qboolean ScriptTokenAvailable( void ){
+       char    *search_p;
+
+       search_p = script->script_p;
+
+       if ( search_p >= script->end_p ) {
+               return false;
+       }
+
+       while ( *search_p <= 32 )
+       {
+               if ( *search_p == '\n' ) {
+                       return false;
+               }
+               search_p++;
+               if ( search_p == script->end_p ) {
+                       return false;
+               }
+
+       }
+
+       if ( *search_p == ';' ) {
+               return false;
+       }
+
+       return true;
+}
diff --git a/tools/heretic2/common/scriplib.h b/tools/heretic2/common/scriplib.h
new file mode 100644 (file)
index 0000000..8c441c8
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// scriplib.h
+
+#ifndef __CMDLIB__
+#include "cmdlib.h"
+#endif
+
+#define MAXTOKEN    1024
+
+extern char token[MAXTOKEN];
+extern char    *scriptbuffer,*script_p,*scriptend_p;
+extern int grabbed;
+extern int scriptline;
+extern qboolean endofscript;
+
+
+void LoadScriptFile( char *filename );
+void ParseFromMemory( char *buffer, int size );
+
+qboolean GetScriptToken( qboolean crossline );
+void UnGetScriptToken( void );
+qboolean ScriptTokenAvailable( void );
diff --git a/tools/heretic2/common/threads.c b/tools/heretic2/common/threads.c
new file mode 100644 (file)
index 0000000..239226b
--- /dev/null
@@ -0,0 +1,606 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "globaldefs.h"
+
+#if !GDEF_OS_WINDOWS
+// The below define is necessary to use
+// pthreads extensions like pthread_mutexattr_settype
+#define _GNU_SOURCE
+#endif // !GDEF_OS_WINDOWS
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "her2_threads.h"
+
+#define MAX_THREADS 64
+
+int dispatch;
+int workcount;
+int oldf;
+qboolean pacifier;
+
+qboolean threaded;
+
+/*
+   =============
+   GetThreadWork
+
+   =============
+ */
+int GetThreadWork( void ){
+       int r;
+       int f;
+
+       ThreadLock();
+
+       if ( dispatch == workcount ) {
+               ThreadUnlock();
+               return -1;
+       }
+
+       f = 10 * dispatch / workcount;
+       if ( f != oldf ) {
+               oldf = f;
+               if ( pacifier ) {
+                       Sys_Printf( "%i...", f );
+                       fflush( stdout );   /* ydnar */
+               }
+       }
+
+       r = dispatch;
+       dispatch++;
+       ThreadUnlock();
+
+       return r;
+}
+
+
+void ( *workfunction )( int );
+
+void ThreadWorkerFunction( int threadnum ){
+       int work;
+
+       while ( 1 )
+       {
+               work = GetThreadWork();
+               if ( work == -1 ) {
+                       break;
+               }
+               //Sys_Printf ("thread %i, work %i\n", threadnum, work);
+               workfunction( work );
+       }
+}
+
+void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       if ( numthreads == -1 ) {
+               ThreadSetDefault();
+       }
+       workfunction = func;
+       RunThreadsOn( workcnt, showpacifier, ThreadWorkerFunction );
+}
+
+
+#if GDEF_OS_WINDOWS
+
+/*
+   ===================================================================
+
+   WIN32
+
+   ===================================================================
+ */
+
+#include <windows.h>
+
+// Setting default Threads to 1
+int numthreads = 1;
+CRITICAL_SECTION crit;
+static int enter;
+
+void ThreadSetDefault( void ){
+       SYSTEM_INFO info;
+
+       if ( numthreads == -1 ) { // not set manually
+               GetSystemInfo( &info );
+               numthreads = info.dwNumberOfProcessors;
+               if ( numthreads < 1 || numthreads > 32 ) {
+                       numthreads = 1;
+               }
+       }
+
+       Sys_Printf( "%i threads\n", numthreads );
+}
+
+
+void ThreadLock( void ){
+       if ( !threaded ) {
+               return;
+       }
+       EnterCriticalSection( &crit );
+       if ( enter ) {
+               Error( "Recursive ThreadLock\n" );
+       }
+       enter = 1;
+}
+
+void ThreadUnlock( void ){
+       if ( !threaded ) {
+               return;
+       }
+       if ( !enter ) {
+               Error( "ThreadUnlock without lock\n" );
+       }
+       enter = 0;
+       LeaveCriticalSection( &crit );
+}
+
+/*
+   =============
+   RunThreadsOn
+   =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       int threadid[MAX_THREADS];
+       HANDLE threadhandle[MAX_THREADS];
+       int i;
+       int start, end;
+
+       start = I_FloatTime();
+       dispatch = 0;
+       workcount = workcnt;
+       oldf = -1;
+       pacifier = showpacifier;
+       threaded = true;
+
+       //
+       // run threads in parallel
+       //
+       InitializeCriticalSection( &crit );
+
+       if ( numthreads == 1 ) { // use same thread
+               func( 0 );
+       }
+       else
+       {
+               for ( i = 0 ; i < numthreads ; i++ )
+               {
+                       threadhandle[i] = CreateThread(
+                               NULL,   // LPSECURITY_ATTRIBUTES lpsa,
+                           //0,                // DWORD cbStack,
+
+                           /* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
+                               ( 4096 * 1024 ),
+
+                               (LPTHREAD_START_ROUTINE)func,   // LPTHREAD_START_ROUTINE lpStartAddr,
+                               (LPVOID)i,  // LPVOID lpvThreadParm,
+                               0,          //   DWORD fdwCreate,
+                               &threadid[i] );
+               }
+
+               for ( i = 0 ; i < numthreads ; i++ )
+                       WaitForSingleObject( threadhandle[i], INFINITE );
+       }
+       DeleteCriticalSection( &crit );
+
+       threaded = false;
+       end = I_FloatTime();
+       if ( pacifier ) {
+               Sys_Printf( " (%i)\n", end - start );
+       }
+}
+
+
+#elif GDEF_OS_OSF1
+
+/*
+   ===================================================================
+
+   OSF1
+
+   ===================================================================
+ */
+
+int numthreads = 4;
+
+void ThreadSetDefault( void ){
+       if ( numthreads == -1 ) { // not set manually
+               numthreads = 4;
+       }
+}
+
+
+#include <pthread.h>
+
+pthread_mutex_t *my_mutex;
+
+void ThreadLock( void ){
+       if ( my_mutex ) {
+               pthread_mutex_lock( my_mutex );
+       }
+}
+
+void ThreadUnlock( void ){
+       if ( my_mutex ) {
+               pthread_mutex_unlock( my_mutex );
+       }
+}
+
+
+/*
+   =============
+   RunThreadsOn
+   =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       int i;
+       pthread_t work_threads[MAX_THREADS];
+       pthread_addr_t status;
+       pthread_attr_t attrib;
+       pthread_mutexattr_t mattrib;
+       int start, end;
+
+       start = I_FloatTime();
+       dispatch = 0;
+       workcount = workcnt;
+       oldf = -1;
+       pacifier = showpacifier;
+       threaded = true;
+
+       if ( pacifier ) {
+               setbuf( stdout, NULL );
+       }
+
+       if ( !my_mutex ) {
+               my_mutex = safe_malloc( sizeof( *my_mutex ) );
+               if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
+                       Error( "pthread_mutex_attr_create failed" );
+               }
+               if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
+                       Error( "pthread_mutexattr_setkind_np failed" );
+               }
+               if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
+                       Error( "pthread_mutex_init failed" );
+               }
+       }
+
+       if ( pthread_attr_create( &attrib ) == -1 ) {
+               Error( "pthread_attr_create failed" );
+       }
+       if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
+               Error( "pthread_attr_setstacksize failed" );
+       }
+
+       for ( i = 0 ; i < numthreads ; i++ )
+       {
+               if ( pthread_create( &work_threads[i], attrib
+                                                        , (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) {
+                       Error( "pthread_create failed" );
+               }
+       }
+
+       for ( i = 0 ; i < numthreads ; i++ )
+       {
+               if ( pthread_join( work_threads[i], &status ) == -1 ) {
+                       Error( "pthread_join failed" );
+               }
+       }
+
+       threaded = false;
+
+       end = I_FloatTime();
+       if ( pacifier ) {
+               Sys_Printf( " (%i)\n", end - start );
+       }
+}
+
+
+#elif GDEF_OS_IRIX
+
+/*
+   ===================================================================
+
+   IRIX
+
+   ===================================================================
+ */
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+int numthreads = -1;
+abilock_t lck;
+
+void ThreadSetDefault( void ){
+       if ( numthreads == -1 ) {
+               numthreads = prctl( PR_MAXPPROCS );
+       }
+       Sys_Printf( "%i threads\n", numthreads );
+       usconfig( CONF_INITUSERS, numthreads );
+}
+
+
+void ThreadLock( void ){
+       spin_lock( &lck );
+}
+
+void ThreadUnlock( void ){
+       release_lock( &lck );
+}
+
+
+/*
+   =============
+   RunThreadsOn
+   =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       int i;
+       int pid[MAX_THREADS];
+       int start, end;
+
+       start = I_FloatTime();
+       dispatch = 0;
+       workcount = workcnt;
+       oldf = -1;
+       pacifier = showpacifier;
+       threaded = true;
+
+       if ( pacifier ) {
+               setbuf( stdout, NULL );
+       }
+
+       init_lock( &lck );
+
+       for ( i = 0 ; i < numthreads - 1 ; i++ )
+       {
+               pid[i] = sprocsp( ( void ( * )( void *, size_t ) )func, PR_SALL, (void *)i
+                                                 , NULL, 0x200000 ); // 2 meg stacks
+               if ( pid[i] == -1 ) {
+                       perror( "sproc" );
+                       Error( "sproc failed" );
+               }
+       }
+
+       func( i );
+
+       for ( i = 0 ; i < numthreads - 1 ; i++ )
+               wait( NULL );
+
+       threaded = false;
+
+       end = I_FloatTime();
+       if ( pacifier ) {
+               Sys_Printf( " (%i)\n", end - start );
+       }
+}
+
+
+#elif GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
+
+/*
+   =======================================================================
+
+   Linux pthreads
+
+   =======================================================================
+ */
+
+// Setting default Threads to 1
+int numthreads = 1;
+
+void ThreadSetDefault( void ){
+       if ( numthreads == -1 ) { // not set manually
+               /* default to one thread, only multi-thread when specifically told to */
+               numthreads = 1;
+       }
+       if ( numthreads > 1 ) {
+               Sys_Printf( "threads: %d\n", numthreads );
+       }
+}
+
+#include <pthread.h>
+
+typedef struct pt_mutex_s
+{
+       pthread_t       *owner;
+       pthread_mutex_t a_mutex;
+       pthread_cond_t cond;
+       unsigned int lock;
+} pt_mutex_t;
+
+pt_mutex_t global_lock;
+
+void ThreadLock( void ){
+       pt_mutex_t *pt_mutex = &global_lock;
+
+       if ( !threaded ) {
+               return;
+       }
+
+       pthread_mutex_lock( &pt_mutex->a_mutex );
+       if ( pthread_equal( pthread_self(), (pthread_t)&pt_mutex->owner ) ) {
+               pt_mutex->lock++;
+       }
+       else
+       {
+               if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
+                       pt_mutex->owner = (pthread_t *)pthread_self();
+                       pt_mutex->lock  = 1;
+               }
+               else
+               {
+                       while ( 1 )
+                       {
+                               pthread_cond_wait( &pt_mutex->cond, &pt_mutex->a_mutex );
+                               if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
+                                       pt_mutex->owner = (pthread_t *)pthread_self();
+                                       pt_mutex->lock  = 1;
+                                       break;
+                               }
+                       }
+               }
+       }
+       pthread_mutex_unlock( &pt_mutex->a_mutex );
+}
+
+void ThreadUnlock( void ){
+       pt_mutex_t *pt_mutex = &global_lock;
+
+       if ( !threaded ) {
+               return;
+       }
+
+       pthread_mutex_lock( &pt_mutex->a_mutex );
+       pt_mutex->lock--;
+
+       if ( pt_mutex->lock == 0 ) {
+               pt_mutex->owner = NULL;
+               pthread_cond_signal( &pt_mutex->cond );
+       }
+
+       pthread_mutex_unlock( &pt_mutex->a_mutex );
+}
+
+void recursive_mutex_init( pthread_mutexattr_t attribs ){
+       pt_mutex_t *pt_mutex = &global_lock;
+
+       pt_mutex->owner = NULL;
+       if ( pthread_mutex_init( &pt_mutex->a_mutex, &attribs ) != 0 ) {
+               Error( "pthread_mutex_init failed\n" );
+       }
+       if ( pthread_cond_init( &pt_mutex->cond, NULL ) != 0 ) {
+               Error( "pthread_cond_init failed\n" );
+       }
+
+       pt_mutex->lock = 0;
+}
+
+/*
+   =============
+   RunThreadsOn
+   =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       pthread_mutexattr_t mattrib;
+       pthread_t work_threads[MAX_THREADS];
+
+       int start, end;
+       int i = 0, status = 0;
+
+       start     = I_FloatTime();
+       pacifier  = showpacifier;
+
+       dispatch  = 0;
+       oldf      = -1;
+       workcount = workcnt;
+
+       if ( numthreads == 1 ) {
+               func( 0 );
+       }
+       else
+       {
+               threaded  = true;
+
+               if ( pacifier ) {
+                       setbuf( stdout, NULL );
+               }
+
+               if ( pthread_mutexattr_init( &mattrib ) != 0 ) {
+                       Error( "pthread_mutexattr_init failed" );
+               }
+               if ( pthread_mutexattr_settype( &mattrib, PTHREAD_MUTEX_ERRORCHECK ) != 0 ) {
+                       Error( "pthread_mutexattr_settype failed" );
+               }
+               recursive_mutex_init( mattrib );
+
+               for ( i = 0 ; i < numthreads ; i++ )
+               {
+                       /* Default pthread attributes: joinable & non-realtime scheduling */
+                       if ( pthread_create( &work_threads[i], NULL, (void*)func, (void*)i ) != 0 ) {
+                               Error( "pthread_create failed" );
+                       }
+               }
+               for ( i = 0 ; i < numthreads ; i++ )
+               {
+                       if ( pthread_join( work_threads[i], (void **)&status ) != 0 ) {
+                               Error( "pthread_join failed" );
+                       }
+               }
+               pthread_mutexattr_destroy( &mattrib );
+               threaded = false;
+       }
+
+       end = I_FloatTime();
+       if ( pacifier ) {
+               Sys_Printf( " (%i)\n", end - start );
+       }
+}
+
+
+#else // UNKNOWN OS
+
+/*
+   =======================================================================
+
+   SINGLE THREAD
+
+   =======================================================================
+ */
+
+int numthreads = 1;
+
+void ThreadSetDefault( void ){
+       numthreads = 1;
+}
+
+void ThreadLock( void ){
+}
+
+void ThreadUnlock( void ){
+}
+
+/*
+   =============
+   RunThreadsOn
+   =============
+ */
+void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
+       int i;
+       int start, end;
+
+       dispatch = 0;
+       workcount = workcnt;
+       oldf = -1;
+       pacifier = showpacifier;
+       start = I_FloatTime();
+       func( 0 );
+
+       end = I_FloatTime();
+       if ( pacifier ) {
+               Sys_Printf( " (%i)\n", end - start );
+       }
+}
+
+#endif // UNKNOWN OS
diff --git a/tools/heretic2/common/token.c b/tools/heretic2/common/token.c
new file mode 100644 (file)
index 0000000..632cfe4
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+//**************************************************************************
+//**
+//** token.c
+//**
+//**************************************************************************
+
+// HEADER FILES ------------------------------------------------------------
+
+#include "token.h"
+#include "inout.h"
+
+// MACROS ------------------------------------------------------------------
+
+// TYPES -------------------------------------------------------------------
+
+typedef enum
+{
+       CHR_EOF,
+       CHR_LETTER,
+       CHR_NUMBER,
+       CHR_QUOTE,
+       CHR_SPECIAL
+} chr_t;
+
+// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
+
+// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
+
+// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
+
+static void ProcessLetterToken( void );
+static void ProcessNumberToken( void );
+static void ProcessQuoteToken( void );
+static void ProcessSpecialToken( void );
+static qboolean CheckForKeyword( void );
+static void NextChr( void );
+
+// EXTERNAL DATA DECLARATIONS ----------------------------------------------
+
+// PUBLIC DATA DEFINITIONS -------------------------------------------------
+
+tokenType_t tk_Token;
+int tk_Line;
+int tk_IntNumber;
+float tk_FloatNumber;
+char *tk_String;
+char tk_SourceName[MAX_FILE_NAME_LENGTH];
+
+// PRIVATE DATA DEFINITIONS ------------------------------------------------
+
+static char Chr;
+static char *FileStart;
+static char *FilePtr;
+static char *FileEnd;
+static qboolean SourceOpen;
+static char ASCIIToChrCode[256];
+static char TokenStringBuffer[MAX_QUOTED_LENGTH];
+static qboolean IncLineNumber;
+static char TempBuffer[2048];
+
+static struct
+{
+       char *name;
+       tokenType_t token;
+} Keywords[] =
+{
+       "model",            TK_MODEL,
+       "mesh",             TK_MESH,
+       "vertices",         TK_VERTICES,
+       "edges",            TK_EDGES,
+       "position",         TK_POSITION,
+       "polygons",         TK_POLYGONS,
+       "nodes",            TK_NODES,
+       "rotation",         TK_ROTATION,
+       "scaling",          TK_SCALING,
+       "translation",      TK_TRANSLATION,
+       "vertex",           TK_VERTEX,
+       "HRCH",             TK_HRCH,
+       "Softimage",        TK_SOFTIMAGE,
+       "material",         TK_MATERIAL,
+       "spline",           TK_SPLINE,
+
+       "Named",            TK_C_NAMED,
+       "object",           TK_OBJECT,
+       "Tri",              TK_C_TRI,
+       "Vertices",         TK_C_VERTICES,
+       "Faces",            TK_C_FACES,
+       "Vertex",           TK_C_VERTEX,
+       "list",             TK_LIST,
+       "Face",             TK_C_FACE,
+
+       "Hexen",            TK_C_HEXEN,
+       "Triangles",        TK_C_TRIANGLES,
+       "Version",          TK_C_VERSION,
+       "faces",            TK_FACES,
+       "face",             TK_FACE,
+       "origin",           TK_ORIGIN,
+
+       "DK_clusters",      TK_CLUSTERS,
+       "DK_cluster_ncvs",  TK_NUM_CLUSTER_VERTICES,
+       "name",             TK_NAME,
+       "DK_cluster_name",  TK_CLUSTER_NAME,
+       "DK_cluster_state", TK_CLUSTER_STATE,
+
+       "actor_data",       TK_ACTOR_DATA,
+       "uvTexture",        TK_UVTEXTURE,
+
+       NULL,               -1
+};
+
+static char *TokenNames[] =
+{
+       "<nothing>",
+       "<unknown_char>",
+       "<EOF>",
+       "<identifier>",
+       "<string>",
+       "<int_number>",
+       "<float_number>",
+       "(",
+       ")",
+       "{",
+       "}",
+       "[",
+       "]",
+       ":",
+       "mesh",
+       "model",
+       "nodes",
+       "rotation",
+       "scaling",
+       "translation",
+       "polygons",
+       "position",
+       "vertex",
+       "vertices",
+       "HRCH",
+       "Softimage"
+};
+
+// CODE --------------------------------------------------------------------
+
+//==========================================================================
+//
+// TK_Init
+//
+//==========================================================================
+
+void TK_Init( void ){
+       int i;
+
+       for ( i = 0; i < 256; i++ )
+       {
+               ASCIIToChrCode[i] = CHR_SPECIAL;
+       }
+       for ( i = '0'; i <= '9'; i++ )
+       {
+               ASCIIToChrCode[i] = CHR_NUMBER;
+       }
+       for ( i = 'A'; i <= 'Z'; i++ )
+       {
+               ASCIIToChrCode[i] = CHR_LETTER;
+       }
+       for ( i = 'a'; i <= 'z'; i++ )
+       {
+               ASCIIToChrCode[i] = CHR_LETTER;
+       }
+       ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
+       ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
+       ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
+       tk_String = TokenStringBuffer;
+       IncLineNumber = FALSE;
+       SourceOpen = FALSE;
+}
+
+//==========================================================================
+//
+// TK_OpenSource
+//
+//==========================================================================
+
+void TK_OpenSource( char *fileName ){
+       int size;
+
+       TK_CloseSource();
+       size = LoadFile( fileName, (void **)&FileStart );
+       strcpy( tk_SourceName, fileName );
+       SourceOpen = TRUE;
+       FileEnd = FileStart + size;
+       FilePtr = FileStart;
+       tk_Line = 1;
+       tk_Token = TK_NONE;
+       NextChr();
+}
+
+//==========================================================================
+//
+// TK_CloseSource
+//
+//==========================================================================
+
+void TK_CloseSource( void ){
+       if ( SourceOpen ) {
+               free( FileStart );
+               SourceOpen = FALSE;
+       }
+}
+
+//==========================================================================
+//
+// TK_Fetch
+//
+//==========================================================================
+
+tokenType_t TK_Fetch( void ){
+       while ( Chr == ASCII_SPACE )
+       {
+               NextChr();
+       }
+       if ( Chr == '-' ) {
+               ProcessNumberToken();
+       }
+       else{switch ( ASCIIToChrCode[(byte)Chr] )
+                {
+                case CHR_EOF:
+                        tk_Token = TK_EOF;
+                        break;
+                case CHR_LETTER:
+                        ProcessLetterToken();
+                        break;
+                case CHR_NUMBER:
+                        ProcessNumberToken();
+                        break;
+                case CHR_QUOTE:
+                        ProcessQuoteToken();
+                        break;
+                default:
+                        ProcessSpecialToken();
+                        break;
+                }}
+       return tk_Token;
+}
+
+//==========================================================================
+//
+// TK_Require
+//
+//==========================================================================
+
+void TK_Require( tokenType_t tokType ){
+       if ( tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER ) {
+               tk_FloatNumber = (float)tk_IntNumber;
+               tk_Token = TK_FLOATNUMBER;
+               return;
+       }
+       if ( tk_Token != tokType ) {
+               Error( "File '%s', line %d:\nExpected '%s', found '%s'.\n",
+                          tk_SourceName, tk_Line, TokenNames[tokType],
+                          TokenNames[tk_Token] );
+       }
+}
+
+void TK_FetchRequire( tokenType_t tokType ){
+       TK_Fetch();
+       TK_Require( tokType );
+}
+
+tokenType_t TK_RequireFetch( tokenType_t tokType ){
+       TK_Require( tokType );
+       return TK_Fetch();
+}
+
+tokenType_t TK_FetchRequireFetch( tokenType_t tokType ){
+       TK_Fetch();
+       TK_Require( tokType );
+       return TK_Fetch();
+}
+
+tokenType_t TK_Beyond( tokenType_t tokType ){
+       while ( tk_Token != tokType )
+       {
+               if ( TK_Fetch() == TK_EOF ) {
+                       Error( "File '%s':\nCould not find token '%s'.\n",       // FIXME: TokenNames table not big enuff
+                                  tk_SourceName, TokenNames[tokType] );
+               }
+       }
+       return TK_Fetch();
+}
+
+void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok ){
+       TK_Beyond( bTok );
+       TK_Require( rTok );
+}
+
+tokenType_t TK_Search( tokenType_t tokType ){
+       while ( tk_Token != tokType )
+       {
+               if ( TK_Fetch() == TK_EOF ) {
+                       return TK_EOF;
+               }
+       }
+       return TK_Fetch();
+}
+
+tokenType_t TK_Get( tokenType_t tokType ){
+       while ( tk_Token != tokType )
+       {
+               if ( TK_Fetch() == TK_EOF ) {
+                       Error( "File '%s':\nCould not find token '%s'.\n",
+                                  tk_SourceName, TokenNames[tokType] );
+               }
+       }
+       return tk_Token;
+}
+
+//==========================================================================
+//
+// ProcessLetterToken
+//
+//==========================================================================
+
+static void ProcessLetterToken( void ){
+       int i;
+       char *text;
+
+       i = 0;
+       text = TokenStringBuffer;
+       while ( ASCIIToChrCode[(byte)Chr] == CHR_LETTER
+                       || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+       {
+               if ( ++i == MAX_IDENTIFIER_LENGTH ) {
+                       Error( "File '%s', line %d:\nIdentifier too long.\n",
+                                  tk_SourceName, tk_Line );
+               }
+               *text++ = Chr;
+               NextChr();
+       }
+       *text = 0;
+       if ( CheckForKeyword() == FALSE ) {
+               tk_Token = TK_IDENTIFIER;
+       }
+}
+
+//==========================================================================
+//
+// CheckForKeyword
+//
+//==========================================================================
+
+static qboolean CheckForKeyword( void ){
+       int i;
+
+       for ( i = 0; Keywords[i].name != NULL; i++ )
+       {
+               if ( strcmp( tk_String, Keywords[i].name ) == 0 ) {
+                       tk_Token = Keywords[i].token;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+//==========================================================================
+//
+// ProcessNumberToken
+//
+//==========================================================================
+
+static void ProcessNumberToken( void ){
+       char *buffer;
+
+       buffer = TempBuffer;
+       *buffer++ = Chr;
+       NextChr();
+       while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+       {
+               *buffer++ = Chr;
+               NextChr();
+       }
+       if ( Chr == '.' ) { // Float
+               *buffer++ = Chr;
+               NextChr(); // Skip period
+               while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
+               {
+                       *buffer++ = Chr;
+                       NextChr();
+               }
+               *buffer = 0;
+               tk_FloatNumber = (float)atof( TempBuffer );
+               tk_Token = TK_FLOATNUMBER;
+               return;
+       }
+
+       // Integer
+       *buffer = 0;
+       tk_IntNumber = atoi( TempBuffer );
+       tk_Token = TK_INTNUMBER;
+}
+
+//==========================================================================
+//
+// ProcessQuoteToken
+//
+//==========================================================================
+
+static void ProcessQuoteToken( void ){
+       int i;
+       char *text;
+
+       i = 0;
+       text = TokenStringBuffer;
+       NextChr();
+       while ( Chr != ASCII_QUOTE )
+       {
+               if ( Chr == EOF_CHARACTER ) {
+                       Error( "File '%s', line %d:\n<EOF> inside string.\n",
+                                  tk_SourceName, tk_Line );
+               }
+               if ( ++i > MAX_QUOTED_LENGTH - 1 ) {
+                       Error( "File '%s', line %d:\nString literal too long.\n",
+                                  tk_SourceName, tk_Line );
+               }
+               *text++ = Chr;
+               NextChr();
+       }
+       *text = 0;
+       NextChr();
+       tk_Token = TK_STRING;
+}
+
+//==========================================================================
+//
+// ProcessSpecialToken
+//
+//==========================================================================
+
+static void ProcessSpecialToken( void ){
+       char c;
+
+       c = Chr;
+       NextChr();
+       switch ( c )
+       {
+       case '(':
+               tk_Token = TK_LPAREN;
+               break;
+       case ')':
+               tk_Token = TK_RPAREN;
+               break;
+       case '{':
+               tk_Token = TK_LBRACE;
+               break;
+       case '}':
+               tk_Token = TK_RBRACE;
+               break;
+       case '[':
+               tk_Token = TK_LBRACKET;
+               break;
+       case ']':
+               tk_Token = TK_RBRACKET;
+               break;
+       case ':':
+               tk_Token = TK_COLON;
+               break;
+       default:
+               tk_Token = TK_UNKNOWNCHAR;
+               break;
+       }
+}
+
+//==========================================================================
+//
+// NextChr
+//
+//==========================================================================
+
+static void NextChr( void ){
+       if ( FilePtr >= FileEnd ) {
+               Chr = EOF_CHARACTER;
+               return;
+       }
+       if ( IncLineNumber == TRUE ) {
+               tk_Line++;
+               IncLineNumber = FALSE;
+       }
+       Chr = *FilePtr++;
+       if ( Chr < ASCII_SPACE ) {
+               if ( Chr == '\n' ) {
+                       IncLineNumber = TRUE;
+               }
+               Chr = ASCII_SPACE;
+       }
+}
diff --git a/tools/heretic2/common/token.h b/tools/heretic2/common/token.h
new file mode 100644 (file)
index 0000000..6dca1a1
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+//**************************************************************************
+//**
+//** token.h
+//**
+//**************************************************************************
+
+#ifndef __TOKEN_H__
+#define __TOKEN_H__
+
+#include "cmdlib.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef YES
+#define YES 1
+#endif
+#ifndef NO
+#define NO 0
+#endif
+#define ASCII_SPACE 32
+#define ASCII_QUOTE 34
+#define ASCII_UNDERSCORE 95
+#define EOF_CHARACTER 127
+#define MAX_IDENTIFIER_LENGTH 64
+#define MAX_QUOTED_LENGTH 1024
+#define MAX_FILE_NAME_LENGTH 1024
+
+typedef enum
+{
+       TK_NONE,
+       TK_UNKNOWNCHAR,
+       TK_EOF,
+       TK_IDENTIFIER,          // VALUE: (char *) tk_String
+       TK_STRING,              // VALUE: (char *) tk_String
+       TK_INTNUMBER,           // VALUE: (int) tk_IntNumber
+       TK_FLOATNUMBER,         // VALUE: (float) tk_FloatNumber
+       TK_LPAREN,
+       TK_RPAREN,
+       TK_LBRACE,
+       TK_RBRACE,              // 10
+       TK_LBRACKET,
+       TK_RBRACKET,
+       TK_COLON,
+       TK_MESH,
+       TK_MODEL,               // 15
+       TK_NODES,
+       TK_ROTATION,
+       TK_SCALING,
+       TK_TRANSLATION,
+       TK_POLYGONS,            // 20
+       TK_POSITION,
+       TK_VERTEX,
+       TK_VERTICES,
+       TK_EDGES,
+       TK_HRCH,                // 25
+       TK_SOFTIMAGE,
+       TK_MATERIAL,
+       TK_SPLINE,              // 28
+
+       TK_C_NAMED,
+       TK_OBJECT,              // 30
+       TK_C_TRI,
+       TK_C_VERTICES,
+       TK_C_FACES,
+       TK_C_VERTEX,
+       TK_LIST,                // 35
+       TK_C_FACE,
+
+       TK_C_HEXEN,
+       TK_C_TRIANGLES,
+       TK_C_VERSION,
+       TK_FACES,               // 40
+       TK_FACE,
+       TK_ORIGIN,
+
+       TK_CLUSTERS,
+       TK_NUM_CLUSTER_VERTICES,
+       TK_NAME,                // 45
+       TK_CLUSTER_NAME,
+       TK_CLUSTER_STATE,
+
+       TK_ACTOR_DATA,
+       TK_UVTEXTURE,
+} tokenType_t;
+
+void TK_Init( void );
+void TK_OpenSource( char *fileName );
+void TK_CloseSource( void );
+tokenType_t TK_Fetch( void );
+void TK_Require( tokenType_t tokType );
+void TK_FetchRequire( tokenType_t tokType );
+tokenType_t TK_RequireFetch( tokenType_t tokType );
+tokenType_t TK_FetchRequireFetch( tokenType_t tokType );
+tokenType_t TK_Beyond( tokenType_t tokType );
+void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok );
+tokenType_t TK_Search( tokenType_t tokType );
+tokenType_t TK_Get( tokenType_t tokType );
+
+extern tokenType_t tk_Token;
+extern int tk_Line;
+extern int tk_IntNumber;
+extern float tk_FloatNumber;
+extern char *tk_String;
+extern char tk_SourceName[MAX_FILE_NAME_LENGTH];
+
+#endif
diff --git a/tools/heretic2/common/trilib.c b/tools/heretic2/common/trilib.c
new file mode 100644 (file)
index 0000000..29acab6
--- /dev/null
@@ -0,0 +1,1039 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// trilib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "token.h"
+#include "l3dslib.h"
+#include "fmodel.h"
+#if 1
+#include "qd_skeletons.h"
+#endif
+
+// on disk representation of a face
+#define FLOAT_START 99999.0
+#define FLOAT_END   -FLOAT_START
+#define MAGIC       123322
+#ifndef M_PI
+  #define M_PI      3.14159265
+#endif
+
+float FixHTRRotateX = 0.0;
+float FixHTRRotateY = 0.0;
+float FixHTRRotateZ = 0.0;
+float FixHTRTranslateX = 0.0;
+float FixHTRTranslateY = 0.0;
+float FixHTRTranslateZ = 0.0;
+
+//#define NOISY 1
+
+typedef struct {
+       float v[3];
+} vector;
+
+typedef struct
+{
+       vector n;    /* normal */
+       vector p;    /* point */
+       vector c;    /* color */
+       float u;     /* u */
+       float v;     /* v */
+} aliaspoint_t;
+
+typedef struct {
+       aliaspoint_t pt[3];
+} tf_triangle;
+
+
+void ByteSwapTri( tf_triangle *tri ){
+       int i;
+
+       for ( i = 0 ; i < sizeof( tf_triangle ) / 4 ; i++ )
+       {
+               ( (int *)tri )[i] = BigLong( ( (int *)tri )[i] );
+       }
+}
+
+void LoadTRI( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
+       FILE        *input;
+       float start;
+       char name[256], tex[256];
+       int i, count, magic;
+       tf_triangle tri;
+       triangle_t  *ptri;
+       int iLevel;
+       int exitpattern;
+       float t;
+
+       if ( nodesList ) {
+               *num_mesh_nodes = 0;
+               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+       }
+
+       t = -FLOAT_START;
+       *( (unsigned char *)&exitpattern + 0 ) = *( (unsigned char *)&t + 3 );
+       *( (unsigned char *)&exitpattern + 1 ) = *( (unsigned char *)&t + 2 );
+       *( (unsigned char *)&exitpattern + 2 ) = *( (unsigned char *)&t + 1 );
+       *( (unsigned char *)&exitpattern + 3 ) = *( (unsigned char *)&t + 0 );
+
+       if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
+               Error( "reader: could not open file '%s'", filename );
+       }
+
+       iLevel = 0;
+
+       fread( &magic, sizeof( int ), 1, input );
+       if ( BigLong( magic ) != MAGIC ) {
+               Error( "%s is not a Alias object separated triangle file, magic number is wrong.", filename );
+       }
+
+       ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
+
+       *pptri = ptri;
+
+       while ( feof( input ) == 0 ) {
+               if ( fread( &start,  sizeof( float ), 1, input ) < 1 ) {
+                       break;
+               }
+               *(int *)&start = BigLong( *(int *)&start );
+               if ( *(int *)&start != exitpattern ) {
+                       if ( start == FLOAT_START ) {
+                               /* Start of an object or group of objects. */
+                               i = -1;
+                               do {
+                                       /* There are probably better ways to read a string from */
+                                       /* a file, but this does allow you to do error checking */
+                                       /* (which I'm not doing) on a per character basis.      */
+                                       ++i;
+                                       fread( &( name[i] ), sizeof( char ), 1, input );
+                               } while ( name[i] != '\0' );
+
+//                             indent();
+//                             fprintf(stdout,"OBJECT START: %s\n",name);
+                               fread( &count, sizeof( int ), 1, input );
+                               count = BigLong( count );
+                               ++iLevel;
+                               if ( count != 0 ) {
+//                                     indent();
+//                                     fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
+
+                                       i = -1;
+                                       do {
+                                               ++i;
+                                               fread( &( tex[i] ), sizeof( char ), 1, input );
+                                       } while ( tex[i] != '\0' );
+
+//                                     indent();
+//                                     fprintf(stdout,"  Object texture name: '%s'\n",tex);
+                               }
+
+                               /* Else (count == 0) this is the start of a group, and */
+                               /* no texture name is present. */
+                       }
+                       else if ( start == FLOAT_END ) {
+                               /* End of an object or group. Yes, the name should be */
+                               /* obvious from context, but it is in here just to be */
+                               /* safe and to provide a little extra information for */
+                               /* those who do not wish to write a recursive reader. */
+                               /* Mia culpa. */
+                               --iLevel;
+                               i = -1;
+                               do {
+                                       ++i;
+                                       fread( &( name[i] ), sizeof( char ), 1, input );
+                               } while ( name[i] != '\0' );
+
+//                             indent();
+//                             fprintf(stdout,"OBJECT END: %s\n",name);
+                               continue;
+                       }
+               }
+
+//
+// read the triangles
+//
+               for ( i = 0; i < count; ++i ) {
+                       int j;
+
+                       fread( &tri, sizeof( tf_triangle ), 1, input );
+                       ByteSwapTri( &tri );
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               int k;
+
+                               for ( k = 0 ; k < 3 ; k++ )
+                               {
+                                       ptri->verts[j][k] = tri.pt[j].p.v[k];
+                               }
+                       }
+
+                       ptri++;
+
+                       if ( ( ptri - *pptri ) >= MAXTRIANGLES ) {
+                               Error( "Error: too many triangles; increase MAXTRIANGLES\n" );
+                       }
+               }
+       }
+
+       *numtriangles = ptri - *pptri;
+
+       fclose( input );
+
+       DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
+}
+
+
+//==========================================================================
+//
+// LoadHRC
+//
+//==========================================================================
+
+float scaling[3];
+float rotation[3];
+float translation[3];
+static char     *hrc_name;
+
+struct
+{
+       float v[3];
+} vList[8192];
+
+void HandleHRCModel( triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
+                                        int ActiveNode, int Depth, int numVerts ){
+       void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex );
+
+       int i, j;
+       int vertexCount;
+       int triCount;
+       triangle_t  *tList;
+       mesh_node_t *meshNode;
+       float x, y, z;
+       float x2, y2, z2;
+       float rx, ry, rz;
+       tokenType_t nextToken;
+       float orig_scaling[3];
+       float orig_rotation[3];
+       float orig_translation[3];
+       int start_tri;
+       int pos,bit;
+       int vertIndexBase;
+
+       // Update Node Info
+       if ( nodesList ) {
+               TK_BeyondRequire( TK_NAME, TK_STRING );
+
+               if ( Depth == 0 || tk_String[0] == '_' ) { // Root
+                       ActiveNode = *num_mesh_nodes;
+                       ( *num_mesh_nodes )++;
+                       if ( ( *num_mesh_nodes ) > MAX_FM_MESH_NODES ) {
+                               Error( "Too many mesh nodes in file %s\n", hrc_name );
+                       }
+                       meshNode = &( *nodesList )[ActiveNode];
+
+//                     memset(meshNode, 0, sizeof(mesh_node_t));
+                       strcpy( meshNode->name, tk_String );
+
+                       memset( meshNode->tris, 0, sizeof( meshNode->tris ) );
+                       memset( meshNode->verts, 0, sizeof( meshNode->verts ) );
+
+                       meshNode->start_glcmds = 0;
+                       meshNode->num_glcmds = 0;
+                       vertIndexBase = 0;
+               }
+               else
+               {   // Childs under the children
+                       meshNode = &( *nodesList )[ActiveNode];
+                       vertIndexBase = numVerts;
+               }
+       }
+       else
+       {
+               meshNode = NULL;
+       }
+
+
+       // Get the scaling, rotation, and translation values
+       TK_Beyond( TK_SCALING );
+       for ( i = 0; i < 3; i++ )
+       {
+               orig_scaling[i] = scaling[i];
+
+               TK_Require( TK_FLOATNUMBER );
+               scaling[i] *= tk_FloatNumber;
+
+               TK_Fetch();
+       }
+       TK_Beyond( TK_ROTATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               orig_rotation[i] = rotation[i];
+
+               TK_Require( TK_FLOATNUMBER );
+               rotation[i] = tk_FloatNumber;
+
+               TK_Fetch();
+       }
+       TK_Beyond( TK_TRANSLATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               orig_translation[i] = translation[i];
+
+               TK_Require( TK_FLOATNUMBER );
+               translation[i] += tk_FloatNumber;
+
+               TK_Fetch();
+       }
+
+       rx = ( ( rotation[0] - 90.0 ) / 360.0 ) * 2.0 * M_PI;
+       ry = ( rotation[2] / 360.0 ) * 2.0 * M_PI;
+       rz = ( rotation[1] / 360.0 ) * 2.0 * M_PI;
+
+       // rjr - might not work if there an item doesn't have a mesh
+       nextToken = tk_Token;
+       if ( nextToken == TK_ACTOR_DATA ) {
+               while ( nextToken != TK_MODEL && nextToken != TK_RBRACE )
+               {
+                       nextToken = TK_Fetch();
+               }
+       }
+
+       while ( nextToken == TK_SPLINE )
+       {   // spline node has two right braces
+               nextToken = TK_Beyond( TK_RBRACE );
+               nextToken = TK_Beyond( TK_RBRACE );
+       }
+
+       while ( nextToken == TK_MATERIAL )
+       {
+               nextToken = TK_Beyond( TK_RBRACE );
+       }
+
+       while ( nextToken == TK_MODEL )
+       {
+               HandleHRCModel( triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth + 1, 0 );
+
+               nextToken = TK_Fetch();
+       }
+
+       if ( nextToken == TK_MESH ) {
+               // Get all the tri and vertex info
+               TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
+               vertexCount = tk_IntNumber;
+               for ( i = 0; i < vertexCount; i++ )
+               {
+                       TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
+                       if ( tk_IntNumber != i ) {
+                               Error( "File '%s', line %d:\nVertex index mismatch.\n",
+                                          tk_SourceName, tk_Line );
+                       }
+                       TK_Beyond( TK_POSITION );
+                       // Apply the scaling, rotation, and translation in the order
+                       // specified in the HRC file.  This could be wrong.
+                       TK_Require( TK_FLOATNUMBER );
+                       x = tk_FloatNumber * scaling[0];
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       y = tk_FloatNumber * scaling[1];
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       z = tk_FloatNumber * scaling[2];
+
+                       y2 = y * cos( rx ) + z*sin( rx );
+                       z2 = -y*sin( rx ) + z*cos( rx );
+                       y = y2;
+                       z = z2;
+
+                       x2 = x * cos( ry ) - z*sin( ry );
+                       z2 = x * sin( ry ) + z*cos( ry );
+                       x = x2;
+                       z = z2;
+
+                       x2 = x * cos( rz ) + y*sin( rz );
+                       y2 = -x*sin( rz ) + y*cos( rz );
+                       x = x2;
+                       y = y2;
+
+                       vList[i].v[0] = x + translation[0];
+                       vList[i].v[1] = y - translation[2];
+                       vList[i].v[2] = z + translation[1];
+               }
+               TK_BeyondRequire( TK_POLYGONS, TK_INTNUMBER );
+               triCount = tk_IntNumber;
+               if ( triCount >= MAXTRIANGLES ) {
+                       Error( "Too many triangles in file %s\n", hrc_name );
+               }
+
+               start_tri = *triangleCount;
+               *triangleCount += triCount;
+
+               tList = *triList;
+
+               for ( i = 0; i < triCount; i++ )
+               {
+                       if ( meshNode ) { // Update the node
+                               pos = ( i + start_tri ) >> 3;
+                               bit = 1 << ( ( i + start_tri ) & 7 );
+                               meshNode->tris[pos] |= bit;
+                       }
+
+                       TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
+                       if ( tk_IntNumber != i ) {
+                               Error( "File '%s', line %d:\nTriangle index mismatch.\n",
+                                          tk_SourceName, tk_Line );
+                       }
+                       TK_BeyondRequire( TK_NODES, TK_INTNUMBER );
+                       if ( tk_IntNumber != 3 ) {
+                               Error( "File '%s', line %d:\nBad polygon vertex count: %d.",
+                                          tk_SourceName, tk_Line, tk_IntNumber );
+                       }
+                       tList[i + start_tri].HasUV = true;
+                       for ( j = 0; j < 3; j++ )
+                       {
+                               TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
+                               if ( tk_IntNumber != j ) {
+                                       Error( "File '%s', line %d:\nTriangle vertex index"
+                                                  " mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
+                                                  tk_IntNumber, j );
+                               }
+                               TK_BeyondRequire( TK_VERTEX, TK_INTNUMBER );
+
+                               tList[i + start_tri].verts[2 - j][0] = vList[tk_IntNumber].v[0];
+                               tList[i + start_tri].verts[2 - j][1] = vList[tk_IntNumber].v[1];
+                               tList[i + start_tri].verts[2 - j][2] = vList[tk_IntNumber].v[2];
+#if 1
+                               tList[i + start_tri].indicies[2 - j] = tk_IntNumber + vertIndexBase;
+#endif
+                               TK_BeyondRequire( TK_UVTEXTURE, TK_FLOATNUMBER );
+                               tList[i + start_tri].uv[2 - j][0] = tk_FloatNumber;
+                               TK_Fetch();
+                               TK_Require( TK_FLOATNUMBER );
+                               tList[i + start_tri].uv[2 - j][1] = tk_FloatNumber;
+                       }
+
+                       /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+                                   "  v2: %f, %f, %f\n", i,
+                                   tList[i].verts[0][0],
+                                   tList[i].verts[0][1],
+                                   tList[i].verts[0][2],
+                                   tList[i].verts[1][0],
+                                   tList[i].verts[1][1],
+                                   tList[i].verts[1][2],
+                                   tList[i].verts[2][0],
+                                   tList[i].verts[2][1],
+                                   tList[i].verts[2][2]);
+                        */
+               }
+
+               TK_Beyond( TK_RBRACE );
+               TK_Beyond( TK_RBRACE );
+
+               if ( tk_Token == TK_EDGES ) {
+                       //      TK_Beyond(TK_EDGES);
+                       TK_Beyond( TK_RBRACE );
+               }
+
+               scaling[0] = scaling[1] = scaling[2] = 1.0;
+               //      rotation[0] = rotation[1] = rotation[2] = 0.0;
+               //      translation[0] = translation[1] = translation[2] = 0.0;
+
+               // See if there are any other models belonging to this node
+
+#if 1
+               TK_Fetch();
+
+               nextToken = tk_Token;
+               if ( nextToken == TK_CLUSTERS ) {
+                       if ( g_skelModel.clustered == -1 ) {
+                               ReadHRCClusterList( meshNode, vertIndexBase );
+                       }
+                       else
+                       {
+                               nextToken = TK_Get( TK_CLUSTER_NAME );
+
+                               while ( nextToken == TK_CLUSTER_NAME )
+                               {
+                                       TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
+                                       nextToken = TK_Fetch();
+                               }
+                       }
+
+                       // one right brace follow the list of clusters
+                       nextToken = TK_Beyond( TK_RBRACE );
+               }
+               else
+               {
+                       if ( g_skelModel.clustered == -1 && !vertIndexBase ) {
+                               meshNode->clustered = false;
+                       }
+               }
+#endif
+
+               nextToken = tk_Token;
+               if ( nextToken == TK_SPLINE ) {
+                       while ( nextToken == TK_SPLINE )
+                       {   // spline node has two right braces
+                               nextToken = TK_Beyond( TK_RBRACE );
+                               nextToken = TK_Beyond( TK_RBRACE );
+                       }
+
+                       nextToken = TK_Beyond( TK_RBRACE );
+               }
+
+               while ( nextToken == TK_MATERIAL )
+               {
+                       nextToken = TK_Beyond( TK_RBRACE );
+               }
+
+               while ( nextToken == TK_MODEL )
+               {
+                       HandleHRCModel( triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth + 1, vertexCount + vertIndexBase );
+
+                       nextToken = TK_Fetch();
+               }
+       }
+
+       for ( i = 0; i < 3; i++ )
+       {
+               scaling[i] = orig_scaling[i];
+               rotation[i] = orig_rotation[i];
+               translation[i] = orig_translation[i];
+       }
+}
+
+static void LoadHRC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
+       if ( nodesList ) {
+               *num_mesh_nodes = 0;
+
+               if ( !*nodesList ) {
+                       *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+               }
+       }
+
+       hrc_name = fileName;
+
+       scaling[0] = scaling[1] = scaling[2] = 1.0;
+       rotation[0] = rotation[1] = rotation[2] = 0.0;
+       translation[0] = translation[1] = translation[2] = 0.0;
+
+       *triangleCount = 0;
+       *triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
+       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       // prime it
+       TK_Beyond( TK_MODEL );
+
+       HandleHRCModel( triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0 );
+       TK_CloseSource();
+}
+
+//==========================================================================
+//
+// LoadHTR
+//
+//==========================================================================
+/*
+   static int Version2;
+
+   void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
+                           int ActiveNode, int Depth, int numVerts)
+   {
+    int                        i, j;
+    int                        vertexCount;
+    int                        vertexNum;
+    int                        triCount;
+    float              origin[3];
+    triangle_t *tList;
+    float              x, y, z;
+    float              x2, y2, z2;
+    float              rx, ry, rz;
+    mesh_node_t *meshNode;
+    int                        pos,bit;
+    int                        vertIndexBase;
+    int                        start_tri;
+
+    if (nodesList)
+    {
+        TK_BeyondRequire(TK_NAME, TK_STRING);
+
+        if (Depth == 0 || tk_String[0] == '_')
+        {      // Root
+            ActiveNode = *num_mesh_nodes;
+            (*num_mesh_nodes)++;
+            if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
+            {
+                Error("Too many mesh nodes in file %s\n", hrc_name);
+            }
+            meshNode = &(*nodesList)[ActiveNode];
+
+   //                  memset(meshNode, 0, sizeof(mesh_node_t));
+            strcpy(meshNode->name, tk_String);
+
+            memset(meshNode->tris, 0, sizeof(meshNode->tris));
+            memset(meshNode->verts, 0, sizeof(meshNode->verts));
+
+            meshNode->start_glcmds = 0;
+            meshNode->num_glcmds = 0;
+            vertIndexBase = 0;
+        }
+        else
+        {      // Childs under the children
+            meshNode = &(*nodesList)[ActiveNode];
+            vertIndexBase = numVerts;
+        }
+    }
+    else
+    {
+        meshNode = NULL;
+    }
+
+    // Get vertex count
+    TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
+    vertexCount = tk_IntNumber;
+
+    // Get triangle count
+    TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
+    triCount = tk_IntNumber;
+    if(triCount >= MAXTRIANGLES)
+    {
+        Error("Too many triangles in file %s\n", hrc_name);
+    }
+
+    // Get origin
+    TK_Beyond(TK_ORIGIN);
+    TK_Require(TK_FLOATNUMBER);
+    origin[0] = tk_FloatNumber;
+    TK_FetchRequire(TK_FLOATNUMBER);
+    origin[1] = tk_FloatNumber;
+    TK_FetchRequire(TK_FLOATNUMBER);
+    origin[2] = tk_FloatNumber;
+
+    //rx = 90.0/360.0*2.0*M_PI;
+    rx = FixHTRRotateX/360.0*2.0*M_PI;
+    ry = FixHTRRotateY/360.0*2.0*M_PI;
+    rz = FixHTRRotateZ/360.0*2.0*M_PI;
+
+    // Get vertex list
+    for(i = 0; i < vertexCount; i++)
+    {
+        TK_FetchRequire(TK_VERTEX);
+        TK_FetchRequire(TK_FLOATNUMBER);
+        x = tk_FloatNumber-origin[0];
+        TK_FetchRequire(TK_FLOATNUMBER);
+        y = tk_FloatNumber-origin[1];
+        TK_FetchRequire(TK_FLOATNUMBER);
+        z = tk_FloatNumber-origin[2];
+
+        x += FixHTRTranslateX;
+        y += FixHTRTranslateY;
+        z += FixHTRTranslateZ;
+
+        y2 = y*cos(rx)-z*sin(rx);
+        z2 = y*sin(rx)+z*cos(rx);
+        y = y2;
+        z = z2;
+        x2 = x*cos(ry)+z*sin(ry);
+        z2 = -x*sin(ry)+z*cos(ry);
+        x = x2;
+        z = z2;
+        x2 = x*cos(rz)-y*sin(rz);
+        y2 = x*sin(rz)+y*cos(rz);
+        x = x2;
+        y = y2;
+
+        vList[i].v[0] = x;
+        vList[i].v[1] = y;
+        vList[i].v[2] = z;
+    }
+
+    start_tri = *triangleCount;
+   *triangleCount += triCount;
+
+    tList = *triList;
+
+    // Get face list
+    for(i = 0; i < triCount; i++)
+    {
+        if (meshNode)
+        {      // Update the node
+            pos = (i + start_tri) >> 3;
+            bit = 1 << ((i + start_tri) & 7 );
+            meshNode->tris[pos] |= bit;
+        }
+
+        TK_FetchRequire(TK_FACE);
+        TK_FetchRequire(TK_LPAREN);
+        for(j = 0; j < 3; j++)
+        {
+            TK_FetchRequire(TK_INTNUMBER);
+            vertexNum = tk_IntNumber-1;
+            if(vertexNum >= vertexCount)
+            {
+                Error("File '%s', line %d:\nVertex number"
+                    " >= vertexCount: %d\n", tk_SourceName, tk_Line,
+                    tk_IntNumber);
+            }
+            tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0];
+            tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1];
+            tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2];
+        }
+        TK_FetchRequire(TK_RPAREN);
+   #ifdef _QDATA
+        if (Version2)
+        {
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[0][0]=tk_FloatNumber;
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[0][1]=tk_FloatNumber;
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[1][0]=tk_FloatNumber;
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[1][1]=tk_FloatNumber;
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[2][0]=tk_FloatNumber;
+            TK_FetchRequire(TK_FLOATNUMBER);
+            tList[i+start_tri].uv[2][1]=tk_FloatNumber;
+            tList[i+start_tri].HasUV=1;
+        }
+        else
+            tList[i+start_tri].HasUV=0;
+   #endif
+   //          printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+   //                  "  v2: %f, %f, %f\n", i,
+   //                  tList[i].verts[0][0],
+   //                  tList[i].verts[0][1],
+   //                  tList[i].verts[0][2],
+   //                  tList[i].verts[1][0],
+   //                  tList[i].verts[1][1],
+   //                  tList[i].verts[1][2],
+   //                  tList[i].verts[2][0],
+   //                  tList[i].verts[2][1],
+   //                  tList[i].verts[2][2]);
+
+    }
+
+    TK_Fetch();
+
+    if (tk_Token == TK_VERTICES)
+    {
+        HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
+    }
+   }
+
+   static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
+   {
+    if (nodesList)
+    {
+   *num_mesh_nodes = 0;
+
+        if(!*nodesList)
+        {
+   *nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+        }
+    }
+
+    hrc_name = fileName;
+
+    scaling[0] = scaling[1] = scaling[2] = 1.0;
+    rotation[0] = rotation[1] = rotation[2] = 0.0;
+    translation[0] = translation[1] = translation[2] = 0.0;
+
+   *triangleCount = 0;
+   *triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+    memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
+
+    TK_OpenSource(fileName);
+
+    TK_Beyond(TK_C_HEXEN);
+    TK_Beyond(TK_C_TRIANGLES);
+    TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
+    if(tk_IntNumber != 1&&tk_IntNumber != 2)
+    {
+        Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
+            fileName);
+    }
+    Version2=(tk_IntNumber==2);
+
+
+    HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
+   }
+
+ */
+
+static void LoadHTR( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
+       int Version2 = 0;
+       int i, j;
+       int vertexCount;
+       int vertexNum;
+       struct
+       {
+               float v[3];
+       }           *vList;
+       int triCount;
+       float origin[3];
+       triangle_t  *tList;
+       float x, y, z;
+       float x2, y2, z2;
+       float rx, ry, rz;
+
+       if ( nodesList ) {
+               *num_mesh_nodes = 0;
+               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+       }
+
+       TK_OpenSource( fileName );
+
+       TK_Beyond( TK_C_HEXEN );
+       TK_Beyond( TK_C_TRIANGLES );
+       TK_BeyondRequire( TK_C_VERSION, TK_INTNUMBER );
+       if ( tk_IntNumber != 1 && tk_IntNumber != 2 ) {
+               Error( "Unsupported version (%d) in file %s\n", tk_IntNumber,
+                          fileName );
+       }
+       Version2 = ( tk_IntNumber == 2 );
+
+
+       // Get vertex count
+       TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
+       vertexCount = tk_IntNumber;
+       vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
+
+       // Get triangle count
+       TK_BeyondRequire( TK_FACES, TK_INTNUMBER );
+       triCount = tk_IntNumber;
+       if ( triCount >= MAXTRIANGLES ) {
+               Error( "Too many triangles in file %s\n", fileName );
+       }
+       *triangleCount = triCount;
+       tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
+       *triList = tList;
+       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
+
+       // Get origin
+       TK_Beyond( TK_ORIGIN );
+       TK_Require( TK_FLOATNUMBER );
+       origin[0] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       origin[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       origin[2] = tk_FloatNumber;
+
+       //rx = 90.0/360.0*2.0*M_PI;
+       rx = FixHTRRotateX / 360.0 * 2.0 * M_PI;
+       ry = FixHTRRotateY / 360.0 * 2.0 * M_PI;
+       rz = FixHTRRotateZ / 360.0 * 2.0 * M_PI;
+
+       // Get vertex list
+       for ( i = 0; i < vertexCount; i++ )
+       {
+               TK_FetchRequire( TK_VERTEX );
+               TK_FetchRequire( TK_FLOATNUMBER );
+               x = tk_FloatNumber - origin[0];
+               TK_FetchRequire( TK_FLOATNUMBER );
+               y = tk_FloatNumber - origin[1];
+               TK_FetchRequire( TK_FLOATNUMBER );
+               z = tk_FloatNumber - origin[2];
+
+               x += FixHTRTranslateX;
+               y += FixHTRTranslateY;
+               z += FixHTRTranslateZ;
+
+               y2 = y * cos( rx ) - z*sin( rx );
+               z2 = y * sin( rx ) + z*cos( rx );
+               y = y2;
+               z = z2;
+               x2 = x * cos( ry ) + z*sin( ry );
+               z2 = -x*sin( ry ) + z*cos( ry );
+               x = x2;
+               z = z2;
+               x2 = x * cos( rz ) - y*sin( rz );
+               y2 = x * sin( rz ) + y*cos( rz );
+               x = x2;
+               y = y2;
+
+               vList[i].v[0] = x;
+               vList[i].v[1] = y;
+               vList[i].v[2] = z;
+       }
+
+       // Get face list
+       for ( i = 0; i < triCount; i++ )
+       {
+               TK_FetchRequire( TK_FACE );
+               TK_FetchRequire( TK_LPAREN );
+               for ( j = 0; j < 3; j++ )
+               {
+                       TK_FetchRequire( TK_INTNUMBER );
+                       vertexNum = tk_IntNumber - 1;
+                       if ( vertexNum >= vertexCount ) {
+                               Error( "File '%s', line %d:\nVertex number"
+                                          " >= vertexCount: %d\n", tk_SourceName, tk_Line,
+                                          tk_IntNumber );
+                       }
+                       tList[i].verts[2 - j][0] = vList[vertexNum].v[0];
+                       tList[i].verts[2 - j][1] = vList[vertexNum].v[1];
+                       tList[i].verts[2 - j][2] = vList[vertexNum].v[2];
+               }
+               TK_FetchRequire( TK_RPAREN );
+#if 1
+               if ( Version2 ) {
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[2][0] = fmod( 1000 + tk_FloatNumber,1 );
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[2][1] = fmod( 1000 + tk_FloatNumber,1 );
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[1][0] = fmod( 1000 + tk_FloatNumber,1 );
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[1][1] = fmod( 1000 + tk_FloatNumber,1 );
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[0][0] = fmod( 1000 + tk_FloatNumber,1 );
+                       TK_FetchRequire( TK_FLOATNUMBER );
+                       tList[i].uv[0][1] = fmod( 1000 + tk_FloatNumber,1 );
+                       tList[i].HasUV = 1;
+               }
+               else{
+                       tList[i].HasUV = 0;
+               }
+#endif
+/*             printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+            "  v2: %f, %f, %f\n", i,
+            tList[i].verts[0][0],
+            tList[i].verts[0][1],
+            tList[i].verts[0][2],
+            tList[i].verts[1][0],
+            tList[i].verts[1][1],
+            tList[i].verts[1][2],
+            tList[i].verts[2][0],
+            tList[i].verts[2][1],
+            tList[i].verts[2][2]);
+ */
+       }
+
+       free( vList );
+       TK_CloseSource();
+       DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
+}
+
+//==========================================================================
+//
+// LoadTriangleList
+//
+//==========================================================================
+
+void LoadTriangleList( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes ){
+       FILE    *file1;
+       int dot = '.';
+       char    *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+                       LoadHRC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".asc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+                       LoadASC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       printf( " - assuming .ASC\n" );
+                       return;
+               }
+
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".tri" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+                       LoadTRI( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       printf( " - assuming .TRI\n" );
+                       return;
+               }
+
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".3ds" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+                       Load3DSTriangleList( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       printf( " - assuming .3DS\n" );
+                       return;
+               }
+
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".htr" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+                       LoadHTR( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       printf( " - assuming .HTR\n" );
+                       return;
+               }
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+                       printf( "\n" );
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       }
+                       else if ( strcmp( dotstart,".asc" ) == 0 || strcmp( dotstart,".ASC" ) == 0 ) {
+                               LoadASC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       }
+                       else if ( strcmp( dotstart,".tri" ) == 0 || strcmp( dotstart,".TRI" ) == 0 ) {
+                               LoadTRI( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       }
+                       else if ( strcmp( dotstart,".3ds" ) == 0 || strcmp( dotstart,".3DS" ) == 0 ) {
+                               Load3DSTriangleList( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       }
+                       else if ( strcmp( dotstart,".htr" ) == 0 || strcmp( dotstart,".HTR" ) == 0 ) {
+                               LoadHTR( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
+                       }
+                       else
+                       {
+                               Error( "Could not open file '%s':\n",fileName );
+                               return;
+                       }
+               }
+               else    //failed to load file
+               {
+                       Error( "Could not open file '%s':\n",fileName );
+               }
+
+       }
+}
diff --git a/tools/heretic2/common/trilib.h b/tools/heretic2/common/trilib.h
new file mode 100644 (file)
index 0000000..8dfd6d2
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// trilib.h: header file for loading triangles from an Alias triangle file
+//
+
+#include "fmodel.h"
+
+#define MAXTRIANGLES    MAX_FM_TRIANGLES
+
+typedef struct
+{
+       vec3_t verts[3];
+#if 1
+       int indicies[3];
+       float uv[3][2];
+       qboolean HasUV;
+#endif
+} triangle_t;
+
+#define NUM_CLUSTERS 8
+
+typedef struct
+{
+       char name[64];
+       byte tris[MAXTRIANGLES >> 3];
+       byte verts[MAX_FM_VERTS >> 3];
+       int start_glcmds, num_glcmds;
+
+       int *clusters[NUM_CLUSTERS];
+       struct IntListNode_s *vertLists[NUM_CLUSTERS];
+       int num_verts[NUM_CLUSTERS + 1];
+       int new_num_verts[NUM_CLUSTERS + 1];
+       qboolean clustered;
+} mesh_node_t;
+
+void LoadTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes );
diff --git a/tools/heretic2/h2data/adpcm.h b/tools/heretic2/h2data/adpcm.h
new file mode 100644 (file)
index 0000000..aad74ea
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+/*
+** adpcm.h - include file for adpcm coder.
+**
+** Version 1.0, 7-Jul-92.
+**
+** Modded 10/3/98
+** John Scott
+*/
+
+typedef struct adpcm_state_s
+{
+       short in_valprev;           // Previous output value
+       short in_index;             // Index into stepsize table
+       short out_valprev;          // Previous output value
+       short out_index;            // Index into stepsize table
+       int count;                  // Number of sample counts
+}   adpcm_state_t;
+
+typedef struct adpcm_s
+{
+       adpcm_state_t state;
+       char adpcm[0x10000];
+}   adpcm_t;
+
+void adpcm_coder( short [], adpcm_t * );
+void adpcm_decoder( adpcm_t *, short [] );
+
+// end
diff --git a/tools/heretic2/h2data/animcomp.c b/tools/heretic2/h2data/animcomp.c
new file mode 100644 (file)
index 0000000..778f4c1
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+#include "animcomp.h"
+
+
+void    *SafeMalloc( size_t n, char *desc );
+
+
+
+float *matrix;
+float *delta;
+float *best;
+float *comp;
+float *tcomp;
+float *bestcomp;
+static float *frames;
+float *base;
+
+int MatWidth;
+int MatHeight;
+int CFrameSize;
+int nFrames;
+
+
+void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
+       nFrames = nframes;
+       MatWidth = nVerts * 3;
+       MatHeight = CompressedFrameSize;
+       CFrameSize = CompressedFrameSize;
+       matrix = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+       best = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+       delta = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
+       comp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+       tcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+       bestcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
+       base = (float *)SafeMalloc( MatWidth * sizeof( float ), "AnimCompressInit" );
+       frames = (float *)SafeMalloc( MatWidth * nFrames * sizeof( float ), "AnimCompressInit" );
+}
+
+void AnimSetFrame( int frame,int index,float x,float y,float z ){
+       frames[frame * MatWidth + index * 3] = x;
+       frames[frame * MatWidth + index * 3 + 1] = y;
+       frames[frame * MatWidth + index * 3 + 2] = z;
+}
+
+typedef struct
+{
+       int index;
+       float val;
+} SORTP;
+
+
+#define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
+
+extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
+
+void AnimCompressDoit(){
+       float compression;
+       float *rescale;
+       float *ans;
+       float maxdev;
+       float avedev;
+       float tmp;
+       int j,k,l,numave;
+
+       for ( k = 0; k < MatWidth; k++ )
+               base[k] = 0.0f;
+       for ( j = 0; j < nFrames; j++ )
+               for ( k = 0; k < MatWidth; k++ )
+                       base[k] += frames[j * MatWidth + k];
+       tmp = 1.0f / (float)nFrames;
+       for ( k = 0; k < MatWidth; k++ )
+               base[k] *= tmp;
+       for ( j = 0; j < nFrames; j++ )
+               for ( k = 0; k < MatWidth; k++ )
+                       frames[j * MatWidth + k] -= base[k];
+
+       ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressDoit" );
+       rescale = (float *)SafeMalloc( sizeof( float ) * CFrameSize, "AnimCompressDoit" );
+       DOsvd( frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight );
+       avedev = 0.0;
+       for ( l = 0; l < CFrameSize; l++ )
+               avedev += rescale[l];
+       for ( l = 0; l < CFrameSize; l++ )
+               printf( "%3.1f ",100.0f * rescale[l] / avedev );
+       printf( "\n" );
+       for ( j = 0; j < nFrames; j++ )
+       {
+               for ( l = 0; l < CFrameSize; l++ )
+               {
+                       bestcomp[j * CFrameSize + l] = 0.0;
+                       for ( k = 0; k < MatWidth; k++ )
+                               bestcomp[j * CFrameSize + l] += best[l * MatWidth + k] * frames[j * MatWidth + k];
+               }
+       }
+       numave = 0;
+       avedev = 0.0;
+       maxdev = 0.0;
+       for ( j = 0; j < nFrames; j++ )
+       {
+               for ( k = 0; k < MatWidth; k++ )
+               {
+                       ans[k] = 0.0;
+                       for ( l = 0; l < CFrameSize; l++ )
+                               ans[k] += best[l * MatWidth + k] * bestcomp[j * CFrameSize + l];
+                       ans[k] -= frames[j * MatWidth + k];
+                       tmp = (float)fabs( ans[k] );
+                       if ( tmp > maxdev ) {
+                               maxdev = tmp;
+                       }
+                       avedev += tmp;
+                       numave++;
+               }
+       }
+       avedev /= (float)numave;
+       printf( "%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev );
+       printf( "%d bytes original size\n",MatWidth * nFrames );
+       printf( "%d bytes of overhead\n",MatWidth * MatHeight );
+       printf( "%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize * nFrames );
+       compression = (float)( MatWidth * MatHeight + CFrameSize * nFrames + MatWidth );
+       compression /= (float)( MatWidth * nFrames );
+       printf( "Overall compression = %f %%\n",100.0f - 100.0f * compression );
+       compression = (float)( CFrameSize );
+       compression /= (float)( MatWidth );
+       printf( "frame size compression = %f %%\n",100.0f - 100.0f * compression );
+       free( rescale );
+       free( ans );
+}
+
+void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
+       int k,l,nv,j;
+       float maxdev;
+       float avedev;
+       float tmp;
+       int numave;
+       float t,mx;
+       float *ans;
+
+
+       nv = MatWidth / 3;
+
+       trans[0] = 1E30f;
+       scale[0] = -1E30f;
+       trans[1] = 1E30f;
+       scale[1] = -1E30f;
+       trans[2] = 1E30f;
+       scale[2] = -1E30f;
+       for ( k = 0; k < MatWidth; k += 3 )
+       {
+               if ( base[k] > scale[0] ) {
+                       scale[0] = base[k];
+               }
+               if ( base[k] < trans[0] ) {
+                       trans[0] = base[k];
+               }
+
+               if ( base[k + 1] > scale[1] ) {
+                       scale[1] = base[k + 1];
+               }
+               if ( base[k + 1] < trans[1] ) {
+                       trans[1] = base[k + 1];
+               }
+
+               if ( base[k + 2] > scale[2] ) {
+                       scale[2] = base[k + 2];
+               }
+               if ( base[k + 2] < trans[2] ) {
+                       trans[2] = base[k + 2];
+               }
+       }
+
+       scale[0] -= trans[0];
+       scale[1] -= trans[1];
+       scale[2] -= trans[2];
+       scale[0] /= 255.0f;
+       scale[1] /= 255.0f;
+       scale[2] /= 255.0f;
+       for ( k = 0; k < MatWidth; k += 3 )
+       {
+               t = ( base[k] - trans[0] ) / scale[0];
+               if ( t < 0.0f ) {
+                       t = 0.0f;
+               }
+               if ( t > 255.0f ) {
+                       t = 255.0f;
+               }
+               cbase[k] = (unsigned char)t;
+
+               t = ( base[k + 1] - trans[1] ) / scale[1];
+               if ( t < 0.0f ) {
+                       t = 0.0f;
+               }
+               if ( t > 255.0f ) {
+                       t = 255.0f;
+               }
+               cbase[k + 1] = (unsigned char)t;
+
+               t = ( base[k + 2] - trans[2] ) / scale[2];
+               if ( t < 0.0f ) {
+                       t = 0.0f;
+               }
+               if ( t > 255.0f ) {
+                       t = 255.0f;
+               }
+               cbase[k + 2] = (unsigned char)t;
+       }
+       for ( l = 0; l < MatHeight; l++ )
+       {
+               mx = 0.0;
+               for ( k = 0; k < MatWidth; k++ )
+               {
+                       if ( fabs( best[l * MatWidth + k] ) > mx ) {
+                               mx = (float)fabs( best[l * MatWidth + k] );
+                       }
+               }
+               if ( mx > 1E-8 ) {
+                       mx /= 127.0f;
+                       coffset[l] = 1E30f;
+                       cscale[l] = -1E30f;
+                       for ( j = 0; j < nFrames; j++ )
+                       {
+                               bestcomp[j * MatHeight + l] *= mx;
+                               if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
+                                       cscale[l] = bestcomp[j * MatHeight + l];
+                               }
+                               if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
+                                       coffset[l] = bestcomp[j * MatHeight + l];
+                               }
+                       }
+                       cscale[l] -= coffset[l];
+                       if ( cscale[l] > 1E-10 ) {
+                               for ( j = 0; j < nFrames; j++ )
+                               {
+                                       tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
+                                       if ( tmp > 127.0f ) {
+                                               tmp = 127.0f;
+                                       }
+                                       if ( tmp < -127.0f ) {
+                                               tmp = -127.0f;
+                                       }
+                                       ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
+                               }
+                               coffset[l] += cscale[l] * 127.0f / 254.0f;
+                               cscale[l] /= 254.0f;
+                       }
+                       else
+                       {
+                               cscale[l] = 1.0f;
+                               coffset[l] = 0.0f;
+                               for ( j = 0; j < nFrames; j++ )
+                                       ccomp[j * MatHeight + l] = 0;
+                       }
+                       mx = 1.0f / mx;
+                       for ( k = 0; k < MatWidth; k++ )
+                       {
+                               tmp = best[l * MatWidth + k] * mx;
+                               if ( tmp > 127.0f ) {
+                                       tmp = 127.0f;
+                               }
+                               if ( tmp < -127.0f ) {
+                                       tmp = -127.0f;
+                               }
+                               mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
+                       }
+               }
+               else
+               {
+                       cscale[l] = 1.0f;
+                       coffset[l] = 0.0f;
+                       for ( j = 0; j < nFrames; j++ )
+                               ccomp[j * MatHeight + l] = 0;
+                       for ( k = 0; k < MatWidth; k++ )
+                               mat[k * MatHeight + l] = 0;
+               }
+       }
+       bmin[0] = 1E30f;
+       bmin[1] = 1E30f;
+       bmin[2] = 1E30f;
+       bmax[0] = -1E30f;
+       bmax[1] = -1E30f;
+       bmax[2] = -1E30f;
+       numave = 0;
+       avedev = 0.0;
+       maxdev = 0.0;
+       ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
+       for ( j = 0; j < nFrames; j++ )
+       {
+               for ( k = 0; k < MatWidth; k++ )
+               {
+                       ans[k] = 0.0;
+                       for ( l = 0; l < CFrameSize; l++ )
+                               ans[k] += (float)( mat[l + k * MatHeight] ) * ( (float)( ccomp[j * CFrameSize + l] ) * cscale[l] + coffset[l] );
+                       ans[k] += (float)( cbase[k] ) * scale[k % 3] + trans[k % 3];
+                       tmp = (float)fabs( ans[k] - frames[j * MatWidth + k] - base[k] );
+                       if ( tmp > maxdev ) {
+                               maxdev = tmp;
+                       }
+                       avedev += tmp;
+                       numave++;
+
+                       if ( bmin[k % 3] > ans[k] ) {
+                               bmin[k % 3] = ans[k];
+                       }
+                       if ( bmax[k % 3] < ans[k] ) {
+                               bmax[k % 3] = ans[k];
+                       }
+               }
+       }
+       avedev /= (float)numave;
+       printf( "%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev );
+       free( ans );
+}
+
+void AnimCompressGetMatrix( float *mat ){
+       int k,l;
+       for ( k = 0; k < MatWidth; k++ )
+               for ( l = 0; l < MatHeight; l++ )
+                       mat[k * MatHeight + l] = best[l * MatWidth + k];
+}
+
+void AnimCompressGetFrames( float *mat ){
+       memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
+}
+
+void AnimCompressGetBase( int i,float *x,float *y,float *z ){
+       *x = base[i * 3];
+       *y = base[i * 3 + 1];
+       *z = base[i * 3 + 2];
+}
+
+void AnimCompressEnd(){
+       free( matrix );
+       free( best );
+       free( delta );
+       free( comp );
+       free( tcomp );
+       free( bestcomp );
+       free( base );
+       free( frames );
+}
diff --git a/tools/heretic2/h2data/animcomp.h b/tools/heretic2/h2data/animcomp.h
new file mode 100644 (file)
index 0000000..36ea3b1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#if !defined( ANIMCOMP_INC )
+#define ANIMCOMP_INC
+
+#ifdef  __cplusplus
+extern "C"
+{
+#endif
+void AnimCompressInit( int nFrames,int nVerts,int CompressedFrameSize );
+void AnimSetFrame( int frame,int index,float x,float y,float z );
+void AnimCompressDoit();
+void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax );
+void AnimCompressGetMatrix( float *mat );
+void AnimCompressGetFrames( float *mat );
+void AnimCompressGetBase( int i,float *x,float *y,float *z );
+void AnimCompressEnd();
+void DOsvdPlane( float *pnts,int npnts,float *n,float *base );
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/heretic2/h2data/anorms.h b/tools/heretic2/h2data/anorms.h
new file mode 100644 (file)
index 0000000..65e92ef
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+{-0.525731f, 0.000000f, 0.850651f},
+{-0.442863f, 0.238856f, 0.864188f},
+{-0.295242f, 0.000000f, 0.955423f},
+{-0.309017f, 0.500000f, 0.809017f},
+{-0.162460f, 0.262866f, 0.951056f},
+{0.000000f, 0.000000f, 1.000000f},
+{0.000000f, 0.850651f, 0.525731f},
+{-0.147621f, 0.716567f, 0.681718f},
+{0.147621f, 0.716567f, 0.681718f},
+{0.000000f, 0.525731f, 0.850651f},
+{0.309017f, 0.500000f, 0.809017f},
+{0.525731f, 0.000000f, 0.850651f},
+{0.295242f, 0.000000f, 0.955423f},
+{0.442863f, 0.238856f, 0.864188f},
+{0.162460f, 0.262866f, 0.951056f},
+{-0.681718f, 0.147621f, 0.716567f},
+{-0.809017f, 0.309017f, 0.500000f},
+{-0.587785f, 0.425325f, 0.688191f},
+{-0.850651f, 0.525731f, 0.000000f},
+{-0.864188f, 0.442863f, 0.238856f},
+{-0.716567f, 0.681718f, 0.147621f},
+{-0.688191f, 0.587785f, 0.425325f},
+{-0.500000f, 0.809017f, 0.309017f},
+{-0.238856f, 0.864188f, 0.442863f},
+{-0.425325f, 0.688191f, 0.587785f},
+{-0.716567f, 0.681718f, -0.147621f},
+{-0.500000f, 0.809017f, -0.309017f},
+{-0.525731f, 0.850651f, 0.000000f},
+{0.000000f, 0.850651f, -0.525731f},
+{-0.238856f, 0.864188f, -0.442863f},
+{0.000000f, 0.955423f, -0.295242f},
+{-0.262866f, 0.951056f, -0.162460f},
+{0.000000f, 1.000000f, 0.000000f},
+{0.000000f, 0.955423f, 0.295242f},
+{-0.262866f, 0.951056f, 0.162460f},
+{0.238856f, 0.864188f, 0.442863f},
+{0.262866f, 0.951056f, 0.162460f},
+{0.500000f, 0.809017f, 0.309017f},
+{0.238856f, 0.864188f, -0.442863f},
+{0.262866f, 0.951056f, -0.162460f},
+{0.500000f, 0.809017f, -0.309017f},
+{0.850651f, 0.525731f, 0.000000f},
+{0.716567f, 0.681718f, 0.147621f},
+{0.716567f, 0.681718f, -0.147621f},
+{0.525731f, 0.850651f, 0.000000f},
+{0.425325f, 0.688191f, 0.587785f},
+{0.864188f, 0.442863f, 0.238856f},
+{0.688191f, 0.587785f, 0.425325f},
+{0.809017f, 0.309017f, 0.500000f},
+{0.681718f, 0.147621f, 0.716567f},
+{0.587785f, 0.425325f, 0.688191f},
+{0.955423f, 0.295242f, 0.000000f},
+{1.000000f, 0.000000f, 0.000000f},
+{0.951056f, 0.162460f, 0.262866f},
+{0.850651f, -0.525731f, 0.000000f},
+{0.955423f, -0.295242f, 0.000000f},
+{0.864188f, -0.442863f, 0.238856f},
+{0.951056f, -0.162460f, 0.262866f},
+{0.809017f, -0.309017f, 0.500000f},
+{0.681718f, -0.147621f, 0.716567f},
+{0.850651f, 0.000000f, 0.525731f},
+{0.864188f, 0.442863f, -0.238856f},
+{0.809017f, 0.309017f, -0.500000f},
+{0.951056f, 0.162460f, -0.262866f},
+{0.525731f, 0.000000f, -0.850651f},
+{0.681718f, 0.147621f, -0.716567f},
+{0.681718f, -0.147621f, -0.716567f},
+{0.850651f, 0.000000f, -0.525731f},
+{0.809017f, -0.309017f, -0.500000f},
+{0.864188f, -0.442863f, -0.238856f},
+{0.951056f, -0.162460f, -0.262866f},
+{0.147621f, 0.716567f, -0.681718f},
+{0.309017f, 0.500000f, -0.809017f},
+{0.425325f, 0.688191f, -0.587785f},
+{0.442863f, 0.238856f, -0.864188f},
+{0.587785f, 0.425325f, -0.688191f},
+{0.688191f, 0.587785f, -0.425325f},
+{-0.147621f, 0.716567f, -0.681718f},
+{-0.309017f, 0.500000f, -0.809017f},
+{0.000000f, 0.525731f, -0.850651f},
+{-0.525731f, 0.000000f, -0.850651f},
+{-0.442863f, 0.238856f, -0.864188f},
+{-0.295242f, 0.000000f, -0.955423f},
+{-0.162460f, 0.262866f, -0.951056f},
+{0.000000f, 0.000000f, -1.000000f},
+{0.295242f, 0.000000f, -0.955423f},
+{0.162460f, 0.262866f, -0.951056f},
+{-0.442863f, -0.238856f, -0.864188f},
+{-0.309017f, -0.500000f, -0.809017f},
+{-0.162460f, -0.262866f, -0.951056f},
+{0.000000f, -0.850651f, -0.525731f},
+{-0.147621f, -0.716567f, -0.681718f},
+{0.147621f, -0.716567f, -0.681718f},
+{0.000000f, -0.525731f, -0.850651f},
+{0.309017f, -0.500000f, -0.809017f},
+{0.442863f, -0.238856f, -0.864188f},
+{0.162460f, -0.262866f, -0.951056f},
+{0.238856f, -0.864188f, -0.442863f},
+{0.500000f, -0.809017f, -0.309017f},
+{0.425325f, -0.688191f, -0.587785f},
+{0.716567f, -0.681718f, -0.147621f},
+{0.688191f, -0.587785f, -0.425325f},
+{0.587785f, -0.425325f, -0.688191f},
+{0.000000f, -0.955423f, -0.295242f},
+{0.000000f, -1.000000f, 0.000000f},
+{0.262866f, -0.951056f, -0.162460f},
+{0.000000f, -0.850651f, 0.525731f},
+{0.000000f, -0.955423f, 0.295242f},
+{0.238856f, -0.864188f, 0.442863f},
+{0.262866f, -0.951056f, 0.162460f},
+{0.500000f, -0.809017f, 0.309017f},
+{0.716567f, -0.681718f, 0.147621f},
+{0.525731f, -0.850651f, 0.000000f},
+{-0.238856f, -0.864188f, -0.442863f},
+{-0.500000f, -0.809017f, -0.309017f},
+{-0.262866f, -0.951056f, -0.162460f},
+{-0.850651f, -0.525731f, 0.000000f},
+{-0.716567f, -0.681718f, -0.147621f},
+{-0.716567f, -0.681718f, 0.147621f},
+{-0.525731f, -0.850651f, 0.000000f},
+{-0.500000f, -0.809017f, 0.309017f},
+{-0.238856f, -0.864188f, 0.442863f},
+{-0.262866f, -0.951056f, 0.162460f},
+{-0.864188f, -0.442863f, 0.238856f},
+{-0.809017f, -0.309017f, 0.500000f},
+{-0.688191f, -0.587785f, 0.425325f},
+{-0.681718f, -0.147621f, 0.716567f},
+{-0.442863f, -0.238856f, 0.864188f},
+{-0.587785f, -0.425325f, 0.688191f},
+{-0.309017f, -0.500000f, 0.809017f},
+{-0.147621f, -0.716567f, 0.681718f},
+{-0.425325f, -0.688191f, 0.587785f},
+{-0.162460f, -0.262866f, 0.951056f},
+{0.442863f, -0.238856f, 0.864188f},
+{0.162460f, -0.262866f, 0.951056f},
+{0.309017f, -0.500000f, 0.809017f},
+{0.147621f, -0.716567f, 0.681718f},
+{0.000000f, -0.525731f, 0.850651f},
+{0.425325f, -0.688191f, 0.587785f},
+{0.587785f, -0.425325f, 0.688191f},
+{0.688191f, -0.587785f, 0.425325f},
+{-0.955423f, 0.295242f, 0.000000f},
+{-0.951056f, 0.162460f, 0.262866f},
+{-1.000000f, 0.000000f, 0.000000f},
+{-0.850651f, 0.000000f, 0.525731f},
+{-0.955423f, -0.295242f, 0.000000f},
+{-0.951056f, -0.162460f, 0.262866f},
+{-0.864188f, 0.442863f, -0.238856f},
+{-0.951056f, 0.162460f, -0.262866f},
+{-0.809017f, 0.309017f, -0.500000f},
+{-0.864188f, -0.442863f, -0.238856f},
+{-0.951056f, -0.162460f, -0.262866f},
+{-0.809017f, -0.309017f, -0.500000f},
+{-0.681718f, 0.147621f, -0.716567f},
+{-0.681718f, -0.147621f, -0.716567f},
+{-0.850651f, 0.000000f, -0.525731f},
+{-0.688191f, 0.587785f, -0.425325f},
+{-0.587785f, 0.425325f, -0.688191f},
+{-0.425325f, 0.688191f, -0.587785f},
+{-0.425325f, -0.688191f, -0.587785f},
+{-0.587785f, -0.425325f, -0.688191f},
+{-0.688191f, -0.587785f, -0.425325f},
diff --git a/tools/heretic2/h2data/book.c b/tools/heretic2/h2data/book.c
new file mode 100644 (file)
index 0000000..0d3ba4f
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "qdata.h"
+
+char book_prefix[1024];
+byte buffer[640 * 480];
+unsigned long bufferl[640 * 480];
+
+miptex_t *CreateBook8( byte *buffer, int w, int h, byte *palette, int *FinalSize ){
+       miptex_t    *mp;
+       int i, j;
+       byte        *pos;
+       int size;
+
+       size = sizeof( *mp ) + ( w * h );
+       mp = (miptex_t *)SafeMalloc( size, "CreateBook8" );
+       memset( mp, 0, size );
+
+       mp->version = MIP_VERSION;
+
+       for ( i = j = 0; i < 256; i++,j += 3 )
+       {
+               mp->palette[i].r = palette[j];
+               mp->palette[i].g = palette[j + 1];
+               mp->palette[i].b = palette[j + 2];
+       }
+       pos = (byte *)( mp + 1 );
+
+       mp->width[0] = w;
+       mp->height[0] = h;
+       mp->offsets[0] = sizeof( *mp );
+       memcpy( pos, buffer, w * h );
+
+       *FinalSize = size;
+       return( mp );
+}
+
+miptex32_t *CreateBook32( long *buffer, int w, int h, int *FinalSize ){
+       miptex32_t  *mp;
+       byte        *pos;
+       int size;
+
+       size = sizeof( *mp ) + ( w * h * 4 );
+       mp = (miptex32_t *)SafeMalloc( size, "CreateBook32" );
+       memset( mp, 0, size );
+
+       mp->version = MIP32_VERSION;
+
+       pos = (byte *)( mp + 1 );
+
+       mp->width[0] = w;
+       mp->height[0] = h;
+       mp->offsets[0] = sizeof( *mp );
+       memcpy( pos, buffer, w * h * 4 );
+
+       *FinalSize = size;
+       return( mp );
+}
+
+
+// Routines to chop a random sized image into gl texture friendly chunks
+
+typedef struct rect_s
+{
+       int x, y;
+       int w, h;
+       char name[4];
+} rect_t;
+
+int GetCoords( int x, int store[MAX_MD2SKINS] ){
+       int index, start, delta;
+
+       index = 0;
+       start = 0;
+       delta = 256;
+
+       store[index++] = start;
+       while ( x )
+       {
+               if ( x >= delta ) {
+                       start += delta;
+                       store[index++] = start;
+                       x -= delta;
+               }
+               else
+               {
+                       delta >>= 1;
+               }
+       }
+       return( index );
+}
+
+int ChopImage( int w, int h, rect_t coords[MAX_MD2SKINS] ){
+       int xs[MAX_MD2SKINS], ys[MAX_MD2SKINS];
+       int xcount, ycount, x, y, index;
+
+       index = 0;
+       xcount = GetCoords( w, xs ) - 1;
+       ycount = GetCoords( h, ys ) - 1;
+
+       for ( y = 0; y < ycount; y++ )
+       {
+               for ( x = 0; x < xcount; x++, index++ )
+               {
+                       coords[index].x = xs[x];
+                       coords[index].y = ys[y];
+                       coords[index].w = xs[x + 1] - xs[x];
+                       coords[index].h = ys[y + 1] - ys[y];
+                       coords[index].name[0] = x + '0';
+                       coords[index].name[1] = y + '0';
+                       coords[index].name[2] = 0;
+               }
+       }
+       return( index );
+}
+
+/*
+   ===============
+   Cmd_Pic
+   ===============
+ */
+
+void Cmd_Book(){
+       int xl,yl,xh,yh,w,h;
+       byte            *dest, *source;
+       int flags, value, contents;
+       char lumpname[64];
+       char filename[1024];
+       unsigned long   *destl, *sourcel;
+       int linedelta, x, y;
+       int size;
+       miptex_t        *qtex;
+       miptex32_t      *qtex32;
+       float scale_x, scale_y;
+       int numrects, i;
+       rect_t coords[MAX_MD2SKINS];
+       bookframe_t bframes[MAX_MD2SKINS];
+       bookframe_t     *bf;
+       book_t book;
+
+       GetScriptToken( false );
+       strcpy( lumpname, token );
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       total_x += w;
+       total_y += h;
+       total_textures++;
+
+       if ( ( w & 7 ) || ( h & 7 ) ) {
+               Error( "line %i: miptex sizes must be multiples of 8", scriptline );
+       }
+
+       flags = 0;
+       contents = 0;
+       value = 0;
+
+       scale_x = scale_y = 0.5;
+
+       if ( g_release ) {
+               return;
+       }
+
+       if ( TrueColorImage ) {
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= longimagewidth || xh > longimagewidth ||
+                        yl >= longimageheight || yh > longimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
+               }
+
+               sourcel = (unsigned long *) longimage + ( yl * longimagewidth ) + xl;
+               destl = (unsigned long *) longimage;
+               linedelta = ( longimagewidth - w );
+
+               for ( y = yl; y < yh; y++ )
+               {
+                       for ( x = xl; x < xh; x++ )
+                       {
+                               *destl++ = *sourcel++;  // RGBA
+                       }
+                       sourcel += linedelta;
+               }
+
+               // Get rectangles to chop into
+               numrects = ChopImage( w, h, coords );
+
+               bf = bframes;
+               for ( i = 0; i < numrects; i++, bf++ )
+               {
+                       // Copy section of image to buffer
+                       sourcel = (unsigned long *) longimage + ( coords[i].y * w ) + coords[i].x;
+                       destl = bufferl;
+                       linedelta = w - coords[i].w;
+
+                       for ( y = 0; y < coords[i].h; y++ )
+                       {
+                               for ( x = 0; x < coords[i].w; x++ )
+                               {
+                                       *destl++ = *sourcel++;
+                               }
+                               sourcel += linedelta;
+                       }
+
+                       qtex32 = CreateBook32( bufferl, coords[i].w, coords[i].h, &size );
+
+                       qtex32->flags = flags;
+                       qtex32->contents = contents;
+                       qtex32->value = value;
+                       qtex32->scale_x = scale_x;
+                       qtex32->scale_y = scale_y;
+
+                       sprintf( filename, "%sbook/%s/%s_%s.m32", gamedir, book_prefix, lumpname, coords[i].name );
+                       sprintf( qtex32->name, "%s/%s_%s.m32", book_prefix, lumpname, coords[i].name );
+
+                       strcpy( bf->name, qtex32->name );
+                       bf->x = coords[i].x;
+                       bf->y = coords[i].y;
+                       bf->w = coords[i].w;
+                       bf->h = coords[i].h;
+                       //
+                       // write it out
+                       //
+                       printf( "writing %s\n", filename );
+                       SaveFile( filename, (byte *)qtex32, size );
+
+                       free( qtex32 );
+               }
+       }
+       else
+       {
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= byteimagewidth || xh > byteimagewidth ||
+                        yl >= byteimageheight || yh > byteimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
+               }
+
+               // Copy image to top left
+               source = byteimage + yl * byteimagewidth + xl;
+               dest = byteimage;
+               linedelta = byteimagewidth - w;
+
+               for ( y = yl; y < yh; y++ )
+               {
+                       for ( x = xl; x < xh; x++ )
+                       {
+                               *dest++ = *source++;
+                       }
+                       source += linedelta;
+               }
+
+               // Get rectangles to chop into
+               numrects = ChopImage( w, h, coords );
+
+               bf = bframes;
+               for ( i = 0; i < numrects; i++, bf++ )
+               {
+                       // Copy section of image to buffer
+                       source = byteimage + ( coords[i].y * w ) + coords[i].x;
+                       dest = buffer;
+                       linedelta = w - coords[i].w;
+
+                       for ( y = 0; y < coords[i].h; y++ )
+                       {
+                               for ( x = 0; x < coords[i].w; x++ )
+                               {
+                                       *dest++ = *source++;
+                               }
+                               source += linedelta;
+                       }
+
+                       qtex = CreateBook8( buffer, coords[i].w, coords[i].h, lbmpalette, &size );
+
+                       qtex->flags = flags;
+                       qtex->contents = contents;
+                       qtex->value = value;
+
+                       sprintf( filename, "%sbook/%s/%s_%s.m8", gamedir, book_prefix, lumpname, coords[i].name );
+                       sprintf( qtex->name, "%s/%s_%s.m8", book_prefix, lumpname, coords[i].name );
+
+                       strcpy( bf->name, qtex->name );
+                       bf->x = coords[i].x;
+                       bf->y = coords[i].y;
+                       bf->w = coords[i].w;
+                       bf->h = coords[i].h;
+                       //
+                       // write it out
+                       //
+                       printf( "writing %s\n", filename );
+                       SaveFile( filename, (byte *)qtex, size );
+
+                       free( qtex );
+               }
+       }
+       // Set up descriptor
+       size = sizeof( bookframe_t ) * numrects;
+
+       book.bheader.ident = IDBOOKHEADER;
+       book.bheader.version = BOOK_VERSION;
+       book.bheader.num_segments = numrects;
+       book.bheader.total_w = w;
+       book.bheader.total_h = h;
+       memcpy( book.bframes, bframes, size );
+
+       // Save out segment descriptor
+       sprintf( filename, "%sBook/%s/%s.bk", gamedir, book_prefix, lumpname );
+       printf( "writing %s\n", filename );
+       SaveFile( filename, (byte *)&book, size + sizeof( bookheader_t ) );
+}
+
+/*
+   ===============
+   Cmd_picdir
+   ===============
+ */
+void Cmd_Bookdir( void ){
+       char filename[1024];
+
+       GetScriptToken( false );
+       strcpy( book_prefix, token );
+       // create the directory if needed
+       sprintf( filename, "%sBook", gamedir );
+       Q_mkdir( filename );
+       sprintf( filename, "%sBook/%s", gamedir, book_prefix );
+       Q_mkdir( filename );
+}
+
+// end
diff --git a/tools/heretic2/h2data/fmodels.c b/tools/heretic2/h2data/fmodels.c
new file mode 100644 (file)
index 0000000..6e8a263
--- /dev/null
@@ -0,0 +1,3299 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qd_fmodel.h"
+#include "animcomp.h"
+#include "qd_skeletons.h"
+#include "skeletons.h"
+#include "qdata.h"
+#include "flex.h"
+#include "reference.h"
+
+#include <assert.h>
+
+/*
+   ========================================================================
+
+   .FM triangle flexible model file format
+
+   ========================================================================
+ */
+
+//=================================================================
+
+#define NUMVERTEXNORMALS    162
+
+extern float avertexnormals[NUMVERTEXNORMALS][3];
+
+#define MAX_GROUPS  128
+
+typedef struct
+{
+       triangle_t triangle;
+       int group;
+} trigroup_t;
+
+#define TRIVERT_DIST    .1
+
+typedef struct
+{
+       int start_frame;
+       int num_frames;
+       int degrees;
+       char *mat;
+       char *ccomp;
+       char *cbase;
+       float *cscale;
+       float *coffset;
+       float trans[3];
+       float scale[3];
+       float bmin[3];
+       float bmax[3];
+} fmgroup_t;
+
+//================================================================
+
+// Initial
+fmheader_t fmheader;
+
+// Skin
+extern char g_skins[MAX_FM_SKINS][64];
+
+// ST Coord
+extern fmstvert_t base_st[MAX_FM_VERTS];
+
+// Triangles
+extern fmtriangle_t triangles[MAX_FM_TRIANGLES];
+
+// Frames
+extern fmframe_t g_frames[MAX_FM_FRAMES];
+//fmframe_t    *g_FMframes;
+
+// GL Commands
+extern int commands[16384];
+extern int numcommands;
+
+
+//
+// varibles set by commands
+//
+extern float scale_up;                              // set by $scale
+extern vec3_t adjust;                               // set by $origin
+extern int g_fixedwidth, g_fixedheight;             // set by $skinsize
+extern char modelname[64];                          // set by $modelname
+
+
+extern char        *g_outputDir;
+
+
+// Mesh Nodes
+mesh_node_t *pmnodes = NULL;
+fmmeshnode_t mesh_nodes[MAX_FM_MESH_NODES];
+
+fmgroup_t groups[MAX_GROUPS];
+int num_groups;
+int frame_to_group[MAX_FM_FRAMES];
+
+//
+// variables set by command line arguments
+//
+qboolean g_no_opimizations = false;
+
+
+//
+// base frame info
+//
+static int triangle_st[MAX_FM_TRIANGLES][3][2];
+
+
+// number of gl vertices
+extern int numglverts;
+// indicates if a triangle has already been used in a glcmd
+extern int used[MAX_FM_TRIANGLES];
+// indicates if a triangle has translucency in it or not
+static qboolean translucent[MAX_FM_TRIANGLES];
+
+// main output file handle
+extern FILE         *headerouthandle;
+// output sizes of buildst()
+static int skin_width, skin_height;
+
+
+// statistics
+static int total_skin_pixels;
+static int skin_pixels_used;
+
+int ShareVertex( trigroup_t trione, trigroup_t tritwo );
+float DistBetween( vec3_t point1, vec3_t point2 );
+int GetNumTris( trigroup_t *tris, int group );
+void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles );
+void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts );
+void NewDrawLine( int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height );
+
+//==============================================================
+
+/*
+   ===============
+   ClearModel
+   ===============
+ */
+static void ClearModel( void ){
+       memset( &fmheader, 0, sizeof( fmheader ) );
+
+       modelname[0] = 0;
+       scale_up = 1.0;
+       VectorCopy( vec3_origin, adjust );
+       g_fixedwidth = g_fixedheight = 0;
+       g_skipmodel = false;
+       num_groups = 0;
+
+       if ( pmnodes ) {
+               free( pmnodes );
+               pmnodes = NULL;
+       }
+
+       ClearSkeletalModel();
+}
+
+
+extern void H_printf( char *fmt, ... );
+
+
+void WriteHeader( FILE *FH, char *Ident, int Version, int Size, void *Data ){
+       header_t header;
+       static long pos = -1;
+       long CurrentPos;
+
+       if ( Size == 0 ) { // Don't write out empty packets
+               return;
+       }
+
+       if ( pos != -1 ) {
+               CurrentPos = ftell( FH );
+               Size = CurrentPos - pos + sizeof( header_t );
+               fseek( FH, pos, SEEK_SET );
+               pos = -2;
+       }
+       else if ( Size == -1 ) {
+               pos = ftell( FH );
+       }
+
+       memset( &header,0,sizeof( header ) );
+       strcpy( header.ident,Ident );
+       header.version = Version;
+       header.size = Size;
+
+       SafeWrite( FH, &header, sizeof( header ) );
+
+       if ( Data ) {
+               SafeWrite( FH, Data, Size );
+       }
+
+       if ( pos == -2 ) {
+               pos = -1;
+               fseek( FH, 0, SEEK_END );
+       }
+}
+
+/*
+   ============
+   WriteModelFile
+   ============
+ */
+static void WriteModelFile( FILE *modelouthandle ){
+       int i;
+       int j, k;
+       fmframe_t       *in;
+       fmaliasframe_t  *out;
+       byte buffer[MAX_FM_VERTS * 4 + 128];
+       float v;
+       int c_on, c_off;
+       IntListNode_t   *current, *toFree;
+       qboolean framesWritten = false;
+       size_t temp,size = 0;
+
+       // probably should do this dynamically one of these days
+       struct
+       {
+               float scale[3];         // multiply byte verts by this
+               float translate[3];         // then add this
+       } outFrames[MAX_FM_FRAMES];
+
+#define DATA_SIZE 0x60000       // 384K had better be enough, particularly for the reference points
+       byte data[DATA_SIZE];
+       byte data2[DATA_SIZE];
+
+       fmheader.num_glcmds = numcommands;
+       fmheader.framesize = (int)&( (fmaliasframe_t *)0 )->verts[fmheader.num_xyz];
+
+       WriteHeader( modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof( fmheader ), &fmheader );
+
+       //
+       // write out the skin names
+       //
+
+       WriteHeader( modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins );
+
+       //
+       // write out the texture coordinates
+       //
+       c_on = c_off = 0;
+       for ( i = 0 ; i < fmheader.num_st ; i++ )
+       {
+               base_st[i].s = LittleShort( base_st[i].s );
+               base_st[i].t = LittleShort( base_st[i].t );
+       }
+
+       WriteHeader( modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof( base_st[0] ), base_st );
+
+       //
+       // write out the triangles
+       //
+       WriteHeader( modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof( fmtriangle_t ), NULL );
+
+       for ( i = 0 ; i < fmheader.num_tris ; i++ )
+       {
+               int j;
+               fmtriangle_t tri;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
+                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
+               }
+
+               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
+       }
+
+       if ( !num_groups ) {
+               //
+               // write out the frames
+               //
+               WriteHeader( modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL );
+               //      WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
+
+               for ( i = 0 ; i < fmheader.num_frames ; i++ )
+               {
+                       in = &g_frames[i];
+                       out = (fmaliasframe_t *)buffer;
+
+                       strcpy( out->name, in->name );
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
+                               out->translate[j] = in->mins[j];
+
+                               outFrames[i].scale[j] = out->scale[j];
+                               outFrames[i].translate[j] = out->translate[j];
+                       }
+
+                       for ( j = 0 ; j < fmheader.num_xyz ; j++ )
+                       {
+                               // all of these are byte values, so no need to deal with endianness
+                               out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+                               for ( k = 0 ; k < 3 ; k++ )
+                               {
+                                       // scale to byte values & min/max check
+                                       v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
+
+                                       // clamp, so rounding doesn't wrap from 255.6 to 0
+                                       if ( v > 255.0 ) {
+                                               v = 255.0;
+                                       }
+                                       if ( v < 0 ) {
+                                               v = 0;
+                                       }
+                                       out->verts[j].v[k] = v;
+                               }
+                       }
+
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               out->scale[j] = LittleFloat( out->scale[j] );
+                               out->translate[j] = LittleFloat( out->translate[j] );
+                       }
+
+                       SafeWrite( modelouthandle, out, fmheader.framesize );
+               }
+
+               // Go back and finish the header
+               //      WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
+       }
+       else
+       {
+               WriteHeader( modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN * fmheader.num_frames, NULL );
+               for ( i = 0 ; i < fmheader.num_frames ; i++ )
+               {
+                       in = &g_frames[i];
+                       SafeWrite( modelouthandle,in->name,FRAME_NAME_LEN );
+               }
+               WriteHeader( modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL );
+               in = &g_frames[0];
+               for ( j = 0 ; j < fmheader.num_xyz ; j++ )
+                       SafeWrite( modelouthandle,&in->v[j].lightnormalindex,1 );
+       }
+
+       //
+       // write out glcmds
+       //
+       WriteHeader( modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands * 4, commands );
+
+       //
+       // write out mesh nodes
+       //
+       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+       {
+               memcpy( mesh_nodes[i].tris, pmnodes[i].tris, sizeof( mesh_nodes[i].tris ) );
+               memcpy( mesh_nodes[i].verts, pmnodes[i].verts, sizeof( mesh_nodes[i].verts ) );
+               mesh_nodes[i].start_glcmds = LittleShort( (short)pmnodes[i].start_glcmds );
+               mesh_nodes[i].num_glcmds = LittleShort( (short)pmnodes[i].num_glcmds );
+       }
+
+       WriteHeader( modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof( fmmeshnode_t ) * fmheader.num_mesh_nodes, mesh_nodes );
+
+       if ( num_groups ) {
+
+/*
+   typedef struct
+   {
+    int                        start_frame;
+    int                        num_frames;
+    int                        degrees;
+    char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char)
+    char *ccomp; g->num_frames*g->degrees*sizeof(char)
+    char *cbase; fmheader.num_xyz*3*sizeof(unsigned char)
+    float *cscale; g->degrees*sizeof(float)
+    float *coffset; g->degrees*sizeof(float)
+    float trans[3]; 3*sizeof(float)
+    float scale[3]; 3*sizeof(float)
+   } fmgroup_t;
+ */
+               int tmp,k;
+               fmgroup_t *g;
+               size = sizeof( int ) + fmheader.num_frames * sizeof( int );
+               for ( k = 0; k < num_groups; k++ )
+               {
+                       g = &groups[k];
+                       size += sizeof( int ) * 3;
+                       size += fmheader.num_xyz * 3 * g->degrees * sizeof( char );
+                       size += g->num_frames * g->degrees * sizeof( char );
+                       size += fmheader.num_xyz * 3 * sizeof( unsigned char );
+                       size += g->degrees * sizeof( float );
+                       size += g->degrees * sizeof( float );
+                       size += 12 * sizeof( float );
+               }
+               WriteHeader( modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL );
+               SafeWrite( modelouthandle,&num_groups,sizeof( int ) );
+               SafeWrite( modelouthandle,frame_to_group,sizeof( int ) * fmheader.num_frames );
+
+               for ( k = 0; k < num_groups; k++ )
+               {
+                       g = &groups[k];
+                       tmp = LittleLong( g->start_frame );
+                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
+                       tmp = LittleLong( g->num_frames );
+                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
+                       tmp = LittleLong( g->degrees );
+                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
+
+                       SafeWrite( modelouthandle,g->mat,fmheader.num_xyz * 3 * g->degrees * sizeof( char ) );
+                       SafeWrite( modelouthandle,g->ccomp,g->num_frames * g->degrees * sizeof( char ) );
+                       SafeWrite( modelouthandle,g->cbase,fmheader.num_xyz * 3 * sizeof( unsigned char ) );
+                       SafeWrite( modelouthandle,g->cscale,g->degrees * sizeof( float ) );
+                       SafeWrite( modelouthandle,g->coffset,g->degrees * sizeof( float ) );
+                       SafeWrite( modelouthandle,g->trans,3 * sizeof( float ) );
+                       SafeWrite( modelouthandle,g->scale,3 * sizeof( float ) );
+                       SafeWrite( modelouthandle,g->bmin,3 * sizeof( float ) );
+                       SafeWrite( modelouthandle,g->bmax,3 * sizeof( float ) );
+                       free( g->mat );
+                       free( g->ccomp );
+                       free( g->cbase );
+                       free( g->cscale );
+                       free( g->coffset );
+               }
+       }
+
+       // write the skeletal info
+       if ( g_skelModel.type != SKEL_NULL ) {
+               size = 0;
+
+               temp = sizeof( int );     // change this to a byte
+               memcpy( data + size, &g_skelModel.type, temp );
+               size += temp;
+
+               // number of joints
+               temp = sizeof( int );     // change this to a byte
+               memcpy( data + size, &numJointsInSkeleton[g_skelModel.type], temp );
+               size += temp;
+
+               // number of verts in each joint cluster
+               temp = sizeof( int ) * numJointsInSkeleton[g_skelModel.type]; // change this to shorts
+               memcpy( data + size, &g_skelModel.new_num_verts[1], temp );
+               size += temp;
+
+               // cluster verts
+               for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
+               {
+                       current = g_skelModel.vertLists[i];
+                       while ( current )
+                       {
+                               temp = sizeof( int ); // change this to a short
+                               memcpy( data + size, &current->data, temp );
+                               size += temp;
+                               toFree = current;
+                               current = current->next;
+                               free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+                       }
+               }
+
+               if ( !num_groups ) { // joints are stored with regular verts for compressed models
+                       framesWritten = true;
+
+                       temp = sizeof( int ); // change this to a byte
+                       memcpy( data + size, &framesWritten, temp );
+                       size += temp;
+
+                       for ( i = 0; i < fmheader.num_frames; ++i )
+                       {
+                               in = &g_frames[i];
+
+                               for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j )
+                               {
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               // scale to byte values & min/max check
+                                               v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data + size, &v, temp );
+                                               size += temp;
+                                       }
+
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data + size, &v, temp );
+                                               size += temp;
+                                       }
+
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data + size, &v, temp );
+                                               size += temp;
+                                       }
+                               }
+                       }
+
+               }
+               else
+               {
+                       temp = sizeof( int ); // change this to a byte
+                       memcpy( data + size, &framesWritten, temp );
+                       size += temp;
+               }
+
+               WriteHeader( modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data );
+       }
+
+       if ( g_skelModel.references != REF_NULL ) {
+               int refnum;
+
+               size = 0;
+               if ( RefPointNum <= 0 ) { // Hard-coded labels
+                       refnum = numReferences[g_skelModel.references];
+               }
+               else
+               {   // Labels indicated in QDT
+                       refnum = RefPointNum;
+               }
+
+               temp = sizeof( int ); // change this to a byte
+               memcpy( data2 + size, &g_skelModel.references, temp );
+               size += temp;
+
+               if ( !num_groups ) {
+                       framesWritten = true;
+
+                       temp = sizeof( int ); // change this to a byte
+                       memcpy( data2 + size, &framesWritten, temp );
+                       size += temp;
+
+                       for ( i = 0; i < fmheader.num_frames; ++i )
+                       {
+                               in = &g_frames[i];
+
+                               for ( j = 0 ; j < refnum; ++j )
+                               {
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               // scale to byte values & min/max check
+                                               v = Q_rint( ( in->references[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data2 + size, &v, temp );
+                                               size += temp;
+                                       }
+
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               v = Q_rint( ( in->references[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data2 + size, &v, temp );
+                                               size += temp;
+                                       }
+
+                                       for ( k = 0 ; k < 3 ; k++ )
+                                       {
+                                               v = Q_rint( ( in->references[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                                               // write out origin as a float since they arn't clamped
+                                               temp = sizeof( float );   // change this to a short
+                                               assert( size + temp < DATA_SIZE );
+                                               memcpy( data2 + size, &v, temp );
+                                               size += temp;
+                                       }
+                               }
+                       }
+               }
+               else    // FINISH ME: references need to be stored with regular verts for compressed models
+               {
+                       framesWritten = false;
+
+                       temp = sizeof( int ); // change this to a byte
+                       memcpy( data2 + size, &framesWritten, temp );
+                       size += temp;
+               }
+
+               WriteHeader( modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2 );
+       }
+}
+
+static void CompressFrames(){
+       fmgroup_t *g;
+       int i,j,k;
+       fmframe_t   *in;
+
+       j = 0;
+       for ( i = 0; i < fmheader.num_frames; i++ )
+       {
+               while ( i >= groups[j].start_frame + groups[j].num_frames && j < num_groups - 1 )
+                       j++;
+               frame_to_group[i] = j;
+       }
+
+       for ( k = 0; k < num_groups; k++ )
+       {
+               g = &groups[k];
+
+               printf( "\nCompressing Frames for group %i...\n", k );
+               AnimCompressInit( g->num_frames,fmheader.num_xyz,g->degrees );
+               for ( i = 0; i < g->num_frames; i++ )
+               {
+                       in = &g_frames[i + g->start_frame];
+                       for ( j = 0; j < fmheader.num_xyz; j++ )
+                               AnimSetFrame( i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2] );
+               }
+               AnimCompressDoit();
+               g->mat = (char *) SafeMalloc( fmheader.num_xyz * 3 * g->degrees * sizeof( char ), "CompressFrames" );
+               g->ccomp = (char *) SafeMalloc( g->num_frames * g->degrees * sizeof( char ), "CompressFrames" );
+               g->cbase = (char *) SafeMalloc( fmheader.num_xyz * 3 * sizeof( unsigned char ), "CompressFrames" );
+               g->cscale = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" );
+               g->coffset = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" );
+               AnimCompressToBytes( g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax );
+               AnimCompressEnd();
+       }
+}
+
+static void OptimizeVertices( void ){
+       qboolean vert_used[MAX_FM_VERTS];
+       short vert_replacement[MAX_FM_VERTS];
+       int i,j,k,l,pos,bit,set_pos,set_bit;
+       fmframe_t   *in;
+       qboolean Found;
+       int num_unique;
+       static IntListNode_t *newVertLists[NUM_CLUSTERS];
+       static int newNum_verts[NUM_CLUSTERS];
+       IntListNode_t *current, *next;
+
+       printf( "Optimizing vertices..." );
+
+       memset( vert_used, 0, sizeof( vert_used ) );
+
+       if ( g_skelModel.clustered == true ) {
+               memset( newNum_verts, 0, sizeof( newNum_verts ) );
+               memset( newVertLists, 0, sizeof( newVertLists ) );
+       }
+
+       num_unique = 0;
+
+       // search for common points among all the frames
+       for ( i = 0 ; i < fmheader.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+
+               for ( j = 0; j < fmheader.num_xyz; j++ )
+               {
+                       for ( k = 0,Found = false; k < j; k++ )
+                       {   // starting from the beginning always ensures vert_replacement points to the first point in the array
+                               if ( in->v[j].v[0] == in->v[k].v[0] &&
+                                        in->v[j].v[1] == in->v[k].v[1] &&
+                                        in->v[j].v[2] == in->v[k].v[2] ) {
+                                       Found = true;
+                                       vert_replacement[j] = k;
+                                       break;
+                               }
+
+                       }
+
+                       if ( !Found ) {
+                               if ( !vert_used[j] ) {
+                                       num_unique++;
+                               }
+                               vert_used[j] = true;
+                       }
+               }
+       }
+
+       // recompute the light normals
+       for ( i = 0 ; i < fmheader.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+
+               for ( j = 0; j < fmheader.num_xyz; j++ )
+               {
+                       if ( !vert_used[j] ) {
+                               k = vert_replacement[j];
+
+                               VectorAdd( in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum );
+                               in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++;
+                       }
+               }
+
+               for ( j = 0 ; j < fmheader.num_xyz ; j++ )
+               {
+                       vec3_t v;
+                       float maxdot;
+                       int maxdotindex;
+                       int c;
+
+                       c = in->v[j].vnorm.numnormals;
+                       if ( !c ) {
+                               Error( "Vertex with no triangles attached" );
+                       }
+
+                       VectorScale( in->v[j].vnorm.normalsum, 1.0 / c, v );
+                       VectorNormalize( v, v );
+
+                       maxdot = -999999.0;
+                       maxdotindex = -1;
+
+                       for ( k = 0 ; k < NUMVERTEXNORMALS ; k++ )
+                       {
+                               float dot;
+
+                               dot = DotProduct( v, avertexnormals[k] );
+                               if ( dot > maxdot ) {
+                                       maxdot = dot;
+                                       maxdotindex = k;
+                               }
+                       }
+
+                       in->v[j].lightnormalindex = maxdotindex;
+               }
+       }
+
+       // create substitution list
+       num_unique = 0;
+       for ( i = 0; i < fmheader.num_xyz; i++ )
+       {
+               if ( vert_used[i] ) {
+                       vert_replacement[i] = num_unique;
+                       num_unique++;
+               }
+               else
+               {
+                       vert_replacement[i] = vert_replacement[vert_replacement[i]];
+               }
+
+               // vert_replacement[i] is the new index, i is the old index
+               // need to add the new index to the cluster list if old index was in it
+               if ( g_skelModel.clustered == true ) {
+                       for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k )
+                       {
+                               for ( l = 0, current = g_skelModel.vertLists[k];
+                                         l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next )
+                               {
+                                       if ( current->data == i ) {
+                                               IntListNode_t *current2;
+                                               int m;
+                                               qboolean added = false;
+
+                                               for ( m = 0, current2 = newVertLists[k]; m < newNum_verts[k + 1];
+                                                         ++m, current2 = current2->next )
+                                               {
+                                                       if ( current2->data == vert_replacement[i] ) {
+                                                               added = true;
+                                                               break;
+                                                       }
+                                               }
+
+                                               if ( !added ) {
+                                                       ++newNum_verts[k + 1];
+
+                                                       next = newVertLists[k];
+
+                                                       newVertLists[k] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "OptimizeVertices" );
+                                                       // freed after model write out
+
+                                                       newVertLists[k]->data = vert_replacement[i];
+                                                       newVertLists[k]->next = next;
+                                               }
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // substitute
+       for ( i = 0 ; i < fmheader.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+
+               for ( j = 0; j < fmheader.num_xyz; j++ )
+               {
+                       in->v[vert_replacement[j]] = in->v[j];
+               }
+
+       }
+
+       for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
+       {
+               IntListNode_t *toFree;
+               current = g_skelModel.vertLists[i];
+
+               while ( current )
+               {
+                       toFree = current;
+                       current = current->next;
+                       free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+               }
+
+               g_skelModel.vertLists[i] = newVertLists[i];
+               g_skelModel.new_num_verts[i + 1] = newNum_verts[i + 1];
+       }
+
+#ifndef NDEBUG
+       for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k )
+       {
+               for ( l = 0, current = g_skelModel.vertLists[k];
+                         l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next )
+               {
+                       IntListNode_t *current2;
+                       int m;
+
+                       for ( m = l + 1, current2 = current->next; m < newNum_verts[k + 1];
+                                 ++m, current2 = current2->next )
+                       {
+                               if ( current->data == current2->data ) {
+                                       printf( "Warning duplicate vertex:  %d\n", current->data );
+                                       break;
+                               }
+                       }
+               }
+       }
+#endif
+
+       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+       {   // reset the vert bits
+               memset( pmnodes[i].verts,0,sizeof( pmnodes[i].verts ) );
+       }
+
+       // repleace the master triangle list vertex indexes and update the vert bits for each mesh node
+       for ( i = 0 ; i < fmheader.num_tris ; i++ )
+       {
+               pos = i >> 3;
+               bit = 1 << ( i & 7 );
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]];
+
+                       set_pos >>= 3;
+                       set_bit = 1 << ( set_bit & 7 );
+
+                       for ( k = 0; k < fmheader.num_mesh_nodes; k++ )
+                       {
+                               if ( !( pmnodes[k].tris[pos] & bit ) ) {
+                                       continue;
+                               }
+                               pmnodes[k].verts[set_pos] |= set_bit;
+                       }
+               }
+       }
+
+       for ( i = 0; i < numcommands; i++ )
+       {
+               j = commands[i];
+               if ( !j ) {
+                       continue;
+               }
+
+               j = abs( j );
+               for ( i++; j; j--,i += 3 )
+               {
+                       commands[i + 2] = vert_replacement[commands[i + 2]];
+               }
+               i--;
+       }
+
+       printf( "Reduced by %d\n",fmheader.num_xyz - num_unique );
+
+       fmheader.num_xyz = num_unique;
+       if ( num_groups ) {
+               // tack on the reference verts to the regular verts
+               if ( g_skelModel.references != REF_NULL ) {
+                       fmframe_t   *in;
+                       int index;
+                       int refnum;
+
+                       if ( RefPointNum <= 0 ) { // Hard-coded labels
+                               refnum = numReferences[g_skelModel.references];
+                       }
+                       else
+                       {   // Labels indicated in QDT
+                               refnum = RefPointNum;
+                       }
+
+
+                       for ( i = 0; i < fmheader.num_frames; ++i )
+                       {
+                               in = &g_frames[i];
+                               index = fmheader.num_xyz;
+
+                               for ( j = 0 ; j < refnum; ++j )
+                               {
+                                       VectorCopy( in->references[j].placement.origin, in->v[index].v );
+                                       index++;
+
+                                       VectorCopy( in->references[j].placement.direction, in->v[index].v );
+                                       index++;
+
+                                       VectorCopy( in->references[j].placement.up, in->v[index].v );
+                                       index++;
+                               }
+                       }
+
+                       fmheader.num_xyz += refnum * 3;
+               }
+
+               // tack on the skeletal joint verts to the regular verts
+               if ( g_skelModel.type != SKEL_NULL ) {
+                       fmframe_t   *in;
+                       int index;
+
+                       for ( i = 0; i < fmheader.num_frames; ++i )
+                       {
+                               in = &g_frames[i];
+                               index = fmheader.num_xyz;
+
+                               for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j )
+                               {
+                                       VectorCopy( in->joints[j].placement.origin, in->v[index].v );
+                                       index++;
+
+                                       VectorCopy( in->joints[j].placement.direction, in->v[index].v );
+                                       index++;
+
+                                       VectorCopy( in->joints[j].placement.up, in->v[index].v );
+                                       index++;
+                               }
+                       }
+
+                       fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type] * 3;
+               }
+
+               CompressFrames();
+       }
+}
+
+
+/*
+   ===============
+   FinishModel
+   ===============
+ */
+void FMFinishModel( void ){
+       FILE        *modelouthandle;
+       int i,j,length,tris,verts,bit,pos,total_tris,total_verts;
+       char name[1024];
+       int trans_count;
+
+       if ( !fmheader.num_frames ) {
+               return;
+       }
+
+//
+// copy to release directory tree if doing a release build
+//
+       if ( g_release ) {
+               if ( modelname[0] ) {
+                       sprintf( name, "%s", modelname );
+               }
+               else{
+                       sprintf( name, "%s/tris.fm", cdpartial );
+               }
+               ReleaseFile( name );
+
+               for ( i = 0 ; i < fmheader.num_skins ; i++ )
+               {
+                       ReleaseFile( g_skins[i] );
+               }
+               fmheader.num_frames = 0;
+               return;
+       }
+
+       printf( "\n" );
+
+       trans_count = 0;
+       for ( i = 0; i < fmheader.num_tris; i++ )
+               if ( translucent[i] ) {
+                       trans_count++;
+               }
+
+       if ( !g_no_opimizations ) {
+               OptimizeVertices();
+       }
+
+//
+// write the model output file
+//
+       if ( modelname[0] ) {
+               sprintf( name, "%s%s", g_outputDir, modelname );
+       }
+       else{
+               sprintf( name, "%s/tris.fm", g_outputDir );
+       }
+       printf( "saving to %s\n", name );
+       CreatePath( name );
+       modelouthandle = SafeOpenWrite( name );
+
+       WriteModelFile( modelouthandle );
+
+       printf( "%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight );
+       printf( "First frame boundaries:\n" );
+       printf( "       minimum x: %3f\n", g_frames[0].mins[0] );
+       printf( "       maximum x: %3f\n", g_frames[0].maxs[0] );
+       printf( "       minimum y: %3f\n", g_frames[0].mins[1] );
+       printf( "       maximum y: %3f\n", g_frames[0].maxs[1] );
+       printf( "       minimum z: %3f\n", g_frames[0].mins[2] );
+       printf( "       maximum z: %3f\n", g_frames[0].maxs[2] );
+       printf( "%4d vertices\n", fmheader.num_xyz );
+       printf( "%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count );
+       printf( "%4d frame\n", fmheader.num_frames );
+       printf( "%4d glverts\n", numglverts );
+       printf( "%4d glcmd\n", fmheader.num_glcmds );
+       printf( "%4d skins\n", fmheader.num_skins );
+       printf( "%4d mesh nodes\n", fmheader.num_mesh_nodes );
+       printf( "wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used,
+                       total_skin_pixels, (double)( total_skin_pixels - skin_pixels_used ) / (double)total_skin_pixels * 100.0 );
+
+       printf( "file size: %d\n", (int)ftell( modelouthandle ) );
+       printf( "---------------------\n" );
+
+       if ( g_verbose ) {
+               if ( fmheader.num_mesh_nodes ) {
+                       total_tris = total_verts = 0;
+                       printf( "Node Name                         Tris Verts\n" );
+                       printf( "--------------------------------- ---- -----\n" );
+                       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+                       {
+                               tris = 0;
+                               verts = 0;
+                               for ( j = 0; j < MAXTRIANGLES; j++ )
+                               {
+                                       pos = ( j ) >> 3;
+                                       bit = 1 << ( ( j ) & 7 );
+                                       if ( pmnodes[i].tris[pos] & bit ) {
+                                               tris++;
+                                       }
+                               }
+                               for ( j = 0; j < MAX_FM_VERTS; j++ )
+                               {
+                                       pos = ( j ) >> 3;
+                                       bit = 1 << ( ( j ) & 7 );
+                                       if ( pmnodes[i].verts[pos] & bit ) {
+                                               verts++;
+                                       }
+                               }
+
+                               printf( "%-33s %4d %5d\n",pmnodes[i].name,tris,verts );
+
+                               total_tris += tris;
+                               total_verts += verts;
+                       }
+                       printf( "--------------------------------- ---- -----\n" );
+                       printf( "%-33s %4d %5d\n","TOTALS",total_tris,total_verts );
+               }
+       }
+       fclose( modelouthandle );
+
+       // finish writing header file
+       H_printf( "\n" );
+
+       // scale_up is usefull to allow step distances to be adjusted
+       H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up );
+
+       // mesh nodes
+       if ( fmheader.num_mesh_nodes ) {
+               H_printf( "\n" );
+               H_printf( "#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes );
+               for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+               {
+                       strcpy( name, pmnodes[i].name );
+                       strupr( name );
+                       length = strlen( name );
+                       for ( j = 0; j < length; j++ )
+                       {
+                               if ( name[j] == ' ' ) {
+                                       name[j] = '_';
+                               }
+                       }
+                       H_printf( "#define MESH_%s\t\t%d\n", name, i );
+               }
+       }
+
+       fclose( headerouthandle );
+       headerouthandle = NULL;
+       free( pmnodes );
+}
+
+
+/*
+   =================================================================
+
+   ALIAS MODEL DISPLAY LIST GENERATION
+
+   =================================================================
+ */
+
+extern int strip_xyz[128];
+extern int strip_st[128];
+extern int strip_tris[128];
+extern int stripcount;
+
+/*
+   ================
+   StripLength
+   ================
+ */
+static int  StripLength( int starttri, int startv, int num_tris, int node ){
+       int m1, m2;
+       int st1, st2;
+       int j;
+       fmtriangle_t    *last, *check;
+       int k;
+       int pos, bit;
+
+       used[starttri] = 2;
+
+       last = &triangles[starttri];
+
+       strip_xyz[0] = last->index_xyz[( startv ) % 3];
+       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
+       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
+       strip_st[0] = last->index_st[( startv ) % 3];
+       strip_st[1] = last->index_st[( startv + 1 ) % 3];
+       strip_st[2] = last->index_st[( startv + 2 ) % 3];
+
+       strip_tris[0] = starttri;
+       stripcount = 1;
+
+       m1 = last->index_xyz[( startv + 2 ) % 3];
+       st1 = last->index_st[( startv + 2 ) % 3];
+       m2 = last->index_xyz[( startv + 1 ) % 3];
+       st2 = last->index_st[( startv + 1 ) % 3];
+
+       // look for a matching triangle
+nexttri:
+       for ( j = starttri + 1, check = &triangles[starttri + 1]
+                 ; j < num_tris ; j++, check++ )
+       {
+               pos = j >> 3;
+               bit = 1 << ( j & 7 );
+               if ( !( pmnodes[node].tris[pos] & bit ) ) {
+                       continue;
+               }
+               for ( k = 0 ; k < 3 ; k++ )
+               {
+                       if ( check->index_xyz[k] != m1 ) {
+                               continue;
+                       }
+                       if ( check->index_st[k] != st1 ) {
+                               continue;
+                       }
+                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
+                               continue;
+                       }
+                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
+                               continue;
+                       }
+
+                       // this is the next part of the fan
+
+                       // if we can't use this triangle, this tristrip is done
+                       if ( used[j] || translucent[j] != translucent[starttri] ) {
+                               goto done;
+                       }
+
+                       // the new edge
+                       if ( stripcount & 1 ) {
+                               m2 = check->index_xyz[ ( k + 2 ) % 3 ];
+                               st2 = check->index_st[ ( k + 2 ) % 3 ];
+                       }
+                       else
+                       {
+                               m1 = check->index_xyz[ ( k + 2 ) % 3 ];
+                               st1 = check->index_st[ ( k + 2 ) % 3 ];
+                       }
+
+                       strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ];
+                       strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ];
+                       strip_tris[stripcount] = j;
+                       stripcount++;
+
+                       used[j] = 2;
+                       goto nexttri;
+               }
+       }
+done:
+
+       // clear the temp used flags
+       for ( j = starttri + 1 ; j < num_tris ; j++ )
+               if ( used[j] == 2 ) {
+                       used[j] = 0;
+               }
+
+       return stripcount;
+}
+
+
+/*
+   ===========
+   FanLength
+   ===========
+ */
+static int  FanLength( int starttri, int startv, int num_tris, int node ){
+       int m1, m2;
+       int st1, st2;
+       int j;
+       fmtriangle_t    *last, *check;
+       int k;
+       int pos, bit;
+
+       used[starttri] = 2;
+
+       last = &triangles[starttri];
+
+       strip_xyz[0] = last->index_xyz[( startv ) % 3];
+       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
+       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
+       strip_st[0] = last->index_st[( startv ) % 3];
+       strip_st[1] = last->index_st[( startv + 1 ) % 3];
+       strip_st[2] = last->index_st[( startv + 2 ) % 3];
+
+       strip_tris[0] = starttri;
+       stripcount = 1;
+
+       m1 = last->index_xyz[( startv + 0 ) % 3];
+       st1 = last->index_st[( startv + 0 ) % 3];
+       m2 = last->index_xyz[( startv + 2 ) % 3];
+       st2 = last->index_st[( startv + 2 ) % 3];
+
+
+       // look for a matching triangle
+nexttri:
+       for ( j = starttri + 1, check = &triangles[starttri + 1]
+                 ; j < num_tris ; j++, check++ )
+       {
+               pos = j >> 3;
+               bit = 1 << ( j & 7 );
+               if ( !( pmnodes[node].tris[pos] & bit ) ) {
+                       continue;
+               }
+               for ( k = 0 ; k < 3 ; k++ )
+               {
+                       if ( check->index_xyz[k] != m1 ) {
+                               continue;
+                       }
+                       if ( check->index_st[k] != st1 ) {
+                               continue;
+                       }
+                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
+                               continue;
+                       }
+                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
+                               continue;
+                       }
+
+                       // this is the next part of the fan
+
+                       // if we can't use this triangle, this tristrip is done
+                       if ( used[j] || translucent[j] != translucent[starttri] ) {
+                               goto done;
+                       }
+
+                       // the new edge
+                       m2 = check->index_xyz[ ( k + 2 ) % 3 ];
+                       st2 = check->index_st[ ( k + 2 ) % 3 ];
+
+                       strip_xyz[stripcount + 2] = m2;
+                       strip_st[stripcount + 2] = st2;
+                       strip_tris[stripcount] = j;
+                       stripcount++;
+
+                       used[j] = 2;
+                       goto nexttri;
+               }
+       }
+done:
+
+       // clear the temp used flags
+       for ( j = starttri + 1 ; j < num_tris ; j++ )
+               if ( used[j] == 2 ) {
+                       used[j] = 0;
+               }
+
+       return stripcount;
+}
+
+
+
+/*
+   ================
+   BuildGlCmds
+
+   Generate a list of trifans or strips
+   for the model, which holds for all frames
+   ================
+ */
+static void BuildGlCmds( void ){
+       int i, j, k, l;
+       int startv;
+       float s, t;
+       int len, bestlen, besttype;
+       int best_xyz[1024];
+       int best_st[1024];
+       int best_tris[1024];
+       int type;
+       int trans_check;
+       int bit,pos;
+
+       //
+       // build tristrips
+       //
+       numcommands = 0;
+       numglverts = 0;
+
+
+       for ( l = 0; l < fmheader.num_mesh_nodes; l++ )
+       {
+               memset( used, 0, sizeof( used ) );
+
+               pmnodes[l].start_glcmds = numcommands;
+
+               for ( trans_check = 0; trans_check < 2; trans_check++ )
+               {
+                       for ( i = 0 ; i < fmheader.num_tris ; i++ )
+                       {
+                               pos = i >> 3;
+                               bit = 1 << ( i & 7 );
+                               if ( !( pmnodes[l].tris[pos] & bit ) ) {
+                                       continue;
+                               }
+
+                               // pick an unused triangle and start the trifan
+                               if ( used[i] || trans_check != translucent[i] ) {
+                                       continue;
+                               }
+
+                               bestlen = 0;
+                               for ( type = 0 ; type < 2 ; type++ )
+                               //      type = 1;
+                               {
+                                       for ( startv = 0 ; startv < 3 ; startv++ )
+                                       {
+                                               if ( type == 1 ) {
+                                                       len = StripLength( i, startv, fmheader.num_tris, l );
+                                               }
+                                               else{
+                                                       len = FanLength( i, startv, fmheader.num_tris, l );
+                                               }
+                                               if ( len > bestlen ) {
+                                                       besttype = type;
+                                                       bestlen = len;
+                                                       for ( j = 0 ; j < bestlen + 2 ; j++ )
+                                                       {
+                                                               best_st[j] = strip_st[j];
+                                                               best_xyz[j] = strip_xyz[j];
+                                                       }
+                                                       for ( j = 0 ; j < bestlen ; j++ )
+                                                               best_tris[j] = strip_tris[j];
+                                               }
+                                       }
+                               }
+
+                               // mark the tris on the best strip/fan as used
+                               for ( j = 0 ; j < bestlen ; j++ )
+                                       used[best_tris[j]] = 1;
+
+                               if ( besttype == 1 ) {
+                                       commands[numcommands++] = ( bestlen + 2 );
+                               }
+                               else{
+                                       commands[numcommands++] = -( bestlen + 2 );
+                               }
+
+                               numglverts += bestlen + 2;
+
+                               for ( j = 0 ; j < bestlen + 2 ; j++ )
+                               {
+                                       // emit a vertex into the reorder buffer
+                                       k = best_st[j];
+
+                                       // emit s/t coords into the commands stream
+                                       s = base_st[k].s;
+                                       t = base_st[k].t;
+
+                                       s = ( s  ) / fmheader.skinwidth;
+                                       t = ( t  ) / fmheader.skinheight;
+
+                                       *(float *)&commands[numcommands++] = s;
+                                       *(float *)&commands[numcommands++] = t;
+                                       *(int *)&commands[numcommands++] = best_xyz[j];
+                               }
+                       }
+               }
+               commands[numcommands++] = 0;        // end of list marker
+               pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds;
+       }
+}
+
+
+/*
+   ===============================================================
+
+   BASE FRAME SETUP
+
+   ===============================================================
+ */
+
+
+#define LINE_NORMAL 1
+#define LINE_FAT 2
+#define LINE_DOTTED 3
+
+
+#define ASCII_SPACE 32
+
+int LineType = LINE_NORMAL;
+extern unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768];
+unsigned char LineColor = 255;
+int ScaleWidth, ScaleHeight;
+
+
+static char *CharDefs[] =
+{
+       "-------------------------",
+       "-------------------------", // !
+       "-------------------------", // "
+       "-------------------------", // #
+       "-------------------------", // $
+       "-------------------------", // %
+       "-------------------------", // &
+       "--*----*-----------------", // '
+       "-*---*----*----*-----*---", // (
+       "*-----*----*----*---*----", // )
+       "-----*--*--**---**--*--*-", // *
+       "-------------------------", // +
+       "----------------**--**---", // ,
+       "-------------------------", // -
+       "----------------**---**--", // .
+       "-------------------------", // /
+       " *** *  *** * ***  * *** ", // 0
+       "   *   **    *    *    * ",
+       "****     * *** *    *****",
+       "****     * ***     ***** ",
+       "  **  * * *  * *****   * ",
+       "**** *    ****     ***** ",
+       " *** *    **** *   * *** ",
+       "*****    *   *   *    *  ",
+       " *** *   * *** *   * *** ",
+       " *** *   * ****    * *** ", // 9
+       "-**---**--------**---**--", // :
+       "-------------------------", // ;
+       "-------------------------", // <
+       "-------------------------", // =
+       "-------------------------", // >
+       "-------------------------", // ?
+       "-------------------------", // @
+       "-***-*---*******---**---*", // A
+       "****-*---*****-*---*****-",
+       "-*****----*----*-----****",
+       "****-*---**---**---*****-",
+       "******----****-*----*****",
+       "******----****-*----*----",
+       "-*****----*--***---*-****",
+       "*---**---*******---**---*",
+       "-***---*----*----*---***-",
+       "----*----*----**---*-***-",
+       "-*--*-*-*--**---*-*--*--*",
+       "-*----*----*----*----****",
+       "*---***-***-*-**---**---*",
+       "*---***--**-*-**--***---*",
+       "-***-*---**---**---*-***-",
+       "****-*---*****-*----*----",
+       "-***-*---**---*-***----**",
+       "****-*---*****-*-*--*--**",
+       "-*****-----***-----*****-",
+       "*****--*----*----*----*--",
+       "*---**---**---**---******",
+       "*---**---**---*-*-*---*--",
+       "*---**---**-*-***-***---*",
+       "*---*-*-*---*---*-*-*---*",
+       "*---**---*-*-*---*----*--",
+       "*****---*---*---*---*****" // Z
+};
+
+void DrawLine( int x1, int y1, int x2, int y2 ){
+       int dx, dy;
+       int adx, ady;
+       int count;
+       float xfrac, yfrac, xstep, ystep;
+       unsigned sx, sy;
+       float u, v;
+
+       dx = x2 - x1;
+       dy = y2 - y1;
+       adx = abs( dx );
+       ady = abs( dy );
+
+       count = adx > ady ? adx : ady;
+       count++;
+
+       if ( count > 300 ) {
+               printf( "Bad count\n" );
+               return; // don't ever hang up on bad data
+       }
+
+       xfrac = x1;
+       yfrac = y1;
+
+       xstep = (float)dx / count;
+       ystep = (float)dy / count;
+
+       switch ( LineType )
+       {
+       case LINE_NORMAL:
+               do
+               {
+                       if ( xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT ) {
+                               pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor;
+                       }
+                       xfrac += xstep;
+                       yfrac += ystep;
+                       count--;
+               } while ( count > 0 );
+               break;
+       case LINE_FAT:
+               do
+               {
+                       for ( u = -0.1 ; u <= 0.9 ; u += 0.999 )
+                       {
+                               for ( v = -0.1 ; v <= 0.9 ; v += 0.999 )
+                               {
+                                       sx = xfrac + u;
+                                       sy = yfrac + v;
+                                       if ( sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT ) {
+                                               pic[sy * SKINPAGE_WIDTH + sx] = LineColor;
+                                       }
+                               }
+                       }
+                       xfrac += xstep;
+                       yfrac += ystep;
+                       count--;
+               } while ( count > 0 );
+               break;
+       case LINE_DOTTED:
+               do
+               {
+                       if ( count & 1 && xfrac < SKINPAGE_WIDTH &&
+                                yfrac < SKINPAGE_HEIGHT ) {
+                               pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor;
+                       }
+                       xfrac += xstep;
+                       yfrac += ystep;
+                       count--;
+               } while ( count > 0 );
+               break;
+       default:
+               Error( "Unknown <linetype> %d.\n", LineType );
+       }
+}
+
+//==========================================================================
+//
+// DrawCharacter
+//
+//==========================================================================
+
+static void DrawCharacter( int x, int y, int character ){
+       int r, c;
+       char *def;
+
+       character = toupper( character );
+       if ( character < ASCII_SPACE || character > 'Z' ) {
+               character = ASCII_SPACE;
+       }
+       character -= ASCII_SPACE;
+       for ( def = CharDefs[character], r = 0; r < 5; r++ )
+       {
+               for ( c = 0; c < 5; c++ )
+               {
+                       pic[( y + r ) * SKINPAGE_WIDTH + x + c] = *def++ == '*' ? 255 : 0;
+               }
+       }
+}
+
+//==========================================================================
+//
+// DrawTextChar
+//
+//==========================================================================
+
+void DrawTextChar( int x, int y, char *text ){
+       int c;
+
+       while ( ( c = *text++ ) != '\0' )
+       {
+               DrawCharacter( x, y, c );
+               x += 6;
+       }
+}
+
+
+extern void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight );
+
+//==========================================================================
+// ExtractDigit
+
+static int ExtractDigit( byte *pic, int x, int y ){
+       int i;
+       int r, c;
+       char digString[32];
+       char    *buffer;
+       byte backColor;
+       char    **DigitDefs;
+
+       backColor = pic[( SKINPAGE_HEIGHT - 1 ) * SKINPAGE_WIDTH];
+       DigitDefs = &CharDefs['0' - ASCII_SPACE];
+
+       buffer = digString;
+       for ( r = 0; r < 5; r++ )
+       {
+               for ( c = 0; c < 5; c++ )
+               {
+                       *buffer++ = ( pic[( y + r ) * SKINPAGE_WIDTH + x + c] == backColor ) ? ' ' : '*';
+               }
+       }
+       *buffer = '\0';
+       for ( i = 0; i < 10; i++ )
+       {
+               if ( strcmp( DigitDefs[i], digString ) == 0 ) {
+                       return i;
+               }
+       }
+
+       Error( "Unable to extract scaling info from skin PCX." );
+       return 0;
+}
+
+//==========================================================================
+// ExtractNumber
+
+int ExtractNumber( byte *pic, int x, int y ){
+       return ExtractDigit( pic, x, y ) * 100 + ExtractDigit( pic, x + 6, y ) * 10 + ExtractDigit( pic, x + 12, y );
+}
+
+
+
+
+
+/*
+   ============
+   BuildST
+
+   Builds the triangle_st array for the base frame and
+   fmheader.skinwidth / fmheader.skinheight
+
+   FIXME: allow this to be loaded from a file for
+   arbitrary mappings
+   ============
+ */
+static void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
+       int backface_flag;
+       int i, j;
+       int width, height, iwidth, iheight, swidth;
+       float basex, basey;
+       float scale;
+       vec3_t mins, maxs;
+       float       *pbasevert;
+       vec3_t vtemp1, vtemp2, normal;
+       float s_scale, t_scale;
+       float scWidth;
+       float scHeight;
+       int skinwidth;
+       int skinheight;
+
+       //
+       // find bounds of all the verts on the base frame
+       //
+       ClearBounds( mins, maxs );
+       backface_flag = false;
+
+       if ( ptri[0].HasUV ) { // if we have the uv already, we don't want to double up or scale
+               iwidth = ScaleWidth;
+               iheight = ScaleHeight;
+
+               t_scale = s_scale = 1.0;
+       }
+       else
+       {
+               for ( i = 0 ; i < numtri ; i++ )
+                       for ( j = 0 ; j < 3 ; j++ )
+                               AddPointToBounds( ptri[i].verts[j], mins, maxs );
+
+               for ( i = 0 ; i < 3 ; i++ )
+               {
+                       mins[i] = floor( mins[i] );
+                       maxs[i] = ceil( maxs[i] );
+               }
+
+               width = maxs[0] - mins[0];
+               height = maxs[2] - mins[2];
+
+               for ( i = 0 ; i < numtri ; i++ )
+               {
+                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+                       CrossProduct( vtemp1, vtemp2, normal );
+
+                       if ( normal[1] > 0 ) {
+                               backface_flag = true;
+                               break;
+                       }
+               }
+               scWidth = ScaleWidth * SCALE_ADJUST_FACTOR;
+               if ( backface_flag ) {  //we are doubling
+                       scWidth /= 2;
+               }
+
+               scHeight = ScaleHeight * SCALE_ADJUST_FACTOR;
+
+               scale = scWidth / width;
+
+               if ( height * scale >= scHeight ) {
+                       scale = scHeight / height;
+               }
+
+               iwidth = ceil( width * scale ) + 4;
+               iheight = ceil( height * scale ) + 4;
+
+               s_scale = (float)( iwidth - 4 ) / width;
+               t_scale = (float)( iheight - 4 ) / height;
+               t_scale = s_scale;
+       }
+       if ( DrawSkin ) {
+               if ( backface_flag ) {
+                       DrawScreen( s_scale, t_scale, iwidth * 2, iheight );
+               }
+               else{
+                       DrawScreen( s_scale, t_scale, iwidth, iheight );
+               }
+       }
+       if ( backface_flag ) {
+               skinwidth = iwidth * 2;
+       }
+       else{
+               skinwidth = iwidth;
+       }
+       skinheight = iheight;
+
+
+/*     if (!g_fixedwidth)
+    {  // old style
+        scale = 8;
+        if (width*scale >= 150)
+            scale = 150.0 / width;
+        if (height*scale >= 190)
+            scale = 190.0 / height;
+
+        s_scale = t_scale = scale;
+
+        iwidth = ceil(width*s_scale);
+        iheight = ceil(height*t_scale);
+
+        iwidth += 4;
+        iheight += 4;
+    }
+    else
+    {  // new style
+        iwidth = g_fixedwidth / 2;
+        iheight = g_fixedheight;
+
+        s_scale = (float)(iwidth-4) / width;
+        t_scale = (float)(iheight-4) / height;
+    }*/
+
+//
+// determine which side of each triangle to map the texture to
+//
+       basey = 2;
+       for ( i = 0 ; i < numtri ; i++ )
+       {
+               if ( ptri[i].HasUV ) {
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * skinwidth );
+                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * skinheight );
+                       }
+               }
+               else
+               {
+                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+                       CrossProduct( vtemp1, vtemp2, normal );
+
+                       if ( normal[1] > 0 ) {
+                               basex = iwidth + 2;
+                       }
+                       else
+                       {
+                               basex = 2;
+                       }
+
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               pbasevert = ptri[i].verts[j];
+
+                               triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
+                               triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
+                       }
+               }
+
+               if ( DrawSkin ) {
+                       DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
+                                         triangle_st[i][1][0], triangle_st[i][1][1] );
+                       DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
+                                         triangle_st[i][2][0], triangle_st[i][2][1] );
+                       DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
+                                         triangle_st[i][0][0], triangle_st[i][0][1] );
+               }
+       }
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+       swidth = iwidth;
+       if ( backface_flag ) {
+               swidth *= 2;
+       }
+       fmheader.skinwidth = ( swidth + 3 ) & ~3;
+       fmheader.skinheight = iheight;
+
+       skin_width = iwidth;
+       skin_height = iheight;
+}
+
+
+static void BuildNewST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
+       int i, j;
+
+       for ( i = 0 ; i < numtri ; i++ )
+       {
+               if ( ptri[i].HasUV ) {
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * ( ScaleWidth - 1 ) );
+                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * ( ScaleHeight - 1 ) );
+                       }
+               }
+
+               if ( DrawSkin ) {
+                       DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
+                                         triangle_st[i][1][0], triangle_st[i][1][1] );
+                       DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
+                                         triangle_st[i][2][0], triangle_st[i][2][1] );
+                       DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
+                                         triangle_st[i][0][0], triangle_st[i][0][1] );
+               }
+       }
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+       fmheader.skinwidth = ( ScaleWidth + 3 ) & ~3;
+       fmheader.skinheight = ScaleHeight;
+
+       skin_width = ScaleWidth;
+       skin_height = ScaleHeight;
+}
+
+
+
+
+byte            *BasePalette;
+byte            *BasePixels,*TransPixels;
+int BaseWidth, BaseHeight, TransWidth, TransHeight;
+qboolean BaseTrueColor;
+static qboolean SetPixel = false;
+
+int CheckTransRecursiveTri( int *lp1, int *lp2, int *lp3 ){
+       int     *temp;
+       int d;
+       int new[2];
+
+       d = lp2[0] - lp1[0];
+       if ( d < -1 || d > 1 ) {
+               goto split;
+       }
+       d = lp2[1] - lp1[1];
+       if ( d < -1 || d > 1 ) {
+               goto split;
+       }
+
+       d = lp3[0] - lp2[0];
+       if ( d < -1 || d > 1 ) {
+               goto split2;
+       }
+       d = lp3[1] - lp2[1];
+       if ( d < -1 || d > 1 ) {
+               goto split2;
+       }
+
+       d = lp1[0] - lp3[0];
+       if ( d < -1 || d > 1 ) {
+               goto split3;
+       }
+       d = lp1[1] - lp3[1];
+       if ( d < -1 || d > 1 ) {
+split3:
+               temp = lp1;
+               lp1 = lp3;
+               lp3 = lp2;
+               lp2 = temp;
+
+               goto split;
+       }
+
+       return 0;           // entire tri is filled
+
+split2:
+       temp = lp1;
+       lp1 = lp2;
+       lp2 = lp3;
+       lp3 = temp;
+
+split:
+// split this edge
+       new[0] = ( lp1[0] + lp2[0] ) >> 1;
+       new[1] = ( lp1[1] + lp2[1] ) >> 1;
+
+// draw the point if splitting a leading edge
+       if ( lp2[1] > lp1[1] ) {
+               goto nodraw;
+       }
+       if ( ( lp2[1] == lp1[1] ) && ( lp2[0] < lp1[0] ) ) {
+               goto nodraw;
+       }
+
+       if ( SetPixel ) {
+               assert( ( new[1] * BaseWidth ) + new[0] < BaseWidth * BaseHeight );
+
+               if ( BaseTrueColor ) {
+                       BasePixels[( ( new[1] * BaseWidth ) + new[0] ) * 4] = 1;
+               }
+               else
+               {
+                       BasePixels[( new[1] * BaseWidth ) + new[0]] = 1;
+               }
+       }
+       else
+       {
+               if ( TransPixels ) {
+                       if ( TransPixels[( new[1] * TransWidth ) + new[0]] != 255 ) {
+                               return 1;
+                       }
+               }
+               else if ( BaseTrueColor ) {
+                       if ( BasePixels[( ( ( new[1] * BaseWidth ) + new[0] ) * 4 ) + 3] != 255 ) {
+                               return 1;
+                       }
+               }
+               else
+               {
+//                     pixel = BasePixels[(new[1]*BaseWidth) + new[0]];
+               }
+       }
+
+nodraw:
+// recursively continue
+       if ( CheckTransRecursiveTri( lp3, lp1, new ) ) {
+               return 1;
+       }
+
+       return CheckTransRecursiveTri( lp3, new, lp2 );
+}
+
+static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters,
+                                                                IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){
+       int i, j;
+       IntListNode_t *next;
+
+       for ( j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j )
+       {
+               if ( !clusters[j] ) {
+                       continue;
+               }
+
+               for ( i = 0; i < num_verts[j + 1]; ++i )
+               {
+                       if ( clusters[j][i] == oldindex ) {
+                               ++new_num_verts[j + 1];
+
+                               next = vertLists[j];
+
+                               vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" );
+                               // Currently freed in WriteJointedModelFile only
+
+                               vertLists[j]->data = newIndex;
+                               vertLists[j]->next = next;
+                       }
+               }
+       }
+}
+
+#define FUDGE_EPSILON   0.002
+
+qboolean VectorFudgeCompare( vec3_t v1, vec3_t v2 ){
+       int i;
+
+       for ( i = 0 ; i < 3 ; i++ )
+               if ( fabs( v1[i] - v2[i] ) > FUDGE_EPSILON ) {
+                       return false;
+               }
+
+       return true;
+}
+
+/*
+   =================
+   Cmd_Base
+   =================
+ */
+void Cmd_FMBase( qboolean GetST ){
+       triangle_t  *ptri, *st_tri;
+       int num_st_tris;
+       int i, j, k, l;
+       int x,y,z;
+//     int                     time1;
+       char file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256];
+       vec3_t base_xyz[MAX_FM_VERTS];
+       FILE        *FH;
+       int pos,bit;
+       qboolean NewSkin;
+
+       GetScriptToken( false );
+
+       if ( g_skipmodel || g_release || g_archive ) {
+               return;
+       }
+
+       printf( "---------------------\n" );
+       sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext );
+       printf( "%s ", file1 );
+
+       ExpandPathAndArchive( file1 );
+
+       // Use the input filepath for this one.
+       sprintf( file1, "%s/%s", cddir, token );
+
+//     time1 = FileTime (file1);
+//     if (time1 == -1)
+//             Error ("%s doesn't exist", file1);
+
+//
+// load the base triangles
+//
+       if ( do3ds ) {
+               Load3DSTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
+       }
+       else{
+               LoadTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
+       }
+
+       if ( g_ignoreTriUV ) {
+               for ( i = 0; i < fmheader.num_tris; i++ )
+               {
+                       ptri[i].HasUV = 0;
+               }
+       }
+
+       GetScriptToken( false );
+       sprintf( file2, "%s/%s", cddir, token );
+       sprintf( trans_file, "%s/!%s_a.pcx", cddir, token );
+
+       ExtractFileExtension( file2, extension );
+       if ( extension[0] == 0 ) {
+               strcat( file2, ".pcx" );
+       }
+       printf( "skin: %s\n", file2 );
+
+       BaseTrueColor = LoadAnyImage( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight );
+
+       NewSkin = false;
+       if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) {
+               if ( g_allow_newskin ) {
+                       ScaleWidth = BaseWidth;
+                       ScaleHeight = BaseHeight;
+                       NewSkin = true;
+               }
+               else
+               {
+                       Error( "Invalid skin page size: (%d,%d) should be (%d,%d)",
+                                  BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT );
+               }
+       }
+       else if ( !BaseTrueColor ) {
+               ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X,
+                                                                                  ENCODED_WIDTH_Y );
+               ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X,
+                                                                                       ENCODED_HEIGHT_Y );
+       }
+       else
+       {
+               Error( "Texture coordinates not supported on true color image" );
+       }
+
+       if ( GetST ) {
+               GetScriptToken( false );
+
+               sprintf( stfile, "%s/%s.%s", cdarchive, token, trifileext );
+               printf( "ST: %s ", stfile );
+
+               sprintf( stfile, "%s/%s", cddir, token );
+
+               if ( do3ds ) {
+                       Load3DSTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL );
+               }
+               else{
+                       LoadTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL );
+               }
+
+               if ( num_st_tris != fmheader.num_tris ) {
+                       Error( "num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris );
+               }
+
+               printf( "   matching triangles...\n" );
+               for ( i = 0; i < fmheader.num_tris; i++ )
+               {
+                       k = -1;
+                       for ( j = 0; j < num_st_tris; j++ )
+                       {
+                               for ( x = 0; x < 3; x++ )
+                               {
+                                       for ( y = 0; y < 3; y++ )
+                                       {
+                                               if ( x == y ) {
+                                                       continue;
+                                               }
+                                               for ( z = 0; z < 3; z++ )
+                                               {
+                                                       if ( z == x || z == y ) {
+                                                               continue;
+                                                       }
+
+                                                       if ( VectorFudgeCompare( ptri[i].verts[0], st_tri[j].verts[x] ) &&
+                                                                VectorFudgeCompare( ptri[i].verts[1], st_tri[j].verts[y] ) &&
+                                                                VectorFudgeCompare( ptri[i].verts[2], st_tri[j].verts[z] ) ) {
+                                                               if ( k == -1 ) {
+                                                                       k = j;
+                                                                       ptri[i].HasUV = st_tri[k].HasUV;
+                                                                       ptri[i].uv[0][0] = st_tri[k].uv[x][0];
+                                                                       ptri[i].uv[0][1] = st_tri[k].uv[x][1];
+                                                                       ptri[i].uv[1][0] = st_tri[k].uv[y][0];
+                                                                       ptri[i].uv[1][1] = st_tri[k].uv[y][1];
+                                                                       ptri[i].uv[2][0] = st_tri[k].uv[z][0];
+                                                                       ptri[i].uv[2][1] = st_tri[k].uv[z][1];
+                                                                       x = y = z = 999;
+                                                               }
+                                                               else if ( k != j ) {
+                                                                       printf( "Duplicate triangle %d found in st file: %d and %d\n",i,k,j );
+                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+                                                                                       ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2],
+                                                                                       ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2],
+                                                                                       ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2] );
+                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+                                                                                       st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2],
+                                                                                       st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2],
+                                                                                       st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2] );
+                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+                                                                                       st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2],
+                                                                                       st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2],
+                                                                                       st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2] );
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if ( k == -1 ) {
+                               printf( "No matching triangle %d\n",i );
+                       }
+               }
+               free( st_tri );
+       }
+
+//
+// get the ST values
+//
+       if ( ptri && ptri[0].HasUV ) {
+               if ( !NewSkin ) {
+                       Error( "Base has UVs with old style skin page\nMaybe you want to use -ignoreUV" );
+               }
+               else
+               {
+                       BuildNewST( ptri, fmheader.num_tris, false );
+               }
+       }
+       else
+       {
+               if ( NewSkin ) {
+                       Error( "Base has new style skin without UVs" );
+               }
+               else
+               {
+                       BuildST( ptri, fmheader.num_tris, false );
+               }
+       }
+
+       TransPixels = NULL;
+       if ( !BaseTrueColor ) {
+               FH = fopen( trans_file,"rb" );
+               if ( FH ) {
+                       fclose( FH );
+                       Load256Image( trans_file, &TransPixels, NULL, &TransWidth, &TransHeight );
+                       if ( TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight ) {
+                               Error( "source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight );
+                       }
+               }
+       }
+
+//
+// run through all the base triangles, storing each unique vertex in the
+// base vertex list and setting the indirect triangles to point to the base
+// vertices
+//
+       for ( l = 0; l < fmheader.num_mesh_nodes; l++ )
+       {
+               for ( i = 0 ; i < fmheader.num_tris ; i++ )
+               {
+                       pos = i >> 3;
+                       bit = 1 << ( i & 7 );
+                       if ( !( pmnodes[l].tris[pos] & bit ) ) {
+                               continue;
+                       }
+
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               // get the xyz index
+                               for ( k = 0 ; k < fmheader.num_xyz ; k++ )
+                               {
+                                       if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) {
+                                               break;  // this vertex is already in the base vertex list
+                                       }
+                               }
+
+                               if ( k == fmheader.num_xyz ) { // new index
+                                       VectorCopy( ptri[i].verts[j], base_xyz[fmheader.num_xyz] );
+
+                                       if ( pmnodes[l].clustered == true ) {
+                                               ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts );
+                                       }
+
+                                       fmheader.num_xyz++;
+                               }
+
+                               pos = k >> 3;
+                               bit = 1 << ( k & 7 );
+                               pmnodes[l].verts[pos] |= bit;
+
+                               triangles[i].index_xyz[j] = k;
+
+                               // get the st index
+                               for ( k = 0 ; k < fmheader.num_st ; k++ )
+                               {
+                                       if ( triangle_st[i][j][0] == base_st[k].s
+                                                && triangle_st[i][j][1] == base_st[k].t ) {
+                                               break;  // this vertex is already in the base vertex list
+                                       }
+                               }
+
+                               if ( k == fmheader.num_st ) { // new index
+                                       base_st[fmheader.num_st].s = triangle_st[i][j][0];
+                                       base_st[fmheader.num_st].t = triangle_st[i][j][1];
+                                       fmheader.num_st++;
+                               }
+
+                               triangles[i].index_st[j] = k;
+                       }
+
+                       if ( TransPixels || BaseTrueColor ) {
+                               translucent[i] = CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
+                       }
+                       else
+                       {
+                               translucent[i] = false;
+                       }
+               }
+       }
+
+       if ( !BaseTrueColor ) {
+               SetPixel = true;
+               memset( BasePixels,0,BaseWidth * BaseHeight );
+               for ( i = 0 ; i < fmheader.num_tris ; i++ )
+               {
+                       CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
+               }
+               SetPixel = false;
+
+               skin_pixels_used = 0;
+               for ( i = 0; i < fmheader.skinheight; i++ )
+               {
+                       for ( j = 0; j < fmheader.skinwidth; j++ )
+                       {
+                               skin_pixels_used += BasePixels[( i * BaseWidth ) + j];
+                       }
+               }
+               total_skin_pixels = fmheader.skinheight * fmheader.skinwidth;
+       }
+       else
+       {
+               SetPixel = true;
+               memset( BasePixels,0,BaseWidth * BaseHeight * 4 );
+               for ( i = 0 ; i < fmheader.num_tris ; i++ )
+               {
+                       CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
+               }
+               SetPixel = false;
+
+               skin_pixels_used = 0;
+               for ( i = 0; i < fmheader.skinheight; i++ )
+               {
+                       for ( j = 0; j < fmheader.skinwidth; j++ )
+                       {
+                               skin_pixels_used += BasePixels[( ( i * BaseWidth ) + j ) * 4];
+                       }
+               }
+               total_skin_pixels = fmheader.skinheight * fmheader.skinwidth;
+       }
+
+       // build triangle strips / fans
+       BuildGlCmds();
+
+       if ( TransPixels ) {
+               free( TransPixels );
+       }
+       free( BasePixels );
+       if ( BasePalette ) {
+               free( BasePalette );
+       }
+       free( ptri );
+}
+
+void Cmd_FMNodeOrder( void ){
+       mesh_node_t *newnodes, *pos;
+       int i,j;
+
+       if ( !pmnodes ) {
+               Error( "Base has not been established yet" );
+       }
+
+       pos = newnodes = malloc( sizeof( mesh_node_t ) * fmheader.num_mesh_nodes );
+
+       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+       {
+               GetScriptToken( false );
+
+               for ( j = 0; j < fmheader.num_mesh_nodes; j++ )
+               {
+                       if ( strcmpi( pmnodes[j].name, token ) == 0 ) {
+                               *pos = pmnodes[j];
+                               pos++;
+                               break;
+                       }
+               }
+               if ( j >= fmheader.num_mesh_nodes ) {
+                       Error( "Node '%s' not in base list!\n", token );
+               }
+       }
+
+       free( pmnodes );
+       pmnodes = newnodes;
+}
+
+//===============================================================
+
+extern char *FindFrameFile( char *frame );
+
+
+/*
+   ===============
+   GrabFrame
+   ===============
+ */
+void GrabFrame( char *frame ){
+       triangle_t      *ptri;
+       int i, j;
+       fmtrivert_t     *ptrivert;
+       int num_tris;
+       char file1[1024];
+       fmframe_t       *fr;
+       int index_xyz;
+       char            *framefile;
+
+       // the frame 'run1' will be looked for as either
+       // run.1 or run1.tri, so the new alias sequence save
+       // feature an be used
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "grabbing %s  ", file1 );
+
+       if ( fmheader.num_frames >= MAX_FM_FRAMES ) {
+               Error( "fmheader.num_frames >= MAX_FM_FRAMES" );
+       }
+       fr = &g_frames[fmheader.num_frames];
+       fmheader.num_frames++;
+
+       strcpy( fr->name, frame );
+
+//
+// load the frame
+//
+       if ( do3ds ) {
+               Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
+       }
+       else{
+               LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
+       }
+
+       if ( num_tris != fmheader.num_tris ) {
+               Error( "%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris );
+       }
+
+//
+// allocate storage for the frame's vertices
+//
+       ptrivert = fr->v;
+
+       for ( i = 0 ; i < fmheader.num_xyz ; i++ )
+       {
+               ptrivert[i].vnorm.numnormals = 0;
+               VectorClear( ptrivert[i].vnorm.normalsum );
+       }
+       ClearBounds( fr->mins, fr->maxs );
+
+//
+// store the frame's vertices in the same order as the base. This assumes the
+// triangles and vertices in this frame are in exactly the same order as in the
+// base
+//
+       for ( i = 0 ; i < num_tris ; i++ )
+       {
+               vec3_t vtemp1, vtemp2, normal;
+               float ftemp;
+
+               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+               CrossProduct( vtemp1, vtemp2, normal );
+
+               VectorNormalize( normal, normal );
+
+               // rotate the normal so the model faces down the positive x axis
+               ftemp = normal[0];
+               normal[0] = -normal[1];
+               normal[1] = ftemp;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       index_xyz = triangles[i].index_xyz[j];
+
+                       // rotate the vertices so the model faces down the positive x axis
+                       // also adjust the vertices to the desired origin
+                       ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
+                                                                          adjust[0];
+                       ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
+                                                                          adjust[1];
+                       ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
+                                                                          adjust[2];
+
+                       AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );
+
+                       VectorAdd( ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum );
+                       ptrivert[index_xyz].vnorm.numnormals++;
+               }
+       }
+
+//
+// calculate the vertex normals, match them to the template list, and store the
+// index of the best match
+//
+       for ( i = 0 ; i < fmheader.num_xyz ; i++ )
+       {
+               int j;
+               vec3_t v;
+               float maxdot;
+               int maxdotindex;
+               int c;
+
+               c = ptrivert[i].vnorm.numnormals;
+               if ( !c ) {
+                       Error( "Vertex with no triangles attached" );
+               }
+
+               VectorScale( ptrivert[i].vnorm.normalsum, 1.0 / c, v );
+               VectorNormalize( v, v );
+
+               maxdot = -999999.0;
+               maxdotindex = -1;
+
+               for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
+               {
+                       float dot;
+
+                       dot = DotProduct( v, avertexnormals[j] );
+                       if ( dot > maxdot ) {
+                               maxdot = dot;
+                               maxdotindex = j;
+                       }
+               }
+
+               ptrivert[i].lightnormalindex = maxdotindex;
+       }
+
+       free( ptri );
+}
+
+/*
+   ===============
+   Cmd_Frame
+   ===============
+ */
+void Cmd_FMFrame( void ){
+       while ( ScriptTokenAvailable() )
+       {
+               GetScriptToken( false );
+               if ( g_skipmodel ) {
+                       continue;
+               }
+               if ( g_release || g_archive ) {
+                       fmheader.num_frames = 1;    // don't skip the writeout
+                       continue;
+               }
+
+               H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames );
+
+               if ( ( g_skelModel.type != SKEL_NULL ) || ( g_skelModel.references != REF_NULL ) ) {
+                       GrabModelTransform( token );
+               }
+
+               GrabFrame( token );
+
+               if ( g_skelModel.type != SKEL_NULL ) {
+                       GrabSkeletalFrame( token );
+               }
+
+               if ( g_skelModel.references != REF_NULL ) {
+                       GrabReferencedFrame( token );
+               }
+
+               // need to add the up and dir points to the frame bounds here
+               // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+               // then remove fudge in determining scale on frame write out
+       }
+}
+
+/*
+   ===============
+   Cmd_Skin
+
+   Skins aren't actually stored in the file, only a reference
+   is saved out to the header file.
+   ===============
+ */
+void Cmd_FMSkin( void ){
+       byte        *palette;
+       byte        *pixels;
+       int width, height;
+       byte        *cropped;
+       int y;
+       char name[1024], savename[1024], transname[1024], extension[256];
+       miptex32_t  *qtex32;
+       int size;
+       FILE        *FH;
+       qboolean TrueColor;
+
+       GetScriptToken( false );
+
+       if ( fmheader.num_skins == MAX_FM_SKINS ) {
+               Error( "fmheader.num_skins == MAX_FM_SKINS" );
+       }
+
+       if ( g_skipmodel ) {
+               return;
+       }
+
+       sprintf( name, "%s/%s", cdarchive, token );
+       strcpy( name, ExpandPathAndArchive( name ) );
+//     sprintf (name, "%s/%s.lbm", cddir, token);
+
+       if ( ScriptTokenAvailable() ) {
+               GetScriptToken( false );
+               sprintf( g_skins[fmheader.num_skins], "!%s", token );
+               sprintf( savename, "%s!%s", g_outputDir, token );
+               sprintf( transname, "%s!%s_a.pcx", gamedir, token );
+       }
+       else
+       {
+               sprintf( g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token );
+               sprintf( savename, "%s/!%s", g_outputDir, token );
+               sprintf( transname, "%s/!%s_a.pcx", cddir, token );
+       }
+
+       fmheader.num_skins++;
+
+       if ( g_skipmodel || g_release || g_archive ) {
+               return;
+       }
+
+       // load the image
+       printf( "loading %s\n", name );
+       ExtractFileExtension( name, extension );
+       if ( extension[0] == 0 ) {
+               strcat( name, ".pcx" );
+       }
+
+
+       TrueColor = LoadAnyImage( name, &pixels, &palette, &width, &height );
+//     RemapZero (pixels, palette, width, height);
+
+       // crop it to the proper size
+
+       if ( !TrueColor ) {
+               cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight, "Cmd_FMSkin" );
+               for ( y = 0 ; y < fmheader.skinheight ; y++ )
+               {
+                       memcpy( cropped + y * fmheader.skinwidth,
+                                       pixels + y * width, fmheader.skinwidth );
+               }
+
+               TransPixels = NULL;
+               FH = fopen( transname,"rb" );
+               if ( FH ) {
+                       fclose( FH );
+
+                       strcat( g_skins[fmheader.num_skins - 1],".pcx" );
+                       strcat( savename,".pcx" );
+
+                       // save off the new image
+                       printf( "saving %s\n", savename );
+                       CreatePath( savename );
+                       WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette );
+               }
+               else
+               {
+       #if 1
+                       miptex_t    *qtex;
+                       qtex = CreateMip( cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true );
+
+                       strcat( g_skins[fmheader.num_skins - 1],".m8" );
+                       strcat( savename,".m8" );
+
+                       printf( "saving %s\n", savename );
+                       CreatePath( savename );
+                       SaveFile( savename, (byte *)qtex, size );
+                       free( qtex );
+       #else
+                       strcat( g_skins[fmheader.num_skins - 1],".pcx" );
+                       strcat( savename,".pcx" );
+
+                       // save off the new image
+                       printf( "saving %s\n", savename );
+                       CreatePath( savename );
+                       WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette );
+       #endif
+               }
+       }
+       else
+       {
+               cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight * 4, "Cmd_FMSkin" );
+               for ( y = 0 ; y < fmheader.skinheight ; y++ )
+               {
+                       memcpy( cropped + ( ( y * fmheader.skinwidth ) * 4 ), pixels + ( y * width * 4 ), fmheader.skinwidth * 4 );
+               }
+
+               qtex32 = CreateMip32( (unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true );
+
+               StripExtension( g_skins[fmheader.num_skins - 1] );
+               strcat( g_skins[fmheader.num_skins - 1],".m32" );
+               StripExtension( savename );
+               strcat( savename,".m32" );
+
+               printf( "saving %s\n", savename );
+               CreatePath( savename );
+               SaveFile( savename, (byte *)qtex32, size );
+       }
+
+       free( pixels );
+       if ( palette ) {
+               free( palette );
+       }
+       free( cropped );
+}
+
+
+/*
+   ===============
+   Cmd_Cd
+   ===============
+ */
+void Cmd_FMCd( void ){
+       char temp[256];
+
+       FinishModel();
+       ClearModel();
+
+       GetScriptToken( false );
+
+       // this is a silly mess...
+       sprintf( cdpartial, "models/%s", token );
+       sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token );
+       sprintf( cddir, "%s%s", gamedir, cdpartial );
+
+       // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
+       sprintf( temp, "%s%s", g_outputDir, cdpartial );
+       strcpy( g_outputDir, temp );
+
+       // if -only was specified and this cd doesn't match,
+       // skip the model (you only need to match leading chars,
+       // so you could regrab all monsters with -only monsters)
+       if ( !g_only[0] ) {
+               return;
+       }
+       if ( strncmp( token, g_only, strlen( g_only ) ) ) {
+               g_skipmodel = true;
+               printf( "skipping %s\n", cdpartial );
+       }
+}
+
+
+/*
+
+   //=======================
+   //          NEW GEN
+   //=======================
+
+   void NewGen (char *ModelFile, char *OutputName, int width, int height)
+   {
+    trigroup_t  *triangles;
+    triangle_t *ptri;
+    triangle_t *grouptris;
+    mesh_node_t        *pmnodes;
+
+    vec3_t             *vertices;
+    vec3_t             *uvs;
+    vec3_t             aveNorm, crossvect;
+    vec3_t             diffvect1, diffvect2;
+    vec3_t             v0, v1, v2;
+    vec3_t             n, u, v;
+    vec3_t             base, zaxis, yaxis;
+    vec3_t             uvwMin, uvwMax;
+    vec3_t             groupMin, groupMax;
+    vec3_t             uvw;
+
+    float              *uFinal, *vFinal;
+    unsigned char      *newpic;
+
+    int                        finalstart = 0, finalcount = 0;
+    int                        xbase = 0, xwidth = 0, ywidth = 0;
+    int                        *todo, *done, finished;
+    int                        i, j, k, l; //counters
+    int                        groupnum, numtris, numverts, num;
+    int                        count;
+    FILE               *grpfile;
+    long               datasize;
+
+    for ( i = 0; i<3; i++)
+    {
+        aveNorm[i] = 0;
+        uvwMin[i] = 1e30f;
+        uvwMax[i] = -1e30f;
+    }
+
+    pmnodes = NULL;
+    ptri = NULL;
+    triangles = NULL;
+
+    zaxis[0] = 0;
+    zaxis[1] = 0;
+    zaxis[2] = 1;
+
+    yaxis[0] = 0;
+    yaxis[1] = 1;
+    yaxis[2] = 0;
+
+    LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
+
+    todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
+    done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
+    triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen");
+
+    for ( i=0; i < fmheader.num_tris; i++)
+    {
+        todo[i] = false;
+        done[i] = false;
+        triangles[i].triangle = ptri[i];
+        triangles[i].group = 0;
+    }
+
+    groupnum = 0;
+
+   //  transitive closure algorithm follows
+   //  put all triangles who transitively share vertices into separate groups
+
+    while (1)
+    {
+        for ( i = 0; i < fmheader.num_tris; i++)
+        {
+            if (!done[i])
+            {
+                break;
+            }
+        }
+        if ( i == fmheader.num_tris)
+        {
+            break;
+        }
+        finished = false;
+        todo[i] = true;
+        while (!finished)
+        {
+            finished = true;
+            for ( i = 0; i < fmheader.num_tris; i++)
+            {
+                if (todo[i])
+                {
+                    done[i] = true;
+                    triangles[i].group = groupnum;
+                    todo[i] = false;
+                    for ( j = 0; j < fmheader.num_tris; j++)
+                    {
+                        if ((!done[j]) && (ShareVertex(triangles[i],triangles[j])))
+                        {
+                            todo[j] = true;
+                            finished = false;
+                        }
+                    }
+                }
+            }
+        }
+        groupnum++;
+    }
+        uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
+        vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
+
+    grpfile = fopen("grpdebug.txt","w");
+
+
+    for (i = 0; i < groupnum; i++)
+    {
+
+        fprintf(grpfile,"Group Number: %d\n", i);
+
+        numtris = GetNumTris(triangles, i); // number of triangles in group i
+        numverts = numtris * 3;
+
+        fprintf(grpfile,"%d triangles.\n", numtris);
+
+        vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
+        uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
+        grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen");
+
+        for (count = 0; count < fmheader.num_tris; count++)
+        {
+            if (triangles[count].group == i)
+            {
+                fprintf(grpfile,"Triangle %d\n", count);
+            }
+        }
+        fprintf(grpfile,"\n");
+
+
+
+
+        GetOneGroup(triangles, i, grouptris);
+
+        num = 0;
+        for (j = 0; j < numtris; j++)
+        {
+            VectorCopy(grouptris[j].verts[0], v0);
+            VectorCopy(grouptris[j].verts[1], v1);
+            VectorCopy(grouptris[j].verts[2], v2);
+            VectorSubtract(v1, v0, diffvect1);
+            VectorSubtract(v2, v1, diffvect2);
+            CrossProduct( diffvect1, diffvect2, crossvect);
+            VectorAdd(aveNorm, crossvect, aveNorm);
+            VectorCopy(v0,vertices[num]);
+            num++;                                     //  FIXME
+            VectorCopy(v1,vertices[num]);
+            num++;                                     //  add routine to add only verts that
+            VectorCopy(v2,vertices[num]);
+            num++;                                     // have not already been added
+        }
+
+        assert (num >= 3);
+   // figure out the best plane projections
+        DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base);
+
+        if (DotProduct(aveNorm,n) < 0.0f)
+        {
+            VectorScale(n, -1.0f, n);
+        }
+        VectorNormalize(n,n);
+        if (fabs(n[2]) < .57)
+        {
+            CrossProduct( zaxis, n, crossvect);
+            VectorCopy(crossvect, u);
+        }
+        else
+        {
+            CrossProduct( yaxis, n, crossvect);
+            VectorCopy(crossvect, u);
+        }
+        VectorNormalize(u,u);
+        CrossProduct( n, u, crossvect);
+        VectorCopy(crossvect, v);
+        VectorNormalize(v,v);
+
+        num = 0;
+
+        for ( j = 0; j < 3; j++)
+        {
+            groupMin[j] = 1e30f;
+            groupMax[j] = -1e30f;
+        }
+
+        for ( j = 0; j < numtris; j++)
+        {
+            for ( k = 0; k < 3; k++)
+            {
+                VectorCopy(grouptris[j].verts[k],v0);
+                VectorSubtract(v0, base, v0);
+                uvw[0] = DotProduct(v0, u);
+                uvw[1] = DotProduct(v0, v);
+                uvw[2] = DotProduct(v0, n);
+                VectorCopy(uvw,uvs[num]);
+                num++;
+                for ( l = 0; l < 3; l++)
+                {
+                    if (uvw[l] < groupMin[l])
+                    {
+                        groupMin[l] = uvw[l];
+                    }
+                    if (uvw[l] > groupMax[l])
+                    {
+                        groupMax[l] = uvw[l];
+                    }
+                }
+            }
+        }
+
+        xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap
+        ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin
+
+        for ( j=0; j < numverts; j++)
+        {
+            uFinal[finalcount] = uvs[j][0] + xwidth + xbase;
+            vFinal[finalcount] = uvs[j][1] + ywidth;
+            if (uFinal[finalcount] < uvwMin[0])
+            {
+                uvwMin[0] = uFinal[finalcount];
+            }
+            if (uFinal[finalcount] > uvwMax[0])
+            {
+                uvwMax[0] = uFinal[finalcount];
+            }
+            if (vFinal[finalcount] < uvwMin[1])
+            {
+                uvwMin[1] = vFinal[finalcount];
+            }
+            if (vFinal[finalcount] > uvwMax[1])
+            {
+                uvwMax[1] = vFinal[finalcount];
+            }
+            finalcount++;
+        }
+
+        fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth);
+        fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth);
+
+        finalcount = finalstart;
+
+        for ( count = 0; count < numverts; count++)
+        {
+            fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]);
+            fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]);
+        }
+
+        finalstart = finalcount;
+
+        fprintf(grpfile,"\n");
+
+        free(vertices);
+        free(uvs);
+        free(grouptris);
+
+        xbase += ceil(groupMax[0] - groupMin[0]) + 2;
+
+    }
+
+    fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]);
+    fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]);
+
+
+    ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount);
+
+    for (k = 0; k < finalcount; k++)
+    {
+        fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]);
+    }
+
+    //  i've got the array of vertices in uFinal and vFinal.  Now I need to write them and draw lines
+
+    datasize = width * height*sizeof(unsigned char);
+    newpic = (unsigned char*)SafeMalloc(datasize, "NewGen");
+    memset(newpic,0,datasize);
+    memset(pic_palette,0,sizeof(pic_palette));
+    pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
+
+    k = 0;
+    while (k < finalcount)
+    {
+        NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
+        k++;
+        NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
+        k++;
+        NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height);
+        k++;
+        fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k);
+    }
+
+    WritePCXfile (OutputName, newpic, width, height, pic_palette);
+
+    fclose(grpfile);
+
+    free(todo);
+    free(done);
+    free(triangles);
+    free(newpic);
+    return;
+   }
+   void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height)
+   {
+    long dx, dy;
+    long adx, ady;
+    long count;
+    float xfrac, yfrac, xstep, ystep;
+    unsigned long sx, sy;
+    float u, v;
+
+    dx = x2 - x1;
+    dy = y2 - y1;
+    adx = abs(dx);
+    ady = abs(dy);
+
+    count = adx > ady ? adx : ady;
+    count++;
+
+    if(count > 300)
+    {
+        printf("Bad count\n");
+        return; // don't ever hang up on bad data
+    }
+
+    xfrac = x1;
+    yfrac = y1;
+
+    xstep = (float)dx/count;
+    ystep = (float)dy/count;
+
+    switch(LineType)
+    {
+        case LINE_NORMAL:
+            do
+            {
+                if(xfrac < width && yfrac < height)
+                {
+                    picture[(long)yfrac*width+(long)xfrac] = LineColor;
+                }
+                xfrac += xstep;
+                yfrac += ystep;
+                count--;
+            } while (count > 0);
+            break;
+        case LINE_FAT:
+            do
+            {
+                for (u=-0.1 ; u<=0.9 ; u+=0.999)
+                {
+                    for (v=-0.1 ; v<=0.9 ; v+=0.999)
+                    {
+                        sx = xfrac+u;
+                        sy = yfrac+v;
+                        if(sx < width && sy < height)
+                        {
+                            picture[sy*width+sx] = LineColor;
+                        }
+                    }
+                }
+                xfrac += xstep;
+                yfrac += ystep;
+                count--;
+            } while (count > 0);
+            break;
+        case LINE_DOTTED:
+            do
+            {
+                if(count&1 && xfrac < width &&
+                    yfrac < height)
+                {
+                    picture[(long)yfrac*width+(long)xfrac] = LineColor;
+                }
+                xfrac += xstep;
+                yfrac += ystep;
+                count--;
+            } while (count > 0);
+            break;
+        default:
+            Error("Unknown <linetype> %d.\n", LineType);
+    }
+   }
+ */
+void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ){
+
+       int i;
+       float hscale, vscale;
+       float scale;
+
+       hscale = max[0];
+       vscale = max[1];
+
+       hscale = ( Width - 2 ) / max[0];
+       vscale = ( Height - 2 ) / max[1];
+
+       scale = hscale;
+       if ( scale > vscale ) {
+               scale = vscale;
+       }
+       for ( i = 0; i < verts; i++ )
+       {
+               u[i] *= scale;
+               v[i] *= scale;
+       }
+       return;
+}
+
+
+void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ){
+       int i;
+       int j;
+
+       j = 0;
+       for ( i = 0; i < fmheader.num_tris; i++ )
+       {
+               if ( tris[i].group == grp ) {
+                       triangles[j++] = tris[i].triangle;
+               }
+       }
+       return;
+}
+
+
+int GetNumTris( trigroup_t *tris, int grp ){
+       int i;
+       int verts;
+
+       verts = 0;
+       for ( i = 0; i < fmheader.num_tris; i++ )
+       {
+               if ( tris[i].group == grp ) {
+                       verts++;
+               }
+       }
+       return verts;
+}
+
+
+int ShareVertex( trigroup_t trione, trigroup_t tritwo ){
+       int i;
+       int j;
+
+       i = 1;
+       j = 1;
+       for ( i = 0; i < 3; i++ )
+       {
+               for ( j = 0; j < 3; j++ )
+               {
+                       if ( DistBetween( trione.triangle.verts[i],tritwo.triangle.verts[j] ) < TRIVERT_DIST ) {
+                               return true;
+                       }
+               }
+       }
+       return false;
+}
+
+
+float DistBetween( vec3_t point1, vec3_t point2 ){
+       float dist;
+
+       dist = ( point1[0] - point2[0] );
+       dist *= dist;
+       dist += ( point1[1] - point2[1] ) * ( point1[1] - point2[1] );
+       dist += ( point1[2] - point2[2] ) * ( point1[2] - point2[2] );
+       dist = sqrt( dist );
+       return dist;
+}
+
+
+void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ){
+       triangle_t  *ptri;
+       mesh_node_t *pmnodes;
+       int i;
+
+       pmnodes = NULL;
+       ptri = NULL;
+
+       LoadTriangleList( ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
+       if ( g_ignoreTriUV ) {
+               for ( i = 0; i < fmheader.num_tris; i++ )
+               {
+                       ptri[i].HasUV = 0;
+               }
+       }
+
+       memset( pic,0,sizeof( pic ) );
+       memset( pic_palette,0,sizeof( pic_palette ) );
+       pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
+
+       ScaleWidth = Width;
+       ScaleHeight = Height;
+
+       BuildST( ptri, fmheader.num_tris, true );
+
+       WritePCXfile( OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette );
+
+       printf( "Gen Skin Stats:\n" );
+       printf( "   Input Base: %s\n",ModelFile );
+       printf( "   Input Dimensions: %d,%d\n",Width,Height );
+       printf( "\n" );
+       printf( "   Output File: %s\n",OutputName );
+       printf( "   Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight );
+
+       if ( fmheader.num_mesh_nodes ) {
+               printf( "\nNodes:\n" );
+               for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
+               {
+                       printf( "   %s\n",pmnodes[i].name );
+               }
+       }
+
+       free( ptri );
+       free( pmnodes );
+}
+
+
+void Cmd_FMBeginGroup( void ){
+       GetScriptToken( false );
+
+       g_no_opimizations = false;
+
+       groups[num_groups].start_frame = fmheader.num_frames;
+       groups[num_groups].num_frames = 0;
+
+       groups[num_groups].degrees = atol( token );
+       if ( groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32 ) {
+               Error( "Degrees of freedom out of range: %d",groups[num_groups].degrees );
+       }
+}
+
+void Cmd_FMEndGroup( void ){
+       groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame;
+
+       if ( num_groups < MAX_GROUPS - 1 ) {
+               num_groups++;
+       }
+       else
+       {
+               Error( "Number of compression groups exceded: %i\n", MAX_GROUPS );
+       }
+}
diff --git a/tools/heretic2/h2data/h2data.rc b/tools/heretic2/h2data/h2data.rc
new file mode 100644 (file)
index 0000000..21540bc
--- /dev/null
@@ -0,0 +1,115 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_ICON1               ICON    DISCARDABLE     "..\\..\\..\\icons\\h2data.ico"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,0,0,1
+ PRODUCTVERSION 1,0,0,1
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x1L
+ FILESUBTYPE 0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "Comments", "Heavily modified from original ID tool\0"
+            VALUE "CompanyName", "Raven Software\0"
+            VALUE "FileDescription", "qdata\0"
+            VALUE "FileVersion", "2.0\0"
+            VALUE "InternalName", "qdata\0"
+            VALUE "LegalCopyright", "Copyright © 1998\0"
+            VALUE "OriginalFilename", "qdata.exe\0"
+            VALUE "ProductName", "Raven Software qdata\0"
+            VALUE "ProductVersion", "2.0\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // !_MAC
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/tools/heretic2/h2data/images.c b/tools/heretic2/h2data/images.c
new file mode 100644 (file)
index 0000000..fe1d050
--- /dev/null
@@ -0,0 +1,1415 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qdata.h"
+
+#if GDEF_OS_WINDOWS
+ #include <windows.h>
+#endif
+
+#if GDEF_OS_MACOS && !defined( XWINDOWS )
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+#if 1
+extern char     *g_outputDir;
+#endif // _QDATA
+
+byte *byteimage, *lbmpalette;
+int byteimagewidth, byteimageheight;
+qboolean TrueColorImage;
+unsigned *longimage;
+int longimagewidth, longimageheight;
+
+char mip_prefix[1024];              // directory to dump the textures in
+
+qboolean colormap_issued;
+byte colormap_palette[768];
+
+unsigned total_x = 0;
+unsigned total_y = 0;
+unsigned total_textures = 0;
+
+#define MAX_IMAGE_SIZE 512
+
+#if 0
+/*
+   ==============
+   RemapZero
+
+   Replaces all 0 bytes in an image with the closest palette entry.
+   This is because NT won't let us change index 0, so any palette
+   animation leaves those pixels untouched.
+   ==============
+ */
+void RemapZero( byte *pixels, byte *palette, int width, int height ){
+       int i, c;
+       int alt_zero;
+       int value, best;
+
+       alt_zero = 0;
+       best = 9999999;
+       for ( i = 1 ; i < 255 ; i++ )
+       {
+               value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
+               if ( value < best ) {
+                       best = value;
+                       alt_zero = i;
+               }
+       }
+
+       c = width * height;
+       for ( i = 0 ; i < c ; i++ )
+               if ( pixels[i] == 0 ) {
+                       pixels[i] = alt_zero;
+               }
+}
+
+#endif
+
+
+// ********************************************************************
+// **  Mip Map Pre-Processing Routines
+// ********************************************************************
+
+#define intensity_value 1
+
+static unsigned image_pal[256];
+
+#define MAX_LAST 25
+
+long palette_r[256], palette_g[256], palette_b[256];
+long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
+
+long cached;
+
+void PrepareConvert( unsigned *palette ){
+       int i;
+
+       for ( i = 0; i < 256; i++ )
+       {
+               palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
+               palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
+               palette_b[i] = ( palette[i] & 0x000000ff );
+       }
+
+       for ( i = 0; i < MAX_LAST; i++ )
+               last_r[i] = -1;
+
+       last_place = -1;
+}
+
+int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
+       int i;
+       long min_dist;
+       int min_index;
+       long dist;
+       long dr, dg, db, biggest_delta;
+
+       for ( i = 0; i < MAX_LAST; i++ )
+               if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
+                       cached++;
+                       return last_i[i];
+               }
+
+       min_dist = 256 * 256 + 256 * 256 + 256 * 256;
+       biggest_delta = 256 * 256;
+       min_index = 0;
+
+       for ( i = 0; i < 256; i++ )
+       {
+               dr = abs( palette_r[i] - r );
+               if ( dr > biggest_delta ) {
+                       continue;
+               }
+               dg = abs( palette_g[i] - g );
+               if ( dg > biggest_delta ) {
+                       continue;
+               }
+               db = abs( palette_b[i] - b );
+               if ( db > biggest_delta ) {
+                       continue;
+               }
+
+               dist = dr * dr + dg * dg + db * db;
+               if ( dist < min_dist ) {
+                       min_dist = dist;
+                       min_index = i;
+                       if ( min_dist == 0 ) {
+                               break;
+                       }
+
+                       dist = dr;
+                       if ( dg > dist ) {
+                               dist = dg;
+                       }
+                       if ( db > dist ) {
+                               dist = db;
+                       }
+                       if ( dist < biggest_delta ) {
+                               biggest_delta = dist;
+                       }
+               }
+       }
+
+       last_place++;
+       if ( last_place >= MAX_LAST ) {
+               last_place = 0;
+       }
+
+       last_r[last_place] = r;
+       last_g[last_place] = g;
+       last_b[last_place] = b;
+       last_i[last_place] = min_index;
+
+       return min_index;
+}
+
+
+void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
+                                                  int outwidth, int outheight, palette_t *palette ){
+       int i, j;
+       byte    *inrow, *inrow2;
+       unsigned frac, fracstep;
+       unsigned p1[1024], p2[1024], *p1p, *p2p;
+       palette_t   *c1,*c2,*c3,*c4;
+       unsigned r,g,b;
+
+       fracstep = inwidth * 0x10000 / outwidth;
+
+       frac = fracstep >> 2;
+       for ( i = 0 ; i < outwidth ; i++ )
+       {
+               p1[i] = frac >> 16;
+               frac += fracstep;
+       }
+       frac = 3 * ( fracstep >> 2 );
+       for ( i = 0 ; i < outwidth ; i++ )
+       {
+               p2[i] = frac >> 16;
+               frac += fracstep;
+       }
+
+       cached = 0;
+
+       for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
+       {
+               inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
+               inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
+
+               p1p = p1;
+               p2p = p2;
+               for ( j = 0 ; j < outwidth ; j++ )
+               {
+                       c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
+                       c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
+                       c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
+                       c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
+
+                       r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
+                       g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
+                       b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
+
+                       *out++ = ConvertTrueColorToPal( r,g,b );
+               }
+       }
+}
+
+void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
+       int i, j;
+       palette_t   *c1,*c2,*c3,*c4;
+       unsigned r,g,b;
+
+       cached = 0;
+       memset( out, 0, 256 * 256 );
+       width <<= 1;
+       height <<= 1;
+
+       for ( i = 0; i < height; i += 2, in += width )
+       {
+               for ( j = 0; j < width; j += 2 )
+               {
+                       c1 = &palette[in[0]];
+                       c3 = &palette[in[width]];
+                       in++;
+                       c2 = &palette[in[0]];
+                       c4 = &palette[in[width]];
+                       in++;
+
+                       r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
+                       g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
+                       b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
+
+                       *out++ = ConvertTrueColorToPal( r, g, b );
+               }
+       }
+}
+
+
+miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
+       int scaled_width, scaled_height;
+       int i,j,r,g,b;
+       byte intensitytable[256];
+       byte scaled[256 * 256];
+       byte out[256 * 256];
+       int miplevel;
+       miptex_t    *mp;
+       byte        *pos;
+       int size;
+
+       for ( i = 0 ; i < 256 ; i++ )
+       {
+               j = i * intensity_value;
+               if ( j > 255 ) {
+                       j = 255;
+               }
+               intensitytable[i] = j;
+       }
+
+       for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
+               ;
+       if ( 1 && scaled_width > width && 1 ) {
+               scaled_width >>= 1;
+       }
+       for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
+               ;
+       if ( 1 && scaled_height > height && 1 ) {
+               scaled_height >>= 1;
+       }
+
+       // don't ever bother with >256 textures
+       if ( scaled_width > 256 ) {
+               scaled_width = 256;
+       }
+       if ( scaled_height > 256 ) {
+               scaled_height = 256;
+       }
+
+       if ( scaled_width < 1 ) {
+               scaled_width = 1;
+       }
+       if ( scaled_height < 1 ) {
+               scaled_height = 1;
+       }
+
+       size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
+       mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
+       memset( mp,0,size );
+
+       mp->version = MIP_VERSION;
+
+       for ( i = j = 0; i < 256; i++,j += 3 )
+       {
+               mp->palette[i].r = r = intensitytable[palette[j]];
+               mp->palette[i].g = g = intensitytable[palette[j + 1]];
+               mp->palette[i].b = b = intensitytable[palette[j + 2]];
+               image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
+       }
+
+       PrepareConvert( image_pal );
+
+       if ( scaled_width == width && scaled_height == height ) {
+               memcpy( scaled, data, width * height );
+       }
+       else{
+               GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
+       }
+
+       pos = (byte *)( mp + 1 );
+       miplevel = 0;
+
+       while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
+       {
+               if ( scaled_width < 1 ) {
+                       scaled_width = 1;
+               }
+               if ( scaled_height < 1 ) {
+                       scaled_height = 1;
+               }
+
+               if ( miplevel > 0 ) {
+                       GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
+               }
+               else{
+                       memcpy( out, scaled, 256 * 256 );
+               }
+
+               mp->width[miplevel] = scaled_width;
+               mp->height[miplevel] = scaled_height;
+               mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
+               memcpy( pos, out, scaled_width * scaled_height );
+               memcpy( scaled, out, 256 * 256 );
+               pos += scaled_width * scaled_height;
+
+               scaled_width >>= 1;
+               scaled_height >>= 1;
+
+               miplevel++;
+       }
+
+       *FinalSize = pos - ( (byte *)( mp ) );
+
+       return mp;
+}
+
+
+void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight ){
+       int i, j;
+       unsigned    *inrow, *inrow2;
+       unsigned frac, fracstep;
+       unsigned p1[1024], p2[1024];
+       byte        *pix1, *pix2, *pix3, *pix4;
+
+       fracstep = inwidth * 0x10000 / outwidth;
+
+       frac = fracstep >> 2;
+       for ( i = 0 ; i < outwidth ; i++ )
+       {
+               p1[i] = 4 * ( frac >> 16 );
+               frac += fracstep;
+       }
+       frac = 3 * ( fracstep >> 2 );
+       for ( i = 0 ; i < outwidth ; i++ )
+       {
+               p2[i] = 4 * ( frac >> 16 );
+               frac += fracstep;
+       }
+
+       for ( i = 0 ; i < outheight ; i++, out += outwidth )
+       {
+               inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
+               inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
+               frac = fracstep >> 1;
+               for ( j = 0 ; j < outwidth ; j++ )
+               {
+                       pix1 = (byte *)inrow + p1[j];
+                       pix2 = (byte *)inrow + p2[j];
+                       pix3 = (byte *)inrow2 + p1[j];
+                       pix4 = (byte *)inrow2 + p2[j];
+                       ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
+                       ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
+                       ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
+                       ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
+               }
+       }
+}
+
+void GL_MipMap( byte *out, byte *in, int width, int height ){
+       int i, j;
+
+       width <<= 3;
+       height <<= 1;
+       for ( i = 0 ; i < height ; i++, in += width )
+       {
+               for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
+               {
+                       out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
+                       out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
+                       out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
+                       out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
+               }
+       }
+}
+
+miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
+       int scaled_width, scaled_height;
+       unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
+       unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
+       int miplevel;
+       miptex32_t      *mp;
+       byte            *pos;
+       int size;
+       paletteRGBA_t   *test;
+
+       for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
+               ;
+       if ( 1 && scaled_width > width && 1 ) {
+               scaled_width >>= 1;
+       }
+       for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
+               ;
+       if ( 1 && scaled_height > height && 1 ) {
+               scaled_height >>= 1;
+       }
+
+       // don't ever bother with >256 textures
+       if ( scaled_width > MAX_IMAGE_SIZE ) {
+               scaled_width = MAX_IMAGE_SIZE;
+       }
+       if ( scaled_height > MAX_IMAGE_SIZE ) {
+               scaled_height = MAX_IMAGE_SIZE;
+       }
+
+       if ( scaled_width < 1 ) {
+               scaled_width = 1;
+       }
+       if ( scaled_height < 1 ) {
+               scaled_height = 1;
+       }
+
+       size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
+       mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
+       memset( mp,0,size );
+
+       mp->version = MIP32_VERSION;
+
+       size = width * height;
+       test = (paletteRGBA_t *)data;
+       while ( size )
+       {
+               if ( test->a != 255 ) {
+                       mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
+                       break;
+               }
+
+               size--;
+               test++;
+       }
+
+       if ( scaled_width == width && scaled_height == height ) {
+               memcpy( scaled, data, width * height * 4 );
+       }
+       else{
+               GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
+       }
+
+       pos = (byte *)( mp + 1 );
+       miplevel = 0;
+
+       while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
+       {
+               if ( scaled_width < 1 ) {
+                       scaled_width = 1;
+               }
+               if ( scaled_height < 1 ) {
+                       scaled_height = 1;
+               }
+
+               if ( miplevel > 0 ) {
+                       GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
+               }
+               else
+               {
+                       memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
+               }
+
+               mp->width[miplevel] = scaled_width;
+               mp->height[miplevel] = scaled_height;
+               mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
+               memcpy( pos, out, scaled_width * scaled_height * 4 );
+               memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
+               pos += scaled_width * scaled_height * 4;
+
+               scaled_width >>= 1;
+               scaled_height >>= 1;
+
+               miplevel++;
+       }
+
+       *FinalSize = pos - ( (byte *)( mp ) );
+
+       return mp;
+}
+
+/*
+   ==============
+   Cmd_Grab
+
+   $grab filename x y width height
+   ==============
+ */
+void Cmd_Grab( void ){
+       int xl,yl,w,h,y;
+       byte            *cropped;
+       char savename[1024];
+       char dest[1024];
+
+       GetScriptToken( false );
+
+       if ( token[0] == '/' || token[0] == '\\' ) {
+               sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
+       }
+       else{
+               sprintf( savename, "%spics/%s.pcx", gamedir, token );
+       }
+
+       if ( g_release ) {
+               if ( token[0] == '/' || token[0] == '\\' ) {
+                       sprintf( dest, "%s.pcx", token + 1 );
+               }
+               else{
+                       sprintf( dest, "pics/%s.pcx", token );
+               }
+
+               ReleaseFile( dest );
+               return;
+       }
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
+               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
+       }
+
+       // crop it to the proper size
+       cropped = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
+       for ( y = 0 ; y < h ; y++ )
+       {
+               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
+       }
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+       WritePCXfile( savename, cropped, w, h, lbmpalette );
+
+       free( cropped );
+}
+
+/*
+   ==============
+   Cmd_Raw
+
+   $grab filename x y width height
+   ==============
+ */
+void Cmd_Raw( void ){
+       int xl,yl,w,h,y;
+       byte            *cropped;
+       char savename[1024];
+       char dest[1024];
+
+       GetScriptToken( false );
+
+       sprintf( savename, "%s%s.lmp", gamedir, token );
+
+       if ( g_release ) {
+               sprintf( dest, "%s.lmp", token );
+               ReleaseFile( dest );
+               return;
+       }
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
+               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
+       }
+
+       // crop it to the proper size
+       cropped = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
+       for ( y = 0 ; y < h ; y++ )
+       {
+               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
+       }
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+
+       SaveFile( savename, cropped, w * h );
+
+       free( cropped );
+}
+
+/*
+   =============================================================================
+
+   COLORMAP GRABBING
+
+   =============================================================================
+ */
+
+/*
+   ===============
+   BestColor
+   ===============
+ */
+byte BestColor( int r, int g, int b, int start, int stop ){
+       int i;
+       int dr, dg, db;
+       int bestdistortion, distortion;
+       int bestcolor;
+       byte    *pal;
+
+//
+// let any color go to 0 as a last resort
+//
+       bestdistortion = 256 * 256 * 4;
+       bestcolor = 0;
+
+       pal = colormap_palette + start * 3;
+       for ( i = start ; i <= stop ; i++ )
+       {
+               dr = r - (int)pal[0];
+               dg = g - (int)pal[1];
+               db = b - (int)pal[2];
+               pal += 3;
+               distortion = dr * dr + dg * dg + db * db;
+               if ( distortion < bestdistortion ) {
+                       if ( !distortion ) {
+                               return i;       // perfect match
+
+                       }
+                       bestdistortion = distortion;
+                       bestcolor = i;
+               }
+       }
+
+       return bestcolor;
+}
+
+
+/*
+   ==============
+   Cmd_Colormap
+
+   $colormap filename
+
+   the brightes colormap is first in the table (FIXME: reverse this now?)
+
+   64 rows of 256 : lightmaps
+   256 rows of 256 : translucency table
+   ==============
+ */
+void Cmd_Colormap( void ){
+       int levels, brights;
+       int l, c;
+       float frac, red, green, blue;
+       float range;
+       byte    *cropped, *lump_p;
+       char savename[1024];
+       char dest[1024];
+
+       colormap_issued = true;
+       if ( !g_release ) {
+               memcpy( colormap_palette, lbmpalette, 768 );
+       }
+
+       if ( !ScriptTokenAvailable() ) { // just setting colormap_issued
+               return;
+       }
+
+       GetScriptToken( false );
+       sprintf( savename, "%spics/%s.pcx", gamedir, token );
+
+       if ( g_release ) {
+               sprintf( dest, "pics/%s.pcx", token );
+               ReleaseFile( dest );
+               return;
+       }
+
+       range = 2;
+       levels = 64;
+       brights = 1;    // ignore 255 (transparent)
+
+       cropped = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
+       lump_p = cropped;
+
+// shaded levels
+       for ( l = 0; l < levels; l++ )
+       {
+               frac = range - range * (float)l / ( levels - 1 );
+               for ( c = 0 ; c < 256 - brights ; c++ )
+               {
+                       red = lbmpalette[c * 3];
+                       green = lbmpalette[c * 3 + 1];
+                       blue = lbmpalette[c * 3 + 2];
+
+                       red = (int)( red * frac + 0.5 );
+                       green = (int)( green * frac + 0.5 );
+                       blue = (int)( blue * frac + 0.5 );
+
+//
+// note: 254 instead of 255 because 255 is the transparent color, and we
+// don't want anything remapping to that
+// don't use color 0, because NT can't remap that (or 255)
+//
+                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
+               }
+
+               // fullbrights allways stay the same
+               for ( ; c < 256 ; c++ )
+                       *lump_p++ = c;
+       }
+
+// 66% transparancy table
+       for ( l = 0; l < 255; l++ )
+       {
+               for ( c = 0 ; c < 255 ; c++ )
+               {
+                       red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
+                       green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
+                       blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
+
+                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
+               }
+               *lump_p++ = 255;
+       }
+       for ( c = 0 ; c < 256 ; c++ )
+               *lump_p++ = 255;
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+       WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
+
+       free( cropped );
+}
+
+/*
+   =============================================================================
+
+   MIPTEX GRABBING
+
+   =============================================================================
+ */
+
+byte pixdata[256];
+
+int d_red, d_green, d_blue;
+
+byte palmap[32][32][32];
+qboolean palmap_built;
+
+/*
+   =============
+   FindColor
+   =============
+ */
+int FindColor( int r, int g, int b ){
+       int bestcolor;
+
+       if ( r > 255 ) {
+               r = 255;
+       }
+       if ( r < 0 ) {
+               r = 0;
+       }
+       if ( g > 255 ) {
+               g = 255;
+       }
+       if ( g < 0 ) {
+               g = 0;
+       }
+       if ( b > 255 ) {
+               b = 255;
+       }
+       if ( b < 0 ) {
+               b = 0;
+       }
+#ifndef TABLECOLORS
+       bestcolor = BestColor( r, g, b, 0, 254 );
+#else
+       bestcolor = palmap[r >> 3][g >> 3][b >> 3];
+#endif
+
+       return bestcolor;
+}
+
+
+void BuildPalmap( void ){
+#ifdef TABLECOLORS
+       int r, g, b;
+       int bestcolor;
+
+       if ( palmap_built ) {
+               return;
+       }
+       palmap_built = true;
+
+       for ( r = 4 ; r < 256 ; r += 8 )
+       {
+               for ( g = 4 ; g < 256 ; g += 8 )
+               {
+                       for ( b = 4 ; b < 256 ; b += 8 )
+                       {
+                               bestcolor = BestColor( r, g, b, 1, 254 );
+                               palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
+                       }
+               }
+       }
+#endif
+
+       if ( !colormap_issued ) {
+               Error( "You must issue a $colormap command first" );
+       }
+
+}
+
+/*
+   =============
+   AveragePixels
+   =============
+ */
+byte AveragePixels( int count ){
+       int r,g,b;
+       int i;
+       int vis;
+       int pix;
+       int bestcolor;
+       byte    *pal;
+       int fullbright;
+
+       vis = 0;
+       r = g = b = 0;
+       fullbright = 0;
+       for ( i = 0 ; i < count ; i++ )
+       {
+               pix = pixdata[i];
+
+               r += lbmpalette[pix * 3];
+               g += lbmpalette[pix * 3 + 1];
+               b += lbmpalette[pix * 3 + 2];
+               vis++;
+       }
+
+       r /= vis;
+       g /= vis;
+       b /= vis;
+
+       // error diffusion
+       r += d_red;
+       g += d_green;
+       b += d_blue;
+
+//
+// find the best color
+//
+       bestcolor = FindColor( r, g, b );
+
+       // error diffusion
+       pal = colormap_palette + bestcolor * 3;
+       d_red = r - (int)pal[0];
+       d_green = g - (int)pal[1];
+       d_blue = b - (int)pal[2];
+
+       return bestcolor;
+}
+
+
+typedef enum
+{
+       pt_contents,
+       pt_flags,
+       pt_animvalue,
+       pt_altnamevalue,
+       pt_damagenamevalue,
+       pt_flagvalue,
+       pt_materialvalue,
+       pt_scale,
+       pt_mip,
+       pt_detail,
+       pt_gl,
+       pt_nomip,
+       pt_detailer,
+} parmtype_t;
+
+typedef struct
+{
+       char    *name;
+       int flags;
+       parmtype_t type;
+} mipparm_t;
+
+mipparm_t mipparms[] =
+{
+       // utility content attributes
+       {"pushpull",CONTENTS_PUSHPULL, pt_contents},
+       {"water",   CONTENTS_WATER, pt_contents},
+       {"slime",   CONTENTS_SLIME, pt_contents},       // mildly damaging
+       {"lava",    CONTENTS_LAVA, pt_contents},        // very damaging
+       {"window",  CONTENTS_WINDOW, pt_contents},  // solid, but doesn't eat internal textures
+       {"mist",    CONTENTS_MIST, pt_contents},    // non-solid window
+       {"origin",  CONTENTS_ORIGIN, pt_contents},  // center of rotating brushes
+       {"playerclip",  CONTENTS_PLAYERCLIP, pt_contents},
+       {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
+
+       // utility surface attributes
+       {"hint",    SURF_HINT, pt_flags},
+       {"skip",    SURF_SKIP, pt_flags},
+       {"light",   SURF_LIGHT, pt_flagvalue},      // value is the light quantity
+
+       {"animspeed",SURF_ANIMSPEED, pt_flagvalue},     // value will hold the anim speed in fps
+
+       // texture chaining
+       {"anim",    0,          pt_animvalue},      // animname is the next animation
+       {"alt",     0,          pt_altnamevalue},   // altname is the alternate texture
+       {"damage",  0,          pt_damagenamevalue},    // damagename is the damage texture
+       {"scale",   0,          pt_scale},      // next two values are for scale
+       {"mip",     0,          pt_mip},
+       {"detail",  0,          pt_detail},
+
+       {"GL_ZERO",                 GL_ZERO,                pt_gl},
+       {"GL_ONE",                  GL_ONE,                 pt_gl},
+       {"GL_SRC_COLOR",            GL_SRC_COLOR,           pt_gl},
+       {"GL_ONE_MINUS_SRC_COLOR",  GL_ONE_MINUS_SRC_COLOR, pt_gl},
+       {"GL_DST_COLOR",            GL_DST_COLOR,           pt_gl},
+       {"GL_ONE_MINUS_DST_COLOR",  GL_ONE_MINUS_DST_COLOR, pt_gl},
+       {"GL_SRC_ALPHA",            GL_SRC_ALPHA,           pt_gl},
+       {"GL_ONE_MINUS_SRC_ALPHA",  GL_ONE_MINUS_SRC_ALPHA, pt_gl},
+       {"GL_DST_ALPHA",            GL_DST_ALPHA,           pt_gl},
+       {"GL_ONE_MINUS_DST_ALPHA",  GL_ONE_MINUS_DST_ALPHA, pt_gl},
+       {"GL_SRC_ALPHA_SATURATE",   GL_SRC_ALPHA_SATURATE,  pt_gl},
+
+       // server attributes
+       {"slick",   SURF_SLICK, pt_flags},
+
+       // drawing attributes
+       {"sky",     SURF_SKY, pt_flags},
+       {"warping", SURF_WARP, pt_flags},       // only valid with 64x64 textures
+       {"trans33", SURF_TRANS33, pt_flags},    // translucent should allso set fullbright
+       {"trans66", SURF_TRANS66, pt_flags},
+       {"flowing", SURF_FLOWING, pt_flags},    // flow direction towards angle 0
+       {"nodraw",  SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
+       {"alpha",   SURF_ALPHA_TEXTURE, pt_flags},
+       {"undulate",    SURF_UNDULATE, pt_flags},       // rock surface up and down...
+       {"skyreflect",  SURF_SKYREFLECT, pt_flags},     // liquid will somewhat reflect the sky - not quite finished....
+
+       {"material", SURF_MATERIAL, pt_materialvalue},
+       {"metal",   SURF_TYPE_METAL, pt_flags},
+       {"stone",   SURF_TYPE_STONE, pt_flags},
+       {"wood",    SURF_TYPE_WOOD, pt_flags},
+
+       {"m_nomip", 0, pt_nomip},
+       {"m_detail", 0, pt_detailer},
+
+       {NULL, 0, pt_contents}
+};
+
+/*
+   ==============
+   Cmd_Mip
+
+   $mip filename x y width height <OPTIONS>
+   must be multiples of sixteen
+   SURF_WINDOW
+   ==============
+ */
+
+void Cmd_Mip( void ){
+       int xl,yl,xh,yh,w,h;
+       byte            *dest, *source;
+       int flags, value, contents;
+       mipparm_t       *mp;
+       char lumpname[128];
+       char altname[128];
+       char animname[128];
+       char damagename[128];
+       byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
+       unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
+       materialtype_t  *mat;
+       char filename[1024];
+       unsigned        *destl, *sourcel;
+       int linedelta, x, y;
+       int size;
+       miptex_t        *qtex;
+       miptex32_t      *qtex32;
+       float scale_x, scale_y;
+       int mip_scale;
+       // detail texturing
+       char dt_name[128];
+       float dt_scale_x, dt_scale_y;
+       float dt_u, dt_v;
+       float dt_alpha;
+       int dt_src_blend_mode, dt_dst_blend_mode;
+       int flags2;
+
+
+       GetScriptToken( false );
+       strcpy( lumpname, token );
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       total_x += w;
+       total_y += h;
+       total_textures++;
+
+       if ( ( w & 15 ) || ( h & 15 ) ) {
+               Error( "line %i: miptex sizes must be multiples of 16", scriptline );
+       }
+
+       flags = 0;
+       flags2 = 0;
+       contents = 0;
+       value = 0;
+       mip_scale = 0;
+
+       altname[0] = animname[0] = damagename[0] = 0;
+
+       scale_x = scale_y = 0.5;
+
+       // detail texturing
+       dt_name[0] = 0;
+       dt_scale_x = dt_scale_y = 0.0;
+       dt_u = dt_v = 0.0;
+       dt_alpha = 0.0;
+       dt_src_blend_mode = dt_dst_blend_mode = 0;
+
+       // get optional flags and values
+       while ( ScriptTokenAvailable() )
+       {
+               GetScriptToken( false );
+
+               for ( mp = mipparms ; mp->name ; mp++ )
+               {
+                       if ( !strcmp( mp->name, token ) ) {
+                               switch ( mp->type )
+                               {
+                               case pt_animvalue:
+                                       GetScriptToken( false );    // specify the next animation frame
+                                       strcpy( animname, token );
+                                       break;
+                               case pt_altnamevalue:
+                                       GetScriptToken( false );    // specify the alternate texture
+                                       strcpy( altname, token );
+                                       break;
+                               case pt_damagenamevalue:
+                                       GetScriptToken( false );    // specify the damage texture
+                                       strcpy( damagename, token );
+                                       break;
+                               case pt_flags:
+                                       flags |= mp->flags;
+                                       break;
+                               case pt_contents:
+                                       contents |= mp->flags;
+                                       break;
+                               case pt_flagvalue:
+                                       flags |= mp->flags;
+                                       GetScriptToken( false );    // specify the light value
+                                       value = atoi( token );
+                                       break;
+                               case pt_materialvalue:
+                                       GetScriptToken( false );
+                                       for ( mat = materialtypes ; mat->name ; mat++ )
+                                       {
+                                               if ( !strcmp( mat->name, token ) ) {
+                                                       // assumes SURF_MATERIAL is in top 8 bits
+                                                       flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
+                                                       break;
+                                               }
+                                       }
+                                       break;
+                               case pt_scale:
+                                       GetScriptToken( false );    // specify the x scale
+                                       scale_x = atof( token );
+                                       GetScriptToken( false );    // specify the y scale
+                                       scale_y = atof( token );
+                                       break;
+
+                               case pt_mip:
+                                       mip_scale = 1;
+                                       break;
+
+                               case pt_detailer:
+                                       flags2 |= MIP32_DETAILER_FLAG2;
+                                       break;
+
+                               case pt_nomip:
+                                       flags2 |= MIP32_NOMIP_FLAG2;
+                                       break;
+
+                               case pt_detail:
+                                       GetScriptToken( false );
+                                       strcpy( dt_name, token );
+                                       GetScriptToken( false );
+                                       dt_scale_x = atof( token );
+                                       GetScriptToken( false );
+                                       dt_scale_y = atof( token );
+                                       GetScriptToken( false );
+                                       dt_u = atof( token );
+                                       GetScriptToken( false );
+                                       dt_v = atof( token );
+                                       GetScriptToken( false );
+                                       dt_alpha = atof( token );
+                                       GetScriptToken( false );
+                                       for ( mp = mipparms ; mp->name ; mp++ )
+                                       {
+                                               if ( !strcmp( mp->name, token ) ) {
+                                                       if ( mp->type == pt_gl ) {
+                                                               dt_src_blend_mode = mp->flags;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if ( !mp->name ) {
+                                               Error( "line %i: invalid gl blend mode %s", scriptline, token );
+                                       }
+                                       GetScriptToken( false );
+                                       for ( mp = mipparms ; mp->name ; mp++ )
+                                       {
+                                               if ( !strcmp( mp->name, token ) ) {
+                                                       if ( mp->type == pt_gl ) {
+                                                               dt_dst_blend_mode = mp->flags;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if ( !mp->name ) {
+                                               Error( "line %i: invalid gl blend mode %s", scriptline, token );
+                                       }
+                                       break;
+                               }
+                               break;
+                       }
+               }
+               if ( !mp->name ) {
+                       Error( "line %i: unknown parm %s", scriptline, token );
+               }
+       }
+
+       if ( g_release ) {
+               return; // textures are only released by $maps
+
+       }
+       xh = xl + w;
+       yh = yl + h;
+       if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
+               Error( "line %i image %s: image is too big!", scriptline, lumpname );
+       }
+
+       if ( TrueColorImage ) {
+               if ( xl >= longimagewidth || xh > longimagewidth ||
+                        yl >= longimageheight || yh > longimageheight ) {
+                       Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
+               }
+
+               sourcel = longimage + ( yl * longimagewidth ) + xl;
+               destl = bufferl;
+               linedelta = ( longimagewidth - w );
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *destl++ = *sourcel++;  // RGBA
+                       }
+                       sourcel += linedelta;
+               }
+
+               qtex32 = CreateMip32( bufferl, w, h, &size, true );
+
+               qtex32->flags |= LittleLong( flags );
+               qtex32->flags2 |= LittleLong( flags2 );
+               qtex32->contents = LittleLong( contents );
+               qtex32->value = LittleLong( value );
+               qtex32->scale_x = scale_x;
+               qtex32->scale_y = scale_y;
+               qtex32->mip_scale = mip_scale;
+               sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
+               if ( animname[0] ) {
+                       sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
+               }
+               if ( altname[0] ) {
+                       sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
+               }
+               if ( damagename[0] ) {
+                       sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
+               }
+               if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
+                       sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
+                       qtex32->dt_scale_x = dt_scale_x;
+                       qtex32->dt_scale_y = dt_scale_y;
+                       qtex32->dt_u = dt_u;
+                       qtex32->dt_v = dt_v;
+                       qtex32->dt_alpha = dt_alpha;
+                       qtex32->dt_src_blend_mode = dt_src_blend_mode;
+                       qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
+               }
+
+               //
+               // write it out
+               //
+               sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
+               if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
+                       printf( "writing %s with ALPHA\n", filename );
+               }
+               else{
+                       printf( "writing %s\n", filename );
+               }
+               SaveFile( filename, (byte *)qtex32, size );
+
+               free( qtex32 );
+       }
+       else
+       {
+               if ( xl >= byteimagewidth || xh > byteimagewidth ||
+                        yl >= byteimageheight || yh > byteimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
+               }
+
+               source = byteimage + yl * byteimagewidth + xl;
+               dest = buffer;
+               linedelta = byteimagewidth - w;
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *dest++ = *source++;
+                       }
+                       source += linedelta;
+               }
+
+               qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
+
+               qtex->flags = LittleLong( flags );
+               qtex->contents = LittleLong( contents );
+               qtex->value = LittleLong( value );
+               sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
+               if ( animname[0] ) {
+                       sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
+               }
+
+               //
+               // write it out
+               //
+               sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
+               printf( "writing %s\n", filename );
+               SaveFile( filename, (byte *)qtex, size );
+
+               free( qtex );
+       }
+}
+
+/*
+   ===============
+   Cmd_Mippal
+   ===============
+ */
+void Cmd_Mippal( void ){
+       colormap_issued = true;
+       if ( g_release ) {
+               return;
+       }
+
+       memcpy( colormap_palette, lbmpalette, 768 );
+
+       BuildPalmap();
+}
+
+
+/*
+   ===============
+   Cmd_Mipdir
+   ===============
+ */
+void Cmd_Mipdir( void ){
+       char filename[1024];
+
+       GetScriptToken( false );
+       strcpy( mip_prefix, token );
+       // create the directory if needed
+       sprintf( filename, "%stextures", g_outputDir );
+       Q_mkdir( filename );
+       sprintf( filename, "%stextures/%s", g_outputDir, mip_prefix );
+       Q_mkdir( filename );
+}
+
+
+/*
+   =============================================================================
+
+   ENVIRONMENT MAP GRABBING
+
+   Creates six pcx files from tga files without any palette edge seams
+   also copies the tga files for GL rendering.
+   =============================================================================
+ */
+
+// 3dstudio environment map suffixes
+char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
+
+/*
+   =================
+   Cmd_Environment
+   =================
+ */
+void Cmd_Environment( void ){
+       char name[1024];
+       int i, x, y;
+       byte image[256 * 256];
+       byte    *tga;
+
+       GetScriptToken( false );
+
+       if ( g_release ) {
+               for ( i = 0 ; i < 6 ; i++ )
+               {
+                       sprintf( name, "env/%s%s.pcx", token, suf[i] );
+                       ReleaseFile( name );
+                       sprintf( name, "env/%s%s.tga", token, suf[i] );
+                       ReleaseFile( name );
+               }
+               return;
+       }
+       // get the palette
+       BuildPalmap();
+
+       sprintf( name, "%senv/", gamedir );
+       CreatePath( name );
+
+       // convert the images
+       for ( i = 0 ; i < 6 ; i++ )
+       {
+               sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
+               printf( "loading %s...\n", name );
+               LoadTGA( name, &tga, NULL, NULL );
+
+               for ( y = 0 ; y < 256 ; y++ )
+               {
+                       for ( x = 0 ; x < 256 ; x++ )
+                       {
+                               image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
+                       }
+               }
+               free( tga );
+               sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
+               if ( FileTime( name ) != -1 ) {
+                       printf( "%s already exists, not overwriting.\n", name );
+               }
+               else{
+                       WritePCXfile( name, image, 256, 256, colormap_palette );
+               }
+       }
+}
diff --git a/tools/heretic2/h2data/jointed.c b/tools/heretic2/h2data/jointed.c
new file mode 100644 (file)
index 0000000..de8b802
--- /dev/null
@@ -0,0 +1,548 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <assert.h>
+#include <math.h>
+#include "token.h"
+#include "joints.h"
+#include "angles.h"
+#include "inout.h"
+
+char *SKEL_ROOT_NAMES[] =
+{
+       "RAVEN_SPINE"
+};
+
+char *SKEL_NAMES[] =
+{
+       "RAVEN_WAIST1",
+       "RAVEN_WAIST2",
+       "RAVEN_NECK"
+};
+
+int NAME_OFFSETS[] =
+{
+       0
+};
+
+int numJointsForSkeleton[] =
+{
+       NUM_JOINTS_RAVEN,
+       NUM_JOINTS_BOX
+};
+
+float g_scaling[3];
+float g_rotation[3];
+float g_translation[3];
+
+//==========================================================================
+//
+// LoadHRCClustered
+//
+//==========================================================================
+
+static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
+       int i, j;
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       TK_Beyond( TK_CLUSTERS );
+
+       while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
+       {
+               TK_Require( TK_STRING );
+
+               for ( i = 0; i < numJointsForSkeleton[skelType]; ++i )
+               {
+                       if ( stricmp( tk_String, SKEL_NAMES[NAME_OFFSETS[skelType] + i] ) == 0 ) {
+                               i = -i + numJointsForSkeleton[skelType] - 1;
+
+                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
+
+                               num_verts[i + 1] = tk_IntNumber;
+
+                               clusterList[i] = (int *) SafeMalloc( num_verts[i + 1] * sizeof( int ), "LoadHRCClustered" );
+                               assert( clusterList[i] );
+                               // currently this function is only called by LoadTriangleListClustered, which in turn is only
+                               // called by Cmd_Base in qdata.  This is where the only call to free for this memory is being made.
+
+                               TK_Beyond( TK_LBRACE );
+
+                               for ( j = 0; j < num_verts[i + 1]; ++j )
+                               {
+                                       TK_Require( TK_INTNUMBER );
+                                       clusterList[i][j] = tk_IntNumber;
+                                       TK_Fetch();
+                               }
+
+                               break;
+                       }
+               }
+       }
+
+       num_verts[0] = numJointsForSkeleton[skelType];
+}
+
+static void LoadHRCGlobals( char *fileName ){
+       int i;
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+       TK_Beyond( TK_MODEL );
+
+       TK_Beyond( TK_SCALING );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_scaling[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+
+       TK_Beyond( TK_ROTATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_rotation[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+
+       TK_Beyond( TK_TRANSLATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_translation[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+}
+
+static void ParseVec3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = -tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void LoadHRCJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
+#define MAX_STACK 64
+       int i, j;
+       vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
+       int curCorrespondingJoint[MAX_STACK];
+       int currentStack = 0, stackSize;
+       int baseJoint;
+       float cx, sx, cy, sy, cz, sz;
+       float rx, ry, rz;
+       float x2, y2, z2;
+
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       TK_Beyond( TK_MODEL );
+       TK_Beyond( TK_MODEL );
+
+/*     while(1)
+    {
+        TK_Beyond(TK_MODEL);
+        TK_BeyondRequire(TK_NAME, TK_STRING);
+
+        if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
+            break;
+    }*/
+
+       TK_Beyond( TK_SCALING );
+
+       ParseVec3( curScale[currentStack] );
+
+       TK_Beyond( TK_ROTATION );
+
+       ParseRotation3( curRotation[currentStack] );
+
+       TK_Beyond( TK_TRANSLATION );
+
+       ParseVec3( curTranslation[currentStack] );
+
+       // account for global model translation
+       curTranslation[currentStack][1] += g_translation[0];
+       curTranslation[currentStack][2] += g_translation[1];
+       curTranslation[currentStack][0] += g_translation[2];
+
+       ++currentStack;
+
+       for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
+       {
+               while ( 1 )
+               {
+                       TK_Beyond( TK_MODEL );
+
+//                     TK_BeyondRequire(TK_NAME, TK_STRING);
+
+//                     if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
+                       break;
+
+                       TK_Beyond( TK_SCALING );
+
+                       ParseVec3( curScale[currentStack] );
+
+                       TK_Beyond( TK_ROTATION );
+
+                       ParseRotation3( curRotation[currentStack] );
+
+                       TK_Beyond( TK_TRANSLATION );
+
+                       ParseVec3( curTranslation[currentStack] );
+
+                       curCorrespondingJoint[currentStack] = -1;
+
+                       ++currentStack;
+               }
+
+               TK_Beyond( TK_SCALING );
+
+               ParseVec3( curScale[currentStack] );
+
+               TK_Beyond( TK_ROTATION );
+
+               ParseRotation3( curRotation[currentStack] );
+
+               jointList[i].rotation[1] = curRotation[currentStack][1];
+               jointList[i].rotation[2] = curRotation[currentStack][2];
+               jointList[i].rotation[0] = curRotation[currentStack][0];
+
+               TK_Beyond( TK_TRANSLATION );
+
+               ParseVec3( curTranslation[currentStack] );
+
+               jointList[i].placement.origin[1] = curTranslation[currentStack][1];
+               jointList[i].placement.origin[2] = curTranslation[currentStack][2];
+               jointList[i].placement.origin[0] = curTranslation[currentStack][0];
+
+               jointList[i].placement.direction[1] = 7.5;
+               jointList[i].placement.direction[2] = 0.0;
+               jointList[i].placement.direction[0] = 0.0;
+
+               jointList[i].placement.up[1] = 0.0;
+               jointList[i].placement.up[2] = 7.5;
+               jointList[i].placement.up[0] = 0.0;
+
+               curCorrespondingJoint[currentStack] = i;
+
+               ++currentStack;
+       }
+
+       stackSize = currentStack;
+
+       for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
+       {
+               rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
+               ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
+               rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
+
+               cx = cos( rx );
+               sx = sin( rx );
+
+               cy = cos( ry );
+               sy = sin( ry );
+
+               cz = cos( rz );
+               sz = sin( rz );
+
+               // y-axis rotation for direction
+               x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
+               z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
+               jointList[i].placement.direction[0] = x2;
+               jointList[i].placement.direction[2] = z2;
+
+               // y-axis rotation for up
+               x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
+               z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
+               jointList[i].placement.up[0] = x2;
+               jointList[i].placement.up[2] = z2;
+
+               // z-axis rotation for direction
+               x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
+               y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
+               jointList[i].placement.direction[0] = x2;
+               jointList[i].placement.direction[1] = y2;
+
+               // z-axis rotation for up
+               x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
+               y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
+               jointList[i].placement.up[0] = x2;
+               jointList[i].placement.up[1] = y2;
+
+               // x-axis rotation for direction vector
+               y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
+               z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
+               jointList[i].placement.direction[1] = y2;
+               jointList[i].placement.direction[2] = z2;
+
+               // x-axis rotation for up vector
+               y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
+               z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
+               jointList[i].placement.up[1] = y2;
+               jointList[i].placement.up[2] = z2;
+
+               // translate to position in model
+               jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
+               jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
+               jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
+
+               // translate to position in model
+               jointList[i].placement.up[0] += jointList[i].placement.origin[0];
+               jointList[i].placement.up[1] += jointList[i].placement.origin[1];
+               jointList[i].placement.up[2] += jointList[i].placement.origin[2];
+       }
+
+       baseJoint = NUM_JOINTS_RAVEN;
+
+       for ( i = stackSize /*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i )
+       {
+
+               rx = curRotation[i - 1][0] * ANGLE_TO_RAD;
+               ry = curRotation[i - 1][1] * ANGLE_TO_RAD;
+               rz = curRotation[i - 1][2] * ANGLE_TO_RAD;
+
+               cx = cos( rx );
+               sx = sin( rx );
+
+               cy = cos( ry );
+               sy = sin( ry );
+
+               cz = cos( rz );
+               sz = sin( rz );
+
+               for ( j = i - 1; j < stackSize - 1; ++j )
+               {
+                       // y-axis rotation for origin
+                       x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
+                       z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
+                       jointList[j].placement.origin[0] = x2;
+                       jointList[j].placement.origin[2] = z2;
+
+                       // y-axis rotation for direction
+                       x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
+                       z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
+                       jointList[j].placement.direction[0] = x2;
+                       jointList[j].placement.direction[2] = z2;
+
+                       // y-axis rotation for up
+                       x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
+                       z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
+                       jointList[j].placement.up[0] = x2;
+                       jointList[j].placement.up[2] = z2;
+
+                       // z-axis rotation for origin
+                       x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
+                       y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
+                       jointList[j].placement.origin[0] = x2;
+                       jointList[j].placement.origin[1] = y2;
+
+                       // z-axis rotation for direction
+                       x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
+                       y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
+                       jointList[j].placement.direction[0] = x2;
+                       jointList[j].placement.direction[1] = y2;
+
+                       // z-axis rotation for up
+                       x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
+                       y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
+                       jointList[j].placement.up[0] = x2;
+                       jointList[j].placement.up[1] = y2;
+
+                       // x-axis rotation for origin
+                       y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
+                       z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
+                       jointList[j].placement.origin[1] = y2;
+                       jointList[j].placement.origin[2] = z2;
+
+                       // x-axis rotation for direction vector
+                       y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
+                       z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
+                       jointList[j].placement.direction[1] = y2;
+                       jointList[j].placement.direction[2] = z2;
+
+                       // x-axis rotation for up vector
+                       y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
+                       z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
+                       jointList[j].placement.up[1] = y2;
+                       jointList[j].placement.up[2] = z2;
+
+                       if ( curCorrespondingJoint[j + 1] != -1 ) {
+                               // translate origin
+                               jointList[j].placement.origin[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.origin[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.origin[2] += curTranslation[i - 1][2];
+
+                               // translate back to local coord
+                               jointList[j].placement.direction[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.direction[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.direction[2] += curTranslation[i - 1][2];
+
+                               // translate back to local coord
+                               jointList[j].placement.up[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.up[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.up[2] += curTranslation[i - 1][2];
+                       }
+               }
+       }
+}
+
+void LoadGlobals( char *fileName ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCGlobals( InputFileName );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC match.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+                       printf( "\n" );
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCGlobals( fileName );
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC match.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+                       printf( "\n" );
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCClustered( fileName, clusterList, num_verts, skelType );
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+void LoadJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCJointList( InputFileName, jointList, skelType );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+                       printf( "\n" );
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCJointList( fileName, jointList, skelType );
+
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
diff --git a/tools/heretic2/h2data/jointed.h b/tools/heretic2/h2data/jointed.h
new file mode 100644 (file)
index 0000000..264d317
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _JOINTED_H
+#define _JOINTED_H
+
+#include "joints.h"
+
+void LoadGlobals( char *fileName );
+void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skel_type );
+void LoadJointList( char *fileName, struct QDataJoint_s *jointList, int num_verts );
+
+#define NUM_CLUSTERS 8
+
+#define NOT_JOINTED -1
+
+#endif //_JOINTED_H
diff --git a/tools/heretic2/h2data/joints.h b/tools/heretic2/h2data/joints.h
new file mode 100644 (file)
index 0000000..f8e64bf
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef JOINTS_H
+#define JOINTS_H
+
+#include "globaldefs.h"
+
+#ifdef _HERETIC2_
+#include "angles.h"
+#endif
+
+//typedef float vec3_t[3];
+//typedef unsigned char byte;
+
+#if !GDEF_OS_WINDOWS
+#define stricmp strcasecmp
+#define strcmpi strcasecmp
+#endif
+
+typedef struct Placement_s
+{
+       vec3_t origin;
+       vec3_t direction;
+       vec3_t up;
+} Placement_t;
+
+#if 1
+typedef struct QDataJoint_s
+{
+       Placement_t placement;
+       vec3_t rotation;
+} QDataJoint_t;
+#endif
+
+typedef struct ArrayedListNode_s
+{
+       int data;
+       int next;
+       int inUse;
+} ArrayedListNode_t;
+
+#define ARRAYEDLISTNODE_NULL -1
+
+typedef struct JointAngles_s
+{
+       float angles[3];
+       int children;
+       int created;
+} JointAngles_t;
+
+typedef struct JointAngles2_s
+{
+       float angles[3];
+       int children;
+       int changed[3];
+       int inUse;
+} JointAngles2_t;
+
+#define MAX_MODELJOINTS         256
+#define MAX_MODELJOINTNODES     255
+
+extern JointAngles_t jointAngles[MAX_MODELJOINTS];
+extern JointAngles2_t jointAngles2[MAX_MODELJOINTS];
+
+extern ArrayedListNode_t jointAngleNodes[MAX_MODELJOINTNODES];
+
+// Skeletal structures enums
+enum {
+       SKEL_RAVEN = 0,
+       SKEL_BOX,
+       NUM_SKELETONS
+};
+
+// Raven Skeletal structures enums
+enum {
+       RAVEN_WAIST1 = 0,
+       RAVEN_WAIST2 = 1,
+       RAVEN_HEAD = 2,
+       NUM_JOINTS_RAVEN
+};
+
+// Box Skeletal structures enums
+enum {
+       BOX_CENTER = 0,
+       NUM_JOINTS_BOX
+};
+
+extern int numJointsForSkeleton[];
+extern char *RAVEN_SKEL_NAMES[];
+
+#define J_NEW_SKELETON      0x00001000
+#define J_YAW_CHANGED       0x00002000
+#define J_PITCH_CHANGED     0x00004000
+#define J_ROLL_CHANGED      0x00008000
+#define MAX_JOINTS          0x00000fff
+/*
+   inline int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
+   {   // yeah, I know this is a sucky, inefficient way to do this, but I didn't feel like taking the time to write a real resource manager in C
+    int i;
+
+    for(i = 0; i < max; ++i)
+    {
+        if(!nodeArray[i].inUse)
+        {
+            nodeArray[i].inUse = 1;
+            return i;
+        }
+    }
+
+    assert(0);
+    return -1;
+   }
+
+   inline void FreeNode(ArrayedListNode_t *nodeArray, int index)
+   {
+    nodeArray[index].inUse = 0;
+   }
+ */
+int CreateSkeleton( int structure );
+void CreateSkeletonAtIndex( int structure, int index );
+void FreeSkeleton( int structure, int index );
+void SetJointAngle( int jointIndex, int angleIndex, float angle );
+float ModifyJointAngle( int jointIndex, int angleIndex, float deltaAngle );
+int ZeroJointAngle( int jointIndex, int angleIndex, float angVel );
+int ApplyAngVelToJoint( int jointIndex, int angleIndex, float angVel, float destAng );
+
+#endif
diff --git a/tools/heretic2/h2data/models.c b/tools/heretic2/h2data/models.c
new file mode 100644 (file)
index 0000000..244f24a
--- /dev/null
@@ -0,0 +1,2041 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "qdata.h"
+#include <assert.h>
+#include "jointed.h"
+#include "fmodel.h"
+
+//=================================================================
+
+typedef struct
+{
+       int numnormals;
+       vec3_t normalsum;
+} vertexnormals_t;
+
+typedef struct
+{
+       vec3_t v;
+       int lightnormalindex;
+} trivert_t;
+
+typedef struct
+{
+       vec3_t mins, maxs;
+       char name[16];
+       trivert_t v[MAX_VERTS];
+       QDataJoint_t joints[NUM_CLUSTERS];    // ,this
+} frame_t;
+
+// ,and all of this should get out of here, need to use new stuff in fmodels instead
+
+typedef struct IntListNode_s
+{
+       int data;
+       struct IntListNode_s *next;
+} IntListNode_t;  // gaak
+
+typedef struct
+{
+       float scale[3];         // multiply byte verts by this
+       float translate[3];         // then add this
+} PartialAliasFrame_t;
+
+int jointed;
+int clustered;
+
+int *clusters[NUM_CLUSTERS];
+IntListNode_t *vertLists[NUM_CLUSTERS];
+int num_verts[NUM_CLUSTERS + 1];
+int new_num_verts[NUM_CLUSTERS + 1];
+
+// end that
+
+//================================================================
+
+frame_t g_frames[MAX_FRAMES];
+//frame_t              *g_frames;
+
+static dmdl_t model;
+
+
+float scale_up;                 // set by $scale
+vec3_t adjust;                  // set by $origin
+int g_fixedwidth, g_fixedheight;            // set by $skinsize
+
+
+//
+// base frame info
+//
+dstvert_t base_st[MAX_VERTS];
+dtriangle_t triangles[MAX_TRIANGLES];
+
+static int triangle_st[MAX_TRIANGLES][3][2];
+
+// the command list holds counts, s/t values, and xyz indexes
+// that are valid for every frame
+int commands[16384];
+int numcommands;
+int numglverts;
+int used[MAX_TRIANGLES];
+
+char g_skins[MAX_MD2SKINS][64];
+
+char cdarchive[1024];
+char cdpartial[1024];
+char cddir[1024];
+
+char modelname[64];         // empty unless $modelname issued (players)
+
+extern char        *g_outputDir;
+
+#define NUMVERTEXNORMALS    162
+
+float avertexnormals[NUMVERTEXNORMALS][3] =
+{
+       #include "anorms.h"
+};
+
+unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768];
+
+FILE    *headerouthandle = NULL;
+
+//==============================================================
+
+/*
+   ===============
+   ClearModel
+   ===============
+ */
+static void ClearModel( void ){
+       memset( &model, 0, sizeof( model ) );
+
+       modelname[0] = 0;
+       jointed = NOT_JOINTED;
+       clustered = 0;
+       scale_up = 1.0;
+       VectorCopy( vec3_origin, adjust );
+       g_fixedwidth = g_fixedheight = 0;
+       g_skipmodel = false;
+}
+
+
+void H_printf( char *fmt, ... ){
+       va_list argptr;
+       char name[1024];
+
+       if ( !headerouthandle ) {
+               sprintf( name, "%s/tris.h", cddir );
+               headerouthandle = SafeOpenWrite( name );
+               fprintf( headerouthandle, "// %s\n\n", cddir );
+               fprintf( headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n" );
+       }
+
+       va_start( argptr, fmt );
+       vfprintf( headerouthandle, fmt, argptr );
+       va_end( argptr );
+}
+
+#if 1
+/*
+   ============
+   WriteModelFile
+   ============
+ */
+void WriteCommonModelFile( FILE *modelouthandle, PartialAliasFrame_t *outFrames ){
+       int i;
+       dmdl_t modeltemp;
+       int j, k;
+       frame_t         *in;
+       daliasframe_t   *out;
+       byte buffer[MAX_VERTS * 4 + 128];
+       float v;
+       int c_on, c_off;
+
+       model.version = ALIAS_VERSION;
+       model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
+       model.num_glcmds = numcommands;
+       model.ofs_skins = sizeof( dmdl_t );
+       model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
+       model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
+       model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
+       model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
+       model.ofs_end = model.ofs_glcmds + model.num_glcmds * sizeof( int );
+       //
+       // write out the model header
+       //
+       for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
+               ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
+
+       SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
+
+       //
+       // write out the skin names
+       //
+       SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
+
+       //
+       // write out the texture coordinates
+       //
+       c_on = c_off = 0;
+       for ( i = 0 ; i < model.num_st ; i++ )
+       {
+               base_st[i].s = LittleShort( base_st[i].s );
+               base_st[i].t = LittleShort( base_st[i].t );
+       }
+
+       SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
+
+       //
+       // write out the triangles
+       //
+       for ( i = 0 ; i < model.num_tris ; i++ )
+       {
+               int j;
+               dtriangle_t tri;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
+                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
+               }
+
+               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
+       }
+
+       //
+       // write out the frames
+       //
+       for ( i = 0 ; i < model.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+               out = (daliasframe_t *)buffer;
+
+               strcpy( out->name, in->name );
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
+                       out->translate[j] = in->mins[j];
+
+                       if ( outFrames ) {
+                               outFrames[i].scale[j] = out->scale[j];
+                               outFrames[i].translate[j] = out->translate[j];
+                       }
+               }
+
+               for ( j = 0 ; j < model.num_xyz ; j++ )
+               {
+                       // all of these are byte values, so no need to deal with endianness
+                       out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               // scale to byte values & min/max check
+                               v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
+
+                               // clamp, so rounding doesn't wrap from 255.6 to 0
+                               if ( v > 255.0 ) {
+                                       v = 255.0;
+                               }
+                               if ( v < 0 ) {
+                                       v = 0;
+                               }
+                               out->verts[j].v[k] = v;
+                       }
+               }
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       out->scale[j] = LittleFloat( out->scale[j] );
+                       out->translate[j] = LittleFloat( out->translate[j] );
+               }
+
+               SafeWrite( modelouthandle, out, model.framesize );
+       }
+
+       //
+       // write out glcmds
+       //
+       SafeWrite( modelouthandle, commands, numcommands * 4 );
+}
+
+/*
+   ============
+   WriteModelFile
+   ============
+ */
+void WriteModelFile( FILE *modelouthandle ){
+       model.ident = IDALIASHEADER;
+
+       WriteCommonModelFile( modelouthandle, NULL );
+}
+
+/*
+   ============
+   WriteJointedModelFile
+   ============
+ */
+void WriteJointedModelFile( FILE *modelouthandle ){
+       int i;
+       int j, k;
+       frame_t         *in;
+       float v;
+       IntListNode_t   *current, *toFree;
+       PartialAliasFrame_t outFrames[MAX_FRAMES];
+
+       model.ident = IDJOINTEDALIASHEADER;
+
+       WriteCommonModelFile( modelouthandle, outFrames );
+
+       // Skeletal Type
+       SafeWrite( modelouthandle, &jointed, sizeof( int ) );
+
+       // number of joints
+       SafeWrite( modelouthandle, &numJointsForSkeleton[jointed], sizeof( int ) );
+
+       // number of verts in each cluster
+       SafeWrite( modelouthandle, &new_num_verts[1], sizeof( int ) * numJointsForSkeleton[jointed] );
+
+       // cluster verts
+       for ( i = 0; i < new_num_verts[0]; ++i )
+       {
+               current = vertLists[i];
+               while ( current )
+               {
+                       SafeWrite( modelouthandle, &current->data, sizeof( int ) );
+                       toFree = current;
+                       current = current->next;
+                       free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+               }
+       }
+
+       for ( i = 0 ; i < model.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+
+               for ( j = 0 ; j < new_num_verts[0]; ++j )
+               {
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               // scale to byte values & min/max check
+                               v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                               // clamp, so rounding doesn't wrap from 255.6 to 0
+                               if ( v > 255.0 ) {
+                                       v = 255.0;
+                               }
+
+                               if ( v < 0 ) {
+                                       v = 0;
+                               }
+
+                               // write out origin as a float (there's only a few per model, so it's not really
+                               // a size issue)
+                               SafeWrite( modelouthandle, &v, sizeof( float ) );
+                       }
+
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                               // clamp, so rounding doesn't wrap from 255.6 to 0
+                               if ( v > 255.0 ) {
+                                       v = 255.0;
+                               }
+
+                               if ( v < 0 ) {
+                                       v = 0;
+                               }
+
+                               // write out origin as a float (there's only a few per model, so it's not really
+                               // a size issue)
+                               SafeWrite( modelouthandle, &v, sizeof( float ) );
+                       }
+
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
+
+                               // clamp, so rounding doesn't wrap from 255.6 to 0
+                               if ( v > 255.0 ) {
+                                       v = 255.0;
+                               }
+
+                               if ( v < 0 ) {
+                                       v = 0;
+                               }
+
+                               // write out origin as a float (there's only a few per model, so it's not really
+                               // a size issue)
+                               SafeWrite( modelouthandle, &v, sizeof( float ) );
+                       }
+               }
+       }
+}
+#else
+/*
+   ============
+   WriteModelFile
+   ============
+ */
+static void WriteModelFile( FILE *modelouthandle ){
+       int i;
+       dmdl_t modeltemp;
+       int j, k;
+       frame_t         *in;
+       daliasframe_t   *out;
+       byte buffer[MAX_VERTS * 4 + 128];
+       float v;
+       int c_on, c_off;
+
+       model.ident = IDALIASHEADER;
+       model.version = ALIAS_VERSION;
+       model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
+       model.num_glcmds = numcommands;
+       model.ofs_skins = sizeof( dmdl_t );
+       model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
+       model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
+       model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
+       model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
+       model.ofs_end = model.ofs_glcmds + model.num_glcmds * 4;
+
+       //
+       // write out the model header
+       //
+       for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
+               ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
+
+       SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
+
+       //
+       // write out the skin names
+       //
+       SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
+
+       //
+       // write out the texture coordinates
+       //
+       c_on = c_off = 0;
+       for ( i = 0 ; i < model.num_st ; i++ )
+       {
+               base_st[i].s = LittleShort( base_st[i].s );
+               base_st[i].t = LittleShort( base_st[i].t );
+       }
+
+       SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
+
+       //
+       // write out the triangles
+       //
+       for ( i = 0 ; i < model.num_tris ; i++ )
+       {
+               int j;
+               dtriangle_t tri;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
+                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
+               }
+
+               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
+       }
+
+       //
+       // write out the frames
+       //
+       for ( i = 0 ; i < model.num_frames ; i++ )
+       {
+               in = &g_frames[i];
+               out = (daliasframe_t *)buffer;
+
+               strcpy( out->name, in->name );
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
+                       out->translate[j] = in->mins[j];
+               }
+
+               for ( j = 0 ; j < model.num_xyz ; j++ )
+               {
+                       // all of these are byte values, so no need to deal with endianness
+                       out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+                       for ( k = 0 ; k < 3 ; k++ )
+                       {
+                               // scale to byte values & min/max check
+                               v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
+
+                               // clamp, so rounding doesn't wrap from 255.6 to 0
+                               if ( v > 255.0 ) {
+                                       v = 255.0;
+                               }
+                               if ( v < 0 ) {
+                                       v = 0;
+                               }
+                               out->verts[j].v[k] = v;
+                       }
+               }
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       out->scale[j] = LittleFloat( out->scale[j] );
+                       out->translate[j] = LittleFloat( out->translate[j] );
+               }
+
+               SafeWrite( modelouthandle, out, model.framesize );
+       }
+
+       //
+       // write out glcmds
+       //
+       SafeWrite( modelouthandle, commands, numcommands * 4 );
+}
+#endif
+
+/*
+   ===============
+   FinishModel
+   ===============
+ */
+void FinishModel( void ){
+       FILE        *modelouthandle;
+       int i;
+       char name[1024];
+
+       if ( !model.num_frames ) {
+               return;
+       }
+
+//
+// copy to release directory tree if doing a release build
+//
+       if ( g_release ) {
+               if ( modelname[0] ) {
+                       sprintf( name, "%s", modelname );
+               }
+               else{
+                       sprintf( name, "%s/tris.md2", cdpartial );
+               }
+               ReleaseFile( name );
+
+               for ( i = 0 ; i < model.num_skins ; i++ )
+               {
+                       ReleaseFile( g_skins[i] );
+               }
+               model.num_frames = 0;
+               return;
+       }
+
+//
+// write the model output file
+//
+       if ( modelname[0] ) {
+               sprintf( name, "%s%s", g_outputDir, modelname );
+       }
+       else{
+               sprintf( name, "%s/tris.md2", g_outputDir );
+       }
+       printf( "saving to %s\n", name );
+       CreatePath( name );
+       modelouthandle = SafeOpenWrite( name );
+
+#if 1
+       if ( jointed != NOT_JOINTED ) {
+               WriteJointedModelFile( modelouthandle );
+       }
+       else
+#endif
+       WriteModelFile( modelouthandle );
+
+       printf( "%3dx%3d skin\n", model.skinwidth, model.skinheight );
+       printf( "First frame boundaries:\n" );
+       printf( "       minimum x: %3f\n", g_frames[0].mins[0] );
+       printf( "       maximum x: %3f\n", g_frames[0].maxs[0] );
+       printf( "       minimum y: %3f\n", g_frames[0].mins[1] );
+       printf( "       maximum y: %3f\n", g_frames[0].maxs[1] );
+       printf( "       minimum z: %3f\n", g_frames[0].mins[2] );
+       printf( "       maximum z: %3f\n", g_frames[0].maxs[2] );
+       printf( "%4d vertices\n", model.num_xyz );
+       printf( "%4d triangles\n", model.num_tris );
+       printf( "%4d frame\n", model.num_frames );
+       printf( "%4d glverts\n", numglverts );
+       printf( "%4d glcmd\n", model.num_glcmds );
+       printf( "%4d skins\n", model.num_skins );
+       printf( "file size: %d\n", (int)ftell( modelouthandle ) );
+       printf( "---------------------\n" );
+
+       fclose( modelouthandle );
+
+       // finish writing header file
+       H_printf( "\n" );
+
+       // scale_up is usefull to allow step distances to be adjusted
+       H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up );
+
+       fclose( headerouthandle );
+       headerouthandle = NULL;
+}
+
+
+/*
+   =================================================================
+
+   ALIAS MODEL DISPLAY LIST GENERATION
+
+   =================================================================
+ */
+
+int strip_xyz[128];
+int strip_st[128];
+int strip_tris[128];
+int stripcount;
+
+/*
+   ================
+   StripLength
+   ================
+ */
+static int  StripLength( int starttri, int startv ){
+       int m1, m2;
+       int st1, st2;
+       int j;
+       dtriangle_t *last, *check;
+       int k;
+
+       used[starttri] = 2;
+
+       last = &triangles[starttri];
+
+       strip_xyz[0] = last->index_xyz[( startv ) % 3];
+       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
+       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
+       strip_st[0] = last->index_st[( startv ) % 3];
+       strip_st[1] = last->index_st[( startv + 1 ) % 3];
+       strip_st[2] = last->index_st[( startv + 2 ) % 3];
+
+       strip_tris[0] = starttri;
+       stripcount = 1;
+
+       m1 = last->index_xyz[( startv + 2 ) % 3];
+       st1 = last->index_st[( startv + 2 ) % 3];
+       m2 = last->index_xyz[( startv + 1 ) % 3];
+       st2 = last->index_st[( startv + 1 ) % 3];
+
+       // look for a matching triangle
+nexttri:
+       for ( j = starttri + 1, check = &triangles[starttri + 1]
+                 ; j < model.num_tris ; j++, check++ )
+       {
+               for ( k = 0 ; k < 3 ; k++ )
+               {
+                       if ( check->index_xyz[k] != m1 ) {
+                               continue;
+                       }
+                       if ( check->index_st[k] != st1 ) {
+                               continue;
+                       }
+                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
+                               continue;
+                       }
+                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
+                               continue;
+                       }
+
+                       // this is the next part of the fan
+
+                       // if we can't use this triangle, this tristrip is done
+                       if ( used[j] ) {
+                               goto done;
+                       }
+
+                       // the new edge
+                       if ( stripcount & 1 ) {
+                               m2 = check->index_xyz[ ( k + 2 ) % 3 ];
+                               st2 = check->index_st[ ( k + 2 ) % 3 ];
+                       }
+                       else
+                       {
+                               m1 = check->index_xyz[ ( k + 2 ) % 3 ];
+                               st1 = check->index_st[ ( k + 2 ) % 3 ];
+                       }
+
+                       strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ];
+                       strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ];
+                       strip_tris[stripcount] = j;
+                       stripcount++;
+
+                       used[j] = 2;
+                       goto nexttri;
+               }
+       }
+done:
+
+       // clear the temp used flags
+       for ( j = starttri + 1 ; j < model.num_tris ; j++ )
+               if ( used[j] == 2 ) {
+                       used[j] = 0;
+               }
+
+       return stripcount;
+}
+
+
+/*
+   ===========
+   FanLength
+   ===========
+ */
+static int  FanLength( int starttri, int startv ){
+       int m1, m2;
+       int st1, st2;
+       int j;
+       dtriangle_t *last, *check;
+       int k;
+
+       used[starttri] = 2;
+
+       last = &triangles[starttri];
+
+       strip_xyz[0] = last->index_xyz[( startv ) % 3];
+       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
+       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
+       strip_st[0] = last->index_st[( startv ) % 3];
+       strip_st[1] = last->index_st[( startv + 1 ) % 3];
+       strip_st[2] = last->index_st[( startv + 2 ) % 3];
+
+       strip_tris[0] = starttri;
+       stripcount = 1;
+
+       m1 = last->index_xyz[( startv + 0 ) % 3];
+       st1 = last->index_st[( startv + 0 ) % 3];
+       m2 = last->index_xyz[( startv + 2 ) % 3];
+       st2 = last->index_st[( startv + 2 ) % 3];
+
+
+       // look for a matching triangle
+nexttri:
+       for ( j = starttri + 1, check = &triangles[starttri + 1]
+                 ; j < model.num_tris ; j++, check++ )
+       {
+               for ( k = 0 ; k < 3 ; k++ )
+               {
+                       if ( check->index_xyz[k] != m1 ) {
+                               continue;
+                       }
+                       if ( check->index_st[k] != st1 ) {
+                               continue;
+                       }
+                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
+                               continue;
+                       }
+                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
+                               continue;
+                       }
+
+                       // this is the next part of the fan
+
+                       // if we can't use this triangle, this tristrip is done
+                       if ( used[j] ) {
+                               goto done;
+                       }
+
+                       // the new edge
+                       m2 = check->index_xyz[ ( k + 2 ) % 3 ];
+                       st2 = check->index_st[ ( k + 2 ) % 3 ];
+
+                       strip_xyz[stripcount + 2] = m2;
+                       strip_st[stripcount + 2] = st2;
+                       strip_tris[stripcount] = j;
+                       stripcount++;
+
+                       used[j] = 2;
+                       goto nexttri;
+               }
+       }
+done:
+
+       // clear the temp used flags
+       for ( j = starttri + 1 ; j < model.num_tris ; j++ )
+               if ( used[j] == 2 ) {
+                       used[j] = 0;
+               }
+
+       return stripcount;
+}
+
+
+
+/*
+   ================
+   BuildGlCmds
+
+   Generate a list of trifans or strips
+   for the model, which holds for all frames
+   ================
+ */
+static void BuildGlCmds( void ){
+       int i, j, k;
+       int startv;
+       float s, t;
+       int len, bestlen, besttype;
+       int best_xyz[1024];
+       int best_st[1024];
+       int best_tris[1024];
+       int type;
+
+       //
+       // build tristrips
+       //
+       numcommands = 0;
+       numglverts = 0;
+       memset( used, 0, sizeof( used ) );
+       for ( i = 0 ; i < model.num_tris ; i++ )
+       {
+               // pick an unused triangle and start the trifan
+               if ( used[i] ) {
+                       continue;
+               }
+
+               bestlen = 0;
+               for ( type = 0 ; type < 2 ; type++ )
+//     type = 1;
+               {
+                       for ( startv = 0 ; startv < 3 ; startv++ )
+                       {
+                               if ( type == 1 ) {
+                                       len = StripLength( i, startv );
+                               }
+                               else{
+                                       len = FanLength( i, startv );
+                               }
+                               if ( len > bestlen ) {
+                                       besttype = type;
+                                       bestlen = len;
+                                       for ( j = 0 ; j < bestlen + 2 ; j++ )
+                                       {
+                                               best_st[j] = strip_st[j];
+                                               best_xyz[j] = strip_xyz[j];
+                                       }
+                                       for ( j = 0 ; j < bestlen ; j++ )
+                                               best_tris[j] = strip_tris[j];
+                               }
+                       }
+               }
+
+               // mark the tris on the best strip/fan as used
+               for ( j = 0 ; j < bestlen ; j++ )
+                       used[best_tris[j]] = 1;
+
+               if ( besttype == 1 ) {
+                       commands[numcommands++] = ( bestlen + 2 );
+               }
+               else{
+                       commands[numcommands++] = -( bestlen + 2 );
+               }
+
+               numglverts += bestlen + 2;
+
+               for ( j = 0 ; j < bestlen + 2 ; j++ )
+               {
+                       // emit a vertex into the reorder buffer
+                       k = best_st[j];
+
+                       // emit s/t coords into the commands stream
+                       s = base_st[k].s;
+                       t = base_st[k].t;
+
+                       s = ( s + 0.5 ) / model.skinwidth;
+                       t = ( t + 0.5 ) / model.skinheight;
+
+                       *(float *)&commands[numcommands++] = s;
+                       *(float *)&commands[numcommands++] = t;
+                       *(int *)&commands[numcommands++] = best_xyz[j];
+               }
+       }
+
+       commands[numcommands++] = 0;        // end of list marker
+}
+
+
+/*
+   ===============================================================
+
+   BASE FRAME SETUP
+
+   ===============================================================
+ */
+
+/*
+   ============
+   BuildST
+
+   Builds the triangle_st array for the base frame and
+   model.skinwidth / model.skinheight
+
+   FIXME: allow this to be loaded from a file for
+   arbitrary mappings
+   ============
+ */
+#if 0
+static void OldBuildST( triangle_t *ptri, int numtri ){
+       int i, j;
+       int width, height, iwidth, iheight, swidth;
+       float basex, basey;
+       float s_scale, t_scale;
+       float scale;
+       vec3_t mins, maxs;
+       float       *pbasevert;
+       vec3_t vtemp1, vtemp2, normal;
+
+       //
+       // find bounds of all the verts on the base frame
+       //
+       ClearBounds( mins, maxs );
+
+       for ( i = 0 ; i < numtri ; i++ )
+               for ( j = 0 ; j < 3 ; j++ )
+                       AddPointToBounds( ptri[i].verts[j], mins, maxs );
+
+       for ( i = 0 ; i < 3 ; i++ )
+       {
+               mins[i] = floor( mins[i] );
+               maxs[i] = ceil( maxs[i] );
+       }
+
+       width = maxs[0] - mins[0];
+       height = maxs[2] - mins[2];
+
+       if ( !g_fixedwidth ) { // old style
+               scale = 8;
+               if ( width * scale >= 150 ) {
+                       scale = 150.0 / width;
+               }
+               if ( height * scale >= 190 ) {
+                       scale = 190.0 / height;
+               }
+
+               s_scale = t_scale = scale;
+
+               iwidth = ceil( width * s_scale );
+               iheight = ceil( height * t_scale );
+
+               iwidth += 4;
+               iheight += 4;
+       }
+       else
+       {   // new style
+               iwidth = g_fixedwidth / 2;
+               iheight = g_fixedheight;
+
+               s_scale = (float)( iwidth - 4 ) / width;
+               t_scale = (float)( iheight - 4 ) / height;
+       }
+
+//
+// determine which side of each triangle to map the texture to
+//
+       for ( i = 0 ; i < numtri ; i++ )
+       {
+               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+               CrossProduct( vtemp1, vtemp2, normal );
+
+               if ( normal[1] > 0 ) {
+                       basex = iwidth + 2;
+               }
+               else
+               {
+                       basex = 2;
+               }
+               basey = 2;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       pbasevert = ptri[i].verts[j];
+
+                       triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
+                       triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
+               }
+       }
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+       swidth = iwidth * 2;
+       model.skinwidth = ( swidth + 3 ) & ~3;
+       model.skinheight = iheight;
+}
+#endif
+
+//==========================================================================
+//
+// DrawScreen
+//
+//==========================================================================
+
+void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ){
+       int i;
+       byte *scrpos;
+       char buffer[256];
+
+       // Divider
+       scrpos = &pic[( INFO_Y - 2 ) * SKINPAGE_WIDTH];
+       for ( i = 0; i < SKINPAGE_WIDTH; i++ )
+       {
+               *scrpos++ = 255;
+       }
+
+       sprintf( buffer, "GENSKIN:  " );
+       DrawTextChar( 16, INFO_Y, buffer );
+
+       sprintf( buffer, "( %03d * %03d )   SCALE %f %f, SKINWIDTH %d,"
+                                        " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth * 2, (int)iheight );
+       DrawTextChar( 80, INFO_Y, buffer );
+}
+
+/*
+   ============
+   BuildST
+
+   Builds the triangle_st array for the base frame and
+   model.skinwidth / model.skinheight
+
+   FIXME: allow this to be loaded from a file for
+   arbitrary mappings
+   ============
+ */
+void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
+       int i, j;
+       int width, height, iwidth, iheight, swidth;
+       float basex, basey;
+       float scale;
+       vec3_t mins, maxs;
+       float       *pbasevert;
+       vec3_t vtemp1, vtemp2, normal;
+       float s_scale, t_scale;
+       float scWidth;
+       float scHeight;
+
+       //
+       // find bounds of all the verts on the base frame
+       //
+       ClearBounds( mins, maxs );
+
+       for ( i = 0 ; i < numtri ; i++ )
+               for ( j = 0 ; j < 3 ; j++ )
+                       AddPointToBounds( ptri[i].verts[j], mins, maxs );
+
+       for ( i = 0 ; i < 3 ; i++ )
+       {
+               mins[i] = floor( mins[i] );
+               maxs[i] = ceil( maxs[i] );
+       }
+
+       width = maxs[0] - mins[0];
+       height = maxs[2] - mins[2];
+
+
+       scWidth = ( ScaleWidth / 2 ) * SCALE_ADJUST_FACTOR;
+       scHeight = ScaleHeight * SCALE_ADJUST_FACTOR;
+
+       scale = scWidth / width;
+
+       if ( height * scale >= scHeight ) {
+               scale = scHeight / height;
+       }
+
+       iwidth = ceil( width * scale ) + 4;
+       iheight = ceil( height * scale ) + 4;
+
+       s_scale = (float)( iwidth - 4 ) / width;
+       t_scale = (float)( iheight - 4 ) / height;
+       t_scale = s_scale;
+
+       if ( DrawSkin ) {
+               DrawScreen( s_scale, t_scale, iwidth, iheight );
+       }
+
+
+/*     if (!g_fixedwidth)
+    {  // old style
+        scale = 8;
+        if (width*scale >= 150)
+            scale = 150.0 / width;
+        if (height*scale >= 190)
+            scale = 190.0 / height;
+
+        s_scale = t_scale = scale;
+
+        iwidth = ceil(width*s_scale);
+        iheight = ceil(height*t_scale);
+
+        iwidth += 4;
+        iheight += 4;
+    }
+    else
+    {  // new style
+        iwidth = g_fixedwidth / 2;
+        iheight = g_fixedheight;
+
+        s_scale = (float)(iwidth-4) / width;
+        t_scale = (float)(iheight-4) / height;
+    }*/
+
+//
+// determine which side of each triangle to map the texture to
+//
+       for ( i = 0 ; i < numtri ; i++ )
+       {
+               if ( ptri[i].HasUV ) {
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * iwidth );
+                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * iheight );
+                       }
+               }
+               else
+               {
+                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+                       CrossProduct( vtemp1, vtemp2, normal );
+
+                       if ( normal[1] > 0 ) {
+                               basex = iwidth + 2;
+                       }
+                       else
+                       {
+                               basex = 2;
+                       }
+                       basey = 2;
+
+                       for ( j = 0 ; j < 3 ; j++ )
+                       {
+                               pbasevert = ptri[i].verts[j];
+
+                               triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
+                               triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
+                       }
+               }
+
+               DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
+                                 triangle_st[i][1][0], triangle_st[i][1][1] );
+               DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
+                                 triangle_st[i][2][0], triangle_st[i][2][1] );
+               DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
+                                 triangle_st[i][0][0], triangle_st[i][0][1] );
+       }
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+       swidth = iwidth * 2;
+       model.skinwidth = ( swidth + 3 ) & ~3;
+       model.skinheight = iheight;
+}
+
+
+static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters,
+                                                                IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){
+       int i, j;
+       IntListNode_t *next;
+
+       for ( j = 0; j < num_verts[0]; ++j )
+       {
+               for ( i = 0; i < num_verts[j + 1]; ++i )
+               {
+                       if ( clusters[j][i] == oldindex ) {
+                               ++new_num_verts[j + 1];
+
+                               next = vertLists[j];
+
+                               vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" );
+                               // Currently freed in WriteJointedModelFile only
+
+                               vertLists[j]->data = newIndex;
+                               vertLists[j]->next = next;
+                       }
+               }
+       }
+}
+
+/*
+   =================
+   Cmd_Base
+   =================
+ */
+void Cmd_Base( void ){
+       vec3_t base_xyz[MAX_VERTS];
+       triangle_t  *ptri;
+       int i, j, k;
+#if 1
+#else
+       int time1;
+#endif
+       char file1[1024];
+       char file2[1024];
+
+       GetScriptToken( false );
+
+       if ( g_skipmodel || g_release || g_archive ) {
+               return;
+       }
+
+       printf( "---------------------\n" );
+#if 1
+       sprintf( file1, "%s/%s", cdpartial, token );
+       printf( "%s  ", file1 );
+
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s", cddir, token );
+#else
+       sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext );
+       printf( "%s\n", file1 );
+
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s.%s", cddir, token, trifileext );
+
+       time1 = FileTime( file1 );
+       if ( time1 == -1 ) {
+               Error( "%s doesn't exist", file1 );
+       }
+#endif
+//
+// load the base triangles
+//
+       if ( do3ds ) {
+               Load3DSTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
+       }
+       else{
+               LoadTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
+       }
+
+
+       GetScriptToken( false );
+       sprintf( file2, "%s/%s.pcx", cddir, token );
+//     sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
+
+       printf( "skin: %s\n", file2 );
+       Load256Image( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight );
+
+       if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) {
+               if ( g_allow_newskin ) {
+                       ScaleWidth = BaseWidth;
+                       ScaleHeight = BaseHeight;
+               }
+               else
+               {
+                       Error( "Invalid skin page size: (%d,%d) should be (%d,%d)",
+                                  BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT );
+               }
+       }
+       else
+       {
+               ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X,
+                                                                                  ENCODED_WIDTH_Y );
+               ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X,
+                                                                                       ENCODED_HEIGHT_Y );
+       }
+
+//
+// get the ST values
+//
+       BuildST( ptri, model.num_tris,false );
+
+//
+// run through all the base triangles, storing each unique vertex in the
+// base vertex list and setting the indirect triangles to point to the base
+// vertices
+//
+       for ( i = 0 ; i < model.num_tris ; i++ )
+       {
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       // get the xyz index
+                       for ( k = 0 ; k < model.num_xyz ; k++ )
+                               if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) {
+                                       break;
+                               }           // this vertex is already in the base vertex list
+
+                       if ( k == model.num_xyz ) { // new index
+                               VectorCopy( ptri[i].verts[j], base_xyz[model.num_xyz] );
+
+                               if ( clustered ) {
+                                       ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts );
+                               }
+
+                               model.num_xyz++;
+                       }
+
+                       triangles[i].index_xyz[j] = k;
+
+                       // get the st index
+                       for ( k = 0 ; k < model.num_st ; k++ )
+                               if ( triangle_st[i][j][0] == base_st[k].s
+                                        && triangle_st[i][j][1] == base_st[k].t ) {
+                                       break;
+                               }           // this vertex is already in the base vertex list
+
+                       if ( k == model.num_st ) { // new index
+                               base_st[model.num_st].s = triangle_st[i][j][0];
+                               base_st[model.num_st].t = triangle_st[i][j][1];
+                               model.num_st++;
+                       }
+
+                       triangles[i].index_st[j] = k;
+               }
+       }
+
+       // build triangle strips / fans
+       BuildGlCmds();
+}
+
+//===============================================================
+
+char    *FindFrameFile( char *frame ){
+       int time1;
+       char file1[1024];
+       static char retname[1024];
+       char base[32];
+       char suffix[32];
+       char            *s;
+
+       if ( strstr( frame, "." ) ) {
+               return frame;       // allready in dot format
+
+       }
+       // split 'run1' into 'run' and '1'
+       s = frame + strlen( frame ) - 1;
+
+       while ( s != frame && *s >= '0' && *s <= '9' )
+               s--;
+
+       strcpy( suffix, s + 1 );
+       strcpy( base, frame );
+       base[s - frame + 1] = 0;
+
+       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "hrc" );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s%s.%s", base, suffix, "hrc" );
+               return retname;
+       }
+
+       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "asc" );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s%s.%s", base, suffix, "asc" );
+               return retname;
+       }
+
+       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "tri" );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s%s.%s", base, suffix, "tri" );
+               return retname;
+       }
+
+       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "3ds" );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s%s.%s", base, suffix, "3ds" );
+               return retname;
+       }
+
+       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "htr" );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s%s.%s", base, suffix, "htr" );
+               return retname;
+       }
+
+       // check for 'run.1'
+       sprintf( file1, "%s/%s.%s",cddir, base, suffix );
+       time1 = FileTime( file1 );
+       if ( time1 != -1 ) {
+               sprintf( retname, "%s.%s", base, suffix );
+               return retname;
+       }
+
+       Error( "frame %s could not be found",frame );
+       return NULL;
+}
+
+/*
+   ===============
+   GrabFrame
+   ===============
+ */
+static void GrabFrame( char *frame ){
+       triangle_t      *ptri;
+       int i, j;
+       trivert_t       *ptrivert;
+       int num_tris;
+       char file1[1024];
+       frame_t         *fr;
+       vertexnormals_t vnorms[MAX_VERTS];
+       int index_xyz;
+       char            *framefile;
+
+       // the frame 'run1' will be looked for as either
+       // run.1 or run1.tri, so the new alias sequence save
+       // feature an be used
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "grabbing %s  ", file1 );
+
+       if ( model.num_frames >= MAX_FRAMES ) {
+               Error( "model.num_frames >= MAX_FRAMES" );
+       }
+       fr = &g_frames[model.num_frames];
+       model.num_frames++;
+
+       strcpy( fr->name, frame );
+
+//
+// load the frame
+//
+       if ( do3ds ) {
+               Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
+       }
+       else{
+               LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
+       }
+
+       if ( num_tris != model.num_tris ) {
+               Error( "%s: number of triangles doesn't match base frame\n", file1 );
+       }
+
+//
+// allocate storage for the frame's vertices
+//
+       ptrivert = fr->v;
+
+       for ( i = 0 ; i < model.num_xyz ; i++ )
+       {
+               vnorms[i].numnormals = 0;
+               VectorClear( vnorms[i].normalsum );
+       }
+       ClearBounds( fr->mins, fr->maxs );
+
+//
+// store the frame's vertices in the same order as the base. This assumes the
+// triangles and vertices in this frame are in exactly the same order as in the
+// base
+//
+       for ( i = 0 ; i < num_tris ; i++ )
+       {
+               vec3_t vtemp1, vtemp2, normal;
+               float ftemp;
+
+               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
+               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
+               CrossProduct( vtemp1, vtemp2, normal );
+
+               VectorNormalize( normal, normal );
+
+               // rotate the normal so the model faces down the positive x axis
+               ftemp = normal[0];
+               normal[0] = -normal[1];
+               normal[1] = ftemp;
+
+               for ( j = 0 ; j < 3 ; j++ )
+               {
+                       index_xyz = triangles[i].index_xyz[j];
+
+                       // rotate the vertices so the model faces down the positive x axis
+                       // also adjust the vertices to the desired origin
+                       ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
+                                                                          adjust[0];
+                       ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
+                                                                          adjust[1];
+                       ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
+                                                                          adjust[2];
+
+                       AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );
+
+                       VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum );
+                       vnorms[index_xyz].numnormals++;
+               }
+       }
+
+//
+// calculate the vertex normals, match them to the template list, and store the
+// index of the best match
+//
+       for ( i = 0 ; i < model.num_xyz ; i++ )
+       {
+               int j;
+               vec3_t v;
+               float maxdot;
+               int maxdotindex;
+               int c;
+
+               c = vnorms[i].numnormals;
+               if ( !c ) {
+                       Error( "Vertex with no triangles attached" );
+               }
+
+               VectorScale( vnorms[i].normalsum, 1.0 / c, v );
+               VectorNormalize( v, v );
+
+               maxdot = -999999.0;
+               maxdotindex = -1;
+
+               for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
+               {
+                       float dot;
+
+                       dot = DotProduct( v, avertexnormals[j] );
+                       if ( dot > maxdot ) {
+                               maxdot = dot;
+                               maxdotindex = j;
+                       }
+               }
+
+               ptrivert[i].lightnormalindex = maxdotindex;
+       }
+
+       free( ptri );
+}
+
+/*
+   ===============
+   GrabJointedFrame
+   ===============
+ */
+void GrabJointedFrame( char *frame ){
+       char file1[1024];
+       char    *framefile;
+       frame_t     *fr;
+
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "grabbing %s\n", file1 );
+
+       fr = &g_frames[model.num_frames - 1]; // last frame read in
+
+       LoadJointList( file1, fr->joints, jointed );
+}
+
+/*
+   ===============
+   GrabGlobals
+   ===============
+ */
+void GrabGlobals( char *frame ){
+       char file1[1024];
+       char    *framefile;
+       frame_t     *fr;
+
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "grabbing %s\n", file1 );
+
+       fr = &g_frames[model.num_frames - 1]; // last frame read in
+
+       LoadGlobals( file1 );
+}
+
+/*
+   ===============
+   Cmd_Frame
+   ===============
+ */
+void Cmd_Frame( void ){
+       while ( ScriptTokenAvailable() )
+       {
+               GetScriptToken( false );
+               if ( g_skipmodel ) {
+                       continue;
+               }
+               if ( g_release || g_archive ) {
+                       model.num_frames = 1;   // don't skip the writeout
+                       continue;
+               }
+
+               H_printf( "#define FRAME_%-16s\t%i\n", token, model.num_frames );
+
+               GrabFrame( token );
+       }
+}
+
+/*
+   ===============
+   Cmd_Skin
+
+   Skins aren't actually stored in the file, only a reference
+   is saved out to the header file.
+   ===============
+ */
+void Cmd_Skin( void ){
+       byte    *palette;
+       byte    *pixels;
+       int width, height;
+       byte    *cropped;
+       int y;
+       char name[1024], savename[1024];
+
+       GetScriptToken( false );
+
+       if ( model.num_skins == MAX_MD2SKINS ) {
+               Error( "model.num_skins == MAX_MD2SKINS" );
+       }
+
+       if ( g_skipmodel ) {
+               return;
+       }
+
+#if 1
+       sprintf( name, "%s/%s.pcx", cddir, token );
+       sprintf( savename, "%s/!%s.pcx", g_outputDir, token );
+       sprintf( g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token );
+#else
+       sprintf( name, "%s/%s.lbm", cdarchive, token );
+       strcpy( name, ExpandPathAndArchive( name ) );
+//     sprintf (name, "%s/%s.lbm", cddir, token);
+
+       if ( ScriptTokenAvailable() ) {
+               GetScriptToken( false );
+               sprintf( g_skins[model.num_skins], "%s.pcx", token );
+               sprintf( savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins] );
+       }
+       else
+       {
+               sprintf( savename, "%s/%s.pcx", g_outputDir, token );
+               sprintf( g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token );
+       }
+#endif
+
+       model.num_skins++;
+
+       if ( g_skipmodel || g_release || g_archive ) {
+               return;
+       }
+
+       // load the image
+       printf( "loading %s\n", name );
+       Load256Image( name, &pixels, &palette, &width, &height );
+//     RemapZero (pixels, palette, width, height);
+
+       // crop it to the proper size
+       cropped = (byte *) SafeMalloc( model.skinwidth * model.skinheight, "Cmd_Skin" );
+       for ( y = 0 ; y < model.skinheight ; y++ )
+       {
+               memcpy( cropped + y * model.skinwidth,
+                               pixels + y * width, model.skinwidth );
+       }
+
+       // save off the new image
+       printf( "saving %s\n", savename );
+       CreatePath( savename );
+       WritePCXfile( savename, cropped, model.skinwidth,
+                                 model.skinheight, palette );
+
+       free( pixels );
+       free( palette );
+       free( cropped );
+}
+
+
+/*
+   =================
+   Cmd_Origin
+   =================
+ */
+void Cmd_Origin( void ){
+       // rotate points into frame of reference so model points down the
+       // positive x axis
+       GetScriptToken( false );
+       adjust[1] = -atof( token );
+
+       GetScriptToken( false );
+       adjust[0] = atof( token );
+
+       GetScriptToken( false );
+       adjust[2] = -atof( token );
+}
+
+
+/*
+   =================
+   Cmd_ScaleUp
+   =================
+ */
+void Cmd_ScaleUp( void ){
+       GetScriptToken( false );
+       scale_up = atof( token );
+       if ( g_skipmodel || g_release || g_archive ) {
+               return;
+       }
+
+       printf( "Scale up: %f\n", scale_up );
+}
+
+
+/*
+   =================
+   Cmd_Skinsize
+
+   Set a skin size other than the default
+   =================
+ */
+void Cmd_Skinsize( void ){
+       GetScriptToken( false );
+       g_fixedwidth = atoi( token );
+       GetScriptToken( false );
+       g_fixedheight = atoi( token );
+}
+
+/*
+   =================
+   Cmd_Modelname
+
+   Gives a different name/location for the file, instead of the cddir
+   =================
+ */
+void Cmd_Modelname( void ){
+       GetScriptToken( false );
+       strcpy( modelname, token );
+}
+
+/*
+   ===============
+   Cmd_Cd
+   ===============
+ */
+void Cmd_Cd( void ){
+       char temp[256];
+
+       FinishModel();
+       ClearModel();
+
+       GetScriptToken( false );
+
+       // this is a silly mess...
+       sprintf( cdpartial, "models/%s", token );
+       sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token );
+       sprintf( cddir, "%s%s", gamedir, cdpartial );
+
+       // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
+       sprintf( temp, "%s%s", g_outputDir, cdpartial );
+       strcpy( g_outputDir, temp );
+
+       // if -only was specified and this cd doesn't match,
+       // skip the model (you only need to match leading chars,
+       // so you could regrab all monsters with -only monsters)
+       if ( !g_only[0] ) {
+               return;
+       }
+       if ( strncmp( token, g_only, strlen( g_only ) ) ) {
+               g_skipmodel = true;
+               printf( "skipping %s\n", cdpartial );
+       }
+}
+
+/*
+   =================
+   Cmd_Cluster
+   =================
+ */
+void Cmd_Cluster(){
+       char file1[1024];
+
+       GetScriptToken( false );
+
+       printf( "---------------------\n" );
+       sprintf( file1, "%s/%s", cdpartial, token );
+       printf( "%s\n", file1 );
+
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s", cddir, token );
+
+       LoadClusters( file1, (int **)&clusters, (int *)&num_verts, jointed );
+
+       new_num_verts[0] = num_verts[0];
+
+       clustered = 1;
+}
+
+// Model construction cover functions.
+void MODELCMD_Modelname( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       Cmd_Modelname();
+/*
+    switch(modeltype)
+    {
+    case MODEL_MD2:
+        Cmd_Modelname ();
+        break;
+    case MODEL_FM:
+        Cmd_FMModelname ();
+        break;
+    }
+ */
+}
+
+void MODELCMD_Cd( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Cd();
+               break;
+       case MODEL_FM:
+               Cmd_FMCd();
+               break;
+       }
+}
+
+void MODELCMD_Origin( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       Cmd_Origin();
+/*     switch(modeltype)
+    {
+    case MODEL_MD2:
+        Cmd_Origin ();
+        break;
+    case MODEL_FM:
+        Cmd_FMOrigin ();
+        break;
+    }
+ */
+}
+
+void MODELCMD_Cluster( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Cluster();
+               break;
+       case MODEL_FM:
+               Cmd_FMCluster();
+               break;
+       }
+}
+
+void MODELCMD_Base( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Base();
+               break;
+       case MODEL_FM:
+               Cmd_FMBase( false );
+               break;
+       }
+}
+
+void MODELCMD_BaseST( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Base();
+               break;
+       case MODEL_FM:
+               Cmd_FMBase( true );
+               break;
+       }
+}
+
+void MODELCMD_ScaleUp( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       Cmd_ScaleUp();
+/*     switch(modeltype)
+    {
+    case MODEL_MD2:
+        Cmd_ScaleUp ();
+        break;
+    case MODEL_FM:
+        Cmd_FMScaleUp ();
+        break;
+    }
+ */
+}
+
+void MODELCMD_Frame( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Frame();
+               break;
+       case MODEL_FM:
+               Cmd_FMFrame();
+               break;
+       }
+}
+
+void MODELCMD_Skin( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               Cmd_Skin();
+               break;
+       case MODEL_FM:
+               Cmd_FMSkin();
+               break;
+       }
+}
+
+void MODELCMD_Skinsize( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       Cmd_Skinsize();
+/*
+    switch(modeltype)
+    {
+    case MODEL_MD2:
+        Cmd_Skinsize ();
+        break;
+    case MODEL_FM:
+        Cmd_FMSkinsize ();
+        break;
+    }
+ */
+}
+
+void MODELCMD_Skeleton( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               break;
+       case MODEL_FM:
+               Cmd_FMSkeleton();
+               break;
+       }
+}
+
+void MODELCMD_BeginGroup( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               break;
+       case MODEL_FM:
+               Cmd_FMBeginGroup();
+               break;
+       }
+}
+
+void MODELCMD_EndGroup( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               break;
+       case MODEL_FM:
+               Cmd_FMEndGroup();
+               break;
+       }
+}
+
+void MODELCMD_Referenced( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               break;
+       case MODEL_FM:
+               Cmd_FMReferenced();
+               break;
+       }
+}
+
+void MODELCMD_NodeOrder( int modeltype ){
+       if ( g_forcemodel ) {
+               modeltype = g_forcemodel;
+       }
+
+       switch ( modeltype )
+       {
+       case MODEL_MD2:
+               break;
+       case MODEL_FM:
+               Cmd_FMNodeOrder();
+               break;
+       }
+}
diff --git a/tools/heretic2/h2data/pics.c b/tools/heretic2/h2data/pics.c
new file mode 100644 (file)
index 0000000..d296033
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "qdata.h"
+
+char pic_prefix[1024];
+extern char        *g_outputDir;
+
+/*
+   ===============
+   Cmd_Pic
+   ===============
+ */
+
+void Cmd_Pic( void ){
+       int xl,yl,xh,yh,w,h;
+       byte            *dest, *source;
+       int flags, value, contents;
+       char lumpname[128];
+       char animname[128];
+       byte buffer[256 * 256];
+       unsigned bufferl[256 * 256];
+       char filename[1024];
+       unsigned        *destl, *sourcel;
+       int linedelta, x, y;
+       int size;
+       miptex_t        *qtex;
+       miptex32_t      *qtex32;
+       float scale_x, scale_y;
+
+       GetScriptToken( false );
+       strcpy( lumpname, token );
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       total_x += w;
+       total_y += h;
+       total_textures++;
+
+       if ( ( w & 7 ) || ( h & 7 ) ) {
+               Error( "line %i: miptex sizes must be multiples of 8", scriptline );
+       }
+
+       flags = 0;
+       contents = 0;
+       value = 0;
+
+       animname[0] = 0;
+
+       scale_x = scale_y = 0.5;
+
+       if ( TrueColorImage ) {
+               sprintf( filename, "%spics/%s/%s.m32", g_outputDir, pic_prefix, lumpname );
+               if ( g_release ) {
+                       return; // textures are only released by $maps
+
+               }
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= longimagewidth || xh > longimagewidth ||
+                        yl >= longimageheight || yh > longimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
+               }
+
+               sourcel = longimage + ( yl * longimagewidth ) + xl;
+               destl = bufferl;
+               linedelta = ( longimagewidth - w );
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *destl++ = *sourcel++;  // RGBA
+                       }
+                       sourcel += linedelta;
+               }
+
+               qtex32 = CreateMip32( bufferl, w, h, &size, false );
+
+               qtex32->flags |= LittleLong( flags );
+               qtex32->contents = contents;
+               qtex32->value = value;
+               qtex32->scale_x = scale_x;
+               qtex32->scale_y = scale_y;
+               sprintf( qtex32->name, "%s/%s", pic_prefix, lumpname );
+               if ( animname[0] ) {
+                       sprintf( qtex32->animname, "%s/%s", pic_prefix, animname );
+               }
+
+               //
+               // write it out
+               //
+               printf( "writing %s\n", filename );
+               SaveFile( filename, (byte *)qtex32, size );
+
+               free( qtex32 );
+       }
+       else
+       {
+               sprintf( filename, "%spics/%s/%s.m8", g_outputDir, pic_prefix, lumpname );
+               if ( g_release ) {
+                       return; // textures are only released by $maps
+
+               }
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= byteimagewidth || xh > byteimagewidth ||
+                        yl >= byteimageheight || yh > byteimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
+               }
+
+               source = byteimage + yl * byteimagewidth + xl;
+               dest = buffer;
+               linedelta = byteimagewidth - w;
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *dest++ = *source++;
+                       }
+                       source += linedelta;
+               }
+
+               qtex = CreateMip( buffer, w, h, lbmpalette, &size, false );
+
+               qtex->flags = flags;
+               qtex->contents = contents;
+               qtex->value = value;
+               sprintf( qtex->name, "%s/%s", pic_prefix, lumpname );
+               if ( animname[0] ) {
+                       sprintf( qtex->animname, "%s/%s", pic_prefix, animname );
+               }
+
+               //
+               // write it out
+               //
+               printf( "writing %s\n", filename );
+               SaveFile( filename, (byte *)qtex, size );
+
+               free( qtex );
+       }
+}
+
+
+/*
+   ===============
+   Cmd_picdir
+   ===============
+ */
+void Cmd_Picdir( void ){
+       char filename[1024];
+
+       GetScriptToken( false );
+       strcpy( pic_prefix, token );
+       // create the directory if needed
+       sprintf( filename, "%sPics", g_outputDir );
+       Q_mkdir( filename );
+       sprintf( filename, "%sPics/%s", g_outputDir, pic_prefix );
+       Q_mkdir( filename );
+}
diff --git a/tools/heretic2/h2data/qd_fmodel.h b/tools/heretic2/h2data/qd_fmodel.h
new file mode 100644 (file)
index 0000000..286fb07
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef FMODEL_H
+#define FMODEL_H
+#include "fmodel.h"
+#endif
+#include "qd_skeletons.h"
+
+typedef struct
+{
+       int numnormals;
+       vec3_t normalsum;
+} fmvertexnormals_t;
+
+typedef struct
+{
+       vec3_t v;
+       int lightnormalindex;
+       fmvertexnormals_t vnorm;
+} fmtrivert_t;
+
+#define FRAME_NAME_LEN ( 16 )
+
+typedef struct
+{
+       vec3_t mins, maxs;
+       char name[FRAME_NAME_LEN];
+       fmtrivert_t v[MAX_FM_VERTS];
+       struct QD_SkeletalJoint_s joints[NUM_CLUSTERS];
+       struct QD_SkeletalJoint_s references[NUM_REFERENCES];
+} fmframe_t;
+
+extern fmframe_t g_frames[MAX_FM_FRAMES];
+
+extern fmheader_t fmheader;
+extern char cdarchive[1024];                        // set by $fmcd
+extern char cdpartial[1024];                        // set by $fmcd
+extern char cddir[1024];                            // set by $fmcd
+
+void GrabFrame( char *frame );
+void H_printf( char *fmt, ... );
+char *FindFrameFile( char *frame );
diff --git a/tools/heretic2/h2data/qd_skeletons.c b/tools/heretic2/h2data/qd_skeletons.c
new file mode 100644 (file)
index 0000000..97e2a1f
--- /dev/null
@@ -0,0 +1,1231 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qd_skeletons.h"
+#include "skeletons.h"
+#include "qd_fmodel.h"
+#include "angles.h"
+#include "token.h"
+#include "qdata.h"
+#include "reference.h"
+
+#include <assert.h>
+#include <math.h>
+#include <memory.h>
+
+
+// We're assuming no more than 16 reference points, with no more than 32 characters in the name
+char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
+int RefPointNum = 0;
+
+Skeletalfmheader_t g_skelModel;
+
+void ClearSkeletalModel(){
+       g_skelModel.type = SKEL_NULL;
+       g_skelModel.clustered = false;
+       g_skelModel.references = REF_NULL;
+}
+
+//==========================================================================
+//
+// LoadHRCClustered
+//
+//==========================================================================
+
+// Places the null terminated src string into the dest string less any trailing digits or underscores
+void StripTrailingDigits( char *src, char *dest ){
+#ifndef NDEBUG
+       int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
+#endif
+       int i = 0;
+
+       while ( src[i] != '\0' )
+       {
+               ++i;
+#ifndef NDEBUG
+               assert( i < max );
+#endif
+       }
+
+       while ( ( src[--i] >= '0' && src[i] <= '9' ) || src[i] == '_' )
+       {
+
+       }
+
+       memcpy( dest, src, ++i );
+
+       dest[i] = '\0';
+}
+
+static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
+       extern void HandleHRCModel( triangle_t **triList, int *triangleCount,
+                                                               mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth );
+
+       extern mesh_node_t  *pmnodes;
+
+       triangle_t *triList;
+//      mesh_node_t *nodesList;
+       int num_mesh_nodes = 0, triangleCount = 0;
+
+#if 0
+       int i;
+       int j, numVerts;
+       char stripped[SKELETAL_NAME_MAX];
+
+       for ( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i )
+       {
+               num_verts[i] = 0;
+       }
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       TK_Beyond( TK_CLUSTERS );
+
+       while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
+       {
+               TK_Require( TK_STRING );
+
+               StripTrailingDigits( tk_String, stripped );
+
+               for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
+               {
+                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
+                               i = -i + numJointsInSkeleton[skelType] - 1;
+
+                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
+
+                               numVerts = tk_IntNumber;
+
+                               if ( !num_verts[i + 1] ) { // first set of verts for cluster
+                                       clusterList[i] = SafeMalloc( numVerts * sizeof( int ), "LoadHRCClustered" );
+                                       assert( clusterList[i] );
+                               }
+                               else                // any later sets of verts need to copy current
+                               {
+                                       int *temp;
+
+                                       temp = SafeMalloc( ( num_verts[i + 1] + numVerts ) * sizeof( int ), "LoadHRCClustered" );
+                                       assert( temp );
+
+                                       memcpy( temp + numVerts, clusterList[i], num_verts[i + 1] * sizeof( int ) );
+
+                                       free( clusterList[i] );
+
+                                       clusterList[i] = temp;
+                               }
+
+                               // currently this function is only called by LoadModelClusters.
+                               // Apparently the matching free has disappeared,
+                               // should probably be free at the end of FMCmd_Base
+
+                               TK_Beyond( TK_LBRACE );
+
+                               for ( j = 0; j < numVerts; ++j )
+                               {
+                                       TK_Require( TK_INTNUMBER );
+                                       clusterList[i][j] = tk_IntNumber;
+                                       TK_Fetch();
+                               }
+
+                               num_verts[i + 1] += numVerts;
+
+                               break;
+                       }
+               }
+       }
+
+       num_verts[0] = numJointsInSkeleton[skelType];
+#endif
+
+#if 1   // get the index number localized to the root
+//     for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
+//     {
+//             g_skelModel.num_verts[i] = 0;
+//     }
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       // prime it
+       TK_Beyond( TK_MODEL );
+
+       triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
+       memset( triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
+//     nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+       pmnodes = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
+
+       memset( pmnodes, 0, MAX_FM_MESH_NODES * sizeof( mesh_node_t ) );
+
+       // this should eventually use a stripped down version of this
+       HandleHRCModel( &triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0 );
+
+//     free(nodesList);
+       free( triList );
+
+       num_verts[0] = numJointsInSkeleton[skelType];
+#endif
+}
+
+void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ){
+       int i, j, numVerts;
+       tokenType_t nextToken;
+       char stripped[SKELETAL_NAME_MAX];
+
+       meshNode->clustered = true;
+
+       nextToken = TK_Get( TK_CLUSTER_NAME );
+
+       while ( nextToken == TK_CLUSTER_NAME )
+       {
+               TK_FetchRequire( TK_STRING );
+
+               StripTrailingDigits( tk_String, stripped );
+
+               for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
+               {
+                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type] + i] ) == 0 ) {
+                               i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
+
+                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
+
+                               numVerts = tk_IntNumber;
+
+                               if ( !baseIndex ) {
+                                       meshNode->clusters[i] = (int *) SafeMalloc( numVerts * sizeof( int ), "ReadHRCClusterList" );
+                                       assert( meshNode->clusters[i] );
+                               }
+                               else
+                               {
+                                       int *temp;
+
+                                       temp = meshNode->clusters[i];
+                                       meshNode->clusters[i] = (int *) SafeMalloc( ( meshNode->num_verts[i + 1] + numVerts ) * sizeof( int ), "ReadHRCClusterList" );
+                                       assert( meshNode->clusters[i] );
+
+                                       memcpy( meshNode->clusters[i], temp, meshNode->num_verts[i + 1] * sizeof( int ) );
+                                       free( temp );
+                               }
+
+                               // currently this function is only called by LoadModelClusters.
+                               // Apparently the matching free has disappeared,
+                               // should probably be free at the end of FMCmd_Base
+
+                               TK_Beyond( TK_LBRACE );
+
+                               for ( j = 0; j < numVerts; ++j )
+                               {
+                                       TK_Require( TK_INTNUMBER );
+                                       meshNode->clusters[i][baseIndex + j] = tk_IntNumber + baseIndex;
+                                       TK_Fetch();
+                               }
+
+                               if ( baseIndex ) {
+                                       meshNode->num_verts[i + 1] += numVerts;
+                               }
+                               else
+                               {
+                                       meshNode->num_verts[i + 1] = numVerts;
+                               }
+
+                               break;
+                       }
+               }
+
+               TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
+               nextToken = TK_Fetch();
+       }
+}
+
+static void LoadHRCGlobals( char *fileName ){
+       int i;
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+       TK_Beyond( TK_MODEL );
+
+       TK_Beyond( TK_SCALING );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_skelModel.scaling[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+
+       TK_Beyond( TK_ROTATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_skelModel.rotation[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+
+       TK_Beyond( TK_TRANSLATION );
+       for ( i = 0; i < 3; i++ )
+       {
+               TK_Require( TK_FLOATNUMBER );
+               g_skelModel.translation[i] = tk_FloatNumber;
+               TK_Fetch();
+       }
+}
+
+static void ParseVec3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseVec3d( vec3d_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3d( vec3d_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3( vec3_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3d( vec3d_t in ){
+       TK_Require( TK_FLOATNUMBER );
+       in[1] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[2] = tk_FloatNumber;
+       TK_FetchRequire( TK_FLOATNUMBER );
+       in[0] = tk_FloatNumber;
+}
+
+static void LoadHRCJointList( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
+#define MAX_STACK 64
+       int i, j;
+       vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
+       int curCorrespondingJoint[MAX_STACK];
+       int currentStack = 0, stackSize;
+       double cx, sx, cy, sy, cz, sz;
+       double rx, ry, rz;
+       double x2, y2, z2;
+       char stripped[SKELETAL_NAME_MAX];
+       Placement_d_t *placement;
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       TK_Beyond( TK_MODEL );
+
+       while ( TK_Search( TK_NAME ) != TK_EOF )
+       {
+               TK_Require( TK_STRING );
+
+               StripTrailingDigits( tk_String, stripped );
+
+               if ( stricmp( stripped, skeletonRootNames[skeletonRNameOffsets[skelType]] ) == 0 ) {
+                       break;
+               }
+       }
+
+       if ( tk_Token == TK_EOF ) {
+               Error( "Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]] );
+               return;
+       }
+
+       TK_Beyond( TK_SCALING );
+
+       ParseVec3d( curScale[currentStack] );
+
+       TK_Beyond( TK_ROTATION );
+
+       ParseRotation3d( curRotation[currentStack] );
+
+       TK_Beyond( TK_TRANSLATION );
+
+       ParseVec3d( curTranslation[currentStack] );
+
+       // account for global model translation
+       curTranslation[currentStack][1] += g_skelModel.translation[0];
+       curTranslation[currentStack][2] += g_skelModel.translation[1];
+       curTranslation[currentStack][0] += g_skelModel.translation[2];
+
+       curCorrespondingJoint[currentStack] = -1;
+
+       ++currentStack;
+
+       for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
+       {
+               while ( 1 )
+               {
+                       TK_Beyond( TK_MODEL );
+
+                       TK_BeyondRequire( TK_NAME, TK_STRING );
+
+                       StripTrailingDigits( tk_String, stripped );
+
+                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
+                               break;
+                       }
+
+                       TK_Beyond( TK_SCALING );
+
+                       ParseVec3d( curScale[currentStack] );
+
+                       TK_Beyond( TK_ROTATION );
+
+                       ParseRotation3d( curRotation[currentStack] );
+
+                       TK_Beyond( TK_TRANSLATION );
+
+                       ParseVec3d( curTranslation[currentStack] );
+
+                       curCorrespondingJoint[currentStack] = -1;
+
+                       ++currentStack;
+               }
+
+               TK_Beyond( TK_SCALING );
+
+               ParseVec3d( curScale[currentStack] );
+
+               TK_Beyond( TK_ROTATION );
+
+               ParseRotation3d( curRotation[currentStack] );
+
+               jointList[i].rotation[1] = curRotation[currentStack][1];
+               jointList[i].rotation[2] = curRotation[currentStack][2];
+               jointList[i].rotation[0] = curRotation[currentStack][0];
+
+               TK_Beyond( TK_TRANSLATION );
+
+               ParseVec3d( curTranslation[currentStack] );
+
+//             jointList[i].placement.origin[1] = curTranslation[currentStack][1];
+//             jointList[i].placement.origin[2] = curTranslation[currentStack][2];
+//             jointList[i].placement.origin[0] = curTranslation[currentStack][0];
+
+               jointList[i].placement.origin[1] = 0.0;
+               jointList[i].placement.origin[2] = 0.0;
+               jointList[i].placement.origin[0] = 0.0;
+
+               jointList[i].placement.direction[1] = 20.0;
+               jointList[i].placement.direction[2] = 0.0;
+               jointList[i].placement.direction[0] = 0.0;
+
+               jointList[i].placement.up[1] = 0.0;
+               jointList[i].placement.up[2] = 20.0;
+               jointList[i].placement.up[0] = 0.0;
+
+               curCorrespondingJoint[currentStack] = i;
+
+               ++currentStack;
+       }
+
+       stackSize = currentStack;
+
+#if 0
+       // rotate the direction and up vectors to correspond to the rotation
+       for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
+       {
+               rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
+               ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
+               rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
+
+               cx = cos( rx );
+               sx = sin( rx );
+
+               cy = cos( ry );
+               sy = sin( ry );
+
+               cz = cos( rz );
+               sz = sin( rz );
+
+               // y-axis rotation for direction
+               x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
+               z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
+               jointList[i].placement.direction[0] = x2;
+               jointList[i].placement.direction[2] = z2;
+
+               // y-axis rotation for up
+               x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
+               z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
+               jointList[i].placement.up[0] = x2;
+               jointList[i].placement.up[2] = z2;
+
+               // z-axis rotation for direction
+               x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
+               y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
+               jointList[i].placement.direction[0] = x2;
+               jointList[i].placement.direction[1] = y2;
+
+               // z-axis rotation for up
+               x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
+               y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
+               jointList[i].placement.up[0] = x2;
+               jointList[i].placement.up[1] = y2;
+
+               // x-axis rotation for direction vector
+               y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
+               z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
+               jointList[i].placement.direction[1] = y2;
+               jointList[i].placement.direction[2] = z2;
+
+               // x-axis rotation for up vector
+               y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
+               z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
+               jointList[i].placement.up[1] = y2;
+               jointList[i].placement.up[2] = z2;
+
+               // translate direction to a point in the model
+               jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
+               jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
+               jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
+
+               // translate up to a point in the model
+               jointList[i].placement.up[0] += jointList[i].placement.origin[0];
+               jointList[i].placement.up[1] += jointList[i].placement.origin[1];
+               jointList[i].placement.up[2] += jointList[i].placement.origin[2];
+       }
+#endif
+
+       for ( i = stackSize - 1; i >= 0; --i )
+       {
+               rx = curRotation[i][0] * ANGLE_TO_RAD;
+               ry = curRotation[i][1] * ANGLE_TO_RAD;
+               rz = curRotation[i][2] * ANGLE_TO_RAD;
+
+               cx = cos( rx );
+               sx = sin( rx );
+
+               cy = cos( ry );
+               sy = sin( ry );
+
+               cz = cos( rz );
+               sz = sin( rz );
+
+#if 1
+               for ( j = i; j < stackSize; ++j )
+               {
+                       if ( curCorrespondingJoint[j] != -1 ) {
+                               placement = &jointList[curCorrespondingJoint[j]].placement;
+
+                               // y-axis rotation for origin
+                               x2 = placement->origin[0] * cy + placement->origin[2] * sy;
+                               z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
+                               placement->origin[0] = x2;
+                               placement->origin[2] = z2;
+
+                               // y-axis rotation for direction
+                               x2 = placement->direction[0] * cy + placement->direction[2] * sy;
+                               z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
+                               placement->direction[0] = x2;
+                               placement->direction[2] = z2;
+
+                               // y-axis rotation for up
+                               x2 = placement->up[0] * cy + placement->up[2] * sy;
+                               z2 = -placement->up[0] * sy + placement->up[2] * cy;
+                               placement->up[0] = x2;
+                               placement->up[2] = z2;
+
+                               // z-axis rotation for origin
+                               x2 = placement->origin[0] * cz - placement->origin[1] * sz;
+                               y2 = placement->origin[0] * sz + placement->origin[1] * cz;
+                               placement->origin[0] = x2;
+                               placement->origin[1] = y2;
+
+                               // z-axis rotation for direction
+                               x2 = placement->direction[0] * cz - placement->direction[1] * sz;
+                               y2 = placement->direction[0] * sz + placement->direction[1] * cz;
+                               placement->direction[0] = x2;
+                               placement->direction[1] = y2;
+
+                               // z-axis rotation for up
+                               x2 = placement->up[0] * cz - placement->up[1] * sz;
+                               y2 = placement->up[0] * sz + placement->up[1] * cz;
+                               placement->up[0] = x2;
+                               placement->up[1] = y2;
+
+                               // x-axis rotation for origin
+                               y2 = placement->origin[1] * cx - placement->origin[2] * sx;
+                               z2 = placement->origin[1] * sx + placement->origin[2] * cx;
+                               placement->origin[1] = y2;
+                               placement->origin[2] = z2;
+
+                               // x-axis rotation for direction vector
+                               y2 = placement->direction[1] * cx - placement->direction[2] * sx;
+                               z2 = placement->direction[1] * sx + placement->direction[2] * cx;
+                               placement->direction[1] = y2;
+                               placement->direction[2] = z2;
+
+                               // x-axis rotation for up vector
+                               y2 = placement->up[1] * cx - placement->up[2] * sx;
+                               z2 = placement->up[1] * sx + placement->up[2] * cx;
+                               placement->up[1] = y2;
+                               placement->up[2] = z2;
+
+                               // translate origin
+                               placement->origin[0] += curTranslation[i][0];
+                               placement->origin[1] += curTranslation[i][1];
+                               placement->origin[2] += curTranslation[i][2];
+
+                               // translate back to local coord
+                               placement->direction[0] += curTranslation[i][0];
+                               placement->direction[1] += curTranslation[i][1];
+                               placement->direction[2] += curTranslation[i][2];
+
+                               // translate back to local coord
+                               placement->up[0] += curTranslation[i][0];
+                               placement->up[1] += curTranslation[i][1];
+                               placement->up[2] += curTranslation[i][2];
+                       }
+               }
+#else
+               // This screwed up and needs to be sorted out!!!
+               // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
+               for ( j = i - 1; j < stackSize - 1; ++j )
+               {
+                       // y-axis rotation for origin
+                       x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
+                       z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
+                       jointList[j].placement.origin[0] = x2;
+                       jointList[j].placement.origin[2] = z2;
+
+                       // y-axis rotation for direction
+                       x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
+                       z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
+                       jointList[j].placement.direction[0] = x2;
+                       jointList[j].placement.direction[2] = z2;
+
+                       // y-axis rotation for up
+                       x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
+                       z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
+                       jointList[j].placement.up[0] = x2;
+                       jointList[j].placement.up[2] = z2;
+
+                       // z-axis rotation for origin
+                       x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
+                       y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
+                       jointList[j].placement.origin[0] = x2;
+                       jointList[j].placement.origin[1] = y2;
+
+                       // z-axis rotation for direction
+                       x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
+                       y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
+                       jointList[j].placement.direction[0] = x2;
+                       jointList[j].placement.direction[1] = y2;
+
+                       // z-axis rotation for up
+                       x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
+                       y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
+                       jointList[j].placement.up[0] = x2;
+                       jointList[j].placement.up[1] = y2;
+
+                       // x-axis rotation for origin
+                       y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
+                       z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
+                       jointList[j].placement.origin[1] = y2;
+                       jointList[j].placement.origin[2] = z2;
+
+                       // x-axis rotation for direction vector
+                       y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
+                       z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
+                       jointList[j].placement.direction[1] = y2;
+                       jointList[j].placement.direction[2] = z2;
+
+                       // x-axis rotation for up vector
+                       y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
+                       z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
+                       jointList[j].placement.up[1] = y2;
+                       jointList[j].placement.up[2] = z2;
+
+                       if ( curCorrespondingJoint[j + 1] != -1 ) {
+                               // translate origin
+                               jointList[j].placement.origin[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.origin[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.origin[2] += curTranslation[i - 1][2];
+
+                               // translate back to local coord
+                               jointList[j].placement.direction[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.direction[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.direction[2] += curTranslation[i - 1][2];
+
+                               // translate back to local coord
+                               jointList[j].placement.up[0] += curTranslation[i - 1][0];
+                               jointList[j].placement.up[1] += curTranslation[i - 1][1];
+                               jointList[j].placement.up[2] += curTranslation[i - 1][2];
+                       }
+               }
+#endif
+       }
+}
+
+void LoadModelTransform( char *fileName ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCGlobals( InputFileName );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC match.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+//                     printf("\n");
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCGlobals( fileName );
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+void LoadModelClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC match.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+//                     printf("\n");
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCClustered( fileName, clusterList, num_verts, skelType );
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+void LoadSkeleton( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCJointList( InputFileName, jointList, skelType );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+//                     printf("\n");
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCJointList( fileName, jointList, skelType );
+
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+/*
+   ===============
+   GrabSkeletalFrame
+   ===============
+ */
+void GrabSkeletalFrame( char *frame ){
+       char file1[1024];
+       char    *framefile;
+       fmframe_t   *fr;
+
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "Grabbing Skeletal Frame %s\n", file1 );
+
+       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+       LoadSkeleton( file1, fr->joints, g_skelModel.type );
+}
+
+/*
+   ===============
+   GrabModelTransform
+   ===============
+ */
+void GrabModelTransform( char *frame ){
+       char file1[1024];
+       char    *framefile;
+       fmframe_t   *fr;
+
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+//     printf ("grabbing %s\n", file1);
+
+       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+       LoadModelTransform( file1 );
+}
+
+void Cmd_FMCluster(){
+       char file1[1024];
+
+       GetScriptToken( false );
+
+       printf( "---------------------\n" );
+       sprintf( file1, "%s/%s", cdpartial, token );
+       printf( "%s\n", file1 );
+
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s", cddir, token );
+
+       g_skelModel.clustered = -1;
+
+       LoadModelClusters( file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type );
+
+       g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
+
+       g_skelModel.clustered = true;
+}
+
+void Cmd_FMSkeleton(){
+       GetScriptToken( false );
+       g_skelModel.type = atoi( token );
+}
+
+void Cmd_FMSkeletalFrame(){
+       while ( ScriptTokenAvailable() )
+       {
+               GetScriptToken( false );
+               if ( g_skipmodel ) {
+                       GetScriptToken( false );
+                       continue;
+               }
+               if ( g_release || g_archive ) {
+                       fmheader.num_frames = 1;    // don't skip the writeout
+                       GetScriptToken( false );
+                       continue;
+               }
+
+               H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames );
+
+               GrabModelTransform( token );
+               GrabFrame( token );
+               GrabSkeletalFrame( token );
+
+               // need to add the up and dir points to the frame bounds here
+               // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+               // then remove fudge in determining scale on frame write out
+       }
+}
+
+static void LoadHRCReferences( char *fileName, fmframe_t *fr ){
+#define MAX_STACK 64
+       int i, j, k;
+       vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
+       int curCorrespondingJoint[MAX_STACK];
+       int currentStack, stackSize;
+       double cx, sx, cy, sy, cz, sz;
+       double rx, ry, rz;
+       double x2, y2, z2;
+       char stripped[SKELETAL_NAME_MAX];
+       Placement_d_t *placement;
+       int refnum;
+
+       TK_OpenSource( fileName );
+       TK_FetchRequire( TK_HRCH );
+       TK_FetchRequire( TK_COLON );
+       TK_FetchRequire( TK_SOFTIMAGE );
+
+       if ( RefPointNum <= 0 ) { // There were no labels indicated in the QDT, so use the hard-coded stuff.
+               refnum = numReferences[g_skelModel.references];
+       }
+       else
+       {
+               refnum = RefPointNum;
+       }
+
+       for ( k = 0; k < refnum; ++k )
+       {
+               currentStack = 0;
+
+               // Load the root to get translation and initial rotation
+//             TK_Beyond(TK_MODEL);
+
+               while ( TK_Search( TK_NAME ) != TK_EOF )
+               {
+                       TK_Require( TK_STRING );
+
+                       StripTrailingDigits( tk_String, stripped );
+
+                       if ( RefPointNum == 0 ) { // Hard coded refpoint labels
+                               if ( stricmp( stripped,
+                                                         referenceRootNames[referenceRootNameOffsets[g_skelModel.references] + k] ) == 0 ) {
+                                       break;
+                               }
+                       }
+                       else
+                       {   // labels indicated by the QDT
+                               if ( stricmp( stripped, RefPointNameList[k] ) == 0 ) {
+                                       break;
+                               }
+                       }
+               }
+
+               if ( tk_Token == TK_EOF ) {
+                       if ( RefPointNum == 0 ) { // Hard coded refpoint labels
+                               Error( "Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]] );
+                       }
+                       else
+                       {   // labels indicated by the QDT
+                               Error( "Bone Chain Root: %s not found\n", RefPointNameList[k] );
+                       }
+                       return;
+               }
+
+//             TK_Beyond(TK_SCALING);
+
+//             ParseVec3d(curScale[currentStack]);
+
+               TK_Beyond( TK_ROTATION );
+
+               ParseRotation3d( curRotation[currentStack] );
+
+               TK_Beyond( TK_TRANSLATION );
+
+               ParseVec3d( curTranslation[currentStack] );
+
+               // account for global model translation
+               curTranslation[currentStack][1] += g_skelModel.translation[0];
+               curTranslation[currentStack][2] += g_skelModel.translation[1];
+               curTranslation[currentStack][0] += g_skelModel.translation[2];
+
+               curCorrespondingJoint[currentStack] = -1;
+
+//             rjr - this one not needed, as there is also a stack increment 20 lines below???
+//             ++currentStack;
+
+               // Load the joint to get orientation
+               TK_Beyond( TK_MODEL );
+
+//             TK_Beyond(TK_SCALING);
+
+//             ParseVec3d(curScale[currentStack]);
+
+               TK_Beyond( TK_ROTATION );
+
+               ParseRotation3d( curRotation[currentStack] );
+
+//             TK_Beyond(TK_TRANSLATION);
+
+//             ParseVec3d(curTranslation[currentStack]);
+
+               fr->references[k].placement.origin[1] = 0.0;
+               fr->references[k].placement.origin[2] = 0.0;
+               fr->references[k].placement.origin[0] = 0.0;
+
+               fr->references[k].placement.direction[1] = 20.0;
+               fr->references[k].placement.direction[2] = 0.0;
+               fr->references[k].placement.direction[0] = 0.0;
+
+               fr->references[k].placement.up[1] = 0.0;
+               fr->references[k].placement.up[2] = 20.0;
+               fr->references[k].placement.up[0] = 0.0;
+
+               curCorrespondingJoint[currentStack] = k;
+
+               ++currentStack;
+
+               stackSize = currentStack;
+
+               for ( i = stackSize - 1; i >= 0; --i )
+               {
+                       rx = curRotation[i][0] * ANGLE_TO_RAD;
+                       ry = curRotation[i][1] * ANGLE_TO_RAD;
+                       rz = curRotation[i][2] * ANGLE_TO_RAD;
+
+                       cx = cos( rx );
+                       sx = sin( rx );
+
+                       cy = cos( ry );
+                       sy = sin( ry );
+
+                       cz = cos( rz );
+                       sz = sin( rz );
+
+                       for ( j = i; j < stackSize; ++j )
+                       {
+                               if ( curCorrespondingJoint[j] != -1 ) {
+                                       placement = &fr->references[curCorrespondingJoint[j]].placement;
+
+                                       // y-axis rotation for origin
+                                       x2 = placement->origin[0] * cy + placement->origin[2] * sy;
+                                       z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
+                                       placement->origin[0] = x2;
+                                       placement->origin[2] = z2;
+
+                                       // y-axis rotation for direction
+                                       x2 = placement->direction[0] * cy + placement->direction[2] * sy;
+                                       z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
+                                       placement->direction[0] = x2;
+                                       placement->direction[2] = z2;
+
+                                       // y-axis rotation for up
+                                       x2 = placement->up[0] * cy + placement->up[2] * sy;
+                                       z2 = -placement->up[0] * sy + placement->up[2] * cy;
+                                       placement->up[0] = x2;
+                                       placement->up[2] = z2;
+
+                                       // z-axis rotation for origin
+                                       x2 = placement->origin[0] * cz - placement->origin[1] * sz;
+                                       y2 = placement->origin[0] * sz + placement->origin[1] * cz;
+                                       placement->origin[0] = x2;
+                                       placement->origin[1] = y2;
+
+                                       // z-axis rotation for direction
+                                       x2 = placement->direction[0] * cz - placement->direction[1] * sz;
+                                       y2 = placement->direction[0] * sz + placement->direction[1] * cz;
+                                       placement->direction[0] = x2;
+                                       placement->direction[1] = y2;
+
+                                       // z-axis rotation for up
+                                       x2 = placement->up[0] * cz - placement->up[1] * sz;
+                                       y2 = placement->up[0] * sz + placement->up[1] * cz;
+                                       placement->up[0] = x2;
+                                       placement->up[1] = y2;
+
+                                       // x-axis rotation for origin
+                                       y2 = placement->origin[1] * cx - placement->origin[2] * sx;
+                                       z2 = placement->origin[1] * sx + placement->origin[2] * cx;
+                                       placement->origin[1] = y2;
+                                       placement->origin[2] = z2;
+
+                                       // x-axis rotation for direction vector
+                                       y2 = placement->direction[1] * cx - placement->direction[2] * sx;
+                                       z2 = placement->direction[1] * sx + placement->direction[2] * cx;
+                                       placement->direction[1] = y2;
+                                       placement->direction[2] = z2;
+
+                                       // x-axis rotation for up vector
+                                       y2 = placement->up[1] * cx - placement->up[2] * sx;
+                                       z2 = placement->up[1] * sx + placement->up[2] * cx;
+                                       placement->up[1] = y2;
+                                       placement->up[2] = z2;
+
+                                       // translate origin
+                                       placement->origin[0] += curTranslation[i][0];
+                                       placement->origin[1] += curTranslation[i][1];
+                                       placement->origin[2] += curTranslation[i][2];
+
+                                       // translate back to local coord
+                                       placement->direction[0] += curTranslation[i][0];
+                                       placement->direction[1] += curTranslation[i][1];
+                                       placement->direction[2] += curTranslation[i][2];
+
+                                       // translate back to local coord
+                                       placement->up[0] += curTranslation[i][0];
+                                       placement->up[1] += curTranslation[i][1];
+                                       placement->up[2] += curTranslation[i][2];
+
+                               }
+                       }
+               }
+               printf( "%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2] );
+       }
+       printf( "\n" );
+}
+
+void Cmd_FMReferenced(){
+       int i;
+
+       GetScriptToken( false );
+       g_skelModel.references = atoi( token );
+
+       // Guess what?  Now, we now want a list of strings to look for here instead of a hard-coded list
+       for ( i = 0; i < REF_MAX_POINTS; i++ )
+       {
+               if ( ScriptTokenAvailable() ) { // There is yet another reference point waiting.
+                       GetScriptToken( false );
+                       strcpy( RefPointNameList[i], token );
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       RefPointNum = i;
+
+       if ( RefPointNum > 0 ) {
+               printf( "Searching for %d different reference points.\n", RefPointNum );
+       }
+       else
+       {
+               printf( "Using built-in reference points.\n" );
+       }
+
+}
+
+void LoadReferences( char *fileName, fmframe_t *fr ){
+       FILE *file1;
+       int dot = '.';
+       char *dotstart;
+       char InputFileName[256];
+
+       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
+
+       if ( !dotstart ) {
+               strcpy( InputFileName, fileName );
+               strcat( InputFileName, ".hrc" );
+               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
+                       fclose( file1 );
+
+                       LoadHRCReferences( InputFileName, fr );
+
+                       printf( " - assuming .HRC\n" );
+                       return;
+               }
+
+               Error( "\n Could not open file '%s':\n"
+                          "No HRC.\n", fileName );
+       }
+       else
+       {
+               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
+                       printf( "\n" );
+                       fclose( file1 );
+                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
+                               LoadHRCReferences( fileName, fr );
+
+                               return;
+                       }
+               }
+
+               Error( "Could not open file '%s':\n",fileName );
+       }
+}
+
+void GrabReferencedFrame( char *frame ){
+       char file1[1024];
+       char    *framefile;
+       fmframe_t   *fr;
+
+       framefile = FindFrameFile( frame );
+
+       sprintf( file1, "%s/%s", cdarchive, framefile );
+       ExpandPathAndArchive( file1 );
+
+       sprintf( file1, "%s/%s",cddir, framefile );
+
+       printf( "Grabbing Referenced %s\n", file1 );
+
+       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+       LoadReferences( file1, fr );
+}
diff --git a/tools/heretic2/h2data/qd_skeletons.h b/tools/heretic2/h2data/qd_skeletons.h
new file mode 100644 (file)
index 0000000..7765c57
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef QD_SKELETONS_H
+#define QD_SKELETONS_H
+
+#include "placement.h"
+
+
+typedef struct Placement_d_s
+{
+       vec3d_t origin;
+       vec3d_t direction;
+       vec3d_t up;
+} Placement_d_t;
+
+typedef struct QD_SkeletalJoint_s
+{
+       Placement_d_t placement;
+       vec3d_t rotation;
+} QD_SkeletalJoint_t;
+
+#define NUM_CLUSTERS 8
+
+typedef struct IntListNode_s
+{
+       int data;
+       struct IntListNode_s *next;
+} IntListNode_t;  // gaak
+
+typedef struct Skeletalfmheader_s
+{
+       int type;
+       int clustered;
+       int references;
+
+       int *clusters[NUM_CLUSTERS];
+       IntListNode_t *vertLists[NUM_CLUSTERS];
+       int num_verts[NUM_CLUSTERS + 1];
+       int new_num_verts[NUM_CLUSTERS + 1];
+
+       float scaling[3];
+       float rotation[3];
+       float translation[3];
+} Skeletalfmheader_t;
+
+#define SKELETAL_NAME_MAX 32
+
+extern Skeletalfmheader_t g_skelModel;
+
+void ClearSkeletalModel();
+void GrabModelTransform( char *frame );
+void GrabSkeletalFrame( char *frame );
+void GrabReferencedFrame( char *frame );
+
+// Reference Stuff
+#define NUM_REFERENCES 8
+
+#define REF_MAX_POINTS  16
+#define REF_MAX_STRLEN  32
+
+// We're assuming no more than 16 reference points, with no more than 32 characters in the name
+extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
+extern int RefPointNum;
+
+#endif
diff --git a/tools/heretic2/h2data/qdata.c b/tools/heretic2/h2data/qdata.c
new file mode 100644 (file)
index 0000000..38a3c28
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qdata.h"
+#include "globaldefs.h"
+#include "md4.h"
+
+void TK_Init();
+
+qboolean g_compress_pak;
+qboolean g_release;             // don't grab, copy output data to new tree
+qboolean g_pak;                 // if true, copy to pak instead of release
+char g_releasedir[1024];        // c:\quake2\baseq2, etc
+qboolean g_archive;             // don't grab, copy source data to new tree
+qboolean do3ds;
+char g_only[256];               // if set, only grab this cd
+qboolean g_skipmodel;           // set true when a cd is not g_only
+int g_forcemodel = MODEL_AUTO;
+qboolean g_verbose = false;
+qboolean g_allow_newskin = true;
+qboolean g_ignoreTriUV = false;
+qboolean g_publishOutput = false;
+
+char        *ext_3ds = "3ds";
+char        *ext_tri = "tri";
+char        *trifileext;
+
+char g_materialFile[256] = "none";          // default for Heretic2
+char        *g_outputDir;
+extern char *g_publishDir;
+
+extern qboolean g_nomkdir;
+
+/*
+   =======================================================
+
+   PAK FILES
+
+   =======================================================
+ */
+
+typedef struct
+{
+       char name[56];
+       int filepos, filelen;
+} packfile_t;
+
+typedef struct
+{
+       char id[4];
+       int dirofs;
+       int dirlen;
+} packheader_t;
+
+packfile_t pfiles[16384];
+FILE            *pakfile;
+packfile_t      *pf;
+packheader_t pakheader;
+
+
+
+/*
+   ==============
+   BeginPak
+   ==============
+ */
+void BeginPak( char *outname ){
+       if ( !g_pak ) {
+               return;
+       }
+
+       pakfile = SafeOpenWrite( outname );
+
+       // leave space for header
+       SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
+
+       pf = pfiles;
+}
+
+
+/*
+   ==============
+   ReleaseFile
+
+   Filename should be gamedir reletive.
+   Either copies the file to the release dir, or adds it to
+   the pak file.
+   ==============
+ */
+void ReleaseFile( char *filename ){
+       int len;
+       byte    *buf;
+       char source[1024];
+       char dest[1024];
+
+       if ( !g_release ) {
+               return;
+       }
+
+       sprintf( source, "%s%s", gamedir, filename );
+
+       if ( !g_pak ) { // copy it
+               sprintf( dest, "%s/%s", g_releasedir, filename );
+               printf( "copying to %s\n", dest );
+               QCopyFile( source, dest );
+               return;
+       }
+
+       // pak it
+       printf( "paking %s\n", filename );
+       if ( strlen( filename ) >= sizeof( pf->name ) ) {
+               Error( "Filename too long for pak: %s", filename );
+       }
+
+       len = LoadFile( source, (void **)&buf );
+
+       // segment moved to old.c
+
+       strcpy( pf->name, filename );
+       pf->filepos = LittleLong( ftell( pakfile ) );
+       pf->filelen = LittleLong( len );
+       pf++;
+
+       SafeWrite( pakfile, buf, len );
+
+       free( buf );
+}
+
+
+/*
+   ==============
+   FinishPak
+   ==============
+ */
+void FinishPak( void ){
+       int dirlen;
+       int d;
+       int i;
+       unsigned checksum;
+
+       if ( !g_pak ) {
+               return;
+       }
+
+       pakheader.id[0] = 'P';
+       pakheader.id[1] = 'A';
+       pakheader.id[2] = 'C';
+       pakheader.id[3] = 'K';
+       dirlen = (byte *)pf - (byte *)pfiles;
+       pakheader.dirofs = LittleLong( ftell( pakfile ) );
+       pakheader.dirlen = LittleLong( dirlen );
+
+       checksum = Com_BlockChecksum( (void *)pfiles, dirlen );
+
+       SafeWrite( pakfile, pfiles, dirlen );
+
+       i = ftell( pakfile );
+
+       fseek( pakfile, 0, SEEK_SET );
+       SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
+       fclose( pakfile );
+
+       d = pf - pfiles;
+       printf( "%i files packed in %i bytes\n",d, i );
+       printf( "checksum: 0x%x\n", checksum );
+}
+
+
+/*
+   ===============
+   Cmd_File
+
+   This is only used to cause a file to be copied during a release
+   build (default.cfg, maps, etc)
+   ===============
+ */
+void Cmd_File( void ){
+       GetScriptToken( false );
+       ReleaseFile( token );
+}
+
+/*
+   ===============
+   PackDirectory_r
+
+   ===============
+ */
+#if GDEF_OS_WINDOWS
+#include "io.h"
+void PackDirectory_r( char *dir ){
+       struct _finddata_t fileinfo;
+       int handle;
+       char dirstring[1024];
+       char filename[1024];
+
+       sprintf( dirstring, "%s%s/*.*", gamedir, dir );
+
+       handle = _findfirst( dirstring, &fileinfo );
+       if ( handle == -1 ) {
+               return;
+       }
+
+       do
+       {
+               sprintf( filename, "%s/%s", dir, fileinfo.name );
+               if ( fileinfo.attrib & _A_SUBDIR ) { // directory
+                       if ( fileinfo.name[0] != '.' ) {  // don't pak . and ..
+                               PackDirectory_r( filename );
+                       }
+                       continue;
+               }
+               // copy or pack the file
+               ReleaseFile( filename );
+       } while ( _findnext( handle, &fileinfo ) != -1 );
+
+       _findclose( handle );
+}
+#else
+
+#include <sys/types.h>
+#ifdef NeXT
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void PackDirectory_r( char *dir ){
+#ifdef NeXT
+       struct direct **namelist, *ent;
+#else
+       struct dirent **namelist, *ent;
+#endif
+       int count;
+       struct stat st;
+       int i;
+       int len;
+       char fullname[1024];
+       char dirstring[1024];
+       char        *name;
+
+       sprintf( dirstring, "%s%s", gamedir, dir );
+       count = scandir( dirstring, &namelist, NULL, NULL );
+
+       for ( i = 0 ; i < count ; i++ )
+       {
+               ent = namelist[i];
+               name = ent->d_name;
+
+               if ( name[0] == '.' ) {
+                       continue;
+               }
+
+               sprintf( fullname, "%s/%s", dir, name );
+               sprintf( dirstring, "%s%s/%s", gamedir, dir, name );
+
+               if ( stat( dirstring, &st ) == -1 ) {
+                       Error( "fstating %s", pf->name );
+               }
+               if ( st.st_mode & S_IFDIR ) { // directory
+                       PackDirectory_r( fullname );
+                       continue;
+               }
+
+               // copy or pack the file
+               ReleaseFile( fullname );
+       }
+}
+#endif
+
+
+/*
+   ===============
+   Cmd_Dir
+
+   This is only used to cause a directory to be copied during a
+   release build (sounds, etc)
+   ===============
+ */
+void Cmd_Dir( void ){
+       GetScriptToken( false );
+       PackDirectory_r( token );
+}
+
+//========================================================================
+
+#define MAX_RTEX    16384
+int numrtex;
+char rtex[MAX_RTEX][64];
+
+void ReleaseTexture( char *name ){
+       int i;
+       char path[1024];
+
+       for ( i = 0 ; i < numrtex ; i++ )
+               if ( !Q_strcasecmp( name, rtex[i] ) ) {
+                       return;
+               }
+
+       if ( numrtex == MAX_RTEX ) {
+               Error( "numrtex == MAX_RTEX" );
+       }
+
+       strcpy( rtex[i], name );
+       numrtex++;
+
+       sprintf( path, "textures/%s.wal", name );
+       ReleaseFile( path );
+}
+
+/*
+   ===============
+   Cmd_Maps
+
+   Only relevent for release and pak files.
+   Releases the .bsp files for the maps, and scans all of the files to
+   build a list of all textures used, which are then released.
+   ===============
+ */
+void Cmd_Maps( void ){
+       char map[1024];
+       int i;
+
+       while ( ScriptTokenAvailable() )
+       {
+               GetScriptToken( false );
+               sprintf( map, "maps/%s.bsp", token );
+               ReleaseFile( map );
+
+               if ( !g_release ) {
+                       continue;
+               }
+
+               // get all the texture references
+               sprintf( map, "%smaps/%s.bsp", gamedir, token );
+               LoadBSPFileTexinfo( map );
+               for ( i = 0 ; i < numtexinfo ; i++ )
+                       ReleaseTexture( texinfo[i].texture );
+       }
+}
+
+
+//==============================================================
+
+/*
+   ===============
+   ParseScript
+   ===============
+ */
+void ParseScript( void ){
+       while ( 1 )
+       {
+               do
+               {   // look for a line starting with a $ command
+                       GetScriptToken( true );
+                       if ( endofscript ) {
+                               return;
+                       }
+                       if ( token[0] == '$' ) {
+                               break;
+                       }
+                       while ( ScriptTokenAvailable() )
+                               GetScriptToken( false );
+               } while ( 1 );
+
+               //
+               // model commands
+               //
+               if ( !strcmp( token, "$modelname" ) ) {
+                       MODELCMD_Modelname( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$cd" ) ) {
+                       MODELCMD_Cd( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$origin" ) ) {
+                       MODELCMD_Origin( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$cluster" ) ) {
+                       MODELCMD_Cluster( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$base" ) ) {
+                       MODELCMD_Base( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$scale" ) ) {
+                       MODELCMD_ScaleUp( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$frame" ) ) {
+                       MODELCMD_Frame( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$skin" ) ) {
+                       MODELCMD_Skin( MODEL_MD2 );
+               }
+               else if ( !strcmp( token, "$skinsize" ) ) {
+                       MODELCMD_Skinsize( MODEL_MD2 );
+               }
+               //
+               // flexible model commands
+               //
+               else if ( !strcmp( token, "$fm_modelname" ) ) {
+                       MODELCMD_Modelname( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_base" ) ) {
+                       MODELCMD_Base( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_basest" ) ) {
+                       MODELCMD_BaseST( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_cd" ) ) {
+                       MODELCMD_Cd( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_origin" ) ) {
+                       MODELCMD_Origin( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_cluster" ) ) {
+                       MODELCMD_Cluster( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_skeleton" ) ) {
+                       MODELCMD_Skeleton( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_scale" ) ) {
+                       MODELCMD_ScaleUp( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_frame" ) ) {
+                       MODELCMD_Frame( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_skeletal_frame" ) ) { // left in for compadibility with qdt already using fm_skeletal_frame
+                       MODELCMD_Frame( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_skin" ) ) {
+                       MODELCMD_Skin( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_skinsize" ) ) {
+                       MODELCMD_Skinsize( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_begin_group" ) ) {
+                       MODELCMD_BeginGroup( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_end_group" ) ) {
+                       MODELCMD_EndGroup( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_referenced" ) ) {
+                       MODELCMD_Referenced( MODEL_FM );
+               }
+               else if ( !strcmp( token, "$fm_node_order" ) ) {
+                       MODELCMD_NodeOrder( MODEL_FM );
+               }
+
+               //
+               // sprite commands
+               //
+               else if ( !strcmp( token, "$spritename" ) ) {
+                       Cmd_SpriteName();
+               }
+               else if ( !strcmp( token, "$sprdir" ) ) {
+                       Cmd_Sprdir();
+               }
+               else if ( !strcmp( token, "$load" ) ) {
+                       Cmd_Load();
+               }
+               else if ( !strcmp( token, "$spriteframe" ) ) {
+                       Cmd_SpriteFrame();
+               }
+               //
+               // image commands
+               //
+               else if ( !strcmpi( token, "$grab" ) ) {
+                       Cmd_Grab();
+               }
+               else if ( !strcmpi( token, "$raw" ) ) {
+                       Cmd_Raw();
+               }
+               else if ( !strcmpi( token, "$colormap" ) ) {
+                       Cmd_Colormap();
+               }
+               else if ( !strcmpi( token, "$mippal" ) ) {
+                       Cmd_Mippal();
+               }
+               else if ( !strcmpi( token, "$mipdir" ) ) {
+                       Cmd_Mipdir();
+               }
+               else if ( !strcmpi( token, "$mip" ) ) {
+                       Cmd_Mip();
+               }
+               else if ( !strcmp( token, "$environment" ) ) {
+                       Cmd_Environment();
+               }
+               //
+               // pics
+               //
+               else if ( !strcmp( token, "$picdir" ) ) {
+                       Cmd_Picdir();
+               }
+               else if ( !strcmp( token, "$pic" ) ) {
+                       Cmd_Pic();
+               }
+               //
+               // book
+               //
+               else if ( !strcmp( token, "$bookdir" ) ) {
+                       Cmd_Bookdir();
+               }
+               else if ( !strcmp( token, "$book" ) ) {
+                       Cmd_Book();
+               }
+               //
+               // tmix
+               //
+               else if ( !strcmp( token, "$texturemix" ) ) {
+                       Cmd_TextureMix();
+               }
+               //
+               // video
+               //
+               else if ( !strcmp( token, "$video" ) ) {
+                       Cmd_Video();
+               }
+               //
+               // misc
+               //
+               else if ( !strcmp( token, "$file" ) ) {
+                       Cmd_File();
+               }
+               else if ( !strcmp( token, "$dir" ) ) {
+                       Cmd_Dir();
+               }
+               else if ( !strcmp( token, "$maps" ) ) {
+                       Cmd_Maps();
+               }
+               else if ( !strcmp( token, "$alphalight" ) ) {
+                       Cmd_Alphalight();
+               }
+               else if ( !strcmp( token, "$inverse16table" ) ) {
+                       Cmd_Inverse16Table();
+               }
+               else{
+                       Error( "bad command %s\n", token );
+               }
+       }
+}
+
+//=======================================================
+
+/*
+   ==============
+   main
+   ==============
+ */
+int main( int argc, char **argv ){
+       int i;
+       char path[1024];
+       char        *basedir;
+       double starttime, endtime;
+
+       printf( "Qdata Plus : "__TIME__ " "__DATE__ "\n" );
+
+       starttime = I_FloatTime();
+       basedir = NULL;
+
+       TK_Init();
+       ExpandWildcards( &argc, &argv );
+
+       for ( i = 1 ; i < argc ; i++ )
+       {
+               if ( !strcmp( argv[i], "-archive" ) ) {
+                       // -archive f:/quake2/release/dump_11_30
+                       archive = true;
+                       strcpy( archivedir, argv[i + 1] );
+                       printf( "Archiving source to: %s\n", archivedir );
+                       i++;
+               }
+               else if ( !strcmp( argv[i], "-release" ) ) {
+                       g_release = true;
+                       strcpy( g_releasedir, argv[i + 1] );
+                       printf( "Copy output to: %s\n", g_releasedir );
+                       i++;
+               }
+               else if ( !strcmp( argv[i], "-base" ) ) {
+                       i++;
+                       basedir = argv[i];
+               }
+               else if ( !strcmp( argv[i], "-compress" ) ) {
+                       g_compress_pak = true;
+                       printf( "Compressing pakfile\n" );
+               }
+               else if ( !strcmp( argv[i], "-pak" ) ) {
+                       g_release = true;
+                       g_pak = true;
+                       printf( "Building pakfile: %s\n", argv[i + 1] );
+                       BeginPak( argv[i + 1] );
+                       i++;
+               }
+               else if ( !strcmp( argv[i], "-only" ) ) {
+                       strcpy( g_only, argv[i + 1] );
+                       printf( "Only grabbing %s\n", g_only );
+                       i++;
+               }
+               else if ( !strcmpi( argv[i], "-keypress" ) ) {
+                       g_dokeypress = true;
+               }
+               else if ( !strcmp( argv[i], "-3ds" ) ) {
+                       do3ds = true;
+                       printf( "loading .3ds files\n" );
+               }
+               else if ( !strcmp( argv[i], "-materialfile" ) ) {
+                       strcpy( g_materialFile, argv[i + 1] );
+                       printf( "Setting material file to %s\n", g_materialFile );
+                       i++;
+               }
+/*             else if (!strcmpi(argv[i], "-newgen"))
+        {
+            if (i < argc-4)
+            {
+                printf("run new triangle grouping routine here\n");
+                NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
+            }
+            else
+            {
+                printf("h2data -newskin <base.hrc> <skin.pcx> width height\n");
+            }
+            return 0;
+        }
+ */     else if ( !strcmpi( argv[i], "-genskin" ) ) {
+                       i++;
+                       if ( i < argc - 3 ) {
+                               GenSkin( argv[i],argv[i + 1],atol( argv[i + 2] ),atol( argv[i + 3] ) );
+                       }
+                       else
+                       {
+                               printf( "h2data -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n" );
+                       }
+                       return 0;
+
+               }
+               else if ( !strcmpi( argv[i], "-noopts" ) ) {
+                       g_no_opimizations = true;
+                       printf( "not performing optimizations\n" );
+               }
+               else if ( !strcmpi( argv[i], "-md2" ) ) {
+                       g_forcemodel = MODEL_MD2;
+               }
+               else if ( !strcmpi( argv[i], "-fm" ) ) {
+                       g_forcemodel = MODEL_FM;
+               }
+               else if ( !strcmpi( argv[i], "-verbose" ) ) {
+                       g_verbose = true;
+               }
+               else if ( !strcmpi( argv[i], "-oldskin" ) ) {
+                       g_allow_newskin = false;
+               }
+               else if ( !strcmpi( argv[i], "-ignoreUV" ) ) {
+                       g_ignoreTriUV = true;
+               }
+               else if ( !strcmpi( argv[i], "-publish" ) ) {
+                       g_publishOutput = true;
+               }
+               else if ( !strcmpi( argv[i], "-nomkdir" ) ) {
+                       g_nomkdir = true;
+               }
+               else if ( argv[i][0] == '-' ) {
+                       Error( "Unknown option \"%s\"", argv[i] );
+               }
+               else{
+                       break;
+               }
+       }
+
+       if ( i >= argc ) {
+               Error( "usage: h2data [-archive <directory>]\n"
+                          "             [-release <directory>]\n"
+                          "             [-base <directory>]\n"
+                          "             [-compress]\n"
+                          "             [-pak <file>]\n"
+                          "             [-only <model>]\n"
+                          "             [-keypress]\n"
+                          "             [-3ds]\n"
+                          "             [-materialfile <file>]\n"
+                          "             [-noopts]\n"
+                          "             [-md2]\n"
+                          "             [-fm]\n"
+                          "             [-verbose]\n"
+                          "             [-ignoreUV]\n"
+                          "             [-oldskin]\n"
+                          "             [-publish]\n"
+                          "             [-nomkdir]\n"
+                          "             file.qdt\n"
+                          "or\n"
+                          "       h2data -genskin <base.hrc> <skin.pcx> <desired width> <desired height>" );
+       }
+
+       if ( do3ds ) {
+               trifileext = ext_3ds;
+       }
+       else{
+               trifileext = ext_tri;
+       }
+
+       for ( ; i < argc ; i++ )
+       {
+               printf( "--------------- %s ---------------\n", argv[i] );
+               // load the script
+               strcpy( path, argv[i] );
+               DefaultExtension( path, ".qdt" );
+               DefaultExtension( g_materialFile, ".mat" );
+               SetQdirFromPath( path );
+
+               printf( "workingdir='%s'\n", gamedir );
+               if ( basedir ) {
+                       qdir[0] = 0;
+                       g_outputDir = basedir;
+               }
+
+               printf( "outputdir='%s'\n", g_outputDir );
+
+               QFile_ReadMaterialTypes( g_materialFile );
+               LoadScriptFile( ExpandArg( path ) );
+
+               //
+               // parse it
+               //
+               ParseScript();
+
+               // write out the last model
+               FinishModel();
+               FMFinishModel();
+               FinishSprite();
+       }
+
+       if ( total_textures ) {
+               printf( "\n" );
+               printf( "Total textures processed: %d\n",total_textures );
+               printf( "Average size: %d x %d\n",total_x / total_textures, total_y / total_textures );
+       }
+
+       if ( g_pak ) {
+               FinishPak();
+       }
+
+       endtime = I_FloatTime();
+       printf( "Time elapsed:  %f\n", endtime - starttime );
+
+       if ( g_dokeypress ) {
+               printf( "Success! ... Hit a key: " );
+               getchar();
+       }
+
+       return 0;
+}
diff --git a/tools/heretic2/h2data/qdata.h b/tools/heretic2/h2data/qdata.h
new file mode 100644 (file)
index 0000000..1a9828f
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// qdata.h
+
+#include "globaldefs.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "scriplib.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "lbmlib.h"
+#include "her2_threads.h"
+#include "l3dslib.h"
+#include "bspfile.h"
+
+#if !GDEF_OS_WINDOWS
+#define stricmp strcasecmp
+#define strcmpi strcasecmp
+#endif
+
+
+#define MODEL_AUTO  0
+#define MODEL_MD2   1
+#define MODEL_FM    2
+
+// Model cover functions (to allow the forcing of a model type)
+void MODELCMD_Modelname( int modeltype );
+void MODELCMD_Cd( int modeltype );
+void MODELCMD_Origin( int modeltype );
+void MODELCMD_Jointed( int modeltype );
+void MODELCMD_Cluster( int modeltype );
+void MODELCMD_Base( int modeltype );
+void MODELCMD_BaseST( int modeltype );
+void MODELCMD_ScaleUp( int modeltype );
+void MODELCMD_Frame( int modeltype );
+void MODELCMD_Skin( int modeltype );
+void MODELCMD_Skinsize( int modeltype );
+void MODELCMD_Skeleton( int modeltype );
+void MODELCMD_SkeletalFrame( int modeltype );
+void MODELCMD_BeginGroup( int modeltype );
+void MODELCMD_EndGroup( int modeltype );
+void MODELCMD_Referenced( int modeltype );
+void MODELCMD_NodeOrder( int modeltype );
+
+void Cmd_Modelname( void );
+void Cmd_Base( void );
+void Cmd_Cd( void );
+void Cmd_Origin( void );
+void Cmd_ScaleUp( void );
+void Cmd_Frame( void );
+void Cmd_Skin( void );
+void Cmd_Skinsize( void );
+void FinishModel( void );
+void Cmd_Cluster( void );
+
+// Flexible Models
+//void Cmd_FMModelname (void);
+void Cmd_FMBase( qboolean GetST );
+void Cmd_FMCd( void );
+//void Cmd_FMOrigin (void);
+void Cmd_FMCluster();
+void Cmd_FMSkeleton();
+//void Cmd_FMScaleUp (void);
+void Cmd_FMFrame( void );
+void Cmd_FMSkeletalFrame();
+void Cmd_FMSkin( void );
+//void Cmd_FMSkinsize (void);
+void Cmd_FMBeginGroup( void );
+void Cmd_FMEndGroup( void );
+void Cmd_FMReferenced();
+void Cmd_FMNodeOrder( void );
+void FMFinishModel( void );
+void GenSkin( char *ModelFile, char *OutputName, int Width, int Height );
+void NewGen( char *ModelFile, char *OutputName, int width, int height );
+
+
+void Cmd_Inverse16Table( void );
+
+void Cmd_SpriteName( void );
+void Cmd_Load( void );
+void Cmd_SpriteFrame( void );
+void Cmd_Sprdir( void );
+void FinishSprite( void );
+
+void Cmd_Grab( void );
+void Cmd_Raw( void );
+void Cmd_Mip( void );
+void Cmd_Environment( void );
+void Cmd_Colormap( void );
+
+void Cmd_File( void );
+void Cmd_Dir( void );
+void Cmd_StartWad( void );
+void Cmd_EndWad( void );
+void Cmd_Mippal( void );
+void Cmd_Mipdir( void );
+void Cmd_Alphalight( void );
+
+void Cmd_Picdir( void );
+void Cmd_Pic( void );
+
+void Cmd_Bookdir( void );
+void Cmd_Book( void );
+
+void Cmd_TextureMix( void );
+
+void Cmd_Video( void );
+
+//void RemapZero (byte *pixels, byte *palette, int width, int height);
+
+void ReleaseFile( char *filename );
+
+extern byte *byteimage, *lbmpalette;
+extern int byteimagewidth, byteimageheight;
+extern qboolean TrueColorImage;
+extern unsigned *longimage;
+extern int longimagewidth, longimageheight;
+
+extern qboolean g_release;              // don't grab, copy output data to new tree
+extern char g_releasedir[1024];         // c:\quake2\baseq2, etc
+extern qboolean g_archive;              // don't grab, copy source data to new tree
+extern qboolean do3ds;
+extern char g_only[256];                // if set, only grab this cd
+extern qboolean g_skipmodel;            // set true when a cd is not g_only
+extern qboolean g_no_opimizations;
+extern int g_forcemodel;
+extern qboolean g_verbose;
+extern qboolean g_allow_newskin;
+extern qboolean g_ignoreTriUV;      //from qdata.c
+extern qboolean g_dokeypress;
+
+extern char        *trifileext;
+
+extern char g_materialFile[256];
+
+extern unsigned total_x;
+extern unsigned total_y;
+extern unsigned total_textures;
+
+miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip );
+miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip );
diff --git a/tools/heretic2/h2data/resource.h b/tools/heretic2/h2data/resource.h
new file mode 100644 (file)
index 0000000..3d6343e
--- /dev/null
@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Script1.rc
+//
+#define IDI_ICON1                       101
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC                     1
+#define _APS_3D_CONTROLS                     1
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/tools/heretic2/h2data/sprites.c b/tools/heretic2/h2data/sprites.c
new file mode 100644 (file)
index 0000000..8bd84ba
--- /dev/null
@@ -0,0 +1,337 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include "qdata.h"
+
+#define MAX_SPRFRAMES           MAX_MD2SKINS
+
+dsprite_t sprite;
+static dsprframe_t frames[MAX_SPRFRAMES];
+
+char spritename[1024];
+
+
+void FinishSprite( void );
+void Cmd_Spritename( void );
+
+char spr_prefix[1024];
+
+extern char        *g_outputDir;
+
+
+/*
+   ==============
+   FinishSprite
+   ==============
+ */
+void FinishSprite( void ){
+       FILE    *spriteouthandle;
+       int i, curframe;
+       dsprite_t spritetemp;
+       char savename[1024];
+
+       if ( sprite.numframes == 0 ) {
+               return;
+       }
+
+       if ( !strlen( spritename ) ) {
+               Error( "Didn't name sprite file" );
+       }
+
+       sprintf( savename, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, spritename );
+
+       if ( g_release ) {
+               char name[1024];
+
+               sprintf( name, "%s.sp2", spritename );
+               ReleaseFile( name );
+               spritename[0] = 0;      // clear for a new sprite
+               sprite.numframes = 0;
+               return;
+       }
+
+
+       printf( "saving in %s\n", savename );
+       CreatePath( savename );
+       spriteouthandle = SafeOpenWrite( savename );
+
+
+//
+// write out the sprite header
+//
+       spritetemp.ident = LittleLong( IDSPRITEHEADER );
+       spritetemp.version = LittleLong( SPRITE_VERSION );
+       spritetemp.numframes = LittleLong( sprite.numframes );
+
+       SafeWrite( spriteouthandle, &spritetemp, 12 );
+
+//
+// write out the frames
+//
+       curframe = 0;
+
+       for ( i = 0 ; i < sprite.numframes ; i++ )
+       {
+               frames[i].width = LittleLong( frames[i].width );
+               frames[i].height = LittleLong( frames[i].height );
+               frames[i].origin_x = LittleLong( frames[i].origin_x );
+               frames[i].origin_y = LittleLong( frames[i].origin_y );
+       }
+       SafeWrite( spriteouthandle, frames, sizeof( frames[0] ) * sprite.numframes );
+
+       fclose( spriteouthandle );
+
+       spritename[0] = 0;      // clear for a new sprite
+       sprite.numframes = 0;
+}
+
+
+/*
+   ===============
+   Cmd_Load
+   ===============
+ */
+void Cmd_Load( void ){
+       char    *name;
+
+       GetScriptToken( false );
+
+       if ( g_release ) {
+               return;
+       }
+
+       name = ExpandPathAndArchive( token );
+
+       // load the image
+       printf( "loading %s\n", name );
+       TrueColorImage = LoadAnyImage( name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight );
+
+       if ( !TrueColorImage ) {
+//             RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight);
+       }
+       else
+       {
+               if ( longimage ) {
+                       free( longimage );
+               }
+               longimage = (unsigned *)byteimage;
+               longimagewidth = byteimagewidth;
+               longimageheight = byteimageheight;
+
+               byteimage = NULL;
+               byteimagewidth = 0;
+               byteimageheight = 0;
+       }
+}
+
+
+/*
+   ===============
+   Cmd_SpriteFrame
+   ===============
+ */
+
+void Cmd_SpriteFrame( void ){
+       int x,y,xl,yl,xh,yh,w,h;
+       dsprframe_t     *pframe;
+       int ox, oy, linedelta, size;
+//     byte                    *cropped;
+       char filename[1024];
+       miptex_t        *qtex;
+       miptex32_t      *qtex32;
+       unsigned        *destl, *sourcel;
+       unsigned bufferl[256 * 256];
+       byte            *dest, *source;
+       byte buffer[256 * 256];
+
+       GetScriptToken( false );
+       xl = atoi( token );
+       GetScriptToken( false );
+       yl = atoi( token );
+       GetScriptToken( false );
+       w = atoi( token );
+       GetScriptToken( false );
+       h = atoi( token );
+
+       // origin offset is optional
+       if ( ScriptTokenAvailable() ) {
+               GetScriptToken( false );
+               ox = atoi( token );
+               GetScriptToken( false );
+               oy = atoi( token );
+       }
+       else
+       {
+               ox = w / 2;
+               oy = h / 2;
+       }
+
+       if ( ( xl & 0x0f ) || ( yl & 0x0f ) || ( w & 0x0f ) || ( h & 0x0f ) ) {
+               Error( "Sprite dimensions not multiples of 16\n" );
+       }
+
+       if ( ( w > 256 ) || ( h > 256 ) ) {
+               Error( "Sprite has a dimension longer than 256" );
+       }
+
+       xh = xl + w;
+       yh = yl + h;
+
+       if ( sprite.numframes >= MAX_SPRFRAMES ) {
+               Error( "Too many frames; increase MAX_SPRFRAMES\n" );
+       }
+
+       pframe = &frames[sprite.numframes];
+       pframe->width = w;
+       pframe->height = h;
+       pframe->origin_x = ox;
+       pframe->origin_y = oy;
+
+       if ( g_release ) {
+               ReleaseFile( pframe->name );
+               return;
+       }
+
+       if ( TrueColorImage ) {
+               sprintf( filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes );
+               sprintf( pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes );
+
+               if ( g_release ) {
+                       return; // textures are only released by $maps
+
+               }
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= longimagewidth || xh > longimagewidth ||
+                        yl >= longimageheight || yh > longimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
+               }
+
+               sourcel = longimage + ( yl * longimagewidth ) + xl;
+               destl = bufferl;
+               linedelta = ( longimagewidth - w );
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *destl++ = *sourcel++;  // RGBA
+                       }
+                       sourcel += linedelta;
+               }
+
+               qtex32 = CreateMip32( bufferl, w, h, &size, true );
+
+               qtex32->contents = 0;
+               qtex32->value = 0;
+               strcpy( qtex32->name, pframe->name );
+               //
+               // write it out
+               //
+               printf( "writing %s\n", filename );
+               SaveFile( filename, (byte *)qtex32, size );
+
+               free( qtex32 );
+       }
+       else
+       {
+               sprintf( filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes );
+               sprintf( pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes );
+
+               if ( g_release ) {
+                       return; // textures are only released by $maps
+
+               }
+               xh = xl + w;
+               yh = yl + h;
+
+               if ( xl >= byteimagewidth || xh > byteimagewidth ||
+                        yl >= byteimageheight || yh > byteimageheight ) {
+                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
+               }
+
+               source = byteimage + yl * byteimagewidth + xl;
+               dest = buffer;
+               linedelta = byteimagewidth - w;
+
+               for ( y = yl ; y < yh ; y++ )
+               {
+                       for ( x = xl ; x < xh ; x++ )
+                       {
+                               *dest++ = *source++;
+                       }
+                       source += linedelta;
+               }
+
+               qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
+
+               qtex->flags = 0;
+               qtex->contents = 0;
+               qtex->value = 0;
+               strcpy( qtex->name, pframe->name );
+               //
+               // write it out
+               //
+               printf( "writing %s\n", filename );
+               SaveFile( filename, (byte *)qtex, size );
+
+               free( qtex );
+       }
+
+       sprite.numframes++;
+}
+
+
+/*
+   ==============
+   Cmd_SpriteName
+   ==============
+ */
+void Cmd_SpriteName( void ){
+       if ( sprite.numframes ) {
+               FinishSprite();
+       }
+
+       GetScriptToken( false );
+       strcpy( spritename, token );
+       memset( &sprite, 0, sizeof( sprite ) );
+       memset( &frames, 0, sizeof( frames ) );
+}
+
+
+/*
+   ===============
+   Cmd_Sprdir
+   ===============
+ */
+void Cmd_Sprdir( void ){
+       char filename[1024];
+
+       GetScriptToken( false );
+       strcpy( spr_prefix, token );
+       // create the directory if needed
+       sprintf( filename, "%sSprites", g_outputDir );
+       Q_mkdir( filename );
+       sprintf( filename, "%sSprites/%s", g_outputDir, spr_prefix );
+       Q_mkdir( filename );
+}
diff --git a/tools/heretic2/h2data/svdcmp.c b/tools/heretic2/h2data/svdcmp.c
new file mode 100644 (file)
index 0000000..14865af
--- /dev/null
@@ -0,0 +1,487 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+static double at,bt,ct;
+#define PYTHAG( a,b ) ( ( at = fabs( a ) ) > ( bt = fabs( b ) ) ? \
+                                               ( ct = bt / at,at * sqrt( 1.0 + ct * ct ) ) : ( bt ? ( ct = at / bt,bt * sqrt( 1.0 + ct * ct ) ) : 0.0 ) )
+
+static double maxarg1,maxarg2;
+#define MAX( a,b ) ( maxarg1 = ( a ),maxarg2 = ( b ),( maxarg1 ) > ( maxarg2 ) ? \
+                                        ( maxarg1 ) : ( maxarg2 ) )
+#define SIGN( a,b ) ( ( b ) >= 0.0 ? fabs( a ) : -fabs( a ) )
+
+void ntrerror( char *s ){
+       printf( "%s\n",s );
+       exit( 1 );
+}
+
+double *allocVect( int sz ){
+       double *ret;
+
+       ret = calloc( sizeof( double ), (size_t)sz );
+       return ret;
+}
+
+void freeVect( double *ret ){
+       free( ret );
+}
+
+double **allocMatrix( int r,int c ){
+       double **ret;
+
+       ret = calloc( sizeof( double ), (size_t)( r * c ) );
+       return ret;
+}
+
+void freeMatrix( double **ret,int r ){
+       free( ret );
+}
+
+void svdcmp( double** a, int m, int n, double* w, double** v ){
+       int flag,i,its,j,jj,k,l,nm;
+       double c,f,h,s,x,y,z;
+       double anorm = 0.0,g = 0.0,scale = 0.0;
+       double *rv1;
+       void nrerror();
+
+       if ( m < n ) {
+               ntrerror( "SVDCMP: You must augment A with extra zero rows" );
+       }
+       rv1 = allocVect( n );
+       for ( i = 1; i <= n; i++ ) {
+               l = i + 1;
+               rv1[i] = scale * g;
+               g = s = scale = 0.0;
+               if ( i <= m ) {
+                       for ( k = i; k <= m; k++ ) scale += fabs( a[k][i] );
+                       if ( scale ) {
+                               for ( k = i; k <= m; k++ ) {
+                                       a[k][i] /= scale;
+                                       s += a[k][i] * a[k][i];
+                               }
+                               f = a[i][i];
+                               g = -SIGN( sqrt( s ),f );
+                               h = f * g - s;
+                               a[i][i] = f - g;
+                               if ( i != n ) {
+                                       for ( j = l; j <= n; j++ ) {
+                                               for ( s = 0.0,k = i; k <= m; k++ ) s += a[k][i] * a[k][j];
+                                               f = s / h;
+                                               for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i];
+                                       }
+                               }
+                               for ( k = i; k <= m; k++ ) a[k][i] *= scale;
+                       }
+               }
+               w[i] = scale * g;
+               g = s = scale = 0.0;
+               if ( i <= m && i != n ) {
+                       for ( k = l; k <= n; k++ ) scale += fabs( a[i][k] );
+                       if ( scale ) {
+                               for ( k = l; k <= n; k++ ) {
+                                       a[i][k] /= scale;
+                                       s += a[i][k] * a[i][k];
+                               }
+                               f = a[i][l];
+                               g = -SIGN( sqrt( s ),f );
+                               h = f * g - s;
+                               a[i][l] = f - g;
+                               for ( k = l; k <= n; k++ ) rv1[k] = a[i][k] / h;
+                               if ( i != m ) {
+                                       for ( j = l; j <= m; j++ ) {
+                                               for ( s = 0.0,k = l; k <= n; k++ ) s += a[j][k] * a[i][k];
+                                               for ( k = l; k <= n; k++ ) a[j][k] += s * rv1[k];
+                                       }
+                               }
+                               for ( k = l; k <= n; k++ ) a[i][k] *= scale;
+                       }
+               }
+               anorm = MAX( anorm,( fabs( w[i] ) + fabs( rv1[i] ) ) );
+       }
+       for ( i = n; i >= 1; i-- ) {
+               if ( i < n ) {
+                       if ( g ) {
+                               for ( j = l; j <= n; j++ )
+                                       v[j][i] = ( a[i][j] / a[i][l] ) / g;
+                               for ( j = l; j <= n; j++ ) {
+                                       for ( s = 0.0,k = l; k <= n; k++ ) s += a[i][k] * v[k][j];
+                                       for ( k = l; k <= n; k++ ) v[k][j] += s * v[k][i];
+                               }
+                       }
+                       for ( j = l; j <= n; j++ ) v[i][j] = v[j][i] = 0.0;
+               }
+               v[i][i] = 1.0;
+               g = rv1[i];
+               l = i;
+       }
+       for ( i = n; i >= 1; i-- ) {
+               l = i + 1;
+               g = w[i];
+               if ( i < n ) {
+                       for ( j = l; j <= n; j++ ) a[i][j] = 0.0;
+               }
+               if ( g ) {
+                       g = 1.0 / g;
+                       if ( i != n ) {
+                               for ( j = l; j <= n; j++ ) {
+                                       for ( s = 0.0,k = l; k <= m; k++ ) s += a[k][i] * a[k][j];
+                                       f = ( s / a[i][i] ) * g;
+                                       for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i];
+                               }
+                       }
+                       for ( j = i; j <= m; j++ ) a[j][i] *= g;
+               }
+               else {
+                       for ( j = i; j <= m; j++ ) a[j][i] = 0.0;
+               }
+               ++a[i][i];
+       }
+       for ( k = n; k >= 1; k-- ) {
+               for ( its = 1; its <= 30; its++ ) {
+                       flag = 1;
+                       for ( l = k; l >= 1; l-- ) {
+                               nm = l - 1;
+                               if ( fabs( rv1[l] ) + anorm == anorm ) {
+                                       flag = 0;
+                                       break;
+                               }
+                               if ( fabs( w[nm] ) + anorm == anorm ) {
+                                       break;
+                               }
+                       }
+                       if ( flag ) {
+                               c = 0.0;
+                               s = 1.0;
+                               for ( i = l; i <= k; i++ ) {
+                                       f = s * rv1[i];
+                                       if ( fabs( f ) + anorm != anorm ) {
+                                               g = w[i];
+                                               h = PYTHAG( f,g );
+                                               w[i] = h;
+                                               h = 1.0 / h;
+                                               c = g * h;
+                                               s = ( -f * h );
+                                               for ( j = 1; j <= m; j++ ) {
+                                                       y = a[j][nm];
+                                                       z = a[j][i];
+                                                       a[j][nm] = y * c + z * s;
+                                                       a[j][i] = z * c - y * s;
+                                               }
+                                       }
+                               }
+                       }
+                       z = w[k];
+                       if ( l == k ) {
+                               if ( z < 0.0 ) {
+                                       w[k] = -z;
+                                       for ( j = 1; j <= n; j++ ) v[j][k] = ( -v[j][k] );
+                               }
+                               break;
+                       }
+                       if ( its == 30 ) {
+                               ntrerror( "No convergence in 30 SVDCMP iterations" );
+                       }
+                       x = w[l];
+                       nm = k - 1;
+                       y = w[nm];
+                       g = rv1[nm];
+                       h = rv1[k];
+                       f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0 * h * y );
+                       g = PYTHAG( f,1.0 );
+                       f = ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + SIGN( g,f ) ) ) - h ) ) / x;
+                       c = s = 1.0;
+                       for ( j = l; j <= nm; j++ ) {
+                               i = j + 1;
+                               g = rv1[i];
+                               y = w[i];
+                               h = s * g;
+                               g = c * g;
+                               z = PYTHAG( f,h );
+                               rv1[j] = z;
+                               c = f / z;
+                               s = h / z;
+                               f = x * c + g * s;
+                               g = g * c - x * s;
+                               h = y * s;
+                               y = y * c;
+                               for ( jj = 1; jj <= n; jj++ ) {
+                                       x = v[jj][j];
+                                       z = v[jj][i];
+                                       v[jj][j] = x * c + z * s;
+                                       v[jj][i] = z * c - x * s;
+                               }
+                               z = PYTHAG( f,h );
+                               w[j] = z;
+                               if ( z ) {
+                                       z = 1.0 / z;
+                                       c = f * z;
+                                       s = h * z;
+                               }
+                               f = ( c * g ) + ( s * y );
+                               x = ( c * y ) - ( s * g );
+                               for ( jj = 1; jj <= m; jj++ ) {
+                                       y = a[jj][j];
+                                       z = a[jj][i];
+                                       a[jj][j] = y * c + z * s;
+                                       a[jj][i] = z * c - y * s;
+                               }
+                       }
+                       rv1[l] = 0.0;
+                       rv1[k] = f;
+                       w[k] = x;
+               }
+       }
+       freeVect( rv1 );
+}
+
+
+
+void svbksb( double** u, double* w, double** v,int m, int n, double* b, double* x ){
+       int jj,j,i;
+       double s,*tmp;
+       tmp = allocVect( n );
+       for ( j = 1; j <= n; j++ )
+       {
+               s = 0.0;
+               if ( w[j] ) {
+                       for ( i = 1; i <= m; i++ )
+                               s += u[i][j] * b[i];
+                       s /= w[j];
+               }
+               tmp[j] = s;
+       }
+       for ( j = 1; j <= n; j++ )
+       {
+               s = 0.0;
+               for ( jj = 1; jj <= n; jj++ )
+                       s += v[j][jj] * tmp[jj];
+               x[j] = s;
+       }
+       freeVect( tmp );
+}
+
+#undef SIGN
+#undef MAX
+#undef PYTHAG
+
+
+#if 1
+void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){
+       int usedfs;
+       int *remap;
+       int i,j;
+       double **da;
+       double **v;
+       double *w;
+       int DOFerr;
+       float mx;
+       int bestat;
+
+       if ( nframes > framesize ) {
+               usedfs = nframes;
+       }
+       else{
+               usedfs = framesize;
+       }
+
+       da = allocMatrix( usedfs,nframes );
+       v = allocMatrix( nframes,nframes );
+       w = allocVect( nframes );
+
+       DOFerr = 0; //false
+       for ( i = 0; i < nframes; i++ )
+       {
+               for ( j = 0; j < framesize; j++ )
+                       da[j + 1][i + 1] = a[i * framesize + j];
+               for (; j < usedfs; j++ )
+                       da[j + 1][i + 1] = 0.0;
+       }
+
+       svdcmp( da,usedfs,nframes,w,v );
+
+       remap = calloc( sizeof( int ), (size_t)nframes );
+
+
+       for ( i = 0; i < nframes; i++ )
+               remap[i] = -1;
+       for ( j = 0; j < compressedsize; j++ )
+       {
+               mx = -1.0f;
+               for ( i = 0; i < nframes; i++ )
+               {
+                       if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) {
+                               mx = (float) fabs( w[i + 1] );
+                               bestat = i;
+                       }
+               }
+
+               if ( mx > 0 ) {
+                       remap[bestat] = j;
+               }
+               else
+               {
+                       DOFerr = 1; //true
+               }
+       }
+
+       if ( DOFerr ) {
+               printf( "Warning:  To many degrees of freedom!  File size may increase\n" );
+
+               for ( i = 0; i < compressedsize; i++ )
+               {
+                       values[i] = 0;
+                       for ( j = 0; j < framesize; j++ )
+                               res[i * framesize + j] = 0;
+               }
+       }
+
+       for ( i = 0; i < nframes; i++ )
+       {
+               if ( remap[i] < 0 ) {
+                       w[i + 1] = 0.0;
+               }
+               else
+               {
+                       values[remap[i]] = (float) w[i + 1];
+                       for ( j = 0; j < framesize; j++ )
+                               res[remap[i] * framesize + j] = (float) da[j + 1][i + 1];
+               }
+       }
+       freeVect( w );
+       freeMatrix( v,nframes );
+       freeMatrix( da,framesize );
+       free( remap );
+}
+
+#else
+
+void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){
+       int *remap;
+       int i,j;
+       int nrows;
+       nrows = nframes;
+       if ( nrows < framesize ) {
+               nrows = framesize;
+       }
+       double **da = allocMatrix( nrows,framesize );
+       double **v = allocMatrix( framesize,framesize );
+       double *w = allocVect( framesize );
+       float mx;
+       int bestat;
+
+       for ( j = 0; j < framesize; j++ )
+       {
+               for ( i = 0; i < nframes; i++ )
+                       da[j + 1][i + 1] = a[i * framesize + j];
+               for (; i < nrows; i++ )
+                       da[j + 1][i + 1] = 0.0;
+       }
+
+       svdcmp( da,nrows,framesize,w,v );
+
+       remap = new int[framesize];
+
+
+       for ( i = 0; i < framesize; i++ )
+               remap[i] = -1;
+       for ( j = 0; j < compressedsize; j++ )
+       {
+               mx = -1.0f;
+               for ( i = 0; i < framesize; i++ )
+               {
+                       if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) {
+                               mx = fabs( w[i + 1] );
+                               bestat = i;
+                       }
+               }
+               assert( mx > -.5f );
+               remap[bestat] = j;
+       }
+       // josh **DO NOT** put your dof>nframes mod here
+       for ( i = 0; i < framesize; i++ )
+       {
+               if ( remap[i] < 0 ) {
+                       w[i + 1] = 0.0;
+               }
+               else
+               {
+                       values[remap[i]] = w[i + 1];
+                       for ( j = 0; j < framesize; j++ )
+                               res[remap[i] * framesize + j] = v[j + 1][i + 1];
+               }
+       }
+       freeVect( w );
+       freeMatrix( v,framesize );
+       freeMatrix( da,nrows );
+       delete[] remap;
+}
+
+#endif
+
+void DOsvdPlane( float *pnts,int npnts,float *n,float *base ){
+       int i,j;
+       double **da = allocMatrix( npnts,3 );
+       double **v = allocMatrix( 3,3 );
+       double *w = allocVect( 3 );
+       float mn = 1E30f;
+       int bestat;
+
+
+       assert( npnts >= 3 );
+       base[0] = pnts[0];
+       base[1] = pnts[1];
+       base[2] = pnts[2];
+       for ( i = 1; i < npnts; i++ )
+       {
+               for ( j = 0; j < 3; j++ )
+                       base[j] += pnts[i * 3 + j];
+       }
+       base[0] /= (float)( npnts );
+       base[1] /= (float)( npnts );
+       base[2] /= (float)( npnts );
+
+       for ( i = 0; i < 3; i++ )
+       {
+               for ( j = 0; j < npnts; j++ )
+                       da[j + 1][i + 1] = pnts[j * 3 + i] - base[i];
+       }
+
+       svdcmp( da,npnts,3,w,v );
+       for ( i = 0; i < 3; i++ )
+       {
+               if ( fabs( w[i + 1] ) < mn ) {
+                       mn = (float) fabs( w[i + 1] );
+                       bestat = i;
+               }
+       }
+       n[0] = (float) v[1][bestat + 1];
+       n[1] = (float) v[2][bestat + 1];
+       n[2] = (float) v[3][bestat + 1];
+       freeVect( w );
+       freeMatrix( v,3 );
+       freeMatrix( da,npnts );
+}
diff --git a/tools/heretic2/h2data/tables.c b/tools/heretic2/h2data/tables.c
new file mode 100644 (file)
index 0000000..ad86c1e
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qdata.h"
+
+/*
+   =============================================================================
+
+   ALPHALIGHT GENERATION
+
+   Find alphamap values that best match modulated lightmap values
+
+   This isn't used anymore, but I'm keeping it around...
+   =============================================================================
+ */
+
+unsigned short alphamap[32 * 32 * 32];
+unsigned char inverse16to8table[65536];
+
+/*
+   static int FindNearestColor( unsigned int color )
+   {
+    int i;
+    int closest_so_far = 0;
+    float closest_distance_so_far = 100000000;
+    float d;
+    float r[2], g[2], b[2];
+
+    // incoming color is assumed to be in 0xRRGGBB format
+    r[0] = ( color & 31 ) << 3;
+    g[0] = ( ( color >> 5 ) & 63 ) << 2;
+    b[0] = ( ( color >> 11 ) & 31 ) << 3;
+
+    for ( i = 0; i < 256; i++ )
+    {
+        r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
+        g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
+        b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
+
+        d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
+            ( g[1] - g[0] ) * ( g[1] - g[0] ) +
+            ( b[1] - b[0] ) * ( b[1] - b[0] );
+
+        if ( d < closest_distance_so_far )
+        {
+            closest_distance_so_far = d;
+            closest_so_far = i;
+        }
+    }
+
+    return closest_so_far;
+   }
+ */
+
+extern byte BestColor( int, int, int, int, int );
+
+void Inverse16_BuildTable( void ){
+       int i;
+
+       /*
+       ** create the 16-to-8 table
+       */
+       for ( i = 0; i < 65536; i++ )
+       {
+               int r = i & 31;
+               int g = ( i >> 5 ) & 63;
+               int b = ( i >> 11 ) & 31;
+
+               r <<= 3;
+               g <<= 2;
+               b <<= 3;
+
+               inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
+       }
+}
+
+void Alphalight_Thread( int i ){
+       int j;
+       float r, g, b;
+       float mr, mg, mb, ma;
+       float distortion, bestdistortion;
+       float v;
+
+       r = ( i >> 10 ) * ( 1.0 / 16 );
+       g = ( ( i >> 5 ) & 31 )  * ( 1.0 / 16 );
+       b = ( i & 31 ) * ( 1.0 / 16 );
+
+       bestdistortion = 999999;
+       for ( j = 0 ; j < 16 * 16 * 16 * 16 ; j++ )
+       {
+               mr = ( j >> 12 ) * ( 1.0 / 16 );
+               mg = ( ( j >> 8 ) & 15 ) * ( 1.0 / 16 );
+               mb = ( ( j >> 4 ) & 15 ) * ( 1.0 / 16 );
+               ma = ( j & 15 ) * ( 1.0 / 16 );
+
+               v = r * 0.5 - ( mr * ma + 0.5 * ( 1.0 - ma ) );
+               distortion = v * v;
+               v = g * 0.5 - ( mg * ma + 0.5 * ( 1.0 - ma ) );
+               distortion += v * v;
+               v = b * 0.5 - ( mb * ma + 0.5 * ( 1.0 - ma ) );
+               distortion += v * v;
+
+               distortion *= 1.0 + ma * 4;
+
+               if ( distortion < bestdistortion ) {
+                       bestdistortion = distortion;
+                       alphamap[i] = j;
+               }
+       }
+}
+
+void Cmd_Alphalight( void ){
+       char savename[1024];
+
+       GetScriptToken( false );
+
+       if ( g_release ) {
+               ReleaseFile( token );
+               return;
+       }
+
+       sprintf( savename, "%s%s", gamedir, token );
+       printf( "Building alphalight table...\n" );
+
+       RunThreadsOnIndividual( 32 * 32 * 32, true, Alphalight_Thread );
+
+       SaveFile( savename, (byte *)alphamap, sizeof( alphamap ) );
+}
+
+
+void Cmd_Inverse16Table( void ){
+       char savename[1024];
+
+       if ( g_release ) {
+               sprintf( savename, "pics/16to8.dat" );
+               ReleaseFile( savename );
+               return;
+       }
+
+       sprintf( savename, "%spics/16to8.dat", gamedir );
+       printf( "Building inverse 16-to-8 table...\n" );
+
+       Inverse16_BuildTable();
+
+       SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
+}
diff --git a/tools/heretic2/h2data/tmix.c b/tools/heretic2/h2data/tmix.c
new file mode 100644 (file)
index 0000000..936cd6e
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "qdata.h"
+#include "flex.h"
+
+#define     MAXFILES    2048
+
+#if !GDEF_OS_WINDOWS
+#define strlwr strlower
+#endif // !GDEF_OS_WINDOWS
+
+typedef struct
+{
+       int x;
+       int y;
+       int w;
+       int h;
+       int cw;
+       int ch;
+       int rw;
+       int index;
+       int depth;
+       int col;
+       int baseline;
+       char name[128];
+} Coords;
+
+int filenum;
+int valid;
+Coords in[MAXFILES];
+Coords out;
+char outscript[256];
+char sourcedir[256];
+char outusage[256];
+char root[32];
+
+int destsize = 0;
+byte            *pixels = NULL;             // Buffer to load image
+long            *outpixels = NULL;          // Buffer to store combined textures
+long            *usagemap = NULL;           // Buffer of usage map
+void            *bmptemp = NULL;            // Buffer of usage map
+byte            *map = NULL;
+
+int xcharsize;
+int ycharsize;
+int dosort = 0;
+int missed = 0;
+int overlap = 0;
+int nobaseline = 0;
+int percent;
+
+//////////////////////////////////////////////////
+// Setting the char based usage map                            //
+//////////////////////////////////////////////////
+
+byte    TryPlace( Coords *coord ){
+       int x, y;
+       byte entry = 0;
+       byte    *mapitem;
+
+       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
+
+       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
+       {
+               for ( x = 0; x < coord->cw; x++ )
+               {
+                       if ( entry |= *mapitem++ & 8 ) {
+                               return( entry );
+                       }
+               }
+       }
+       return( entry );
+}
+
+void    SetMap( Coords *coord ){
+       int x, y;
+       byte    *mapitem;
+
+       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
+
+       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
+               for ( x = 0; x < coord->cw; x++ )
+                       *mapitem++ |= 8;
+}
+
+//////////////////////////////////////////////////
+// Setting the pixel based usage map                   //
+//////////////////////////////////////////////////
+
+void    CheckOverlap( Coords *coord ){
+       int x;
+       int y;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       dest = (long *)( usagemap + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       if ( *dest++ ) {
+                               overlap++;
+                               return;
+                       }
+               }
+       }
+}
+
+void    SetUsageMap( Coords *coord ){
+       int x;
+       int y;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       dest = (long *)( usagemap + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       *dest++ = coord->col;
+               }
+       }
+}
+
+//////////////////////////////////////////////////
+// Flips the BMP image to the correct way up   //
+//////////////////////////////////////////////////
+
+void    CopyLine( byte *dest, byte *src, int size ){
+       int x;
+
+       for ( x = 0; x < size; x++ )
+               *dest++ = *src++;
+}
+
+/****************************************************/
+/* Printing headers etc                                                                */
+/****************************************************/
+
+void RemoveLeading( char *name ){
+       int i;
+       char temp[128];
+
+       for ( i = strlen( name ) - 1; i > 0; i-- )
+       {
+               if ( ( name[i] == '\\' ) || ( name[i] == '/' ) ) {
+                       strcpy( temp, name + i + 1 );
+                       strcpy( name, temp );
+                       return;
+               }
+       }
+}
+
+void RemoveExt( char *name ){
+       while ( ( *name != '.' ) && *name )
+               name++;
+       *name = 0;
+}
+
+/****************************************************/
+/* Misc calcualtions                                                           */
+/****************************************************/
+
+int TotalArea(){
+       int i;
+       int total = 0;
+
+       for ( i = 0; i < ( filenum + 2 ); i++ )
+               total += in[i].w * in[i].h;
+
+       return( total );
+}
+
+/****************************************************/
+/* Setup and checking of all info                                      */
+/****************************************************/
+
+void    InitVars(){
+       filenum = 0;
+       valid = 0;
+       dosort = 0;
+       missed = 0;
+       overlap = 0;
+       nobaseline = 0;
+
+       memset( outscript, 0, sizeof( outscript ) );
+       memset( outscript, 0, sizeof( sourcedir ) );
+       memset( outscript, 0, sizeof( outusage ) );
+       memset( outscript, 0, sizeof( root ) );
+
+       memset( in, 0, sizeof( in ) );
+       memset( &out, 0, sizeof( out ) );
+}
+void Cleanup(){
+       if ( pixels ) {
+               free( pixels );
+       }
+       if ( usagemap ) {
+               free( usagemap );
+       }
+       if ( outpixels ) {
+               free( outpixels );
+       }
+       if ( bmptemp ) {
+               free( bmptemp );
+       }
+       if ( map ) {
+               free( map );
+       }
+}
+
+typedef struct glxy_s
+{
+       float xl, yt, xr, yb;
+       int w, h, baseline;
+} glxy_t;
+
+int SaveScript( char *name ){
+       FILE        *fp;
+       int i, j;
+       glxy_t buff;
+
+       if ( fp = fopen( name, "wb" ) ) {
+               for ( j = 0; j < filenum; j++ )
+               {
+                       for ( i = 0; i < filenum; i++ )
+                       {
+                               if ( in[i].index == j ) {
+                                       if ( in[i].depth ) {
+                                               buff.xl = (float)in[i].x / (float)out.w;
+                                               buff.yt = (float)in[i].y / (float)out.h;
+                                               buff.xr = ( (float)in[i].w + (float)in[i].x ) / (float)out.w;
+                                               buff.yb = ( (float)in[i].h + (float)in[i].y ) / (float)out.h;
+                                               buff.w = in[i].w;
+                                               buff.h = in[i].h;
+                                               buff.baseline = in[i].baseline;
+                                       }
+                                       else
+                                       {
+                                               memset( &buff, 0, sizeof( glxy_t ) );
+                                       }
+                                       fwrite( &buff, 1, sizeof( glxy_t ), fp );
+                                       i = filenum;
+                               }
+                       }
+               }
+               fclose( fp );
+               return( true );
+       }
+       else{
+               return( false );
+       }
+}
+
+int     GetScriptInfo( char *name ){
+       FILE        *fp;
+       char buffer[256];
+       char tempbuff[256];
+       char delims[] = {" \t,\n"};
+
+       printf( "Opening script file %s.\n", name );
+
+       if ( fp = fopen( name, "r" ) ) {
+               while ( fgets( buffer, 256, fp ) )
+               {
+                       if ( strncmp( buffer, "//", 2 ) && strncmp( buffer, "\n", 1 ) ) {
+                               strupr( buffer );
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTPUT" ) == 0 ) {
+                                       strcpy( out.name, strtok( NULL, delims ) );
+                                       strlwr( out.name );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "SOURCEDIR" ) == 0 ) {
+                                       strcpy( tempbuff, strtok( NULL, delims ) );
+                                       strcpy( sourcedir, ExpandPathAndArchive( tempbuff ) );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "DOSORT" ) == 0 ) {
+                                       dosort = 1;
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "XCHARSIZE" ) == 0 ) {
+                                       xcharsize = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "YCHARSIZE" ) == 0 ) {
+                                       ycharsize = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTSCRIPT" ) == 0 ) {
+                                       strcpy( outscript, strtok( NULL, delims ) );
+                                       strlwr( outscript );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "OUTUSAGE" ) == 0 ) {
+                                       strcpy( outusage, strtok( NULL, delims ) );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "POS" ) == 0 ) {
+                                       out.w = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       out.h = strtol( strtok( NULL, delims ), NULL, 0 );
+                               }
+
+                               strcpy( tempbuff, buffer );
+                               if ( strcmp( strtok( tempbuff, delims ), "FILE" ) == 0 ) {
+                                       strcpy( in[filenum].name, strtok( NULL, delims ) );
+                                       in[filenum].x = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       in[filenum].y = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       in[filenum].col = strtol( strtok( NULL, delims ), NULL, 0 );
+                                       filenum++;
+                               }
+                       }
+               }
+               fclose( fp );
+               return( true );
+       }
+       else
+       {
+               printf( "ERROR : Could not open script file.\n" );
+               return( false );
+       }
+}
+
+int CheckVars(){
+       int i;
+
+       if ( out.name[0] == 0 ) {
+               printf( "ERROR : No output name specified.\n" );
+               return( false );
+       }
+       if ( ( out.w <= 0 ) || ( out.h <= 0 ) ) {
+               printf( "ERROR : Invalid VRAM coordinates.\n" );
+               return( false );
+       }
+       if ( filenum == 0 ) {
+               printf( "ERROR : No input files specified.\n" );
+               return( false );
+       }
+       for ( i = 0; i < filenum; i++ )
+               if ( in[i].name[0] == 0 ) {
+                       printf( "ERROR : Input filename invalid.\n" );
+                       return( false );
+               }
+       return( true );
+}
+
+// Makes sure texture is totally within the output area
+
+int CheckCoords( Coords *coord ){
+       if ( ( coord->x + coord->w ) > out.w ) {
+               return( false );
+       }
+       if ( ( coord->y + coord->h ) > out.h ) {
+               return( false );
+       }
+
+       return( true );
+}
+// Gets the width, height, palette width and palette height of each BMP file
+
+int     GetFileDimensions(){
+       int i;
+       int width, height;
+       char name[128];
+
+       for ( i = 0; i < filenum; i++ )
+       {
+               in[i].index = i;
+
+               strcpy( name, sourcedir );
+               strcat( name, in[i].name );
+               printf( "Getting file dimensions, file : %s        \r", in[i].name );
+               if ( FileExists( name ) ) {
+                       LoadAnyImage( name, NULL, NULL, &width, &height );
+                       in[i].depth = 32;
+                       in[i].rw = width;
+                       in[i].w = width;                        // makes it width in
+                       in[i].h = height;
+                       in[i].cw = ( in[i].w + ( xcharsize - 1 ) ) / xcharsize;
+                       in[i].ch = ( in[i].h + ( ycharsize - 1 ) ) / ycharsize;
+
+                       if ( !CheckCoords( &in[i] ) && ( in[i].x >= 0 ) ) {
+                               printf( "Error : texture %s out of bounds.\n", in[i].name );
+                               return( false );
+                       }
+                       valid++;
+               }
+               else
+               {
+                       in[i].depth = 0;
+                       in[i].x = -1;
+                       in[i].y = -1;
+                       in[i].w = 0;
+                       in[i].h = 0;
+               }
+       }
+       printf( "\n\n" );
+       return( true );
+}
+
+// Sorts files into order for optimal space finding
+// Fixed position ones first, followed by the others in descending size
+// The theory being that it is easier to find space for smaller textures.
+// size = (width + height)
+// For space finding it is easier to place a 32x32 than a 128x2
+
+#define WEIGHT  0x8000
+
+void    Swap( Coords *a, Coords *b ){
+       Coords c;
+
+       c = *a;
+       *a = *b;
+       *b = c;
+}
+
+void    SortInNames(){
+       int i, j;
+       int largest, largcount;
+       int size;
+
+       printf( "Sorting filenames by size.\n\n" );
+
+       for ( j = 0; j < filenum; j++ )
+       {
+               largest = -1;
+               largcount = -1;
+
+               for ( i = j; i < filenum; i++ )
+               {
+                       if ( in[i].depth ) {
+                               size = in[i].w + in[i].h;
+
+                               if ( ( in[i].x < 0 ) && ( size > largest ) ) {
+                                       largcount = i;
+                                       largest = size;
+                               }
+                       }
+               }
+               if ( ( largcount >= 0 ) && ( largcount != j ) ) {
+                       Swap( &in[j], &in[largcount] );
+               }
+       }
+}
+
+int SetVars( char *name ){
+       if ( !GetScriptInfo( name ) ) {
+               return( false );
+       }
+
+       if ( !CheckVars() ) {
+               return( false );
+       }
+
+       destsize = out.w * out.h;
+
+       out.cw = out.w / xcharsize;
+       out.ch = out.h / ycharsize;
+
+       if ( ( usagemap = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( outpixels = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( bmptemp = (void *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
+               return( false );
+       }
+       if ( ( map = (byte *)SafeMalloc( destsize / ( xcharsize * ycharsize ), "" ) ) == NULL ) {
+               return( false );
+       }
+
+       if ( GetFileDimensions() == false ) {
+               return( false );
+       }
+
+       if ( dosort ) {
+               SortInNames();
+       }
+
+       return( true );
+}
+/****************************************************/
+/* Actual copying routines                                                     */
+/****************************************************/
+
+int FindCoords( Coords *coord ){
+       int tx, ty;
+
+       if ( coord->x >= 0 ) {
+               SetMap( coord );
+               return( true );
+       }
+       else
+       {
+               for ( ty = 0; ty < out.ch; ty++ )
+               {
+                       for ( tx = 0; tx < out.cw; tx++ )
+                       {
+                               coord->x = ( tx * xcharsize );
+                               coord->y = ( ty * ycharsize );
+
+                               if ( CheckCoords( coord ) && !TryPlace( coord ) ) {
+                                       SetMap( coord );
+                                       return( true );
+                               }
+                       }
+               }
+       }
+       coord->x = -1;
+       coord->y = -1;
+
+       return( false );
+}
+
+void CheckBaseline( int i ){
+       int y;
+       long    *pix;
+
+       in[i].baseline = -1;
+       pix = (long *)pixels;
+
+       for ( y = 0; y < in[i].h; y++, pix += in[i].w )
+       {
+               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
+                       in[i].baseline = y;
+                       break;
+               }
+       }
+       pix = (long *)pixels;
+       for ( y = 0; y < in[i].w * in[i].h; y++, pix++ )
+       {
+               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
+                       *pix = 0;
+               }
+       }
+
+       if ( in[i].baseline == -1 ) {
+               printf( "\nERROR : %s has no baseline\n", in[i].name );
+               nobaseline++;
+       }
+}
+
+void    CopyToMain32( Coords *coord ){
+       int x;
+       int y;
+       long        *source;
+       long        *dest;
+
+       x = coord->x;
+       y = coord->y;
+
+       source = (long *)pixels;
+       dest = (long *)( outpixels + x + ( y * out.w ) );
+
+       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
+       {
+               for ( x = 0; x < coord->w; x++ )
+               {
+                       *dest++ = *source++;
+               }
+       }
+}
+
+void CreateMain(){
+       int i, count;
+       int width, height;
+       char name[128];
+
+       for ( i = 0, count = 0; i < filenum; i++ )
+       {
+               if ( in[i].depth ) {
+                       printf( "\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline );
+                       count++;
+                       if ( !FindCoords( &in[i] ) ) {
+                               missed++;
+                       }
+                       else
+                       {
+                               strcpy( name, sourcedir );
+                               strcat( name, in[i].name );
+                               LoadAnyImage( name, &pixels, NULL, &width, &height );
+                               CheckBaseline( i );
+                               CheckOverlap( &in[i] );
+                               CopyToMain32( &in[i] );
+                               SetUsageMap( &in[i] );
+                       }
+               }
+       }
+}
+
+void Cmd_TextureMix(){
+       miptex32_t      *qtex32;
+       char filename[1024];
+       int size;
+
+       InitVars();
+
+       GetScriptToken( false );
+
+       strcpy( root, token );
+       RemoveExt( root );
+       RemoveLeading( root );
+
+       strcpy( filename, ExpandPathAndArchive( token ) );
+       if ( SetVars( filename ) ) {
+               // Create combined texture
+               percent = ( ( TotalArea() * 100 ) / ( out.w * out.h ) );
+               printf( "Total area consumed : %d%%\n", percent );
+               printf( "Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize );
+               CreateMain();
+
+               // Save image as m32
+               sprintf( filename, "%spics/misc/%s.m32", gamedir, out.name );
+               qtex32 = CreateMip32( (unsigned *)outpixels, out.w, out.h, &size, false );
+
+               qtex32->contents = 0;
+               qtex32->value = 0;
+               qtex32->scale_x = 1.0;
+               qtex32->scale_y = 1.0;
+               sprintf( qtex32->name, "misc/%s", out.name );
+
+               printf( "\n\nwriting %s\n", filename );
+               SaveFile( filename, (byte *)qtex32, size );
+               free( qtex32 );
+
+               // Save out script file
+               sprintf( filename, "%spics/misc/%s.fnt", gamedir, outscript );
+               printf( "Writing %s as script file\n", filename );
+               if ( !SaveScript( filename ) ) {
+                       printf( "Unable to save output script.\n" );
+               }
+       }
+       printf( "Everythings groovy.\n" );
+       Cleanup();
+}
+
+// end
diff --git a/tools/heretic2/h2data/video.c b/tools/heretic2/h2data/video.c
new file mode 100644 (file)
index 0000000..51bf462
--- /dev/null
@@ -0,0 +1,1154 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// To do
+
+// Sound error handling (when sound too short)
+// rle b4 huffing
+// adpcm encoding of sound
+
+#if 0
+#include "qdata.h"
+#include "flex.h"
+#include "fc.h"
+#include "adpcm.h"
+
+#define MIN_REPT    15
+#define MAX_REPT    0
+#define HUF_TOKENS  ( 256 + MAX_REPT )
+
+#define BLOCKSIZE   8
+
+#define M_PI        3.14159265358979323846  // matches value in gcc v2 math.h
+#define SQRT2       1.414213562
+
+typedef struct hnode_s
+{
+       int count;
+       qboolean used;
+       int children[2];
+} hnode_t;
+
+typedef struct
+{
+       int rate;
+       int width;
+       int channels;
+       int loopstart;
+       int samples;
+       int dataofs;                // chunk starts this many bytes from file start
+} wavinfo_t;
+
+// These weren`t picked out my ass....
+// They were defined at http://www.rahul.net/jfm/dct.html
+// However, I think he plucked them out of his ass.....
+
+float Quantise[BLOCKSIZE * BLOCKSIZE];
+
+float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
+{
+       16.0F / 16.0F, 11.0F / 16.0F, 10.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 51.0F / 16.0F, 61.0F / 16.0F,
+       12.0F / 16.0F, 13.0F / 16.0F, 14.0F / 16.0F, 19.0F / 16.0F, 26.0F / 16.0F, 58.0F / 16.0F, 60.0F / 16.0F, 55.0F / 16.0F,
+       14.0F / 16.0F, 13.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 57.0F / 16.0F, 69.0F / 16.0F, 56.0F / 16.0F,
+       14.0F / 16.0F, 17.0F / 16.0F, 22.0F / 16.0F, 29.0F / 16.0F, 51.0F / 16.0F, 87.0F / 16.0F, 80.0F / 16.0F, 62.0F / 16.0F,
+       18.0F / 16.0F, 22.0F / 16.0F, 37.0F / 16.0F, 56.0F / 16.0F, 68.0F / 16.0F,109.0F / 16.0F,103.0F / 16.0F, 77.0F / 16.0F,
+       24.0F / 16.0F, 35.0F / 16.0F, 55.0F / 16.0F, 64.0F / 16.0F, 81.0F / 16.0F,104.0F / 16.0F,113.0F / 16.0F, 92.0F / 16.0F,
+       49.0F / 16.0F, 64.0F / 16.0F, 78.0F / 16.0F, 87.0F / 16.0F,103.0F / 16.0F,121.0F / 16.0F,120.0F / 16.0F,101.0F / 16.0F,
+       72.0F / 16.0F, 92.0F / 16.0F, 95.0F / 16.0F, 98.0F / 16.0F,112.0F / 16.0F,100.0F / 16.0F,103.0F / 16.0F, 99.0F / 16.0F
+};
+
+int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
+{
+       0,
+       1,  8,
+       16,  9,  2,
+       3, 10, 17, 24,
+       32, 25, 18, 11,  4,
+       5, 12, 19, 26, 33, 40,
+       48, 41, 34, 27, 20, 13, 6,
+       7, 14, 21, 28, 35, 42, 49, 56,
+       57, 50, 43, 36, 29, 22, 15,
+       23, 30, 37, 44, 51, 58,
+       59, 52, 45, 38, 31,
+       39, 46, 53, 60,
+       61, 54, 47,
+       55, 62,
+       63
+};
+
+char base[32];
+
+byte            *soundtrack;
+
+byte scaled[256][HUF_TOKENS];
+unsigned int charbits1[256][HUF_TOKENS];
+int charbitscount1[256][HUF_TOKENS];
+hnode_t hnodes1[256][HUF_TOKENS * 2];
+int numhnodes1[256];
+int order0counts[256];
+int numhnodes;
+hnode_t hnodes[512];
+unsigned charbits[256];
+int charbitscount[256];
+
+CineHead_t cinehead;
+
+byte            *data_p;
+byte            *iff_end;
+byte            *last_chunk;
+byte            *iff_data;
+int iff_chunk_len;
+
+float dctbase[BLOCKSIZE][BLOCKSIZE];
+float red[BLOCKSIZE * BLOCKSIZE];
+float green[BLOCKSIZE * BLOCKSIZE];
+float blue[BLOCKSIZE * BLOCKSIZE];
+float temp[BLOCKSIZE * BLOCKSIZE];
+
+wavinfo_t wavinfo;
+adpcm_t adpcm;
+
+/*
+   ===============================================================================
+
+   WAV loading
+
+   ===============================================================================
+ */
+
+/* Intel ADPCM step variation table */
+static int indexTable[16] =
+{
+       -1, -1, -1, -1, 2, 4, 6, 8,
+       -1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] =
+{
+       7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+       19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+       50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+       130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+       337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+       876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+       2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+       5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+       15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#if 0
+static void adpcm_decoder( char *indata, short *outdata, int len, adpcm_state_t *state ){
+       signed char *inp;       /* Input buffer pointer */
+       short *outp;        /* output buffer pointer */
+       int sign;           /* Current adpcm sign bit */
+       int delta;          /* Current adpcm output value */
+       int step;           /* Stepsize */
+       int valpred;        /* Predicted value */
+       int vpdiff;         /* Current change to valpred */
+       int index;          /* Current step change index */
+       int inputbuffer;        /* place to keep next 4-bit value */
+       int bufferstep;     /* toggle between inputbuffer/input */
+
+       outp = outdata;
+       inp = (signed char *)indata;
+
+       valpred = state->valprev;
+       index = state->index;
+       step = stepsizeTable[index];
+
+       bufferstep = 0;
+
+       for (; len > 0; len-- )
+       {
+               /* Step 1 - get the delta value */
+               if ( bufferstep ) {
+                       delta = inputbuffer & 0xf;
+               }
+               else
+               {
+                       inputbuffer = *inp++;
+                       delta = ( inputbuffer >> 4 ) & 0xf;
+               }
+               bufferstep = !bufferstep;
+
+               /* Step 2 - Find new index value (for later) */
+               index += indexTable[delta];
+               if ( index < 0 ) {
+                       index = 0;
+               }
+               if ( index > 88 ) {
+                       index = 88;
+               }
+
+               /* Step 3 - Separate sign and magnitude */
+               sign = delta & 8;
+               delta = delta & 7;
+
+               /* Step 4 - Compute difference and new predicted value */
+               /*
+               ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+               ** in adpcm_coder.
+               */
+               vpdiff = step >> 3;
+               if ( delta & 4 ) {
+                       vpdiff += step;
+               }
+               if ( delta & 2 ) {
+                       vpdiff += step >> 1;
+               }
+               if ( delta & 1 ) {
+                       vpdiff += step >> 2;
+               }
+
+               if ( sign ) {
+                       valpred -= vpdiff;
+               }
+               else{
+                       valpred += vpdiff;
+               }
+
+               /* Step 5 - clamp output value */
+               if ( valpred > 32767 ) {
+                       valpred = 32767;
+               }
+               else if ( valpred < -32768 ) {
+                       valpred = -32768;
+               }
+
+               /* Step 6 - Update step value */
+               step = stepsizeTable[index];
+
+               /* Step 7 - Output value */
+               *outp++ = valpred;
+       }
+
+       state->valprev = valpred;
+       state->index = index;
+}
+#endif
+
+void adpcm_coder( short *inp, adpcm_t *adpcm ){
+       int val;                        /* Current input sample value */
+       int sign;                       /* Current adpcm sign bit */
+       int delta;                      /* Current adpcm output value */
+       int diff;                       /* Difference between val and valprev */
+       int step;                       /* Stepsize */
+       int valpred;                    /* Predicted output value */
+       int vpdiff;                     /* Current change to valpred */
+       int index;                      /* Current step change index */
+       int outputbuffer;               /* place to keep previous 4-bit value */
+       int bufferstep;                 /* toggle between outputbuffer/output */
+       adpcm_state_t   *state;
+       char            *outp;
+       int len;
+
+       state = &adpcm->state;
+       len = state->count;
+       outp = adpcm->adpcm;
+
+       valpred = state->in_valprev;
+       index = state->in_index;
+       step = stepsizeTable[index];
+
+       bufferstep = 1;
+       while ( len-- )
+       {
+               val = *inp++;
+
+               /* Step 1 - compute difference with previous value */
+               diff = val - valpred;
+               sign = ( diff < 0 ) ? 8 : 0;
+               if ( sign ) {
+                       diff = -diff;
+               }
+
+               /* Step 2 - Divide and clamp */
+               /* Note:
+               ** This code *approximately* computes:
+               **        delta = diff*4/step;
+               **        vpdiff = (delta+0.5)*step/4;
+               ** but in shift step bits are dropped. The net result of this is
+               ** that even if you have fast mul/div hardware you cannot put it to
+               ** good use since the fixup would be too expensive.
+               */
+               delta = 0;
+               vpdiff = ( step >> 3 );
+
+               if ( diff >= step ) {
+                       delta = 4;
+                       diff -= step;
+                       vpdiff += step;
+               }
+               step >>= 1;
+               if ( diff >= step ) {
+                       delta |= 2;
+                       diff -= step;
+                       vpdiff += step;
+               }
+               step >>= 1;
+               if ( diff >= step ) {
+                       delta |= 1;
+                       vpdiff += step;
+               }
+
+               /* Step 3 - Update previous value */
+               if ( sign ) {
+                       valpred -= vpdiff;
+               }
+               else{
+                       valpred += vpdiff;
+               }
+
+               /* Step 4 - Clamp previous value to 16 bits */
+               if ( valpred > 32767 ) {
+                       valpred = 32767;
+               }
+               else if ( valpred < -32768 ) {
+                       valpred = -32768;
+               }
+
+               /* Step 5 - Assemble value, update index and step values */
+               delta |= sign;
+
+               index += indexTable[delta];
+               if ( index < 0 ) {
+                       index = 0;
+               }
+               if ( index > 88 ) {
+                       index = 88;
+               }
+               step = stepsizeTable[index];
+
+               /* Step 6 - Output value */
+               if ( bufferstep ) {
+                       outputbuffer = ( delta << 4 ) & 0xf0;
+               }
+               else{
+                       *outp++ = ( delta & 0x0f ) | outputbuffer;
+               }
+
+               bufferstep = !bufferstep;
+       }
+
+       /* Output last step, if needed */
+       if ( !bufferstep ) {
+               *outp++ = outputbuffer;
+       }
+
+       state->out_valprev = valpred;
+       state->out_index = index;
+}
+
+void FindNextChunk( char *name ){
+       while ( 1 )
+       {
+               data_p = last_chunk;
+
+               if ( data_p >= iff_end ) {         // didn't find the chunk
+                       data_p = NULL;
+                       return;
+               }
+
+               data_p += 4;
+               iff_chunk_len = *(long *)data_p;
+               data_p += 4;
+               if ( iff_chunk_len < 0 ) {
+                       data_p = NULL;
+                       return;
+               }
+
+               data_p -= 8;
+               last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 );
+               if ( !strncmp( data_p, name, 4 ) ) {
+                       return;
+               }
+       }
+}
+
+void FindChunk( char *name ){
+       last_chunk = iff_data;
+       FindNextChunk( name );
+}
+
+void DumpChunks( void ){
+       char str[5];
+
+       str[4] = 0;
+       data_p = iff_data;
+       do
+       {
+               memcpy( str, data_p, 4 );
+               data_p += 4;
+               iff_chunk_len = *(long *)data_p;
+               data_p += 4;
+               printf( "0x%x : %s (%d)\n", (int)( data_p - 4 ), str, iff_chunk_len );
+               data_p += ( iff_chunk_len + 1 ) & ~1;
+       }
+       while ( data_p < iff_end );
+}
+
+/*
+   ============
+   GetWavinfo
+   ============
+ */
+wavinfo_t GetWavinfo( char *name, byte *wav, int wavlength ){
+       wavinfo_t info;
+       int i;
+       int format;
+       int samples;
+
+       memset( &info, 0, sizeof( info ) );
+
+       if ( !wav ) {
+               return( info );
+       }
+
+       iff_data = wav;
+       iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+       FindChunk( "RIFF" );
+       if ( !( data_p && !strncmp( data_p + 8, "WAVE", 4 ) ) ) {
+               printf( "Missing RIFF/WAVE chunks\n" );
+               return( info );
+       }
+
+// get "fmt " chunk
+       iff_data = data_p + 12;
+
+       FindChunk( "fmt " );
+       if ( !data_p ) {
+               printf( "Missing fmt chunk\n" );
+               return( info );
+       }
+       data_p += 8;
+       format = *(short *)data_p;
+       data_p += 2;
+       if ( format != 1 ) {
+               printf( "Microsoft PCM format only\n" );
+               return( info );
+       }
+
+       info.channels = *(short *)data_p;
+       data_p += 2;
+       info.rate = *(long *)data_p;
+       data_p += 4;
+       data_p += 6;
+       info.width = *(short *)data_p / 8;
+       data_p += 2;
+
+// get cue chunk
+       FindChunk( "cue " );
+       if ( data_p ) {
+               data_p += 32;
+               info.loopstart = *(long *)data_p;
+               data_p += 4;
+
+// if the next chunk is a LIST chunk, look for a cue length marker
+               FindNextChunk( "LIST" );
+               if ( data_p ) {
+// this is not a proper parse, but it works with cooledit...
+                       if ( !strncmp( data_p + 28, "mark", 4 ) ) {
+                               data_p += 24;
+                               i = *(long *)data_p;                    // samples in loop
+                               data_p += 4;
+                               info.samples = info.loopstart + i;
+                       }
+               }
+       }
+       else{
+               info.loopstart = -1;
+       }
+
+// find data chunk
+       FindChunk( "data" );
+       if ( !data_p ) {
+               printf( "Missing data chunk\n" );
+               return( info );
+       }
+
+       data_p += 4;
+       samples = *(long *)data_p;
+       data_p += 4;
+
+       if ( info.samples ) {
+               if ( samples < info.samples ) {
+                       Error( "Sound %s has a bad loop length", name );
+               }
+       }
+       else{
+               info.samples = samples;
+       }
+
+       info.dataofs = data_p - wav;
+       return( info );
+}
+
+// ==============
+// LoadSoundtrack
+// ==============
+
+void LoadSoundtrack(){
+       char name[1024];
+       FILE    *f;
+       int len;
+
+       soundtrack = NULL;
+       sprintf( name, "%svideo/%s/%s.wav", gamedir, base, base );
+       printf( "\nLoading sound    : %s\n", name );
+       f = fopen( name, "rb" );
+       if ( !f ) {
+               printf( "\nNo soundtrack for %s\n", base );
+               return;
+       }
+       len = Q_filelength( f );
+       soundtrack = SafeMalloc( len, "LoadSoundtrack" );
+       fread( soundtrack, 1, len, f );
+       fclose( f );
+
+       wavinfo = GetWavinfo( name, soundtrack, len );
+       adpcm.state.out_valprev = 0;
+       adpcm.state.out_index = 0;
+}
+
+// ==================
+// WriteSound
+// ==================
+
+int WriteSound( FILE *output, int frame, int numframes ){
+       int start, end;
+       int count;
+       int empty = 0;
+       int width;
+       char    *work;
+
+       width = wavinfo.width * wavinfo.channels;
+       start = ( ( frame * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;                // start sample
+       end = ( ( ( frame + numframes ) * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;    // end sample
+       count = end - start;
+
+       work = soundtrack + wavinfo.dataofs + ( start * width );
+       adpcm.state.count = count * wavinfo.channels;           // Number of samples
+       adpcm.state.in_valprev = adpcm.state.out_valprev;
+       adpcm.state.in_index = adpcm.state.out_index;
+       adpcm_coder( (short *)work, &adpcm );
+       WriteHeader( output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, ( adpcm.state.count / 2 ) + sizeof( adpcm_state_t ), (char *)&adpcm );
+       return( count / 2 );
+}
+// ==============================
+// Basic run length encoder
+// ==============================
+
+char *RLEZZ( char *in, char *out ){
+       int srun;
+       char count;
+       int idx = 0;
+
+       while ( idx < 64 )
+       {
+               srun = idx;                             // Start of run
+
+               while ( idx < 63 )
+               {
+                       if ( in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]] ) {
+                               break;
+                       }
+                       idx++;
+               }
+               count = (char)( idx - srun );             // count of repeated bytes
+
+               if ( !count ) {
+                       while ( idx < 63 )
+                       {
+                               if ( in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]] ) {
+                                       break;
+                               }
+                               idx++;
+                       }
+                       if ( idx == 63 ) {
+                               idx++;
+                       }
+
+                       count = (char)( idx - srun );         // count of unique bytes
+                       *out++ = count;
+                       while ( count-- )
+                               *out++ = in[LUT_ZZ[srun++]];
+               }
+               else
+               {
+                       *out++ = -( count + 1 );
+                       *out++ = in[LUT_ZZ[idx]];
+                       idx++;
+               }
+       }
+       return( out );
+}
+
+// ==============================
+// Discrete Cosine Transformation
+// ==============================
+
+void init_base( float quant ){
+       int y, x;
+
+       for ( y = 0; y < BLOCKSIZE; y++ )
+               for ( x = 0; x < BLOCKSIZE; x++ )
+               {
+                       if ( y == 0 ) {
+                               dctbase[y][x] = 1;
+                       }
+                       else{
+                               dctbase[y][x] = SQRT2 * cos( ( ( x * 2 + 1 ) * y * M_PI ) / ( BLOCKSIZE * 2 ) );
+                       }
+               }
+
+       for ( y = 0; y < BLOCKSIZE * BLOCKSIZE; y++ )
+               Quantise[y] = LUT_Quantise[y] / quant;
+}
+
+void SplitComponents( byte *src, int width, int height ){
+       int i, j;
+       float   *tr = red;
+       float   *tg = green;
+       float   *tb = blue;
+
+       for ( i = 0; i < BLOCKSIZE; i++, src += ( width - BLOCKSIZE ) * 4 )
+               for ( j = 0; j < BLOCKSIZE; j++ )
+               {
+                       *tr++ = ( (float)*src++ ) - 128.0F;
+                       *tg++ = ( (float)*src++ ) - 128.0F;
+                       *tb++ = ( (float)*src++ ) - 128.0F;
+                       src++;
+               }
+}
+
+void transferH( float *src, float *dst ){
+       int y, dx, dy;
+       float sum;
+       float   *work;
+
+       for ( y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE )
+       {
+               for ( dy = 0; dy < BLOCKSIZE; dy++ )
+               {
+                       sum = 0;
+                       work = src;
+                       for ( dx = 0; dx < BLOCKSIZE; dx++, work++ )
+                               sum += dctbase[dy][dx] * *work;
+
+                       *dst++ = sum / BLOCKSIZE;
+               }
+       }
+}
+
+void transferV( float *src, float *dst ){
+       int x, dy, fy;
+       float sum;
+       float   *work;
+
+       for ( x = 0; x < BLOCKSIZE; x++, src++, dst++ )
+       {
+               for ( fy = 0; fy < BLOCKSIZE; fy++ )
+               {
+                       sum = 0;
+                       work = src;
+                       for ( dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE )
+                               sum += dctbase[fy][dy] * *work;
+
+                       dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
+               }
+       }
+}
+
+char *Combine( byte *dst, float *p, float *q ){
+       int i, j;
+       byte rlesrc[BLOCKSIZE * BLOCKSIZE];
+       int c;
+       byte    *work;
+
+       work = rlesrc;
+       for ( j = 0; j < BLOCKSIZE; j++ )
+               for ( i = 0; i < BLOCKSIZE; i++ )
+               {
+                       c = (int)( ( *p++ / *q++ ) + 128.5F );
+                       c -= 128;
+
+                       if ( c < -128 ) {
+                               c = -128;
+                       }
+                       if ( c > 127 ) {
+                               c = 127;
+                       }
+
+                       *work++ = (char)c;
+               }
+
+       dst = RLEZZ( rlesrc, dst );
+       return( dst );
+}
+
+char *CombineComponents( char *dst, int width, int height ){
+       dst = Combine( dst, red, Quantise );
+       dst = Combine( dst, green, Quantise );
+       dst = Combine( dst, blue, Quantise );
+       return( dst );
+}
+
+void DCT( cblock_t *out, cblock_t in, int width, int height ){
+       int x, y;
+       char    *cursrc;
+       char    *curdst;
+
+       curdst = out->data;
+       for ( y = 0; y < height; y += BLOCKSIZE )
+               for ( x = 0; x < width; x += BLOCKSIZE )
+               {
+                       cursrc = in.data + ( ( y * width ) + x ) * 4;
+                       SplitComponents( cursrc, width, height );
+                       transferH( red, temp );
+                       transferV( temp, red );
+                       transferH( green, temp );
+                       transferV( temp, green );
+                       transferH( blue, temp );
+                       transferV( temp, blue );
+                       curdst = CombineComponents( curdst, width, height );
+               }
+       out->count = curdst - out->data;
+}
+
+// ==================
+// BuildChars1
+// ==================
+
+void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){
+       hnode_t     *node;
+
+       if ( nodenum < HUF_TOKENS ) {
+               if ( bitcount > 32 ) {
+                       Error( "bitcount > 32" );
+               }
+               charbits1[prev][nodenum] = bits;
+               charbitscount1[prev][nodenum] = bitcount;
+               return;
+       }
+
+       node = &hnodes1[prev][nodenum];
+       bits <<= 1;
+       BuildChars1( prev, node->children[0], bits, bitcount + 1 );
+       bits |= 1;
+       BuildChars1( prev, node->children[1], bits, bitcount + 1 );
+}
+
+// ==================
+// SmallestNode1
+// ==================
+
+int SmallestNode1( hnode_t *hnodes, int numhnodes ){
+       int i;
+       int best, bestnode;
+
+       best = 99999999;
+       bestnode = -1;
+       for ( i = 0; i < numhnodes; i++ )
+       {
+               if ( hnodes[i].used ) {
+                       continue;
+               }
+               if ( !hnodes[i].count ) {
+                       continue;
+               }
+               if ( hnodes[i].count < best ) {
+                       best = hnodes[i].count;
+                       bestnode = i;
+               }
+       }
+
+       if ( bestnode == -1 ) {
+               return( -1 );
+       }
+
+       hnodes[bestnode].used = true;
+       return( bestnode );
+}
+
+// ==================
+// BuildTree1
+// ==================
+
+void BuildTree1( int prev ){
+       hnode_t     *node, *nodebase;
+       int numhnodes;
+
+       // build the nodes
+       numhnodes = HUF_TOKENS;
+       nodebase = hnodes1[prev];
+       while ( 1 )
+       {
+               node = &nodebase[numhnodes];
+
+               // pick two lowest counts
+               node->children[0] = SmallestNode1( nodebase, numhnodes );
+               if ( node->children[0] == -1 ) {
+                       break;  // no more
+
+               }
+               node->children[1] = SmallestNode1( nodebase, numhnodes );
+               if ( node->children[1] == -1 ) {
+                       break;
+               }
+
+               node->count = nodebase[node->children[0]].count +
+                                         nodebase[node->children[1]].count;
+               numhnodes++;
+       }
+       numhnodes1[prev] = numhnodes - 1;
+       BuildChars1( prev, numhnodes - 1, 0, 0 );
+}
+
+// ==================
+// Huffman1_Count
+// ==================
+
+void Huffman1_Count( cblock_t in ){
+       int i;
+       int prev;
+       int v;
+       int rept;
+
+       prev = 0;
+       for ( i = 0; i < in.count; i++ )
+       {
+               v = in.data[i];
+               order0counts[v]++;
+               hnodes1[prev][v].count++;
+               prev = v;
+
+               for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
+                       if ( in.data[i + rept] != v ) {
+                               break;
+                       }
+               if ( rept > MIN_REPT ) {
+                       hnodes1[prev][255 + rept].count++;
+                       i += rept - 1;
+               }
+       }
+}
+
+// ==================
+// Huffman1_Build
+// ==================
+
+void Huffman1_Build(){
+       int i, j, v;
+       int max;
+       int total;
+
+       for ( i = 0; i < 256; i++ )
+       {
+// normalize and save the counts
+               max = 0;
+               for ( j = 0; j < HUF_TOKENS; j++ )
+               {
+                       if ( hnodes1[i][j].count > max ) {
+                               max = hnodes1[i][j].count;
+                       }
+               }
+               if ( max == 0 ) {
+                       max = 1;
+               }
+               total = 0;
+// easy to overflow 32 bits here!
+               for ( j = 0; j < HUF_TOKENS; j++ )
+               {
+                       v = ( hnodes1[i][j].count * (double) 255 + max - 1 ) / max;
+                       if ( v > 255 ) {
+                               Error( "v > 255" );
+                       }
+                       scaled[i][j] = hnodes1[i][j].count = v;
+                       if ( v ) {
+                               total++;
+                       }
+               }
+               if ( total == 1 ) { // must have two tokens
+                       if ( !scaled[i][0] ) {
+                               scaled[i][0] = hnodes1[i][0].count = 1;
+                       }
+                       else{
+                               scaled[i][1] = hnodes1[i][1].count = 1;
+                       }
+               }
+               BuildTree1( i );
+       }
+}
+
+// ==================
+// Huffman1
+// Order 1 compression with pre-built table
+// ==================
+
+cblock_t Huffman1( cblock_t in ){
+       int i;
+       int outbits, c;
+       unsigned bits;
+       byte        *out_p;
+       cblock_t out;
+       int prev;
+       int v;
+       int rept;
+
+       out_p = out.data = SafeMalloc( ( in.count * 2 ) + 1024 + 4, "Huffman" );
+       memset( out_p, 0, ( in.count * 2 ) + 1024 + 4 );
+
+       // leave space for compressed count
+       out_p += 4;
+       // write count
+       *(long *)out_p = in.count;
+       out_p += 4;
+
+       // write bits
+       outbits = 0;
+       prev = 0;
+       for ( i = 0; i < in.count; i++ )
+       {
+               v = in.data[i];
+
+               c = charbitscount1[prev][v];
+               bits = charbits1[prev][v];
+               if ( !c ) {
+                       Error( "!bits" );
+               }
+               while ( c )
+               {
+                       c--;
+                       if ( bits & ( 1 << c ) ) {
+                               out_p[outbits >> 3] |= 1 << ( outbits & 7 );
+                       }
+                       outbits++;
+               }
+
+               prev = v;
+               // check for repeat encodes
+               for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
+                       if ( in.data[i + rept] != v ) {
+                               break;
+                       }
+               if ( rept > MIN_REPT ) {
+                       c = charbitscount1[prev][255 + rept];
+                       bits = charbits1[prev][255 + rept];
+                       if ( !c ) {
+                               Error( "!bits" );
+                       }
+                       while ( c )
+                       {
+                               c--;
+                               if ( bits & ( 1 << c ) ) {
+                                       out_p[outbits >> 3] |= 1 << ( outbits & 7 );
+                               }
+                               outbits++;
+                       }
+                       i += rept - 1;
+               }
+       }
+       out_p += ( outbits + 7 ) >> 3;
+       out.count = out_p - out.data;
+
+       out_p = out.data;
+       *(long *)out_p = out.count;
+       return( out );
+}
+// ===================
+// LoadFrame
+// ===================
+
+void LoadFrame( cblock_t *out, char *base, int frame ){
+       cblock_t in;
+       int width, height;
+       char name[1024];
+       FILE        *f;
+
+       in.data = NULL;
+       in.count = -1;
+       sprintf( name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame );
+
+       f = fopen( name, "rb" );
+       if ( !f ) {
+               out->data = NULL;
+               return;
+       }
+       fclose( f );
+
+       LoadTGA( name, &in.data, &width, &height );
+       if ( ( width != cinehead.Width ) || ( height != cinehead.Height ) ) {
+               free( in.data );
+               printf( "Invalid picture size\n" );
+               out->data = NULL;
+               return;
+       }
+       out->data = SafeMalloc( width * height * 3, "LoadFrame" );        // rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
+       DCT( out, in, width, height );
+       free( in.data );
+}
+
+// ==================================
+// Cmd_Video
+//
+// video <directory> <framedigits>
+// ==================================
+
+void Cmd_Video(){
+       char savename[256];
+       char name[256];
+       FILE        *output;
+       int frame;
+       int width, height;
+       cblock_t in, huffman;
+       int size;
+       float dctconst;
+       int maxsize, ssize;
+       int min_rle_size, warnings;
+       int ave_image, ave_sound;
+
+       GetScriptToken( false );
+       strcpy( base, token );
+       if ( g_release ) {
+               return;
+       }
+
+       GetScriptToken( false );
+       dctconst = atof( token );
+       GetScriptToken( false );
+       maxsize = atoi( token );
+
+       sprintf( savename, "%svideo/%s.cin", gamedir, base );
+
+       // clear stuff
+       memset( charbits1, 0, sizeof( charbits1 ) );
+       memset( charbitscount1, 0, sizeof( charbitscount1 ) );
+       memset( hnodes1, 0, sizeof( hnodes1 ) );
+       memset( numhnodes1, 0, sizeof( numhnodes1 ) );
+       memset( order0counts, 0, sizeof( order0counts ) );
+
+       // load the entire sound wav file if present
+       LoadSoundtrack();
+
+       cinehead.SndRate = wavinfo.rate;
+       cinehead.SndWidth = wavinfo.width;
+       cinehead.SndChannels = wavinfo.channels;
+
+       sprintf( name, "%svideo/%s/%s0000.tga", gamedir, base, base );
+       printf( "Loading sequence : %s\n", name );
+       printf( "DCT constant     : %f\n", dctconst );
+
+       LoadTGA( name, NULL, &width, &height );
+
+       output = fopen( savename, "wb" );
+       if ( !output ) {
+               Error( "Can't open %s", savename );
+       }
+
+       if ( ( width % BLOCKSIZE ) || ( height % BLOCKSIZE ) ) {
+               Error( "Width and height must be a multiple of %d", BLOCKSIZE );
+       }
+
+       cinehead.Width = width;
+       cinehead.Height = height;
+       init_base( dctconst );
+
+       // build the dictionary
+       printf( "Counting         : " );
+       min_rle_size = 0;
+       for ( frame = 0;  ; frame++ )
+       {
+               printf( "." );
+               LoadFrame( &in, base, frame );
+               if ( !in.data ) {
+                       break;
+               }
+               Huffman1_Count( in );
+               if ( in.count > min_rle_size ) {
+                       min_rle_size = in.count;
+               }
+               free( in.data );
+       }
+       printf( "\n" );
+       cinehead.NumFrames = frame;
+       printf( "Num Frames       : %d\n", frame );
+       cinehead.MaxRleSize = ( min_rle_size + 0x1f ) & 0xfffffe0;
+       cinehead.MaxSndSize = ( ( 4 * wavinfo.rate * wavinfo.channels / 14 ) + 0x1f ) & 0xffffffe0;
+
+       WriteHeader( output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof( CineHead_t ), &cinehead );
+
+       // build nodes and write counts
+       Huffman1_Build();
+       WriteHeader( output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof( scaled ), scaled );
+       WriteHeader( output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof( Quantise ), Quantise );
+
+       ave_image = 0;
+       ave_sound = 0;
+       warnings = 0;
+       // compress it with the dictionary
+       if ( soundtrack ) {
+               ssize = WriteSound( output, frame, 4 );
+               ave_sound += ssize;
+       }
+
+       for ( frame = 0; frame < cinehead.NumFrames; frame++ )
+       {
+               // save some sound samples
+               printf( "Packing          : ", frame );
+               LoadFrame( &in, base, frame );
+
+               // save the image
+               huffman = Huffman1( in );
+               printf( "%d bytes rle, %d bytes huffman", in.count, huffman.count );
+               size = ( huffman.count + 3 ) & 0xfffffffc;                    // round up to longwords
+               if ( size > maxsize ) {
+                       printf( " ** WARNING **" );
+                       warnings++;
+               }
+               printf( "\n" );
+               ave_image += huffman.count;
+
+               WriteHeader( output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data );
+               if ( soundtrack ) {
+                       ssize = WriteSound( output, frame + 4, 1 );
+                       ave_sound += ssize;
+               }
+
+               free( in.data );
+               free( huffman.data );
+       }
+       printf( "\nTotal size: %d (headers + %d image + %d sound)\n", ftell( output ), ave_image, ave_sound );
+       printf( "Data rate : %d bytes per sec (image and sound)\n", ( ave_image + ave_sound ) / cinehead.NumFrames );
+       printf( "Cin created ok with %d warnings.\n", warnings );
+       fclose( output );
+
+       if ( soundtrack ) {
+               free( soundtrack );
+       }
+}
+#endif
+
+void Cmd_Video(){
+}
+
+// end
diff --git a/tools/heretic2/qcommon/angles.h b/tools/heretic2/qcommon/angles.h
new file mode 100644 (file)
index 0000000..b0baf31
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// Angles in radians
+
+#define ANGLE_0         0.0F
+#define ANGLE_1         0.017453292F
+#define ANGLE_5         0.087266462F
+#define ANGLE_10        0.174532925F
+#define ANGLE_15        0.261799387F
+#define ANGLE_20        0.392699081F
+#define ANGLE_30        0.523598775F
+#define ANGLE_45        0.785398163F
+#define ANGLE_60        1.047197551F
+#define ANGLE_72        1.256637061F
+#define ANGLE_90        1.570796327F
+#define ANGLE_120       2.094395102F
+#define ANGLE_135       2.35619449F
+#define ANGLE_144       2.513274123F
+#define ANGLE_180       3.141592653F
+#define ANGLE_225       3.926990817F
+#define ANGLE_270       4.71238898F
+#define ANGLE_315       5.497787144F
+#define ANGLE_360       6.283185307F
+
+// Angles in degrees
+
+#define DEGREE_0        0.0F
+#define DEGREE_180      180.0F
+#define DEGREE_45       ( DEGREE_180 / 4.0F )
+#define DEGREE_90       ( DEGREE_180 / 2.0F )
+#define DEGREE_135      ( DEGREE_90 + DEGREE_45 )
+#define DEGREE_270      ( DEGREE_180 + DEGREE_90 )
+#define DEGREE_360      ( DEGREE_180 * 2.0F )
+
+#define DEGREE_225      ( DEGREE_180 + DEGREE_45 )
+#define DEGREE_315      ( DEGREE_270 + DEGREE_45 )
+
+#define DEGREE_30       ( DEGREE_180 / 6.0F )
+#define DEGREE_60       ( DEGREE_180 / 3.0F )
+#define DEGREE_120      ( DEGREE_360 / 3.0F )
+
+#define DEGREE_1        ( DEGREE_180 / 180.0F )
+#define DEGREE_5        ( DEGREE_180 / 36.0F )
+#define DEGREE_10       ( DEGREE_180 / 18.0F )
+#define DEGREE_15       ( DEGREE_180 / 12.0F )
+#define DEGREE_20       ( DEGREE_180 / 8.0F )
+
+// Conversion routines
+
+#define ANGLE_TO_RAD    ANGLE_1
+#define RAD_TO_ANGLE    ( 180.0F / ANGLE_180 )
+
+#define SHORT_TO_ANGLE  ( 360.0 / 65536 )
+
+#if GDEF_COMPILER_MSVC
+#pragma warning(disable : 4305)     // 'initializing' : truncation from 'const double ' to 'float '
+#endif
diff --git a/tools/heretic2/qcommon/arrayedlist.h b/tools/heretic2/qcommon/arrayedlist.h
new file mode 100644 (file)
index 0000000..46663dd
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef _ARRAYEDLIST_H
+#define _ARRAYEDLIST_H
+
+#include <assert.h>
+#include <globaldefs.h>
+
+typedef struct ArrayedListNode_s
+{
+       int data;
+       int next;
+       int inUse;
+} ArrayedListNode_t;
+
+#define ARRAYEDLISTNODE_NULL -1
+
+static GDEF_ATTRIBUTE_INLINE int GetFreeNode( ArrayedListNode_t *nodeArray, int max ){
+       int i;
+
+       for ( i = 0; i < max; ++i )
+       {
+               if ( !nodeArray[i].inUse ) {
+                       nodeArray[i].inUse = 1;
+                       return i;
+               }
+       }
+
+       assert( 0 );
+       return -1;
+}
+
+static GDEF_ATTRIBUTE_INLINE void FreeNode( ArrayedListNode_t *nodeArray, int index ){
+       nodeArray[index].inUse = 0;
+}
+
+#endif //_ARRAYEDLIST_H
diff --git a/tools/heretic2/qcommon/flex.h b/tools/heretic2/qcommon/flex.h
new file mode 100644 (file)
index 0000000..98184e8
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+// Generic flexible format
+
+typedef struct
+{
+       char ident[32];
+       int version;
+       int size;
+} header_t;
+
+void WriteHeader( FILE *, char *, int, int, void * );
+
+// end
diff --git a/tools/heretic2/qcommon/fmodel.h b/tools/heretic2/qcommon/fmodel.h
new file mode 100644 (file)
index 0000000..e2ebfa8
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+/*
+   ========================================================================
+
+   .FM triangle flexible model file format
+
+   ========================================================================
+ */
+
+#ifndef __FMODEL_HEADER
+#define __FMODEL_HEADER
+
+#include "bspfile.h"
+
+//typedef unsigned char         byte;
+//typedef int  qboolean;
+//typedef float vec3_t[3];
+
+#define MAX_FM_TRIANGLES    2048
+#define MAX_FM_VERTS        2048
+#define MAX_FM_FRAMES       2048
+#define MAX_FM_SKINS        64
+#define MAX_FM_SKINNAME     64
+#define MAX_FM_MESH_NODES   16      // also defined in game/qshared.h
+
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+#define SKINPAGE_WIDTH 640
+#define SKINPAGE_HEIGHT 480
+
+#define ENCODED_WIDTH_X 92
+#define ENCODED_WIDTH_Y 475
+#define ENCODED_HEIGHT_X 128
+#define ENCODED_HEIGHT_Y 475
+
+#define SCALE_ADJUST_FACTOR 0.96
+
+#define INFO_HEIGHT 5
+#define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT )
+
+extern byte     *BasePalette;
+extern byte     *BasePixels,*TransPixels;
+extern int BaseWidth, BaseHeight, TransWidth, TransHeight;
+extern int ScaleWidth, ScaleHeight;
+
+int ExtractNumber( byte *pic, int x, int y );
+void DrawTextChar( int x, int y, char *text );
+void DrawLine( int x1, int y1, int x2, int y2 );
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+// Initial Header
+#define FM_HEADER_NAME  "header"
+#define FM_HEADER_VER   2
+
+typedef struct
+{
+       int skinwidth;
+       int skinheight;
+       int framesize;              // byte size of each frame
+
+       int num_skins;
+       int num_xyz;
+       int num_st;                 // greater than num_xyz for seams
+       int num_tris;
+       int num_glcmds;             // dwords in strip/fan command list
+       int num_frames;
+       int num_mesh_nodes;
+} fmheader_t;
+
+
+// Skin Header
+#define FM_SKIN_NAME    "skin"
+#define FM_SKIN_VER     1
+
+
+// ST Coord Header
+#define FM_ST_NAME      "st coord"
+#define FM_ST_VER       1
+
+typedef struct
+{
+       short s;
+       short t;
+} fmstvert_t;
+
+
+// Tri Header
+#define FM_TRI_NAME     "tris"
+#define FM_TRI_VER      1
+
+typedef struct
+{
+       short index_xyz[3];
+       short index_st[3];
+} fmtriangle_t;
+
+
+// Frame Header
+#define FM_FRAME_NAME   "frames"
+#define FM_FRAME_VER    1
+
+// Frame for compression, just the names
+#define FM_SHORT_FRAME_NAME "short frames"
+#define FM_SHORT_FRAME_VER  1
+
+// Normals for compressed frames
+#define FM_NORMAL_NAME  "normals"
+#define FM_NORMAL_VER   1
+
+// Compressed Frame Data
+#define FM_COMP_NAME    "comp data"
+#define FM_COMP_VER 1
+
+// GL Cmds Header
+#define FM_GLCMDS_NAME  "glcmds"
+#define FM_GLCMDS_VER   1
+
+
+// Mesh Nodes Header
+#define FM_MESH_NAME    "mesh nodes"
+#define FM_MESH_VER     3
+
+// Skeleton Header
+#define FM_SKELETON_NAME "skeleton"
+#define FM_SKELETON_VER 1
+
+// References Header
+#define FM_REFERENCES_NAME "references"
+#define FM_REFERENCES_VER   1
+
+typedef struct
+{
+
+       union
+       {
+
+               byte tris[MAX_FM_TRIANGLES >> 3];
+
+               struct {
+                       short   *triIndicies;
+                       int num_tris;
+               };
+
+       };
+
+       byte verts[MAX_FM_VERTS >> 3];
+       short start_glcmds, num_glcmds;
+} fmmeshnode_t;
+
+//=================================================================
+
+// Frame info
+typedef struct
+{
+       byte v[3];              // scaled byte to fit in frame mins/maxs
+       byte lightnormalindex;
+} fmtrivertx_t;
+
+typedef struct
+{
+       float scale[3];                 // multiply byte verts by this
+       float translate[3];             // then add this
+       char name[16];                  // frame name from grabbing
+       fmtrivertx_t verts[1];          // variable sized
+} fmaliasframe_t;
+
+
+#endif // #define __FMODEL_HEADER
diff --git a/tools/heretic2/qcommon/h2common.h b/tools/heretic2/qcommon/h2common.h
new file mode 100644 (file)
index 0000000..e1f2559
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef H2COMMON_H
+#define H2COMMON_H
+  #define H2COMMON_API
+#endif
diff --git a/tools/heretic2/qcommon/placement.h b/tools/heretic2/qcommon/placement.h
new file mode 100644 (file)
index 0000000..9151183
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef PLACEMENT_H
+#define PLACEMENT_H
+
+#include "q_typedef.h"
+
+//typedef float vec3_t[3];
+
+typedef struct Placement_s
+{
+       vec3_t origin;
+       vec3_t direction;
+       vec3_t up;
+} Placement_t;
+
+#endif
diff --git a/tools/heretic2/qcommon/q_typedef.h b/tools/heretic2/qcommon/q_typedef.h
new file mode 100644 (file)
index 0000000..cbe69dd
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef Q_TYPEDEF_H
+#define Q_TYPEDEF_H
+
+typedef float vec_t;
+typedef vec_t vec2_t[2];
+typedef vec_t vec3_t[3];
+typedef double vec3d_t[3];
+typedef vec_t vec5_t[5];
+
+typedef float matrix3_t[3][3];
+typedef float matrix3d_t[3][3];
+
+typedef int fixed4_t;
+typedef int fixed8_t;
+typedef int fixed16_t;
+
+typedef unsigned char byte;
+
+#ifndef __cplusplus
+typedef enum {false, true}  qboolean;
+#else
+typedef int qboolean;
+#endif
+
+typedef struct edict_s edict_t;
+
+typedef struct paletteRGBA_s
+{
+       union
+       {
+               struct
+               {
+                       byte r,g,b,a;
+               };
+               unsigned c;
+               byte c_array[4];
+       };
+} paletteRGBA_t;
+
+#endif
diff --git a/tools/heretic2/qcommon/qfiles.h b/tools/heretic2/qcommon/qfiles.h
new file mode 100644 (file)
index 0000000..4d0648c
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+   ========================================================================
+
+   The .pak files are just a linear collapse of a directory tree
+
+   ========================================================================
+ */
+
+#define IDPAKHEADER     ( ( 'K' << 24 ) + ( 'C' << 16 ) + ( 'A' << 8 ) + 'P' )
+
+typedef struct
+{
+       char name[56];
+       int filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+       int ident;          // == IDPAKHEADER
+       int dirofs;
+       int dirlen;
+} dpackheader_t;
+
+#define MAX_FILES_IN_PACK   6144
+
+
+/*
+   ========================================================================
+
+   PCX files are used for as many images as possible
+
+   ========================================================================
+ */
+
+typedef struct
+{
+       char manufacturer;
+       char version;
+       char encoding;
+       char bits_per_pixel;
+       unsigned short xmin,ymin,xmax,ymax;
+       unsigned short hres,vres;
+       unsigned char palette[48];
+       char reserved;
+       char color_planes;
+       unsigned short bytes_per_line;
+       unsigned short palette_type;
+       char filler[58];
+       unsigned char data;             // unbounded
+} pcx_t;
+
+/*
+   ========================================================================
+
+   .MD2 compressed triangle model file format
+
+   ========================================================================
+ */
+#define IDCOMPRESSEDALIASHEADER ( ( '2' << 24 ) + ( 'C' << 16 ) + ( 'D' << 8 ) + 'I' )
+
+/*
+   ========================================================================
+
+   .MD2 compressed triangle model file format
+
+   ========================================================================
+ */
+#define IDJOINTEDALIASHEADER    ( ( '2' << 24 ) + ( 'J' << 16 ) + ( 'D' << 8 ) + 'I' )
+
+/*
+   ========================================================================
+
+   .MD2 triangle model file format
+
+   ========================================================================
+ */
+
+#define IDALIASHEADER       ( ( '2' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
+#define ALIAS_VERSION   8
+
+#define MAX_TRIANGLES   4096
+#define MAX_VERTS       2048
+#define MAX_FRAMES      512
+#define MAX_MD2SKINS    64
+#define MAX_SKINNAME    64
+
+typedef struct
+{
+       short s;
+       short t;
+} dstvert_t;
+
+typedef struct
+{
+       short index_xyz[3];
+       short index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+       union
+       {
+               struct
+               {
+                       byte v[3];          // scaled byte to fit in frame mins/maxs
+                       byte lightnormalindex;
+               };
+
+               int vert;
+       };
+} dtrivertx_t;
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+typedef struct
+{
+       float scale[3];         // multiply byte verts by this
+       float translate[3];         // then add this
+       char name[16];          // frame name from grabbing
+       dtrivertx_t verts[1];   // variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+       int ident;
+       int version;
+
+       int skinwidth;
+       int skinheight;
+       int framesize;              // byte size of each frame
+
+       int num_skins;
+       int num_xyz;
+       int num_st;                 // greater than num_xyz for seams
+       int num_tris;
+       int num_glcmds;             // dwords in strip/fan command list
+       int num_frames;
+
+       int ofs_skins;              // each skin is a MAX_SKINNAME string
+       int ofs_st;                 // byte offset from start for stverts
+       int ofs_tris;               // offset for dtriangles
+       int ofs_frames;             // offset for first frame
+       int ofs_glcmds;
+       int ofs_end;                // end of file
+
+} dmdl_t;
+
+// compressed model
+typedef struct dcompmdl_s
+{
+       dmdl_t header;
+       short CompressedFrameSize;
+       short UniqueVerts;
+       short *remap;
+       float *translate;   // then add this
+       float *scale;   // multiply byte verts by this
+       char *mat;
+       char *frames;
+       char *base;
+       float *ctranslate;
+       float *cscale;
+       char data[1];
+} dcompmdl_t;
+
+typedef struct
+{
+       dcompmdl_t compModInfo;
+       int rootCluster;
+       int skeletalType;
+       struct ModelSkeleton_s *skeletons;
+} JointedModel_t;
+
+/*
+   ========================================================================
+
+   .BK file format
+
+   ========================================================================
+ */
+
+#define IDBOOKHEADER    ( ( 'K' << 24 ) + ( 'O' << 16 ) + ( 'O' << 8 ) + 'B' )
+#define BOOK_VERSION    2
+
+typedef struct bookframe_s
+{
+       int x;
+       int y;
+       int w;
+       int h;
+       char name[MAX_SKINNAME];            // name of gfx file
+} bookframe_t;
+
+typedef struct bookheader_s
+{
+       unsigned int ident;
+       unsigned int version;
+       int num_segments;
+       int total_w;
+       int total_h;
+} bookheader_t;
+
+typedef struct book_s
+{
+       bookheader_t bheader;
+       bookframe_t bframes[MAX_MD2SKINS];
+} book_t;
+
+/*
+   ========================================================================
+
+   .SP2 sprite file format
+
+   ========================================================================
+ */
+
+#define IDSPRITEHEADER  ( ( '2' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' )
+// little-endian "IDS2"
+#define SPRITE_VERSION  2
+
+typedef struct
+{
+       int width, height;
+       int origin_x, origin_y;         // raster coordinates inside pic
+       char name[MAX_SKINNAME];        // name of pcx file
+} dsprframe_t;
+
+typedef struct {
+       int ident;
+       int version;
+       int numframes;
+       dsprframe_t frames[1];          // variable sized
+} dsprite_t;
+
+/*
+   ==============================================================================
+
+   .M8 texture file format
+
+   ==============================================================================
+ */
+
+typedef struct palette_s
+{
+       union
+       {
+               struct
+               {
+                       byte r,g,b;
+               };
+       };
+} palette_t;
+
+#define MIP_VERSION     2
+#define PAL_SIZE        256
+#define MIPLEVELS       16
+
+typedef struct miptex_s
+{
+       int version;
+       char name[32];
+       unsigned width[MIPLEVELS], height[MIPLEVELS];
+       unsigned offsets[MIPLEVELS];        // four mip maps stored
+       char animname[32];                  // next frame in animation chain
+       palette_t palette[PAL_SIZE];
+       int flags;
+       int contents;
+       int value;
+} miptex_t;
+
+
+
+#define MIP32_VERSION   4
+
+typedef struct miptex32_s
+{
+       int version;
+       char name[128];
+       char altname[128];                  // texture substitution
+       char animname[128];                 // next frame in animation chain
+       char damagename[128];               // image that should be shown when damaged
+       unsigned width[MIPLEVELS], height[MIPLEVELS];
+       unsigned offsets[MIPLEVELS];
+       int flags;
+       int contents;
+       int value;
+       float scale_x, scale_y;
+       int mip_scale;
+
+       // detail texturing info
+       char dt_name[128];              // detailed texture name
+       float dt_scale_x, dt_scale_y;
+       float dt_u, dt_v;
+       float dt_alpha;
+       int dt_src_blend_mode, dt_dst_blend_mode;
+
+       int unused[20];                     // future expansion to maintain compatibility with h2
+} miptex32_t;
+
+
+/*
+   ==============================================================================
+
+   .BSP file format
+
+   ==============================================================================
+ */
+
+#define IDBSPHEADER ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' )
+// little-endian "IBSP"
+
+#define BSPVERSION  38
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define MAX_MAP_MODELS      1024
+//#define      MAX_MAP_BRUSHES         8192    // Quake 2 original
+#define MAX_MAP_BRUSHES     10240
+#define MAX_MAP_ENTITIES    2048
+#define MAX_MAP_ENTSTRING   0x40000
+#define MAX_MAP_TEXINFO     8192
+
+#define MAX_MAP_AREAS       256
+#define MAX_MAP_AREAPORTALS 1024
+#define MAX_MAP_PLANES      65536
+#define MAX_MAP_NODES       65536
+#define MAX_MAP_BRUSHSIDES  65536
+#define MAX_MAP_LEAFS       65536
+#define MAX_MAP_VERTS       65536
+#define MAX_MAP_FACES       65536
+#define MAX_MAP_LEAFFACES   65536
+#define MAX_MAP_LEAFBRUSHES 65536
+#define MAX_MAP_PORTALS     65536
+#define MAX_MAP_EDGES       128000
+#define MAX_MAP_SURFEDGES   256000
+#define MAX_MAP_LIGHTING    0x200000
+#define MAX_MAP_VISIBILITY  0x180000
+
+// key / value pair sizes
+
+#define MAX_KEY     32
+#define MAX_VALUE   1024
+
+//=============================================================================
+
+typedef struct
+{
+       int fileofs, filelen;
+} lump_t;
+
+#define LUMP_ENTITIES       0
+#define LUMP_PLANES         1
+#define LUMP_VERTEXES       2
+#define LUMP_VISIBILITY     3
+#define LUMP_NODES          4
+#define LUMP_TEXINFO        5
+#define LUMP_FACES          6
+#define LUMP_LIGHTING       7
+#define LUMP_LEAFS          8
+#define LUMP_LEAFFACES      9
+#define LUMP_LEAFBRUSHES    10
+#define LUMP_EDGES          11
+#define LUMP_SURFEDGES      12
+#define LUMP_MODELS         13
+#define LUMP_BRUSHES        14
+#define LUMP_BRUSHSIDES     15
+#define LUMP_POP            16
+#define LUMP_AREAS          17
+#define LUMP_AREAPORTALS    18
+#define HEADER_LUMPS        19
+
+typedef struct
+{
+       int ident;
+       int version;
+       lump_t lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+       float mins[3], maxs[3];
+       float origin[3];            // for sounds or lights
+       int headnode;
+       int firstface, numfaces;            // submodels just draw faces
+                                           // without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+       float point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define PLANE_X         0
+#define PLANE_Y         1
+#define PLANE_Z         2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define PLANE_ANYX      3
+#define PLANE_ANYY      4
+#define PLANE_ANYZ      5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+       float normal[3];
+       float dist;
+       int type;           // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// These definitions also need to be in q_shared.h!
+
+// ************************************************************************************************
+// CONTENTS_XXX
+// ------------
+// Contents flags.
+// ************************************************************************************************
+
+// Lower bits are stronger, and will eat weaker brushes completely.
+
+#define CONTENTS_SOLID          0x00000001  // An eye is never valid in a solid.
+#define CONTENTS_WINDOW         0x00000002  // Translucent, but not watery.
+#define CONTENTS_AUX            0x00000004
+#define CONTENTS_LAVA           0x00000008
+#define CONTENTS_SLIME          0x00000010
+#define CONTENTS_WATER          0x00000020
+#define CONTENTS_MIST           0x00000040
+#define LAST_VISIBLE_CONTENTS   CONTENTS_MIST
+
+// Remaining contents are non-visible, and don't eat brushes.
+
+#define CONTENTS_AREAPORTAL     0x00008000
+#define CONTENTS_PLAYERCLIP     0x00010000
+#define CONTENTS_MONSTERCLIP    0x00020000
+
+// Currents can be added to any other contents, and may be mixed.
+
+#define CONTENTS_CURRENT_0      0x00040000
+#define CONTENTS_CURRENT_90     0x00080000
+#define CONTENTS_CURRENT_180    0x00100000
+#define CONTENTS_CURRENT_270    0x00200000
+#define CONTENTS_CURRENT_UP     0x00400000
+#define CONTENTS_CURRENT_DOWN   0x00800000
+#define CONTENTS_ORIGIN         0x01000000  // Removed before bsping an entity.
+#define CONTENTS_MONSTER        0x02000000  // Should never be on a brush, only in game.
+#define CONTENTS_DEADMONSTER    0x04000000
+#define CONTENTS_DETAIL         0x08000000  // Brushes to be added after vis leaves.
+#define CONTENTS_TRANSLUCENT    0x10000000  // Auto set if any surface has transparency.
+#define CONTENTS_LADDER         0x20000000
+#define CONTENTS_CAMERANOBLOCK  0x40000000  // Camera LOS ignores any brushes with this flag.
+
+typedef struct
+{
+       int planenum;
+       int children[2];            // negative numbers are -(leafs+1), not nodes
+       short mins[3];              // for frustom culling
+       short maxs[3];
+       unsigned short firstface;
+       unsigned short numfaces;    // counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+       float vecs[2][4];           // [s/t][xyz offset]
+       int flags;                  // miptex flags + overrides
+       int value;                  // light emission, etc
+       char texture[32];           // texture name (textures/*.wal)
+       int nexttexinfo;            // for animations, -1 = end of chain
+} texinfo_t;
+
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+       unsigned short v[2];        // vertex numbers
+} dedge_t;
+
+#define MAXLIGHTMAPS    4
+typedef struct
+{
+       unsigned short planenum;
+       short side;
+
+       int firstedge;              // we must support > 64k edges
+       short numedges;
+       short texinfo;
+
+// lighting info
+       byte styles[MAXLIGHTMAPS];
+       int lightofs;               // start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+       int contents;                       // OR of all brushes (not needed?)
+
+       short cluster;
+       short area;
+
+       short mins[3];                      // for frustum culling
+       short maxs[3];
+
+       unsigned short firstleafface;
+       unsigned short numleaffaces;
+
+       unsigned short firstleafbrush;
+       unsigned short numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+       unsigned short planenum;        // facing out of the leaf
+       short texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+       int firstside;
+       int numsides;
+       int contents;
+} dbrush_t;
+
+#define ANGLE_UP    -1
+#define ANGLE_DOWN  -2
+
+
+// the visibility lump consists of a header with a count, then
+// byte offsets for the PVS and PHS of each cluster, then the raw
+// compressed bit vectors
+#define DVIS_PVS    0
+#define DVIS_PHS    1
+typedef struct
+{
+       int numclusters;
+       int bitofs[8][2];           // bitofs[numclusters][2]
+} dvis_t;
+
+// each area has a list of portals that lead into other areas
+// when portals are closed, other areas may not be visible or
+// hearable even if the vis info says that it should be
+typedef struct
+{
+       int portalnum;
+       int otherarea;
+} dareaportal_t;
+
+typedef struct
+{
+       int numareaportals;
+       int firstareaportal;
+} darea_t;
diff --git a/tools/heretic2/qcommon/reference.c b/tools/heretic2/qcommon/reference.c
new file mode 100644 (file)
index 0000000..7be9740
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <string.h>
+#include "reference.h"
+#include "arrayedlist.h"
+#include "resourcemanager.h"
+#include "skeletons.h"
+
+char *referenceRootNames[] =
+{
+       "elf_Lhandroot", //0
+       "elf_Rhandroot",
+       "elf_Rfootroot",
+       "elf_Lfootroot",
+       "elf_Bstaffroot",
+       "elf_bladeroot",
+       "elf_hellroot",
+       "StaffBone", //7
+       "SwordBone",
+       "SpearBone",
+       "RFootBone",
+       "LFootBone",
+       "hp_backroot", //12
+       "hp_staffroot",
+       "hp_lhandroot",
+       "hp_rhandroot",
+       "hp_rfootroot",
+       "hp_lfootroot",
+       "staffroot", //18
+       "rfootroot",
+       "lfootroot",
+       "rhandroot",
+       "lhandroot",
+       "leyeroot",
+       "reyeroot"
+};
+
+int referenceRootNameOffsets[NUM_REFERENCED] =
+{
+       0,  // CORVUS
+       7,  // INSECT
+       12, // HIGH PRIESTESS
+       18, // MORCALAVIN
+};
+
+int numReferences[NUM_REFERENCED] =
+{
+       NUM_REFERENCES_CORVUS,
+       NUM_REFERENCES_INSECT,
+       NUM_REFERENCES_PRIESTESS,
+       NUM_REFERENCES_MORK,
+};
+
+int corvusJointIDs[NUM_REFERENCES_CORVUS] =
+{
+       CORVUS_UPPERBACK,
+       CORVUS_UPPERBACK,
+       -1,
+       -1,
+       CORVUS_UPPERBACK,
+       CORVUS_UPPERBACK,
+       CORVUS_UPPERBACK,
+};
+
+int *jointIDs[NUM_REFERENCED] =
+{
+       corvusJointIDs,
+};
+
+static ResourceManager_t ReferenceMngr;
+
+void InitReferenceMngr(){
+#define REFERENCE_BLOCK_SIZE 8
+       char *dummystr = NULL;
+
+       ResMngr_Con( &ReferenceMngr, sizeof( LERPedReferences_t ), REFERENCE_BLOCK_SIZE, dummystr );
+}
+
+void ReleaseReferenceMngr(){
+       ResMngr_Des( &ReferenceMngr );
+}
+
+LERPedReferences_t *LERPedReferences_new( int init_refType ){
+       LERPedReferences_t  *newRefs;
+
+       newRefs = ResMngr_AllocateResource( &ReferenceMngr, sizeof( *newRefs ) );
+       newRefs->refType = init_refType;
+       newRefs->jointIDs = jointIDs[init_refType];
+       newRefs->lastUpdate = -( REF_MINCULLTIME * 2.0 );
+
+       memset( newRefs->references, 0, MAX_REFPOINTS * sizeof( Reference_t ) );
+       memset( newRefs->oldReferences, 0, MAX_REFPOINTS * sizeof( Reference_t ) );
+
+       return newRefs;
+}
+
+void LERPedReferences_delete( LERPedReferences_t *toDelete ){
+       ResMngr_DeallocateResource( &ReferenceMngr, toDelete, sizeof( *toDelete ) );
+}
+
+// end
diff --git a/tools/heretic2/qcommon/reference.h b/tools/heretic2/qcommon/reference.h
new file mode 100644 (file)
index 0000000..747c4d4
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef REFERENCE_H
+#define REFERENCE_H
+
+#include "placement.h"
+
+#define MAX_REFPOINTS       16
+#define REF_MINCULLTIME     1.0
+
+typedef struct Reference_s
+{
+       int activecount;
+       Placement_t placement;
+} Reference_t;
+
+typedef struct LERPedReferences_s
+{
+       int refType;
+       int         *jointIDs;
+       float lastUpdate;
+       Reference_t references[MAX_REFPOINTS];
+       Reference_t oldReferences[MAX_REFPOINTS];
+} LERPedReferences_t;
+
+// Reference Types
+enum {
+       REF_NULL = -1,
+       REF_CORVUS, //0
+       REF_INSECT, //1
+       REF_PRIESTESS, //2
+       REF_MORK, //3
+       NUM_REFERENCED //4
+};
+
+// Corvus Reference Points
+enum {
+       CORVUS_LEFTHAND, //0
+       CORVUS_RIGHTHAND,
+       CORVUS_LEFTFOOT,
+       CORVUS_RIGHTFOOT,
+       CORVUS_STAFF,
+       CORVUS_BLADE,
+       CORVUS_HELL_HEAD,
+       NUM_REFERENCES_CORVUS //7
+};
+
+// Tchekrik Reference Points
+enum {
+       INSECT_STAFF, //0
+       INSECT_SWORD,
+       INSECT_SPEAR,
+       INSECT_RIGHTFOOT,
+       INSECT_LEFTFOOT,
+       NUM_REFERENCES_INSECT //5
+};
+
+// High Priestess Reference Points
+enum {
+       PRIESTESS_BACK, //0
+       PRIESTESS_STAFF,
+       PRIESTESS_LHAND,
+       PRIESTESS_RHAND,
+       PRIESTESS_RFOOT,
+       PRIESTESS_LFOOT,
+       NUM_REFERENCES_PRIESTESS //6
+};
+
+// Morcalavin Reference Points
+enum
+{
+       MORK_STAFFREF, //0
+       MORK_RFOOTREF, //1
+       MORK_LFOOTREF, //2
+       MORK_RHANDREF, //3
+       MORK_LHANDREF, //4
+       MORK_LEYEREF, //5
+       MORK_REYEREF, //6
+       NUM_REFERENCES_MORK //7
+};
+
+#define CORVUS_LIMBS_MASK   ( ( 1 << CORVUS_LEFTHAND ) | ( 1 << CORVUS_RIGHTHAND ) | ( 1 << CORVUS_LEFTFOOT ) | ( 1 << CORVUS_RIGHTFOOT ) )
+#define CORVUS_WEAPON_MASK  ( ( 1 << CORVUS_STAFF ) | ( 1 << CORVUS_BLADE ) | ( 1 << CORVUS_HELL_HEAD ) )
+#define CORVUS_MASK         ( CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK )
+
+#define INSECT_MASK         ( ( 1 << INSECT_STAFF ) | ( 1 << INSECT_SWORD ) | ( 1 << INSECT_SPEAR ) | ( 1 << INSECT_RIGHTFOOT ) | ( 1 << INSECT_LEFTFOOT ) )
+
+#define PRIESTESS_MASK      ( ( 1 << PRIESTESS_BACK ) | ( 1 << PRIESTESS_STAFF ) | ( 1 << PRIESTESS_LHAND ) | ( 1 << PRIESTESS_RHAND ) | ( 1 << PRIESTESS_RFOOT ) | ( 1 << PRIESTESS_LFOOT ) )
+
+#define MORK_MASK           ( ( 1 << MORK_STAFFREF ) | ( 1 << MORK_RFOOTREF ) | ( 1 << MORK_LFOOTREF ) | ( 1 << MORK_RHANDREF ) | ( 1 << MORK_LHANDREF ) | ( 1 << MORK_LEYEREF ) | ( 1 << MORK_REYEREF ) )
+
+extern char *referenceRootNames[];
+extern int referenceRootNameOffsets[];
+extern int numReferences[];
+
+void EnableRefPoints( LERPedReferences_t *refInfo, int mask );
+void DisableRefPoints( LERPedReferences_t *refInfo, int mask );
+
+void InitReferenceMngr();
+void ReleaseReferenceMngr();
+
+LERPedReferences_t *LERPedReferences_new( int init_refType );
+void LERPedReferences_delete( LERPedReferences_t *toDelete );
+
+#endif
diff --git a/tools/heretic2/qcommon/resourcemanager.c b/tools/heretic2/qcommon/resourcemanager.c
new file mode 100644 (file)
index 0000000..2eb0140
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+//
+// ResourceManager.c
+//
+
+#include <stdio.h>
+#include "resourcemanager.h"
+#include <assert.h>
+
+typedef struct ResMngr_Block_s
+{
+       char *start;
+       unsigned int size;
+       struct ResMngr_Block_s *next;
+} ResMngr_Block_t;
+
+static void ResMngr_CreateBlock( ResourceManager_t *resource ){
+       unsigned int _blockSize;
+       char *block;
+       char **current;
+       ResMngr_Block_t *temp;
+       unsigned int i;
+
+       _blockSize = resource->nodeSize * resource->resPerBlock;
+
+       block = malloc( _blockSize );
+
+       assert( block );
+
+       temp = malloc( sizeof( *temp ) );
+
+       temp->start = block;
+       temp->size = _blockSize;
+       temp->next = resource->blockList;
+
+       resource->blockList = temp;
+
+       resource->free = (char **)( block );
+
+       current = resource->free;
+
+       for ( i = 1; i < resource->resPerBlock; ++i )
+       {
+               // set current->next to point to next node
+               *current = (char *)( current ) + resource->nodeSize;
+
+               // set current node to current->next
+               current = (char **)( *current );
+       }
+
+       *current = NULL;
+}
+
+H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ){
+       resource->resSize = init_resSize;
+
+       resource->resPerBlock = init_resPerBlock;
+
+       resource->nodeSize = resource->resSize + sizeof( *resource->free );
+
+       resource->blockList = NULL;
+
+       resource->numResourcesAllocated = 0;
+
+       ResMngr_CreateBlock( resource );
+}
+
+H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ){
+       ResMngr_Block_t *toDelete;
+
+#if 0
+       if ( resource->numResourcesAllocated ) {
+               char mess[100];
+               sprintf( mess,"Potential memory leak %d bytes unfreed\n",resource->resSize * resource->numResourcesAllocated );
+               OutputDebugString( mess );
+       }
+#endif
+
+       while ( resource->blockList )
+       {
+               toDelete = resource->blockList;
+               resource->blockList = resource->blockList->next;
+               free( toDelete->start );
+               free( toDelete );
+       }
+}
+
+H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ){
+       char **toPop;
+
+       assert( size == resource->resSize );
+
+       ++resource->numResourcesAllocated;
+
+       assert( resource->free ); // constructor not called; possibly due to a static object
+       // containing a static ResourceManagerFastLarge member being
+       // constructed before its own static members
+
+       toPop = resource->free;
+
+       // set unallocated to the next node and check for NULL (end of list)
+       if ( !( resource->free = (char **)( *resource->free ) ) ) { // if at end create new block
+               ResMngr_CreateBlock( resource );
+       }
+
+       // set next to NULL
+       *toPop = NULL;
+
+       // return the resource for the node
+       return (void *)( toPop + 1 );
+}
+
+H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ){
+       char **toPush;
+
+       assert( size == resource->resSize );
+
+       --resource->numResourcesAllocated;
+
+       toPush = (char **)( toDeallocate ) - 1;
+
+       assert( resource->free ); // see same assert at top of AllocateResource
+
+       // set toPop->next to current unallocated front
+       *toPush = (char *)( resource->free );
+
+       // set unallocated to the node removed from allocated
+       resource->free = toPush;
+}
+
+// end
diff --git a/tools/heretic2/qcommon/resourcemanager.h b/tools/heretic2/qcommon/resourcemanager.h
new file mode 100644 (file)
index 0000000..be82d78
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// ResourceManager.h
+//
+
+#include "h2common.h"
+#include <stdlib.h>     // needed here for size_t
+
+typedef struct ResourceManager_s
+{
+       size_t resSize;
+       unsigned int resPerBlock;
+       unsigned int nodeSize;
+       struct ResMngr_Block_s *blockList;
+       char **free;
+       char *ResMan_Name;
+
+       unsigned numResourcesAllocated;
+
+} ResourceManager_t;
+
+extern H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name );
+extern H2COMMON_API void ResMngr_Des( ResourceManager_t *resource );
+extern H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size );
+extern H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size );
diff --git a/tools/heretic2/qcommon/skeletons.c b/tools/heretic2/qcommon/skeletons.c
new file mode 100644 (file)
index 0000000..453cb77
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+//
+// Skeletons.c
+//
+
+#include "skeletons.h"
+
+char *skeletonRootNames[] =
+{
+       "RAVEN_ROOT",
+       "BOX_ROOT",
+       "BEETLE_ROOT",
+       "ELFLORD_ROOT",
+       "PLAGUELF_ROOT",
+       "ELF_BACKROOT",
+};
+
+int skeletonRNameOffsets[] =
+{
+       0,  // RAVEN
+       1,  // BOX
+       2,  // BEETLE
+       3,  // ELFLORD
+       4,  // PLAGUE ELF
+       5,  // CORVUS
+};
+
+char *skeletonJointNames[] =
+{
+       "RAVEN_LOWERBACK",  // 0
+       "RAVEN_UPPERBACK",
+       "RAVEN_NECK",
+       "BOX_CENTER",       // 3
+       "BEETLE_NECK",      // 4
+       "BEETLE_HEAD",
+       "PLAGUELF_BACKB",   // 6
+       "PLAGUELF_BACKC",
+       "PLAGUELF_NECK",
+       "ELF_BACKB",        // 9
+       "ELF_BACKC",
+       "ELF_NECKB",
+};
+
+int skeletonNameOffsets[] =
+{
+       0,  // RAVEN
+       3,  // BOX
+       4,  // BEETLE
+       -1, // ELFLORD
+       6,  // PLAGUE ELF
+       9,  // CORVUS
+};
+
+char *skeletonEffectorNames[] =
+{
+       "BEETLE_EYES",      // 0
+       "CORVUS_EYES",      // 1
+};
+
+int skeletonENameOffsets[] =
+{
+       -1, // RAVEN
+       -1, // BOX
+       0,  // BEETLE
+       -1, // ELFLORD
+       1,  // PLAGUE ELF
+};
+
+int numJointsInSkeleton[] =
+{
+       NUM_JOINTS_RAVEN,
+       NUM_JOINTS_BOX,
+       NUM_JOINTS_BEETLE,
+       NUM_JOINTS_ELFLORD,
+       NUM_JOINTS_PLAGUE_ELF,
+       NUM_JOINTS_CORVUS,
+};
+
+int numNodesInSkeleton[] =
+{
+       2,  // RAVEN
+       0,  // BOX
+       1,  // BEETLE
+       -1, // ELFLORD
+       2,  // PLAGUE ELF
+       2,  // CORVUS
+};
+
+void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root );
+void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root );
+void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
+void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
+void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
+
+CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] =
+{
+       CreateRavenSkel,
+       CreateBoxSkel,
+       CreateBeetleSkel,
+       CreateElfLordSkel,
+       CreatePlagueElfSkel,
+       CreatePlagueElfSkel,    // Corvus has the same structure as the Plague Elf
+};
+
+void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
+       char *root;
+       int *children;
+       int nodeIndex;
+
+       root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+       children = (int *)( root + RAVEN_HEAD * jointSize );
+       *children = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + RAVEN_UPPERBACK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + RAVEN_LOWERBACK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
+       char *root;
+       int *children;
+
+       root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+       children = (int *)( root + RAVEN_HEAD * jointSize );
+       *children = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
+       char *root;
+       int *children;
+       int nodeIndex;
+
+       root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+       children = (int *)( root + BEETLE_HEAD * jointSize );
+       *children = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + BEETLE_NECK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
+       char *root;
+       int *children;
+       int nodeIndex;
+
+       root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+       children = (int *)( root + BEETLE_HEAD * jointSize );
+       *children = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + BEETLE_NECK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
+       char *root;
+       int *children;
+       int nodeIndex;
+
+       root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+       children = (int *)( root + PLAGUE_ELF_HEAD * jointSize );
+       *children = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + PLAGUE_ELF_UPPERBACK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+
+       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
+
+       children = (int *)( root + PLAGUE_ELF_LOWERBACK * jointSize );
+       *children = nodeIndex;
+
+       g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK;
+       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
diff --git a/tools/heretic2/qcommon/skeletons.h b/tools/heretic2/qcommon/skeletons.h
new file mode 100644 (file)
index 0000000..9d7fe96
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <stdlib.h> // for size_t
+#include "arrayedlist.h"
+
+#define JN_YAW_CHANGED      0x00000001
+#define JN_PITCH_CHANGED    0x00000002
+#define JN_ROLL_CHANGED     0x00000004
+
+// Skeleton types
+enum {
+       SKEL_NULL = -1,
+       SKEL_RAVEN = 0,
+       SKEL_BOX,
+       SKEL_BEETLE,
+       SKEL_ELFLORD,
+       SKEL_PLAGUE_ELF,
+       SKEL_CORVUS,
+       NUM_SKELETONS
+};
+
+// Raven Skeletal joints
+enum {
+       RAVEN_LOWERBACK = 0,
+       RAVEN_UPPERBACK,
+       RAVEN_HEAD,
+       NUM_JOINTS_RAVEN
+};
+
+// Box Skeletal joints
+enum {
+       BOX_CENTER = 0,
+       NUM_JOINTS_BOX
+};
+
+// Beetle Skeletal joints
+enum {
+       BEETLE_NECK = 0,
+       BEETLE_HEAD,
+       NUM_JOINTS_BEETLE
+};
+
+// Elflord Skeletal joints
+enum {
+       ELFLORD_,
+       ELFLORD__,
+       NUM_JOINTS_ELFLORD
+};
+
+// Plague Elf Skeletal joints
+enum {
+       PLAGUE_ELF_LOWERBACK,
+       PLAGUE_ELF_UPPERBACK,
+       PLAGUE_ELF_HEAD,
+       NUM_JOINTS_PLAGUE_ELF
+};
+
+// Corvus Skeletal joints
+enum {
+       CORVUS_LOWERBACK,
+       CORVUS_UPPERBACK,
+       CORVUS_HEAD,
+       NUM_JOINTS_CORVUS
+};
+
+#define NO_SWAP_FRAME -1
+#define NULL_ROOT_JOINT -1
+
+#define MAX_ARRAYED_SKELETAL_JOINTS 255 // has max of 65,535 (if this remains at 255, net code can be changed to reflect)
+#define MAX_ARRAYED_JOINT_NODES ( MAX_ARRAYED_SKELETAL_JOINTS - 1 )
+
+#define MAX_JOINTS_PER_SKELETON 8   // arbitrary small number
+#define MAX_JOINT_NODES_PER_SKELETON ( MAX_JOINTS_PER_SKELETON - 1 )
+
+extern char *skeletonRootNames[];
+extern int skeletonRNameOffsets[];
+extern char *skeletonJointNames[];
+extern int skeletonNameOffsets[];
+extern int numJointsInSkeleton[];
+extern char *skeletonEffectorNames[];
+extern int skeletonENameOffsets[];
+extern int numNodesInSkeleton[];
+
+typedef void ( *CreateSkeleton_t )( void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex );
+
+extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS];
diff --git a/tools/quake2/CMakeLists.txt b/tools/quake2/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b36be1a
--- /dev/null
@@ -0,0 +1,99 @@
+include_directories(BEFORE common)
+
+find_package(LibXml2 REQUIRED)
+include_directories(${LIBXML2_INCLUDE_DIR})
+
+radiant_tool(q2map
+    q2map/q2map.rc
+
+    common/bspfile.c common/bspfile.h
+    common/cmdlib.c common/cmdlib.h
+    common/inout.c common/inout.h
+    common/l3dslib.c common/l3dslib.h
+    common/lbmlib.c common/lbmlib.h
+    common/mathlib.c common/mathlib.h
+    common/md4.c common/md4.h
+    common/path_init.c
+    common/qfiles.h
+    common/polylib.c common/polylib.h
+    common/scriplib.c common/scriplib.h
+    common/threads.c common/q2_threads.h
+    common/trilib.c common/trilib.h
+    
+    q2map/brushbsp.c
+    q2map/csg.c
+    q2map/faces.c
+    q2map/flow.c
+#   q2map/gldraw.c
+    q2map/glfile.c
+    q2map/leakfile.c
+    q2map/lightmap.c
+    q2map/main.c q2map/q2map.h
+    q2map/map.c
+    q2map/nodraw.c
+    q2map/patches.c
+    q2map/portals.c
+    q2map/prtfile.c
+    q2map/qbsp.c
+    q2map/qbsp.h
+    q2map/qrad.c
+    q2map/qrad.h
+    q2map/qvis.c
+    q2map/qvis.h
+    q2map/textures.c
+    q2map/trace.c
+    q2map/tree.c
+    q2map/writebsp.c
+)
+
+target_compile_definitions(q2map
+    PRIVATE
+)
+
+target_link_libraries(q2map
+    ${LIBXML2_LIBRARIES}
+    l_net
+)
+
+radiant_tool(qdata3
+    qdata/qdata.rc
+
+    common/bspfile.c common/bspfile.h
+    common/cmdlib.c common/cmdlib.h
+    common/inout.c common/inout.h
+    common/l3dslib.c common/l3dslib.h
+    common/lbmlib.c common/lbmlib.h
+    common/mathlib.c common/mathlib.h
+    common/md4.c common/md4.h
+    common/path_init.c
+    common/qfiles.h
+    common/polylib.c common/polylib.h
+    common/scriplib.c common/scriplib.h
+    common/threads.c common/q2_threads.h
+    common/trilib.c common/trilib.h
+
+    qdata/anorms.h
+    qdata/images.c
+    qdata/models.c
+    qdata/qdata.c qdata/qdata.h
+    qdata/sprites.c
+    qdata/tables.c
+    qdata/video.c
+)
+
+target_compile_definitions(qdata3
+    PRIVATE
+)
+
+target_link_libraries(qdata3
+    ${LIBXML2_LIBRARIES}
+    l_net
+)
+
+add_custom_target(quake2)
+add_dependencies(quake2 q2map qdata3)
+
+if (UNIX)
+    target_link_libraries(q2map pthread m)
+    target_link_libraries(qdata3 pthread m)
+endif ()
index 02e0be87c39cbb3a610852ab6268a99a4911b7e1..fd025691a30f7742773c9834f6bc7b635c5da14c 100644 (file)
 #if GDEF_OS_WINDOWS
 #include <direct.h>
 #include <windows.h>
-#endif
-
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#else // !GDEF_OS_WINDOWS
 #include <unistd.h>
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 #ifdef NeXT
 #include <libc.h>
@@ -48,7 +46,6 @@
 
 // qboolean verbose = false;
 
-#ifdef SAFE_MALLOC
 void *safe_malloc( size_t size ){
        void *p;
 
@@ -72,7 +69,6 @@ void *safe_malloc_info( size_t size, char* info ){
        memset( p, 0, size );
        return p;
 }
-#endif
 
 // set these before calling CheckParm
 int myargc;
@@ -494,23 +490,20 @@ int Q_strcasecmp( const char *s1, const char *s2 ){
        return Q_strncasecmp( s1, s2, 99999 );
 }
 
-
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-   char *strupr (char *start)
-   {
-    char       *in;
-    in = start;
-    while (*in)
-    {
-   *in = toupper(*in);
-        in++;
-    }
-    return start;
-   }
- */
+// May be already defined with some compilers on Windows
+#ifndef strupr
+char *strupr (char *start)
+{
+       char *in;
+       in = start;
+       while (*in)
+       {
+               *in = toupper(*in);
+               in++;
+       }
+       return start;
+}
+#endif
 
 char *strlower( char *start ){
        char    *in;
@@ -1177,8 +1170,7 @@ void QCopyFile( const char *from, const char *to ){
 void Sys_Sleep( int n ){
 #if GDEF_OS_WINDOWS
        Sleep( n );
-#endif
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#else // !GDEF_OS_WINDOWS
        usleep( n * 1000 );
-#endif
+#endif // !GDEF_OS_WINDOWS
 }
index f8d8e0d361a415c2e4996fd651a0cad789393e79..3dbf9682f51aedf55271b2a15b927974469b564c 100644 (file)
@@ -70,18 +70,18 @@ typedef unsigned char byte;
 // the dec offsetof macro doesnt work very well...
 #define myoffsetof( type,identifier ) ( (size_t)& ( (type *)0 )->identifier )
 
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
 void *safe_malloc( size_t size );
 void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc( a ) malloc( a )
-#endif /* SAFE_MALLOC */
 
 // set these before calling CheckParm
 extern int myargc;
 extern char **myargv;
 
+// May be already defined with some compilers on Windows
+#ifndef strupr
+char *strupr (char *start);
+#endif
+
 char *strlower( char *in );
 int Q_strncasecmp( const char *s1, const char *s2, int n );
 int Q_strcasecmp( const char *s1, const char *s2 );
index cd413805b9acda86e4628818a07fb38720161730..766531418f792016ad074f88d838df39523ba60e 100644 (file)
    You should have received a copy of the GNU General Public License
    along with GtkRadiant; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
+/*
    Nurail: Swiped from Q3Map2
-
  */
 
 #include "globaldefs.h"
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-       #define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
+#if !GDEF_OS_WINDOWS
        #include <unistd.h>
        #include <pwd.h>
        #include <limits.h>
-#endif
-
+#endif // !GDEF_OS_WINDOWS
 
 /* dependencies */
 #include "cmdlib.h"
 #include "inout.h"
 
-
-
 /* path support */
 #define MAX_BASE_PATHS  10
 #define MAX_GAME_PATHS  10
@@ -65,9 +59,9 @@ char                    *gamePaths[ MAX_GAME_PATHS ];
  */
 
 char *LokiGetHomeDir( void ){
-       #ifndef Q_UNIX
+       #if GDEF_OS_WINDOWS
        return NULL;
-       #else
+       #else // !GDEF_OS_WINDOWS
        char            *home;
        uid_t id;
        struct passwd   *pwd;
@@ -91,7 +85,7 @@ char *LokiGetHomeDir( void ){
 
        /* return it */
        return home;
-       #endif
+       #endif // !GDEF_OS_WINDOWS
 }
 
 
@@ -102,10 +96,10 @@ char *LokiGetHomeDir( void ){
  */
 
 void LokiInitPaths( char *argv0 ){
-       #ifndef Q_UNIX
+       #if GDEF_OS_WINDOWS
        /* this is kinda crap, but hey */
        strcpy( installPath, "../" );
-       #else
+       #else // !GDEF_OS_WINDOWS
        char temp[ MAX_OS_PATH ];
        char        *home;
        char        *path;
@@ -177,7 +171,7 @@ void LokiInitPaths( char *argv0 ){
 
        /* set home path */
        homePath = home;
-       #endif
+       #endif // !GDEF_OS_WINDOWS
 }
 
 
@@ -223,7 +217,7 @@ void AddBasePath( char *path ){
  */
 
 void AddHomeBasePath( char *path ){
-       #ifdef Q_UNIX
+       #if !GDEF_OS_WINDOWS
        int i;
        char temp[ MAX_OS_PATH ];
 
@@ -245,7 +239,7 @@ void AddHomeBasePath( char *path ){
        strcpy( basePaths[ 0 ], temp );
        CleanPath( basePaths[ 0 ] );
        numBasePaths++;
-       #endif
+       #endif // !GDEF_OS_WINDOWS
 }
 
 
index d648e99e490b07165e6117fdc484207eb97613f7..1d4e996b649c857636a30869d30dff3267ce8cb9 100644 (file)
@@ -25,8 +25,7 @@
 // The below define is necessary to use
 // pthreads extensions like pthread_mutexattr_settype
 #define _GNU_SOURCE
-#include <pthread.h>
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 #include "cmdlib.h"
 #include "mathlib.h"
@@ -101,6 +100,8 @@ void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )(
 }
 
 
+#if GDEF_OS_WINDOWS
+
 /*
    ===================================================================
 
@@ -108,9 +109,6 @@ void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )(
 
    ===================================================================
  */
-#if GDEF_OS_WINDOWS
-
-#define USED
 
 #include <windows.h>
 
@@ -212,7 +210,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
+#elif GDEF_OS_OSF1
 
 /*
    ===================================================================
@@ -222,9 +220,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    ===================================================================
  */
 
-#ifdef __osf__
-#define USED
-
 int numthreads = 4;
 
 void ThreadSetDefault( void ){
@@ -319,7 +314,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
+#elif GDEF_OS_IRIX
 
 /*
    ===================================================================
@@ -329,15 +324,11 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    ===================================================================
  */
 
-#ifdef _MIPS_ISA
-#define USED
-
 #include <task.h>
 #include <abi_mutex.h>
 #include <sys/types.h>
 #include <sys/prctl.h>
 
-
 int numthreads = -1;
 abilock_t lck;
 
@@ -406,8 +397,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
-
+#elif GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
 
 /*
    =======================================================================
@@ -417,9 +407,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    =======================================================================
  */
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-#define USED
-
 // Setting default Threads to 1
 int numthreads = 1;
 
@@ -570,9 +557,10 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
                Sys_Printf( " (%i)\n", end - start );
        }
 }
-#endif // ifdef __linux__
 
 
+#else // UNKNOWN OS
+
 /*
    =======================================================================
 
@@ -581,8 +569,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    =======================================================================
  */
 
-#ifndef USED
-
 int numthreads = 1;
 
 void ThreadSetDefault( void ){
@@ -617,4 +603,4 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
        }
 }
 
-#endif
+#endif // UNKNOWN OS
index 792690790530546297e0254c17cc776dd40c8505..ab900c9033d03bce773e3c9396c560f64bea96bd 100644 (file)
@@ -461,7 +461,8 @@ int Q_strcasecmp (char *s1, char *s2)
        return Q_strncasecmp (s1, s2, 99999);
 }
 
-
+// May be already defined with some compilers on Windows
+#ifndef strupr
 char *strupr (char *start)
 {
        char    *in;
@@ -473,6 +474,7 @@ char *strupr (char *start)
        }
        return start;
 }
+#endif
 
 char *strlower (char *start)
 {
index 0821ce512f517de8b02ef2d56584fa7679a5e20b..afbeb348e72345f5e7734fd983099fe15c41516c 100644 (file)
@@ -56,8 +56,12 @@ typedef unsigned char byte;
 extern int myargc;
 extern char **myargv;
 
-char *strupr (char *in);
-char *strlower (char *in);
+// May be already defined with some compilers on Windows
+#ifndef strupr
+char *strupr (char *start);
+#endif
+
+char *strlower (char *start);
 int Q_strncasecmp (char *s1, char *s2, int n);
 int Q_strcasecmp (char *s1, char *s2);
 void Q_getwd (char *out);
index fb85403b0a128a4750eae2b12bfaa10fe3b3d95e..6f5318f5ae626306df2f460c871b48f3f04cddf3 100644 (file)
@@ -60,6 +60,7 @@ extern float subdivide_size;
 
 // VIS
 extern char inbase[32];
+extern char outbase[32];
 extern qboolean fastvis;
 extern qboolean nosort;
 extern int testlevel;
index 644f7b9e88fda0a536d8eaaa01fef6c974823666..8f4ac8d3eaabea9b815d123f1743fda41bc0e023 100644 (file)
 #include "globaldefs.h"
 
 /* platform-specific */
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-       #define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
+#if GDEF_OS_WINDOWS
+       #include <windows.h>
+#else // !GDEF_OS_WINDOWS
        #include <unistd.h>
        #include <pwd.h>
        #include <limits.h>
-#endif
-
-#if GDEF_OS_WINDOWS
-       #include <windows.h>
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 #include <stdlib.h>
 
diff --git a/tools/quake2/q2map/q2map.rc b/tools/quake2/q2map/q2map.rc
new file mode 100644 (file)
index 0000000..29e1dbd
--- /dev/null
@@ -0,0 +1 @@
+101                     ICON    DISCARDABLE     "..\\..\\..\\icons\\q2map.ico"
index 3b8995b2677e70bd8b2c2ffbe69a469369b1522b..1642c1d21fe9110692f77ce8950ceac864f6d5b4 100644 (file)
@@ -45,8 +45,6 @@ qboolean noopt;
 qboolean leaktest;
 qboolean verboseentities;
 
-char outbase[32];
-
 int block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
 
 int entity_num;
index c17b5bb9e01cd47b632f72dad55b7fc90adf7c6e..6772c9d88c4211e32c6bf3cbccee85d7b8ab2a9e 100644 (file)
@@ -44,7 +44,8 @@ vec3_t illumination[MAX_PATCHES];       // light arriving at a patch
 vec3_t face_offset[MAX_MAP_FACES];          // for rotating bmodels
 dplane_t backplanes[MAX_MAP_PLANES];
 
-char inbase[32], outbase[32];
+extern char inbase[32];
+extern char outbase[32];
 
 int fakeplanes;                         // created planes for origin offset
 
@@ -64,11 +65,11 @@ float maxlight = 196;
 
 float lightscale = 1.0;
 
-qboolean glview;
+extern qboolean glview;
 
 qboolean nopvs;
 
-char source[1024];
+extern char source[1024];
 
 float direct_scale =  0.4;
 float entity_scale =  1.0;
@@ -582,7 +583,6 @@ void RadWorld( void ){
        RunThreadsOnIndividual( numfaces, true, FinalLightFace );
 }
 
-
 /*
    ========
    main
@@ -603,6 +603,8 @@ int RAD_Main(){
 
        start = I_FloatTime();
 
+       void ( *CalcTextureReflectivity )( void );
+
        if ( !strcmp( game, "heretic2" ) ) {
                CalcTextureReflectivity = &CalcTextureReflectivity_Heretic2;
        }
index 7f5df16c61b58d4464f96194445577ecac2e6b4a..66a4ec4d0e39e7f6fbc705a39e3c4c27d1676c8b 100644 (file)
@@ -172,7 +172,6 @@ void MakeTnodes( dmodel_t *bm );
 void MakePatches( void );
 void SubdividePatches( void );
 void PairEdges( void );
-void ( *CalcTextureReflectivity )( void );
 void CalcTextureReflectivity_Quake2( void );
 void CalcTextureReflectivity_Heretic2( void );
 
diff --git a/tools/quake2/qdata/qdata.rc b/tools/quake2/qdata/qdata.rc
new file mode 100644 (file)
index 0000000..d6e75b9
--- /dev/null
@@ -0,0 +1 @@
+101                     ICON    DISCARDABLE     "..\\..\\..\\icons\\qdata3.ico"
diff --git a/tools/quake2/qdata_heretic2/adpcm.h b/tools/quake2/qdata_heretic2/adpcm.h
deleted file mode 100644 (file)
index aad74ea..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/*
-** adpcm.h - include file for adpcm coder.
-**
-** Version 1.0, 7-Jul-92.
-**
-** Modded 10/3/98
-** John Scott
-*/
-
-typedef struct adpcm_state_s
-{
-       short in_valprev;           // Previous output value
-       short in_index;             // Index into stepsize table
-       short out_valprev;          // Previous output value
-       short out_index;            // Index into stepsize table
-       int count;                  // Number of sample counts
-}   adpcm_state_t;
-
-typedef struct adpcm_s
-{
-       adpcm_state_t state;
-       char adpcm[0x10000];
-}   adpcm_t;
-
-void adpcm_coder( short [], adpcm_t * );
-void adpcm_decoder( adpcm_t *, short [] );
-
-// end
diff --git a/tools/quake2/qdata_heretic2/animcomp.c b/tools/quake2/qdata_heretic2/animcomp.c
deleted file mode 100644 (file)
index a761932..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <memory.h>
-#include "animcomp.h"
-
-
-void    *SafeMalloc( size_t n, char *desc );
-
-
-
-float *matrix;
-float *delta;
-float *best;
-float *comp;
-float *tcomp;
-float *bestcomp;
-float *frames;
-float *base;
-
-int MatWidth;
-int MatHeight;
-int CFrameSize;
-int nFrames;
-
-
-void AnimCompressInit( int nframes,int nVerts,int CompressedFrameSize ){
-       nFrames = nframes;
-       MatWidth = nVerts * 3;
-       MatHeight = CompressedFrameSize;
-       CFrameSize = CompressedFrameSize;
-       matrix = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
-       best = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
-       delta = (float *)SafeMalloc( MatWidth * MatHeight * sizeof( float ), "AnimCompressInit" );
-       comp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
-       tcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
-       bestcomp = (float *)SafeMalloc( CFrameSize * nFrames * sizeof( float ), "AnimCompressInit" );
-       base = (float *)SafeMalloc( MatWidth * sizeof( float ), "AnimCompressInit" );
-       frames = (float *)SafeMalloc( MatWidth * nFrames * sizeof( float ), "AnimCompressInit" );
-}
-
-void AnimSetFrame( int frame,int index,float x,float y,float z ){
-       frames[frame * MatWidth + index * 3] = x;
-       frames[frame * MatWidth + index * 3 + 1] = y;
-       frames[frame * MatWidth + index * 3 + 2] = z;
-}
-
-typedef struct
-{
-       int index;
-       float val;
-} SORTP;
-
-
-#define F_RANDOM ( ( (float)rand() ) / (float)RAND_MAX )
-
-extern void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize );
-
-void AnimCompressDoit(){
-       float compression;
-       float *rescale;
-       float *ans;
-       float maxdev;
-       float avedev;
-       float tmp;
-       int j,k,l,numave;
-
-       for ( k = 0; k < MatWidth; k++ )
-               base[k] = 0.0f;
-       for ( j = 0; j < nFrames; j++ )
-               for ( k = 0; k < MatWidth; k++ )
-                       base[k] += frames[j * MatWidth + k];
-       tmp = 1.0f / (float)nFrames;
-       for ( k = 0; k < MatWidth; k++ )
-               base[k] *= tmp;
-       for ( j = 0; j < nFrames; j++ )
-               for ( k = 0; k < MatWidth; k++ )
-                       frames[j * MatWidth + k] -= base[k];
-
-       ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressDoit" );
-       rescale = (float *)SafeMalloc( sizeof( float ) * CFrameSize, "AnimCompressDoit" );
-       DOsvd( frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight );
-       avedev = 0.0;
-       for ( l = 0; l < CFrameSize; l++ )
-               avedev += rescale[l];
-       for ( l = 0; l < CFrameSize; l++ )
-               printf( "%3.1f ",100.0f * rescale[l] / avedev );
-       printf( "\n" );
-       for ( j = 0; j < nFrames; j++ )
-       {
-               for ( l = 0; l < CFrameSize; l++ )
-               {
-                       bestcomp[j * CFrameSize + l] = 0.0;
-                       for ( k = 0; k < MatWidth; k++ )
-                               bestcomp[j * CFrameSize + l] += best[l * MatWidth + k] * frames[j * MatWidth + k];
-               }
-       }
-       numave = 0;
-       avedev = 0.0;
-       maxdev = 0.0;
-       for ( j = 0; j < nFrames; j++ )
-       {
-               for ( k = 0; k < MatWidth; k++ )
-               {
-                       ans[k] = 0.0;
-                       for ( l = 0; l < CFrameSize; l++ )
-                               ans[k] += best[l * MatWidth + k] * bestcomp[j * CFrameSize + l];
-                       ans[k] -= frames[j * MatWidth + k];
-                       tmp = (float)fabs( ans[k] );
-                       if ( tmp > maxdev ) {
-                               maxdev = tmp;
-                       }
-                       avedev += tmp;
-                       numave++;
-               }
-       }
-       avedev /= (float)numave;
-       printf( "%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev );
-       printf( "%d bytes original size\n",MatWidth * nFrames );
-       printf( "%d bytes of overhead\n",MatWidth * MatHeight );
-       printf( "%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize * nFrames );
-       compression = (float)( MatWidth * MatHeight + CFrameSize * nFrames + MatWidth );
-       compression /= (float)( MatWidth * nFrames );
-       printf( "Overall compression = %f %%\n",100.0f - 100.0f * compression );
-       compression = (float)( CFrameSize );
-       compression /= (float)( MatWidth );
-       printf( "frame size compression = %f %%\n",100.0f - 100.0f * compression );
-       free( rescale );
-       free( ans );
-}
-
-void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax ){
-       int k,l,nv,j;
-       float maxdev;
-       float avedev;
-       float tmp;
-       int numave;
-       float t,mx;
-       float *ans;
-
-
-       nv = MatWidth / 3;
-
-       trans[0] = 1E30f;
-       scale[0] = -1E30f;
-       trans[1] = 1E30f;
-       scale[1] = -1E30f;
-       trans[2] = 1E30f;
-       scale[2] = -1E30f;
-       for ( k = 0; k < MatWidth; k += 3 )
-       {
-               if ( base[k] > scale[0] ) {
-                       scale[0] = base[k];
-               }
-               if ( base[k] < trans[0] ) {
-                       trans[0] = base[k];
-               }
-
-               if ( base[k + 1] > scale[1] ) {
-                       scale[1] = base[k + 1];
-               }
-               if ( base[k + 1] < trans[1] ) {
-                       trans[1] = base[k + 1];
-               }
-
-               if ( base[k + 2] > scale[2] ) {
-                       scale[2] = base[k + 2];
-               }
-               if ( base[k + 2] < trans[2] ) {
-                       trans[2] = base[k + 2];
-               }
-       }
-
-       scale[0] -= trans[0];
-       scale[1] -= trans[1];
-       scale[2] -= trans[2];
-       scale[0] /= 255.0f;
-       scale[1] /= 255.0f;
-       scale[2] /= 255.0f;
-       for ( k = 0; k < MatWidth; k += 3 )
-       {
-               t = ( base[k] - trans[0] ) / scale[0];
-               if ( t < 0.0f ) {
-                       t = 0.0f;
-               }
-               if ( t > 255.0f ) {
-                       t = 255.0f;
-               }
-               cbase[k] = (unsigned char)t;
-
-               t = ( base[k + 1] - trans[1] ) / scale[1];
-               if ( t < 0.0f ) {
-                       t = 0.0f;
-               }
-               if ( t > 255.0f ) {
-                       t = 255.0f;
-               }
-               cbase[k + 1] = (unsigned char)t;
-
-               t = ( base[k + 2] - trans[2] ) / scale[2];
-               if ( t < 0.0f ) {
-                       t = 0.0f;
-               }
-               if ( t > 255.0f ) {
-                       t = 255.0f;
-               }
-               cbase[k + 2] = (unsigned char)t;
-       }
-       for ( l = 0; l < MatHeight; l++ )
-       {
-               mx = 0.0;
-               for ( k = 0; k < MatWidth; k++ )
-               {
-                       if ( fabs( best[l * MatWidth + k] ) > mx ) {
-                               mx = (float)fabs( best[l * MatWidth + k] );
-                       }
-               }
-               if ( mx > 1E-8 ) {
-                       mx /= 127.0f;
-                       coffset[l] = 1E30f;
-                       cscale[l] = -1E30f;
-                       for ( j = 0; j < nFrames; j++ )
-                       {
-                               bestcomp[j * MatHeight + l] *= mx;
-                               if ( bestcomp[j * MatHeight + l] > cscale[l] ) {
-                                       cscale[l] = bestcomp[j * MatHeight + l];
-                               }
-                               if ( bestcomp[j * MatHeight + l] < coffset[l] ) {
-                                       coffset[l] = bestcomp[j * MatHeight + l];
-                               }
-                       }
-                       cscale[l] -= coffset[l];
-                       if ( cscale[l] > 1E-10 ) {
-                               for ( j = 0; j < nFrames; j++ )
-                               {
-                                       tmp = 254.0f * ( bestcomp[j * MatHeight + l] - coffset[l] ) / cscale[l] - 127.0f;
-                                       if ( tmp > 127.0f ) {
-                                               tmp = 127.0f;
-                                       }
-                                       if ( tmp < -127.0f ) {
-                                               tmp = -127.0f;
-                                       }
-                                       ccomp[j * MatHeight + l] = (char)floor( tmp + 0.5 );
-                               }
-                               coffset[l] += cscale[l] * 127.0f / 254.0f;
-                               cscale[l] /= 254.0f;
-                       }
-                       else
-                       {
-                               cscale[l] = 1.0f;
-                               coffset[l] = 0.0f;
-                               for ( j = 0; j < nFrames; j++ )
-                                       ccomp[j * MatHeight + l] = 0;
-                       }
-                       mx = 1.0f / mx;
-                       for ( k = 0; k < MatWidth; k++ )
-                       {
-                               tmp = best[l * MatWidth + k] * mx;
-                               if ( tmp > 127.0f ) {
-                                       tmp = 127.0f;
-                               }
-                               if ( tmp < -127.0f ) {
-                                       tmp = -127.0f;
-                               }
-                               mat[k * MatHeight + l] = (char)floor( tmp + 0.5 );
-                       }
-               }
-               else
-               {
-                       cscale[l] = 1.0f;
-                       coffset[l] = 0.0f;
-                       for ( j = 0; j < nFrames; j++ )
-                               ccomp[j * MatHeight + l] = 0;
-                       for ( k = 0; k < MatWidth; k++ )
-                               mat[k * MatHeight + l] = 0;
-               }
-       }
-       bmin[0] = 1E30f;
-       bmin[1] = 1E30f;
-       bmin[2] = 1E30f;
-       bmax[0] = -1E30f;
-       bmax[1] = -1E30f;
-       bmax[2] = -1E30f;
-       numave = 0;
-       avedev = 0.0;
-       maxdev = 0.0;
-       ans = (float *)SafeMalloc( sizeof( float ) * MatWidth, "AnimCompressToBytes" );
-       for ( j = 0; j < nFrames; j++ )
-       {
-               for ( k = 0; k < MatWidth; k++ )
-               {
-                       ans[k] = 0.0;
-                       for ( l = 0; l < CFrameSize; l++ )
-                               ans[k] += (float)( mat[l + k * MatHeight] ) * ( (float)( ccomp[j * CFrameSize + l] ) * cscale[l] + coffset[l] );
-                       ans[k] += (float)( cbase[k] ) * scale[k % 3] + trans[k % 3];
-                       tmp = (float)fabs( ans[k] - frames[j * MatWidth + k] - base[k] );
-                       if ( tmp > maxdev ) {
-                               maxdev = tmp;
-                       }
-                       avedev += tmp;
-                       numave++;
-
-                       if ( bmin[k % 3] > ans[k] ) {
-                               bmin[k % 3] = ans[k];
-                       }
-                       if ( bmax[k % 3] < ans[k] ) {
-                               bmax[k % 3] = ans[k];
-                       }
-               }
-       }
-       avedev /= (float)numave;
-       printf( "%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev );
-       free( ans );
-}
-
-void AnimCompressGetMatrix( float *mat ){
-       int k,l;
-       for ( k = 0; k < MatWidth; k++ )
-               for ( l = 0; l < MatHeight; l++ )
-                       mat[k * MatHeight + l] = best[l * MatWidth + k];
-}
-
-void AnimCompressGetFrames( float *mat ){
-       memcpy( mat,bestcomp,CFrameSize * nFrames * sizeof( float ) );
-}
-
-void AnimCompressGetBase( int i,float *x,float *y,float *z ){
-       *x = base[i * 3];
-       *y = base[i * 3 + 1];
-       *z = base[i * 3 + 2];
-}
-
-void AnimCompressEnd(){
-       free( matrix );
-       free( best );
-       free( delta );
-       free( comp );
-       free( tcomp );
-       free( bestcomp );
-       free( base );
-       free( frames );
-}
diff --git a/tools/quake2/qdata_heretic2/animcomp.h b/tools/quake2/qdata_heretic2/animcomp.h
deleted file mode 100644 (file)
index 36ea3b1..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#if !defined( ANIMCOMP_INC )
-#define ANIMCOMP_INC
-
-#ifdef  __cplusplus
-extern "C"
-{
-#endif
-void AnimCompressInit( int nFrames,int nVerts,int CompressedFrameSize );
-void AnimSetFrame( int frame,int index,float x,float y,float z );
-void AnimCompressDoit();
-void AnimCompressToBytes( float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax );
-void AnimCompressGetMatrix( float *mat );
-void AnimCompressGetFrames( float *mat );
-void AnimCompressGetBase( int i,float *x,float *y,float *z );
-void AnimCompressEnd();
-void DOsvdPlane( float *pnts,int npnts,float *n,float *base );
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/anorms.h b/tools/quake2/qdata_heretic2/anorms.h
deleted file mode 100644 (file)
index 65e92ef..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-{-0.525731f, 0.000000f, 0.850651f},
-{-0.442863f, 0.238856f, 0.864188f},
-{-0.295242f, 0.000000f, 0.955423f},
-{-0.309017f, 0.500000f, 0.809017f},
-{-0.162460f, 0.262866f, 0.951056f},
-{0.000000f, 0.000000f, 1.000000f},
-{0.000000f, 0.850651f, 0.525731f},
-{-0.147621f, 0.716567f, 0.681718f},
-{0.147621f, 0.716567f, 0.681718f},
-{0.000000f, 0.525731f, 0.850651f},
-{0.309017f, 0.500000f, 0.809017f},
-{0.525731f, 0.000000f, 0.850651f},
-{0.295242f, 0.000000f, 0.955423f},
-{0.442863f, 0.238856f, 0.864188f},
-{0.162460f, 0.262866f, 0.951056f},
-{-0.681718f, 0.147621f, 0.716567f},
-{-0.809017f, 0.309017f, 0.500000f},
-{-0.587785f, 0.425325f, 0.688191f},
-{-0.850651f, 0.525731f, 0.000000f},
-{-0.864188f, 0.442863f, 0.238856f},
-{-0.716567f, 0.681718f, 0.147621f},
-{-0.688191f, 0.587785f, 0.425325f},
-{-0.500000f, 0.809017f, 0.309017f},
-{-0.238856f, 0.864188f, 0.442863f},
-{-0.425325f, 0.688191f, 0.587785f},
-{-0.716567f, 0.681718f, -0.147621f},
-{-0.500000f, 0.809017f, -0.309017f},
-{-0.525731f, 0.850651f, 0.000000f},
-{0.000000f, 0.850651f, -0.525731f},
-{-0.238856f, 0.864188f, -0.442863f},
-{0.000000f, 0.955423f, -0.295242f},
-{-0.262866f, 0.951056f, -0.162460f},
-{0.000000f, 1.000000f, 0.000000f},
-{0.000000f, 0.955423f, 0.295242f},
-{-0.262866f, 0.951056f, 0.162460f},
-{0.238856f, 0.864188f, 0.442863f},
-{0.262866f, 0.951056f, 0.162460f},
-{0.500000f, 0.809017f, 0.309017f},
-{0.238856f, 0.864188f, -0.442863f},
-{0.262866f, 0.951056f, -0.162460f},
-{0.500000f, 0.809017f, -0.309017f},
-{0.850651f, 0.525731f, 0.000000f},
-{0.716567f, 0.681718f, 0.147621f},
-{0.716567f, 0.681718f, -0.147621f},
-{0.525731f, 0.850651f, 0.000000f},
-{0.425325f, 0.688191f, 0.587785f},
-{0.864188f, 0.442863f, 0.238856f},
-{0.688191f, 0.587785f, 0.425325f},
-{0.809017f, 0.309017f, 0.500000f},
-{0.681718f, 0.147621f, 0.716567f},
-{0.587785f, 0.425325f, 0.688191f},
-{0.955423f, 0.295242f, 0.000000f},
-{1.000000f, 0.000000f, 0.000000f},
-{0.951056f, 0.162460f, 0.262866f},
-{0.850651f, -0.525731f, 0.000000f},
-{0.955423f, -0.295242f, 0.000000f},
-{0.864188f, -0.442863f, 0.238856f},
-{0.951056f, -0.162460f, 0.262866f},
-{0.809017f, -0.309017f, 0.500000f},
-{0.681718f, -0.147621f, 0.716567f},
-{0.850651f, 0.000000f, 0.525731f},
-{0.864188f, 0.442863f, -0.238856f},
-{0.809017f, 0.309017f, -0.500000f},
-{0.951056f, 0.162460f, -0.262866f},
-{0.525731f, 0.000000f, -0.850651f},
-{0.681718f, 0.147621f, -0.716567f},
-{0.681718f, -0.147621f, -0.716567f},
-{0.850651f, 0.000000f, -0.525731f},
-{0.809017f, -0.309017f, -0.500000f},
-{0.864188f, -0.442863f, -0.238856f},
-{0.951056f, -0.162460f, -0.262866f},
-{0.147621f, 0.716567f, -0.681718f},
-{0.309017f, 0.500000f, -0.809017f},
-{0.425325f, 0.688191f, -0.587785f},
-{0.442863f, 0.238856f, -0.864188f},
-{0.587785f, 0.425325f, -0.688191f},
-{0.688191f, 0.587785f, -0.425325f},
-{-0.147621f, 0.716567f, -0.681718f},
-{-0.309017f, 0.500000f, -0.809017f},
-{0.000000f, 0.525731f, -0.850651f},
-{-0.525731f, 0.000000f, -0.850651f},
-{-0.442863f, 0.238856f, -0.864188f},
-{-0.295242f, 0.000000f, -0.955423f},
-{-0.162460f, 0.262866f, -0.951056f},
-{0.000000f, 0.000000f, -1.000000f},
-{0.295242f, 0.000000f, -0.955423f},
-{0.162460f, 0.262866f, -0.951056f},
-{-0.442863f, -0.238856f, -0.864188f},
-{-0.309017f, -0.500000f, -0.809017f},
-{-0.162460f, -0.262866f, -0.951056f},
-{0.000000f, -0.850651f, -0.525731f},
-{-0.147621f, -0.716567f, -0.681718f},
-{0.147621f, -0.716567f, -0.681718f},
-{0.000000f, -0.525731f, -0.850651f},
-{0.309017f, -0.500000f, -0.809017f},
-{0.442863f, -0.238856f, -0.864188f},
-{0.162460f, -0.262866f, -0.951056f},
-{0.238856f, -0.864188f, -0.442863f},
-{0.500000f, -0.809017f, -0.309017f},
-{0.425325f, -0.688191f, -0.587785f},
-{0.716567f, -0.681718f, -0.147621f},
-{0.688191f, -0.587785f, -0.425325f},
-{0.587785f, -0.425325f, -0.688191f},
-{0.000000f, -0.955423f, -0.295242f},
-{0.000000f, -1.000000f, 0.000000f},
-{0.262866f, -0.951056f, -0.162460f},
-{0.000000f, -0.850651f, 0.525731f},
-{0.000000f, -0.955423f, 0.295242f},
-{0.238856f, -0.864188f, 0.442863f},
-{0.262866f, -0.951056f, 0.162460f},
-{0.500000f, -0.809017f, 0.309017f},
-{0.716567f, -0.681718f, 0.147621f},
-{0.525731f, -0.850651f, 0.000000f},
-{-0.238856f, -0.864188f, -0.442863f},
-{-0.500000f, -0.809017f, -0.309017f},
-{-0.262866f, -0.951056f, -0.162460f},
-{-0.850651f, -0.525731f, 0.000000f},
-{-0.716567f, -0.681718f, -0.147621f},
-{-0.716567f, -0.681718f, 0.147621f},
-{-0.525731f, -0.850651f, 0.000000f},
-{-0.500000f, -0.809017f, 0.309017f},
-{-0.238856f, -0.864188f, 0.442863f},
-{-0.262866f, -0.951056f, 0.162460f},
-{-0.864188f, -0.442863f, 0.238856f},
-{-0.809017f, -0.309017f, 0.500000f},
-{-0.688191f, -0.587785f, 0.425325f},
-{-0.681718f, -0.147621f, 0.716567f},
-{-0.442863f, -0.238856f, 0.864188f},
-{-0.587785f, -0.425325f, 0.688191f},
-{-0.309017f, -0.500000f, 0.809017f},
-{-0.147621f, -0.716567f, 0.681718f},
-{-0.425325f, -0.688191f, 0.587785f},
-{-0.162460f, -0.262866f, 0.951056f},
-{0.442863f, -0.238856f, 0.864188f},
-{0.162460f, -0.262866f, 0.951056f},
-{0.309017f, -0.500000f, 0.809017f},
-{0.147621f, -0.716567f, 0.681718f},
-{0.000000f, -0.525731f, 0.850651f},
-{0.425325f, -0.688191f, 0.587785f},
-{0.587785f, -0.425325f, 0.688191f},
-{0.688191f, -0.587785f, 0.425325f},
-{-0.955423f, 0.295242f, 0.000000f},
-{-0.951056f, 0.162460f, 0.262866f},
-{-1.000000f, 0.000000f, 0.000000f},
-{-0.850651f, 0.000000f, 0.525731f},
-{-0.955423f, -0.295242f, 0.000000f},
-{-0.951056f, -0.162460f, 0.262866f},
-{-0.864188f, 0.442863f, -0.238856f},
-{-0.951056f, 0.162460f, -0.262866f},
-{-0.809017f, 0.309017f, -0.500000f},
-{-0.864188f, -0.442863f, -0.238856f},
-{-0.951056f, -0.162460f, -0.262866f},
-{-0.809017f, -0.309017f, -0.500000f},
-{-0.681718f, 0.147621f, -0.716567f},
-{-0.681718f, -0.147621f, -0.716567f},
-{-0.850651f, 0.000000f, -0.525731f},
-{-0.688191f, 0.587785f, -0.425325f},
-{-0.587785f, 0.425325f, -0.688191f},
-{-0.425325f, 0.688191f, -0.587785f},
-{-0.425325f, -0.688191f, -0.587785f},
-{-0.587785f, -0.425325f, -0.688191f},
-{-0.688191f, -0.587785f, -0.425325f},
diff --git a/tools/quake2/qdata_heretic2/book.c b/tools/quake2/qdata_heretic2/book.c
deleted file mode 100644 (file)
index 412aefe..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "qdata.h"
-
-byte            *byteimage, *lbmpalette;
-int byteimagewidth, byteimageheight;
-
-qboolean TrueColorImage;
-int longimagewidth, longimageheight;
-
-char book_prefix[1024];
-byte buffer[640 * 480];
-unsigned long bufferl[640 * 480];
-
-miptex_t *CreateBook8( byte *buffer, int w, int h, byte *palette, int *FinalSize ){
-       miptex_t    *mp;
-       int i, j;
-       byte        *pos;
-       int size;
-
-       size = sizeof( *mp ) + ( w * h );
-       mp = (miptex_t *)SafeMalloc( size, "CreateBook8" );
-       memset( mp, 0, size );
-
-       mp->version = MIP_VERSION;
-
-       for ( i = j = 0; i < 256; i++,j += 3 )
-       {
-               mp->palette[i].r = palette[j];
-               mp->palette[i].g = palette[j + 1];
-               mp->palette[i].b = palette[j + 2];
-       }
-       pos = (byte *)( mp + 1 );
-
-       mp->width[0] = w;
-       mp->height[0] = h;
-       mp->offsets[0] = sizeof( *mp );
-       memcpy( pos, buffer, w * h );
-
-       *FinalSize = size;
-       return( mp );
-}
-
-miptex32_t *CreateBook32( long *buffer, int w, int h, int *FinalSize ){
-       miptex32_t  *mp;
-       byte        *pos;
-       int size;
-
-       size = sizeof( *mp ) + ( w * h * 4 );
-       mp = (miptex32_t *)SafeMalloc( size, "CreateBook32" );
-       memset( mp, 0, size );
-
-       mp->version = MIP32_VERSION;
-
-       pos = (byte *)( mp + 1 );
-
-       mp->width[0] = w;
-       mp->height[0] = h;
-       mp->offsets[0] = sizeof( *mp );
-       memcpy( pos, buffer, w * h * 4 );
-
-       *FinalSize = size;
-       return( mp );
-}
-
-
-// Routines to chop a random sized image into gl texture friendly chunks
-
-typedef struct rect_s
-{
-       int x, y;
-       int w, h;
-       char name[4];
-} rect_t;
-
-int GetCoords( int x, int store[MAX_MD2SKINS] ){
-       int index, start, delta;
-
-       index = 0;
-       start = 0;
-       delta = 256;
-
-       store[index++] = start;
-       while ( x )
-       {
-               if ( x >= delta ) {
-                       start += delta;
-                       store[index++] = start;
-                       x -= delta;
-               }
-               else
-               {
-                       delta >>= 1;
-               }
-       }
-       return( index );
-}
-
-int ChopImage( int w, int h, rect_t coords[MAX_MD2SKINS] ){
-       int xs[MAX_MD2SKINS], ys[MAX_MD2SKINS];
-       int xcount, ycount, x, y, index;
-
-       index = 0;
-       xcount = GetCoords( w, xs ) - 1;
-       ycount = GetCoords( h, ys ) - 1;
-
-       for ( y = 0; y < ycount; y++ )
-       {
-               for ( x = 0; x < xcount; x++, index++ )
-               {
-                       coords[index].x = xs[x];
-                       coords[index].y = ys[y];
-                       coords[index].w = xs[x + 1] - xs[x];
-                       coords[index].h = ys[y + 1] - ys[y];
-                       coords[index].name[0] = x + '0';
-                       coords[index].name[1] = y + '0';
-                       coords[index].name[2] = 0;
-               }
-       }
-       return( index );
-}
-
-/*
-   ===============
-   Cmd_Pic
-   ===============
- */
-
-void Cmd_Book(){
-       int xl,yl,xh,yh,w,h;
-       byte            *dest, *source;
-       int flags, value, contents;
-       char lumpname[64];
-       char filename[1024];
-       unsigned long   *destl, *sourcel;
-       int linedelta, x, y;
-       int size;
-       miptex_t        *qtex;
-       miptex32_t      *qtex32;
-       float scale_x, scale_y;
-       int numrects, i;
-       rect_t coords[MAX_MD2SKINS];
-       bookframe_t bframes[MAX_MD2SKINS];
-       bookframe_t     *bf;
-       book_t book;
-
-       GetScriptToken( false );
-       strcpy( lumpname, token );
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       total_x += w;
-       total_y += h;
-       total_textures++;
-
-       if ( ( w & 7 ) || ( h & 7 ) ) {
-               Error( "line %i: miptex sizes must be multiples of 8", scriptline );
-       }
-
-       flags = 0;
-       contents = 0;
-       value = 0;
-
-       scale_x = scale_y = 0.5;
-
-       if ( g_release ) {
-               return;
-       }
-
-       if ( TrueColorImage ) {
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= longimagewidth || xh > longimagewidth ||
-                        yl >= longimageheight || yh > longimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
-               }
-
-               sourcel = (unsigned long *) longimage + ( yl * longimagewidth ) + xl;
-               destl = (unsigned long *) longimage;
-               linedelta = ( longimagewidth - w );
-
-               for ( y = yl; y < yh; y++ )
-               {
-                       for ( x = xl; x < xh; x++ )
-                       {
-                               *destl++ = *sourcel++;  // RGBA
-                       }
-                       sourcel += linedelta;
-               }
-
-               // Get rectangles to chop into
-               numrects = ChopImage( w, h, coords );
-
-               bf = bframes;
-               for ( i = 0; i < numrects; i++, bf++ )
-               {
-                       // Copy section of image to buffer
-                       sourcel = (unsigned long *) longimage + ( coords[i].y * w ) + coords[i].x;
-                       destl = bufferl;
-                       linedelta = w - coords[i].w;
-
-                       for ( y = 0; y < coords[i].h; y++ )
-                       {
-                               for ( x = 0; x < coords[i].w; x++ )
-                               {
-                                       *destl++ = *sourcel++;
-                               }
-                               sourcel += linedelta;
-                       }
-
-                       qtex32 = CreateBook32( bufferl, coords[i].w, coords[i].h, &size );
-
-                       qtex32->flags = flags;
-                       qtex32->contents = contents;
-                       qtex32->value = value;
-                       qtex32->scale_x = scale_x;
-                       qtex32->scale_y = scale_y;
-
-                       sprintf( filename, "%sbook/%s/%s_%s.m32", gamedir, book_prefix, lumpname, coords[i].name );
-                       sprintf( qtex32->name, "%s/%s_%s.m32", book_prefix, lumpname, coords[i].name );
-
-                       strcpy( bf->name, qtex32->name );
-                       bf->x = coords[i].x;
-                       bf->y = coords[i].y;
-                       bf->w = coords[i].w;
-                       bf->h = coords[i].h;
-                       //
-                       // write it out
-                       //
-                       printf( "writing %s\n", filename );
-                       SaveFile( filename, (byte *)qtex32, size );
-
-                       free( qtex32 );
-               }
-       }
-       else
-       {
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= byteimagewidth || xh > byteimagewidth ||
-                        yl >= byteimageheight || yh > byteimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
-               }
-
-               // Copy image to top left
-               source = byteimage + yl * byteimagewidth + xl;
-               dest = byteimage;
-               linedelta = byteimagewidth - w;
-
-               for ( y = yl; y < yh; y++ )
-               {
-                       for ( x = xl; x < xh; x++ )
-                       {
-                               *dest++ = *source++;
-                       }
-                       source += linedelta;
-               }
-
-               // Get rectangles to chop into
-               numrects = ChopImage( w, h, coords );
-
-               bf = bframes;
-               for ( i = 0; i < numrects; i++, bf++ )
-               {
-                       // Copy section of image to buffer
-                       source = byteimage + ( coords[i].y * w ) + coords[i].x;
-                       dest = buffer;
-                       linedelta = w - coords[i].w;
-
-                       for ( y = 0; y < coords[i].h; y++ )
-                       {
-                               for ( x = 0; x < coords[i].w; x++ )
-                               {
-                                       *dest++ = *source++;
-                               }
-                               source += linedelta;
-                       }
-
-                       qtex = CreateBook8( buffer, coords[i].w, coords[i].h, lbmpalette, &size );
-
-                       qtex->flags = flags;
-                       qtex->contents = contents;
-                       qtex->value = value;
-
-                       sprintf( filename, "%sbook/%s/%s_%s.m8", gamedir, book_prefix, lumpname, coords[i].name );
-                       sprintf( qtex->name, "%s/%s_%s.m8", book_prefix, lumpname, coords[i].name );
-
-                       strcpy( bf->name, qtex->name );
-                       bf->x = coords[i].x;
-                       bf->y = coords[i].y;
-                       bf->w = coords[i].w;
-                       bf->h = coords[i].h;
-                       //
-                       // write it out
-                       //
-                       printf( "writing %s\n", filename );
-                       SaveFile( filename, (byte *)qtex, size );
-
-                       free( qtex );
-               }
-       }
-       // Set up descriptor
-       size = sizeof( bookframe_t ) * numrects;
-
-       book.bheader.ident = IDBOOKHEADER;
-       book.bheader.version = BOOK_VERSION;
-       book.bheader.num_segments = numrects;
-       book.bheader.total_w = w;
-       book.bheader.total_h = h;
-       memcpy( book.bframes, bframes, size );
-
-       // Save out segment descriptor
-       sprintf( filename, "%sBook/%s/%s.bk", gamedir, book_prefix, lumpname );
-       printf( "writing %s\n", filename );
-       SaveFile( filename, (byte *)&book, size + sizeof( bookheader_t ) );
-}
-
-/*
-   ===============
-   Cmd_picdir
-   ===============
- */
-void Cmd_Bookdir( void ){
-       char filename[1024];
-
-       GetScriptToken( false );
-       strcpy( book_prefix, token );
-       // create the directory if needed
-       sprintf( filename, "%sBook", gamedir );
-       Q_mkdir( filename );
-       sprintf( filename, "%sBook/%s", gamedir, book_prefix );
-       Q_mkdir( filename );
-}
-
-// end
diff --git a/tools/quake2/qdata_heretic2/common/bspfile.c b/tools/quake2/qdata_heretic2/common/bspfile.c
deleted file mode 100644 (file)
index add0ef3..0000000
+++ /dev/null
@@ -1,793 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "bspfile.h"
-#include "scriplib.h"
-
-void GetLeafNums( void );
-
-//=============================================================================
-
-int nummodels;
-dmodel_t dmodels[MAX_MAP_MODELS];
-
-int visdatasize;
-byte dvisdata[MAX_MAP_VISIBILITY];
-dvis_t      *dvis = (dvis_t *)dvisdata;
-
-int lightdatasize;
-byte dlightdata[MAX_MAP_LIGHTING];
-
-int entdatasize;
-char dentdata[MAX_MAP_ENTSTRING];
-
-int numleafs;
-dleaf_t dleafs[MAX_MAP_LEAFS];
-
-int numplanes;
-dplane_t dplanes[MAX_MAP_PLANES];
-
-int numvertexes;
-dvertex_t dvertexes[MAX_MAP_VERTS];
-
-int numnodes;
-dnode_t dnodes[MAX_MAP_NODES];
-
-int numtexinfo;
-texinfo_t texinfo[MAX_MAP_TEXINFO];
-
-int numfaces;
-dface_t dfaces[MAX_MAP_FACES];
-
-int numedges;
-dedge_t dedges[MAX_MAP_EDGES];
-
-int numleaffaces;
-unsigned short dleaffaces[MAX_MAP_LEAFFACES];
-
-int numleafbrushes;
-unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-int numsurfedges;
-int dsurfedges[MAX_MAP_SURFEDGES];
-
-int numbrushes;
-dbrush_t dbrushes[MAX_MAP_BRUSHES];
-
-int numbrushsides;
-dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
-
-int numareas;
-darea_t dareas[MAX_MAP_AREAS];
-
-int numareaportals;
-dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
-
-byte dpop[256];
-
-/*
-   ===============
-   CompressVis
-
-   ===============
- */
-int CompressVis( byte *vis, byte *dest ){
-       int j;
-       int rep;
-       int visrow;
-       byte    *dest_p;
-
-       dest_p = dest;
-//     visrow = (r_numvisleafs + 7)>>3;
-       visrow = ( dvis->numclusters + 7 ) >> 3;
-
-       for ( j = 0 ; j < visrow ; j++ )
-       {
-               *dest_p++ = vis[j];
-               if ( vis[j] ) {
-                       continue;
-               }
-
-               rep = 1;
-               for ( j++; j < visrow ; j++ )
-                       if ( vis[j] || rep == 255 ) {
-                               break;
-                       }
-                       else{
-                               rep++;
-                       }
-               *dest_p++ = rep;
-               j--;
-       }
-
-       return dest_p - dest;
-}
-
-
-/*
-   ===================
-   DecompressVis
-   ===================
- */
-void DecompressVis( byte *in, byte *decompressed ){
-       int c;
-       byte    *out;
-       int row;
-
-//     row = (r_numvisleafs+7)>>3;
-       row = ( dvis->numclusters + 7 ) >> 3;
-       out = decompressed;
-
-       do
-       {
-               if ( *in ) {
-                       *out++ = *in++;
-                       continue;
-               }
-
-               c = in[1];
-               if ( !c ) {
-                       Error( "DecompressVis: 0 repeat" );
-               }
-               in += 2;
-               while ( c )
-               {
-                       *out++ = 0;
-                       c--;
-               }
-       } while ( out - decompressed < row );
-}
-
-//=============================================================================
-
-/*
-   =============
-   SwapBSPFile
-
-   Byte swaps all data in a bsp file.
-   =============
- */
-void SwapBSPFile( qboolean todisk ){
-       int i, j;
-       dmodel_t        *d;
-
-
-// models
-       for ( i = 0 ; i < nummodels ; i++ )
-       {
-               d = &dmodels[i];
-
-               d->firstface = LittleLong( d->firstface );
-               d->numfaces = LittleLong( d->numfaces );
-               d->headnode = LittleLong( d->headnode );
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       d->mins[j] = LittleFloat( d->mins[j] );
-                       d->maxs[j] = LittleFloat( d->maxs[j] );
-                       d->origin[j] = LittleFloat( d->origin[j] );
-               }
-       }
-
-//
-// vertexes
-//
-       for ( i = 0 ; i < numvertexes ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-                       dvertexes[i].point[j] = LittleFloat( dvertexes[i].point[j] );
-       }
-
-//
-// planes
-//
-       for ( i = 0 ; i < numplanes ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-                       dplanes[i].normal[j] = LittleFloat( dplanes[i].normal[j] );
-               dplanes[i].dist = LittleFloat( dplanes[i].dist );
-               dplanes[i].type = LittleLong( dplanes[i].type );
-       }
-
-//
-// texinfos
-//
-       for ( i = 0 ; i < numtexinfo ; i++ )
-       {
-               for ( j = 0 ; j < 8 ; j++ )
-                       texinfo[i].vecs[0][j] = LittleFloat( texinfo[i].vecs[0][j] );
-               texinfo[i].flags = LittleLong( texinfo[i].flags );
-               texinfo[i].value = LittleLong( texinfo[i].value );
-               texinfo[i].nexttexinfo = LittleLong( texinfo[i].nexttexinfo );
-       }
-
-//
-// faces
-//
-       for ( i = 0 ; i < numfaces ; i++ )
-       {
-               dfaces[i].texinfo = LittleShort( dfaces[i].texinfo );
-               dfaces[i].planenum = LittleShort( dfaces[i].planenum );
-               dfaces[i].side = LittleShort( dfaces[i].side );
-               dfaces[i].lighting.c = LittleLong( dfaces[i].lighting.c );
-               dfaces[i].lightofs = LittleLong( dfaces[i].lightofs );
-               dfaces[i].firstedge = LittleLong( dfaces[i].firstedge );
-               dfaces[i].numedges = LittleShort( dfaces[i].numedges );
-       }
-
-//
-// nodes
-//
-       for ( i = 0 ; i < numnodes ; i++ )
-       {
-               dnodes[i].planenum = LittleLong( dnodes[i].planenum );
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       dnodes[i].mins[j] = LittleShort( dnodes[i].mins[j] );
-                       dnodes[i].maxs[j] = LittleShort( dnodes[i].maxs[j] );
-               }
-               dnodes[i].children[0] = LittleLong( dnodes[i].children[0] );
-               dnodes[i].children[1] = LittleLong( dnodes[i].children[1] );
-               dnodes[i].firstface = LittleShort( dnodes[i].firstface );
-               dnodes[i].numfaces = LittleShort( dnodes[i].numfaces );
-       }
-
-//
-// leafs
-//
-       for ( i = 0 ; i < numleafs ; i++ )
-       {
-               dleafs[i].contents = LittleLong( dleafs[i].contents );
-               dleafs[i].cluster = LittleShort( dleafs[i].cluster );
-               dleafs[i].area = LittleShort( dleafs[i].area );
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       dleafs[i].mins[j] = LittleShort( dleafs[i].mins[j] );
-                       dleafs[i].maxs[j] = LittleShort( dleafs[i].maxs[j] );
-               }
-
-               dleafs[i].firstleafface = LittleShort( dleafs[i].firstleafface );
-               dleafs[i].numleaffaces = LittleShort( dleafs[i].numleaffaces );
-               dleafs[i].firstleafbrush = LittleShort( dleafs[i].firstleafbrush );
-               dleafs[i].numleafbrushes = LittleShort( dleafs[i].numleafbrushes );
-       }
-
-//
-// leaffaces
-//
-       for ( i = 0 ; i < numleaffaces ; i++ )
-               dleaffaces[i] = LittleShort( dleaffaces[i] );
-
-//
-// leafbrushes
-//
-       for ( i = 0 ; i < numleafbrushes ; i++ )
-               dleafbrushes[i] = LittleShort( dleafbrushes[i] );
-
-//
-// surfedges
-//
-       for ( i = 0 ; i < numsurfedges ; i++ )
-               dsurfedges[i] = LittleLong( dsurfedges[i] );
-
-//
-// edges
-//
-       for ( i = 0 ; i < numedges ; i++ )
-       {
-               dedges[i].v[0] = LittleShort( dedges[i].v[0] );
-               dedges[i].v[1] = LittleShort( dedges[i].v[1] );
-       }
-
-//
-// brushes
-//
-       for ( i = 0 ; i < numbrushes ; i++ )
-       {
-               dbrushes[i].firstside = LittleLong( dbrushes[i].firstside );
-               dbrushes[i].numsides = LittleLong( dbrushes[i].numsides );
-               dbrushes[i].contents = LittleLong( dbrushes[i].contents );
-       }
-
-//
-// areas
-//
-       for ( i = 0 ; i < numareas ; i++ )
-       {
-               dareas[i].numareaportals = LittleLong( dareas[i].numareaportals );
-               dareas[i].firstareaportal = LittleLong( dareas[i].firstareaportal );
-       }
-
-//
-// areasportals
-//
-       for ( i = 0 ; i < numareaportals ; i++ )
-       {
-               dareaportals[i].portalnum = LittleLong( dareaportals[i].portalnum );
-               dareaportals[i].otherarea = LittleLong( dareaportals[i].otherarea );
-       }
-
-//
-// brushsides
-//
-       for ( i = 0 ; i < numbrushsides ; i++ )
-       {
-               dbrushsides[i].planenum = LittleShort( dbrushsides[i].planenum );
-               dbrushsides[i].texinfo = LittleShort( dbrushsides[i].texinfo );
-       }
-
-//
-// visibility
-//
-       if ( todisk ) {
-               j = dvis->numclusters;
-       }
-       else{
-               j = LittleLong( dvis->numclusters );
-       }
-       dvis->numclusters = LittleLong( dvis->numclusters );
-       for ( i = 0 ; i < j ; i++ )
-       {
-               dvis->bitofs[i][0] = LittleLong( dvis->bitofs[i][0] );
-               dvis->bitofs[i][1] = LittleLong( dvis->bitofs[i][1] );
-       }
-}
-
-
-dheader_t   *header;
-
-int CopyLump( int lump, void *dest, int size ){
-       int length, ofs;
-
-       length = header->lumps[lump].filelen;
-       ofs = header->lumps[lump].fileofs;
-
-       if ( length % size ) {
-               Error( "LoadBSPFile: odd lump size" );
-       }
-
-       memcpy( dest, (byte *)header + ofs, length );
-
-       return length / size;
-}
-
-/*
-   =============
-   LoadBSPFile
-   =============
- */
-void    LoadBSPFile( char *filename ){
-       int i;
-
-//
-// load the file header
-//
-       LoadFile( filename, (void **)&header );
-
-// swap the header
-       for ( i = 0 ; i < sizeof( dheader_t ) / 4 ; i++ )
-               ( (int *)header )[i] = LittleLong( ( (int *)header )[i] );
-
-       if ( header->ident != IDBSPHEADER ) {
-               Error( "%s is not a IBSP file", filename );
-       }
-       if ( header->version != BSPVERSION ) {
-               Error( "%s is version %i, not %i", filename, header->version, BSPVERSION );
-       }
-
-       nummodels = CopyLump( LUMP_MODELS, dmodels, sizeof( dmodel_t ) );
-       numvertexes = CopyLump( LUMP_VERTEXES, dvertexes, sizeof( dvertex_t ) );
-       numplanes = CopyLump( LUMP_PLANES, dplanes, sizeof( dplane_t ) );
-       numleafs = CopyLump( LUMP_LEAFS, dleafs, sizeof( dleaf_t ) );
-       numnodes = CopyLump( LUMP_NODES, dnodes, sizeof( dnode_t ) );
-       numtexinfo = CopyLump( LUMP_TEXINFO, texinfo, sizeof( texinfo_t ) );
-       numfaces = CopyLump( LUMP_FACES, dfaces, sizeof( dface_t ) );
-       numleaffaces = CopyLump( LUMP_LEAFFACES, dleaffaces, sizeof( dleaffaces[0] ) );
-       numleafbrushes = CopyLump( LUMP_LEAFBRUSHES, dleafbrushes, sizeof( dleafbrushes[0] ) );
-       numsurfedges = CopyLump( LUMP_SURFEDGES, dsurfedges, sizeof( dsurfedges[0] ) );
-       numedges = CopyLump( LUMP_EDGES, dedges, sizeof( dedge_t ) );
-       numbrushes = CopyLump( LUMP_BRUSHES, dbrushes, sizeof( dbrush_t ) );
-       numbrushsides = CopyLump( LUMP_BRUSHSIDES, dbrushsides, sizeof( dbrushside_t ) );
-       numareas = CopyLump( LUMP_AREAS, dareas, sizeof( darea_t ) );
-       numareaportals = CopyLump( LUMP_AREAPORTALS, dareaportals, sizeof( dareaportal_t ) );
-
-       visdatasize = CopyLump( LUMP_VISIBILITY, dvisdata, 1 );
-       lightdatasize = CopyLump( LUMP_LIGHTING, dlightdata, 1 );
-       entdatasize = CopyLump( LUMP_ENTITIES, dentdata, 1 );
-
-       CopyLump( LUMP_POP, dpop, 1 );
-
-       free( header );      // everything has been copied out
-
-//
-// swap everything
-//
-       SwapBSPFile( false );
-}
-
-
-/*
-   =============
-   LoadBSPFileTexinfo
-
-   Only loads the texinfo lump, so qdata can scan for textures
-   =============
- */
-void    LoadBSPFileTexinfo( char *filename ){
-       int i;
-       FILE        *f;
-       int length, ofs;
-
-       header = malloc( sizeof( dheader_t ) );
-
-       f = fopen( filename, "rb" );
-       fread( header, sizeof( dheader_t ), 1, f );
-
-// swap the header
-       for ( i = 0 ; i < sizeof( dheader_t ) / 4 ; i++ )
-               ( (int *)header )[i] = LittleLong( ( (int *)header )[i] );
-
-       if ( header->ident != IDBSPHEADER ) {
-               Error( "%s is not a IBSP file", filename );
-       }
-       if ( header->version != BSPVERSION ) {
-               Error( "%s is version %i, not %i", filename, header->version, BSPVERSION );
-       }
-
-
-       length = header->lumps[LUMP_TEXINFO].filelen;
-       ofs = header->lumps[LUMP_TEXINFO].fileofs;
-
-       fseek( f, ofs, SEEK_SET );
-       fread( texinfo, length, 1, f );
-       fclose( f );
-
-       numtexinfo = length / sizeof( texinfo_t );
-
-       free( header );      // everything has been copied out
-
-       SwapBSPFile( false );
-}
-
-
-//============================================================================
-
-FILE        *wadfile;
-dheader_t outheader;
-
-void AddLump( int lumpnum, void *data, int len ){
-       lump_t *lump;
-
-       lump = &header->lumps[lumpnum];
-
-       lump->fileofs = LittleLong( ftell( wadfile ) );
-       lump->filelen = LittleLong( len );
-       SafeWrite( wadfile, data, ( len + 3 ) & ~3 );
-}
-
-/*
-   =============
-   WriteBSPFile
-
-   Swaps the bsp file in place, so it should not be referenced again
-   =============
- */
-void    WriteBSPFile( char *filename ){
-       header = &outheader;
-       memset( header, 0, sizeof( dheader_t ) );
-
-       SwapBSPFile( true );
-
-       header->ident = LittleLong( IDBSPHEADER );
-       header->version = LittleLong( BSPVERSION );
-
-       wadfile = SafeOpenWrite( filename );
-       SafeWrite( wadfile, header, sizeof( dheader_t ) ); // overwritten later
-
-       AddLump( LUMP_PLANES, dplanes, numplanes * sizeof( dplane_t ) );
-       AddLump( LUMP_LEAFS, dleafs, numleafs * sizeof( dleaf_t ) );
-       AddLump( LUMP_VERTEXES, dvertexes, numvertexes * sizeof( dvertex_t ) );
-       AddLump( LUMP_NODES, dnodes, numnodes * sizeof( dnode_t ) );
-       AddLump( LUMP_TEXINFO, texinfo, numtexinfo * sizeof( texinfo_t ) );
-       AddLump( LUMP_FACES, dfaces, numfaces * sizeof( dface_t ) );
-       AddLump( LUMP_BRUSHES, dbrushes, numbrushes * sizeof( dbrush_t ) );
-       AddLump( LUMP_BRUSHSIDES, dbrushsides, numbrushsides * sizeof( dbrushside_t ) );
-       AddLump( LUMP_LEAFFACES, dleaffaces, numleaffaces * sizeof( dleaffaces[0] ) );
-       AddLump( LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
-       AddLump( LUMP_SURFEDGES, dsurfedges, numsurfedges * sizeof( dsurfedges[0] ) );
-       AddLump( LUMP_EDGES, dedges, numedges * sizeof( dedge_t ) );
-       AddLump( LUMP_MODELS, dmodels, nummodels * sizeof( dmodel_t ) );
-       AddLump( LUMP_AREAS, dareas, numareas * sizeof( darea_t ) );
-       AddLump( LUMP_AREAPORTALS, dareaportals, numareaportals * sizeof( dareaportal_t ) );
-
-       AddLump( LUMP_LIGHTING, dlightdata, lightdatasize );
-       AddLump( LUMP_VISIBILITY, dvisdata, visdatasize );
-       AddLump( LUMP_ENTITIES, dentdata, entdatasize );
-       AddLump( LUMP_POP, dpop, sizeof( dpop ) );
-
-       fseek( wadfile, 0, SEEK_SET );
-       SafeWrite( wadfile, header, sizeof( dheader_t ) );
-       fclose( wadfile );
-}
-
-//============================================================================
-
-/*
-   =============
-   PrintBSPFileSizes
-
-   Dumps info about current file
-   =============
- */
-void PrintBSPFileSizes( void ){
-       if ( !num_entities ) {
-               ParseEntities();
-       }
-
-       printf( "%5i models       %7i\n"
-                       ,nummodels, (int)( nummodels * sizeof( dmodel_t ) ) );
-       printf( "%5i brushes      %7i\n"
-                       ,numbrushes, (int)( numbrushes * sizeof( dbrush_t ) ) );
-       printf( "%5i brushsides   %7i\n"
-                       ,numbrushsides, (int)( numbrushsides * sizeof( dbrushside_t ) ) );
-       printf( "%5i planes       %7i\n"
-                       ,numplanes, (int)( numplanes * sizeof( dplane_t ) ) );
-       printf( "%5i texinfo      %7i\n"
-                       ,numtexinfo, (int)( numtexinfo * sizeof( texinfo_t ) ) );
-       printf( "%5i entdata      %7i\n", num_entities, entdatasize );
-
-       printf( "\n" );
-
-       printf( "%5i vertexes     %7i\n"
-                       ,numvertexes, (int)( numvertexes * sizeof( dvertex_t ) ) );
-       printf( "%5i nodes        %7i\n"
-                       ,numnodes, (int)( numnodes * sizeof( dnode_t ) ) );
-       printf( "%5i faces        %7i\n"
-                       ,numfaces, (int)( numfaces * sizeof( dface_t ) ) );
-       printf( "%5i leafs        %7i\n"
-                       ,numleafs, (int)( numleafs * sizeof( dleaf_t ) ) );
-       printf( "%5i leaffaces    %7i\n"
-                       ,numleaffaces, (int)( numleaffaces * sizeof( dleaffaces[0] ) ) );
-       printf( "%5i leafbrushes  %7i\n"
-                       ,numleafbrushes, (int)( numleafbrushes * sizeof( dleafbrushes[0] ) ) );
-       printf( "%5i surfedges    %7i\n"
-                       ,numsurfedges, (int)( numsurfedges * sizeof( dsurfedges[0] ) ) );
-       printf( "%5i edges        %7i\n"
-                       ,numedges, (int)( numedges * sizeof( dedge_t ) ) );
-       printf( "      lightdata    %7i\n", lightdatasize );
-       printf( "      visdata      %7i\n", visdatasize );
-}
-
-
-//============================================
-
-int num_entities;
-entity_t entities[MAX_MAP_ENTITIES];
-
-void StripTrailing( char *e ){
-       char    *s;
-
-       s = e + strlen( e ) - 1;
-       while ( s >= e && *s <= 32 )
-       {
-               *s = 0;
-               s--;
-       }
-}
-
-/*
-   =================
-   ParseEpair
-   =================
- */
-epair_t *ParseEpair( void ){
-       epair_t *e;
-
-       e = malloc( sizeof( epair_t ) );
-       memset( e, 0, sizeof( epair_t ) );
-
-       if ( strlen( token ) >= MAX_KEY - 1 ) {
-               Error( "ParseEpar: token too long" );
-       }
-       e->key = copystring( token );
-       GetScriptToken( false );
-       if ( strlen( token ) >= MAX_VALUE - 1 ) {
-               Error( "ParseEpar: token too long" );
-       }
-       e->value = copystring( token );
-
-       // strip trailing spaces
-       StripTrailing( e->key );
-       StripTrailing( e->value );
-
-       return e;
-}
-
-
-/*
-   ================
-   ParseEntity
-   ================
- */
-qboolean    ParseEntity( void ){
-       epair_t     *e;
-       entity_t    *mapent;
-
-       if ( !GetScriptToken( true ) ) {
-               return false;
-       }
-
-       if ( strcmp( token, "{" ) ) {
-               Error( "ParseEntity: { not found" );
-       }
-
-       if ( num_entities == MAX_MAP_ENTITIES ) {
-               Error( "num_entities == MAX_MAP_ENTITIES" );
-       }
-
-       mapent = &entities[num_entities];
-       num_entities++;
-
-       do
-       {
-               if ( !GetScriptToken( true ) ) {
-                       Error( "ParseEntity: EOF without closing brace" );
-               }
-               if ( !strcmp( token, "}" ) ) {
-                       break;
-               }
-               e = ParseEpair();
-               e->next = mapent->epairs;
-               mapent->epairs = e;
-       } while ( 1 );
-
-       return true;
-}
-
-/*
-   ================
-   ParseEntities
-
-   Parses the dentdata string into entities
-   ================
- */
-void ParseEntities( void ){
-       num_entities = 0;
-       ParseFromMemory( dentdata, entdatasize );
-
-       while ( ParseEntity() )
-       {
-       }
-}
-
-
-/*
-   ================
-   UnparseEntities
-
-   Generates the dentdata string from all the entities
-   ================
- */
-void UnparseEntities( void ){
-       char    *buf, *end;
-       epair_t *ep;
-       char line[2048];
-       int i;
-       char key[1024], value[1024];
-
-       buf = dentdata;
-       end = buf;
-       *end = 0;
-
-       for ( i = 0 ; i < num_entities ; i++ )
-       {
-               ep = entities[i].epairs;
-               if ( !ep ) {
-                       continue;   // ent got removed
-
-               }
-               strcat( end,"{\n" );
-               end += 2;
-
-               for ( ep = entities[i].epairs ; ep ; ep = ep->next )
-               {
-                       strcpy( key, ep->key );
-                       StripTrailing( key );
-                       strcpy( value, ep->value );
-                       StripTrailing( value );
-
-                       sprintf( line, "\"%s\" \"%s\"\n", key, value );
-                       strcat( end, line );
-                       end += strlen( line );
-               }
-               strcat( end,"}\n" );
-               end += 2;
-
-               if ( end > buf + MAX_MAP_ENTSTRING ) {
-                       Error( "Entity text too long" );
-               }
-       }
-       entdatasize = end - buf + 1;
-}
-
-void PrintEntity( entity_t *ent ){
-       epair_t *ep;
-
-       printf( "------- entity %p -------\n", ent );
-       for ( ep = ent->epairs ; ep ; ep = ep->next )
-       {
-               printf( "%s = %s\n", ep->key, ep->value );
-       }
-
-}
-
-void    SetKeyValue( entity_t *ent, char *key, char *value ){
-       epair_t *ep;
-
-       for ( ep = ent->epairs ; ep ; ep = ep->next )
-               if ( !strcmp( ep->key, key ) ) {
-                       free( ep->value );
-                       ep->value = copystring( value );
-                       return;
-               }
-       ep = malloc( sizeof( *ep ) );
-       if ( !ep ) {
-               Error( "SetKeyValue MALLOC failed!  Could not allocate %s bytes.", sizeof( *ep ) );
-       }
-       ep->next = ent->epairs;
-       ent->epairs = ep;
-       ep->key = copystring( key );
-       ep->value = copystring( value );
-}
-
-char    *ValueForKey( entity_t *ent, char *key ){
-       epair_t *ep;
-
-       for ( ep = ent->epairs ; ep ; ep = ep->next )
-               if ( !strcmp( ep->key, key ) ) {
-                       return ep->value;
-               }
-       return "";
-}
-
-vec_t   FloatForKey( entity_t *ent, char *key ){
-       char    *k;
-
-       k = ValueForKey( ent, key );
-       return atof( k );
-}
-
-void    GetVectorForKey( entity_t *ent, char *key, vec3_t vec ){
-       char    *k;
-       double v1, v2, v3;
-
-       k = ValueForKey( ent, key );
-// scanf into doubles, then assign, so it is vec_t size independent
-       v1 = v2 = v3 = 0;
-       sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
-       vec[0] = v1;
-       vec[1] = v2;
-       vec[2] = v3;
-}
diff --git a/tools/quake2/qdata_heretic2/common/bspfile.h b/tools/quake2/qdata_heretic2/common/bspfile.h
deleted file mode 100644 (file)
index f66659b..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _QBSP3_H
-#define _QBSP3_H
-
-
-#include "qfiles.h"
-
-
-extern int nummodels;
-extern dmodel_t dmodels[MAX_MAP_MODELS];
-
-extern int visdatasize;
-extern byte dvisdata[MAX_MAP_VISIBILITY];
-extern dvis_t      *dvis;
-
-extern int lightdatasize;
-extern byte dlightdata[MAX_MAP_LIGHTING];
-
-extern int entdatasize;
-extern char dentdata[MAX_MAP_ENTSTRING];
-
-extern int numleafs;
-extern dleaf_t dleafs[MAX_MAP_LEAFS];
-
-extern int numplanes;
-extern dplane_t dplanes[MAX_MAP_PLANES];
-
-extern int numvertexes;
-extern dvertex_t dvertexes[MAX_MAP_VERTS];
-
-extern int numnodes;
-extern dnode_t dnodes[MAX_MAP_NODES];
-
-extern int numtexinfo;
-extern texinfo_t texinfo[MAX_MAP_TEXINFO];
-
-extern int numfaces;
-extern dface_t dfaces[MAX_MAP_FACES];
-
-extern int numedges;
-extern dedge_t dedges[MAX_MAP_EDGES];
-
-extern int numleaffaces;
-extern unsigned short dleaffaces[MAX_MAP_LEAFFACES];
-
-extern int numleafbrushes;
-extern unsigned short dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-extern int numsurfedges;
-extern int dsurfedges[MAX_MAP_SURFEDGES];
-
-extern int numareas;
-extern darea_t dareas[MAX_MAP_AREAS];
-
-extern int numareaportals;
-extern dareaportal_t dareaportals[MAX_MAP_AREAPORTALS];
-
-extern int numbrushes;
-extern dbrush_t dbrushes[MAX_MAP_BRUSHES];
-
-extern int numbrushsides;
-extern dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
-
-extern byte dpop[256];
-
-void DecompressVis( byte *in, byte *decompressed );
-int CompressVis( byte *vis, byte *dest );
-
-void    LoadBSPFile( char *filename );
-void    LoadBSPFileTexinfo( char *filename );    // just for qdata
-void    WriteBSPFile( char *filename );
-void    PrintBSPFileSizes( void );
-
-//===============
-
-
-typedef struct epair_s
-{
-       struct epair_s  *next;
-       char    *key;
-       char    *value;
-} epair_t;
-
-typedef struct
-{
-       vec3_t origin;
-       int firstbrush;
-       int numbrushes;
-       epair_t     *epairs;
-
-// only valid for func_areaportals
-       int areaportalnum;
-       int portalareas[2];
-} entity_t;
-
-extern int num_entities;
-extern entity_t entities[MAX_MAP_ENTITIES];
-
-void    ParseEntities( void );
-void    UnparseEntities( void );
-
-void    SetKeyValue( entity_t *ent, char *key, char *value );
-char    *ValueForKey( entity_t *ent, char *key );
-// will return "" if not present
-
-vec_t   FloatForKey( entity_t *ent, char *key );
-void    GetVectorForKey( entity_t *ent, char *key, vec3_t vec );
-
-epair_t *ParseEpair( void );
-
-void PrintEntity( entity_t *ent );
-
-#endif //_QBSP3_H
diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.c b/tools/quake2/qdata_heretic2/common/cmdlib.c
deleted file mode 100644 (file)
index 9a06870..0000000
+++ /dev/null
@@ -1,1195 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// Nurail: Swiped from quake3/common
-
-#include "cmdlib.h"
-#include "globaldefs.h"
-#include "mathlib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if GDEF_OS_WINDOWS
-#include <direct.h>
-#include <windows.h>
-#endif
-
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#endif
-
-#define BASEDIRNAME "h"
-#define PATHSEPERATOR   '/'
-
-extern qboolean verbose;
-
-qboolean g_dokeypress = false;
-
-qboolean g_nomkdir = false;
-
-
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size ){
-       void *p;
-
-       p = malloc( size );
-       if ( !p ) {
-               Error( "safe_malloc failed on allocation of %i bytes", size );
-       }
-
-       return p;
-}
-
-void *safe_malloc_info( size_t size, char* info ){
-       void *p;
-
-       p = malloc( size );
-       if ( !p ) {
-               Error( "%s: safe_malloc failed on allocation of %i bytes", info, size );
-       }
-
-       return p;
-}
-#endif
-
-void *SafeMalloc( size_t n, char *desc ){
-       void *p;
-
-       if ( ( p = malloc( n ) ) == NULL ) {
-               Error( "Failed to allocate %d bytes for '%s'.\n", n, desc );
-       }
-       memset( p, 0, n );
-       return p;
-}
-
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-void strlwr( char *conv_str ){
-       int i;
-
-       for ( i = 0; i < strlen( conv_str ); i++ )
-               conv_str[i] = tolower( conv_str[i] );
-}
-#endif
-
-
-// set these before calling CheckParm
-int myargc;
-char **myargv;
-
-char com_token[1024];
-qboolean com_eof;
-
-qboolean archive;
-char archivedir[1024];
-
-
-/*
-   ===================
-   ExpandWildcards
-
-   Mimic unix command line expansion
-   ===================
- */
-#define MAX_EX_ARGC 1024
-int ex_argc;
-char    *ex_argv[MAX_EX_ARGC];
-#if GDEF_OS_WINDOWS
-#include "io.h"
-void ExpandWildcards( int *argc, char ***argv ){
-       struct _finddata_t fileinfo;
-       int handle;
-       int i;
-       char filename[1024];
-       char filebase[1024];
-       char    *path;
-
-       ex_argc = 0;
-       for ( i = 0 ; i < *argc ; i++ )
-       {
-               path = ( *argv )[i];
-               if ( path[0] == '-'
-                        || ( !strstr( path, "*" ) && !strstr( path, "?" ) ) ) {
-                       ex_argv[ex_argc++] = path;
-                       continue;
-               }
-
-               handle = _findfirst( path, &fileinfo );
-               if ( handle == -1 ) {
-                       return;
-               }
-
-               ExtractFilePath( path, filebase );
-
-               do
-               {
-                       sprintf( filename, "%s%s", filebase, fileinfo.name );
-                       ex_argv[ex_argc++] = copystring( filename );
-               } while ( _findnext( handle, &fileinfo ) != -1 );
-
-               _findclose( handle );
-       }
-
-       *argc = ex_argc;
-       *argv = ex_argv;
-}
-#else
-void ExpandWildcards( int *argc, char ***argv ){
-}
-#endif
-
-/*
-
-   qdir will hold the path up to the quake directory, including the slash
-
-   f:\quake\
-   /raid/quake/
-
-   gamedir will hold qdir + the game directory (id1, id2, etc)
-
- */
-
-char qdir[1024];
-char gamedir[1024];
-char writedir[1024];
-
-void SetQdirFromPath( const char *path ){
-       char temp[1024];
-       const char  *c;
-       const char *sep;
-       int len, count;
-
-       if ( !( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) ) { // path is partial
-               Q_getwd( temp );
-               strcat( temp, path );
-               path = temp;
-       }
-
-       // search for "quake2" in path
-
-       len = strlen( BASEDIRNAME );
-       for ( c = path + strlen( path ) - 1 ; c != path ; c-- )
-       {
-               int i;
-
-               if ( !Q_strncasecmp( c, BASEDIRNAME, len ) ) {
-                       //
-                       //strncpy (qdir, path, c+len+2-path);
-                       // the +2 assumes a 2 or 3 following quake which is not the
-                       // case with a retail install
-                       // so we need to add up how much to the next separator
-                       sep = c + len;
-                       count = 1;
-                       while ( *sep && *sep != '/' && *sep != '\\' )
-                       {
-                               sep++;
-                               count++;
-                       }
-                       strncpy( qdir, path, c + len + count - path );
-                       Sys_Printf( "qdir: %s\n", qdir );
-                       for ( i = 0; i < strlen( qdir ); i++ )
-                       {
-                               if ( qdir[i] == '\\' ) {
-                                       qdir[i] = '/';
-                               }
-                       }
-
-                       c += len + count;
-                       while ( *c )
-                       {
-                               if ( *c == '/' || *c == '\\' ) {
-                                       strncpy( gamedir, path, c + 1 - path );
-
-                                       for ( i = 0; i < strlen( gamedir ); i++ )
-                                       {
-                                               if ( gamedir[i] == '\\' ) {
-                                                       gamedir[i] = '/';
-                                               }
-                                       }
-
-                                       Sys_Printf( "gamedir: %s\n", gamedir );
-
-                                       if ( !writedir[0] ) {
-                                               strcpy( writedir, gamedir );
-                                       }
-                                       else if ( writedir[strlen( writedir ) - 1] != '/' ) {
-                                               writedir[strlen( writedir )] = '/';
-                                               writedir[strlen( writedir ) + 1] = 0;
-                                       }
-
-                                       return;
-                               }
-                               c++;
-                       }
-                       Error( "No gamedir in %s", path );
-                       return;
-               }
-       }
-       Error( "SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path );
-}
-
-char *ExpandArg( const char *path ){
-       static char full[1024];
-
-       if ( path[0] != '/' && path[0] != '\\' && path[1] != ':' ) {
-               Q_getwd( full );
-               strcat( full, path );
-       }
-       else{
-               strcpy( full, path );
-       }
-       return full;
-}
-
-char *ExpandPath( const char *path ){
-       static char full[1024];
-       if ( !qdir ) {
-               Error( "ExpandPath called without qdir set" );
-       }
-       if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
-               strcpy( full, path );
-               return full;
-       }
-       sprintf( full, "%s%s", qdir, path );
-       return full;
-}
-
-char *ExpandGamePath( const char *path ){
-       static char full[1024];
-       if ( !qdir ) {
-               Error( "ExpandGamePath called without qdir set" );
-       }
-       if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ) {
-               strcpy( full, path );
-               return full;
-       }
-       sprintf( full, "%s%s", gamedir, path );
-       return full;
-}
-
-char *ExpandPathAndArchive( const char *path ){
-       char    *expanded;
-       char archivename[1024];
-
-       expanded = ExpandPath( path );
-
-       if ( archive ) {
-               sprintf( archivename, "%s/%s", archivedir, path );
-               QCopyFile( expanded, archivename );
-       }
-       return expanded;
-}
-
-
-char *copystring( const char *s ){
-       char    *b;
-       b = safe_malloc( strlen( s ) + 1 );
-       strcpy( b, s );
-       return b;
-}
-
-
-
-/*
-   ================
-   I_FloatTime
-   ================
- */
-double I_FloatTime( void ){
-       time_t t;
-
-       time( &t );
-
-       return t;
-#if 0
-// more precise, less portable
-       struct timeval tp;
-       struct timezone tzp;
-       static int secbase;
-
-       gettimeofday( &tp, &tzp );
-
-       if ( !secbase ) {
-               secbase = tp.tv_sec;
-               return tp.tv_usec / 1000000.0;
-       }
-
-       return ( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0;
-#endif
-}
-
-void Q_getwd( char *out ){
-       int i = 0;
-
-#if GDEF_OS_WINDOWS
-       _getcwd( out, 256 );
-       strcat( out, "\\" );
-#else
-       // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
-       getcwd( out, 256 );
-       strcat( out, "/" );
-#endif
-       while ( out[i] != 0 )
-       {
-               if ( out[i] == '\\' ) {
-                       out[i] = '/';
-               }
-               i++;
-       }
-}
-
-
-void Q_mkdir( const char *path ){
-#if GDEF_OS_WINDOWS
-       if ( _mkdir( path ) != -1 ) {
-               return;
-       }
-#else
-       if ( mkdir( path, 0777 ) != -1 ) {
-               return;
-       }
-#endif
-       if ( errno != EEXIST ) {
-               Error( "mkdir %s: %s",path, strerror( errno ) );
-       }
-}
-
-/*
-   ============
-   FileTime
-
-   returns -1 if not present
-   ============
- */
-int FileTime( const char *path ){
-       struct  stat buf;
-
-       if ( stat( path,&buf ) == -1 ) {
-               return -1;
-       }
-
-       return buf.st_mtime;
-}
-
-
-
-/*
-   ==============
-   COM_Parse
-
-   Parse a token out of a string
-   ==============
- */
-char *COM_Parse( char *data ){
-       int c;
-       int len;
-
-       len = 0;
-       com_token[0] = 0;
-
-       if ( !data ) {
-               return NULL;
-       }
-
-// skip whitespace
-skipwhite:
-       while ( ( c = *data ) <= ' ' )
-       {
-               if ( c == 0 ) {
-                       com_eof = true;
-                       return NULL;            // end of file;
-               }
-               data++;
-       }
-
-// skip // comments
-       if ( c == '/' && data[1] == '/' ) {
-               while ( *data && *data != '\n' )
-                       data++;
-               goto skipwhite;
-       }
-
-
-// handle quoted strings specially
-       if ( c == '\"' ) {
-               data++;
-               do
-               {
-                       c = *data++;
-                       if ( c == '\"' ) {
-                               com_token[len] = 0;
-                               return data;
-                       }
-                       com_token[len] = c;
-                       len++;
-               } while ( 1 );
-       }
-
-// parse single characters
-       if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
-               com_token[len] = c;
-               len++;
-               com_token[len] = 0;
-               return data + 1;
-       }
-
-// parse a regular word
-       do
-       {
-               com_token[len] = c;
-               data++;
-               len++;
-               c = *data;
-               if ( c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' ) {
-                       break;
-               }
-       } while ( c > 32 );
-
-       com_token[len] = 0;
-       return data;
-}
-
-int Q_strncasecmp( const char *s1, const char *s2, int n ){
-       int c1, c2;
-
-       do
-       {
-               c1 = *s1++;
-               c2 = *s2++;
-
-               if ( !n-- ) {
-                       return 0;       // strings are equal until end point
-
-               }
-               if ( c1 != c2 ) {
-                       if ( c1 >= 'a' && c1 <= 'z' ) {
-                               c1 -= ( 'a' - 'A' );
-                       }
-                       if ( c2 >= 'a' && c2 <= 'z' ) {
-                               c2 -= ( 'a' - 'A' );
-                       }
-                       if ( c1 != c2 ) {
-                               return -1;      // strings not equal
-                       }
-               }
-       } while ( c1 );
-
-       return 0;       // strings are equal
-}
-
-int Q_stricmp( const char *s1, const char *s2 ){
-       return Q_strncasecmp( s1, s2, 99999 );
-}
-
-int Q_strcasecmp( const char *s1, const char *s2 ){
-       return Q_strncasecmp( s1, s2, 99999 );
-}
-
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-   char *strupr (char *start)
-   {
-    char       *in;
-    in = start;
-    while (*in)
-    {
-   *in = toupper(*in);
-        in++;
-    }
-    return start;
-   }
- */
-
-char *strlower( char *start ){
-       char    *in;
-       in = start;
-       while ( *in )
-       {
-               *in = tolower( *in );
-               in++;
-       }
-       return start;
-}
-
-
-/*
-   =============================================================================
-
-                        MISC FUNCTIONS
-
-   =============================================================================
- */
-
-
-/*
-   =================
-   CheckParm
-
-   Checks for the given parameter in the program's command line arguments
-   Returns the argument number (1 to argc-1) or 0 if not present
-   =================
- */
-int CheckParm( const char *check ){
-       int i;
-
-       for ( i = 1; i < myargc; i++ )
-       {
-               if ( !Q_stricmp( check, myargv[i] ) ) {
-                       return i;
-               }
-       }
-
-       return 0;
-}
-
-
-
-/*
-   ================
-   Q_filelength
-   ================
- */
-int Q_filelength( FILE *f ){
-       int pos;
-       int end;
-
-       pos = ftell( f );
-       fseek( f, 0, SEEK_END );
-       end = ftell( f );
-       fseek( f, pos, SEEK_SET );
-
-       return end;
-}
-
-
-FILE *SafeOpenWrite( const char *filename ){
-       FILE    *f;
-
-       f = fopen( filename, "wb" );
-
-       if ( !f ) {
-               Error( "Error opening %s: %s",filename,strerror( errno ) );
-       }
-
-       return f;
-}
-
-FILE *SafeOpenRead( const char *filename ){
-       FILE    *f;
-
-       f = fopen( filename, "rb" );
-
-       if ( !f ) {
-               Error( "Error opening %s: %s",filename,strerror( errno ) );
-       }
-
-       return f;
-}
-
-
-void SafeRead( FILE *f, void *buffer, int count ){
-       if ( fread( buffer, 1, count, f ) != (size_t)count ) {
-               Error( "File read failure" );
-       }
-}
-
-
-void SafeWrite( FILE *f, const void *buffer, int count ){
-       if ( fwrite( buffer, 1, count, f ) != (size_t)count ) {
-               Error( "File write failure" );
-       }
-}
-
-
-/*
-   ==============
-   FileExists
-   ==============
- */
-qboolean    FileExists( const char *filename ){
-       FILE    *f;
-
-       f = fopen( filename, "r" );
-       if ( !f ) {
-               return false;
-       }
-       fclose( f );
-       return true;
-}
-
-/*
-   ==============
-   LoadFile
-   ==============
- */
-int    LoadFile( const char *filename, void **bufferptr ){
-       FILE    *f;
-       int length;
-       void    *buffer;
-
-       f = SafeOpenRead( filename );
-       length = Q_filelength( f );
-       buffer = safe_malloc( length + 1 );
-       ( (char *)buffer )[length] = 0;
-       SafeRead( f, buffer, length );
-       fclose( f );
-
-       *bufferptr = buffer;
-       return length;
-}
-
-
-/*
-   ==============
-   LoadFileBlock
-   -
-   rounds up memory allocation to 4K boundry
-   -
-   ==============
- */
-int    LoadFileBlock( const char *filename, void **bufferptr ){
-       FILE    *f;
-       int length, nBlock, nAllocSize;
-       void    *buffer;
-
-       f = SafeOpenRead( filename );
-       length = Q_filelength( f );
-       nAllocSize = length;
-       nBlock = nAllocSize % MEM_BLOCKSIZE;
-       if ( nBlock > 0 ) {
-               nAllocSize += MEM_BLOCKSIZE - nBlock;
-       }
-       buffer = safe_malloc( nAllocSize + 1 );
-       memset( buffer, 0, nAllocSize + 1 );
-       SafeRead( f, buffer, length );
-       fclose( f );
-
-       *bufferptr = buffer;
-       return length;
-}
-
-
-/*
-   ==============
-   TryLoadFile
-
-   Allows failure
-   ==============
- */
-int    TryLoadFile( const char *filename, void **bufferptr ){
-       FILE    *f;
-       int length;
-       void    *buffer;
-
-       *bufferptr = NULL;
-
-       f = fopen( filename, "rb" );
-       if ( !f ) {
-               return -1;
-       }
-       length = Q_filelength( f );
-       buffer = safe_malloc( length + 1 );
-       ( (char *)buffer )[length] = 0;
-       SafeRead( f, buffer, length );
-       fclose( f );
-
-       *bufferptr = buffer;
-       return length;
-}
-
-
-/*
-   ==============
-   SaveFile
-   ==============
- */
-void    SaveFile( const char *filename, const void *buffer, int count ){
-       FILE    *f;
-
-       f = SafeOpenWrite( filename );
-       SafeWrite( f, buffer, count );
-       fclose( f );
-}
-
-
-
-void DefaultExtension( char *path, const char *extension ){
-       char    *src;
-//
-// if path doesnt have a .EXT, append extension
-// (extension should include the .)
-//
-       src = path + strlen( path ) - 1;
-
-       while ( *src != '/' && *src != '\\' && src != path )
-       {
-               if ( *src == '.' ) {
-                       return;                 // it has an extension
-               }
-               src--;
-       }
-
-       strcat( path, extension );
-}
-
-
-void DefaultPath( char *path, const char *basepath ){
-       char temp[128];
-
-       if ( path[ 0 ] == '/' || path[ 0 ] == '\\' ) {
-               return;                   // absolute path location
-       }
-       strcpy( temp,path );
-       strcpy( path,basepath );
-       strcat( path,temp );
-}
-
-
-void    StripFilename( char *path ){
-       int length;
-
-       length = strlen( path ) - 1;
-       while ( length > 0 && path[length] != '/' && path[ length ] != '\\' )
-               length--;
-       path[length] = 0;
-}
-
-void    StripExtension( char *path ){
-       int length;
-
-       length = strlen( path ) - 1;
-       while ( length > 0 && path[length] != '.' )
-       {
-               length--;
-               if ( path[length] == '/' || path[ length ] == '\\' ) {
-                       return;     // no extension
-               }
-       }
-       if ( length ) {
-               path[length] = 0;
-       }
-}
-
-
-/*
-   ====================
-   Extract file parts
-   ====================
- */
-// FIXME: should include the slash, otherwise
-// backing to an empty path will be wrong when appending a slash
-void ExtractFilePath( const char *path, char *dest ){
-       const char    *src;
-
-       src = path + strlen( path ) - 1;
-
-//
-// back up until a \ or the start
-//
-       while ( src != path && *( src - 1 ) != '\\' && *( src - 1 ) != '/' )
-               src--;
-
-       memcpy( dest, path, src - path );
-       dest[src - path] = 0;
-}
-
-void ExtractFileBase( const char *path, char *dest ){
-       const char    *src;
-
-       src = path + strlen( path ) - 1;
-
-//
-// back up until a \ or the start
-//
-       while ( src != path && *( src - 1 ) != '/' && *( src - 1 ) != '\\' )
-               src--;
-
-       while ( *src && *src != '.' )
-       {
-               *dest++ = *src++;
-       }
-       *dest = 0;
-}
-
-void ExtractFileExtension( const char *path, char *dest ){
-       const char    *src;
-
-       src = path + strlen( path ) - 1;
-
-//
-// back up until a . or the start
-//
-       while ( src != path && *( src - 1 ) != '.' )
-               src--;
-       if ( src == path ) {
-               *dest = 0;  // no extension
-               return;
-       }
-
-       strcpy( dest,src );
-}
-
-
-/*
-   ==============
-   ParseNum / ParseHex
-   ==============
- */
-int ParseHex( const char *hex ){
-       const char    *str;
-       int num;
-
-       num = 0;
-       str = hex;
-
-       while ( *str )
-       {
-               num <<= 4;
-               if ( *str >= '0' && *str <= '9' ) {
-                       num += *str - '0';
-               }
-               else if ( *str >= 'a' && *str <= 'f' ) {
-                       num += 10 + *str - 'a';
-               }
-               else if ( *str >= 'A' && *str <= 'F' ) {
-                       num += 10 + *str - 'A';
-               }
-               else{
-                       Error( "Bad hex number: %s",hex );
-               }
-               str++;
-       }
-
-       return num;
-}
-
-
-int ParseNum( const char *str ){
-       if ( str[0] == '$' ) {
-               return ParseHex( str + 1 );
-       }
-       if ( str[0] == '0' && str[1] == 'x' ) {
-               return ParseHex( str + 2 );
-       }
-       return atol( str );
-}
-/*
-   // all output ends up through here
-   void FPrintf (int flag, char *buf)
-   {
-   printf( "%s", buf );
-
-   }
-
-   void Sys_FPrintf (int flag, const char *format, ...)
-   {
-   char out_buffer[4096];
-    va_list argptr;
-
-   if ((flag == SYS_VRB) && (verbose == false))
-    return;
-
-   va_start (argptr, format);
-    vsprintf (out_buffer, format, argptr);
-    va_end (argptr);
-
-   FPrintf (flag, out_buffer);
-   }
-
-   void Sys_Printf (const char *format, ...)
-   {
-   char out_buffer[4096];
-    va_list argptr;
-
-   va_start (argptr, format);
-    vsprintf (out_buffer, format, argptr);
-    va_end (argptr);
-
-   FPrintf (SYS_STD, out_buffer);
-   }
-
-   //=================
-   //Error
-   //
-   //For abnormal program terminations
-   //=================
-
-   void Error( const char *error, ...)
-   {
-   char out_buffer[4096];
-   char tmp[4096];
-    va_list argptr;
-
-    va_start (argptr,error);
-    vsprintf (tmp, error, argptr);
-    va_end (argptr);
-
-   sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-   FPrintf( SYS_ERR, out_buffer );
-
-    exit (1);
-   }
-
- */
-
-/*
-   ============================================================================
-
-                    BYTE ORDER FUNCTIONS
-
-   ============================================================================
- */
-
-#if GDEF_ARCH_ENDIAN_BIG
-
-short   LittleShort( short l ){
-       byte b1,b2;
-
-       b1 = l & 255;
-       b2 = ( l >> 8 ) & 255;
-
-       return ( b1 << 8 ) + b2;
-}
-
-short   BigShort( short l ){
-       return l;
-}
-
-
-int    LittleLong( int l ){
-       byte b1,b2,b3,b4;
-
-       b1 = l & 255;
-       b2 = ( l >> 8 ) & 255;
-       b3 = ( l >> 16 ) & 255;
-       b4 = ( l >> 24 ) & 255;
-
-       return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
-}
-
-int    BigLong( int l ){
-       return l;
-}
-
-
-float   LittleFloat( float l ){
-       union {byte b[4]; float f; } in, out;
-
-       in.f = l;
-       out.b[0] = in.b[3];
-       out.b[1] = in.b[2];
-       out.b[2] = in.b[1];
-       out.b[3] = in.b[0];
-
-       return out.f;
-}
-
-float   BigFloat( float l ){
-       return l;
-}
-
-
-#else
-
-
-short   BigShort( short l ){
-       byte b1,b2;
-
-       b1 = l & 255;
-       b2 = ( l >> 8 ) & 255;
-
-       return ( b1 << 8 ) + b2;
-}
-
-short   LittleShort( short l ){
-       return l;
-}
-
-
-int    BigLong( int l ){
-       byte b1,b2,b3,b4;
-
-       b1 = l & 255;
-       b2 = ( l >> 8 ) & 255;
-       b3 = ( l >> 16 ) & 255;
-       b4 = ( l >> 24 ) & 255;
-
-       return ( (int)b1 << 24 ) + ( (int)b2 << 16 ) + ( (int)b3 << 8 ) + b4;
-}
-
-int    LittleLong( int l ){
-       return l;
-}
-
-float   BigFloat( float l ){
-       union {byte b[4]; float f; } in, out;
-
-       in.f = l;
-       out.b[0] = in.b[3];
-       out.b[1] = in.b[2];
-       out.b[2] = in.b[1];
-       out.b[3] = in.b[0];
-
-       return out.f;
-}
-
-float   LittleFloat( float l ){
-       return l;
-}
-
-
-#endif
-
-
-//=======================================================
-
-
-// FIXME: byte swap?
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below...  in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE  0xffff
-#define CRC_XOR_VALUE   0x0000
-
-static unsigned short crctable[256] =
-{
-       0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
-       0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
-       0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
-       0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
-       0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
-       0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
-       0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
-       0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
-       0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
-       0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
-       0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
-       0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
-       0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
-       0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
-       0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
-       0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
-       0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
-       0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
-       0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
-       0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
-       0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
-       0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
-       0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
-       0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
-       0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
-       0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
-       0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
-       0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
-       0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
-       0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
-       0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
-       0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
-};
-
-void CRC_Init( unsigned short *crcvalue ){
-       *crcvalue = CRC_INIT_VALUE;
-}
-
-void CRC_ProcessByte( unsigned short *crcvalue, byte data ){
-       *crcvalue = ( *crcvalue << 8 ) ^ crctable[( *crcvalue >> 8 ) ^ data];
-}
-
-unsigned short CRC_Value( unsigned short crcvalue ){
-       return crcvalue ^ CRC_XOR_VALUE;
-}
-//=============================================================================
-
-/*
-   ============
-   CreatePath
-   ============
- */
-void    CreatePath( const char *path ){
-       const char  *ofs;
-       char c;
-       char dir[1024];
-
-#if GDEF_OS_WINDOWS
-       int olddrive = -1;
-
-       if ( path[1] == ':' ) {
-               olddrive = _getdrive();
-               _chdrive( toupper( path[0] ) - 'A' + 1 );
-       }
-#endif
-
-       if ( path[1] == ':' ) {
-               path += 2;
-       }
-
-       for ( ofs = path + 1 ; *ofs ; ofs++ )
-       {
-               c = *ofs;
-               if ( c == '/' || c == '\\' ) { // create the directory
-                       memcpy( dir, path, ofs - path );
-                       dir[ ofs - path ] = 0;
-                       Q_mkdir( dir );
-               }
-       }
-
-#if GDEF_OS_WINDOWS
-       if ( olddrive != -1 ) {
-               _chdrive( olddrive );
-       }
-#endif
-}
-
-
-/*
-   ============
-   QCopyFile
-
-   Used to archive source files
-   ============
- */
-void QCopyFile( const char *from, const char *to ){
-       void    *buffer;
-       int length;
-
-       length = LoadFile( from, &buffer );
-       CreatePath( to );
-       SaveFile( to, buffer, length );
-       free( buffer );
-}
-
-void Sys_Sleep( int n ){
-#if GDEF_OS_WINDOWS
-       Sleep( n );
-#endif
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-       usleep( n * 1000 );
-#endif
-}
diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.h b/tools/quake2/qdata_heretic2/common/cmdlib.h
deleted file mode 100644 (file)
index b8b1aa3..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// cmdlib.h
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#if GDEF_COMPILER_MSVC
-#pragma warning(disable : 4244)     // MIPS
-#pragma warning(disable : 4136)     // X86
-#pragma warning(disable : 4051)     // ALPHA
-
-#pragma warning(disable : 4018)     // signed/unsigned mismatch
-#pragma warning(disable : 4305)     // truncate from double to float
-
-#pragma check_stack(off)
-
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#if GDEF_COMPILER_MSVC
-
-#pragma intrinsic( memset, memcpy )
-
-#endif
-
-#ifndef __BYTEBOOL__
-  #define __BYTEBOOL__
-//typedef enum {false, true} qboolean;
-//typedef unsigned char byte;
-  #include "q_typedef.h"
-#endif
-
-#ifdef PATH_MAX
-#define MAX_OS_PATH     PATH_MAX
-#else
-#define MAX_OS_PATH     1024
-#endif
-#define MEM_BLOCKSIZE 4096
-/*
-   extern      qboolean verbose;
-   #define SYS_VRB 0 // verbose support (on/off)
-   #define SYS_STD 1 // standard print level
-   #define SYS_WRN 2 // warnings
-   #define SYS_ERR 3 // error
- */
-// the dec offsetof macro doesnt work very well...
-#define myoffsetof( type,identifier ) ( (size_t)& ( (type *)0 )->identifier )
-
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size );
-void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc( a ) malloc( a )
-#endif /* SAFE_MALLOC */
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-char *strlower( char *in );
-int Q_strncasecmp( const char *s1, const char *s2, int n );
-int Q_stricmp( const char *s1, const char *s2 );
-int Q_strcasecmp( const char *s1, const char *s2 );
-void Q_getwd( char *out );
-
-int Q_filelength( FILE *f );
-int FileTime( const char *path );
-
-void    Q_mkdir( const char *path );
-
-extern char qdir[1024];
-extern char gamedir[1024];
-extern char writedir[1024];
-extern char    *moddirparam;
-void SetQdirFromPath( const char *path );
-char *ExpandArg( const char *path );    // from cmd line
-char *ExpandPath( const char *path );   // from scripts
-char *ExpandGamePath( const char *path );
-char *ExpandPathAndArchive( const char *path );
-void ExpandWildcards( int *argc, char ***argv );
-
-
-double I_FloatTime( void );
-
-int     CheckParm( const char *check );
-
-void    *SafeMalloc( size_t n, char *desc );
-FILE    *SafeOpenWrite( const char *filename );
-FILE    *SafeOpenRead( const char *filename );
-void    SafeRead( FILE *f, void *buffer, int count );
-void    SafeWrite( FILE *f, const void *buffer, int count );
-
-int     LoadFile( const char *filename, void **bufferptr );
-int   LoadFileBlock( const char *filename, void **bufferptr );
-int     TryLoadFile( const char *filename, void **bufferptr );
-void    SaveFile( const char *filename, const void *buffer, int count );
-qboolean    FileExists( const char *filename );
-
-void    DefaultExtension( char *path, const char *extension );
-void    DefaultPath( char *path, const char *basepath );
-void    StripFilename( char *path );
-void    StripExtension( char *path );
-
-void    ExtractFilePath( const char *path, char *dest );
-void    ExtractFileBase( const char *path, char *dest );
-void    ExtractFileExtension( const char *path, char *dest );
-
-int     ParseNum( const char *str );
-/*
-   void Sys_Printf (const char *text, ...);
-   void Sys_FPrintf (int flag, const char *text, ...);
-   void        Error( const char *error, ... );
- */
-short   BigShort( short l );
-short   LittleShort( short l );
-int     BigLong( int l );
-int     LittleLong( int l );
-float   BigFloat( float l );
-float   LittleFloat( float l );
-
-
-char *COM_Parse( char *data );
-
-extern char com_token[1024];
-extern qboolean com_eof;
-
-char *copystring( const char *s );
-
-
-void CRC_Init( unsigned short *crcvalue );
-void CRC_ProcessByte( unsigned short *crcvalue, byte data );
-unsigned short CRC_Value( unsigned short crcvalue );
-
-void    CreatePath( const char *path );
-void    QCopyFile( const char *from, const char *to );
-
-extern qboolean archive;
-extern char archivedir[1024];
-
-extern qboolean g_dokeypress;
-
-// sleep for the given amount of milliseconds
-void Sys_Sleep( int n );
-
-// for compression routines
-typedef struct
-{
-       byte    *data;
-       int count;
-} cblock_t;
-
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/common/her2_threads.h b/tools/quake2/qdata_heretic2/common/her2_threads.h
deleted file mode 100644 (file)
index 6027a69..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-#ifndef _THREADS_H
-
-#define _THREADS_H
-
-
-extern int numthreads;
-
-void ThreadSetDefault( void );
-int GetThreadWork( void );
-void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )( int ) );
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) );
-void ThreadLock( void );
-void ThreadUnlock( void );
-
-#endif //_THREADS_H
diff --git a/tools/quake2/qdata_heretic2/common/inout.c b/tools/quake2/qdata_heretic2/common/inout.c
deleted file mode 100644 (file)
index b6d272f..0000000
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// deal with in/out tasks, for either stdin/stdout or network/XML stream
-//
-
-#include "globaldefs.h"
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "polylib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if GDEF_OS_WINDOWS
-#include <direct.h>
-#include <windows.h>
-#endif
-
-// network broadcasting
-#include "l_net/l_net.h"
-#include "libxml/tree.h"
-
-#if GDEF_OS_WINDOWS
-HWND hwndOut = NULL;
-qboolean lookedForServer = false;
-UINT wm_BroadcastCommand = -1;
-#endif
-
-socket_t *brdcst_socket;
-netmessage_t msg;
-
-qboolean verbose = false;
-
-// our main document
-// is streamed through the network to Radiant
-// possibly written to disk at the end of the run
-//++timo FIXME: need to be global, required when creating nodes?
-xmlDocPtr doc;
-xmlNodePtr tree;
-
-// some useful stuff
-xmlNodePtr xml_NodeForVec( vec3_t v ){
-       xmlNodePtr ret;
-       char buf[1024];
-
-       sprintf( buf, "%f %f %f", v[0], v[1], v[2] );
-       ret = xmlNewNode( NULL, "point" );
-       xmlNodeAddContent( ret, buf );
-       return ret;
-}
-
-// send a node down the stream, add it to the document
-void xml_SendNode( xmlNodePtr node ){
-       xmlBufferPtr xml_buf;
-       char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
-       // this index loops through the node buffer
-       int pos = 0;
-       int size;
-
-       xmlAddChild( doc->children, node );
-
-       if ( brdcst_socket ) {
-               xml_buf = xmlBufferCreate();
-               xmlNodeDump( xml_buf, doc, node, 0, 0 );
-
-               // the XML node might be too big to fit in a single network message
-               // l_net library defines an upper limit of MAX_NETMESSAGE
-               // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
-               // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
-               while ( pos < xml_buf->use )
-               {
-                       // what size are we gonna send now?
-                       ( xml_buf->use - pos < MAX_NETMESSAGE - 10 ) ? ( size = xml_buf->use - pos ) : ( size = MAX_NETMESSAGE - 10 );
-                       //++timo just a debug thing
-                       if ( size == MAX_NETMESSAGE - 10 ) {
-                               Sys_FPrintf( SYS_NOXML, "Got to split the buffer\n" );
-                       }
-                       memcpy( xmlbuf, xml_buf->content + pos, size );
-                       xmlbuf[size] = '\0';
-                       NMSG_Clear( &msg );
-                       NMSG_WriteString( &msg, xmlbuf );
-                       Net_Send( brdcst_socket, &msg );
-                       // now that the thing is sent prepare to loop again
-                       pos += size;
-               }
-
-#if 0
-               // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
-               // we will need to split into chunks
-               // (we could also go lower level, in the end it's using send and receiv which are not size limited)
-               //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
-               //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
-
-               //++timo we need to handle the case of a buffer too big to fit in a single message
-               // try without checks for now
-               if ( xml_buf->use > MAX_NETMESSAGE - 10 ) {
-                       // if we send that we are probably gonna break the stream at the other end..
-                       // and Error will call right there
-                       //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-                       Sys_FPrintf( SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use );
-                       xml_buf->content[xml_buf->use] = '\0'; //++timo this corrupts the buffer but we don't care it's for printing
-                       Sys_FPrintf( SYS_NOXML, xml_buf->content );
-
-               }
-
-               size = xml_buf->use;
-               memcpy( xmlbuf, xml_buf->content, size );
-               xmlbuf[size] = '\0';
-               NMSG_Clear( &msg );
-               NMSG_WriteString( &msg, xmlbuf );
-               Net_Send( brdcst_socket, &msg );
-#endif
-
-               xmlBufferFree( xml_buf );
-       }
-}
-
-void xml_Select( char *msg, int entitynum, int brushnum, qboolean bError ){
-       xmlNodePtr node, select;
-       char buf[1024];
-       char level[2];
-
-       // now build a proper "select" XML node
-       sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
-       node = xmlNewNode( NULL, "select" );
-       xmlNodeAddContent( node, buf );
-       level[0] = (int)'0' + ( bError ? SYS_ERR : SYS_WRN )  ;
-       level[1] = 0;
-       xmlSetProp( node, "level", (char *)&level );
-       // a 'select' information
-       sprintf( buf, "%i %i", entitynum, brushnum );
-       select = xmlNewNode( NULL, "brush" );
-       xmlNodeAddContent( select, buf );
-       xmlAddChild( node, select );
-       xml_SendNode( node );
-
-       sprintf( buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg );
-       if ( bError ) {
-               Error( buf );
-       }
-       else{
-               Sys_FPrintf( SYS_NOXML, "%s\n", buf );
-       }
-
-}
-
-void xml_Point( char *msg, vec3_t pt ){
-       xmlNodePtr node, point;
-       char buf[1024];
-       char level[2];
-
-       node = xmlNewNode( NULL, "pointmsg" );
-       xmlNodeAddContent( node, msg );
-       level[0] = (int)'0' + SYS_ERR;
-       level[1] = 0;
-       xmlSetProp( node, "level", (char *)&level );
-       // a 'point' node
-       sprintf( buf, "%g %g %g", pt[0], pt[1], pt[2] );
-       point = xmlNewNode( NULL, "point" );
-       xmlNodeAddContent( point, buf );
-       xmlAddChild( node, point );
-       xml_SendNode( node );
-
-       sprintf( buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2] );
-       Error( buf );
-}
-
-#define WINDING_BUFSIZE 2048
-void xml_Winding( char *msg, vec3_t p[], int numpoints, qboolean die ){
-       xmlNodePtr node, winding;
-       char buf[WINDING_BUFSIZE];
-       char smlbuf[128];
-       char level[2];
-       int i;
-
-       node = xmlNewNode( NULL, "windingmsg" );
-       xmlNodeAddContent( node, msg );
-       level[0] = (int)'0' + SYS_ERR;
-       level[1] = 0;
-       xmlSetProp( node, "level", (char *)&level );
-       // a 'winding' node
-       sprintf( buf, "%i ", numpoints );
-       for ( i = 0; i < numpoints; i++ )
-       {
-               sprintf( smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2] );
-               // don't overflow
-               if ( strlen( buf ) + strlen( smlbuf ) > WINDING_BUFSIZE ) {
-                       break;
-               }
-               strcat( buf, smlbuf );
-       }
-
-       winding = xmlNewNode( NULL, "winding" );
-       xmlNodeAddContent( winding, buf );
-       xmlAddChild( node, winding );
-       xml_SendNode( node );
-
-       if ( die ) {
-               Error( msg );
-       }
-       else
-       {
-               Sys_Printf( msg );
-               Sys_Printf( "\n" );
-       }
-}
-
-// in include
-#include "stream_version.h"
-
-void Broadcast_Setup( const char *dest ){
-       address_t address;
-       char sMsg[1024];
-
-       Net_Setup();
-       Net_StringToAddress( (char *)dest, &address );
-       brdcst_socket = Net_Connect( &address, 0 );
-       if ( brdcst_socket ) {
-               // send in a header
-               sprintf( sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">" );
-               NMSG_Clear( &msg );
-               NMSG_WriteString( &msg, sMsg );
-               Net_Send( brdcst_socket, &msg );
-       }
-}
-
-void Broadcast_Shutdown(){
-       if ( brdcst_socket ) {
-               Sys_Printf( "Disconnecting\n" );
-               Net_Disconnect( brdcst_socket );
-               brdcst_socket = NULL;
-       }
-}
-
-// all output ends up through here
-void FPrintf( int flag, char *buf ){
-       xmlNodePtr node;
-       static qboolean bGotXML = false;
-       char level[2];
-
-       printf( "%s", buf );
-
-       // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
-       if ( flag == SYS_NOXML ) {
-               return;
-       }
-
-       // ouput an XML file of the run
-       // use the DOM interface to build a tree
-       /*
-          <message level='flag'>
-          message string
-          .. various nodes to describe corresponding geometry ..
-          </message>
-        */
-       if ( !bGotXML ) {
-               // initialize
-               doc = xmlNewDoc( "1.0" );
-               doc->children = xmlNewDocRawNode( doc, NULL, "q3map_feedback", NULL );
-               bGotXML = true;
-       }
-       node = xmlNewNode( NULL, "message" );
-       xmlNodeAddContent( node, buf );
-       level[0] = (int)'0' + flag;
-       level[1] = 0;
-       xmlSetProp( node, "level", (char *)&level );
-
-       xml_SendNode( node );
-}
-
-#ifdef DBG_XML
-void DumpXML(){
-       xmlSaveFile( "XMLDump.xml", doc );
-}
-#endif
-
-void Sys_FPrintf( int flag, const char *format, ... ){
-       char out_buffer[4096];
-       va_list argptr;
-
-       if ( ( flag == SYS_VRB ) && ( verbose == false ) ) {
-               return;
-       }
-
-       va_start( argptr, format );
-       vsprintf( out_buffer, format, argptr );
-       va_end( argptr );
-
-       FPrintf( flag, out_buffer );
-}
-
-void Sys_Printf( const char *format, ... ){
-       char out_buffer[4096];
-       va_list argptr;
-
-       va_start( argptr, format );
-       vsprintf( out_buffer, format, argptr );
-       va_end( argptr );
-
-       FPrintf( SYS_STD, out_buffer );
-}
-
-/*
-   =================
-   Error
-
-   For abnormal program terminations
-   =================
- */
-void Error( const char *error, ... ){
-       char out_buffer[4096];
-       char tmp[4096];
-       va_list argptr;
-
-       va_start( argptr,error );
-       vsprintf( tmp, error, argptr );
-       va_end( argptr );
-
-       sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-       FPrintf( SYS_ERR, out_buffer );
-
-#ifdef DBG_XML
-       DumpXML();
-#endif
-
-       //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
-       // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
-       Sys_Sleep( 1000 );
-
-       Broadcast_Shutdown();
-
-       exit( 1 );
-}
diff --git a/tools/quake2/qdata_heretic2/common/inout.h b/tools/quake2/qdata_heretic2/common/inout.h
deleted file mode 100644 (file)
index 934189f..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __INOUT__
-#define __INOUT__
-
-#include "globaldefs.h"
-// inout is the only stuff relying on xml, include the headers there
-#include "libxml/tree.h"
-#include "mathlib.h"
-
-// some useful xml routines
-xmlNodePtr xml_NodeForVec( vec3_t v );
-void xml_SendNode( xmlNodePtr node );
-// print a message in q3map output and send the corresponding select information down the xml stream
-// bError: do we end with an error on this one or do we go ahead?
-void xml_Select( char *msg, int entitynum, int brushnum, qboolean bError );
-// end q3map with an error message and send a point information in the xml stream
-// note: we might want to add a boolean to use this as a warning or an error thing..
-void xml_Winding( char *msg, vec3_t p[], int numpoints, qboolean die );
-void xml_Point( char *msg, vec3_t pt );
-
-extern qboolean bNetworkBroadcast;
-void Broadcast_Setup( const char *dest );
-void Broadcast_Shutdown();
-
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-#define SYS_NOXML 4 // don't send that down the XML stream
-
-extern qboolean verbose;
-void Sys_Printf( const char *text, ... );
-void Sys_FPrintf( int flag, const char *text, ... );
-void Error( const char *error, ... );
-
-#if GDEF_DEBUG
-#define DBG_XML 1
-#endif
-
-#ifdef DBG_XML
-void DumpXML();
-#endif
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.c b/tools/quake2/qdata_heretic2/common/l3dslib.c
deleted file mode 100644 (file)
index 708577a..0000000
+++ /dev/null
@@ -1,478 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// l3dslib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "l3dslib.h"
-#include "token.h"
-#include "fmodel.h"
-#include "bspfile.h"
-
-#define MAIN3DS       0x4D4D
-#define EDIT3DS       0x3D3D  // this is the start of the editor config
-#define EDIT_OBJECT   0x4000
-#define OBJ_TRIMESH   0x4100
-#define TRI_VERTEXL   0x4110
-#define TRI_FACEL1    0x4120
-
-#define MAXVERTS    2000
-
-typedef struct {
-       int v[4];
-} tri;
-
-float fverts[MAXVERTS][3];
-tri tris[MAXTRIANGLES];
-
-int bytesread, level, numtris, totaltris;
-int vertsfound, trisfound;
-
-triangle_t  *ptri;
-
-
-
-void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles ){
-       int pos, bit, i;
-
-       if ( nodesList ) {
-               *num_mesh_nodes = 1;
-               memset( &( *nodesList )[0], 0, sizeof( mesh_node_t ) );
-               strcpy( ( *nodesList )[0].name, "default" );
-
-               // set all of the tris to be used for the top node
-               for ( i = 0; i < ( *numtriangles ); i++ )
-               {
-                       pos = ( i ) >> 3;
-                       bit = 1 << ( ( i ) & 7 );
-
-                       ( *nodesList )[0].tris[pos] |= bit;
-               }
-       }
-}
-
-
-// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
-// start out with a vertex pool and vertex indices for triangles, we have to convert
-// to raw, explicit triangles
-void StoreAliasTriangles( void ){
-       int i, j, k;
-
-       if ( ( totaltris + numtris ) > MAXTRIANGLES ) {
-               Error( "Error: Too many triangles" );
-       }
-
-       for ( i = 0; i < numtris ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               ptri[i + totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
-                       }
-               }
-       }
-
-       totaltris += numtris;
-       numtris = 0;
-       vertsfound = 0;
-       trisfound = 0;
-}
-
-
-int ParseVertexL( FILE *input ){
-       int i, j, startbytesread, numverts;
-       unsigned short tshort;
-
-       if ( vertsfound ) {
-               Error( "Error: Multiple vertex chunks" );
-       }
-
-       vertsfound = 1;
-       startbytesread = bytesread;
-
-       if ( feof( input ) ) {
-               Error( "Error: unexpected end of file" );
-       }
-
-       fread( &tshort, sizeof( tshort ), 1, input );
-       bytesread += sizeof( tshort );
-       numverts = (int)tshort;
-
-       if ( numverts > MAXVERTS ) {
-               Error( "Error: Too many vertices" );
-       }
-
-       for ( i = 0 ; i < numverts ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       if ( feof( input ) ) {
-                               Error( "Error: unexpected end of file" );
-                       }
-
-                       fread( &fverts[i][j], sizeof( float ), 1, input );
-                       bytesread += sizeof( float );
-               }
-       }
-
-       if ( vertsfound && trisfound ) {
-               StoreAliasTriangles();
-       }
-
-       return bytesread - startbytesread;
-}
-
-
-int ParseFaceL1( FILE *input ){
-
-       int i, j, startbytesread;
-       unsigned short tshort;
-
-       if ( trisfound ) {
-               Error( "Error: Multiple face chunks" );
-       }
-
-       trisfound = 1;
-       startbytesread = bytesread;
-
-       if ( feof( input ) ) {
-               Error( "Error: unexpected end of file" );
-       }
-
-       fread( &tshort, sizeof( tshort ), 1, input );
-       bytesread += sizeof( tshort );
-       numtris = (int)tshort;
-
-       if ( numtris > MAXTRIANGLES ) {
-               Error( "Error: Too many triangles" );
-       }
-
-       for ( i = 0 ; i < numtris ; i++ )
-       {
-               for ( j = 0 ; j < 4 ; j++ )
-               {
-                       if ( feof( input ) ) {
-                               Error( "Error: unexpected end of file" );
-                       }
-
-                       fread( &tshort, sizeof( tshort ), 1, input );
-                       bytesread += sizeof( tshort );
-                       tris[i].v[j] = (int)tshort;
-               }
-       }
-
-       if ( vertsfound && trisfound ) {
-               StoreAliasTriangles();
-       }
-
-       return bytesread - startbytesread;
-}
-
-
-int ParseChunk( FILE *input ){
-#define BLOCK_SIZE  4096
-       char temp[BLOCK_SIZE];
-       unsigned short type;
-       int i, length, w, t, retval;
-
-       level++;
-       retval = 0;
-
-// chunk type
-       if ( feof( input ) ) {
-               Error( "Error: unexpected end of file" );
-       }
-
-       fread( &type, sizeof( type ), 1, input );
-       bytesread += sizeof( type );
-
-// chunk length
-       if ( feof( input ) ) {
-               Error( "Error: unexpected end of file" );
-       }
-
-       fread( &length, sizeof( length ), 1, input );
-       bytesread += sizeof( length );
-       w = length - 6;
-
-// process chunk if we care about it, otherwise skip it
-       switch ( type )
-       {
-       case TRI_VERTEXL:
-               w -= ParseVertexL( input );
-               goto ParseSubchunk;
-
-       case TRI_FACEL1:
-               w -= ParseFaceL1( input );
-               goto ParseSubchunk;
-
-       case EDIT_OBJECT:
-               // read the name
-               i = 0;
-
-               do
-               {
-                       if ( feof( input ) ) {
-                               Error( "Error: unexpected end of file" );
-                       }
-
-                       fread( &temp[i], 1, 1, input );
-                       i++;
-                       w--;
-                       bytesread++;
-               } while ( temp[i - 1] );
-
-       case MAIN3DS:
-       case OBJ_TRIMESH:
-       case EDIT3DS:
-               // parse through subchunks
-ParseSubchunk:
-               while ( w > 0 )
-               {
-                       w -= ParseChunk( input );
-               }
-
-               retval = length;
-               goto Done;
-
-       default:
-               // skip other chunks
-               while ( w > 0 )
-               {
-                       t = w;
-
-                       if ( t > BLOCK_SIZE ) {
-                               t = BLOCK_SIZE;
-                       }
-
-                       if ( feof( input ) ) {
-                               Error( "Error: unexpected end of file" );
-                       }
-
-                       fread( &temp, t, 1, input );
-                       bytesread += t;
-
-                       w -= t;
-               }
-
-               retval = length;
-               goto Done;
-       }
-
-Done:
-       level--;
-       return retval;
-}
-
-
-void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
-       FILE        *input;
-       short int tshort;
-
-       if ( nodesList ) {
-               *num_mesh_nodes = 0;
-               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-       }
-
-       bytesread = 0;
-       level = 0;
-       numtris = 0;
-       totaltris = 0;
-       vertsfound = 0;
-       trisfound = 0;
-
-       if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
-               fprintf( stderr,"reader: could not open file '%s'\n", filename );
-               exit( 0 );
-       }
-
-       fread( &tshort, sizeof( tshort ), 1, input );
-
-// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
-// no MAIN3DS
-       if ( ( tshort != MAIN3DS ) && ( tshort != EDIT3DS ) ) {
-               fprintf( stderr,"File is not a 3DS file.\n" );
-               exit( 0 );
-       }
-
-// back to top of file so we can parse the first chunk descriptor
-       fseek( input, 0, SEEK_SET );
-
-       ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
-
-       *pptri = ptri;
-
-// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
-// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
-       ParseChunk( input );
-
-       if ( vertsfound || trisfound ) {
-               Error( "Incomplete triangle set" );
-       }
-
-       *numtriangles = totaltris;
-
-       fclose( input );
-
-       DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
-}
-
-//==========================================================================
-//
-// LoadASC
-//
-//==========================================================================
-
-void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
-       int i, j;
-       int vertexCount;
-       struct
-       {
-               float v[3];
-       }           *vList;
-       int triCount;
-       triangle_t  *tList;
-       float x, y, z;
-//     float           x2, y2, z2;
-//     float           rx, ry, rz;
-       qboolean goodObject;
-
-       if ( nodesList ) {
-               *num_mesh_nodes = 0;
-               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-       }
-
-       TK_OpenSource( fileName );
-
-       goodObject = false;
-       while ( goodObject == false )
-       {
-               TK_Beyond( TK_C_NAMED );
-               TK_Beyond( TK_OBJECT );
-               TK_Beyond( TK_C_TRI );
-               TK_Beyond( TK_MESH );
-               TK_BeyondRequire( TK_C_VERTICES, TK_COLON );
-               TK_FetchRequire( TK_INTNUMBER );
-               vertexCount = tk_IntNumber;
-               if ( vertexCount > 0 ) {
-                       goodObject = true;
-               }
-       }
-       TK_BeyondRequire( TK_C_FACES, TK_COLON );
-       TK_FetchRequire( TK_INTNUMBER );
-       triCount = tk_IntNumber;
-       if ( triCount >= MAXTRIANGLES ) {
-               Error( "Too many triangles in file %s\n", fileName );
-       }
-       *triangleCount = triCount;
-       tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
-       *triList = tList;
-
-       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
-       TK_BeyondRequire( TK_C_VERTEX, TK_LIST );
-
-/*     rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
-    //rx = (rotation[0]/360.0)*2.0*M_PI;
-    ry = (rotation[1]/360.0)*2.0*M_PI;
-    rz = (rotation[2]/360.0)*2.0*M_PI;
- */
-       vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
-       for ( i = 0; i < vertexCount; i++ )
-       {
-               TK_BeyondRequire( TK_C_VERTEX, TK_INTNUMBER );
-               if ( tk_IntNumber != i ) {
-                       Error( "File '%s', line %d:\nVertex index mismatch.\n",
-                                  tk_SourceName, tk_Line );
-               }
-               TK_FetchRequireFetch( TK_COLON );
-
-               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
-               x = tk_FloatNumber;
-               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
-               y = tk_FloatNumber;
-               TK_BeyondRequire( TK_COLON, TK_FLOATNUMBER );
-               z = tk_FloatNumber;
-
-/*             x2 = x*cos(rz)+y*sin(rz);
-        y2 = -x*sin(rz)+y*cos(rz);
-        x = x2;
-        y = y2;
-        y2 = y*cos(rx)+z*sin(rx);
-        z2 = -y*sin(rx)+z*cos(rx);
-        y = y2;
-        z = z2;
-        x2 = x*cos(ry)-z*sin(ry);
-        z2 = x*sin(ry)+z*cos(ry);
-        x = x2;
-        z = z2;
- */
-               vList[i].v[0] = x;
-               vList[i].v[1] = y;
-               vList[i].v[2] = z;
-       }
-       TK_BeyondRequire( TK_C_FACE, TK_LIST );
-       for ( i = 0; i < triCount; i++ )
-       {
-               TK_BeyondRequire( TK_C_FACE, TK_INTNUMBER );
-               if ( tk_IntNumber != i ) {
-                       Error( "File '%s', line %d:\nTriangle index mismatch.\n",
-                                  tk_SourceName, tk_Line );
-               }
-               for ( j = 0; j < 3; j++ )
-               {
-                       TK_BeyondRequire( TK_IDENTIFIER, TK_COLON );
-                       TK_FetchRequire( TK_INTNUMBER );
-                       if ( tk_IntNumber >= vertexCount ) {
-                               Error( "File '%s', line %d:\nVertex number"
-                                          " > vertexCount: %d\n", tk_SourceName, tk_Line,
-                                          tk_IntNumber );
-                       }
-                       tList[i].verts[2 - j][0] = vList[tk_IntNumber].v[0];
-                       tList[i].verts[2 - j][1] = vList[tk_IntNumber].v[1];
-                       tList[i].verts[2 - j][2] = vList[tk_IntNumber].v[2];
-#ifdef _QDATA
-                       tList[i].indicies[2 - j] = tk_IntNumber;
-#endif
-               }
-
-/*             printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-            "  v2: %f, %f, %f\n", i,
-            tList[i].verts[0][0],
-            tList[i].verts[0][1],
-            tList[i].verts[0][2],
-            tList[i].verts[1][0],
-            tList[i].verts[1][1],
-            tList[i].verts[1][2],
-            tList[i].verts[2][0],
-            tList[i].verts[2][1],
-            tList[i].verts[2][2]);
- */
-       }
-
-       DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
-}
diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.h b/tools/quake2/qdata_heretic2/common/l3dslib.h
deleted file mode 100644 (file)
index 0b1b537..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// l3dslib.h: header file for loading triangles from a 3DS triangle file
-//
-void DefaultNodesList( mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles );
-
-void Load3DSTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes );
-void LoadASC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes );
diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.c b/tools/quake2/qdata_heretic2/common/lbmlib.c
deleted file mode 100644 (file)
index 7eabd19..0000000
+++ /dev/null
@@ -1,1043 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// lbmlib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "lbmlib.h"
-
-// Ups the palette values so no pixels except 0 appear transparent
-// Need a value of 8 to cater for 16bit renderers
-
-typedef struct
-{
-       byte r;
-       byte g;
-       byte b;
-} paletteRGB_t;
-
-
-void CorrectPalette( byte *pal ){
-       paletteRGB_t    *p;
-
-       p = (paletteRGB_t *)pal;
-       // Color 0 always transparent
-       p->r = 0;
-       p->g = 0;
-       p->b = 0;
-}
-
-/*
-   ============================================================================
-
-                        LBM STUFF
-
-   ============================================================================
- */
-
-
-typedef unsigned char UBYTE;
-//conflicts with windows typedef short                 WORD;
-typedef unsigned short UWORD;
-typedef long LONG;
-
-typedef enum
-{
-       ms_none,
-       ms_mask,
-       ms_transcolor,
-       ms_lasso
-} mask_t;
-
-typedef enum
-{
-       cm_none,
-       cm_rle1
-} compress_t;
-
-typedef struct
-{
-       UWORD w,h;
-       short x,y;
-       UBYTE nPlanes;
-       UBYTE masking;
-       UBYTE compression;
-       UBYTE pad1;
-       UWORD transparentColor;
-       UBYTE xAspect,yAspect;
-       short pageWidth,pageHeight;
-} bmhd_t;
-
-extern bmhd_t bmhd;                         // will be in native byte order
-
-
-
-#define FORMID ( 'F' + ( 'O' << 8 ) + ( (int)'R' << 16 ) + ( (int)'M' << 24 ) )
-#define ILBMID ( 'I' + ( 'L' << 8 ) + ( (int)'B' << 16 ) + ( (int)'M' << 24 ) )
-#define PBMID  ( 'P' + ( 'B' << 8 ) + ( (int)'M' << 16 ) + ( (int)' ' << 24 ) )
-#define BMHDID ( 'B' + ( 'M' << 8 ) + ( (int)'H' << 16 ) + ( (int)'D' << 24 ) )
-#define BODYID ( 'B' + ( 'O' << 8 ) + ( (int)'D' << 16 ) + ( (int)'Y' << 24 ) )
-#define CMAPID ( 'C' + ( 'M' << 8 ) + ( (int)'A' << 16 ) + ( (int)'P' << 24 ) )
-
-
-bmhd_t bmhd;
-
-int    Align( int l ){
-       if ( l & 1 ) {
-               return l + 1;
-       }
-       return l;
-}
-
-
-
-/*
-   ================
-   LBMRLEdecompress
-
-   Source must be evenly aligned!
-   ================
- */
-byte  *LBMRLEDecompress( byte *source,byte *unpacked, int bpwidth ){
-       int count;
-       byte b,rept;
-
-       count = 0;
-
-       do
-       {
-               rept = *source++;
-
-               if ( rept > 0x80 ) {
-                       rept = ( rept ^ 0xff ) + 2;
-                       b = *source++;
-                       memset( unpacked,b,rept );
-                       unpacked += rept;
-               }
-               else if ( rept < 0x80 ) {
-                       rept++;
-                       memcpy( unpacked,source,rept );
-                       unpacked += rept;
-                       source += rept;
-               }
-               else{
-                       rept = 0;               // rept of 0x80 is NOP
-
-               }
-               count += rept;
-
-       } while ( count < bpwidth );
-
-       if ( count > bpwidth ) {
-               Error( "Decompression exceeded width!\n" );
-       }
-
-
-       return source;
-}
-
-
-/*
-   =================
-   LoadLBM
-   =================
- */
-void LoadLBM( char *filename, byte **picture, byte **palette ){
-       byte    *LBMbuffer, *picbuffer, *cmapbuffer;
-       int y;
-       byte    *LBM_P, *LBMEND_P;
-       byte    *pic_p;
-       byte    *body_p;
-
-       int formtype,formlength;
-       int chunktype,chunklength;
-
-// qiet compiler warnings
-       picbuffer = NULL;
-       cmapbuffer = NULL;
-
-//
-// load the LBM
-//
-       LoadFile( filename, (void **)&LBMbuffer );
-
-//
-// parse the LBM header
-//
-       LBM_P = LBMbuffer;
-       if ( *(int *)LBMbuffer != LittleLong( FORMID ) ) {
-               Error( "No FORM ID at start of file!\n" );
-       }
-
-       LBM_P += 4;
-       formlength = BigLong( *(int *)LBM_P );
-       LBM_P += 4;
-       LBMEND_P = LBM_P + Align( formlength );
-
-       formtype = LittleLong( *(int *)LBM_P );
-
-       if ( formtype != ILBMID && formtype != PBMID ) {
-               Error( "Unrecognized form type: %c%c%c%c\n", formtype & 0xff
-                          ,( formtype >> 8 ) & 0xff,( formtype >> 16 ) & 0xff,( formtype >> 24 ) & 0xff );
-       }
-
-       LBM_P += 4;
-
-//
-// parse chunks
-//
-
-       while ( LBM_P < LBMEND_P )
-       {
-               chunktype = LBM_P[0] + ( LBM_P[1] << 8 ) + ( LBM_P[2] << 16 ) + ( LBM_P[3] << 24 );
-               LBM_P += 4;
-               chunklength = LBM_P[3] + ( LBM_P[2] << 8 ) + ( LBM_P[1] << 16 ) + ( LBM_P[0] << 24 );
-               LBM_P += 4;
-
-               switch ( chunktype )
-               {
-               case BMHDID:
-                       memcpy( &bmhd,LBM_P,sizeof( bmhd ) );
-                       bmhd.w = BigShort( bmhd.w );
-                       bmhd.h = BigShort( bmhd.h );
-                       bmhd.x = BigShort( bmhd.x );
-                       bmhd.y = BigShort( bmhd.y );
-                       bmhd.pageWidth = BigShort( bmhd.pageWidth );
-                       bmhd.pageHeight = BigShort( bmhd.pageHeight );
-                       break;
-
-               case CMAPID:
-                       cmapbuffer = malloc( 768 );
-                       memset( cmapbuffer, 0, 768 );
-                       memcpy( cmapbuffer, LBM_P, chunklength );
-                       CorrectPalette( cmapbuffer );
-                       break;
-
-               case BODYID:
-                       body_p = LBM_P;
-
-                       pic_p = picbuffer = malloc( bmhd.w * bmhd.h );
-                       if ( formtype == PBMID ) {
-                               //
-                               // unpack PBM
-                               //
-                               for ( y = 0 ; y < bmhd.h ; y++, pic_p += bmhd.w )
-                               {
-                                       if ( bmhd.compression == cm_rle1 ) {
-                                               body_p = LBMRLEDecompress( (byte *)body_p
-                                                                                                  , pic_p, bmhd.w );
-                                       }
-                                       else if ( bmhd.compression == cm_none ) {
-                                               memcpy( pic_p,body_p,bmhd.w );
-                                               body_p += Align( bmhd.w );
-                                       }
-                               }
-
-                       }
-                       else
-                       {
-                               //
-                               // unpack ILBM
-                               //
-                               Error( "%s is an interlaced LBM, not packed", filename );
-                       }
-                       break;
-               }
-
-               LBM_P += Align( chunklength );
-       }
-
-       free( LBMbuffer );
-
-       *picture = picbuffer;
-
-       if ( palette ) {
-               *palette = cmapbuffer;
-       }
-}
-
-
-/*
-   ============================================================================
-
-                            WRITE LBM
-
-   ============================================================================
- */
-
-/*
-   ==============
-   WriteLBMfile
-   ==============
- */
-void WriteLBMfile( char *filename, byte *data,
-                                  int width, int height, byte *palette ){
-       byte    *lbm, *lbmptr;
-       int    *formlength, *bmhdlength, *cmaplength, *bodylength;
-       int length;
-       bmhd_t basebmhd;
-
-       lbm = lbmptr = malloc( width * height + 1000 );
-
-//
-// start FORM
-//
-       *lbmptr++ = 'F';
-       *lbmptr++ = 'O';
-       *lbmptr++ = 'R';
-       *lbmptr++ = 'M';
-
-       formlength = (int*)lbmptr;
-       lbmptr += 4;                      // leave space for length
-
-       *lbmptr++ = 'P';
-       *lbmptr++ = 'B';
-       *lbmptr++ = 'M';
-       *lbmptr++ = ' ';
-
-//
-// write BMHD
-//
-       *lbmptr++ = 'B';
-       *lbmptr++ = 'M';
-       *lbmptr++ = 'H';
-       *lbmptr++ = 'D';
-
-       bmhdlength = (int *)lbmptr;
-       lbmptr += 4;                      // leave space for length
-
-       memset( &basebmhd,0,sizeof( basebmhd ) );
-       basebmhd.w = BigShort( (short)width );
-       basebmhd.h = BigShort( (short)height );
-       basebmhd.nPlanes = BigShort( 8 );
-       basebmhd.xAspect = BigShort( 5 );
-       basebmhd.yAspect = BigShort( 6 );
-       basebmhd.pageWidth = BigShort( (short)width );
-       basebmhd.pageHeight = BigShort( (short)height );
-
-       memcpy( lbmptr,&basebmhd,sizeof( basebmhd ) );
-       lbmptr += sizeof( basebmhd );
-
-       length = lbmptr - (byte *)bmhdlength - 4;
-       *bmhdlength = BigLong( length );
-       if ( length & 1 ) {
-               *lbmptr++ = 0;          // pad chunk to even offset
-
-       }
-//
-// write CMAP
-//
-       *lbmptr++ = 'C';
-       *lbmptr++ = 'M';
-       *lbmptr++ = 'A';
-       *lbmptr++ = 'P';
-
-       cmaplength = (int *)lbmptr;
-       lbmptr += 4;                      // leave space for length
-
-       memcpy( lbmptr,palette,768 );
-       lbmptr += 768;
-
-       length = lbmptr - (byte *)cmaplength - 4;
-       *cmaplength = BigLong( length );
-       if ( length & 1 ) {
-               *lbmptr++ = 0;          // pad chunk to even offset
-
-       }
-//
-// write BODY
-//
-       *lbmptr++ = 'B';
-       *lbmptr++ = 'O';
-       *lbmptr++ = 'D';
-       *lbmptr++ = 'Y';
-
-       bodylength = (int *)lbmptr;
-       lbmptr += 4;                      // leave space for length
-
-       memcpy( lbmptr,data,width * height );
-       lbmptr += width * height;
-
-       length = lbmptr - (byte *)bodylength - 4;
-       *bodylength = BigLong( length );
-       if ( length & 1 ) {
-               *lbmptr++ = 0;          // pad chunk to even offset
-
-       }
-//
-// done
-//
-       length = lbmptr - (byte *)formlength - 4;
-       *formlength = BigLong( length );
-       if ( length & 1 ) {
-               *lbmptr++ = 0;          // pad chunk to even offset
-
-       }
-//
-// write output file
-//
-       SaveFile( filename, lbm, lbmptr - lbm );
-       free( lbm );
-}
-
-
-/*
-   ============================================================================
-
-   LOAD PCX
-
-   ============================================================================
- */
-
-typedef struct
-{
-       char manufacturer;
-       char version;
-       char encoding;
-       char bits_per_pixel;
-       unsigned short xmin,ymin,xmax,ymax;
-       unsigned short hres,vres;
-       unsigned char palette[48];
-       char reserved;
-       char color_planes;
-       unsigned short bytes_per_line;
-       unsigned short palette_type;
-       char filler[58];
-       unsigned char data;             // unbounded
-} pcx_t;
-
-/*
-   ==============
-   LoadPCX
-   ==============
- */
-void LoadPCX( char *filename, byte **pic, byte **palette, int *width, int *height ){
-       byte    *raw;
-       pcx_t   *pcx;
-       int x, y;
-       int len;
-       int dataByte, runLength;
-       byte    *out, *pix;
-
-       //
-       // load the file
-       //
-       len = LoadFile( filename, (void **)&raw );
-
-       //
-       // parse the PCX file
-       //
-       pcx = (pcx_t *)raw;
-       raw = &pcx->data;
-
-       pcx->xmin = LittleShort( pcx->xmin );
-       pcx->ymin = LittleShort( pcx->ymin );
-       pcx->xmax = LittleShort( pcx->xmax );
-       pcx->ymax = LittleShort( pcx->ymax );
-       pcx->hres = LittleShort( pcx->hres );
-       pcx->vres = LittleShort( pcx->vres );
-       pcx->bytes_per_line = LittleShort( pcx->bytes_per_line );
-       pcx->palette_type = LittleShort( pcx->palette_type );
-
-       if ( pcx->manufacturer != 0x0a
-                || pcx->version != 5
-                || pcx->encoding != 1
-                || pcx->bits_per_pixel != 8
-                || pcx->xmax >= 640
-                || pcx->ymax >= 480 ) {
-               Error( "Bad pcx file %s", filename );
-       }
-
-       if ( palette ) {
-               *palette = malloc( 768 );
-               memcpy( *palette, (byte *)pcx + len - 768, 768 );
-               CorrectPalette( *palette );
-       }
-
-       if ( width ) {
-               *width = pcx->xmax + 1;
-       }
-       if ( height ) {
-               *height = pcx->ymax + 1;
-       }
-
-       if ( !pic ) {
-               return;
-       }
-
-       out = malloc( ( pcx->ymax + 1 ) * ( pcx->xmax + 1 ) );
-       if ( !out ) {
-               Error( "Skin_Cache: couldn't allocate" );
-       }
-
-       *pic = out;
-
-       pix = out;
-
-       for ( y = 0 ; y <= pcx->ymax ; y++, pix += pcx->xmax + 1 )
-       {
-               for ( x = 0 ; x <= pcx->xmax ; )
-               {
-                       dataByte = *raw++;
-
-                       if ( ( dataByte & 0xC0 ) == 0xC0 ) {
-                               runLength = dataByte & 0x3F;
-                               dataByte = *raw++;
-                       }
-                       else{
-                               runLength = 1;
-                       }
-
-                       while ( runLength-- > 0 )
-                               pix[x++] = dataByte;
-               }
-
-       }
-
-       if ( raw - (byte *)pcx > len ) {
-               Error( "PCX file %s was malformed", filename );
-       }
-
-       free( pcx );
-}
-
-/*
-   ==============
-   WritePCXfile
-   ==============
- */
-
-void StuffPackedByte( int curRepCount, byte curByte, byte** packPtr ){
-       byte* pack;
-
-       pack = *packPtr;
-
-       while ( curRepCount > 0 )
-       {
-               if ( curRepCount == 1 ) {
-                       if ( ( curByte & 0xc0 ) != 0xc0 ) {
-                               *pack++ = curByte;
-                       }
-                       else
-                       {
-                               *pack++ = 0xc1;
-                               *pack++ = curByte;
-                       }
-                       break;
-               }
-               if ( curRepCount < 0x0040 ) {
-                       *pack++ = ( 0x00c0 | curRepCount );
-                       curRepCount = 0;
-               }
-               else
-               {
-                       *pack++ = 0xff;
-                       curRepCount -= 0x003f;
-               }
-               *pack++ = curByte;
-       }
-       *packPtr = pack;
-}
-
-void WritePCXfile( char *filename, byte *data,
-                                  int width, int height, byte *palette ){
-       int i, j, length;
-       pcx_t       *pcx;
-       byte        *pack;
-       byte curByte;
-       int curRepCount;
-
-       pcx = malloc( width * height * 2 + 1000 );
-       memset( pcx, 0, sizeof( *pcx ) );
-
-       pcx->manufacturer = 0x0a;   // PCX id
-       pcx->version = 5;           // 256 color
-       pcx->encoding = 1;      // RLE
-       pcx->bits_per_pixel = 8;        // 256 color
-       pcx->xmin = 0;
-       pcx->ymin = 0;
-       pcx->xmax = LittleShort( (short)( width - 1 ) );
-       pcx->ymax = LittleShort( (short)( height - 1 ) );
-       pcx->hres = LittleShort( (short)width );
-       pcx->vres = LittleShort( (short)height );
-       pcx->color_planes = 1;      // chunky image
-       pcx->bytes_per_line = LittleShort( (short)width );
-       pcx->palette_type = LittleShort( 1 );     // not a grey scale
-
-       // pack the image
-       pack = &pcx->data;
-
-/*     for (i=0 ; i<height ; i++)
-    {
-        for (j=0 ; j<width ; j++)
-        {
-            if ( (*data & 0xc0) != 0xc0)
-   *pack++ = *data++;
-            else
-            {
-   *pack++ = 0xc1;
-   *pack++ = *data++;
-            }
-        }
-    }
- */
-       for ( i = 0 ; i < height ; i++ )
-       {
-               curByte = *data;
-               curRepCount = 0;
-               for ( j = 0 ; j < width ; j++ )
-               {
-                       if ( *data == curByte ) {
-                               curRepCount++;
-                               data++;
-                               continue;
-                       }
-                       StuffPackedByte( curRepCount, curByte, &pack );
-                       curByte = *data++;
-                       curRepCount = 1;
-               }
-               StuffPackedByte( curRepCount, curByte, &pack );
-       }
-       // write the palette
-       *pack++ = 0x0c; // palette ID byte
-       for ( i = 0 ; i < 768 ; i++ )
-               *pack++ = *palette++;
-
-// write output file
-       length = pack - (byte *)pcx;
-       SaveFile( filename, pcx, length );
-
-       free( pcx );
-}
-
-
-/*
-   ============================================================================
-
-   LOAD IMAGE
-
-   ============================================================================
- */
-
-/*
-   ==============
-   Load256Image
-
-   Will load either an lbm or pcx, depending on extension.
-   Any of the return pointers can be NULL if you don't want them.
-   ==============
- */
-void Load256Image( char *name, byte **pixels, byte **palette,
-                                  int *width, int *height ){
-       char ext[128];
-
-       ExtractFileExtension( name, ext );
-       if ( !Q_strcasecmp( ext, "lbm" ) ) {
-               LoadLBM( name, pixels, palette );
-               if ( width ) {
-                       *width = bmhd.w;
-               }
-               if ( height ) {
-                       *height = bmhd.h;
-               }
-       }
-       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
-               LoadPCX( name, pixels, palette, width, height );
-       }
-       else{
-               Error( "%s doesn't have a known image extension", name );
-       }
-}
-
-
-/*
-   ==============
-   Save256Image
-
-   Will save either an lbm or pcx, depending on extension.
-   ==============
- */
-void Save256Image( char *name, byte *pixels, byte *palette,
-                                  int width, int height ){
-       char ext[128];
-
-       ExtractFileExtension( name, ext );
-       if ( !Q_strcasecmp( ext, "lbm" ) ) {
-               WriteLBMfile( name, pixels, width, height, palette );
-       }
-       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
-               WritePCXfile( name, pixels, width, height, palette );
-       }
-       else{
-               Error( "%s doesn't have a known image extension", name );
-       }
-}
-
-
-
-
-/*
-   ============================================================================
-
-   TARGA IMAGE
-
-   ============================================================================
- */
-
-typedef struct _TargaHeader
-{
-       unsigned char id_length, colormap_type, image_type;
-       unsigned short colormap_index, colormap_length;
-       unsigned char colormap_size;
-       unsigned short x_origin, y_origin, width, height;
-       unsigned char pixel_size, attributes;
-} TargaHeader;
-
-int fgetLittleShort( FILE *f ){
-       byte b1, b2;
-
-       b1 = fgetc( f );
-       b2 = fgetc( f );
-
-       return( (short)( b1 + ( b2 << 8 ) ) );
-}
-
-int fgetLittleLong( FILE *f ){
-       byte b1, b2, b3, b4;
-
-       b1 = fgetc( f );
-       b2 = fgetc( f );
-       b3 = fgetc( f );
-       b4 = fgetc( f );
-
-       return( b1 + ( b2 << 8 ) + ( b3 << 16 ) + ( b4 << 24 ) );
-}
-
-
-/*
-   =============
-   LoadTGA
-   =============
- */
-void LoadTGA( char *name, byte **pixels, int *width, int *height ){
-       int columns, rows, numPixels;
-       byte            *pixbuf;
-       byte            *rowBuf;
-       int row, column;
-       FILE            *fin;
-       byte            *targa_rgba;
-       TargaHeader targa_header;
-       unsigned char red, green, blue, alphabyte;
-       unsigned char packetHeader, packetSize, j;
-       int flip;
-       int mirror;
-       int rowOffset;
-       int pixDirection;
-
-       fin = fopen( name, "rb" );
-       if ( !fin ) {
-               Error( "Couldn't read %s", name );
-       }
-
-       targa_header.id_length = fgetc( fin );
-       targa_header.colormap_type = fgetc( fin );
-       targa_header.image_type = fgetc( fin );
-
-       targa_header.colormap_index = fgetLittleShort( fin );
-       targa_header.colormap_length = fgetLittleShort( fin );
-       targa_header.colormap_size = fgetc( fin );
-       targa_header.x_origin = fgetLittleShort( fin );
-       targa_header.y_origin = fgetLittleShort( fin );
-       targa_header.width = fgetLittleShort( fin );
-       targa_header.height = fgetLittleShort( fin );
-       targa_header.pixel_size = fgetc( fin );
-       targa_header.attributes = fgetc( fin );
-       flip = ( targa_header.attributes & 0x020 ) == 0;
-       mirror = ( targa_header.attributes & 0x010 ) != 0;
-
-       if ( ( targa_header.image_type != 2 ) && ( targa_header.image_type != 10 ) ) {
-               Error( "LoadTGA: Only type 2 and 10 targa RGB images supported\n" );
-       }
-
-       if ( targa_header.colormap_type || ( ( targa_header.pixel_size != 32 ) && ( targa_header.pixel_size != 24 ) ) ) {
-               Error( "Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n" );
-       }
-
-       columns = targa_header.width;
-       rows = targa_header.height;
-       numPixels = columns * rows;
-
-       if ( width ) {
-               *width = columns;
-       }
-       if ( height ) {
-               *height = rows;
-       }
-
-       if ( !pixels ) {
-               return;
-       }
-
-       targa_rgba = malloc( numPixels * 4 );
-       *pixels = targa_rgba;
-
-       if ( flip ) {
-               pixbuf = targa_rgba + ( ( rows - 1 ) * columns * 4 );
-               rowOffset = -columns * 4;
-       }
-       else
-       {
-               pixbuf = targa_rgba;
-               rowOffset = columns * 4;
-       }
-       if ( mirror ) {
-               pixDirection = -4;
-               pixbuf += ( ( columns - 1 ) * 4 );
-       }
-       else
-       {
-               pixDirection = 4;
-       }
-
-       if ( targa_header.id_length ) {
-               fseek( fin, targa_header.id_length, SEEK_CUR );  // skip TARGA image comment
-
-       }
-       if ( targa_header.image_type == 2 ) {                 // Uncompressed, RGB images
-               for ( row = 0; row < rows; row++ )
-               {
-                       rowBuf = pixbuf;
-                       for ( column = 0; column < columns; column++ )
-                       {
-                               switch ( targa_header.pixel_size )
-                               {
-                               case 24:
-                                       blue = getc( fin );
-                                       green = getc( fin );
-                                       red = getc( fin );
-                                       rowBuf[0] = red;
-                                       rowBuf[1] = green;
-                                       rowBuf[2] = blue;
-                                       rowBuf[3] = 255;
-                                       rowBuf += pixDirection;
-                                       break;
-                               case 32:
-                                       blue = getc( fin );
-                                       green = getc( fin );
-                                       red = getc( fin );
-                                       alphabyte = getc( fin );
-                                       rowBuf[0] = red;
-                                       rowBuf[1] = green;
-                                       rowBuf[2] = blue;
-                                       rowBuf[3] = alphabyte;
-                                       rowBuf += pixDirection;
-                                       break;
-                               }
-                       }
-                       pixbuf += rowOffset;
-               }
-       }
-       else if ( targa_header.image_type == 10 ) {        // Runlength encoded RGB images
-               for ( row = 0; row < rows; row++ )
-               {
-                       rowBuf = pixbuf;
-                       for ( column = 0; column < columns; )
-                       {
-                               packetHeader = getc( fin );
-                               packetSize = 1 + ( packetHeader & 0x7f );
-                               if ( packetHeader & 0x80 ) {          // run-length packet
-                                       switch ( targa_header.pixel_size )
-                                       {
-                                       case 24:
-                                               blue = getc( fin );
-                                               green = getc( fin );
-                                               red = getc( fin );
-                                               alphabyte = 255;
-                                               break;
-                                       case 32:
-                                               blue = getc( fin );
-                                               green = getc( fin );
-                                               red = getc( fin );
-                                               alphabyte = getc( fin );
-                                               break;
-                                       }
-
-                                       for ( j = 0; j < packetSize; j++ )
-                                       {
-                                               rowBuf[0] = red;
-                                               rowBuf[1] = green;
-                                               rowBuf[2] = blue;
-                                               rowBuf[3] = alphabyte;
-                                               rowBuf += pixDirection;
-                                               column++;
-                                               if ( column == columns ) {             // run spans across rows
-                                                       column = 0;
-                                                       row++;
-                                                       if ( row >= rows ) {
-                                                               goto breakOut;
-                                                       }
-                                                       pixbuf += rowOffset;
-                                                       rowBuf = pixbuf;
-                                               }
-                                       }
-                               }
-                               else
-                               {                                       // non run-length packet
-                                       for ( j = 0; j < packetSize; j++ )
-                                       {
-                                               switch ( targa_header.pixel_size )
-                                               {
-                                               case 24:
-                                                       blue = getc( fin );
-                                                       green = getc( fin );
-                                                       red = getc( fin );
-                                                       rowBuf[0] = red;
-                                                       rowBuf[1] = green;
-                                                       rowBuf[2] = blue;
-                                                       rowBuf[3] = 255;
-                                                       rowBuf += pixDirection;
-                                                       break;
-                                               case 32:
-                                                       blue = getc( fin );
-                                                       green = getc( fin );
-                                                       red = getc( fin );
-                                                       alphabyte = getc( fin );
-                                                       rowBuf[0] = red;
-                                                       rowBuf[1] = green;
-                                                       rowBuf[2] = blue;
-                                                       rowBuf[3] = alphabyte;
-                                                       rowBuf += pixDirection;
-                                                       break;
-                                               }
-                                               column++;
-                                               if ( column == columns ) {    // pixel packet run spans across rows
-                                                       column = 0;
-                                                       row++;
-                                                       if ( row >= rows ) {
-                                                               goto breakOut;
-                                                       }
-                                                       pixbuf += rowOffset;
-                                                       rowBuf = pixbuf;
-                                               }
-                                       }
-                               }
-                       }
-breakOut:;
-                       pixbuf += rowOffset;
-               }
-       }
-       fclose( fin );
-}
-
-void MergeAlpha( byte *pix, byte *alpha, byte *pal, byte **out, int width, int height ){
-       int size, i;
-       byte    *data, *src, *srca;
-
-       size = width * height;
-       data = malloc( size * 4 );
-       if ( !data ) {
-               Error( "Could not allocate memory for true color image" );
-       }
-
-       *out = data;
-       src = pix;
-       srca = alpha;
-
-       for ( i = 0; i < size; i++, src++, srca++ )
-       {
-               *data++ = pal[*src * 3 + 0];      // r
-               *data++ = pal[*src * 3 + 1];      // g
-               *data++ = pal[*src * 3 + 2];      // b
-               *data++ = *srca;                  // a
-       }
-       free( pix );
-       free( alpha );
-       free( pal );
-}
-
-/*
-   ==============
-   LoadAnyImage
-
-   Return Value:
-    false: paletted texture
-    true:  true color RGBA image (no palette)
-   ==============
- */
-qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height ){
-       char ext[128];
-       int len;
-       int alpha_width, alpha_height;
-       char alpha_name[128];
-       byte    *alpha_pixels;
-
-       ExtractFileExtension( name, ext );
-
-       if ( palette ) {
-               *palette = NULL;
-       }
-
-       if ( !Q_strcasecmp( ext, "lbm" ) ) {
-               LoadLBM( name, pixels, palette );
-               if ( width ) {
-                       *width = bmhd.w;
-               }
-               if ( height ) {
-                       *height = bmhd.h;
-               }
-               return false;
-       }
-       else if ( !Q_strcasecmp( ext, "pcx" ) ) {
-               len = strlen( name );
-               strcpy( alpha_name, name );
-               strcpy( &alpha_name[len - 4], "_a.pcx" );                 // Alpha map name (may not exist)
-
-               if ( FileExists( alpha_name ) ) {
-                       LoadPCX( name, pixels, palette, width, height );                         // Load in image
-                       LoadPCX( alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height ); // Load in alpha map
-                       if ( ( *width != alpha_width ) || ( *height != alpha_height ) ) {
-                               Error( "Alpha image dimensions not equal to graphic image dimensions" );
-                       }
-                       MergeAlpha( *pixels, alpha_pixels, *palette, pixels, *width, *height );
-                       *palette = NULL; //Merge Frees pal
-                       return true;
-               }
-               else
-               {
-                       LoadPCX( name, pixels, palette, width, height );         // Load in image
-                       return false;
-               }
-       }
-       else if ( !Q_strcasecmp( ext, "tga" ) ) {
-               LoadTGA( name, pixels, width, height );
-               if ( palette ) {
-                       *palette = NULL;
-               }
-
-               return true;
-       }
-       else{
-               Error( "%s doesn't have a known image extension", name );
-       }
-
-       return false;
-}
diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.h b/tools/quake2/qdata_heretic2/common/lbmlib.h
deleted file mode 100644 (file)
index 5ee2909..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// piclib.h
-
-
-void LoadLBM( char *filename, byte **picture, byte **palette );
-void WriteLBMfile( char *filename, byte *data, int width, int height
-                                  , byte *palette );
-void LoadPCX( char *filename, byte **picture, byte **palette, int *width, int *height );
-void WritePCXfile( char *filename, byte *data, int width, int height
-                                  , byte *palette );
-
-// loads / saves either lbm or pcx, depending on extension
-void Load256Image( char *name, byte **pixels, byte **palette,
-                                  int *width, int *height );
-void Save256Image( char *name, byte *pixels, byte *palette,
-                                  int width, int height );
-
-
-void LoadTGA( char *filename, byte **pixels, int *width, int *height );
-
-qboolean LoadAnyImage( char *name, byte **pixels, byte **palette, int *width, int *height );
diff --git a/tools/quake2/qdata_heretic2/common/mathlib.c b/tools/quake2/qdata_heretic2/common/mathlib.c
deleted file mode 100644 (file)
index 8243d86..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// mathlib.c -- math primitives
-
-#include "cmdlib.h"
-#include "mathlib.h"
-
-vec3_t vec3_origin = {0,0,0};
-
-
-double VectorLength( vec3_t v ){
-       int i;
-       double length;
-
-       length = 0;
-       for ( i = 0 ; i < 3 ; i++ )
-               length += v[i] * v[i];
-       length = sqrt( length );     // FIXME
-
-       return length;
-}
-
-qboolean VectorCompare( vec3_t v1, vec3_t v2 ){
-       int i;
-
-       for ( i = 0 ; i < 3 ; i++ )
-               if ( fabs( v1[i] - v2[i] ) > EQUAL_EPSILON ) {
-                       return false;
-               }
-
-       return true;
-}
-
-vec_t Q_rint( vec_t in ){
-       return floor( in + 0.5 );
-}
-
-void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc ){
-       vc[0] = va[0] + scale * vb[0];
-       vc[1] = va[1] + scale * vb[1];
-       vc[2] = va[2] + scale * vb[2];
-}
-
-void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross ){
-       cross[0] = v1[1] * v2[2] - v1[2] * v2[1];
-       cross[1] = v1[2] * v2[0] - v1[0] * v2[2];
-       cross[2] = v1[0] * v2[1] - v1[1] * v2[0];
-}
-
-vec_t _DotProduct( vec3_t v1, vec3_t v2 ){
-       return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
-}
-
-void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out ){
-       out[0] = va[0] - vb[0];
-       out[1] = va[1] - vb[1];
-       out[2] = va[2] - vb[2];
-}
-
-void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out ){
-       out[0] = va[0] + vb[0];
-       out[1] = va[1] + vb[1];
-       out[2] = va[2] + vb[2];
-}
-
-void _VectorCopy( vec3_t in, vec3_t out ){
-       out[0] = in[0];
-       out[1] = in[1];
-       out[2] = in[2];
-}
-
-void _VectorScale( vec3_t v, vec_t scale, vec3_t out ){
-       out[0] = v[0] * scale;
-       out[1] = v[1] * scale;
-       out[2] = v[2] * scale;
-}
-
-#if GDEF_COMPILER_MSVC
-#pragma optimize("g", off)  // went back to turning optimization off,
-                            // the bug_fix thing stopped working
-#endif
-
-vec_t VectorNormalize( vec3_t in, vec3_t out ){
-       vec_t length, ilength;
-
-       length = sqrt( in[0] * in[0] + in[1] * in[1] + in[2] * in[2] );
-       if ( length == 0 ) {
-               VectorClear( out );
-               return 0;
-       }
-
-       ilength = 1.0 / length;
-       out[0] = in[0] * ilength;
-       out[1] = in[1] * ilength;
-       out[2] = in[2] * ilength;
-
-       return length;
-}
-
-vec_t ColorNormalize( vec3_t in, vec3_t out ){
-       float max, scale;
-
-       max = in[0];
-       if ( in[1] > max ) {
-               max = in[1];
-       }
-       if ( in[2] > max ) {
-               max = in[2];
-       }
-
-       if ( max == 0 ) {
-               return 0;
-       }
-
-       scale = 1.0 / max;
-
-       VectorScale( in, scale, out );
-
-       return max;
-}
-
-#if GDEF_COMPILER_MSVC
-#pragma optimize("", on)
-#endif
-
-void VectorInverse( vec3_t v ){
-       v[0] = -v[0];
-       v[1] = -v[1];
-       v[2] = -v[2];
-}
-
-void ClearBounds( vec3_t mins, vec3_t maxs ){
-       mins[0] = mins[1] = mins[2] = 99999;
-       maxs[0] = maxs[1] = maxs[2] = -99999;
-}
-
-void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs ){
-       int i;
-       vec_t val;
-
-       for ( i = 0 ; i < 3 ; i++ )
-       {
-               val = v[i];
-               if ( val < mins[i] ) {
-                       mins[i] = val;
-               }
-               if ( val > maxs[i] ) {
-                       maxs[i] = val;
-               }
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/common/mathlib.h b/tools/quake2/qdata_heretic2/common/mathlib.h
deleted file mode 100644 (file)
index cd989ea..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef __MATHLIB__
-#define __MATHLIB__
-
-// mathlib.h
-
-#include <math.h>
-/*
-   #ifdef DOUBLEVEC_T
-   typedef double vec_t;
-   #else
-   typedef float vec_t;
-   #endif
-   typedef vec_t vec3_t[3];
- */
-#define SIDE_FRONT      0
-#define SIDE_ON         2
-#define SIDE_BACK       1
-#define SIDE_CROSS      -2
-
-#define Q_PI    3.14159265358979323846
-
-extern vec3_t vec3_origin;
-
-#define EQUAL_EPSILON   0.001
-
-qboolean VectorCompare( vec3_t v1, vec3_t v2 );
-
-#define DotProduct( x,y ) ( x[0] * y[0] + x[1] * y[1] + x[2] * y[2] )
-#define VectorSubtract( a,b,c ) {c[0] = a[0] - b[0]; c[1] = a[1] - b[1]; c[2] = a[2] - b[2]; }
-#define VectorAdd( a,b,c ) {c[0] = a[0] + b[0]; c[1] = a[1] + b[1]; c[2] = a[2] + b[2]; }
-#define VectorCopy( a,b ) {b[0] = a[0]; b[1] = a[1]; b[2] = a[2]; }
-#define VectorScale( a,b,c ) {c[0] = b * a[0]; c[1] = b * a[1]; c[2] = b * a[2]; }
-#define VectorClear( x ) {x[0] = x[1] = x[2] = 0; }
-#define VectorNegate( x ) {x[0] = -x[0]; x[1] = -x[1]; x[2] = -x[2]; }
-
-vec_t Q_rint( vec_t in );
-vec_t _DotProduct( vec3_t v1, vec3_t v2 );
-void _VectorSubtract( vec3_t va, vec3_t vb, vec3_t out );
-void _VectorAdd( vec3_t va, vec3_t vb, vec3_t out );
-void _VectorCopy( vec3_t in, vec3_t out );
-void _VectorScale( vec3_t v, vec_t scale, vec3_t out );
-
-double VectorLength( vec3_t v );
-
-void VectorMA( vec3_t va, double scale, vec3_t vb, vec3_t vc );
-
-void CrossProduct( vec3_t v1, vec3_t v2, vec3_t cross );
-vec_t VectorNormalize( vec3_t in, vec3_t out );
-vec_t ColorNormalize( vec3_t in, vec3_t out );
-void VectorInverse( vec3_t v );
-
-void ClearBounds( vec3_t mins, vec3_t maxs );
-void AddPointToBounds( vec3_t v, vec3_t mins, vec3_t maxs );
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/common/md4.c b/tools/quake2/qdata_heretic2/common/md4.c
deleted file mode 100644 (file)
index f503422..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
-    mdfour.c
-
-    An implementation of MD4 designed for use in the samba SMB
-    authentication protocol
-
-    Copyright (C) 1997-1998  Andrew Tridgell
-
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License
-    as published by the Free Software Foundation; either version 2
-    of the License, or (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-    See the GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to:
-
-        Free Software Foundation, Inc.
-        59 Temple Place - Suite 330
-        Boston, MA  02111-1307, USA
-
-    $Id: mdfour.c 7689 2007-11-12 14:28:40Z divverent $
- */
-
-#include <string.h>     /* XoXus: needed for memset call */
-#include "md4.h"
-
-/* NOTE: This code makes no attempt to be fast!
-
-   It assumes that a int is at least 32 bits long
- */
-
-static struct mdfour *m;
-
-#define F( X,Y,Z ) ( ( (X)&( Y ) ) | ( ( ~( X ) ) & ( Z ) ) )
-#define G( X,Y,Z ) ( ( (X)&( Y ) ) | ( (X)&( Z ) ) | ( (Y)&( Z ) ) )
-#define H( X,Y,Z ) ( ( X ) ^ ( Y ) ^ ( Z ) )
-#ifdef LARGE_INT32
-#define lshift( x,s ) ( ( ( ( x ) << ( s ) ) & 0xFFFFFFFF ) | ( ( ( x ) >> ( 32 - ( s ) ) ) & 0xFFFFFFFF ) )
-#else
-#define lshift( x,s ) ( ( ( x ) << ( s ) ) | ( ( x ) >> ( 32 - ( s ) ) ) )
-#endif
-
-#define ROUND1( a,b,c,d,k,s ) a = lshift( a + F( b,c,d ) + X[k], s )
-#define ROUND2( a,b,c,d,k,s ) a = lshift( a + G( b,c,d ) + X[k] + 0x5A827999,s )
-#define ROUND3( a,b,c,d,k,s ) a = lshift( a + H( b,c,d ) + X[k] + 0x6ED9EBA1,s )
-
-/* this applies md4 to 64 byte chunks */
-static void mdfour64( uint32 *M ){
-       int j;
-       uint32 AA, BB, CC, DD;
-       uint32 X[16];
-       uint32 A,B,C,D;
-
-       for ( j = 0; j < 16; j++ )
-               X[j] = M[j];
-
-       A = m->A; B = m->B; C = m->C; D = m->D;
-       AA = A; BB = B; CC = C; DD = D;
-
-       ROUND1( A,B,C,D,  0,  3 );  ROUND1( D,A,B,C,  1,  7 );
-       ROUND1( C,D,A,B,  2, 11 );  ROUND1( B,C,D,A,  3, 19 );
-       ROUND1( A,B,C,D,  4,  3 );  ROUND1( D,A,B,C,  5,  7 );
-       ROUND1( C,D,A,B,  6, 11 );  ROUND1( B,C,D,A,  7, 19 );
-       ROUND1( A,B,C,D,  8,  3 );  ROUND1( D,A,B,C,  9,  7 );
-       ROUND1( C,D,A,B, 10, 11 );  ROUND1( B,C,D,A, 11, 19 );
-       ROUND1( A,B,C,D, 12,  3 );  ROUND1( D,A,B,C, 13,  7 );
-       ROUND1( C,D,A,B, 14, 11 );  ROUND1( B,C,D,A, 15, 19 );
-
-       ROUND2( A,B,C,D,  0,  3 );  ROUND2( D,A,B,C,  4,  5 );
-       ROUND2( C,D,A,B,  8,  9 );  ROUND2( B,C,D,A, 12, 13 );
-       ROUND2( A,B,C,D,  1,  3 );  ROUND2( D,A,B,C,  5,  5 );
-       ROUND2( C,D,A,B,  9,  9 );  ROUND2( B,C,D,A, 13, 13 );
-       ROUND2( A,B,C,D,  2,  3 );  ROUND2( D,A,B,C,  6,  5 );
-       ROUND2( C,D,A,B, 10,  9 );  ROUND2( B,C,D,A, 14, 13 );
-       ROUND2( A,B,C,D,  3,  3 );  ROUND2( D,A,B,C,  7,  5 );
-       ROUND2( C,D,A,B, 11,  9 );  ROUND2( B,C,D,A, 15, 13 );
-
-       ROUND3( A,B,C,D,  0,  3 );  ROUND3( D,A,B,C,  8,  9 );
-       ROUND3( C,D,A,B,  4, 11 );  ROUND3( B,C,D,A, 12, 15 );
-       ROUND3( A,B,C,D,  2,  3 );  ROUND3( D,A,B,C, 10,  9 );
-       ROUND3( C,D,A,B,  6, 11 );  ROUND3( B,C,D,A, 14, 15 );
-       ROUND3( A,B,C,D,  1,  3 );  ROUND3( D,A,B,C,  9,  9 );
-       ROUND3( C,D,A,B,  5, 11 );  ROUND3( B,C,D,A, 13, 15 );
-       ROUND3( A,B,C,D,  3,  3 );  ROUND3( D,A,B,C, 11,  9 );
-       ROUND3( C,D,A,B,  7, 11 );  ROUND3( B,C,D,A, 15, 15 );
-
-       A += AA; B += BB; C += CC; D += DD;
-
-#ifdef LARGE_INT32
-       A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
-       C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
-#endif
-
-       for ( j = 0; j < 16; j++ )
-               X[j] = 0;
-
-       m->A = A; m->B = B; m->C = C; m->D = D;
-}
-
-static void copy64( uint32 *M, unsigned char *in ){
-       int i;
-
-       for ( i = 0; i < 16; i++ )
-               M[i] = ( in[i * 4 + 3] << 24 ) | ( in[i * 4 + 2] << 16 ) |
-                          ( in[i * 4 + 1] << 8 ) | ( in[i * 4 + 0] << 0 );
-}
-
-static void copy4( unsigned char *out,uint32 x ){
-       out[0] = x & 0xFF;
-       out[1] = ( x >> 8 ) & 0xFF;
-       out[2] = ( x >> 16 ) & 0xFF;
-       out[3] = ( x >> 24 ) & 0xFF;
-}
-
-void mdfour_begin( struct mdfour *md ){
-       md->A = 0x67452301;
-       md->B = 0xefcdab89;
-       md->C = 0x98badcfe;
-       md->D = 0x10325476;
-       md->totalN = 0;
-}
-
-
-static void mdfour_tail( unsigned char *in, int n ){
-       unsigned char buf[128];
-       uint32 M[16];
-       uint32 b;
-
-       m->totalN += n;
-
-       b = m->totalN * 8;
-
-       memset( buf, 0, 128 );
-       if ( n ) {
-               memcpy( buf, in, n );
-       }
-       buf[n] = 0x80;
-
-       if ( n <= 55 ) {
-               copy4( buf + 56, b );
-               copy64( M, buf );
-               mdfour64( M );
-       }
-       else {
-               copy4( buf + 120, b );
-               copy64( M, buf );
-               mdfour64( M );
-               copy64( M, buf + 64 );
-               mdfour64( M );
-       }
-}
-
-void mdfour_update( struct mdfour *md, unsigned char *in, int n ){
-       uint32 M[16];
-
-// start of edit by Forest 'LordHavoc' Hale
-// commented out to prevent crashing when length is 0
-//     if (n == 0) mdfour_tail(in, n);
-// end of edit by Forest 'LordHavoc' Hale
-
-       m = md;
-
-       while ( n >= 64 ) {
-               copy64( M, in );
-               mdfour64( M );
-               in += 64;
-               n -= 64;
-               m->totalN += 64;
-       }
-
-       mdfour_tail( in, n );
-}
-
-
-void mdfour_result( struct mdfour *md, unsigned char *out ){
-       m = md;
-
-       copy4( out, m->A );
-       copy4( out + 4, m->B );
-       copy4( out + 8, m->C );
-       copy4( out + 12, m->D );
-}
-
-
-void mdfour( unsigned char *out, unsigned char *in, int n ){
-       struct mdfour md;
-       mdfour_begin( &md );
-       mdfour_update( &md, in, n );
-       mdfour_result( &md, out );
-}
-
-///////////////////////////////////////////////////////////////
-//     MD4-based checksum utility functions
-//
-//     Copyright (C) 2000       Jeff Teunissen <d2deek@pmail.net>
-//
-//     Author: Jeff Teunissen  <d2deek@pmail.net>
-//     Date: 01 Jan 2000
-
-unsigned Com_BlockChecksum( void *buffer, int length ){
-       int digest[4];
-       unsigned val;
-
-       mdfour( (unsigned char *) digest, (unsigned char *) buffer, length );
-
-       val = digest[0] ^ digest[1] ^ digest[2] ^ digest[3];
-
-       return val;
-}
-
-void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf ){
-       mdfour( outbuf, (unsigned char *) buffer, len );
-}
diff --git a/tools/quake2/qdata_heretic2/common/md4.h b/tools/quake2/qdata_heretic2/common/md4.h
deleted file mode 100644 (file)
index 6f64c28..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-    mdfour.h
-
-    an implementation of MD4 designed for use in the SMB authentication
-    protocol
-
-    Copyright (C) Andrew Tridgell 1997-1998
-
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License
-    as published by the Free Software Foundation; either version 2
-    of the License, or (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-    See the GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to:
-
-        Free Software Foundation, Inc.
-        59 Temple Place - Suite 330
-        Boston, MA  02111-1307, USA
- */
-
-#ifndef _MDFOUR_H
-#define _MDFOUR_H
-
-#ifndef int32
-#define int32 int
-#endif
-
-#if SIZEOF_INT > 4
-#define LARGE_INT32
-#endif
-
-#ifndef uint32
-#define uint32 unsigned int32
-#endif
-
-struct mdfour {
-       uint32 A, B, C, D;
-       uint32 totalN;
-};
-
-void mdfour_begin( struct mdfour *md ); // old: MD4Init
-void mdfour_update( struct mdfour *md, unsigned char *in, int n ); //old: MD4Update
-void mdfour_result( struct mdfour *md, unsigned char *out ); // old: MD4Final
-void mdfour( unsigned char *out, unsigned char *in, int n );
-
-unsigned Com_BlockChecksum( void *buffer, int length );
-void Com_BlockFullChecksum( void *buffer, int len, unsigned char *outbuf );
-
-#endif  // _MDFOUR_H
diff --git a/tools/quake2/qdata_heretic2/common/path_init.c b/tools/quake2/qdata_heretic2/common/path_init.c
deleted file mode 100644 (file)
index 1447037..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/* -------------------------------------------------------------------------------
-
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-/*
-   Nurail: Swiped from Q3Map2
- */
-
-#include "globaldefs.h"
-
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-       #define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
-       #include <unistd.h>
-       #include <pwd.h>
-       #include <limits.h>
-#endif
-
-
-/* dependencies */
-#include "cmdlib.h"
-#include "inout.h"
-
-
-
-/* path support */
-#define MAX_BASE_PATHS  10
-#define MAX_GAME_PATHS  10
-
-char                    *homePath;
-char installPath[ MAX_OS_PATH ];
-
-int numBasePaths;
-char                    *basePaths[ MAX_BASE_PATHS ];
-int numGamePaths;
-char                    *gamePaths[ MAX_GAME_PATHS ];
-
-/*
-   some of this code is based off the original q3map port from loki
-   and finds various paths. moved here from bsp.c for clarity.
- */
-
-/*
-   PathLokiGetHomeDir()
-   gets the user's home dir (for ~/.q3a)
- */
-
-char *LokiGetHomeDir( void ){
-       #ifndef Q_UNIX
-       return NULL;
-       #else
-       char            *home;
-       uid_t id;
-       struct passwd   *pwd;
-
-
-       /* get the home environment variable */
-       home = getenv( "HOME" );
-       if ( home == NULL ) {
-               /* do some more digging */
-               id = getuid();
-               setpwent();
-               while ( ( pwd = getpwent() ) != NULL )
-               {
-                       if ( pwd->pw_uid == id ) {
-                               home = pwd->pw_dir;
-                               break;
-                       }
-               }
-               endpwent();
-       }
-
-       /* return it */
-       return home;
-       #endif
-}
-
-
-
-/*
-   PathLokiInitPaths()
-   initializes some paths on linux/os x
- */
-
-void LokiInitPaths( char *argv0 ){
-       #ifndef Q_UNIX
-       /* this is kinda crap, but hey */
-       strcpy( installPath, "../" );
-       #else
-       char temp[ MAX_OS_PATH ];
-       char        *home;
-       char        *path;
-       char        *last;
-       qboolean found;
-
-
-       /* get home dir */
-       home = LokiGetHomeDir();
-       if ( home == NULL ) {
-               home = ".";
-       }
-
-       /* do some path divining */
-       strcpy( temp, argv0 );
-       if ( strrchr( temp, '/' ) ) {
-               argv0 = strrchr( argv0, '/' ) + 1;
-       }
-       else
-       {
-               /* get path environment variable */
-               path = getenv( "PATH" );
-
-               /* minor setup */
-               last[ 0 ] = path[ 0 ];
-               last[ 1 ] = '\0';
-               found = false;
-
-               /* go through each : segment of path */
-               while ( last[ 0 ] != '\0' && found == false )
-               {
-                       /* null out temp */
-                       temp[ 0 ] = '\0';
-
-                       /* find next chunk */
-                       last = strchr( path, ':' );
-                       if ( last == NULL ) {
-                               last = path + strlen( path );
-                       }
-
-                       /* found home dir candidate */
-                       if ( *path == '~' ) {
-                               strcpy( temp, home );
-                               path++;
-                       }
-
-                       /* concatenate */
-                       if ( last > ( path + 1 ) ) {
-                               strncat( temp, path, ( last - path ) );
-                               strcat( temp, "/" );
-                       }
-                       strcat( temp, "./" );
-                       strcat( temp, argv0 );
-
-                       /* verify the path */
-                       if ( access( temp, X_OK ) == 0 ) {
-                               found++;
-                       }
-                       path = last + 1;
-               }
-       }
-
-       /* flake */
-       if ( realpath( temp, installPath ) ) {
-               /* q3map is in "tools/" */
-               *( strrchr( installPath, '/' ) ) = '\0';
-               *( strrchr( installPath, '/' ) + 1 ) = '\0';
-       }
-
-       /* set home path */
-       homePath = home;
-       #endif
-}
-
-
-
-/*
-   CleanPath() - ydnar
-   cleans a dos path \ -> /
- */
-
-void CleanPath( char *path ){
-       while ( *path )
-       {
-               if ( *path == '\\' ) {
-                       *path = '/';
-               }
-               path++;
-       }
-}
-
-/*
-   AddBasePath() - ydnar
-   adds a base path to the list
- */
-
-void AddBasePath( char *path ){
-       /* dummy check */
-       if ( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS ) {
-               return;
-       }
-
-       /* add it to the list */
-       basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
-       strcpy( basePaths[ numBasePaths ], path );
-       CleanPath( basePaths[ numBasePaths ] );
-       numBasePaths++;
-}
-
-
-
-/*
-   AddHomeBasePath() - ydnar
-   adds a base path to the beginning of the list, prefixed by ~/
- */
-
-void AddHomeBasePath( char *path ){
-       #ifdef Q_UNIX
-       int i;
-       char temp[ MAX_OS_PATH ];
-
-
-       /* dummy check */
-       if ( path == NULL || path[ 0 ] == '\0' ) {
-               return;
-       }
-
-       /* make a hole */
-       for ( i = 0; i < ( MAX_BASE_PATHS - 1 ); i++ )
-               basePaths[ i + 1 ] = basePaths[ i ];
-
-       /* concatenate home dir and path */
-       sprintf( temp, "%s/%s", homePath, path );
-
-       /* add it to the list */
-       basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
-       strcpy( basePaths[ 0 ], temp );
-       CleanPath( basePaths[ 0 ] );
-       numBasePaths++;
-       #endif
-}
-
-
-
-/*
-   AddGamePath() - ydnar
-   adds a game path to the list
- */
-
-void AddGamePath( char *path ){
-       /* dummy check */
-       if ( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS ) {
-               return;
-       }
-
-       /* add it to the list */
-       gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
-       strcpy( gamePaths[ numGamePaths ], path );
-       CleanPath( gamePaths[ numGamePaths ] );
-       numGamePaths++;
-}
-
-
-
-
-/*
-   InitPaths() - ydnar
-   cleaned up some of the path initialization code from bsp.c
-   will remove any arguments it uses
- */
-
-void InitPaths( int *argc, char **argv ){
-       int i, j, k, len, len2;
-       char temp[ MAX_OS_PATH ];
-       char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
-
-       strcpy( gamePath, "base" );
-       strcpy( game_magic, "h" );
-       strcpy( homeBasePath, ".heretic2" );
-
-       /* note it */
-       Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
-
-       /* get the install path for backup */
-       LokiInitPaths( argv[ 0 ] );
-
-       /* set game to default (q3a) */
-       numBasePaths = 0;
-       numGamePaths = 0;
-
-       /* parse through the arguments and extract those relevant to paths */
-       for ( i = 0; i < *argc; i++ )
-       {
-               /* check for null */
-               if ( argv[ i ] == NULL ) {
-                       continue;
-               }
-
-               /* -fs_basepath */
-               if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
-                       if ( ++i >= *argc ) {
-                               Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
-                       }
-                       argv[ i - 1 ] = NULL;
-                       AddBasePath( argv[ i ] );
-                       argv[ i ] = NULL;
-               }
-
-       }
-
-       /* remove processed arguments */
-       for ( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
-       {
-               for ( j; j < *argc && argv[ j ] == NULL; j++ ) ;
-               argv[ i ] = argv[ j ];
-               if ( argv[ i ] != NULL ) {
-                       k++;
-               }
-       }
-       *argc = k;
-
-       /* add standard game path */
-       AddGamePath( gamePath );
-
-       /* if there is no base path set, figure it out */
-       if ( numBasePaths == 0 ) {
-               /* this is another crappy replacement for SetQdirFromPath() */
-               len2 = strlen( game_magic );
-               for ( i = 0; i < *argc && numBasePaths == 0; i++ )
-               {
-                       /* extract the arg */
-                       strcpy( temp, argv[ i ] );
-                       CleanPath( temp );
-                       len = strlen( temp );
-                       Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
-
-                       /* this is slow, but only done once */
-                       for ( j = 0; j < ( len - len2 ); j++ )
-                       {
-                               /* check for the game's magic word */
-                               if ( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 ) {
-                                       /* now find the next slash and nuke everything after it */
-                                       while ( temp[ ++j ] != '/' && temp[ j ] != '\0' ) ;
-                                       temp[ j ] = '\0';
-
-                                       /* add this as a base path */
-                                       AddBasePath( temp );
-                                       break;
-                               }
-                       }
-               }
-
-               /* add install path */
-               if ( numBasePaths == 0 ) {
-                       AddBasePath( installPath );
-               }
-
-               /* check again */
-               if ( numBasePaths == 0 ) {
-                       Error( "Failed to find a valid base path." );
-               }
-       }
-
-       /* this only affects unix */
-       AddHomeBasePath( homeBasePath );
-
-       /* initialize vfs paths */
-       if ( numBasePaths > MAX_BASE_PATHS ) {
-               numBasePaths = MAX_BASE_PATHS;
-       }
-       if ( numGamePaths > MAX_GAME_PATHS ) {
-               numGamePaths = MAX_GAME_PATHS;
-       }
-
-       /* walk the list of game paths */
-       //for( j = 0; j < numGamePaths; j++ )
-       //{
-       /* walk the list of base paths */
-       //      for( i = 0; i < numBasePaths; i++ )
-       //      {
-       /* create a full path and initialize it */
-       //              sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
-       //              vfsInitDirectory( temp );
-       //      }
-       //}
-
-       /* done */
-       Sys_Printf( "\n" );
-}
diff --git a/tools/quake2/qdata_heretic2/common/polylib.c b/tools/quake2/qdata_heretic2/common/polylib.c
deleted file mode 100644 (file)
index af5df49..0000000
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "polylib.h"
-
-
-extern int numthreads;
-
-// counters are only bumped when running single threaded,
-// because they are an awefull coherence problem
-int c_active_windings;
-int c_peak_windings;
-int c_winding_allocs;
-int c_winding_points;
-
-#define BOGUS_RANGE 8192
-
-void pw( winding_t *w ){
-       int i;
-       for ( i = 0 ; i < w->numpoints ; i++ )
-               printf( "(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2] );
-}
-
-
-/*
-   =============
-   AllocWinding
-   =============
- */
-winding_t   *AllocWinding( int points ){
-       winding_t   *w;
-       int s;
-
-       if ( numthreads == 1 ) {
-               c_winding_allocs++;
-               c_winding_points += points;
-               c_active_windings++;
-               if ( c_active_windings > c_peak_windings ) {
-                       c_peak_windings = c_active_windings;
-               }
-       }
-       s = sizeof( vec_t ) * 3 * points + sizeof( int );
-       w = malloc( s );
-       if ( !w ) {
-               Error( "AllocWinding MALLOC failed!  Could not allocate %s bytes.", s );
-       }
-       memset( w, 0, s );
-       return w;
-}
-
-void FreeWinding( winding_t *w ){
-       if ( *(unsigned *)w == 0xdeaddead ) {
-               Error( "FreeWinding: freed a freed winding" );
-       }
-       *(unsigned *)w = 0xdeaddead;
-
-       if ( numthreads == 1 ) {
-               c_active_windings--;
-       }
-       free( w );
-}
-
-/*
-   ============
-   RemoveColinearPoints
-   ============
- */
-int c_removed;
-
-void    RemoveColinearPoints( winding_t *w ){
-       int i, j, k;
-       vec3_t v1, v2;
-       int nump;
-       vec3_t p[MAX_POINTS_ON_WINDING];
-
-       nump = 0;
-       for ( i = 0 ; i < w->numpoints ; i++ )
-       {
-               j = ( i + 1 ) % w->numpoints;
-               k = ( i + w->numpoints - 1 ) % w->numpoints;
-               VectorSubtract( w->p[j], w->p[i], v1 );
-               VectorSubtract( w->p[i], w->p[k], v2 );
-               VectorNormalize( v1,v1 );
-               VectorNormalize( v2,v2 );
-               if ( DotProduct( v1, v2 ) < 0.999 ) {
-                       VectorCopy( w->p[i], p[nump] );
-                       nump++;
-               }
-       }
-
-       if ( nump == w->numpoints ) {
-               return;
-       }
-
-       if ( numthreads == 1 ) {
-               c_removed += w->numpoints - nump;
-       }
-       w->numpoints = nump;
-       memcpy( w->p, p, nump * sizeof( p[0] ) );
-}
-
-/*
-   ============
-   WindingPlane
-   ============
- */
-void WindingPlane( winding_t *w, vec3_t normal, vec_t *dist ){
-       vec3_t v1, v2;
-
-       VectorSubtract( w->p[1], w->p[0], v1 );
-       VectorSubtract( w->p[2], w->p[0], v2 );
-       CrossProduct( v2, v1, normal );
-       VectorNormalize( normal, normal );
-       *dist = DotProduct( w->p[0], normal );
-
-}
-
-/*
-   =============
-   WindingArea
-   =============
- */
-vec_t   WindingArea( winding_t *w ){
-       int i;
-       vec3_t d1, d2, cross;
-       vec_t total;
-
-       total = 0;
-       for ( i = 2 ; i < w->numpoints ; i++ )
-       {
-               VectorSubtract( w->p[i - 1], w->p[0], d1 );
-               VectorSubtract( w->p[i], w->p[0], d2 );
-               CrossProduct( d1, d2, cross );
-               total += 0.5 * VectorLength( cross );
-       }
-       return total;
-}
-
-void    WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs ){
-       vec_t v;
-       int i,j;
-
-       mins[0] = mins[1] = mins[2] = 99999;
-       maxs[0] = maxs[1] = maxs[2] = -99999;
-
-       for ( i = 0 ; i < w->numpoints ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       v = w->p[i][j];
-                       if ( v < mins[j] ) {
-                               mins[j] = v;
-                       }
-                       if ( v > maxs[j] ) {
-                               maxs[j] = v;
-                       }
-               }
-       }
-}
-
-/*
-   =============
-   WindingCenter
-   =============
- */
-void    WindingCenter( winding_t *w, vec3_t center ){
-       int i;
-       float scale;
-
-       VectorCopy( vec3_origin, center );
-       for ( i = 0 ; i < w->numpoints ; i++ )
-               VectorAdd( w->p[i], center, center );
-
-       scale = 1.0 / w->numpoints;
-       VectorScale( center, scale, center );
-}
-
-/*
-   =================
-   BaseWindingForPlane
-   =================
- */
-winding_t *BaseWindingForPlane( vec3_t normal, vec_t dist ){
-       int i, x;
-       vec_t max, v;
-       vec3_t org, vright, vup;
-       winding_t   *w;
-
-// find the major axis
-
-       max = -BOGUS_RANGE;
-       x = -1;
-       for ( i = 0 ; i < 3; i++ )
-       {
-               v = fabs( normal[i] );
-               if ( v > max ) {
-                       x = i;
-                       max = v;
-               }
-       }
-       if ( x == -1 ) {
-               Error( "BaseWindingForPlane: no axis found" );
-       }
-
-       VectorCopy( vec3_origin, vup );
-       switch ( x )
-       {
-       case 0:
-       case 1:
-               vup[2] = 1;
-               break;
-       case 2:
-               vup[0] = 1;
-               break;
-       }
-
-       v = DotProduct( vup, normal );
-       VectorMA( vup, -v, normal, vup );
-       VectorNormalize( vup, vup );
-
-       VectorScale( normal, dist, org );
-
-       CrossProduct( vup, normal, vright );
-
-       VectorScale( vup, 8192, vup );
-       VectorScale( vright, 8192, vright );
-
-// project a really big        axis aligned box onto the plane
-       w = AllocWinding( 4 );
-
-       VectorSubtract( org, vright, w->p[0] );
-       VectorAdd( w->p[0], vup, w->p[0] );
-
-       VectorAdd( org, vright, w->p[1] );
-       VectorAdd( w->p[1], vup, w->p[1] );
-
-       VectorAdd( org, vright, w->p[2] );
-       VectorSubtract( w->p[2], vup, w->p[2] );
-
-       VectorSubtract( org, vright, w->p[3] );
-       VectorSubtract( w->p[3], vup, w->p[3] );
-
-       w->numpoints = 4;
-
-       return w;
-}
-
-/*
-   ==================
-   CopyWinding
-   ==================
- */
-winding_t   *CopyWinding( winding_t *w ){
-       int size;
-       winding_t   *c;
-
-       c = AllocWinding( w->numpoints );
-       size = (int)( (winding_t *)0 )->p[w->numpoints];
-       memcpy( c, w, size );
-       return c;
-}
-
-/*
-   ==================
-   ReverseWinding
-   ==================
- */
-winding_t   *ReverseWinding( winding_t *w ){
-       int i;
-       winding_t   *c;
-
-       c = AllocWinding( w->numpoints );
-       for ( i = 0 ; i < w->numpoints ; i++ )
-       {
-               VectorCopy( w->p[w->numpoints - 1 - i], c->p[i] );
-       }
-       c->numpoints = w->numpoints;
-       return c;
-}
-
-
-/*
-   =============
-   ClipWindingEpsilon
-   =============
- */
-void    ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
-                                                       vec_t epsilon, winding_t **front, winding_t **back ){
-       vec_t dists[MAX_POINTS_ON_WINDING + 4];
-       int sides[MAX_POINTS_ON_WINDING + 4];
-       int counts[3];
-       vec_t dot;          // VC 4.2 optimizer bug if not static
-       int i, j;
-       vec_t   *p1, *p2;
-       vec3_t mid;
-       winding_t   *f, *b;
-       int maxpts;
-
-       if ( in->numpoints >= MAX_POINTS_ON_WINDING - 4 ) {
-               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
-       }
-
-       counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-       for ( i = 0 ; i < in->numpoints ; i++ )
-       {
-               dot = DotProduct( in->p[i], normal );
-               dot -= dist;
-               dists[i] = dot;
-               if ( dot > epsilon ) {
-                       sides[i] = SIDE_FRONT;
-               }
-               else if ( dot < -epsilon ) {
-                       sides[i] = SIDE_BACK;
-               }
-               else
-               {
-                       sides[i] = SIDE_ON;
-               }
-               counts[sides[i]]++;
-       }
-       sides[i] = sides[0];
-       dists[i] = dists[0];
-
-       *front = *back = NULL;
-
-       if ( !counts[0] ) {
-               *back = CopyWinding( in );
-               return;
-       }
-       if ( !counts[1] ) {
-               *front = CopyWinding( in );
-               return;
-       }
-
-       maxpts = in->numpoints + 4;   // cant use counts[0]+2 because
-                                     // of fp grouping errors
-
-       *front = f = AllocWinding( maxpts );
-       *back = b = AllocWinding( maxpts );
-
-       for ( i = 0 ; i < in->numpoints ; i++ )
-       {
-               p1 = in->p[i];
-
-               if ( sides[i] == SIDE_ON ) {
-                       VectorCopy( p1, f->p[f->numpoints] );
-                       f->numpoints++;
-                       VectorCopy( p1, b->p[b->numpoints] );
-                       b->numpoints++;
-                       continue;
-               }
-
-               if ( sides[i] == SIDE_FRONT ) {
-                       VectorCopy( p1, f->p[f->numpoints] );
-                       f->numpoints++;
-               }
-               if ( sides[i] == SIDE_BACK ) {
-                       VectorCopy( p1, b->p[b->numpoints] );
-                       b->numpoints++;
-               }
-
-               if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
-                       continue;
-               }
-
-               // generate a split point
-               p2 = in->p[( i + 1 ) % in->numpoints];
-
-               dot = dists[i] / ( dists[i] - dists[i + 1] );
-               for ( j = 0 ; j < 3 ; j++ )
-               {   // avoid round off error when possible
-                       if ( normal[j] == 1 ) {
-                               mid[j] = dist;
-                       }
-                       else if ( normal[j] == -1 ) {
-                               mid[j] = -dist;
-                       }
-                       else{
-                               mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
-                       }
-               }
-
-               VectorCopy( mid, f->p[f->numpoints] );
-               f->numpoints++;
-               VectorCopy( mid, b->p[b->numpoints] );
-               b->numpoints++;
-       }
-
-       if ( f->numpoints > maxpts || b->numpoints > maxpts ) {
-               Error( "ClipWinding: points exceeded estimate" );
-       }
-       if ( f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING ) {
-               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
-       }
-}
-
-
-/*
-   =============
-   ChopWindingInPlace
-   =============
- */
-void ChopWindingInPlace( winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon ){
-       winding_t   *in;
-       vec_t dists[MAX_POINTS_ON_WINDING + 4];
-       int sides[MAX_POINTS_ON_WINDING + 4];
-       int counts[3];
-       vec_t dot;          // VC 4.2 optimizer bug if not static
-       int i, j;
-       vec_t   *p1, *p2;
-       vec3_t mid;
-       winding_t   *f;
-       int maxpts;
-
-       in = *inout;
-       counts[0] = counts[1] = counts[2] = 0;
-
-       if ( !in ) {
-               printf( "Warning: NULL passed to ChopWindingInPlace\n" );
-               return;
-       }
-       if ( in->numpoints >= MAX_POINTS_ON_WINDING - 4 ) {
-               Error( "ChopWinding: MAX_POINTS_ON_WINDING" );
-       }
-
-// determine sides for each point
-       for ( i = 0 ; i < in->numpoints ; i++ )
-       {
-               dot = DotProduct( in->p[i], normal );
-               dot -= dist;
-               dists[i] = dot;
-               if ( dot > epsilon ) {
-                       sides[i] = SIDE_FRONT;
-               }
-               else if ( dot < -epsilon ) {
-                       sides[i] = SIDE_BACK;
-               }
-               else
-               {
-                       sides[i] = SIDE_ON;
-               }
-               counts[sides[i]]++;
-       }
-       sides[i] = sides[0];
-       dists[i] = dists[0];
-
-       if ( !counts[0] ) {
-               FreeWinding( in );
-               *inout = NULL;
-               return;
-       }
-       if ( !counts[1] ) {
-               return;     // inout stays the same
-
-       }
-       maxpts = in->numpoints + 4;   // cant use counts[0]+2 because
-                                     // of fp grouping errors
-
-       f = AllocWinding( maxpts );
-
-       for ( i = 0 ; i < in->numpoints ; i++ )
-       {
-               p1 = in->p[i];
-
-               if ( sides[i] == SIDE_ON ) {
-                       VectorCopy( p1, f->p[f->numpoints] );
-                       f->numpoints++;
-                       continue;
-               }
-
-               if ( sides[i] == SIDE_FRONT ) {
-                       VectorCopy( p1, f->p[f->numpoints] );
-                       f->numpoints++;
-               }
-
-               if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) {
-                       continue;
-               }
-
-               // generate a split point
-               p2 = in->p[( i + 1 ) % in->numpoints];
-
-               dot = dists[i] / ( dists[i] - dists[i + 1] );
-               for ( j = 0 ; j < 3 ; j++ )
-               {   // avoid round off error when possible
-                       if ( normal[j] == 1 ) {
-                               mid[j] = dist;
-                       }
-                       else if ( normal[j] == -1 ) {
-                               mid[j] = -dist;
-                       }
-                       else{
-                               mid[j] = p1[j] + dot * ( p2[j] - p1[j] );
-                       }
-               }
-
-               VectorCopy( mid, f->p[f->numpoints] );
-               f->numpoints++;
-       }
-
-       if ( f->numpoints > maxpts ) {
-               Error( "ClipWinding: points exceeded estimate" );
-       }
-       if ( f->numpoints > MAX_POINTS_ON_WINDING ) {
-               Error( "ClipWinding: MAX_POINTS_ON_WINDING" );
-       }
-
-       FreeWinding( in );
-       *inout = f;
-}
-
-
-/*
-   =================
-   ChopWinding
-
-   Returns the fragment of in that is on the front side
-   of the cliping plane.  The original is freed.
-   =================
- */
-winding_t   *ChopWinding( winding_t *in, vec3_t normal, vec_t dist ){
-       winding_t   *f, *b;
-
-       ClipWindingEpsilon( in, normal, dist, ON_EPSILON, &f, &b );
-       FreeWinding( in );
-       if ( b ) {
-               FreeWinding( b );
-       }
-       return f;
-}
-
-
-/*
-   =================
-   CheckWinding
-
-   =================
- */
-void CheckWinding( winding_t *w ){
-       int i, j;
-       vec_t   *p1, *p2;
-       vec_t d, edgedist;
-       vec3_t dir, edgenormal, facenormal;
-       vec_t area;
-       vec_t facedist;
-
-       if ( w->numpoints < 3 ) {
-               Error( "CheckWinding: %i points",w->numpoints );
-       }
-
-       area = WindingArea( w );
-       if ( area < 1 ) {
-               Error( "CheckWinding: %f area", area );
-       }
-
-       WindingPlane( w, facenormal, &facedist );
-
-       for ( i = 0 ; i < w->numpoints ; i++ )
-       {
-               p1 = w->p[i];
-
-               for ( j = 0 ; j < 3 ; j++ )
-                       if ( p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE ) {
-                               Error( "CheckFace: BUGUS_RANGE: %f",p1[j] );
-                       }
-
-               j = i + 1 == w->numpoints ? 0 : i + 1;
-
-               // check the point is on the face plane
-               d = DotProduct( p1, facenormal ) - facedist;
-               if ( d < -ON_EPSILON || d > ON_EPSILON ) {
-                       Error( "CheckWinding: point off plane" );
-               }
-
-               // check the edge isnt degenerate
-               p2 = w->p[j];
-               VectorSubtract( p2, p1, dir );
-
-               if ( VectorLength( dir ) < ON_EPSILON ) {
-                       Error( "CheckWinding: degenerate edge" );
-               }
-
-               CrossProduct( facenormal, dir, edgenormal );
-               VectorNormalize( edgenormal, edgenormal );
-               edgedist = DotProduct( p1, edgenormal );
-               edgedist += ON_EPSILON;
-
-               // all other points must be on front side
-               for ( j = 0 ; j < w->numpoints ; j++ )
-               {
-                       if ( j == i ) {
-                               continue;
-                       }
-                       d = DotProduct( w->p[j], edgenormal );
-                       if ( d > edgedist ) {
-                               Error( "CheckWinding: non-convex" );
-                       }
-               }
-       }
-}
-
-
-/*
-   ============
-   WindingOnPlaneSide
-   ============
- */
-int     WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist ){
-       qboolean front, back;
-       int i;
-       vec_t d;
-
-       front = false;
-       back = false;
-       for ( i = 0 ; i < w->numpoints ; i++ )
-       {
-               d = DotProduct( w->p[i], normal ) - dist;
-               if ( d < -ON_EPSILON ) {
-                       if ( front ) {
-                               return SIDE_CROSS;
-                       }
-                       back = true;
-                       continue;
-               }
-               if ( d > ON_EPSILON ) {
-                       if ( back ) {
-                               return SIDE_CROSS;
-                       }
-                       front = true;
-                       continue;
-               }
-       }
-
-       if ( back ) {
-               return SIDE_BACK;
-       }
-       if ( front ) {
-               return SIDE_FRONT;
-       }
-       return SIDE_ON;
-}
diff --git a/tools/quake2/qdata_heretic2/common/polylib.h b/tools/quake2/qdata_heretic2/common/polylib.h
deleted file mode 100644 (file)
index 00b7b39..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-typedef struct
-{
-       int numpoints;
-       vec3_t p[4];        // variable sized
-} winding_t;
-
-#define MAX_POINTS_ON_WINDING   64
-
-// you can define on_epsilon in the makefile as tighter
-#ifndef ON_EPSILON
-#define ON_EPSILON  0.1
-#endif
-
-winding_t   *AllocWinding( int points );
-vec_t   WindingArea( winding_t *w );
-void    WindingCenter( winding_t *w, vec3_t center );
-void    ClipWindingEpsilon( winding_t *in, vec3_t normal, vec_t dist,
-                                                       vec_t epsilon, winding_t **front, winding_t **back );
-winding_t   *ChopWinding( winding_t *in, vec3_t normal, vec_t dist );
-winding_t   *CopyWinding( winding_t *w );
-winding_t   *ReverseWinding( winding_t *w );
-winding_t   *BaseWindingForPlane( vec3_t normal, vec_t dist );
-void    CheckWinding( winding_t *w );
-void    WindingPlane( winding_t *w, vec3_t normal, vec_t *dist );
-void    RemoveColinearPoints( winding_t *w );
-int     WindingOnPlaneSide( winding_t *w, vec3_t normal, vec_t dist );
-void    FreeWinding( winding_t *w );
-void    WindingBounds( winding_t *w, vec3_t mins, vec3_t maxs );
-
-void    ChopWindingInPlace( winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon );
-// frees the original if clipped
-
-void pw( winding_t *w );
diff --git a/tools/quake2/qdata_heretic2/common/qfiles.c b/tools/quake2/qdata_heretic2/common/qfiles.c
deleted file mode 100644 (file)
index 53452f3..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qfiles.h"
-#include "scriplib.h"
-//#include <windows.h>
-
-materialtype_t defaultmaterialtypes[] =
-{
-       {"gravel",  MATERIAL_GRAVEL},
-       {"metal",   MATERIAL_METAL},
-       {"stone",   MATERIAL_STONE},
-       {"wood",    MATERIAL_WOOD},
-       {NULL,      0}
-};
-
-materialtype_t  *materialtypes;
-
-void QFile_ReadMaterialTypes( char* filename ){
-       int i;
-       FILE    *f;
-
-       f = fopen( filename, "rb" );
-       if ( !f ) {
-               materialtypes = defaultmaterialtypes;
-               return;
-       }
-       fclose( f );
-
-       free( materialtypes );
-       materialtypes = (materialtype_t*)malloc( 256 * sizeof( materialtype_t ) );
-
-       LoadScriptFile( filename );
-       i = 0;
-
-       while ( i < 255 )
-       {
-               GetScriptToken( true );
-               if ( endofscript ) {
-                       break;
-               }
-               if ( strcmp( token, "material" ) != 0 ) {
-                       while ( ScriptTokenAvailable() )
-                       {
-                               GetScriptToken( false );
-                       }
-               }
-               else
-               {
-                       GetScriptToken( false );
-                       materialtypes[i].name = (char*)malloc( strlen( token ) + 1 );
-                       strcpy( materialtypes[i].name, token );
-                       GetScriptToken( false );
-                       materialtypes[i].value = atoi( token );
-               }
-               i++;
-       }
-       materialtypes[i].name = NULL;
-       materialtypes[i].value = 0;
-}
diff --git a/tools/quake2/qdata_heretic2/common/qfiles.h b/tools/quake2/qdata_heretic2/common/qfiles.h
deleted file mode 100644 (file)
index bee4b4f..0000000
+++ /dev/null
@@ -1,619 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _QFILES_H
-#define _QFILES_H
-
-#include "q_typedef.h"
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-   ========================================================================
-
-   The .pak files are just a linear collapse of a directory tree
-
-   ========================================================================
- */
-
-#define IDPAKHEADER     ( ( 'K' << 24 ) + ( 'C' << 16 ) + ( 'A' << 8 ) + 'P' )
-
-typedef struct
-{
-       char name[56];
-       int filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-       int ident;          // == IDPAKHEADER
-       int dirofs;
-       int dirlen;
-} dpackheader_t;
-
-#define MAX_FILES_IN_PACK   4096
-
-
-/*
-   ========================================================================
-
-   PCX files are used for as many images as possible
-
-   ========================================================================
- */
-
-typedef struct
-{
-       char manufacturer;
-       char version;
-       char encoding;
-       char bits_per_pixel;
-       unsigned short xmin,ymin,xmax,ymax;
-       unsigned short hres,vres;
-       unsigned char palette[48];
-       char reserved;
-       char color_planes;
-       unsigned short bytes_per_line;
-       unsigned short palette_type;
-       char filler[58];
-       unsigned char data;             // unbounded
-} pcx_t;
-
-
-/*
-   ========================================================================
-
-   .MD2 compressed triangle model file format
-
-   ========================================================================
- */
-#define IDJOINTEDALIASHEADER    ( ( '2' << 24 ) + ( 'J' << 16 ) + ( 'D' << 8 ) + 'I' )
-
-/*
-   ========================================================================
-
-   .MD2 triangle model file format
-
-   ========================================================================
- */
-
-#define IDALIASHEADER       ( ( '2' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
-#define ALIAS_VERSION   8
-
-#define MAX_TRIANGLES   2048
-#define MAX_VERTS       2048
-#define MAX_FRAMES      512
-#define MAX_MD2SKINS    64
-#define MAX_SKINNAME    64
-
-typedef struct
-{
-       short s;
-       short t;
-} dstvert_t;
-
-typedef struct
-{
-       short index_xyz[3];
-       short index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-       byte v[3];              // scaled byte to fit in frame mins/maxs
-       byte lightnormalindex;
-} dtrivertx_t;
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-typedef struct
-{
-       float scale[3];         // multiply byte verts by this
-       float translate[3];         // then add this
-       char name[16];          // frame name from grabbing
-       dtrivertx_t verts[1];   // variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-       int ident;
-       int version;
-
-       int skinwidth;
-       int skinheight;
-       int framesize;              // byte size of each frame
-
-       int num_skins;
-       int num_xyz;
-       int num_st;                 // greater than num_xyz for seams
-       int num_tris;
-       int num_glcmds;             // dwords in strip/fan command list
-       int num_frames;
-
-       int ofs_skins;              // each skin is a MAX_SKINNAME string
-       int ofs_st;                 // byte offset from start for stverts
-       int ofs_tris;               // offset for dtriangles
-       int ofs_frames;             // offset for first frame
-       int ofs_glcmds;
-       int ofs_end;                // end of file
-
-} dmdl_t;
-
-/*
-   ========================================================================
-
-   .BK file format
-
-   ========================================================================
- */
-
-#define IDBOOKHEADER    ( ( 'K' << 24 ) + ( 'O' << 16 ) + ( 'O' << 8 ) + 'B' )
-#define BOOK_VERSION    2
-
-typedef struct bookframe_s
-{
-       int x;
-       int y;
-       int w;
-       int h;
-       char name[MAX_SKINNAME];            // name of gfx file
-} bookframe_t;
-
-typedef struct bookheader_s
-{
-       unsigned int ident;
-       unsigned int version;
-       int num_segments;
-       int total_w;
-       int total_h;
-} bookheader_t;
-
-typedef struct book_s
-{
-       bookheader_t bheader;
-       bookframe_t bframes[MAX_MD2SKINS];
-} book_t;
-
-/*
-   ========================================================================
-
-   .SP2 sprite file format
-
-   ========================================================================
- */
-
-#define IDSPRITEHEADER  ( ( '2' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' )
-// little-endian "IDS2"
-#define SPRITE_VERSION  2
-
-typedef struct
-{
-       int width, height;
-       int origin_x, origin_y;         // raster coordinates inside pic
-       char name[MAX_SKINNAME];        // name of pcx file
-} dsprframe_t;
-
-typedef struct {
-       int ident;
-       int version;
-       int numframes;
-       dsprframe_t frames[1];          // variable sized
-} dsprite_t;
-
-/*
-   ==============================================================================
-
-   .M8 texture file format
-
-   ==============================================================================
- */
-
-typedef struct palette_s
-{
-       union
-       {
-               struct
-               {
-                       byte r,g,b;
-               };
-       };
-} palette_t;
-
-#define MIP_VERSION     2
-#define PAL_SIZE        256
-#define MIPLEVELS       16
-
-typedef struct miptex_s
-{
-       int version;
-       char name[32];
-       unsigned width[MIPLEVELS], height[MIPLEVELS];
-       unsigned offsets[MIPLEVELS];        // four mip maps stored
-       char animname[32];                  // next frame in animation chain
-       palette_t palette[PAL_SIZE];
-       int flags;
-       int contents;
-       int value;
-} miptex_t;
-
-
-#define MIP32_VERSION   4
-
-#define MIP32_NOMIP_FLAG2           0x00000001
-#define MIP32_DETAILER_FLAG2        0x00000002
-
-typedef struct miptex32_s
-{
-       int version;
-       char name[128];
-       char altname[128];                  // texture substitution
-       char animname[128];                 // next frame in animation chain
-       char damagename[128];               // image that should be shown when damaged
-       unsigned width[MIPLEVELS], height[MIPLEVELS];
-       unsigned offsets[MIPLEVELS];
-       int flags;
-       int contents;
-       int value;
-       float scale_x, scale_y;
-       int mip_scale;
-
-       // detail texturing info
-       char dt_name[128];              // detailed texture name
-       float dt_scale_x, dt_scale_y;
-       float dt_u, dt_v;
-       float dt_alpha;
-       int dt_src_blend_mode, dt_dst_blend_mode;
-
-       int flags2;
-       int unused[19];                     // future expansion to maintain compatibility with h2
-} miptex32_t;
-
-
-
-/*
-   ==============================================================================
-
-   .BSP file format
-
-   ==============================================================================
- */
-
-#define IDBSPHEADER ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' )
-// little-endian "IBSP"
-
-#define BSPVERSION  38
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define MAX_MAP_MODELS      1024
-#define MAX_MAP_BRUSHES     8192
-#define MAX_MAP_ENTITIES    2048
-#define MAX_MAP_ENTSTRING   0x40000
-#define MAX_MAP_TEXINFO     8192
-
-#define MAX_MAP_AREAS       256
-#define MAX_MAP_AREAPORTALS 1024
-#define MAX_MAP_PLANES      65536
-#define MAX_MAP_NODES       65536
-#define MAX_MAP_BRUSHSIDES  65536
-#define MAX_MAP_LEAFS       65536
-#define MAX_MAP_VERTS       65536
-#define MAX_MAP_FACES       65536
-#define MAX_MAP_LEAFFACES   65536
-#define MAX_MAP_LEAFBRUSHES 65536
-#define MAX_MAP_PORTALS     65536
-#define MAX_MAP_EDGES       128000
-#define MAX_MAP_SURFEDGES   256000
-#define MAX_MAP_LIGHTING    0x200000
-#define MAX_MAP_VISIBILITY  0x180000
-
-// key / value pair sizes
-
-#define MAX_KEY     32
-#define MAX_VALUE   1024
-
-//=============================================================================
-
-typedef struct
-{
-       int fileofs, filelen;
-} lump_t;
-
-#define LUMP_ENTITIES       0
-#define LUMP_PLANES         1
-#define LUMP_VERTEXES       2
-#define LUMP_VISIBILITY     3
-#define LUMP_NODES          4
-#define LUMP_TEXINFO        5
-#define LUMP_FACES          6
-#define LUMP_LIGHTING       7
-#define LUMP_LEAFS          8
-#define LUMP_LEAFFACES      9
-#define LUMP_LEAFBRUSHES    10
-#define LUMP_EDGES          11
-#define LUMP_SURFEDGES      12
-#define LUMP_MODELS         13
-#define LUMP_BRUSHES        14
-#define LUMP_BRUSHSIDES     15
-#define LUMP_POP            16
-#define LUMP_AREAS          17
-#define LUMP_AREAPORTALS    18
-#define HEADER_LUMPS        19
-
-typedef struct
-{
-       int ident;
-       int version;
-       lump_t lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-       float mins[3], maxs[3];
-       float origin[3];            // for sounds or lights
-       int headnode;
-       int firstface, numfaces;            // submodels just draw faces
-                                           // without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-       float point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define PLANE_X         0
-#define PLANE_Y         1
-#define PLANE_Z         2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define PLANE_ANYX      3
-#define PLANE_ANYY      4
-#define PLANE_ANYZ      5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
-       float normal[3];
-       float dist;
-       int type;           // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// these definitions also need to be in q_shared.h!
-
-// lower bits are stronger, and will eat weaker brushes completely
-#define CONTENTS_SOLID          0x00000001      // an eye is never valid in a solid
-#define CONTENTS_WINDOW         0x00000002      // translucent, but not watery
-#define CONTENTS_PUSHPULL       0x00000004
-#define CONTENTS_LAVA           0x00000008
-#define CONTENTS_SLIME          0x00000010
-#define CONTENTS_WATER          0x00000020
-#define CONTENTS_MIST           0x00000040      // 64
-#define LAST_VISIBLE_CONTENTS   64              // this one worries me a bit JKH
-
-// remaining contents are non-visible, and don't eat brushes
-
-#define CONTENTS_AREAPORTAL     0x00008000
-
-#define CONTENTS_PLAYERCLIP     0x00010000
-#define CONTENTS_MONSTERCLIP    0x00020000
-
-// currents can be added to any other contents, and may be mixed
-#define CONTENTS_CURRENT_0      0x00040000
-#define CONTENTS_CURRENT_90     0x00080000
-#define CONTENTS_CURRENT_180    0x00100000
-#define CONTENTS_CURRENT_270    0x00200000
-#define CONTENTS_CURRENT_UP     0x00400000
-#define CONTENTS_CURRENT_DOWN   0x00800000
-
-#define CONTENTS_ORIGIN         0x01000000  // removed before bsping an entity
-
-#define CONTENTS_MONSTER        0x02000000  // should never be on a brush, only in game
-#define CONTENTS_DEADMONSTER    0x04000000
-#define CONTENTS_DETAIL         0x08000000  // brushes to be added after vis leafs
-#define CONTENTS_TRANSLUCENT    0x10000000  // auto set if any surface has trans
-#define CONTENTS_LADDER         0x20000000
-
-
-
-#define SURF_LIGHT              0x00000001      // value will hold the light strength
-
-#define SURF_SLICK              0x00000002      // effects game physics
-
-#define SURF_SKY                0x00000004      // don't draw, but add to skybox
-#define SURF_WARP               0x00000008      // turbulent water warp
-#define SURF_TRANS33            0x00000010
-#define SURF_TRANS66            0x00000020
-#define SURF_FLOWING            0x00000040  // scroll towards angle
-#define SURF_NODRAW             0x00000080  // don't bother referencing the texture
-
-#define SURF_HINT               0x00000100  // make a primary bsp splitter
-#define SURF_SKIP               0x00000200  // completely ignore, allowing non-closed brushes
-#define SURF_TALL_WALL          0x00000400  // face doesn't get broken up as normal
-
-#define SURF_ALPHA_TEXTURE      0x00000800  // texture has alpha in it, and should show through in bsp process
-#define SURF_ANIMSPEED          0x00001000      // value will hold the anim speed in fps
-
-#define SURF_UNDULATE           0x00002000  // rock surface up and down...
-#define SURF_SKYREFLECT         0x00004000  // liquid will somewhat reflect the sky - not quite finished....
-
-#define SURF_TYPE_GRAVEL        0x00000000
-#define SURF_TYPE_METAL         0x01000000
-#define SURF_TYPE_STONE         0x02000000
-#define SURF_TYPE_WOOD          0x03000000
-#define SURF_MATERIAL           0xFF000000
-
-
-
-typedef struct
-{
-       int planenum;
-       int children[2];            // negative numbers are -(leafs+1), not nodes
-       short mins[3];              // for frustom culling
-       short maxs[3];
-       unsigned short firstface;
-       unsigned short numfaces;    // counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-       float vecs[2][4];           // [s/t][xyz offset]
-       int flags;                  // miptex flags + overrides
-       int value;                  // light emission, etc
-       char texture[32];           // texture name (textures/*.wal)
-       int nexttexinfo;            // for animations, -1 = end of chain
-} texinfo_t;
-
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-       unsigned short v[2];        // vertex numbers
-} dedge_t;
-
-#define MAXLIGHTMAPS    4
-typedef struct
-{
-       unsigned short planenum;
-       short side;
-
-       int firstedge;              // we must support > 64k edges
-       short numedges;
-       short texinfo;
-
-// lighting info
-       union {
-               byte styles[MAXLIGHTMAPS];
-               paletteRGBA_t lighting;
-       };
-       int lightofs;               // start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-       int contents;                       // OR of all brushes (not needed?)
-
-       short cluster;
-       short area;
-
-       short mins[3];                      // for frustum culling
-       short maxs[3];
-
-       unsigned short firstleafface;
-       unsigned short numleaffaces;
-
-       unsigned short firstleafbrush;
-       unsigned short numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-       unsigned short planenum;        // facing out of the leaf
-       short texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-       int firstside;
-       int numsides;
-       int contents;
-} dbrush_t;
-
-#define ANGLE_UP    -1
-#define ANGLE_DOWN  -2
-
-
-// the visibility lump consists of a header with a count, then
-// byte offsets for the PVS and PHS of each cluster, then the raw
-// compressed bit vectors
-#define DVIS_PVS    0
-#define DVIS_PHS    1
-typedef struct
-{
-       int numclusters;
-       int bitofs[8][2];           // bitofs[numclusters][2]
-} dvis_t;
-
-// each area has a list of portals that lead into other areas
-// when portals are closed, other areas may not be visible or
-// hearable even if the vis info says that it should be
-typedef struct
-{
-       int portalnum;
-       int otherarea;
-} dareaportal_t;
-
-
-typedef struct
-{
-       int numareaportals;
-       int firstareaportal;
-} darea_t;
-
-typedef struct
-{
-       char    *name;
-       int value;
-} materialtype_t;
-
-enum
-{
-       MATERIAL_GRAVEL,
-       MATERIAL_METAL,
-       MATERIAL_STONE,
-       MATERIAL_WOOD,
-};
-
-materialtype_t  *materialtypes;
-
-void QFile_ReadMaterialTypes( char* filename );
-
-
-#endif //_QFILES_H
diff --git a/tools/quake2/qdata_heretic2/common/scriplib.c b/tools/quake2/qdata_heretic2/common/scriplib.c
deleted file mode 100644 (file)
index af5e571..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// scriplib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "scriplib.h"
-
-/*
-   =============================================================================
-
-                        PARSING STUFF
-
-   =============================================================================
- */
-
-typedef struct
-{
-       char filename[1024];
-       char    *buffer,*script_p,*end_p;
-       int line;
-} script_t;
-
-#define MAX_INCLUDES    8
-script_t scriptstack[MAX_INCLUDES];
-script_t    *script;
-int scriptline;
-
-char token[MAXTOKEN];
-qboolean endofscript;
-qboolean tokenready;                     // only true if UnGetScriptToken was just called
-
-/*
-   ==============
-   AddScriptToStack
-   ==============
- */
-void AddScriptToStack( char *filename ){
-       int size;
-
-       script++;
-       if ( script == &scriptstack[MAX_INCLUDES] ) {
-               Error( "script file exceeded MAX_INCLUDES" );
-       }
-       strcpy( script->filename, ExpandPath( filename ) );
-
-       size = LoadFile( script->filename, (void **)&script->buffer );
-
-       printf( "entering %s\n", script->filename );
-
-       script->line = 1;
-
-       script->script_p = script->buffer;
-       script->end_p = script->buffer + size;
-}
-
-
-/*
-   ==============
-   LoadScriptFile
-   ==============
- */
-void LoadScriptFile( char *filename ){
-       script = scriptstack;
-       AddScriptToStack( filename );
-
-       endofscript = false;
-       tokenready = false;
-}
-
-
-/*
-   ==============
-   ParseFromMemory
-   ==============
- */
-void ParseFromMemory( char *buffer, int size ){
-       script = scriptstack;
-       script++;
-       if ( script == &scriptstack[MAX_INCLUDES] ) {
-               Error( "script file exceeded MAX_INCLUDES" );
-       }
-       strcpy( script->filename, "memory buffer" );
-
-       script->buffer = buffer;
-       script->line = 1;
-       script->script_p = script->buffer;
-       script->end_p = script->buffer + size;
-
-       endofscript = false;
-       tokenready = false;
-}
-
-
-/*
-   ==============
-   UnGetScriptToken
-
-   Signals that the current token was not used, and should be reported
-   for the next GetScriptToken.  Note that
-
-   GetScriptToken (true);
-   UnGetScriptToken ();
-   GetScriptToken (false);
-
-   could cross a line boundary.
-   ==============
- */
-void UnGetScriptToken( void ){
-       tokenready = true;
-}
-
-
-qboolean EndOfScript( qboolean crossline ){
-       if ( !crossline ) {
-               Error( "Line %i is incomplete\n",scriptline );
-       }
-
-       if ( !strcmp( script->filename, "memory buffer" ) ) {
-               endofscript = true;
-               return false;
-       }
-
-       free( script->buffer );
-       if ( script == scriptstack + 1 ) {
-               endofscript = true;
-               return false;
-       }
-       script--;
-       scriptline = script->line;
-       printf( "returning to %s\n", script->filename );
-       return GetScriptToken( crossline );
-}
-
-/*
-   ==============
-   GetScriptToken
-   ==============
- */
-qboolean GetScriptToken( qboolean crossline ){
-       char    *token_p;
-
-       if ( tokenready ) {                       // is a token allready waiting?
-               tokenready = false;
-               return true;
-       }
-
-       if ( script->script_p >= script->end_p ) {
-               return EndOfScript( crossline );
-       }
-
-//
-// skip space
-//
-skipspace:
-       while ( *script->script_p <= 32 )
-       {
-               if ( script->script_p >= script->end_p ) {
-                       return EndOfScript( crossline );
-               }
-               if ( *script->script_p++ == '\n' ) {
-                       if ( !crossline ) {
-                               Error( "Line %i is incomplete\n",scriptline );
-                       }
-                       scriptline = script->line++;
-               }
-       }
-
-       if ( script->script_p >= script->end_p ) {
-               return EndOfScript( crossline );
-       }
-
-       // ; # // comments
-       if ( *script->script_p == ';' || *script->script_p == '#'
-                || ( script->script_p[0] == '/' && script->script_p[1] == '/' ) ) {
-               if ( !crossline ) {
-                       Error( "Line %i is incomplete\n",scriptline );
-               }
-               while ( *script->script_p++ != '\n' )
-                       if ( script->script_p >= script->end_p ) {
-                               return EndOfScript( crossline );
-                       }
-               goto skipspace;
-       }
-
-       // /* */ comments
-       if ( script->script_p[0] == '/' && script->script_p[1] == '*' ) {
-               if ( !crossline ) {
-                       Error( "Line %i is incomplete\n",scriptline );
-               }
-               script->script_p += 2;
-               while ( script->script_p[0] != '*' && script->script_p[1] != '/' )
-               {
-                       script->script_p++;
-                       if ( script->script_p >= script->end_p ) {
-                               return EndOfScript( crossline );
-                       }
-               }
-               script->script_p += 2;
-               goto skipspace;
-       }
-
-//
-// copy token
-//
-       token_p = token;
-
-       if ( *script->script_p == '"' ) {
-               // quoted token
-               script->script_p++;
-               while ( *script->script_p != '"' )
-               {
-                       *token_p++ = *script->script_p++;
-                       if ( script->script_p == script->end_p ) {
-                               break;
-                       }
-                       if ( token_p == &token[MAXTOKEN] ) {
-                               Error( "Token too large on line %i\n",scriptline );
-                       }
-               }
-               script->script_p++;
-       }
-       else{   // regular token
-               while ( *script->script_p > 32 && *script->script_p != ';' )
-               {
-                       *token_p++ = *script->script_p++;
-                       if ( script->script_p == script->end_p ) {
-                               break;
-                       }
-                       if ( token_p == &token[MAXTOKEN] ) {
-                               Error( "Token too large on line %i\n",scriptline );
-                       }
-               }
-       }
-
-       *token_p = 0;
-
-       if ( !strcmp( token, "$include" ) ) {
-               GetScriptToken( false );
-               AddScriptToStack( token );
-               return GetScriptToken( crossline );
-       }
-
-       return true;
-}
-
-
-/*
-   ==============
-   ScriptTokenAvailable
-
-   Returns true if there is another token on the line
-   ==============
- */
-qboolean ScriptTokenAvailable( void ){
-       char    *search_p;
-
-       search_p = script->script_p;
-
-       if ( search_p >= script->end_p ) {
-               return false;
-       }
-
-       while ( *search_p <= 32 )
-       {
-               if ( *search_p == '\n' ) {
-                       return false;
-               }
-               search_p++;
-               if ( search_p == script->end_p ) {
-                       return false;
-               }
-
-       }
-
-       if ( *search_p == ';' ) {
-               return false;
-       }
-
-       return true;
-}
diff --git a/tools/quake2/qdata_heretic2/common/scriplib.h b/tools/quake2/qdata_heretic2/common/scriplib.h
deleted file mode 100644 (file)
index 8c441c8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// scriplib.h
-
-#ifndef __CMDLIB__
-#include "cmdlib.h"
-#endif
-
-#define MAXTOKEN    1024
-
-extern char token[MAXTOKEN];
-extern char    *scriptbuffer,*script_p,*scriptend_p;
-extern int grabbed;
-extern int scriptline;
-extern qboolean endofscript;
-
-
-void LoadScriptFile( char *filename );
-void ParseFromMemory( char *buffer, int size );
-
-qboolean GetScriptToken( qboolean crossline );
-void UnGetScriptToken( void );
-qboolean ScriptTokenAvailable( void );
diff --git a/tools/quake2/qdata_heretic2/common/threads.c b/tools/quake2/qdata_heretic2/common/threads.c
deleted file mode 100644 (file)
index 0ee1e2d..0000000
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "globaldefs.h"
-
-#if !GDEF_OS_WINDOWS
-// The below define is necessary to use
-// pthreads extensions like pthread_mutexattr_settype
-#define _GNU_SOURCE
-#include <pthread.h>
-#endif
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "her2_threads.h"
-
-#define MAX_THREADS 64
-
-int dispatch;
-int workcount;
-int oldf;
-qboolean pacifier;
-
-qboolean threaded;
-
-/*
-   =============
-   GetThreadWork
-
-   =============
- */
-int GetThreadWork( void ){
-       int r;
-       int f;
-
-       ThreadLock();
-
-       if ( dispatch == workcount ) {
-               ThreadUnlock();
-               return -1;
-       }
-
-       f = 10 * dispatch / workcount;
-       if ( f != oldf ) {
-               oldf = f;
-               if ( pacifier ) {
-                       Sys_Printf( "%i...", f );
-                       fflush( stdout );   /* ydnar */
-               }
-       }
-
-       r = dispatch;
-       dispatch++;
-       ThreadUnlock();
-
-       return r;
-}
-
-
-void ( *workfunction )( int );
-
-void ThreadWorkerFunction( int threadnum ){
-       int work;
-
-       while ( 1 )
-       {
-               work = GetThreadWork();
-               if ( work == -1 ) {
-                       break;
-               }
-//Sys_Printf ("thread %i, work %i\n", threadnum, work);
-               workfunction( work );
-       }
-}
-
-void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       if ( numthreads == -1 ) {
-               ThreadSetDefault();
-       }
-       workfunction = func;
-       RunThreadsOn( workcnt, showpacifier, ThreadWorkerFunction );
-}
-
-
-/*
-   ===================================================================
-
-   WIN32
-
-   ===================================================================
- */
-#if GDEF_OS_WINDOWS
-
-#define USED
-
-#include <windows.h>
-
-int numthreads = -1;
-CRITICAL_SECTION crit;
-static int enter;
-
-void ThreadSetDefault( void ){
-       SYSTEM_INFO info;
-
-       if ( numthreads == -1 ) { // not set manually
-               GetSystemInfo( &info );
-               numthreads = info.dwNumberOfProcessors;
-               if ( numthreads < 1 || numthreads > 32 ) {
-                       numthreads = 1;
-               }
-       }
-
-       Sys_Printf( "%i threads\n", numthreads );
-}
-
-
-void ThreadLock( void ){
-       if ( !threaded ) {
-               return;
-       }
-       EnterCriticalSection( &crit );
-       if ( enter ) {
-               Error( "Recursive ThreadLock\n" );
-       }
-       enter = 1;
-}
-
-void ThreadUnlock( void ){
-       if ( !threaded ) {
-               return;
-       }
-       if ( !enter ) {
-               Error( "ThreadUnlock without lock\n" );
-       }
-       enter = 0;
-       LeaveCriticalSection( &crit );
-}
-
-/*
-   =============
-   RunThreadsOn
-   =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       int threadid[MAX_THREADS];
-       HANDLE threadhandle[MAX_THREADS];
-       int i;
-       int start, end;
-
-       start = I_FloatTime();
-       dispatch = 0;
-       workcount = workcnt;
-       oldf = -1;
-       pacifier = showpacifier;
-       threaded = true;
-
-       //
-       // run threads in parallel
-       //
-       InitializeCriticalSection( &crit );
-
-       if ( numthreads == 1 ) { // use same thread
-               func( 0 );
-       }
-       else
-       {
-               for ( i = 0 ; i < numthreads ; i++ )
-               {
-                       threadhandle[i] = CreateThread(
-                               NULL,   // LPSECURITY_ATTRIBUTES lpsa,
-                           //0,                // DWORD cbStack,
-
-                           /* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
-                               ( 4096 * 1024 ),
-
-                               (LPTHREAD_START_ROUTINE)func,   // LPTHREAD_START_ROUTINE lpStartAddr,
-                               (LPVOID)i,  // LPVOID lpvThreadParm,
-                               0,          //   DWORD fdwCreate,
-                               &threadid[i] );
-               }
-
-               for ( i = 0 ; i < numthreads ; i++ )
-                       WaitForSingleObject( threadhandle[i], INFINITE );
-       }
-       DeleteCriticalSection( &crit );
-
-       threaded = false;
-       end = I_FloatTime();
-       if ( pacifier ) {
-               Sys_Printf( " (%i)\n", end - start );
-       }
-}
-
-
-#endif
-
-/*
-   ===================================================================
-
-   OSF1
-
-   ===================================================================
- */
-
-#ifdef __osf__
-#define USED
-
-int numthreads = 4;
-
-void ThreadSetDefault( void ){
-       if ( numthreads == -1 ) { // not set manually
-               numthreads = 4;
-       }
-}
-
-
-#include <pthread.h>
-
-pthread_mutex_t *my_mutex;
-
-void ThreadLock( void ){
-       if ( my_mutex ) {
-               pthread_mutex_lock( my_mutex );
-       }
-}
-
-void ThreadUnlock( void ){
-       if ( my_mutex ) {
-               pthread_mutex_unlock( my_mutex );
-       }
-}
-
-
-/*
-   =============
-   RunThreadsOn
-   =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       int i;
-       pthread_t work_threads[MAX_THREADS];
-       pthread_addr_t status;
-       pthread_attr_t attrib;
-       pthread_mutexattr_t mattrib;
-       int start, end;
-
-       start = I_FloatTime();
-       dispatch = 0;
-       workcount = workcnt;
-       oldf = -1;
-       pacifier = showpacifier;
-       threaded = true;
-
-       if ( pacifier ) {
-               setbuf( stdout, NULL );
-       }
-
-       if ( !my_mutex ) {
-               my_mutex = safe_malloc( sizeof( *my_mutex ) );
-               if ( pthread_mutexattr_create( &mattrib ) == -1 ) {
-                       Error( "pthread_mutex_attr_create failed" );
-               }
-               if ( pthread_mutexattr_setkind_np( &mattrib, MUTEX_FAST_NP ) == -1 ) {
-                       Error( "pthread_mutexattr_setkind_np failed" );
-               }
-               if ( pthread_mutex_init( my_mutex, mattrib ) == -1 ) {
-                       Error( "pthread_mutex_init failed" );
-               }
-       }
-
-       if ( pthread_attr_create( &attrib ) == -1 ) {
-               Error( "pthread_attr_create failed" );
-       }
-       if ( pthread_attr_setstacksize( &attrib, 0x100000 ) == -1 ) {
-               Error( "pthread_attr_setstacksize failed" );
-       }
-
-       for ( i = 0 ; i < numthreads ; i++ )
-       {
-               if ( pthread_create( &work_threads[i], attrib
-                                                        , (pthread_startroutine_t)func, (pthread_addr_t)i ) == -1 ) {
-                       Error( "pthread_create failed" );
-               }
-       }
-
-       for ( i = 0 ; i < numthreads ; i++ )
-       {
-               if ( pthread_join( work_threads[i], &status ) == -1 ) {
-                       Error( "pthread_join failed" );
-               }
-       }
-
-       threaded = false;
-
-       end = I_FloatTime();
-       if ( pacifier ) {
-               Sys_Printf( " (%i)\n", end - start );
-       }
-}
-
-
-#endif
-
-/*
-   ===================================================================
-
-   IRIX
-
-   ===================================================================
- */
-
-#ifdef _MIPS_ISA
-#define USED
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-
-int numthreads = -1;
-abilock_t lck;
-
-void ThreadSetDefault( void ){
-       if ( numthreads == -1 ) {
-               numthreads = prctl( PR_MAXPPROCS );
-       }
-       Sys_Printf( "%i threads\n", numthreads );
-       usconfig( CONF_INITUSERS, numthreads );
-}
-
-
-void ThreadLock( void ){
-       spin_lock( &lck );
-}
-
-void ThreadUnlock( void ){
-       release_lock( &lck );
-}
-
-
-/*
-   =============
-   RunThreadsOn
-   =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       int i;
-       int pid[MAX_THREADS];
-       int start, end;
-
-       start = I_FloatTime();
-       dispatch = 0;
-       workcount = workcnt;
-       oldf = -1;
-       pacifier = showpacifier;
-       threaded = true;
-
-       if ( pacifier ) {
-               setbuf( stdout, NULL );
-       }
-
-       init_lock( &lck );
-
-       for ( i = 0 ; i < numthreads - 1 ; i++ )
-       {
-               pid[i] = sprocsp( ( void ( * )( void *, size_t ) )func, PR_SALL, (void *)i
-                                                 , NULL, 0x200000 ); // 2 meg stacks
-               if ( pid[i] == -1 ) {
-                       perror( "sproc" );
-                       Error( "sproc failed" );
-               }
-       }
-
-       func( i );
-
-       for ( i = 0 ; i < numthreads - 1 ; i++ )
-               wait( NULL );
-
-       threaded = false;
-
-       end = I_FloatTime();
-       if ( pacifier ) {
-               Sys_Printf( " (%i)\n", end - start );
-       }
-}
-
-
-#endif
-
-
-/*
-   =======================================================================
-
-   Linux pthreads
-
-   =======================================================================
- */
-
-#if GDEF_OS_LINUX
-#define USED
-
-int numthreads = 4;
-
-void ThreadSetDefault( void ){
-       if ( numthreads == -1 ) { // not set manually
-               /* default to one thread, only multi-thread when specifically told to */
-               numthreads = 1;
-       }
-       if ( numthreads > 1 ) {
-               Sys_Printf( "threads: %d\n", numthreads );
-       }
-}
-
-#include <pthread.h>
-
-typedef struct pt_mutex_s
-{
-       pthread_t       *owner;
-       pthread_mutex_t a_mutex;
-       pthread_cond_t cond;
-       unsigned int lock;
-} pt_mutex_t;
-
-pt_mutex_t global_lock;
-
-void ThreadLock( void ){
-       pt_mutex_t *pt_mutex = &global_lock;
-
-       if ( !threaded ) {
-               return;
-       }
-
-       pthread_mutex_lock( &pt_mutex->a_mutex );
-       if ( pthread_equal( pthread_self(), (pthread_t)&pt_mutex->owner ) ) {
-               pt_mutex->lock++;
-       }
-       else
-       {
-               if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
-                       pt_mutex->owner = (pthread_t *)pthread_self();
-                       pt_mutex->lock  = 1;
-               }
-               else
-               {
-                       while ( 1 )
-                       {
-                               pthread_cond_wait( &pt_mutex->cond, &pt_mutex->a_mutex );
-                               if ( ( !pt_mutex->owner ) && ( pt_mutex->lock == 0 ) ) {
-                                       pt_mutex->owner = (pthread_t *)pthread_self();
-                                       pt_mutex->lock  = 1;
-                                       break;
-                               }
-                       }
-               }
-       }
-       pthread_mutex_unlock( &pt_mutex->a_mutex );
-}
-
-void ThreadUnlock( void ){
-       pt_mutex_t *pt_mutex = &global_lock;
-
-       if ( !threaded ) {
-               return;
-       }
-
-       pthread_mutex_lock( &pt_mutex->a_mutex );
-       pt_mutex->lock--;
-
-       if ( pt_mutex->lock == 0 ) {
-               pt_mutex->owner = NULL;
-               pthread_cond_signal( &pt_mutex->cond );
-       }
-
-       pthread_mutex_unlock( &pt_mutex->a_mutex );
-}
-
-void recursive_mutex_init( pthread_mutexattr_t attribs ){
-       pt_mutex_t *pt_mutex = &global_lock;
-
-       pt_mutex->owner = NULL;
-       if ( pthread_mutex_init( &pt_mutex->a_mutex, &attribs ) != 0 ) {
-               Error( "pthread_mutex_init failed\n" );
-       }
-       if ( pthread_cond_init( &pt_mutex->cond, NULL ) != 0 ) {
-               Error( "pthread_cond_init failed\n" );
-       }
-
-       pt_mutex->lock = 0;
-}
-
-/*
-   =============
-   RunThreadsOn
-   =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       pthread_mutexattr_t mattrib;
-       pthread_t work_threads[MAX_THREADS];
-
-       int start, end;
-       int i = 0, status = 0;
-
-       start     = I_FloatTime();
-       pacifier  = showpacifier;
-
-       dispatch  = 0;
-       oldf      = -1;
-       workcount = workcnt;
-
-       if ( numthreads == 1 ) {
-               func( 0 );
-       }
-       else
-       {
-               threaded  = true;
-
-               if ( pacifier ) {
-                       setbuf( stdout, NULL );
-               }
-
-               if ( pthread_mutexattr_init( &mattrib ) != 0 ) {
-                       Error( "pthread_mutexattr_init failed" );
-               }
-#if __GLIBC_MINOR__ == 1
-               if ( pthread_mutexattr_settype( &mattrib, PTHREAD_MUTEX_FAST_NP ) != 0 )
-#else
-               if ( pthread_mutexattr_settype( &mattrib, PTHREAD_MUTEX_ADAPTIVE_NP ) != 0 )
-#endif
-               { Error( "pthread_mutexattr_settype failed" ); }
-               recursive_mutex_init( mattrib );
-
-               for ( i = 0 ; i < numthreads ; i++ )
-               {
-                       /* Default pthread attributes: joinable & non-realtime scheduling */
-                       if ( pthread_create( &work_threads[i], NULL, (void*)func, (void*)i ) != 0 ) {
-                               Error( "pthread_create failed" );
-                       }
-               }
-               for ( i = 0 ; i < numthreads ; i++ )
-               {
-                       if ( pthread_join( work_threads[i], (void **)&status ) != 0 ) {
-                               Error( "pthread_join failed" );
-                       }
-               }
-               pthread_mutexattr_destroy( &mattrib );
-               threaded = false;
-       }
-
-       end = I_FloatTime();
-       if ( pacifier ) {
-               Sys_Printf( " (%i)\n", end - start );
-       }
-}
-#endif // ifdef __linux__
-
-
-/*
-   =======================================================================
-
-   SINGLE THREAD
-
-   =======================================================================
- */
-
-#ifndef USED
-
-int numthreads = 1;
-
-void ThreadSetDefault( void ){
-       numthreads = 1;
-}
-
-void ThreadLock( void ){
-}
-
-void ThreadUnlock( void ){
-}
-
-/*
-   =============
-   RunThreadsOn
-   =============
- */
-void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
-       int i;
-       int start, end;
-
-       dispatch = 0;
-       workcount = workcnt;
-       oldf = -1;
-       pacifier = showpacifier;
-       start = I_FloatTime();
-       func( 0 );
-
-       end = I_FloatTime();
-       if ( pacifier ) {
-               Sys_Printf( " (%i)\n", end - start );
-       }
-}
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/common/token.c b/tools/quake2/qdata_heretic2/common/token.c
deleted file mode 100644 (file)
index 632cfe4..0000000
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-//**************************************************************************
-//**
-//** token.c
-//**
-//**************************************************************************
-
-// HEADER FILES ------------------------------------------------------------
-
-#include "token.h"
-#include "inout.h"
-
-// MACROS ------------------------------------------------------------------
-
-// TYPES -------------------------------------------------------------------
-
-typedef enum
-{
-       CHR_EOF,
-       CHR_LETTER,
-       CHR_NUMBER,
-       CHR_QUOTE,
-       CHR_SPECIAL
-} chr_t;
-
-// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
-
-// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
-
-// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
-
-static void ProcessLetterToken( void );
-static void ProcessNumberToken( void );
-static void ProcessQuoteToken( void );
-static void ProcessSpecialToken( void );
-static qboolean CheckForKeyword( void );
-static void NextChr( void );
-
-// EXTERNAL DATA DECLARATIONS ----------------------------------------------
-
-// PUBLIC DATA DEFINITIONS -------------------------------------------------
-
-tokenType_t tk_Token;
-int tk_Line;
-int tk_IntNumber;
-float tk_FloatNumber;
-char *tk_String;
-char tk_SourceName[MAX_FILE_NAME_LENGTH];
-
-// PRIVATE DATA DEFINITIONS ------------------------------------------------
-
-static char Chr;
-static char *FileStart;
-static char *FilePtr;
-static char *FileEnd;
-static qboolean SourceOpen;
-static char ASCIIToChrCode[256];
-static char TokenStringBuffer[MAX_QUOTED_LENGTH];
-static qboolean IncLineNumber;
-static char TempBuffer[2048];
-
-static struct
-{
-       char *name;
-       tokenType_t token;
-} Keywords[] =
-{
-       "model",            TK_MODEL,
-       "mesh",             TK_MESH,
-       "vertices",         TK_VERTICES,
-       "edges",            TK_EDGES,
-       "position",         TK_POSITION,
-       "polygons",         TK_POLYGONS,
-       "nodes",            TK_NODES,
-       "rotation",         TK_ROTATION,
-       "scaling",          TK_SCALING,
-       "translation",      TK_TRANSLATION,
-       "vertex",           TK_VERTEX,
-       "HRCH",             TK_HRCH,
-       "Softimage",        TK_SOFTIMAGE,
-       "material",         TK_MATERIAL,
-       "spline",           TK_SPLINE,
-
-       "Named",            TK_C_NAMED,
-       "object",           TK_OBJECT,
-       "Tri",              TK_C_TRI,
-       "Vertices",         TK_C_VERTICES,
-       "Faces",            TK_C_FACES,
-       "Vertex",           TK_C_VERTEX,
-       "list",             TK_LIST,
-       "Face",             TK_C_FACE,
-
-       "Hexen",            TK_C_HEXEN,
-       "Triangles",        TK_C_TRIANGLES,
-       "Version",          TK_C_VERSION,
-       "faces",            TK_FACES,
-       "face",             TK_FACE,
-       "origin",           TK_ORIGIN,
-
-       "DK_clusters",      TK_CLUSTERS,
-       "DK_cluster_ncvs",  TK_NUM_CLUSTER_VERTICES,
-       "name",             TK_NAME,
-       "DK_cluster_name",  TK_CLUSTER_NAME,
-       "DK_cluster_state", TK_CLUSTER_STATE,
-
-       "actor_data",       TK_ACTOR_DATA,
-       "uvTexture",        TK_UVTEXTURE,
-
-       NULL,               -1
-};
-
-static char *TokenNames[] =
-{
-       "<nothing>",
-       "<unknown_char>",
-       "<EOF>",
-       "<identifier>",
-       "<string>",
-       "<int_number>",
-       "<float_number>",
-       "(",
-       ")",
-       "{",
-       "}",
-       "[",
-       "]",
-       ":",
-       "mesh",
-       "model",
-       "nodes",
-       "rotation",
-       "scaling",
-       "translation",
-       "polygons",
-       "position",
-       "vertex",
-       "vertices",
-       "HRCH",
-       "Softimage"
-};
-
-// CODE --------------------------------------------------------------------
-
-//==========================================================================
-//
-// TK_Init
-//
-//==========================================================================
-
-void TK_Init( void ){
-       int i;
-
-       for ( i = 0; i < 256; i++ )
-       {
-               ASCIIToChrCode[i] = CHR_SPECIAL;
-       }
-       for ( i = '0'; i <= '9'; i++ )
-       {
-               ASCIIToChrCode[i] = CHR_NUMBER;
-       }
-       for ( i = 'A'; i <= 'Z'; i++ )
-       {
-               ASCIIToChrCode[i] = CHR_LETTER;
-       }
-       for ( i = 'a'; i <= 'z'; i++ )
-       {
-               ASCIIToChrCode[i] = CHR_LETTER;
-       }
-       ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
-       ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
-       ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
-       tk_String = TokenStringBuffer;
-       IncLineNumber = FALSE;
-       SourceOpen = FALSE;
-}
-
-//==========================================================================
-//
-// TK_OpenSource
-//
-//==========================================================================
-
-void TK_OpenSource( char *fileName ){
-       int size;
-
-       TK_CloseSource();
-       size = LoadFile( fileName, (void **)&FileStart );
-       strcpy( tk_SourceName, fileName );
-       SourceOpen = TRUE;
-       FileEnd = FileStart + size;
-       FilePtr = FileStart;
-       tk_Line = 1;
-       tk_Token = TK_NONE;
-       NextChr();
-}
-
-//==========================================================================
-//
-// TK_CloseSource
-//
-//==========================================================================
-
-void TK_CloseSource( void ){
-       if ( SourceOpen ) {
-               free( FileStart );
-               SourceOpen = FALSE;
-       }
-}
-
-//==========================================================================
-//
-// TK_Fetch
-//
-//==========================================================================
-
-tokenType_t TK_Fetch( void ){
-       while ( Chr == ASCII_SPACE )
-       {
-               NextChr();
-       }
-       if ( Chr == '-' ) {
-               ProcessNumberToken();
-       }
-       else{switch ( ASCIIToChrCode[(byte)Chr] )
-                {
-                case CHR_EOF:
-                        tk_Token = TK_EOF;
-                        break;
-                case CHR_LETTER:
-                        ProcessLetterToken();
-                        break;
-                case CHR_NUMBER:
-                        ProcessNumberToken();
-                        break;
-                case CHR_QUOTE:
-                        ProcessQuoteToken();
-                        break;
-                default:
-                        ProcessSpecialToken();
-                        break;
-                }}
-       return tk_Token;
-}
-
-//==========================================================================
-//
-// TK_Require
-//
-//==========================================================================
-
-void TK_Require( tokenType_t tokType ){
-       if ( tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER ) {
-               tk_FloatNumber = (float)tk_IntNumber;
-               tk_Token = TK_FLOATNUMBER;
-               return;
-       }
-       if ( tk_Token != tokType ) {
-               Error( "File '%s', line %d:\nExpected '%s', found '%s'.\n",
-                          tk_SourceName, tk_Line, TokenNames[tokType],
-                          TokenNames[tk_Token] );
-       }
-}
-
-void TK_FetchRequire( tokenType_t tokType ){
-       TK_Fetch();
-       TK_Require( tokType );
-}
-
-tokenType_t TK_RequireFetch( tokenType_t tokType ){
-       TK_Require( tokType );
-       return TK_Fetch();
-}
-
-tokenType_t TK_FetchRequireFetch( tokenType_t tokType ){
-       TK_Fetch();
-       TK_Require( tokType );
-       return TK_Fetch();
-}
-
-tokenType_t TK_Beyond( tokenType_t tokType ){
-       while ( tk_Token != tokType )
-       {
-               if ( TK_Fetch() == TK_EOF ) {
-                       Error( "File '%s':\nCould not find token '%s'.\n",       // FIXME: TokenNames table not big enuff
-                                  tk_SourceName, TokenNames[tokType] );
-               }
-       }
-       return TK_Fetch();
-}
-
-void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok ){
-       TK_Beyond( bTok );
-       TK_Require( rTok );
-}
-
-tokenType_t TK_Search( tokenType_t tokType ){
-       while ( tk_Token != tokType )
-       {
-               if ( TK_Fetch() == TK_EOF ) {
-                       return TK_EOF;
-               }
-       }
-       return TK_Fetch();
-}
-
-tokenType_t TK_Get( tokenType_t tokType ){
-       while ( tk_Token != tokType )
-       {
-               if ( TK_Fetch() == TK_EOF ) {
-                       Error( "File '%s':\nCould not find token '%s'.\n",
-                                  tk_SourceName, TokenNames[tokType] );
-               }
-       }
-       return tk_Token;
-}
-
-//==========================================================================
-//
-// ProcessLetterToken
-//
-//==========================================================================
-
-static void ProcessLetterToken( void ){
-       int i;
-       char *text;
-
-       i = 0;
-       text = TokenStringBuffer;
-       while ( ASCIIToChrCode[(byte)Chr] == CHR_LETTER
-                       || ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
-       {
-               if ( ++i == MAX_IDENTIFIER_LENGTH ) {
-                       Error( "File '%s', line %d:\nIdentifier too long.\n",
-                                  tk_SourceName, tk_Line );
-               }
-               *text++ = Chr;
-               NextChr();
-       }
-       *text = 0;
-       if ( CheckForKeyword() == FALSE ) {
-               tk_Token = TK_IDENTIFIER;
-       }
-}
-
-//==========================================================================
-//
-// CheckForKeyword
-//
-//==========================================================================
-
-static qboolean CheckForKeyword( void ){
-       int i;
-
-       for ( i = 0; Keywords[i].name != NULL; i++ )
-       {
-               if ( strcmp( tk_String, Keywords[i].name ) == 0 ) {
-                       tk_Token = Keywords[i].token;
-                       return TRUE;
-               }
-       }
-       return FALSE;
-}
-
-//==========================================================================
-//
-// ProcessNumberToken
-//
-//==========================================================================
-
-static void ProcessNumberToken( void ){
-       char *buffer;
-
-       buffer = TempBuffer;
-       *buffer++ = Chr;
-       NextChr();
-       while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
-       {
-               *buffer++ = Chr;
-               NextChr();
-       }
-       if ( Chr == '.' ) { // Float
-               *buffer++ = Chr;
-               NextChr(); // Skip period
-               while ( ASCIIToChrCode[(byte)Chr] == CHR_NUMBER )
-               {
-                       *buffer++ = Chr;
-                       NextChr();
-               }
-               *buffer = 0;
-               tk_FloatNumber = (float)atof( TempBuffer );
-               tk_Token = TK_FLOATNUMBER;
-               return;
-       }
-
-       // Integer
-       *buffer = 0;
-       tk_IntNumber = atoi( TempBuffer );
-       tk_Token = TK_INTNUMBER;
-}
-
-//==========================================================================
-//
-// ProcessQuoteToken
-//
-//==========================================================================
-
-static void ProcessQuoteToken( void ){
-       int i;
-       char *text;
-
-       i = 0;
-       text = TokenStringBuffer;
-       NextChr();
-       while ( Chr != ASCII_QUOTE )
-       {
-               if ( Chr == EOF_CHARACTER ) {
-                       Error( "File '%s', line %d:\n<EOF> inside string.\n",
-                                  tk_SourceName, tk_Line );
-               }
-               if ( ++i > MAX_QUOTED_LENGTH - 1 ) {
-                       Error( "File '%s', line %d:\nString literal too long.\n",
-                                  tk_SourceName, tk_Line );
-               }
-               *text++ = Chr;
-               NextChr();
-       }
-       *text = 0;
-       NextChr();
-       tk_Token = TK_STRING;
-}
-
-//==========================================================================
-//
-// ProcessSpecialToken
-//
-//==========================================================================
-
-static void ProcessSpecialToken( void ){
-       char c;
-
-       c = Chr;
-       NextChr();
-       switch ( c )
-       {
-       case '(':
-               tk_Token = TK_LPAREN;
-               break;
-       case ')':
-               tk_Token = TK_RPAREN;
-               break;
-       case '{':
-               tk_Token = TK_LBRACE;
-               break;
-       case '}':
-               tk_Token = TK_RBRACE;
-               break;
-       case '[':
-               tk_Token = TK_LBRACKET;
-               break;
-       case ']':
-               tk_Token = TK_RBRACKET;
-               break;
-       case ':':
-               tk_Token = TK_COLON;
-               break;
-       default:
-               tk_Token = TK_UNKNOWNCHAR;
-               break;
-       }
-}
-
-//==========================================================================
-//
-// NextChr
-//
-//==========================================================================
-
-static void NextChr( void ){
-       if ( FilePtr >= FileEnd ) {
-               Chr = EOF_CHARACTER;
-               return;
-       }
-       if ( IncLineNumber == TRUE ) {
-               tk_Line++;
-               IncLineNumber = FALSE;
-       }
-       Chr = *FilePtr++;
-       if ( Chr < ASCII_SPACE ) {
-               if ( Chr == '\n' ) {
-                       IncLineNumber = TRUE;
-               }
-               Chr = ASCII_SPACE;
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/common/token.h b/tools/quake2/qdata_heretic2/common/token.h
deleted file mode 100644 (file)
index 6dca1a1..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-//**************************************************************************
-//**
-//** token.h
-//**
-//**************************************************************************
-
-#ifndef __TOKEN_H__
-#define __TOKEN_H__
-
-#include "cmdlib.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef YES
-#define YES 1
-#endif
-#ifndef NO
-#define NO 0
-#endif
-#define ASCII_SPACE 32
-#define ASCII_QUOTE 34
-#define ASCII_UNDERSCORE 95
-#define EOF_CHARACTER 127
-#define MAX_IDENTIFIER_LENGTH 64
-#define MAX_QUOTED_LENGTH 1024
-#define MAX_FILE_NAME_LENGTH 1024
-
-typedef enum
-{
-       TK_NONE,
-       TK_UNKNOWNCHAR,
-       TK_EOF,
-       TK_IDENTIFIER,          // VALUE: (char *) tk_String
-       TK_STRING,              // VALUE: (char *) tk_String
-       TK_INTNUMBER,           // VALUE: (int) tk_IntNumber
-       TK_FLOATNUMBER,         // VALUE: (float) tk_FloatNumber
-       TK_LPAREN,
-       TK_RPAREN,
-       TK_LBRACE,
-       TK_RBRACE,              // 10
-       TK_LBRACKET,
-       TK_RBRACKET,
-       TK_COLON,
-       TK_MESH,
-       TK_MODEL,               // 15
-       TK_NODES,
-       TK_ROTATION,
-       TK_SCALING,
-       TK_TRANSLATION,
-       TK_POLYGONS,            // 20
-       TK_POSITION,
-       TK_VERTEX,
-       TK_VERTICES,
-       TK_EDGES,
-       TK_HRCH,                // 25
-       TK_SOFTIMAGE,
-       TK_MATERIAL,
-       TK_SPLINE,              // 28
-
-       TK_C_NAMED,
-       TK_OBJECT,              // 30
-       TK_C_TRI,
-       TK_C_VERTICES,
-       TK_C_FACES,
-       TK_C_VERTEX,
-       TK_LIST,                // 35
-       TK_C_FACE,
-
-       TK_C_HEXEN,
-       TK_C_TRIANGLES,
-       TK_C_VERSION,
-       TK_FACES,               // 40
-       TK_FACE,
-       TK_ORIGIN,
-
-       TK_CLUSTERS,
-       TK_NUM_CLUSTER_VERTICES,
-       TK_NAME,                // 45
-       TK_CLUSTER_NAME,
-       TK_CLUSTER_STATE,
-
-       TK_ACTOR_DATA,
-       TK_UVTEXTURE,
-} tokenType_t;
-
-void TK_Init( void );
-void TK_OpenSource( char *fileName );
-void TK_CloseSource( void );
-tokenType_t TK_Fetch( void );
-void TK_Require( tokenType_t tokType );
-void TK_FetchRequire( tokenType_t tokType );
-tokenType_t TK_RequireFetch( tokenType_t tokType );
-tokenType_t TK_FetchRequireFetch( tokenType_t tokType );
-tokenType_t TK_Beyond( tokenType_t tokType );
-void TK_BeyondRequire( tokenType_t bTok, tokenType_t rTok );
-tokenType_t TK_Search( tokenType_t tokType );
-tokenType_t TK_Get( tokenType_t tokType );
-
-extern tokenType_t tk_Token;
-extern int tk_Line;
-extern int tk_IntNumber;
-extern float tk_FloatNumber;
-extern char *tk_String;
-extern char tk_SourceName[MAX_FILE_NAME_LENGTH];
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/common/trilib.c b/tools/quake2/qdata_heretic2/common/trilib.c
deleted file mode 100644 (file)
index 29acab6..0000000
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// trilib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "token.h"
-#include "l3dslib.h"
-#include "fmodel.h"
-#if 1
-#include "qd_skeletons.h"
-#endif
-
-// on disk representation of a face
-#define FLOAT_START 99999.0
-#define FLOAT_END   -FLOAT_START
-#define MAGIC       123322
-#ifndef M_PI
-  #define M_PI      3.14159265
-#endif
-
-float FixHTRRotateX = 0.0;
-float FixHTRRotateY = 0.0;
-float FixHTRRotateZ = 0.0;
-float FixHTRTranslateX = 0.0;
-float FixHTRTranslateY = 0.0;
-float FixHTRTranslateZ = 0.0;
-
-//#define NOISY 1
-
-typedef struct {
-       float v[3];
-} vector;
-
-typedef struct
-{
-       vector n;    /* normal */
-       vector p;    /* point */
-       vector c;    /* color */
-       float u;     /* u */
-       float v;     /* v */
-} aliaspoint_t;
-
-typedef struct {
-       aliaspoint_t pt[3];
-} tf_triangle;
-
-
-void ByteSwapTri( tf_triangle *tri ){
-       int i;
-
-       for ( i = 0 ; i < sizeof( tf_triangle ) / 4 ; i++ )
-       {
-               ( (int *)tri )[i] = BigLong( ( (int *)tri )[i] );
-       }
-}
-
-void LoadTRI( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes ){
-       FILE        *input;
-       float start;
-       char name[256], tex[256];
-       int i, count, magic;
-       tf_triangle tri;
-       triangle_t  *ptri;
-       int iLevel;
-       int exitpattern;
-       float t;
-
-       if ( nodesList ) {
-               *num_mesh_nodes = 0;
-               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-       }
-
-       t = -FLOAT_START;
-       *( (unsigned char *)&exitpattern + 0 ) = *( (unsigned char *)&t + 3 );
-       *( (unsigned char *)&exitpattern + 1 ) = *( (unsigned char *)&t + 2 );
-       *( (unsigned char *)&exitpattern + 2 ) = *( (unsigned char *)&t + 1 );
-       *( (unsigned char *)&exitpattern + 3 ) = *( (unsigned char *)&t + 0 );
-
-       if ( ( input = fopen( filename, "rb" ) ) == 0 ) {
-               Error( "reader: could not open file '%s'", filename );
-       }
-
-       iLevel = 0;
-
-       fread( &magic, sizeof( int ), 1, input );
-       if ( BigLong( magic ) != MAGIC ) {
-               Error( "%s is not a Alias object separated triangle file, magic number is wrong.", filename );
-       }
-
-       ptri = malloc( MAXTRIANGLES * sizeof( triangle_t ) );
-
-       *pptri = ptri;
-
-       while ( feof( input ) == 0 ) {
-               if ( fread( &start,  sizeof( float ), 1, input ) < 1 ) {
-                       break;
-               }
-               *(int *)&start = BigLong( *(int *)&start );
-               if ( *(int *)&start != exitpattern ) {
-                       if ( start == FLOAT_START ) {
-                               /* Start of an object or group of objects. */
-                               i = -1;
-                               do {
-                                       /* There are probably better ways to read a string from */
-                                       /* a file, but this does allow you to do error checking */
-                                       /* (which I'm not doing) on a per character basis.      */
-                                       ++i;
-                                       fread( &( name[i] ), sizeof( char ), 1, input );
-                               } while ( name[i] != '\0' );
-
-//                             indent();
-//                             fprintf(stdout,"OBJECT START: %s\n",name);
-                               fread( &count, sizeof( int ), 1, input );
-                               count = BigLong( count );
-                               ++iLevel;
-                               if ( count != 0 ) {
-//                                     indent();
-//                                     fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
-
-                                       i = -1;
-                                       do {
-                                               ++i;
-                                               fread( &( tex[i] ), sizeof( char ), 1, input );
-                                       } while ( tex[i] != '\0' );
-
-//                                     indent();
-//                                     fprintf(stdout,"  Object texture name: '%s'\n",tex);
-                               }
-
-                               /* Else (count == 0) this is the start of a group, and */
-                               /* no texture name is present. */
-                       }
-                       else if ( start == FLOAT_END ) {
-                               /* End of an object or group. Yes, the name should be */
-                               /* obvious from context, but it is in here just to be */
-                               /* safe and to provide a little extra information for */
-                               /* those who do not wish to write a recursive reader. */
-                               /* Mia culpa. */
-                               --iLevel;
-                               i = -1;
-                               do {
-                                       ++i;
-                                       fread( &( name[i] ), sizeof( char ), 1, input );
-                               } while ( name[i] != '\0' );
-
-//                             indent();
-//                             fprintf(stdout,"OBJECT END: %s\n",name);
-                               continue;
-                       }
-               }
-
-//
-// read the triangles
-//
-               for ( i = 0; i < count; ++i ) {
-                       int j;
-
-                       fread( &tri, sizeof( tf_triangle ), 1, input );
-                       ByteSwapTri( &tri );
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               int k;
-
-                               for ( k = 0 ; k < 3 ; k++ )
-                               {
-                                       ptri->verts[j][k] = tri.pt[j].p.v[k];
-                               }
-                       }
-
-                       ptri++;
-
-                       if ( ( ptri - *pptri ) >= MAXTRIANGLES ) {
-                               Error( "Error: too many triangles; increase MAXTRIANGLES\n" );
-                       }
-               }
-       }
-
-       *numtriangles = ptri - *pptri;
-
-       fclose( input );
-
-       DefaultNodesList( nodesList,num_mesh_nodes,numtriangles );
-}
-
-
-//==========================================================================
-//
-// LoadHRC
-//
-//==========================================================================
-
-float scaling[3];
-float rotation[3];
-float translation[3];
-static char     *hrc_name;
-
-struct
-{
-       float v[3];
-} vList[8192];
-
-void HandleHRCModel( triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
-                                        int ActiveNode, int Depth, int numVerts ){
-       void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex );
-
-       int i, j;
-       int vertexCount;
-       int triCount;
-       triangle_t  *tList;
-       mesh_node_t *meshNode;
-       float x, y, z;
-       float x2, y2, z2;
-       float rx, ry, rz;
-       tokenType_t nextToken;
-       float orig_scaling[3];
-       float orig_rotation[3];
-       float orig_translation[3];
-       int start_tri;
-       int pos,bit;
-       int vertIndexBase;
-
-       // Update Node Info
-       if ( nodesList ) {
-               TK_BeyondRequire( TK_NAME, TK_STRING );
-
-               if ( Depth == 0 || tk_String[0] == '_' ) { // Root
-                       ActiveNode = *num_mesh_nodes;
-                       ( *num_mesh_nodes )++;
-                       if ( ( *num_mesh_nodes ) > MAX_FM_MESH_NODES ) {
-                               Error( "Too many mesh nodes in file %s\n", hrc_name );
-                       }
-                       meshNode = &( *nodesList )[ActiveNode];
-
-//                     memset(meshNode, 0, sizeof(mesh_node_t));
-                       strcpy( meshNode->name, tk_String );
-
-                       memset( meshNode->tris, 0, sizeof( meshNode->tris ) );
-                       memset( meshNode->verts, 0, sizeof( meshNode->verts ) );
-
-                       meshNode->start_glcmds = 0;
-                       meshNode->num_glcmds = 0;
-                       vertIndexBase = 0;
-               }
-               else
-               {   // Childs under the children
-                       meshNode = &( *nodesList )[ActiveNode];
-                       vertIndexBase = numVerts;
-               }
-       }
-       else
-       {
-               meshNode = NULL;
-       }
-
-
-       // Get the scaling, rotation, and translation values
-       TK_Beyond( TK_SCALING );
-       for ( i = 0; i < 3; i++ )
-       {
-               orig_scaling[i] = scaling[i];
-
-               TK_Require( TK_FLOATNUMBER );
-               scaling[i] *= tk_FloatNumber;
-
-               TK_Fetch();
-       }
-       TK_Beyond( TK_ROTATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               orig_rotation[i] = rotation[i];
-
-               TK_Require( TK_FLOATNUMBER );
-               rotation[i] = tk_FloatNumber;
-
-               TK_Fetch();
-       }
-       TK_Beyond( TK_TRANSLATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               orig_translation[i] = translation[i];
-
-               TK_Require( TK_FLOATNUMBER );
-               translation[i] += tk_FloatNumber;
-
-               TK_Fetch();
-       }
-
-       rx = ( ( rotation[0] - 90.0 ) / 360.0 ) * 2.0 * M_PI;
-       ry = ( rotation[2] / 360.0 ) * 2.0 * M_PI;
-       rz = ( rotation[1] / 360.0 ) * 2.0 * M_PI;
-
-       // rjr - might not work if there an item doesn't have a mesh
-       nextToken = tk_Token;
-       if ( nextToken == TK_ACTOR_DATA ) {
-               while ( nextToken != TK_MODEL && nextToken != TK_RBRACE )
-               {
-                       nextToken = TK_Fetch();
-               }
-       }
-
-       while ( nextToken == TK_SPLINE )
-       {   // spline node has two right braces
-               nextToken = TK_Beyond( TK_RBRACE );
-               nextToken = TK_Beyond( TK_RBRACE );
-       }
-
-       while ( nextToken == TK_MATERIAL )
-       {
-               nextToken = TK_Beyond( TK_RBRACE );
-       }
-
-       while ( nextToken == TK_MODEL )
-       {
-               HandleHRCModel( triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth + 1, 0 );
-
-               nextToken = TK_Fetch();
-       }
-
-       if ( nextToken == TK_MESH ) {
-               // Get all the tri and vertex info
-               TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
-               vertexCount = tk_IntNumber;
-               for ( i = 0; i < vertexCount; i++ )
-               {
-                       TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
-                       if ( tk_IntNumber != i ) {
-                               Error( "File '%s', line %d:\nVertex index mismatch.\n",
-                                          tk_SourceName, tk_Line );
-                       }
-                       TK_Beyond( TK_POSITION );
-                       // Apply the scaling, rotation, and translation in the order
-                       // specified in the HRC file.  This could be wrong.
-                       TK_Require( TK_FLOATNUMBER );
-                       x = tk_FloatNumber * scaling[0];
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       y = tk_FloatNumber * scaling[1];
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       z = tk_FloatNumber * scaling[2];
-
-                       y2 = y * cos( rx ) + z*sin( rx );
-                       z2 = -y*sin( rx ) + z*cos( rx );
-                       y = y2;
-                       z = z2;
-
-                       x2 = x * cos( ry ) - z*sin( ry );
-                       z2 = x * sin( ry ) + z*cos( ry );
-                       x = x2;
-                       z = z2;
-
-                       x2 = x * cos( rz ) + y*sin( rz );
-                       y2 = -x*sin( rz ) + y*cos( rz );
-                       x = x2;
-                       y = y2;
-
-                       vList[i].v[0] = x + translation[0];
-                       vList[i].v[1] = y - translation[2];
-                       vList[i].v[2] = z + translation[1];
-               }
-               TK_BeyondRequire( TK_POLYGONS, TK_INTNUMBER );
-               triCount = tk_IntNumber;
-               if ( triCount >= MAXTRIANGLES ) {
-                       Error( "Too many triangles in file %s\n", hrc_name );
-               }
-
-               start_tri = *triangleCount;
-               *triangleCount += triCount;
-
-               tList = *triList;
-
-               for ( i = 0; i < triCount; i++ )
-               {
-                       if ( meshNode ) { // Update the node
-                               pos = ( i + start_tri ) >> 3;
-                               bit = 1 << ( ( i + start_tri ) & 7 );
-                               meshNode->tris[pos] |= bit;
-                       }
-
-                       TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
-                       if ( tk_IntNumber != i ) {
-                               Error( "File '%s', line %d:\nTriangle index mismatch.\n",
-                                          tk_SourceName, tk_Line );
-                       }
-                       TK_BeyondRequire( TK_NODES, TK_INTNUMBER );
-                       if ( tk_IntNumber != 3 ) {
-                               Error( "File '%s', line %d:\nBad polygon vertex count: %d.",
-                                          tk_SourceName, tk_Line, tk_IntNumber );
-                       }
-                       tList[i + start_tri].HasUV = true;
-                       for ( j = 0; j < 3; j++ )
-                       {
-                               TK_BeyondRequire( TK_LBRACKET, TK_INTNUMBER );
-                               if ( tk_IntNumber != j ) {
-                                       Error( "File '%s', line %d:\nTriangle vertex index"
-                                                  " mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
-                                                  tk_IntNumber, j );
-                               }
-                               TK_BeyondRequire( TK_VERTEX, TK_INTNUMBER );
-
-                               tList[i + start_tri].verts[2 - j][0] = vList[tk_IntNumber].v[0];
-                               tList[i + start_tri].verts[2 - j][1] = vList[tk_IntNumber].v[1];
-                               tList[i + start_tri].verts[2 - j][2] = vList[tk_IntNumber].v[2];
-#if 1
-                               tList[i + start_tri].indicies[2 - j] = tk_IntNumber + vertIndexBase;
-#endif
-                               TK_BeyondRequire( TK_UVTEXTURE, TK_FLOATNUMBER );
-                               tList[i + start_tri].uv[2 - j][0] = tk_FloatNumber;
-                               TK_Fetch();
-                               TK_Require( TK_FLOATNUMBER );
-                               tList[i + start_tri].uv[2 - j][1] = tk_FloatNumber;
-                       }
-
-                       /*              printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-                                   "  v2: %f, %f, %f\n", i,
-                                   tList[i].verts[0][0],
-                                   tList[i].verts[0][1],
-                                   tList[i].verts[0][2],
-                                   tList[i].verts[1][0],
-                                   tList[i].verts[1][1],
-                                   tList[i].verts[1][2],
-                                   tList[i].verts[2][0],
-                                   tList[i].verts[2][1],
-                                   tList[i].verts[2][2]);
-                        */
-               }
-
-               TK_Beyond( TK_RBRACE );
-               TK_Beyond( TK_RBRACE );
-
-               if ( tk_Token == TK_EDGES ) {
-                       //      TK_Beyond(TK_EDGES);
-                       TK_Beyond( TK_RBRACE );
-               }
-
-               scaling[0] = scaling[1] = scaling[2] = 1.0;
-               //      rotation[0] = rotation[1] = rotation[2] = 0.0;
-               //      translation[0] = translation[1] = translation[2] = 0.0;
-
-               // See if there are any other models belonging to this node
-
-#if 1
-               TK_Fetch();
-
-               nextToken = tk_Token;
-               if ( nextToken == TK_CLUSTERS ) {
-                       if ( g_skelModel.clustered == -1 ) {
-                               ReadHRCClusterList( meshNode, vertIndexBase );
-                       }
-                       else
-                       {
-                               nextToken = TK_Get( TK_CLUSTER_NAME );
-
-                               while ( nextToken == TK_CLUSTER_NAME )
-                               {
-                                       TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
-                                       nextToken = TK_Fetch();
-                               }
-                       }
-
-                       // one right brace follow the list of clusters
-                       nextToken = TK_Beyond( TK_RBRACE );
-               }
-               else
-               {
-                       if ( g_skelModel.clustered == -1 && !vertIndexBase ) {
-                               meshNode->clustered = false;
-                       }
-               }
-#endif
-
-               nextToken = tk_Token;
-               if ( nextToken == TK_SPLINE ) {
-                       while ( nextToken == TK_SPLINE )
-                       {   // spline node has two right braces
-                               nextToken = TK_Beyond( TK_RBRACE );
-                               nextToken = TK_Beyond( TK_RBRACE );
-                       }
-
-                       nextToken = TK_Beyond( TK_RBRACE );
-               }
-
-               while ( nextToken == TK_MATERIAL )
-               {
-                       nextToken = TK_Beyond( TK_RBRACE );
-               }
-
-               while ( nextToken == TK_MODEL )
-               {
-                       HandleHRCModel( triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth + 1, vertexCount + vertIndexBase );
-
-                       nextToken = TK_Fetch();
-               }
-       }
-
-       for ( i = 0; i < 3; i++ )
-       {
-               scaling[i] = orig_scaling[i];
-               rotation[i] = orig_rotation[i];
-               translation[i] = orig_translation[i];
-       }
-}
-
-static void LoadHRC( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
-       if ( nodesList ) {
-               *num_mesh_nodes = 0;
-
-               if ( !*nodesList ) {
-                       *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-               }
-       }
-
-       hrc_name = fileName;
-
-       scaling[0] = scaling[1] = scaling[2] = 1.0;
-       rotation[0] = rotation[1] = rotation[2] = 0.0;
-       translation[0] = translation[1] = translation[2] = 0.0;
-
-       *triangleCount = 0;
-       *triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
-       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       // prime it
-       TK_Beyond( TK_MODEL );
-
-       HandleHRCModel( triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0 );
-       TK_CloseSource();
-}
-
-//==========================================================================
-//
-// LoadHTR
-//
-//==========================================================================
-/*
-   static int Version2;
-
-   void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
-                           int ActiveNode, int Depth, int numVerts)
-   {
-    int                        i, j;
-    int                        vertexCount;
-    int                        vertexNum;
-    int                        triCount;
-    float              origin[3];
-    triangle_t *tList;
-    float              x, y, z;
-    float              x2, y2, z2;
-    float              rx, ry, rz;
-    mesh_node_t *meshNode;
-    int                        pos,bit;
-    int                        vertIndexBase;
-    int                        start_tri;
-
-    if (nodesList)
-    {
-        TK_BeyondRequire(TK_NAME, TK_STRING);
-
-        if (Depth == 0 || tk_String[0] == '_')
-        {      // Root
-            ActiveNode = *num_mesh_nodes;
-            (*num_mesh_nodes)++;
-            if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
-            {
-                Error("Too many mesh nodes in file %s\n", hrc_name);
-            }
-            meshNode = &(*nodesList)[ActiveNode];
-
-   //                  memset(meshNode, 0, sizeof(mesh_node_t));
-            strcpy(meshNode->name, tk_String);
-
-            memset(meshNode->tris, 0, sizeof(meshNode->tris));
-            memset(meshNode->verts, 0, sizeof(meshNode->verts));
-
-            meshNode->start_glcmds = 0;
-            meshNode->num_glcmds = 0;
-            vertIndexBase = 0;
-        }
-        else
-        {      // Childs under the children
-            meshNode = &(*nodesList)[ActiveNode];
-            vertIndexBase = numVerts;
-        }
-    }
-    else
-    {
-        meshNode = NULL;
-    }
-
-    // Get vertex count
-    TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
-    vertexCount = tk_IntNumber;
-
-    // Get triangle count
-    TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
-    triCount = tk_IntNumber;
-    if(triCount >= MAXTRIANGLES)
-    {
-        Error("Too many triangles in file %s\n", hrc_name);
-    }
-
-    // Get origin
-    TK_Beyond(TK_ORIGIN);
-    TK_Require(TK_FLOATNUMBER);
-    origin[0] = tk_FloatNumber;
-    TK_FetchRequire(TK_FLOATNUMBER);
-    origin[1] = tk_FloatNumber;
-    TK_FetchRequire(TK_FLOATNUMBER);
-    origin[2] = tk_FloatNumber;
-
-    //rx = 90.0/360.0*2.0*M_PI;
-    rx = FixHTRRotateX/360.0*2.0*M_PI;
-    ry = FixHTRRotateY/360.0*2.0*M_PI;
-    rz = FixHTRRotateZ/360.0*2.0*M_PI;
-
-    // Get vertex list
-    for(i = 0; i < vertexCount; i++)
-    {
-        TK_FetchRequire(TK_VERTEX);
-        TK_FetchRequire(TK_FLOATNUMBER);
-        x = tk_FloatNumber-origin[0];
-        TK_FetchRequire(TK_FLOATNUMBER);
-        y = tk_FloatNumber-origin[1];
-        TK_FetchRequire(TK_FLOATNUMBER);
-        z = tk_FloatNumber-origin[2];
-
-        x += FixHTRTranslateX;
-        y += FixHTRTranslateY;
-        z += FixHTRTranslateZ;
-
-        y2 = y*cos(rx)-z*sin(rx);
-        z2 = y*sin(rx)+z*cos(rx);
-        y = y2;
-        z = z2;
-        x2 = x*cos(ry)+z*sin(ry);
-        z2 = -x*sin(ry)+z*cos(ry);
-        x = x2;
-        z = z2;
-        x2 = x*cos(rz)-y*sin(rz);
-        y2 = x*sin(rz)+y*cos(rz);
-        x = x2;
-        y = y2;
-
-        vList[i].v[0] = x;
-        vList[i].v[1] = y;
-        vList[i].v[2] = z;
-    }
-
-    start_tri = *triangleCount;
-   *triangleCount += triCount;
-
-    tList = *triList;
-
-    // Get face list
-    for(i = 0; i < triCount; i++)
-    {
-        if (meshNode)
-        {      // Update the node
-            pos = (i + start_tri) >> 3;
-            bit = 1 << ((i + start_tri) & 7 );
-            meshNode->tris[pos] |= bit;
-        }
-
-        TK_FetchRequire(TK_FACE);
-        TK_FetchRequire(TK_LPAREN);
-        for(j = 0; j < 3; j++)
-        {
-            TK_FetchRequire(TK_INTNUMBER);
-            vertexNum = tk_IntNumber-1;
-            if(vertexNum >= vertexCount)
-            {
-                Error("File '%s', line %d:\nVertex number"
-                    " >= vertexCount: %d\n", tk_SourceName, tk_Line,
-                    tk_IntNumber);
-            }
-            tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0];
-            tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1];
-            tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2];
-        }
-        TK_FetchRequire(TK_RPAREN);
-   #ifdef _QDATA
-        if (Version2)
-        {
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[0][0]=tk_FloatNumber;
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[0][1]=tk_FloatNumber;
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[1][0]=tk_FloatNumber;
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[1][1]=tk_FloatNumber;
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[2][0]=tk_FloatNumber;
-            TK_FetchRequire(TK_FLOATNUMBER);
-            tList[i+start_tri].uv[2][1]=tk_FloatNumber;
-            tList[i+start_tri].HasUV=1;
-        }
-        else
-            tList[i+start_tri].HasUV=0;
-   #endif
-   //          printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-   //                  "  v2: %f, %f, %f\n", i,
-   //                  tList[i].verts[0][0],
-   //                  tList[i].verts[0][1],
-   //                  tList[i].verts[0][2],
-   //                  tList[i].verts[1][0],
-   //                  tList[i].verts[1][1],
-   //                  tList[i].verts[1][2],
-   //                  tList[i].verts[2][0],
-   //                  tList[i].verts[2][1],
-   //                  tList[i].verts[2][2]);
-
-    }
-
-    TK_Fetch();
-
-    if (tk_Token == TK_VERTICES)
-    {
-        HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
-    }
-   }
-
-   static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
-   {
-    if (nodesList)
-    {
-   *num_mesh_nodes = 0;
-
-        if(!*nodesList)
-        {
-   *nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-        }
-    }
-
-    hrc_name = fileName;
-
-    scaling[0] = scaling[1] = scaling[2] = 1.0;
-    rotation[0] = rotation[1] = rotation[2] = 0.0;
-    translation[0] = translation[1] = translation[2] = 0.0;
-
-   *triangleCount = 0;
-   *triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-    memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
-
-    TK_OpenSource(fileName);
-
-    TK_Beyond(TK_C_HEXEN);
-    TK_Beyond(TK_C_TRIANGLES);
-    TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
-    if(tk_IntNumber != 1&&tk_IntNumber != 2)
-    {
-        Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
-            fileName);
-    }
-    Version2=(tk_IntNumber==2);
-
-
-    HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
-   }
-
- */
-
-static void LoadHTR( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes ){
-       int Version2 = 0;
-       int i, j;
-       int vertexCount;
-       int vertexNum;
-       struct
-       {
-               float v[3];
-       }           *vList;
-       int triCount;
-       float origin[3];
-       triangle_t  *tList;
-       float x, y, z;
-       float x2, y2, z2;
-       float rx, ry, rz;
-
-       if ( nodesList ) {
-               *num_mesh_nodes = 0;
-               *nodesList = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-       }
-
-       TK_OpenSource( fileName );
-
-       TK_Beyond( TK_C_HEXEN );
-       TK_Beyond( TK_C_TRIANGLES );
-       TK_BeyondRequire( TK_C_VERSION, TK_INTNUMBER );
-       if ( tk_IntNumber != 1 && tk_IntNumber != 2 ) {
-               Error( "Unsupported version (%d) in file %s\n", tk_IntNumber,
-                          fileName );
-       }
-       Version2 = ( tk_IntNumber == 2 );
-
-
-       // Get vertex count
-       TK_BeyondRequire( TK_VERTICES, TK_INTNUMBER );
-       vertexCount = tk_IntNumber;
-       vList = (void *) SafeMalloc( vertexCount * sizeof vList[0], "Vertex list" );
-
-       // Get triangle count
-       TK_BeyondRequire( TK_FACES, TK_INTNUMBER );
-       triCount = tk_IntNumber;
-       if ( triCount >= MAXTRIANGLES ) {
-               Error( "Too many triangles in file %s\n", fileName );
-       }
-       *triangleCount = triCount;
-       tList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
-       *triList = tList;
-       memset( *triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
-
-       // Get origin
-       TK_Beyond( TK_ORIGIN );
-       TK_Require( TK_FLOATNUMBER );
-       origin[0] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       origin[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       origin[2] = tk_FloatNumber;
-
-       //rx = 90.0/360.0*2.0*M_PI;
-       rx = FixHTRRotateX / 360.0 * 2.0 * M_PI;
-       ry = FixHTRRotateY / 360.0 * 2.0 * M_PI;
-       rz = FixHTRRotateZ / 360.0 * 2.0 * M_PI;
-
-       // Get vertex list
-       for ( i = 0; i < vertexCount; i++ )
-       {
-               TK_FetchRequire( TK_VERTEX );
-               TK_FetchRequire( TK_FLOATNUMBER );
-               x = tk_FloatNumber - origin[0];
-               TK_FetchRequire( TK_FLOATNUMBER );
-               y = tk_FloatNumber - origin[1];
-               TK_FetchRequire( TK_FLOATNUMBER );
-               z = tk_FloatNumber - origin[2];
-
-               x += FixHTRTranslateX;
-               y += FixHTRTranslateY;
-               z += FixHTRTranslateZ;
-
-               y2 = y * cos( rx ) - z*sin( rx );
-               z2 = y * sin( rx ) + z*cos( rx );
-               y = y2;
-               z = z2;
-               x2 = x * cos( ry ) + z*sin( ry );
-               z2 = -x*sin( ry ) + z*cos( ry );
-               x = x2;
-               z = z2;
-               x2 = x * cos( rz ) - y*sin( rz );
-               y2 = x * sin( rz ) + y*cos( rz );
-               x = x2;
-               y = y2;
-
-               vList[i].v[0] = x;
-               vList[i].v[1] = y;
-               vList[i].v[2] = z;
-       }
-
-       // Get face list
-       for ( i = 0; i < triCount; i++ )
-       {
-               TK_FetchRequire( TK_FACE );
-               TK_FetchRequire( TK_LPAREN );
-               for ( j = 0; j < 3; j++ )
-               {
-                       TK_FetchRequire( TK_INTNUMBER );
-                       vertexNum = tk_IntNumber - 1;
-                       if ( vertexNum >= vertexCount ) {
-                               Error( "File '%s', line %d:\nVertex number"
-                                          " >= vertexCount: %d\n", tk_SourceName, tk_Line,
-                                          tk_IntNumber );
-                       }
-                       tList[i].verts[2 - j][0] = vList[vertexNum].v[0];
-                       tList[i].verts[2 - j][1] = vList[vertexNum].v[1];
-                       tList[i].verts[2 - j][2] = vList[vertexNum].v[2];
-               }
-               TK_FetchRequire( TK_RPAREN );
-#if 1
-               if ( Version2 ) {
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[2][0] = fmod( 1000 + tk_FloatNumber,1 );
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[2][1] = fmod( 1000 + tk_FloatNumber,1 );
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[1][0] = fmod( 1000 + tk_FloatNumber,1 );
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[1][1] = fmod( 1000 + tk_FloatNumber,1 );
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[0][0] = fmod( 1000 + tk_FloatNumber,1 );
-                       TK_FetchRequire( TK_FLOATNUMBER );
-                       tList[i].uv[0][1] = fmod( 1000 + tk_FloatNumber,1 );
-                       tList[i].HasUV = 1;
-               }
-               else{
-                       tList[i].HasUV = 0;
-               }
-#endif
-/*             printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-            "  v2: %f, %f, %f\n", i,
-            tList[i].verts[0][0],
-            tList[i].verts[0][1],
-            tList[i].verts[0][2],
-            tList[i].verts[1][0],
-            tList[i].verts[1][1],
-            tList[i].verts[1][2],
-            tList[i].verts[2][0],
-            tList[i].verts[2][1],
-            tList[i].verts[2][2]);
- */
-       }
-
-       free( vList );
-       TK_CloseSource();
-       DefaultNodesList( nodesList,num_mesh_nodes,triangleCount );
-}
-
-//==========================================================================
-//
-// LoadTriangleList
-//
-//==========================================================================
-
-void LoadTriangleList( char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes ){
-       FILE    *file1;
-       int dot = '.';
-       char    *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-                       LoadHRC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".asc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-                       LoadASC( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       printf( " - assuming .ASC\n" );
-                       return;
-               }
-
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".tri" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-                       LoadTRI( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       printf( " - assuming .TRI\n" );
-                       return;
-               }
-
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".3ds" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-                       Load3DSTriangleList( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       printf( " - assuming .3DS\n" );
-                       return;
-               }
-
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".htr" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-                       LoadHTR( InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       printf( " - assuming .HTR\n" );
-                       return;
-               }
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-                       printf( "\n" );
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       }
-                       else if ( strcmp( dotstart,".asc" ) == 0 || strcmp( dotstart,".ASC" ) == 0 ) {
-                               LoadASC( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       }
-                       else if ( strcmp( dotstart,".tri" ) == 0 || strcmp( dotstart,".TRI" ) == 0 ) {
-                               LoadTRI( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       }
-                       else if ( strcmp( dotstart,".3ds" ) == 0 || strcmp( dotstart,".3DS" ) == 0 ) {
-                               Load3DSTriangleList( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       }
-                       else if ( strcmp( dotstart,".htr" ) == 0 || strcmp( dotstart,".HTR" ) == 0 ) {
-                               LoadHTR( fileName, triList, triangleCount, ppmnodes, num_mesh_nodes );
-                       }
-                       else
-                       {
-                               Error( "Could not open file '%s':\n",fileName );
-                               return;
-                       }
-               }
-               else    //failed to load file
-               {
-                       Error( "Could not open file '%s':\n",fileName );
-               }
-
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/common/trilib.h b/tools/quake2/qdata_heretic2/common/trilib.h
deleted file mode 100644 (file)
index 8dfd6d2..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// trilib.h: header file for loading triangles from an Alias triangle file
-//
-
-#include "fmodel.h"
-
-#define MAXTRIANGLES    MAX_FM_TRIANGLES
-
-typedef struct
-{
-       vec3_t verts[3];
-#if 1
-       int indicies[3];
-       float uv[3][2];
-       qboolean HasUV;
-#endif
-} triangle_t;
-
-#define NUM_CLUSTERS 8
-
-typedef struct
-{
-       char name[64];
-       byte tris[MAXTRIANGLES >> 3];
-       byte verts[MAX_FM_VERTS >> 3];
-       int start_glcmds, num_glcmds;
-
-       int *clusters[NUM_CLUSTERS];
-       struct IntListNode_s *vertLists[NUM_CLUSTERS];
-       int num_verts[NUM_CLUSTERS + 1];
-       int new_num_verts[NUM_CLUSTERS + 1];
-       qboolean clustered;
-} mesh_node_t;
-
-void LoadTriangleList( char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes );
diff --git a/tools/quake2/qdata_heretic2/fmodels.c b/tools/quake2/qdata_heretic2/fmodels.c
deleted file mode 100644 (file)
index 7d8df18..0000000
+++ /dev/null
@@ -1,3311 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qd_fmodel.h"
-#include "animcomp.h"
-#include "qd_skeletons.h"
-#include "skeletons.h"
-#include "qdata.h"
-#include "flex.h"
-#include "reference.h"
-
-#include <assert.h>
-
-/*
-   ========================================================================
-
-   .FM triangle flexible model file format
-
-   ========================================================================
- */
-
-//=================================================================
-
-#define NUMVERTEXNORMALS    162
-
-extern float avertexnormals[NUMVERTEXNORMALS][3];
-
-#define MAX_GROUPS  128
-
-typedef struct
-{
-       triangle_t triangle;
-       int group;
-} trigroup_t;
-
-#define TRIVERT_DIST    .1
-
-typedef struct
-{
-       int start_frame;
-       int num_frames;
-       int degrees;
-       char *mat;
-       char *ccomp;
-       char *cbase;
-       float *cscale;
-       float *coffset;
-       float trans[3];
-       float scale[3];
-       float bmin[3];
-       float bmax[3];
-} fmgroup_t;
-
-//================================================================
-
-// Initial
-fmheader_t fmheader;
-
-// Skin
-extern char g_skins[MAX_FM_SKINS][64];
-
-// ST Coord
-extern fmstvert_t base_st[MAX_FM_VERTS];
-
-// Triangles
-extern fmtriangle_t triangles[MAX_FM_TRIANGLES];
-
-// Frames
-fmframe_t g_frames[MAX_FM_FRAMES];
-//fmframe_t    *g_FMframes;
-
-// GL Commands
-extern int commands[16384];
-extern int numcommands;
-
-
-//
-// varibles set by commands
-//
-extern float scale_up;                              // set by $scale
-extern vec3_t adjust;                               // set by $origin
-extern int g_fixedwidth, g_fixedheight;             // set by $skinsize
-extern char modelname[64];                          // set by $modelname
-
-
-extern char        *g_outputDir;
-
-
-// Mesh Nodes
-mesh_node_t *pmnodes = NULL;
-fmmeshnode_t mesh_nodes[MAX_FM_MESH_NODES];
-
-fmgroup_t groups[MAX_GROUPS];
-int num_groups;
-int frame_to_group[MAX_FM_FRAMES];
-
-//
-// variables set by command line arguments
-//
-qboolean g_no_opimizations = false;
-
-
-//
-// base frame info
-//
-static int triangle_st[MAX_FM_TRIANGLES][3][2];
-
-
-// number of gl vertices
-extern int numglverts;
-// indicates if a triangle has already been used in a glcmd
-extern int used[MAX_FM_TRIANGLES];
-// indicates if a triangle has translucency in it or not
-static qboolean translucent[MAX_FM_TRIANGLES];
-
-// main output file handle
-extern FILE         *headerouthandle;
-// output sizes of buildst()
-static int skin_width, skin_height;
-
-
-// statistics
-static int total_skin_pixels;
-static int skin_pixels_used;
-
-int ShareVertex( trigroup_t trione, trigroup_t tritwo );
-float DistBetween( vec3_t point1, vec3_t point2 );
-int GetNumTris( trigroup_t *tris, int group );
-void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles );
-void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts );
-void NewDrawLine( int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height );
-
-#if !GDEF_OS_WINDOWS
-
-void strupr( char *string ){
-       int i;
-
-       for ( i = 0 ; i < strlen( string ); i++ )
-               toupper( string[i] );
-
-       return;
-}
-
-#endif
-//==============================================================
-
-/*
-   ===============
-   ClearModel
-   ===============
- */
-static void ClearModel( void ){
-       memset( &fmheader, 0, sizeof( fmheader ) );
-
-       modelname[0] = 0;
-       scale_up = 1.0;
-       VectorCopy( vec3_origin, adjust );
-       g_fixedwidth = g_fixedheight = 0;
-       g_skipmodel = false;
-       num_groups = 0;
-
-       if ( pmnodes ) {
-               free( pmnodes );
-               pmnodes = NULL;
-       }
-
-       ClearSkeletalModel();
-}
-
-
-extern void H_printf( char *fmt, ... );
-
-
-void WriteHeader( FILE *FH, char *Ident, int Version, int Size, void *Data ){
-       header_t header;
-       static long pos = -1;
-       long CurrentPos;
-
-       if ( Size == 0 ) { // Don't write out empty packets
-               return;
-       }
-
-       if ( pos != -1 ) {
-               CurrentPos = ftell( FH );
-               Size = CurrentPos - pos + sizeof( header_t );
-               fseek( FH, pos, SEEK_SET );
-               pos = -2;
-       }
-       else if ( Size == -1 ) {
-               pos = ftell( FH );
-       }
-
-       memset( &header,0,sizeof( header ) );
-       strcpy( header.ident,Ident );
-       header.version = Version;
-       header.size = Size;
-
-       SafeWrite( FH, &header, sizeof( header ) );
-
-       if ( Data ) {
-               SafeWrite( FH, Data, Size );
-       }
-
-       if ( pos == -2 ) {
-               pos = -1;
-               fseek( FH, 0, SEEK_END );
-       }
-}
-
-/*
-   ============
-   WriteModelFile
-   ============
- */
-static void WriteModelFile( FILE *modelouthandle ){
-       int i;
-       int j, k;
-       fmframe_t       *in;
-       fmaliasframe_t  *out;
-       byte buffer[MAX_FM_VERTS * 4 + 128];
-       float v;
-       int c_on, c_off;
-       IntListNode_t   *current, *toFree;
-       qboolean framesWritten = false;
-       size_t temp,size = 0;
-
-       // probably should do this dynamically one of these days
-       struct
-       {
-               float scale[3];         // multiply byte verts by this
-               float translate[3];         // then add this
-       } outFrames[MAX_FM_FRAMES];
-
-#define DATA_SIZE 0x60000       // 384K had better be enough, particularly for the reference points
-       byte data[DATA_SIZE];
-       byte data2[DATA_SIZE];
-
-       fmheader.num_glcmds = numcommands;
-       fmheader.framesize = (int)&( (fmaliasframe_t *)0 )->verts[fmheader.num_xyz];
-
-       WriteHeader( modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof( fmheader ), &fmheader );
-
-       //
-       // write out the skin names
-       //
-
-       WriteHeader( modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins );
-
-       //
-       // write out the texture coordinates
-       //
-       c_on = c_off = 0;
-       for ( i = 0 ; i < fmheader.num_st ; i++ )
-       {
-               base_st[i].s = LittleShort( base_st[i].s );
-               base_st[i].t = LittleShort( base_st[i].t );
-       }
-
-       WriteHeader( modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof( base_st[0] ), base_st );
-
-       //
-       // write out the triangles
-       //
-       WriteHeader( modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof( fmtriangle_t ), NULL );
-
-       for ( i = 0 ; i < fmheader.num_tris ; i++ )
-       {
-               int j;
-               fmtriangle_t tri;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
-                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
-               }
-
-               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
-       }
-
-       if ( !num_groups ) {
-               //
-               // write out the frames
-               //
-               WriteHeader( modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL );
-               //      WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
-
-               for ( i = 0 ; i < fmheader.num_frames ; i++ )
-               {
-                       in = &g_frames[i];
-                       out = (fmaliasframe_t *)buffer;
-
-                       strcpy( out->name, in->name );
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
-                               out->translate[j] = in->mins[j];
-
-                               outFrames[i].scale[j] = out->scale[j];
-                               outFrames[i].translate[j] = out->translate[j];
-                       }
-
-                       for ( j = 0 ; j < fmheader.num_xyz ; j++ )
-                       {
-                               // all of these are byte values, so no need to deal with endianness
-                               out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-                               for ( k = 0 ; k < 3 ; k++ )
-                               {
-                                       // scale to byte values & min/max check
-                                       v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
-
-                                       // clamp, so rounding doesn't wrap from 255.6 to 0
-                                       if ( v > 255.0 ) {
-                                               v = 255.0;
-                                       }
-                                       if ( v < 0 ) {
-                                               v = 0;
-                                       }
-                                       out->verts[j].v[k] = v;
-                               }
-                       }
-
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               out->scale[j] = LittleFloat( out->scale[j] );
-                               out->translate[j] = LittleFloat( out->translate[j] );
-                       }
-
-                       SafeWrite( modelouthandle, out, fmheader.framesize );
-               }
-
-               // Go back and finish the header
-               //      WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
-       }
-       else
-       {
-               WriteHeader( modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN * fmheader.num_frames, NULL );
-               for ( i = 0 ; i < fmheader.num_frames ; i++ )
-               {
-                       in = &g_frames[i];
-                       SafeWrite( modelouthandle,in->name,FRAME_NAME_LEN );
-               }
-               WriteHeader( modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL );
-               in = &g_frames[0];
-               for ( j = 0 ; j < fmheader.num_xyz ; j++ )
-                       SafeWrite( modelouthandle,&in->v[j].lightnormalindex,1 );
-       }
-
-       //
-       // write out glcmds
-       //
-       WriteHeader( modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands * 4, commands );
-
-       //
-       // write out mesh nodes
-       //
-       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-       {
-               memcpy( mesh_nodes[i].tris, pmnodes[i].tris, sizeof( mesh_nodes[i].tris ) );
-               memcpy( mesh_nodes[i].verts, pmnodes[i].verts, sizeof( mesh_nodes[i].verts ) );
-               mesh_nodes[i].start_glcmds = LittleShort( (short)pmnodes[i].start_glcmds );
-               mesh_nodes[i].num_glcmds = LittleShort( (short)pmnodes[i].num_glcmds );
-       }
-
-       WriteHeader( modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof( fmmeshnode_t ) * fmheader.num_mesh_nodes, mesh_nodes );
-
-       if ( num_groups ) {
-
-/*
-   typedef struct
-   {
-    int                        start_frame;
-    int                        num_frames;
-    int                        degrees;
-    char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char)
-    char *ccomp; g->num_frames*g->degrees*sizeof(char)
-    char *cbase; fmheader.num_xyz*3*sizeof(unsigned char)
-    float *cscale; g->degrees*sizeof(float)
-    float *coffset; g->degrees*sizeof(float)
-    float trans[3]; 3*sizeof(float)
-    float scale[3]; 3*sizeof(float)
-   } fmgroup_t;
- */
-               int tmp,k;
-               fmgroup_t *g;
-               size = sizeof( int ) + fmheader.num_frames * sizeof( int );
-               for ( k = 0; k < num_groups; k++ )
-               {
-                       g = &groups[k];
-                       size += sizeof( int ) * 3;
-                       size += fmheader.num_xyz * 3 * g->degrees * sizeof( char );
-                       size += g->num_frames * g->degrees * sizeof( char );
-                       size += fmheader.num_xyz * 3 * sizeof( unsigned char );
-                       size += g->degrees * sizeof( float );
-                       size += g->degrees * sizeof( float );
-                       size += 12 * sizeof( float );
-               }
-               WriteHeader( modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL );
-               SafeWrite( modelouthandle,&num_groups,sizeof( int ) );
-               SafeWrite( modelouthandle,frame_to_group,sizeof( int ) * fmheader.num_frames );
-
-               for ( k = 0; k < num_groups; k++ )
-               {
-                       g = &groups[k];
-                       tmp = LittleLong( g->start_frame );
-                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
-                       tmp = LittleLong( g->num_frames );
-                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
-                       tmp = LittleLong( g->degrees );
-                       SafeWrite( modelouthandle,&tmp,sizeof( int ) );
-
-                       SafeWrite( modelouthandle,g->mat,fmheader.num_xyz * 3 * g->degrees * sizeof( char ) );
-                       SafeWrite( modelouthandle,g->ccomp,g->num_frames * g->degrees * sizeof( char ) );
-                       SafeWrite( modelouthandle,g->cbase,fmheader.num_xyz * 3 * sizeof( unsigned char ) );
-                       SafeWrite( modelouthandle,g->cscale,g->degrees * sizeof( float ) );
-                       SafeWrite( modelouthandle,g->coffset,g->degrees * sizeof( float ) );
-                       SafeWrite( modelouthandle,g->trans,3 * sizeof( float ) );
-                       SafeWrite( modelouthandle,g->scale,3 * sizeof( float ) );
-                       SafeWrite( modelouthandle,g->bmin,3 * sizeof( float ) );
-                       SafeWrite( modelouthandle,g->bmax,3 * sizeof( float ) );
-                       free( g->mat );
-                       free( g->ccomp );
-                       free( g->cbase );
-                       free( g->cscale );
-                       free( g->coffset );
-               }
-       }
-
-       // write the skeletal info
-       if ( g_skelModel.type != SKEL_NULL ) {
-               size = 0;
-
-               temp = sizeof( int );     // change this to a byte
-               memcpy( data + size, &g_skelModel.type, temp );
-               size += temp;
-
-               // number of joints
-               temp = sizeof( int );     // change this to a byte
-               memcpy( data + size, &numJointsInSkeleton[g_skelModel.type], temp );
-               size += temp;
-
-               // number of verts in each joint cluster
-               temp = sizeof( int ) * numJointsInSkeleton[g_skelModel.type]; // change this to shorts
-               memcpy( data + size, &g_skelModel.new_num_verts[1], temp );
-               size += temp;
-
-               // cluster verts
-               for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
-               {
-                       current = g_skelModel.vertLists[i];
-                       while ( current )
-                       {
-                               temp = sizeof( int ); // change this to a short
-                               memcpy( data + size, &current->data, temp );
-                               size += temp;
-                               toFree = current;
-                               current = current->next;
-                               free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-                       }
-               }
-
-               if ( !num_groups ) { // joints are stored with regular verts for compressed models
-                       framesWritten = true;
-
-                       temp = sizeof( int ); // change this to a byte
-                       memcpy( data + size, &framesWritten, temp );
-                       size += temp;
-
-                       for ( i = 0; i < fmheader.num_frames; ++i )
-                       {
-                               in = &g_frames[i];
-
-                               for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j )
-                               {
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               // scale to byte values & min/max check
-                                               v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data + size, &v, temp );
-                                               size += temp;
-                                       }
-
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data + size, &v, temp );
-                                               size += temp;
-                                       }
-
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data + size, &v, temp );
-                                               size += temp;
-                                       }
-                               }
-                       }
-
-               }
-               else
-               {
-                       temp = sizeof( int ); // change this to a byte
-                       memcpy( data + size, &framesWritten, temp );
-                       size += temp;
-               }
-
-               WriteHeader( modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data );
-       }
-
-       if ( g_skelModel.references != REF_NULL ) {
-               int refnum;
-
-               size = 0;
-               if ( RefPointNum <= 0 ) { // Hard-coded labels
-                       refnum = numReferences[g_skelModel.references];
-               }
-               else
-               {   // Labels indicated in QDT
-                       refnum = RefPointNum;
-               }
-
-               temp = sizeof( int ); // change this to a byte
-               memcpy( data2 + size, &g_skelModel.references, temp );
-               size += temp;
-
-               if ( !num_groups ) {
-                       framesWritten = true;
-
-                       temp = sizeof( int ); // change this to a byte
-                       memcpy( data2 + size, &framesWritten, temp );
-                       size += temp;
-
-                       for ( i = 0; i < fmheader.num_frames; ++i )
-                       {
-                               in = &g_frames[i];
-
-                               for ( j = 0 ; j < refnum; ++j )
-                               {
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               // scale to byte values & min/max check
-                                               v = Q_rint( ( in->references[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data2 + size, &v, temp );
-                                               size += temp;
-                                       }
-
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               v = Q_rint( ( in->references[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data2 + size, &v, temp );
-                                               size += temp;
-                                       }
-
-                                       for ( k = 0 ; k < 3 ; k++ )
-                                       {
-                                               v = Q_rint( ( in->references[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                                               // write out origin as a float since they arn't clamped
-                                               temp = sizeof( float );   // change this to a short
-                                               assert( size + temp < DATA_SIZE );
-                                               memcpy( data2 + size, &v, temp );
-                                               size += temp;
-                                       }
-                               }
-                       }
-               }
-               else    // FINISH ME: references need to be stored with regular verts for compressed models
-               {
-                       framesWritten = false;
-
-                       temp = sizeof( int ); // change this to a byte
-                       memcpy( data2 + size, &framesWritten, temp );
-                       size += temp;
-               }
-
-               WriteHeader( modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2 );
-       }
-}
-
-static void CompressFrames(){
-       fmgroup_t *g;
-       int i,j,k;
-       fmframe_t   *in;
-
-       j = 0;
-       for ( i = 0; i < fmheader.num_frames; i++ )
-       {
-               while ( i >= groups[j].start_frame + groups[j].num_frames && j < num_groups - 1 )
-                       j++;
-               frame_to_group[i] = j;
-       }
-
-       for ( k = 0; k < num_groups; k++ )
-       {
-               g = &groups[k];
-
-               printf( "\nCompressing Frames for group %i...\n", k );
-               AnimCompressInit( g->num_frames,fmheader.num_xyz,g->degrees );
-               for ( i = 0; i < g->num_frames; i++ )
-               {
-                       in = &g_frames[i + g->start_frame];
-                       for ( j = 0; j < fmheader.num_xyz; j++ )
-                               AnimSetFrame( i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2] );
-               }
-               AnimCompressDoit();
-               g->mat = (char *) SafeMalloc( fmheader.num_xyz * 3 * g->degrees * sizeof( char ), "CompressFrames" );
-               g->ccomp = (char *) SafeMalloc( g->num_frames * g->degrees * sizeof( char ), "CompressFrames" );
-               g->cbase = (char *) SafeMalloc( fmheader.num_xyz * 3 * sizeof( unsigned char ), "CompressFrames" );
-               g->cscale = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" );
-               g->coffset = (float *) SafeMalloc( g->degrees * sizeof( float ), "CompressFrames" );
-               AnimCompressToBytes( g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax );
-               AnimCompressEnd();
-       }
-}
-
-static void OptimizeVertices( void ){
-       qboolean vert_used[MAX_FM_VERTS];
-       short vert_replacement[MAX_FM_VERTS];
-       int i,j,k,l,pos,bit,set_pos,set_bit;
-       fmframe_t   *in;
-       qboolean Found;
-       int num_unique;
-       static IntListNode_t *newVertLists[NUM_CLUSTERS];
-       static int newNum_verts[NUM_CLUSTERS];
-       IntListNode_t *current, *next;
-
-       printf( "Optimizing vertices..." );
-
-       memset( vert_used, 0, sizeof( vert_used ) );
-
-       if ( g_skelModel.clustered == true ) {
-               memset( newNum_verts, 0, sizeof( newNum_verts ) );
-               memset( newVertLists, 0, sizeof( newVertLists ) );
-       }
-
-       num_unique = 0;
-
-       // search for common points among all the frames
-       for ( i = 0 ; i < fmheader.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-
-               for ( j = 0; j < fmheader.num_xyz; j++ )
-               {
-                       for ( k = 0,Found = false; k < j; k++ )
-                       {   // starting from the beginning always ensures vert_replacement points to the first point in the array
-                               if ( in->v[j].v[0] == in->v[k].v[0] &&
-                                        in->v[j].v[1] == in->v[k].v[1] &&
-                                        in->v[j].v[2] == in->v[k].v[2] ) {
-                                       Found = true;
-                                       vert_replacement[j] = k;
-                                       break;
-                               }
-
-                       }
-
-                       if ( !Found ) {
-                               if ( !vert_used[j] ) {
-                                       num_unique++;
-                               }
-                               vert_used[j] = true;
-                       }
-               }
-       }
-
-       // recompute the light normals
-       for ( i = 0 ; i < fmheader.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-
-               for ( j = 0; j < fmheader.num_xyz; j++ )
-               {
-                       if ( !vert_used[j] ) {
-                               k = vert_replacement[j];
-
-                               VectorAdd( in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum );
-                               in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++;
-                       }
-               }
-
-               for ( j = 0 ; j < fmheader.num_xyz ; j++ )
-               {
-                       vec3_t v;
-                       float maxdot;
-                       int maxdotindex;
-                       int c;
-
-                       c = in->v[j].vnorm.numnormals;
-                       if ( !c ) {
-                               Error( "Vertex with no triangles attached" );
-                       }
-
-                       VectorScale( in->v[j].vnorm.normalsum, 1.0 / c, v );
-                       VectorNormalize( v, v );
-
-                       maxdot = -999999.0;
-                       maxdotindex = -1;
-
-                       for ( k = 0 ; k < NUMVERTEXNORMALS ; k++ )
-                       {
-                               float dot;
-
-                               dot = DotProduct( v, avertexnormals[k] );
-                               if ( dot > maxdot ) {
-                                       maxdot = dot;
-                                       maxdotindex = k;
-                               }
-                       }
-
-                       in->v[j].lightnormalindex = maxdotindex;
-               }
-       }
-
-       // create substitution list
-       num_unique = 0;
-       for ( i = 0; i < fmheader.num_xyz; i++ )
-       {
-               if ( vert_used[i] ) {
-                       vert_replacement[i] = num_unique;
-                       num_unique++;
-               }
-               else
-               {
-                       vert_replacement[i] = vert_replacement[vert_replacement[i]];
-               }
-
-               // vert_replacement[i] is the new index, i is the old index
-               // need to add the new index to the cluster list if old index was in it
-               if ( g_skelModel.clustered == true ) {
-                       for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k )
-                       {
-                               for ( l = 0, current = g_skelModel.vertLists[k];
-                                         l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next )
-                               {
-                                       if ( current->data == i ) {
-                                               IntListNode_t *current2;
-                                               int m;
-                                               qboolean added = false;
-
-                                               for ( m = 0, current2 = newVertLists[k]; m < newNum_verts[k + 1];
-                                                         ++m, current2 = current2->next )
-                                               {
-                                                       if ( current2->data == vert_replacement[i] ) {
-                                                               added = true;
-                                                               break;
-                                                       }
-                                               }
-
-                                               if ( !added ) {
-                                                       ++newNum_verts[k + 1];
-
-                                                       next = newVertLists[k];
-
-                                                       newVertLists[k] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "OptimizeVertices" );
-                                                       // freed after model write out
-
-                                                       newVertLists[k]->data = vert_replacement[i];
-                                                       newVertLists[k]->next = next;
-                                               }
-                                               break;
-                                       }
-                               }
-                       }
-               }
-       }
-
-       // substitute
-       for ( i = 0 ; i < fmheader.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-
-               for ( j = 0; j < fmheader.num_xyz; j++ )
-               {
-                       in->v[vert_replacement[j]] = in->v[j];
-               }
-
-       }
-
-       for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
-       {
-               IntListNode_t *toFree;
-               current = g_skelModel.vertLists[i];
-
-               while ( current )
-               {
-                       toFree = current;
-                       current = current->next;
-                       free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-               }
-
-               g_skelModel.vertLists[i] = newVertLists[i];
-               g_skelModel.new_num_verts[i + 1] = newNum_verts[i + 1];
-       }
-
-#ifndef NDEBUG
-       for ( k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k )
-       {
-               for ( l = 0, current = g_skelModel.vertLists[k];
-                         l < g_skelModel.new_num_verts[k + 1]; ++l, current = current->next )
-               {
-                       IntListNode_t *current2;
-                       int m;
-
-                       for ( m = l + 1, current2 = current->next; m < newNum_verts[k + 1];
-                                 ++m, current2 = current2->next )
-                       {
-                               if ( current->data == current2->data ) {
-                                       printf( "Warning duplicate vertex:  %d\n", current->data );
-                                       break;
-                               }
-                       }
-               }
-       }
-#endif
-
-       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-       {   // reset the vert bits
-               memset( pmnodes[i].verts,0,sizeof( pmnodes[i].verts ) );
-       }
-
-       // repleace the master triangle list vertex indexes and update the vert bits for each mesh node
-       for ( i = 0 ; i < fmheader.num_tris ; i++ )
-       {
-               pos = i >> 3;
-               bit = 1 << ( i & 7 );
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]];
-
-                       set_pos >>= 3;
-                       set_bit = 1 << ( set_bit & 7 );
-
-                       for ( k = 0; k < fmheader.num_mesh_nodes; k++ )
-                       {
-                               if ( !( pmnodes[k].tris[pos] & bit ) ) {
-                                       continue;
-                               }
-                               pmnodes[k].verts[set_pos] |= set_bit;
-                       }
-               }
-       }
-
-       for ( i = 0; i < numcommands; i++ )
-       {
-               j = commands[i];
-               if ( !j ) {
-                       continue;
-               }
-
-               j = abs( j );
-               for ( i++; j; j--,i += 3 )
-               {
-                       commands[i + 2] = vert_replacement[commands[i + 2]];
-               }
-               i--;
-       }
-
-       printf( "Reduced by %d\n",fmheader.num_xyz - num_unique );
-
-       fmheader.num_xyz = num_unique;
-       if ( num_groups ) {
-               // tack on the reference verts to the regular verts
-               if ( g_skelModel.references != REF_NULL ) {
-                       fmframe_t   *in;
-                       int index;
-                       int refnum;
-
-                       if ( RefPointNum <= 0 ) { // Hard-coded labels
-                               refnum = numReferences[g_skelModel.references];
-                       }
-                       else
-                       {   // Labels indicated in QDT
-                               refnum = RefPointNum;
-                       }
-
-
-                       for ( i = 0; i < fmheader.num_frames; ++i )
-                       {
-                               in = &g_frames[i];
-                               index = fmheader.num_xyz;
-
-                               for ( j = 0 ; j < refnum; ++j )
-                               {
-                                       VectorCopy( in->references[j].placement.origin, in->v[index].v );
-                                       index++;
-
-                                       VectorCopy( in->references[j].placement.direction, in->v[index].v );
-                                       index++;
-
-                                       VectorCopy( in->references[j].placement.up, in->v[index].v );
-                                       index++;
-                               }
-                       }
-
-                       fmheader.num_xyz += refnum * 3;
-               }
-
-               // tack on the skeletal joint verts to the regular verts
-               if ( g_skelModel.type != SKEL_NULL ) {
-                       fmframe_t   *in;
-                       int index;
-
-                       for ( i = 0; i < fmheader.num_frames; ++i )
-                       {
-                               in = &g_frames[i];
-                               index = fmheader.num_xyz;
-
-                               for ( j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j )
-                               {
-                                       VectorCopy( in->joints[j].placement.origin, in->v[index].v );
-                                       index++;
-
-                                       VectorCopy( in->joints[j].placement.direction, in->v[index].v );
-                                       index++;
-
-                                       VectorCopy( in->joints[j].placement.up, in->v[index].v );
-                                       index++;
-                               }
-                       }
-
-                       fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type] * 3;
-               }
-
-               CompressFrames();
-       }
-}
-
-
-/*
-   ===============
-   FinishModel
-   ===============
- */
-void FMFinishModel( void ){
-       FILE        *modelouthandle;
-       int i,j,length,tris,verts,bit,pos,total_tris,total_verts;
-       char name[1024];
-       int trans_count;
-
-       if ( !fmheader.num_frames ) {
-               return;
-       }
-
-//
-// copy to release directory tree if doing a release build
-//
-       if ( g_release ) {
-               if ( modelname[0] ) {
-                       sprintf( name, "%s", modelname );
-               }
-               else{
-                       sprintf( name, "%s/tris.fm", cdpartial );
-               }
-               ReleaseFile( name );
-
-               for ( i = 0 ; i < fmheader.num_skins ; i++ )
-               {
-                       ReleaseFile( g_skins[i] );
-               }
-               fmheader.num_frames = 0;
-               return;
-       }
-
-       printf( "\n" );
-
-       trans_count = 0;
-       for ( i = 0; i < fmheader.num_tris; i++ )
-               if ( translucent[i] ) {
-                       trans_count++;
-               }
-
-       if ( !g_no_opimizations ) {
-               OptimizeVertices();
-       }
-
-//
-// write the model output file
-//
-       if ( modelname[0] ) {
-               sprintf( name, "%s%s", g_outputDir, modelname );
-       }
-       else{
-               sprintf( name, "%s/tris.fm", g_outputDir );
-       }
-       printf( "saving to %s\n", name );
-       CreatePath( name );
-       modelouthandle = SafeOpenWrite( name );
-
-       WriteModelFile( modelouthandle );
-
-       printf( "%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight );
-       printf( "First frame boundaries:\n" );
-       printf( "       minimum x: %3f\n", g_frames[0].mins[0] );
-       printf( "       maximum x: %3f\n", g_frames[0].maxs[0] );
-       printf( "       minimum y: %3f\n", g_frames[0].mins[1] );
-       printf( "       maximum y: %3f\n", g_frames[0].maxs[1] );
-       printf( "       minimum z: %3f\n", g_frames[0].mins[2] );
-       printf( "       maximum z: %3f\n", g_frames[0].maxs[2] );
-       printf( "%4d vertices\n", fmheader.num_xyz );
-       printf( "%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count );
-       printf( "%4d frame\n", fmheader.num_frames );
-       printf( "%4d glverts\n", numglverts );
-       printf( "%4d glcmd\n", fmheader.num_glcmds );
-       printf( "%4d skins\n", fmheader.num_skins );
-       printf( "%4d mesh nodes\n", fmheader.num_mesh_nodes );
-       printf( "wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used,
-                       total_skin_pixels, (double)( total_skin_pixels - skin_pixels_used ) / (double)total_skin_pixels * 100.0 );
-
-       printf( "file size: %d\n", (int)ftell( modelouthandle ) );
-       printf( "---------------------\n" );
-
-       if ( g_verbose ) {
-               if ( fmheader.num_mesh_nodes ) {
-                       total_tris = total_verts = 0;
-                       printf( "Node Name                         Tris Verts\n" );
-                       printf( "--------------------------------- ---- -----\n" );
-                       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-                       {
-                               tris = 0;
-                               verts = 0;
-                               for ( j = 0; j < MAXTRIANGLES; j++ )
-                               {
-                                       pos = ( j ) >> 3;
-                                       bit = 1 << ( ( j ) & 7 );
-                                       if ( pmnodes[i].tris[pos] & bit ) {
-                                               tris++;
-                                       }
-                               }
-                               for ( j = 0; j < MAX_FM_VERTS; j++ )
-                               {
-                                       pos = ( j ) >> 3;
-                                       bit = 1 << ( ( j ) & 7 );
-                                       if ( pmnodes[i].verts[pos] & bit ) {
-                                               verts++;
-                                       }
-                               }
-
-                               printf( "%-33s %4d %5d\n",pmnodes[i].name,tris,verts );
-
-                               total_tris += tris;
-                               total_verts += verts;
-                       }
-                       printf( "--------------------------------- ---- -----\n" );
-                       printf( "%-33s %4d %5d\n","TOTALS",total_tris,total_verts );
-               }
-       }
-       fclose( modelouthandle );
-
-       // finish writing header file
-       H_printf( "\n" );
-
-       // scale_up is usefull to allow step distances to be adjusted
-       H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up );
-
-       // mesh nodes
-       if ( fmheader.num_mesh_nodes ) {
-               H_printf( "\n" );
-               H_printf( "#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes );
-               for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-               {
-                       strcpy( name, pmnodes[i].name );
-                       strupr( name );
-                       length = strlen( name );
-                       for ( j = 0; j < length; j++ )
-                       {
-                               if ( name[j] == ' ' ) {
-                                       name[j] = '_';
-                               }
-                       }
-                       H_printf( "#define MESH_%s\t\t%d\n", name, i );
-               }
-       }
-
-       fclose( headerouthandle );
-       headerouthandle = NULL;
-       free( pmnodes );
-}
-
-
-/*
-   =================================================================
-
-   ALIAS MODEL DISPLAY LIST GENERATION
-
-   =================================================================
- */
-
-extern int strip_xyz[128];
-extern int strip_st[128];
-extern int strip_tris[128];
-extern int stripcount;
-
-/*
-   ================
-   StripLength
-   ================
- */
-static int  StripLength( int starttri, int startv, int num_tris, int node ){
-       int m1, m2;
-       int st1, st2;
-       int j;
-       fmtriangle_t    *last, *check;
-       int k;
-       int pos, bit;
-
-       used[starttri] = 2;
-
-       last = &triangles[starttri];
-
-       strip_xyz[0] = last->index_xyz[( startv ) % 3];
-       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
-       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
-       strip_st[0] = last->index_st[( startv ) % 3];
-       strip_st[1] = last->index_st[( startv + 1 ) % 3];
-       strip_st[2] = last->index_st[( startv + 2 ) % 3];
-
-       strip_tris[0] = starttri;
-       stripcount = 1;
-
-       m1 = last->index_xyz[( startv + 2 ) % 3];
-       st1 = last->index_st[( startv + 2 ) % 3];
-       m2 = last->index_xyz[( startv + 1 ) % 3];
-       st2 = last->index_st[( startv + 1 ) % 3];
-
-       // look for a matching triangle
-nexttri:
-       for ( j = starttri + 1, check = &triangles[starttri + 1]
-                 ; j < num_tris ; j++, check++ )
-       {
-               pos = j >> 3;
-               bit = 1 << ( j & 7 );
-               if ( !( pmnodes[node].tris[pos] & bit ) ) {
-                       continue;
-               }
-               for ( k = 0 ; k < 3 ; k++ )
-               {
-                       if ( check->index_xyz[k] != m1 ) {
-                               continue;
-                       }
-                       if ( check->index_st[k] != st1 ) {
-                               continue;
-                       }
-                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
-                               continue;
-                       }
-                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
-                               continue;
-                       }
-
-                       // this is the next part of the fan
-
-                       // if we can't use this triangle, this tristrip is done
-                       if ( used[j] || translucent[j] != translucent[starttri] ) {
-                               goto done;
-                       }
-
-                       // the new edge
-                       if ( stripcount & 1 ) {
-                               m2 = check->index_xyz[ ( k + 2 ) % 3 ];
-                               st2 = check->index_st[ ( k + 2 ) % 3 ];
-                       }
-                       else
-                       {
-                               m1 = check->index_xyz[ ( k + 2 ) % 3 ];
-                               st1 = check->index_st[ ( k + 2 ) % 3 ];
-                       }
-
-                       strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ];
-                       strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ];
-                       strip_tris[stripcount] = j;
-                       stripcount++;
-
-                       used[j] = 2;
-                       goto nexttri;
-               }
-       }
-done:
-
-       // clear the temp used flags
-       for ( j = starttri + 1 ; j < num_tris ; j++ )
-               if ( used[j] == 2 ) {
-                       used[j] = 0;
-               }
-
-       return stripcount;
-}
-
-
-/*
-   ===========
-   FanLength
-   ===========
- */
-static int  FanLength( int starttri, int startv, int num_tris, int node ){
-       int m1, m2;
-       int st1, st2;
-       int j;
-       fmtriangle_t    *last, *check;
-       int k;
-       int pos, bit;
-
-       used[starttri] = 2;
-
-       last = &triangles[starttri];
-
-       strip_xyz[0] = last->index_xyz[( startv ) % 3];
-       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
-       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
-       strip_st[0] = last->index_st[( startv ) % 3];
-       strip_st[1] = last->index_st[( startv + 1 ) % 3];
-       strip_st[2] = last->index_st[( startv + 2 ) % 3];
-
-       strip_tris[0] = starttri;
-       stripcount = 1;
-
-       m1 = last->index_xyz[( startv + 0 ) % 3];
-       st1 = last->index_st[( startv + 0 ) % 3];
-       m2 = last->index_xyz[( startv + 2 ) % 3];
-       st2 = last->index_st[( startv + 2 ) % 3];
-
-
-       // look for a matching triangle
-nexttri:
-       for ( j = starttri + 1, check = &triangles[starttri + 1]
-                 ; j < num_tris ; j++, check++ )
-       {
-               pos = j >> 3;
-               bit = 1 << ( j & 7 );
-               if ( !( pmnodes[node].tris[pos] & bit ) ) {
-                       continue;
-               }
-               for ( k = 0 ; k < 3 ; k++ )
-               {
-                       if ( check->index_xyz[k] != m1 ) {
-                               continue;
-                       }
-                       if ( check->index_st[k] != st1 ) {
-                               continue;
-                       }
-                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
-                               continue;
-                       }
-                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
-                               continue;
-                       }
-
-                       // this is the next part of the fan
-
-                       // if we can't use this triangle, this tristrip is done
-                       if ( used[j] || translucent[j] != translucent[starttri] ) {
-                               goto done;
-                       }
-
-                       // the new edge
-                       m2 = check->index_xyz[ ( k + 2 ) % 3 ];
-                       st2 = check->index_st[ ( k + 2 ) % 3 ];
-
-                       strip_xyz[stripcount + 2] = m2;
-                       strip_st[stripcount + 2] = st2;
-                       strip_tris[stripcount] = j;
-                       stripcount++;
-
-                       used[j] = 2;
-                       goto nexttri;
-               }
-       }
-done:
-
-       // clear the temp used flags
-       for ( j = starttri + 1 ; j < num_tris ; j++ )
-               if ( used[j] == 2 ) {
-                       used[j] = 0;
-               }
-
-       return stripcount;
-}
-
-
-
-/*
-   ================
-   BuildGlCmds
-
-   Generate a list of trifans or strips
-   for the model, which holds for all frames
-   ================
- */
-static void BuildGlCmds( void ){
-       int i, j, k, l;
-       int startv;
-       float s, t;
-       int len, bestlen, besttype;
-       int best_xyz[1024];
-       int best_st[1024];
-       int best_tris[1024];
-       int type;
-       int trans_check;
-       int bit,pos;
-
-       //
-       // build tristrips
-       //
-       numcommands = 0;
-       numglverts = 0;
-
-
-       for ( l = 0; l < fmheader.num_mesh_nodes; l++ )
-       {
-               memset( used, 0, sizeof( used ) );
-
-               pmnodes[l].start_glcmds = numcommands;
-
-               for ( trans_check = 0; trans_check < 2; trans_check++ )
-               {
-                       for ( i = 0 ; i < fmheader.num_tris ; i++ )
-                       {
-                               pos = i >> 3;
-                               bit = 1 << ( i & 7 );
-                               if ( !( pmnodes[l].tris[pos] & bit ) ) {
-                                       continue;
-                               }
-
-                               // pick an unused triangle and start the trifan
-                               if ( used[i] || trans_check != translucent[i] ) {
-                                       continue;
-                               }
-
-                               bestlen = 0;
-                               for ( type = 0 ; type < 2 ; type++ )
-                               //      type = 1;
-                               {
-                                       for ( startv = 0 ; startv < 3 ; startv++ )
-                                       {
-                                               if ( type == 1 ) {
-                                                       len = StripLength( i, startv, fmheader.num_tris, l );
-                                               }
-                                               else{
-                                                       len = FanLength( i, startv, fmheader.num_tris, l );
-                                               }
-                                               if ( len > bestlen ) {
-                                                       besttype = type;
-                                                       bestlen = len;
-                                                       for ( j = 0 ; j < bestlen + 2 ; j++ )
-                                                       {
-                                                               best_st[j] = strip_st[j];
-                                                               best_xyz[j] = strip_xyz[j];
-                                                       }
-                                                       for ( j = 0 ; j < bestlen ; j++ )
-                                                               best_tris[j] = strip_tris[j];
-                                               }
-                                       }
-                               }
-
-                               // mark the tris on the best strip/fan as used
-                               for ( j = 0 ; j < bestlen ; j++ )
-                                       used[best_tris[j]] = 1;
-
-                               if ( besttype == 1 ) {
-                                       commands[numcommands++] = ( bestlen + 2 );
-                               }
-                               else{
-                                       commands[numcommands++] = -( bestlen + 2 );
-                               }
-
-                               numglverts += bestlen + 2;
-
-                               for ( j = 0 ; j < bestlen + 2 ; j++ )
-                               {
-                                       // emit a vertex into the reorder buffer
-                                       k = best_st[j];
-
-                                       // emit s/t coords into the commands stream
-                                       s = base_st[k].s;
-                                       t = base_st[k].t;
-
-                                       s = ( s  ) / fmheader.skinwidth;
-                                       t = ( t  ) / fmheader.skinheight;
-
-                                       *(float *)&commands[numcommands++] = s;
-                                       *(float *)&commands[numcommands++] = t;
-                                       *(int *)&commands[numcommands++] = best_xyz[j];
-                               }
-                       }
-               }
-               commands[numcommands++] = 0;        // end of list marker
-               pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds;
-       }
-}
-
-
-/*
-   ===============================================================
-
-   BASE FRAME SETUP
-
-   ===============================================================
- */
-
-
-#define LINE_NORMAL 1
-#define LINE_FAT 2
-#define LINE_DOTTED 3
-
-
-#define ASCII_SPACE 32
-
-int LineType = LINE_NORMAL;
-extern unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768];
-unsigned char LineColor = 255;
-int ScaleWidth, ScaleHeight;
-
-
-static char *CharDefs[] =
-{
-       "-------------------------",
-       "-------------------------", // !
-       "-------------------------", // "
-       "-------------------------", // #
-       "-------------------------", // $
-       "-------------------------", // %
-       "-------------------------", // &
-       "--*----*-----------------", // '
-       "-*---*----*----*-----*---", // (
-       "*-----*----*----*---*----", // )
-       "-----*--*--**---**--*--*-", // *
-       "-------------------------", // +
-       "----------------**--**---", // ,
-       "-------------------------", // -
-       "----------------**---**--", // .
-       "-------------------------", // /
-       " *** *  *** * ***  * *** ", // 0
-       "   *   **    *    *    * ",
-       "****     * *** *    *****",
-       "****     * ***     ***** ",
-       "  **  * * *  * *****   * ",
-       "**** *    ****     ***** ",
-       " *** *    **** *   * *** ",
-       "*****    *   *   *    *  ",
-       " *** *   * *** *   * *** ",
-       " *** *   * ****    * *** ", // 9
-       "-**---**--------**---**--", // :
-       "-------------------------", // ;
-       "-------------------------", // <
-       "-------------------------", // =
-       "-------------------------", // >
-       "-------------------------", // ?
-       "-------------------------", // @
-       "-***-*---*******---**---*", // A
-       "****-*---*****-*---*****-",
-       "-*****----*----*-----****",
-       "****-*---**---**---*****-",
-       "******----****-*----*****",
-       "******----****-*----*----",
-       "-*****----*--***---*-****",
-       "*---**---*******---**---*",
-       "-***---*----*----*---***-",
-       "----*----*----**---*-***-",
-       "-*--*-*-*--**---*-*--*--*",
-       "-*----*----*----*----****",
-       "*---***-***-*-**---**---*",
-       "*---***--**-*-**--***---*",
-       "-***-*---**---**---*-***-",
-       "****-*---*****-*----*----",
-       "-***-*---**---*-***----**",
-       "****-*---*****-*-*--*--**",
-       "-*****-----***-----*****-",
-       "*****--*----*----*----*--",
-       "*---**---**---**---******",
-       "*---**---**---*-*-*---*--",
-       "*---**---**-*-***-***---*",
-       "*---*-*-*---*---*-*-*---*",
-       "*---**---*-*-*---*----*--",
-       "*****---*---*---*---*****" // Z
-};
-
-void DrawLine( int x1, int y1, int x2, int y2 ){
-       int dx, dy;
-       int adx, ady;
-       int count;
-       float xfrac, yfrac, xstep, ystep;
-       unsigned sx, sy;
-       float u, v;
-
-       dx = x2 - x1;
-       dy = y2 - y1;
-       adx = abs( dx );
-       ady = abs( dy );
-
-       count = adx > ady ? adx : ady;
-       count++;
-
-       if ( count > 300 ) {
-               printf( "Bad count\n" );
-               return; // don't ever hang up on bad data
-       }
-
-       xfrac = x1;
-       yfrac = y1;
-
-       xstep = (float)dx / count;
-       ystep = (float)dy / count;
-
-       switch ( LineType )
-       {
-       case LINE_NORMAL:
-               do
-               {
-                       if ( xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT ) {
-                               pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor;
-                       }
-                       xfrac += xstep;
-                       yfrac += ystep;
-                       count--;
-               } while ( count > 0 );
-               break;
-       case LINE_FAT:
-               do
-               {
-                       for ( u = -0.1 ; u <= 0.9 ; u += 0.999 )
-                       {
-                               for ( v = -0.1 ; v <= 0.9 ; v += 0.999 )
-                               {
-                                       sx = xfrac + u;
-                                       sy = yfrac + v;
-                                       if ( sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT ) {
-                                               pic[sy * SKINPAGE_WIDTH + sx] = LineColor;
-                                       }
-                               }
-                       }
-                       xfrac += xstep;
-                       yfrac += ystep;
-                       count--;
-               } while ( count > 0 );
-               break;
-       case LINE_DOTTED:
-               do
-               {
-                       if ( count & 1 && xfrac < SKINPAGE_WIDTH &&
-                                yfrac < SKINPAGE_HEIGHT ) {
-                               pic[(int)yfrac * SKINPAGE_WIDTH + (int)xfrac] = LineColor;
-                       }
-                       xfrac += xstep;
-                       yfrac += ystep;
-                       count--;
-               } while ( count > 0 );
-               break;
-       default:
-               Error( "Unknown <linetype> %d.\n", LineType );
-       }
-}
-
-//==========================================================================
-//
-// DrawCharacter
-//
-//==========================================================================
-
-static void DrawCharacter( int x, int y, int character ){
-       int r, c;
-       char *def;
-
-       character = toupper( character );
-       if ( character < ASCII_SPACE || character > 'Z' ) {
-               character = ASCII_SPACE;
-       }
-       character -= ASCII_SPACE;
-       for ( def = CharDefs[character], r = 0; r < 5; r++ )
-       {
-               for ( c = 0; c < 5; c++ )
-               {
-                       pic[( y + r ) * SKINPAGE_WIDTH + x + c] = *def++ == '*' ? 255 : 0;
-               }
-       }
-}
-
-//==========================================================================
-//
-// DrawTextChar
-//
-//==========================================================================
-
-void DrawTextChar( int x, int y, char *text ){
-       int c;
-
-       while ( ( c = *text++ ) != '\0' )
-       {
-               DrawCharacter( x, y, c );
-               x += 6;
-       }
-}
-
-
-extern void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight );
-
-//==========================================================================
-// ExtractDigit
-
-static int ExtractDigit( byte *pic, int x, int y ){
-       int i;
-       int r, c;
-       char digString[32];
-       char    *buffer;
-       byte backColor;
-       char    **DigitDefs;
-
-       backColor = pic[( SKINPAGE_HEIGHT - 1 ) * SKINPAGE_WIDTH];
-       DigitDefs = &CharDefs['0' - ASCII_SPACE];
-
-       buffer = digString;
-       for ( r = 0; r < 5; r++ )
-       {
-               for ( c = 0; c < 5; c++ )
-               {
-                       *buffer++ = ( pic[( y + r ) * SKINPAGE_WIDTH + x + c] == backColor ) ? ' ' : '*';
-               }
-       }
-       *buffer = '\0';
-       for ( i = 0; i < 10; i++ )
-       {
-               if ( strcmp( DigitDefs[i], digString ) == 0 ) {
-                       return i;
-               }
-       }
-
-       Error( "Unable to extract scaling info from skin PCX." );
-       return 0;
-}
-
-//==========================================================================
-// ExtractNumber
-
-int ExtractNumber( byte *pic, int x, int y ){
-       return ExtractDigit( pic, x, y ) * 100 + ExtractDigit( pic, x + 6, y ) * 10 + ExtractDigit( pic, x + 12, y );
-}
-
-
-
-
-
-/*
-   ============
-   BuildST
-
-   Builds the triangle_st array for the base frame and
-   fmheader.skinwidth / fmheader.skinheight
-
-   FIXME: allow this to be loaded from a file for
-   arbitrary mappings
-   ============
- */
-static void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
-       int backface_flag;
-       int i, j;
-       int width, height, iwidth, iheight, swidth;
-       float basex, basey;
-       float scale;
-       vec3_t mins, maxs;
-       float       *pbasevert;
-       vec3_t vtemp1, vtemp2, normal;
-       float s_scale, t_scale;
-       float scWidth;
-       float scHeight;
-       int skinwidth;
-       int skinheight;
-
-       //
-       // find bounds of all the verts on the base frame
-       //
-       ClearBounds( mins, maxs );
-       backface_flag = false;
-
-       if ( ptri[0].HasUV ) { // if we have the uv already, we don't want to double up or scale
-               iwidth = ScaleWidth;
-               iheight = ScaleHeight;
-
-               t_scale = s_scale = 1.0;
-       }
-       else
-       {
-               for ( i = 0 ; i < numtri ; i++ )
-                       for ( j = 0 ; j < 3 ; j++ )
-                               AddPointToBounds( ptri[i].verts[j], mins, maxs );
-
-               for ( i = 0 ; i < 3 ; i++ )
-               {
-                       mins[i] = floor( mins[i] );
-                       maxs[i] = ceil( maxs[i] );
-               }
-
-               width = maxs[0] - mins[0];
-               height = maxs[2] - mins[2];
-
-               for ( i = 0 ; i < numtri ; i++ )
-               {
-                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-                       CrossProduct( vtemp1, vtemp2, normal );
-
-                       if ( normal[1] > 0 ) {
-                               backface_flag = true;
-                               break;
-                       }
-               }
-               scWidth = ScaleWidth * SCALE_ADJUST_FACTOR;
-               if ( backface_flag ) {  //we are doubling
-                       scWidth /= 2;
-               }
-
-               scHeight = ScaleHeight * SCALE_ADJUST_FACTOR;
-
-               scale = scWidth / width;
-
-               if ( height * scale >= scHeight ) {
-                       scale = scHeight / height;
-               }
-
-               iwidth = ceil( width * scale ) + 4;
-               iheight = ceil( height * scale ) + 4;
-
-               s_scale = (float)( iwidth - 4 ) / width;
-               t_scale = (float)( iheight - 4 ) / height;
-               t_scale = s_scale;
-       }
-       if ( DrawSkin ) {
-               if ( backface_flag ) {
-                       DrawScreen( s_scale, t_scale, iwidth * 2, iheight );
-               }
-               else{
-                       DrawScreen( s_scale, t_scale, iwidth, iheight );
-               }
-       }
-       if ( backface_flag ) {
-               skinwidth = iwidth * 2;
-       }
-       else{
-               skinwidth = iwidth;
-       }
-       skinheight = iheight;
-
-
-/*     if (!g_fixedwidth)
-    {  // old style
-        scale = 8;
-        if (width*scale >= 150)
-            scale = 150.0 / width;
-        if (height*scale >= 190)
-            scale = 190.0 / height;
-
-        s_scale = t_scale = scale;
-
-        iwidth = ceil(width*s_scale);
-        iheight = ceil(height*t_scale);
-
-        iwidth += 4;
-        iheight += 4;
-    }
-    else
-    {  // new style
-        iwidth = g_fixedwidth / 2;
-        iheight = g_fixedheight;
-
-        s_scale = (float)(iwidth-4) / width;
-        t_scale = (float)(iheight-4) / height;
-    }*/
-
-//
-// determine which side of each triangle to map the texture to
-//
-       basey = 2;
-       for ( i = 0 ; i < numtri ; i++ )
-       {
-               if ( ptri[i].HasUV ) {
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * skinwidth );
-                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * skinheight );
-                       }
-               }
-               else
-               {
-                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-                       CrossProduct( vtemp1, vtemp2, normal );
-
-                       if ( normal[1] > 0 ) {
-                               basex = iwidth + 2;
-                       }
-                       else
-                       {
-                               basex = 2;
-                       }
-
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               pbasevert = ptri[i].verts[j];
-
-                               triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
-                               triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
-                       }
-               }
-
-               if ( DrawSkin ) {
-                       DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
-                                         triangle_st[i][1][0], triangle_st[i][1][1] );
-                       DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
-                                         triangle_st[i][2][0], triangle_st[i][2][1] );
-                       DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
-                                         triangle_st[i][0][0], triangle_st[i][0][1] );
-               }
-       }
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-       swidth = iwidth;
-       if ( backface_flag ) {
-               swidth *= 2;
-       }
-       fmheader.skinwidth = ( swidth + 3 ) & ~3;
-       fmheader.skinheight = iheight;
-
-       skin_width = iwidth;
-       skin_height = iheight;
-}
-
-
-static void BuildNewST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
-       int i, j;
-
-       for ( i = 0 ; i < numtri ; i++ )
-       {
-               if ( ptri[i].HasUV ) {
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * ( ScaleWidth - 1 ) );
-                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * ( ScaleHeight - 1 ) );
-                       }
-               }
-
-               if ( DrawSkin ) {
-                       DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
-                                         triangle_st[i][1][0], triangle_st[i][1][1] );
-                       DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
-                                         triangle_st[i][2][0], triangle_st[i][2][1] );
-                       DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
-                                         triangle_st[i][0][0], triangle_st[i][0][1] );
-               }
-       }
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-       fmheader.skinwidth = ( ScaleWidth + 3 ) & ~3;
-       fmheader.skinheight = ScaleHeight;
-
-       skin_width = ScaleWidth;
-       skin_height = ScaleHeight;
-}
-
-
-
-
-byte            *BasePalette;
-byte            *BasePixels,*TransPixels;
-int BaseWidth, BaseHeight, TransWidth, TransHeight;
-qboolean BaseTrueColor;
-static qboolean SetPixel = false;
-
-int CheckTransRecursiveTri( int *lp1, int *lp2, int *lp3 ){
-       int     *temp;
-       int d;
-       int new[2];
-
-       d = lp2[0] - lp1[0];
-       if ( d < -1 || d > 1 ) {
-               goto split;
-       }
-       d = lp2[1] - lp1[1];
-       if ( d < -1 || d > 1 ) {
-               goto split;
-       }
-
-       d = lp3[0] - lp2[0];
-       if ( d < -1 || d > 1 ) {
-               goto split2;
-       }
-       d = lp3[1] - lp2[1];
-       if ( d < -1 || d > 1 ) {
-               goto split2;
-       }
-
-       d = lp1[0] - lp3[0];
-       if ( d < -1 || d > 1 ) {
-               goto split3;
-       }
-       d = lp1[1] - lp3[1];
-       if ( d < -1 || d > 1 ) {
-split3:
-               temp = lp1;
-               lp1 = lp3;
-               lp3 = lp2;
-               lp2 = temp;
-
-               goto split;
-       }
-
-       return 0;           // entire tri is filled
-
-split2:
-       temp = lp1;
-       lp1 = lp2;
-       lp2 = lp3;
-       lp3 = temp;
-
-split:
-// split this edge
-       new[0] = ( lp1[0] + lp2[0] ) >> 1;
-       new[1] = ( lp1[1] + lp2[1] ) >> 1;
-
-// draw the point if splitting a leading edge
-       if ( lp2[1] > lp1[1] ) {
-               goto nodraw;
-       }
-       if ( ( lp2[1] == lp1[1] ) && ( lp2[0] < lp1[0] ) ) {
-               goto nodraw;
-       }
-
-       if ( SetPixel ) {
-               assert( ( new[1] * BaseWidth ) + new[0] < BaseWidth * BaseHeight );
-
-               if ( BaseTrueColor ) {
-                       BasePixels[( ( new[1] * BaseWidth ) + new[0] ) * 4] = 1;
-               }
-               else
-               {
-                       BasePixels[( new[1] * BaseWidth ) + new[0]] = 1;
-               }
-       }
-       else
-       {
-               if ( TransPixels ) {
-                       if ( TransPixels[( new[1] * TransWidth ) + new[0]] != 255 ) {
-                               return 1;
-                       }
-               }
-               else if ( BaseTrueColor ) {
-                       if ( BasePixels[( ( ( new[1] * BaseWidth ) + new[0] ) * 4 ) + 3] != 255 ) {
-                               return 1;
-                       }
-               }
-               else
-               {
-//                     pixel = BasePixels[(new[1]*BaseWidth) + new[0]];
-               }
-       }
-
-nodraw:
-// recursively continue
-       if ( CheckTransRecursiveTri( lp3, lp1, new ) ) {
-               return 1;
-       }
-
-       return CheckTransRecursiveTri( lp3, new, lp2 );
-}
-
-static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters,
-                                                                IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){
-       int i, j;
-       IntListNode_t *next;
-
-       for ( j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j )
-       {
-               if ( !clusters[j] ) {
-                       continue;
-               }
-
-               for ( i = 0; i < num_verts[j + 1]; ++i )
-               {
-                       if ( clusters[j][i] == oldindex ) {
-                               ++new_num_verts[j + 1];
-
-                               next = vertLists[j];
-
-                               vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" );
-                               // Currently freed in WriteJointedModelFile only
-
-                               vertLists[j]->data = newIndex;
-                               vertLists[j]->next = next;
-                       }
-               }
-       }
-}
-
-#define FUDGE_EPSILON   0.002
-
-qboolean VectorFudgeCompare( vec3_t v1, vec3_t v2 ){
-       int i;
-
-       for ( i = 0 ; i < 3 ; i++ )
-               if ( fabs( v1[i] - v2[i] ) > FUDGE_EPSILON ) {
-                       return false;
-               }
-
-       return true;
-}
-
-/*
-   =================
-   Cmd_Base
-   =================
- */
-void Cmd_FMBase( qboolean GetST ){
-       triangle_t  *ptri, *st_tri;
-       int num_st_tris;
-       int i, j, k, l;
-       int x,y,z;
-//     int                     time1;
-       char file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256];
-       vec3_t base_xyz[MAX_FM_VERTS];
-       FILE        *FH;
-       int pos,bit;
-       qboolean NewSkin;
-
-       GetScriptToken( false );
-
-       if ( g_skipmodel || g_release || g_archive ) {
-               return;
-       }
-
-       printf( "---------------------\n" );
-       sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext );
-       printf( "%s ", file1 );
-
-       ExpandPathAndArchive( file1 );
-
-       // Use the input filepath for this one.
-       sprintf( file1, "%s/%s", cddir, token );
-
-//     time1 = FileTime (file1);
-//     if (time1 == -1)
-//             Error ("%s doesn't exist", file1);
-
-//
-// load the base triangles
-//
-       if ( do3ds ) {
-               Load3DSTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
-       }
-       else{
-               LoadTriangleList( file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
-       }
-
-       if ( g_ignoreTriUV ) {
-               for ( i = 0; i < fmheader.num_tris; i++ )
-               {
-                       ptri[i].HasUV = 0;
-               }
-       }
-
-       GetScriptToken( false );
-       sprintf( file2, "%s/%s", cddir, token );
-       sprintf( trans_file, "%s/!%s_a.pcx", cddir, token );
-
-       ExtractFileExtension( file2, extension );
-       if ( extension[0] == 0 ) {
-               strcat( file2, ".pcx" );
-       }
-       printf( "skin: %s\n", file2 );
-
-       BaseTrueColor = LoadAnyImage( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight );
-
-       NewSkin = false;
-       if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) {
-               if ( g_allow_newskin ) {
-                       ScaleWidth = BaseWidth;
-                       ScaleHeight = BaseHeight;
-                       NewSkin = true;
-               }
-               else
-               {
-                       Error( "Invalid skin page size: (%d,%d) should be (%d,%d)",
-                                  BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT );
-               }
-       }
-       else if ( !BaseTrueColor ) {
-               ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X,
-                                                                                  ENCODED_WIDTH_Y );
-               ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X,
-                                                                                       ENCODED_HEIGHT_Y );
-       }
-       else
-       {
-               Error( "Texture coordinates not supported on true color image" );
-       }
-
-       if ( GetST ) {
-               GetScriptToken( false );
-
-               sprintf( stfile, "%s/%s.%s", cdarchive, token, trifileext );
-               printf( "ST: %s ", stfile );
-
-               sprintf( stfile, "%s/%s", cddir, token );
-
-               if ( do3ds ) {
-                       Load3DSTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL );
-               }
-               else{
-                       LoadTriangleList( stfile, &st_tri, &num_st_tris, NULL, NULL );
-               }
-
-               if ( num_st_tris != fmheader.num_tris ) {
-                       Error( "num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris );
-               }
-
-               printf( "   matching triangles...\n" );
-               for ( i = 0; i < fmheader.num_tris; i++ )
-               {
-                       k = -1;
-                       for ( j = 0; j < num_st_tris; j++ )
-                       {
-                               for ( x = 0; x < 3; x++ )
-                               {
-                                       for ( y = 0; y < 3; y++ )
-                                       {
-                                               if ( x == y ) {
-                                                       continue;
-                                               }
-                                               for ( z = 0; z < 3; z++ )
-                                               {
-                                                       if ( z == x || z == y ) {
-                                                               continue;
-                                                       }
-
-                                                       if ( VectorFudgeCompare( ptri[i].verts[0], st_tri[j].verts[x] ) &&
-                                                                VectorFudgeCompare( ptri[i].verts[1], st_tri[j].verts[y] ) &&
-                                                                VectorFudgeCompare( ptri[i].verts[2], st_tri[j].verts[z] ) ) {
-                                                               if ( k == -1 ) {
-                                                                       k = j;
-                                                                       ptri[i].HasUV = st_tri[k].HasUV;
-                                                                       ptri[i].uv[0][0] = st_tri[k].uv[x][0];
-                                                                       ptri[i].uv[0][1] = st_tri[k].uv[x][1];
-                                                                       ptri[i].uv[1][0] = st_tri[k].uv[y][0];
-                                                                       ptri[i].uv[1][1] = st_tri[k].uv[y][1];
-                                                                       ptri[i].uv[2][0] = st_tri[k].uv[z][0];
-                                                                       ptri[i].uv[2][1] = st_tri[k].uv[z][1];
-                                                                       x = y = z = 999;
-                                                               }
-                                                               else if ( k != j ) {
-                                                                       printf( "Duplicate triangle %d found in st file: %d and %d\n",i,k,j );
-                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-                                                                                       ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2],
-                                                                                       ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2],
-                                                                                       ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2] );
-                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-                                                                                       st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2],
-                                                                                       st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2],
-                                                                                       st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2] );
-                                                                       printf( "   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-                                                                                       st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2],
-                                                                                       st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2],
-                                                                                       st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2] );
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       if ( k == -1 ) {
-                               printf( "No matching triangle %d\n",i );
-                       }
-               }
-               free( st_tri );
-       }
-
-//
-// get the ST values
-//
-       if ( ptri && ptri[0].HasUV ) {
-               if ( !NewSkin ) {
-                       Error( "Base has UVs with old style skin page\nMaybe you want to use -ignoreUV" );
-               }
-               else
-               {
-                       BuildNewST( ptri, fmheader.num_tris, false );
-               }
-       }
-       else
-       {
-               if ( NewSkin ) {
-                       Error( "Base has new style skin without UVs" );
-               }
-               else
-               {
-                       BuildST( ptri, fmheader.num_tris, false );
-               }
-       }
-
-       TransPixels = NULL;
-       if ( !BaseTrueColor ) {
-               FH = fopen( trans_file,"rb" );
-               if ( FH ) {
-                       fclose( FH );
-                       Load256Image( trans_file, &TransPixels, NULL, &TransWidth, &TransHeight );
-                       if ( TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight ) {
-                               Error( "source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight );
-                       }
-               }
-       }
-
-//
-// run through all the base triangles, storing each unique vertex in the
-// base vertex list and setting the indirect triangles to point to the base
-// vertices
-//
-       for ( l = 0; l < fmheader.num_mesh_nodes; l++ )
-       {
-               for ( i = 0 ; i < fmheader.num_tris ; i++ )
-               {
-                       pos = i >> 3;
-                       bit = 1 << ( i & 7 );
-                       if ( !( pmnodes[l].tris[pos] & bit ) ) {
-                               continue;
-                       }
-
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               // get the xyz index
-                               for ( k = 0 ; k < fmheader.num_xyz ; k++ )
-                               {
-                                       if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) {
-                                               break;  // this vertex is already in the base vertex list
-                                       }
-                               }
-
-                               if ( k == fmheader.num_xyz ) { // new index
-                                       VectorCopy( ptri[i].verts[j], base_xyz[fmheader.num_xyz] );
-
-                                       if ( pmnodes[l].clustered == true ) {
-                                               ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts );
-                                       }
-
-                                       fmheader.num_xyz++;
-                               }
-
-                               pos = k >> 3;
-                               bit = 1 << ( k & 7 );
-                               pmnodes[l].verts[pos] |= bit;
-
-                               triangles[i].index_xyz[j] = k;
-
-                               // get the st index
-                               for ( k = 0 ; k < fmheader.num_st ; k++ )
-                               {
-                                       if ( triangle_st[i][j][0] == base_st[k].s
-                                                && triangle_st[i][j][1] == base_st[k].t ) {
-                                               break;  // this vertex is already in the base vertex list
-                                       }
-                               }
-
-                               if ( k == fmheader.num_st ) { // new index
-                                       base_st[fmheader.num_st].s = triangle_st[i][j][0];
-                                       base_st[fmheader.num_st].t = triangle_st[i][j][1];
-                                       fmheader.num_st++;
-                               }
-
-                               triangles[i].index_st[j] = k;
-                       }
-
-                       if ( TransPixels || BaseTrueColor ) {
-                               translucent[i] = CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
-                       }
-                       else
-                       {
-                               translucent[i] = false;
-                       }
-               }
-       }
-
-       if ( !BaseTrueColor ) {
-               SetPixel = true;
-               memset( BasePixels,0,BaseWidth * BaseHeight );
-               for ( i = 0 ; i < fmheader.num_tris ; i++ )
-               {
-                       CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
-               }
-               SetPixel = false;
-
-               skin_pixels_used = 0;
-               for ( i = 0; i < fmheader.skinheight; i++ )
-               {
-                       for ( j = 0; j < fmheader.skinwidth; j++ )
-                       {
-                               skin_pixels_used += BasePixels[( i * BaseWidth ) + j];
-                       }
-               }
-               total_skin_pixels = fmheader.skinheight * fmheader.skinwidth;
-       }
-       else
-       {
-               SetPixel = true;
-               memset( BasePixels,0,BaseWidth * BaseHeight * 4 );
-               for ( i = 0 ; i < fmheader.num_tris ; i++ )
-               {
-                       CheckTransRecursiveTri( triangle_st[i][0], triangle_st[i][1], triangle_st[i][2] );
-               }
-               SetPixel = false;
-
-               skin_pixels_used = 0;
-               for ( i = 0; i < fmheader.skinheight; i++ )
-               {
-                       for ( j = 0; j < fmheader.skinwidth; j++ )
-                       {
-                               skin_pixels_used += BasePixels[( ( i * BaseWidth ) + j ) * 4];
-                       }
-               }
-               total_skin_pixels = fmheader.skinheight * fmheader.skinwidth;
-       }
-
-       // build triangle strips / fans
-       BuildGlCmds();
-
-       if ( TransPixels ) {
-               free( TransPixels );
-       }
-       free( BasePixels );
-       if ( BasePalette ) {
-               free( BasePalette );
-       }
-       free( ptri );
-}
-
-void Cmd_FMNodeOrder( void ){
-       mesh_node_t *newnodes, *pos;
-       int i,j;
-
-       if ( !pmnodes ) {
-               Error( "Base has not been established yet" );
-       }
-
-       pos = newnodes = malloc( sizeof( mesh_node_t ) * fmheader.num_mesh_nodes );
-
-       for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-       {
-               GetScriptToken( false );
-
-               for ( j = 0; j < fmheader.num_mesh_nodes; j++ )
-               {
-                       if ( strcmpi( pmnodes[j].name, token ) == 0 ) {
-                               *pos = pmnodes[j];
-                               pos++;
-                               break;
-                       }
-               }
-               if ( j >= fmheader.num_mesh_nodes ) {
-                       Error( "Node '%s' not in base list!\n", token );
-               }
-       }
-
-       free( pmnodes );
-       pmnodes = newnodes;
-}
-
-//===============================================================
-
-extern char *FindFrameFile( char *frame );
-
-
-/*
-   ===============
-   GrabFrame
-   ===============
- */
-void GrabFrame( char *frame ){
-       triangle_t      *ptri;
-       int i, j;
-       fmtrivert_t     *ptrivert;
-       int num_tris;
-       char file1[1024];
-       fmframe_t       *fr;
-       int index_xyz;
-       char            *framefile;
-
-       // the frame 'run1' will be looked for as either
-       // run.1 or run1.tri, so the new alias sequence save
-       // feature an be used
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "grabbing %s  ", file1 );
-
-       if ( fmheader.num_frames >= MAX_FM_FRAMES ) {
-               Error( "fmheader.num_frames >= MAX_FM_FRAMES" );
-       }
-       fr = &g_frames[fmheader.num_frames];
-       fmheader.num_frames++;
-
-       strcpy( fr->name, frame );
-
-//
-// load the frame
-//
-       if ( do3ds ) {
-               Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
-       }
-       else{
-               LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
-       }
-
-       if ( num_tris != fmheader.num_tris ) {
-               Error( "%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris );
-       }
-
-//
-// allocate storage for the frame's vertices
-//
-       ptrivert = fr->v;
-
-       for ( i = 0 ; i < fmheader.num_xyz ; i++ )
-       {
-               ptrivert[i].vnorm.numnormals = 0;
-               VectorClear( ptrivert[i].vnorm.normalsum );
-       }
-       ClearBounds( fr->mins, fr->maxs );
-
-//
-// store the frame's vertices in the same order as the base. This assumes the
-// triangles and vertices in this frame are in exactly the same order as in the
-// base
-//
-       for ( i = 0 ; i < num_tris ; i++ )
-       {
-               vec3_t vtemp1, vtemp2, normal;
-               float ftemp;
-
-               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-               CrossProduct( vtemp1, vtemp2, normal );
-
-               VectorNormalize( normal, normal );
-
-               // rotate the normal so the model faces down the positive x axis
-               ftemp = normal[0];
-               normal[0] = -normal[1];
-               normal[1] = ftemp;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       index_xyz = triangles[i].index_xyz[j];
-
-                       // rotate the vertices so the model faces down the positive x axis
-                       // also adjust the vertices to the desired origin
-                       ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
-                                                                          adjust[0];
-                       ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
-                                                                          adjust[1];
-                       ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
-                                                                          adjust[2];
-
-                       AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );
-
-                       VectorAdd( ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum );
-                       ptrivert[index_xyz].vnorm.numnormals++;
-               }
-       }
-
-//
-// calculate the vertex normals, match them to the template list, and store the
-// index of the best match
-//
-       for ( i = 0 ; i < fmheader.num_xyz ; i++ )
-       {
-               int j;
-               vec3_t v;
-               float maxdot;
-               int maxdotindex;
-               int c;
-
-               c = ptrivert[i].vnorm.numnormals;
-               if ( !c ) {
-                       Error( "Vertex with no triangles attached" );
-               }
-
-               VectorScale( ptrivert[i].vnorm.normalsum, 1.0 / c, v );
-               VectorNormalize( v, v );
-
-               maxdot = -999999.0;
-               maxdotindex = -1;
-
-               for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
-               {
-                       float dot;
-
-                       dot = DotProduct( v, avertexnormals[j] );
-                       if ( dot > maxdot ) {
-                               maxdot = dot;
-                               maxdotindex = j;
-                       }
-               }
-
-               ptrivert[i].lightnormalindex = maxdotindex;
-       }
-
-       free( ptri );
-}
-
-/*
-   ===============
-   Cmd_Frame
-   ===============
- */
-void Cmd_FMFrame( void ){
-       while ( ScriptTokenAvailable() )
-       {
-               GetScriptToken( false );
-               if ( g_skipmodel ) {
-                       continue;
-               }
-               if ( g_release || g_archive ) {
-                       fmheader.num_frames = 1;    // don't skip the writeout
-                       continue;
-               }
-
-               H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames );
-
-               if ( ( g_skelModel.type != SKEL_NULL ) || ( g_skelModel.references != REF_NULL ) ) {
-                       GrabModelTransform( token );
-               }
-
-               GrabFrame( token );
-
-               if ( g_skelModel.type != SKEL_NULL ) {
-                       GrabSkeletalFrame( token );
-               }
-
-               if ( g_skelModel.references != REF_NULL ) {
-                       GrabReferencedFrame( token );
-               }
-
-               // need to add the up and dir points to the frame bounds here
-               // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-               // then remove fudge in determining scale on frame write out
-       }
-}
-
-/*
-   ===============
-   Cmd_Skin
-
-   Skins aren't actually stored in the file, only a reference
-   is saved out to the header file.
-   ===============
- */
-void Cmd_FMSkin( void ){
-       byte        *palette;
-       byte        *pixels;
-       int width, height;
-       byte        *cropped;
-       int y;
-       char name[1024], savename[1024], transname[1024], extension[256];
-       miptex32_t  *qtex32;
-       int size;
-       FILE        *FH;
-       qboolean TrueColor;
-
-       GetScriptToken( false );
-
-       if ( fmheader.num_skins == MAX_FM_SKINS ) {
-               Error( "fmheader.num_skins == MAX_FM_SKINS" );
-       }
-
-       if ( g_skipmodel ) {
-               return;
-       }
-
-       sprintf( name, "%s/%s", cdarchive, token );
-       strcpy( name, ExpandPathAndArchive( name ) );
-//     sprintf (name, "%s/%s.lbm", cddir, token);
-
-       if ( ScriptTokenAvailable() ) {
-               GetScriptToken( false );
-               sprintf( g_skins[fmheader.num_skins], "!%s", token );
-               sprintf( savename, "%s!%s", g_outputDir, token );
-               sprintf( transname, "%s!%s_a.pcx", gamedir, token );
-       }
-       else
-       {
-               sprintf( g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token );
-               sprintf( savename, "%s/!%s", g_outputDir, token );
-               sprintf( transname, "%s/!%s_a.pcx", cddir, token );
-       }
-
-       fmheader.num_skins++;
-
-       if ( g_skipmodel || g_release || g_archive ) {
-               return;
-       }
-
-       // load the image
-       printf( "loading %s\n", name );
-       ExtractFileExtension( name, extension );
-       if ( extension[0] == 0 ) {
-               strcat( name, ".pcx" );
-       }
-
-
-       TrueColor = LoadAnyImage( name, &pixels, &palette, &width, &height );
-//     RemapZero (pixels, palette, width, height);
-
-       // crop it to the proper size
-
-       if ( !TrueColor ) {
-               cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight, "Cmd_FMSkin" );
-               for ( y = 0 ; y < fmheader.skinheight ; y++ )
-               {
-                       memcpy( cropped + y * fmheader.skinwidth,
-                                       pixels + y * width, fmheader.skinwidth );
-               }
-
-               TransPixels = NULL;
-               FH = fopen( transname,"rb" );
-               if ( FH ) {
-                       fclose( FH );
-
-                       strcat( g_skins[fmheader.num_skins - 1],".pcx" );
-                       strcat( savename,".pcx" );
-
-                       // save off the new image
-                       printf( "saving %s\n", savename );
-                       CreatePath( savename );
-                       WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette );
-               }
-               else
-               {
-       #if 1
-                       miptex_t    *qtex;
-                       qtex = CreateMip( cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true );
-
-                       strcat( g_skins[fmheader.num_skins - 1],".m8" );
-                       strcat( savename,".m8" );
-
-                       printf( "saving %s\n", savename );
-                       CreatePath( savename );
-                       SaveFile( savename, (byte *)qtex, size );
-                       free( qtex );
-       #else
-                       strcat( g_skins[fmheader.num_skins - 1],".pcx" );
-                       strcat( savename,".pcx" );
-
-                       // save off the new image
-                       printf( "saving %s\n", savename );
-                       CreatePath( savename );
-                       WritePCXfile( savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette );
-       #endif
-               }
-       }
-       else
-       {
-               cropped = (byte *) SafeMalloc( fmheader.skinwidth * fmheader.skinheight * 4, "Cmd_FMSkin" );
-               for ( y = 0 ; y < fmheader.skinheight ; y++ )
-               {
-                       memcpy( cropped + ( ( y * fmheader.skinwidth ) * 4 ), pixels + ( y * width * 4 ), fmheader.skinwidth * 4 );
-               }
-
-               qtex32 = CreateMip32( (unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true );
-
-               StripExtension( g_skins[fmheader.num_skins - 1] );
-               strcat( g_skins[fmheader.num_skins - 1],".m32" );
-               StripExtension( savename );
-               strcat( savename,".m32" );
-
-               printf( "saving %s\n", savename );
-               CreatePath( savename );
-               SaveFile( savename, (byte *)qtex32, size );
-       }
-
-       free( pixels );
-       if ( palette ) {
-               free( palette );
-       }
-       free( cropped );
-}
-
-
-/*
-   ===============
-   Cmd_Cd
-   ===============
- */
-void Cmd_FMCd( void ){
-       char temp[256];
-
-       FinishModel();
-       ClearModel();
-
-       GetScriptToken( false );
-
-       // this is a silly mess...
-       sprintf( cdpartial, "models/%s", token );
-       sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token );
-       sprintf( cddir, "%s%s", gamedir, cdpartial );
-
-       // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
-       sprintf( temp, "%s%s", g_outputDir, cdpartial );
-       strcpy( g_outputDir, temp );
-
-       // if -only was specified and this cd doesn't match,
-       // skip the model (you only need to match leading chars,
-       // so you could regrab all monsters with -only monsters)
-       if ( !g_only[0] ) {
-               return;
-       }
-       if ( strncmp( token, g_only, strlen( g_only ) ) ) {
-               g_skipmodel = true;
-               printf( "skipping %s\n", cdpartial );
-       }
-}
-
-
-/*
-
-   //=======================
-   //          NEW GEN
-   //=======================
-
-   void NewGen (char *ModelFile, char *OutputName, int width, int height)
-   {
-    trigroup_t  *triangles;
-    triangle_t *ptri;
-    triangle_t *grouptris;
-    mesh_node_t        *pmnodes;
-
-    vec3_t             *vertices;
-    vec3_t             *uvs;
-    vec3_t             aveNorm, crossvect;
-    vec3_t             diffvect1, diffvect2;
-    vec3_t             v0, v1, v2;
-    vec3_t             n, u, v;
-    vec3_t             base, zaxis, yaxis;
-    vec3_t             uvwMin, uvwMax;
-    vec3_t             groupMin, groupMax;
-    vec3_t             uvw;
-
-    float              *uFinal, *vFinal;
-    unsigned char      *newpic;
-
-    int                        finalstart = 0, finalcount = 0;
-    int                        xbase = 0, xwidth = 0, ywidth = 0;
-    int                        *todo, *done, finished;
-    int                        i, j, k, l; //counters
-    int                        groupnum, numtris, numverts, num;
-    int                        count;
-    FILE               *grpfile;
-    long               datasize;
-
-    for ( i = 0; i<3; i++)
-    {
-        aveNorm[i] = 0;
-        uvwMin[i] = 1e30f;
-        uvwMax[i] = -1e30f;
-    }
-
-    pmnodes = NULL;
-    ptri = NULL;
-    triangles = NULL;
-
-    zaxis[0] = 0;
-    zaxis[1] = 0;
-    zaxis[2] = 1;
-
-    yaxis[0] = 0;
-    yaxis[1] = 1;
-    yaxis[2] = 0;
-
-    LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
-
-    todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
-    done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
-    triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen");
-
-    for ( i=0; i < fmheader.num_tris; i++)
-    {
-        todo[i] = false;
-        done[i] = false;
-        triangles[i].triangle = ptri[i];
-        triangles[i].group = 0;
-    }
-
-    groupnum = 0;
-
-   //  transitive closure algorithm follows
-   //  put all triangles who transitively share vertices into separate groups
-
-    while (1)
-    {
-        for ( i = 0; i < fmheader.num_tris; i++)
-        {
-            if (!done[i])
-            {
-                break;
-            }
-        }
-        if ( i == fmheader.num_tris)
-        {
-            break;
-        }
-        finished = false;
-        todo[i] = true;
-        while (!finished)
-        {
-            finished = true;
-            for ( i = 0; i < fmheader.num_tris; i++)
-            {
-                if (todo[i])
-                {
-                    done[i] = true;
-                    triangles[i].group = groupnum;
-                    todo[i] = false;
-                    for ( j = 0; j < fmheader.num_tris; j++)
-                    {
-                        if ((!done[j]) && (ShareVertex(triangles[i],triangles[j])))
-                        {
-                            todo[j] = true;
-                            finished = false;
-                        }
-                    }
-                }
-            }
-        }
-        groupnum++;
-    }
-        uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
-        vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
-
-    grpfile = fopen("grpdebug.txt","w");
-
-
-    for (i = 0; i < groupnum; i++)
-    {
-
-        fprintf(grpfile,"Group Number: %d\n", i);
-
-        numtris = GetNumTris(triangles, i); // number of triangles in group i
-        numverts = numtris * 3;
-
-        fprintf(grpfile,"%d triangles.\n", numtris);
-
-        vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
-        uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
-        grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen");
-
-        for (count = 0; count < fmheader.num_tris; count++)
-        {
-            if (triangles[count].group == i)
-            {
-                fprintf(grpfile,"Triangle %d\n", count);
-            }
-        }
-        fprintf(grpfile,"\n");
-
-
-
-
-        GetOneGroup(triangles, i, grouptris);
-
-        num = 0;
-        for (j = 0; j < numtris; j++)
-        {
-            VectorCopy(grouptris[j].verts[0], v0);
-            VectorCopy(grouptris[j].verts[1], v1);
-            VectorCopy(grouptris[j].verts[2], v2);
-            VectorSubtract(v1, v0, diffvect1);
-            VectorSubtract(v2, v1, diffvect2);
-            CrossProduct( diffvect1, diffvect2, crossvect);
-            VectorAdd(aveNorm, crossvect, aveNorm);
-            VectorCopy(v0,vertices[num]);
-            num++;                                     //  FIXME
-            VectorCopy(v1,vertices[num]);
-            num++;                                     //  add routine to add only verts that
-            VectorCopy(v2,vertices[num]);
-            num++;                                     // have not already been added
-        }
-
-        assert (num >= 3);
-   // figure out the best plane projections
-        DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base);
-
-        if (DotProduct(aveNorm,n) < 0.0f)
-        {
-            VectorScale(n, -1.0f, n);
-        }
-        VectorNormalize(n,n);
-        if (fabs(n[2]) < .57)
-        {
-            CrossProduct( zaxis, n, crossvect);
-            VectorCopy(crossvect, u);
-        }
-        else
-        {
-            CrossProduct( yaxis, n, crossvect);
-            VectorCopy(crossvect, u);
-        }
-        VectorNormalize(u,u);
-        CrossProduct( n, u, crossvect);
-        VectorCopy(crossvect, v);
-        VectorNormalize(v,v);
-
-        num = 0;
-
-        for ( j = 0; j < 3; j++)
-        {
-            groupMin[j] = 1e30f;
-            groupMax[j] = -1e30f;
-        }
-
-        for ( j = 0; j < numtris; j++)
-        {
-            for ( k = 0; k < 3; k++)
-            {
-                VectorCopy(grouptris[j].verts[k],v0);
-                VectorSubtract(v0, base, v0);
-                uvw[0] = DotProduct(v0, u);
-                uvw[1] = DotProduct(v0, v);
-                uvw[2] = DotProduct(v0, n);
-                VectorCopy(uvw,uvs[num]);
-                num++;
-                for ( l = 0; l < 3; l++)
-                {
-                    if (uvw[l] < groupMin[l])
-                    {
-                        groupMin[l] = uvw[l];
-                    }
-                    if (uvw[l] > groupMax[l])
-                    {
-                        groupMax[l] = uvw[l];
-                    }
-                }
-            }
-        }
-
-        xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap
-        ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin
-
-        for ( j=0; j < numverts; j++)
-        {
-            uFinal[finalcount] = uvs[j][0] + xwidth + xbase;
-            vFinal[finalcount] = uvs[j][1] + ywidth;
-            if (uFinal[finalcount] < uvwMin[0])
-            {
-                uvwMin[0] = uFinal[finalcount];
-            }
-            if (uFinal[finalcount] > uvwMax[0])
-            {
-                uvwMax[0] = uFinal[finalcount];
-            }
-            if (vFinal[finalcount] < uvwMin[1])
-            {
-                uvwMin[1] = vFinal[finalcount];
-            }
-            if (vFinal[finalcount] > uvwMax[1])
-            {
-                uvwMax[1] = vFinal[finalcount];
-            }
-            finalcount++;
-        }
-
-        fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth);
-        fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth);
-
-        finalcount = finalstart;
-
-        for ( count = 0; count < numverts; count++)
-        {
-            fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]);
-            fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]);
-        }
-
-        finalstart = finalcount;
-
-        fprintf(grpfile,"\n");
-
-        free(vertices);
-        free(uvs);
-        free(grouptris);
-
-        xbase += ceil(groupMax[0] - groupMin[0]) + 2;
-
-    }
-
-    fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]);
-    fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]);
-
-
-    ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount);
-
-    for (k = 0; k < finalcount; k++)
-    {
-        fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]);
-    }
-
-    //  i've got the array of vertices in uFinal and vFinal.  Now I need to write them and draw lines
-
-    datasize = width * height*sizeof(unsigned char);
-    newpic = (unsigned char*)SafeMalloc(datasize, "NewGen");
-    memset(newpic,0,datasize);
-    memset(pic_palette,0,sizeof(pic_palette));
-    pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
-
-    k = 0;
-    while (k < finalcount)
-    {
-        NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
-        k++;
-        NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
-        k++;
-        NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height);
-        k++;
-        fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k);
-    }
-
-    WritePCXfile (OutputName, newpic, width, height, pic_palette);
-
-    fclose(grpfile);
-
-    free(todo);
-    free(done);
-    free(triangles);
-    free(newpic);
-    return;
-   }
-   void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height)
-   {
-    long dx, dy;
-    long adx, ady;
-    long count;
-    float xfrac, yfrac, xstep, ystep;
-    unsigned long sx, sy;
-    float u, v;
-
-    dx = x2 - x1;
-    dy = y2 - y1;
-    adx = abs(dx);
-    ady = abs(dy);
-
-    count = adx > ady ? adx : ady;
-    count++;
-
-    if(count > 300)
-    {
-        printf("Bad count\n");
-        return; // don't ever hang up on bad data
-    }
-
-    xfrac = x1;
-    yfrac = y1;
-
-    xstep = (float)dx/count;
-    ystep = (float)dy/count;
-
-    switch(LineType)
-    {
-        case LINE_NORMAL:
-            do
-            {
-                if(xfrac < width && yfrac < height)
-                {
-                    picture[(long)yfrac*width+(long)xfrac] = LineColor;
-                }
-                xfrac += xstep;
-                yfrac += ystep;
-                count--;
-            } while (count > 0);
-            break;
-        case LINE_FAT:
-            do
-            {
-                for (u=-0.1 ; u<=0.9 ; u+=0.999)
-                {
-                    for (v=-0.1 ; v<=0.9 ; v+=0.999)
-                    {
-                        sx = xfrac+u;
-                        sy = yfrac+v;
-                        if(sx < width && sy < height)
-                        {
-                            picture[sy*width+sx] = LineColor;
-                        }
-                    }
-                }
-                xfrac += xstep;
-                yfrac += ystep;
-                count--;
-            } while (count > 0);
-            break;
-        case LINE_DOTTED:
-            do
-            {
-                if(count&1 && xfrac < width &&
-                    yfrac < height)
-                {
-                    picture[(long)yfrac*width+(long)xfrac] = LineColor;
-                }
-                xfrac += xstep;
-                yfrac += ystep;
-                count--;
-            } while (count > 0);
-            break;
-        default:
-            Error("Unknown <linetype> %d.\n", LineType);
-    }
-   }
- */
-void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts ){
-
-       int i;
-       float hscale, vscale;
-       float scale;
-
-       hscale = max[0];
-       vscale = max[1];
-
-       hscale = ( Width - 2 ) / max[0];
-       vscale = ( Height - 2 ) / max[1];
-
-       scale = hscale;
-       if ( scale > vscale ) {
-               scale = vscale;
-       }
-       for ( i = 0; i < verts; i++ )
-       {
-               u[i] *= scale;
-               v[i] *= scale;
-       }
-       return;
-}
-
-
-void GetOneGroup( trigroup_t *tris, int grp, triangle_t* triangles ){
-       int i;
-       int j;
-
-       j = 0;
-       for ( i = 0; i < fmheader.num_tris; i++ )
-       {
-               if ( tris[i].group == grp ) {
-                       triangles[j++] = tris[i].triangle;
-               }
-       }
-       return;
-}
-
-
-int GetNumTris( trigroup_t *tris, int grp ){
-       int i;
-       int verts;
-
-       verts = 0;
-       for ( i = 0; i < fmheader.num_tris; i++ )
-       {
-               if ( tris[i].group == grp ) {
-                       verts++;
-               }
-       }
-       return verts;
-}
-
-
-int ShareVertex( trigroup_t trione, trigroup_t tritwo ){
-       int i;
-       int j;
-
-       i = 1;
-       j = 1;
-       for ( i = 0; i < 3; i++ )
-       {
-               for ( j = 0; j < 3; j++ )
-               {
-                       if ( DistBetween( trione.triangle.verts[i],tritwo.triangle.verts[j] ) < TRIVERT_DIST ) {
-                               return true;
-                       }
-               }
-       }
-       return false;
-}
-
-
-float DistBetween( vec3_t point1, vec3_t point2 ){
-       float dist;
-
-       dist = ( point1[0] - point2[0] );
-       dist *= dist;
-       dist += ( point1[1] - point2[1] ) * ( point1[1] - point2[1] );
-       dist += ( point1[2] - point2[2] ) * ( point1[2] - point2[2] );
-       dist = sqrt( dist );
-       return dist;
-}
-
-
-void GenSkin( char *ModelFile, char *OutputName, int Width, int Height ){
-       triangle_t  *ptri;
-       mesh_node_t *pmnodes;
-       int i;
-
-       pmnodes = NULL;
-       ptri = NULL;
-
-       LoadTriangleList( ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes );
-       if ( g_ignoreTriUV ) {
-               for ( i = 0; i < fmheader.num_tris; i++ )
-               {
-                       ptri[i].HasUV = 0;
-               }
-       }
-
-       memset( pic,0,sizeof( pic ) );
-       memset( pic_palette,0,sizeof( pic_palette ) );
-       pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
-
-       ScaleWidth = Width;
-       ScaleHeight = Height;
-
-       BuildST( ptri, fmheader.num_tris, true );
-
-       WritePCXfile( OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette );
-
-       printf( "Gen Skin Stats:\n" );
-       printf( "   Input Base: %s\n",ModelFile );
-       printf( "   Input Dimensions: %d,%d\n",Width,Height );
-       printf( "\n" );
-       printf( "   Output File: %s\n",OutputName );
-       printf( "   Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight );
-
-       if ( fmheader.num_mesh_nodes ) {
-               printf( "\nNodes:\n" );
-               for ( i = 0; i < fmheader.num_mesh_nodes; i++ )
-               {
-                       printf( "   %s\n",pmnodes[i].name );
-               }
-       }
-
-       free( ptri );
-       free( pmnodes );
-}
-
-
-void Cmd_FMBeginGroup( void ){
-       GetScriptToken( false );
-
-       g_no_opimizations = false;
-
-       groups[num_groups].start_frame = fmheader.num_frames;
-       groups[num_groups].num_frames = 0;
-
-       groups[num_groups].degrees = atol( token );
-       if ( groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32 ) {
-               Error( "Degrees of freedom out of range: %d",groups[num_groups].degrees );
-       }
-}
-
-void Cmd_FMEndGroup( void ){
-       groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame;
-
-       if ( num_groups < MAX_GROUPS - 1 ) {
-               num_groups++;
-       }
-       else
-       {
-               Error( "Number of compression groups exceded: %i\n", MAX_GROUPS );
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/icon1.ico b/tools/quake2/qdata_heretic2/icon1.ico
deleted file mode 100644 (file)
index 8f44194..0000000
Binary files a/tools/quake2/qdata_heretic2/icon1.ico and /dev/null differ
diff --git a/tools/quake2/qdata_heretic2/images.c b/tools/quake2/qdata_heretic2/images.c
deleted file mode 100644 (file)
index a7138b1..0000000
+++ /dev/null
@@ -1,1405 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qdata.h"
-
-#if GDEF_OS_WINDOWS
- #include <windows.h>
-#endif
-
-#include <GL/gl.h>
-
-#if 1
-extern char     *g_outputDir;
-#endif // _QDATA
-
-char mip_prefix[1024];              // directory to dump the textures in
-
-qboolean colormap_issued;
-byte colormap_palette[768];
-
-unsigned total_x = 0;
-unsigned total_y = 0;
-unsigned total_textures = 0;
-
-#define MAX_IMAGE_SIZE 512
-
-#if 0
-/*
-   ==============
-   RemapZero
-
-   Replaces all 0 bytes in an image with the closest palette entry.
-   This is because NT won't let us change index 0, so any palette
-   animation leaves those pixels untouched.
-   ==============
- */
-void RemapZero( byte *pixels, byte *palette, int width, int height ){
-       int i, c;
-       int alt_zero;
-       int value, best;
-
-       alt_zero = 0;
-       best = 9999999;
-       for ( i = 1 ; i < 255 ; i++ )
-       {
-               value = palette[i * 3 + 0] + palette[i * 3 + 1] + palette[i * 3 + 2];
-               if ( value < best ) {
-                       best = value;
-                       alt_zero = i;
-               }
-       }
-
-       c = width * height;
-       for ( i = 0 ; i < c ; i++ )
-               if ( pixels[i] == 0 ) {
-                       pixels[i] = alt_zero;
-               }
-}
-
-#endif
-
-
-// ********************************************************************
-// **  Mip Map Pre-Processing Routines
-// ********************************************************************
-
-#define intensity_value 1
-
-static unsigned image_pal[256];
-
-#define MAX_LAST 25
-
-long palette_r[256], palette_g[256], palette_b[256];
-long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
-
-long cached;
-
-void PrepareConvert( unsigned *palette ){
-       int i;
-
-       for ( i = 0; i < 256; i++ )
-       {
-               palette_r[i] = ( palette[i] & 0x00ff0000 ) >> 16;
-               palette_g[i] = ( palette[i] & 0x0000ff00 ) >> 8;
-               palette_b[i] = ( palette[i] & 0x000000ff );
-       }
-
-       for ( i = 0; i < MAX_LAST; i++ )
-               last_r[i] = -1;
-
-       last_place = -1;
-}
-
-int ConvertTrueColorToPal( unsigned r, unsigned g, unsigned b ){
-       int i;
-       long min_dist;
-       int min_index;
-       long dist;
-       long dr, dg, db, biggest_delta;
-
-       for ( i = 0; i < MAX_LAST; i++ )
-               if ( r == last_r[i] && g == last_g[i] && b == last_b[i] ) {
-                       cached++;
-                       return last_i[i];
-               }
-
-       min_dist = 256 * 256 + 256 * 256 + 256 * 256;
-       biggest_delta = 256 * 256;
-       min_index = 0;
-
-       for ( i = 0; i < 256; i++ )
-       {
-               dr = abs( palette_r[i] - r );
-               if ( dr > biggest_delta ) {
-                       continue;
-               }
-               dg = abs( palette_g[i] - g );
-               if ( dg > biggest_delta ) {
-                       continue;
-               }
-               db = abs( palette_b[i] - b );
-               if ( db > biggest_delta ) {
-                       continue;
-               }
-
-               dist = dr * dr + dg * dg + db * db;
-               if ( dist < min_dist ) {
-                       min_dist = dist;
-                       min_index = i;
-                       if ( min_dist == 0 ) {
-                               break;
-                       }
-
-                       dist = dr;
-                       if ( dg > dist ) {
-                               dist = dg;
-                       }
-                       if ( db > dist ) {
-                               dist = db;
-                       }
-                       if ( dist < biggest_delta ) {
-                               biggest_delta = dist;
-                       }
-               }
-       }
-
-       last_place++;
-       if ( last_place >= MAX_LAST ) {
-               last_place = 0;
-       }
-
-       last_r[last_place] = r;
-       last_g[last_place] = g;
-       last_b[last_place] = b;
-       last_i[last_place] = min_index;
-
-       return min_index;
-}
-
-
-void GL_ResampleTexture8P( byte *in, int inwidth, int inheight, byte *out,
-                                                  int outwidth, int outheight, palette_t *palette ){
-       int i, j;
-       byte    *inrow, *inrow2;
-       unsigned frac, fracstep;
-       unsigned p1[1024], p2[1024], *p1p, *p2p;
-       palette_t   *c1,*c2,*c3,*c4;
-       unsigned r,g,b;
-
-       fracstep = inwidth * 0x10000 / outwidth;
-
-       frac = fracstep >> 2;
-       for ( i = 0 ; i < outwidth ; i++ )
-       {
-               p1[i] = frac >> 16;
-               frac += fracstep;
-       }
-       frac = 3 * ( fracstep >> 2 );
-       for ( i = 0 ; i < outwidth ; i++ )
-       {
-               p2[i] = frac >> 16;
-               frac += fracstep;
-       }
-
-       cached = 0;
-
-       for ( i = 0 ; i < outheight ; i++ ) //, out += outwidth)
-       {
-               inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
-               inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
-
-               p1p = p1;
-               p2p = p2;
-               for ( j = 0 ; j < outwidth ; j++ )
-               {
-                       c1 = &palette[*( (byte *)inrow + ( *p1p ) )];
-                       c2 = &palette[*( (byte *)inrow + ( *p2p ) )];
-                       c3 = &palette[*( (byte *)inrow2 + ( *p1p++ ) )];
-                       c4 = &palette[*( (byte *)inrow2 + ( *p2p++ ) )];
-
-                       r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
-                       g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
-                       b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
-
-                       *out++ = ConvertTrueColorToPal( r,g,b );
-               }
-       }
-}
-
-void GL_MipMap8P( byte *out, byte *in, int width, int height, palette_t *palette ){
-       int i, j;
-       palette_t   *c1,*c2,*c3,*c4;
-       unsigned r,g,b;
-
-       cached = 0;
-       memset( out, 0, 256 * 256 );
-       width <<= 1;
-       height <<= 1;
-
-       for ( i = 0; i < height; i += 2, in += width )
-       {
-               for ( j = 0; j < width; j += 2 )
-               {
-                       c1 = &palette[in[0]];
-                       c3 = &palette[in[width]];
-                       in++;
-                       c2 = &palette[in[0]];
-                       c4 = &palette[in[width]];
-                       in++;
-
-                       r = ( (unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r ) >> 2;
-                       g = ( (unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g ) >> 2;
-                       b = ( (unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b ) >> 2;
-
-                       *out++ = ConvertTrueColorToPal( r, g, b );
-               }
-       }
-}
-
-
-miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip ){
-       int scaled_width, scaled_height;
-       int i,j,r,g,b;
-       byte intensitytable[256];
-       byte scaled[256 * 256];
-       byte out[256 * 256];
-       int miplevel;
-       miptex_t    *mp;
-       byte        *pos;
-       int size;
-
-       for ( i = 0 ; i < 256 ; i++ )
-       {
-               j = i * intensity_value;
-               if ( j > 255 ) {
-                       j = 255;
-               }
-               intensitytable[i] = j;
-       }
-
-       for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
-               ;
-       if ( 1 && scaled_width > width && 1 ) {
-               scaled_width >>= 1;
-       }
-       for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
-               ;
-       if ( 1 && scaled_height > height && 1 ) {
-               scaled_height >>= 1;
-       }
-
-       // don't ever bother with >256 textures
-       if ( scaled_width > 256 ) {
-               scaled_width = 256;
-       }
-       if ( scaled_height > 256 ) {
-               scaled_height = 256;
-       }
-
-       if ( scaled_width < 1 ) {
-               scaled_width = 1;
-       }
-       if ( scaled_height < 1 ) {
-               scaled_height = 1;
-       }
-
-       size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 );
-       mp = (miptex_t *)SafeMalloc( size, "CreateMip" );
-       memset( mp,0,size );
-
-       mp->version = MIP_VERSION;
-
-       for ( i = j = 0; i < 256; i++,j += 3 )
-       {
-               mp->palette[i].r = r = intensitytable[palette[j]];
-               mp->palette[i].g = g = intensitytable[palette[j + 1]];
-               mp->palette[i].b = b = intensitytable[palette[j + 2]];
-               image_pal[i] = 0xff000000 | ( r << 16 ) | ( g << 8 ) | ( b );
-       }
-
-       PrepareConvert( image_pal );
-
-       if ( scaled_width == width && scaled_height == height ) {
-               memcpy( scaled, data, width * height );
-       }
-       else{
-               GL_ResampleTexture8P( data, width, height, scaled, scaled_width, scaled_height, mp->palette );
-       }
-
-       pos = (byte *)( mp + 1 );
-       miplevel = 0;
-
-       while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
-       {
-               if ( scaled_width < 1 ) {
-                       scaled_width = 1;
-               }
-               if ( scaled_height < 1 ) {
-                       scaled_height = 1;
-               }
-
-               if ( miplevel > 0 ) {
-                       GL_MipMap8P( out, (byte *)scaled, scaled_width, scaled_height, mp->palette );
-               }
-               else{
-                       memcpy( out, scaled, 256 * 256 );
-               }
-
-               mp->width[miplevel] = scaled_width;
-               mp->height[miplevel] = scaled_height;
-               mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
-               memcpy( pos, out, scaled_width * scaled_height );
-               memcpy( scaled, out, 256 * 256 );
-               pos += scaled_width * scaled_height;
-
-               scaled_width >>= 1;
-               scaled_height >>= 1;
-
-               miplevel++;
-       }
-
-       *FinalSize = pos - ( (byte *)( mp ) );
-
-       return mp;
-}
-
-
-void GL_ResampleTexture( unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight ){
-       int i, j;
-       unsigned    *inrow, *inrow2;
-       unsigned frac, fracstep;
-       unsigned p1[1024], p2[1024];
-       byte        *pix1, *pix2, *pix3, *pix4;
-
-       fracstep = inwidth * 0x10000 / outwidth;
-
-       frac = fracstep >> 2;
-       for ( i = 0 ; i < outwidth ; i++ )
-       {
-               p1[i] = 4 * ( frac >> 16 );
-               frac += fracstep;
-       }
-       frac = 3 * ( fracstep >> 2 );
-       for ( i = 0 ; i < outwidth ; i++ )
-       {
-               p2[i] = 4 * ( frac >> 16 );
-               frac += fracstep;
-       }
-
-       for ( i = 0 ; i < outheight ; i++, out += outwidth )
-       {
-               inrow = in + inwidth * (int)( ( i + 0.25 ) * inheight / outheight );
-               inrow2 = in + inwidth * (int)( ( i + 0.75 ) * inheight / outheight );
-               frac = fracstep >> 1;
-               for ( j = 0 ; j < outwidth ; j++ )
-               {
-                       pix1 = (byte *)inrow + p1[j];
-                       pix2 = (byte *)inrow + p2[j];
-                       pix3 = (byte *)inrow2 + p1[j];
-                       pix4 = (byte *)inrow2 + p2[j];
-                       ( (byte *)( out + j ) )[0] = ( pix1[0] + pix2[0] + pix3[0] + pix4[0] ) >> 2;
-                       ( (byte *)( out + j ) )[1] = ( pix1[1] + pix2[1] + pix3[1] + pix4[1] ) >> 2;
-                       ( (byte *)( out + j ) )[2] = ( pix1[2] + pix2[2] + pix3[2] + pix4[2] ) >> 2;
-                       ( (byte *)( out + j ) )[3] = ( pix1[3] + pix2[3] + pix3[3] + pix4[3] ) >> 2;
-               }
-       }
-}
-
-void GL_MipMap( byte *out, byte *in, int width, int height ){
-       int i, j;
-
-       width <<= 3;
-       height <<= 1;
-       for ( i = 0 ; i < height ; i++, in += width )
-       {
-               for ( j = 0 ; j < width ; j += 8, out += 4, in += 8 )
-               {
-                       out[0] = ( in[0] + in[4] + in[width + 0] + in[width + 4] ) >> 2;
-                       out[1] = ( in[1] + in[5] + in[width + 1] + in[width + 5] ) >> 2;
-                       out[2] = ( in[2] + in[6] + in[width + 2] + in[width + 6] ) >> 2;
-                       out[3] = ( in[3] + in[7] + in[width + 3] + in[width + 7] ) >> 2;
-               }
-       }
-}
-
-miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip ){
-       int scaled_width, scaled_height;
-       unsigned scaled[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
-       unsigned out[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
-       int miplevel;
-       miptex32_t      *mp;
-       byte            *pos;
-       int size;
-       paletteRGBA_t   *test;
-
-       for ( scaled_width = 1 ; scaled_width < width ; scaled_width <<= 1 )
-               ;
-       if ( 1 && scaled_width > width && 1 ) {
-               scaled_width >>= 1;
-       }
-       for ( scaled_height = 1 ; scaled_height < height ; scaled_height <<= 1 )
-               ;
-       if ( 1 && scaled_height > height && 1 ) {
-               scaled_height >>= 1;
-       }
-
-       // don't ever bother with >256 textures
-       if ( scaled_width > MAX_IMAGE_SIZE ) {
-               scaled_width = MAX_IMAGE_SIZE;
-       }
-       if ( scaled_height > MAX_IMAGE_SIZE ) {
-               scaled_height = MAX_IMAGE_SIZE;
-       }
-
-       if ( scaled_width < 1 ) {
-               scaled_width = 1;
-       }
-       if ( scaled_height < 1 ) {
-               scaled_height = 1;
-       }
-
-       size = sizeof( *mp ) + ( scaled_width * scaled_height * 3 * 4 );
-       mp = (miptex32_t *)SafeMalloc( size, "CreateMip" );
-       memset( mp,0,size );
-
-       mp->version = MIP32_VERSION;
-
-       size = width * height;
-       test = (paletteRGBA_t *)data;
-       while ( size )
-       {
-               if ( test->a != 255 ) {
-                       mp->flags |= LittleLong( SURF_ALPHA_TEXTURE );
-                       break;
-               }
-
-               size--;
-               test++;
-       }
-
-       if ( scaled_width == width && scaled_height == height ) {
-               memcpy( scaled, data, width * height * 4 );
-       }
-       else{
-               GL_ResampleTexture( data, width, height, scaled, scaled_width, scaled_height );
-       }
-
-       pos = (byte *)( mp + 1 );
-       miplevel = 0;
-
-       while ( ( scaled_width >= 1 || scaled_height >= 1 ) && ( miplevel <= MIPLEVELS - 1 ) && ( !miplevel || mip ) )
-       {
-               if ( scaled_width < 1 ) {
-                       scaled_width = 1;
-               }
-               if ( scaled_height < 1 ) {
-                       scaled_height = 1;
-               }
-
-               if ( miplevel > 0 ) {
-                       GL_MipMap( (byte *)out, (byte *)scaled, scaled_width, scaled_height );
-               }
-               else
-               {
-                       memcpy( out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
-               }
-
-               mp->width[miplevel] = scaled_width;
-               mp->height[miplevel] = scaled_height;
-               mp->offsets[miplevel] = pos - ( (byte *)( mp ) );
-               memcpy( pos, out, scaled_width * scaled_height * 4 );
-               memcpy( scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4 );
-               pos += scaled_width * scaled_height * 4;
-
-               scaled_width >>= 1;
-               scaled_height >>= 1;
-
-               miplevel++;
-       }
-
-       *FinalSize = pos - ( (byte *)( mp ) );
-
-       return mp;
-}
-
-/*
-   ==============
-   Cmd_Grab
-
-   $grab filename x y width height
-   ==============
- */
-void Cmd_Grab( void ){
-       int xl,yl,w,h,y;
-       byte            *cropped;
-       char savename[1024];
-       char dest[1024];
-
-       GetScriptToken( false );
-
-       if ( token[0] == '/' || token[0] == '\\' ) {
-               sprintf( savename, "%s%s.pcx", gamedir, token + 1 );
-       }
-       else{
-               sprintf( savename, "%spics/%s.pcx", gamedir, token );
-       }
-
-       if ( g_release ) {
-               if ( token[0] == '/' || token[0] == '\\' ) {
-                       sprintf( dest, "%s.pcx", token + 1 );
-               }
-               else{
-                       sprintf( dest, "pics/%s.pcx", token );
-               }
-
-               ReleaseFile( dest );
-               return;
-       }
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
-               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
-       }
-
-       // crop it to the proper size
-       cropped = (byte *) SafeMalloc( w * h, "Cmd_Grab" );
-       for ( y = 0 ; y < h ; y++ )
-       {
-               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
-       }
-
-       // save off the new image
-       printf( "saving %s\n", savename );
-       CreatePath( savename );
-       WritePCXfile( savename, cropped, w, h, lbmpalette );
-
-       free( cropped );
-}
-
-/*
-   ==============
-   Cmd_Raw
-
-   $grab filename x y width height
-   ==============
- */
-void Cmd_Raw( void ){
-       int xl,yl,w,h,y;
-       byte            *cropped;
-       char savename[1024];
-       char dest[1024];
-
-       GetScriptToken( false );
-
-       sprintf( savename, "%s%s.lmp", gamedir, token );
-
-       if ( g_release ) {
-               sprintf( dest, "%s.lmp", token );
-               ReleaseFile( dest );
-               return;
-       }
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       if ( xl < 0 || yl < 0 || w < 0 || h < 0 || xl + w > byteimagewidth || yl + h > byteimageheight ) {
-               Error( "GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h );
-       }
-
-       // crop it to the proper size
-       cropped = (byte *) SafeMalloc( w * h, "Cmd_Raw" );
-       for ( y = 0 ; y < h ; y++ )
-       {
-               memcpy( cropped + y * w, byteimage + ( y + yl ) * byteimagewidth + xl, w );
-       }
-
-       // save off the new image
-       printf( "saving %s\n", savename );
-       CreatePath( savename );
-
-       SaveFile( savename, cropped, w * h );
-
-       free( cropped );
-}
-
-/*
-   =============================================================================
-
-   COLORMAP GRABBING
-
-   =============================================================================
- */
-
-/*
-   ===============
-   BestColor
-   ===============
- */
-byte BestColor( int r, int g, int b, int start, int stop ){
-       int i;
-       int dr, dg, db;
-       int bestdistortion, distortion;
-       int bestcolor;
-       byte    *pal;
-
-//
-// let any color go to 0 as a last resort
-//
-       bestdistortion = 256 * 256 * 4;
-       bestcolor = 0;
-
-       pal = colormap_palette + start * 3;
-       for ( i = start ; i <= stop ; i++ )
-       {
-               dr = r - (int)pal[0];
-               dg = g - (int)pal[1];
-               db = b - (int)pal[2];
-               pal += 3;
-               distortion = dr * dr + dg * dg + db * db;
-               if ( distortion < bestdistortion ) {
-                       if ( !distortion ) {
-                               return i;       // perfect match
-
-                       }
-                       bestdistortion = distortion;
-                       bestcolor = i;
-               }
-       }
-
-       return bestcolor;
-}
-
-
-/*
-   ==============
-   Cmd_Colormap
-
-   $colormap filename
-
-   the brightes colormap is first in the table (FIXME: reverse this now?)
-
-   64 rows of 256 : lightmaps
-   256 rows of 256 : translucency table
-   ==============
- */
-void Cmd_Colormap( void ){
-       int levels, brights;
-       int l, c;
-       float frac, red, green, blue;
-       float range;
-       byte    *cropped, *lump_p;
-       char savename[1024];
-       char dest[1024];
-
-       colormap_issued = true;
-       if ( !g_release ) {
-               memcpy( colormap_palette, lbmpalette, 768 );
-       }
-
-       if ( !ScriptTokenAvailable() ) { // just setting colormap_issued
-               return;
-       }
-
-       GetScriptToken( false );
-       sprintf( savename, "%spics/%s.pcx", gamedir, token );
-
-       if ( g_release ) {
-               sprintf( dest, "pics/%s.pcx", token );
-               ReleaseFile( dest );
-               return;
-       }
-
-       range = 2;
-       levels = 64;
-       brights = 1;    // ignore 255 (transparent)
-
-       cropped = (byte *) SafeMalloc( ( levels + 256 ) * 256, "Cmd_ColorMap" );
-       lump_p = cropped;
-
-// shaded levels
-       for ( l = 0; l < levels; l++ )
-       {
-               frac = range - range * (float)l / ( levels - 1 );
-               for ( c = 0 ; c < 256 - brights ; c++ )
-               {
-                       red = lbmpalette[c * 3];
-                       green = lbmpalette[c * 3 + 1];
-                       blue = lbmpalette[c * 3 + 2];
-
-                       red = (int)( red * frac + 0.5 );
-                       green = (int)( green * frac + 0.5 );
-                       blue = (int)( blue * frac + 0.5 );
-
-//
-// note: 254 instead of 255 because 255 is the transparent color, and we
-// don't want anything remapping to that
-// don't use color 0, because NT can't remap that (or 255)
-//
-                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
-               }
-
-               // fullbrights allways stay the same
-               for ( ; c < 256 ; c++ )
-                       *lump_p++ = c;
-       }
-
-// 66% transparancy table
-       for ( l = 0; l < 255; l++ )
-       {
-               for ( c = 0 ; c < 255 ; c++ )
-               {
-                       red = lbmpalette[c * 3] * 0.33 + lbmpalette[l * 3] * 0.66;
-                       green = lbmpalette[c * 3 + 1] * 0.33 + lbmpalette[l * 3 + 1] * 0.66;
-                       blue = lbmpalette[c * 3 + 2] * 0.33 + lbmpalette[l * 3 + 2] * 0.66;
-
-                       *lump_p++ = BestColor( red,green,blue, 1, 254 );
-               }
-               *lump_p++ = 255;
-       }
-       for ( c = 0 ; c < 256 ; c++ )
-               *lump_p++ = 255;
-
-       // save off the new image
-       printf( "saving %s\n", savename );
-       CreatePath( savename );
-       WritePCXfile( savename, cropped, 256, levels + 256, lbmpalette );
-
-       free( cropped );
-}
-
-/*
-   =============================================================================
-
-   MIPTEX GRABBING
-
-   =============================================================================
- */
-
-byte pixdata[256];
-
-int d_red, d_green, d_blue;
-
-byte palmap[32][32][32];
-qboolean palmap_built;
-
-/*
-   =============
-   FindColor
-   =============
- */
-int FindColor( int r, int g, int b ){
-       int bestcolor;
-
-       if ( r > 255 ) {
-               r = 255;
-       }
-       if ( r < 0 ) {
-               r = 0;
-       }
-       if ( g > 255 ) {
-               g = 255;
-       }
-       if ( g < 0 ) {
-               g = 0;
-       }
-       if ( b > 255 ) {
-               b = 255;
-       }
-       if ( b < 0 ) {
-               b = 0;
-       }
-#ifndef TABLECOLORS
-       bestcolor = BestColor( r, g, b, 0, 254 );
-#else
-       bestcolor = palmap[r >> 3][g >> 3][b >> 3];
-#endif
-
-       return bestcolor;
-}
-
-
-void BuildPalmap( void ){
-#ifdef TABLECOLORS
-       int r, g, b;
-       int bestcolor;
-
-       if ( palmap_built ) {
-               return;
-       }
-       palmap_built = true;
-
-       for ( r = 4 ; r < 256 ; r += 8 )
-       {
-               for ( g = 4 ; g < 256 ; g += 8 )
-               {
-                       for ( b = 4 ; b < 256 ; b += 8 )
-                       {
-                               bestcolor = BestColor( r, g, b, 1, 254 );
-                               palmap[r >> 3][g >> 3][b >> 3] = bestcolor;
-                       }
-               }
-       }
-#endif
-
-       if ( !colormap_issued ) {
-               Error( "You must issue a $colormap command first" );
-       }
-
-}
-
-/*
-   =============
-   AveragePixels
-   =============
- */
-byte AveragePixels( int count ){
-       int r,g,b;
-       int i;
-       int vis;
-       int pix;
-       int bestcolor;
-       byte    *pal;
-       int fullbright;
-
-       vis = 0;
-       r = g = b = 0;
-       fullbright = 0;
-       for ( i = 0 ; i < count ; i++ )
-       {
-               pix = pixdata[i];
-
-               r += lbmpalette[pix * 3];
-               g += lbmpalette[pix * 3 + 1];
-               b += lbmpalette[pix * 3 + 2];
-               vis++;
-       }
-
-       r /= vis;
-       g /= vis;
-       b /= vis;
-
-       // error diffusion
-       r += d_red;
-       g += d_green;
-       b += d_blue;
-
-//
-// find the best color
-//
-       bestcolor = FindColor( r, g, b );
-
-       // error diffusion
-       pal = colormap_palette + bestcolor * 3;
-       d_red = r - (int)pal[0];
-       d_green = g - (int)pal[1];
-       d_blue = b - (int)pal[2];
-
-       return bestcolor;
-}
-
-
-typedef enum
-{
-       pt_contents,
-       pt_flags,
-       pt_animvalue,
-       pt_altnamevalue,
-       pt_damagenamevalue,
-       pt_flagvalue,
-       pt_materialvalue,
-       pt_scale,
-       pt_mip,
-       pt_detail,
-       pt_gl,
-       pt_nomip,
-       pt_detailer,
-} parmtype_t;
-
-typedef struct
-{
-       char    *name;
-       int flags;
-       parmtype_t type;
-} mipparm_t;
-
-mipparm_t mipparms[] =
-{
-       // utility content attributes
-       {"pushpull",CONTENTS_PUSHPULL, pt_contents},
-       {"water",   CONTENTS_WATER, pt_contents},
-       {"slime",   CONTENTS_SLIME, pt_contents},       // mildly damaging
-       {"lava",    CONTENTS_LAVA, pt_contents},        // very damaging
-       {"window",  CONTENTS_WINDOW, pt_contents},  // solid, but doesn't eat internal textures
-       {"mist",    CONTENTS_MIST, pt_contents},    // non-solid window
-       {"origin",  CONTENTS_ORIGIN, pt_contents},  // center of rotating brushes
-       {"playerclip",  CONTENTS_PLAYERCLIP, pt_contents},
-       {"monsterclip", CONTENTS_MONSTERCLIP, pt_contents},
-
-       // utility surface attributes
-       {"hint",    SURF_HINT, pt_flags},
-       {"skip",    SURF_SKIP, pt_flags},
-       {"light",   SURF_LIGHT, pt_flagvalue},      // value is the light quantity
-
-       {"animspeed",SURF_ANIMSPEED, pt_flagvalue},     // value will hold the anim speed in fps
-
-       // texture chaining
-       {"anim",    0,          pt_animvalue},      // animname is the next animation
-       {"alt",     0,          pt_altnamevalue},   // altname is the alternate texture
-       {"damage",  0,          pt_damagenamevalue},    // damagename is the damage texture
-       {"scale",   0,          pt_scale},      // next two values are for scale
-       {"mip",     0,          pt_mip},
-       {"detail",  0,          pt_detail},
-
-       {"GL_ZERO",                 GL_ZERO,                pt_gl},
-       {"GL_ONE",                  GL_ONE,                 pt_gl},
-       {"GL_SRC_COLOR",            GL_SRC_COLOR,           pt_gl},
-       {"GL_ONE_MINUS_SRC_COLOR",  GL_ONE_MINUS_SRC_COLOR, pt_gl},
-       {"GL_DST_COLOR",            GL_DST_COLOR,           pt_gl},
-       {"GL_ONE_MINUS_DST_COLOR",  GL_ONE_MINUS_DST_COLOR, pt_gl},
-       {"GL_SRC_ALPHA",            GL_SRC_ALPHA,           pt_gl},
-       {"GL_ONE_MINUS_SRC_ALPHA",  GL_ONE_MINUS_SRC_ALPHA, pt_gl},
-       {"GL_DST_ALPHA",            GL_DST_ALPHA,           pt_gl},
-       {"GL_ONE_MINUS_DST_ALPHA",  GL_ONE_MINUS_DST_ALPHA, pt_gl},
-       {"GL_SRC_ALPHA_SATURATE",   GL_SRC_ALPHA_SATURATE,  pt_gl},
-
-       // server attributes
-       {"slick",   SURF_SLICK, pt_flags},
-
-       // drawing attributes
-       {"sky",     SURF_SKY, pt_flags},
-       {"warping", SURF_WARP, pt_flags},       // only valid with 64x64 textures
-       {"trans33", SURF_TRANS33, pt_flags},    // translucent should allso set fullbright
-       {"trans66", SURF_TRANS66, pt_flags},
-       {"flowing", SURF_FLOWING, pt_flags},    // flow direction towards angle 0
-       {"nodraw",  SURF_NODRAW, pt_flags}, // for clip textures and trigger textures
-       {"alpha",   SURF_ALPHA_TEXTURE, pt_flags},
-       {"undulate",    SURF_UNDULATE, pt_flags},       // rock surface up and down...
-       {"skyreflect",  SURF_SKYREFLECT, pt_flags},     // liquid will somewhat reflect the sky - not quite finished....
-
-       {"material", SURF_MATERIAL, pt_materialvalue},
-       {"metal",   SURF_TYPE_METAL, pt_flags},
-       {"stone",   SURF_TYPE_STONE, pt_flags},
-       {"wood",    SURF_TYPE_WOOD, pt_flags},
-
-       {"m_nomip", 0, pt_nomip},
-       {"m_detail", 0, pt_detailer},
-
-       {NULL, 0, pt_contents}
-};
-
-/*
-   ==============
-   Cmd_Mip
-
-   $mip filename x y width height <OPTIONS>
-   must be multiples of sixteen
-   SURF_WINDOW
-   ==============
- */
-
-void Cmd_Mip( void ){
-       int xl,yl,xh,yh,w,h;
-       byte            *dest, *source;
-       int flags, value, contents;
-       mipparm_t       *mp;
-       char lumpname[128];
-       char altname[128];
-       char animname[128];
-       char damagename[128];
-       byte buffer[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
-       unsigned bufferl[MAX_IMAGE_SIZE * MAX_IMAGE_SIZE];
-       materialtype_t  *mat;
-       char filename[1024];
-       unsigned        *destl, *sourcel;
-       int linedelta, x, y;
-       int size;
-       miptex_t        *qtex;
-       miptex32_t      *qtex32;
-       float scale_x, scale_y;
-       int mip_scale;
-       // detail texturing
-       char dt_name[128];
-       float dt_scale_x, dt_scale_y;
-       float dt_u, dt_v;
-       float dt_alpha;
-       int dt_src_blend_mode, dt_dst_blend_mode;
-       int flags2;
-
-
-       GetScriptToken( false );
-       strcpy( lumpname, token );
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       total_x += w;
-       total_y += h;
-       total_textures++;
-
-       if ( ( w & 15 ) || ( h & 15 ) ) {
-               Error( "line %i: miptex sizes must be multiples of 16", scriptline );
-       }
-
-       flags = 0;
-       flags2 = 0;
-       contents = 0;
-       value = 0;
-       mip_scale = 0;
-
-       altname[0] = animname[0] = damagename[0] = 0;
-
-       scale_x = scale_y = 0.5;
-
-       // detail texturing
-       dt_name[0] = 0;
-       dt_scale_x = dt_scale_y = 0.0;
-       dt_u = dt_v = 0.0;
-       dt_alpha = 0.0;
-       dt_src_blend_mode = dt_dst_blend_mode = 0;
-
-       // get optional flags and values
-       while ( ScriptTokenAvailable() )
-       {
-               GetScriptToken( false );
-
-               for ( mp = mipparms ; mp->name ; mp++ )
-               {
-                       if ( !strcmp( mp->name, token ) ) {
-                               switch ( mp->type )
-                               {
-                               case pt_animvalue:
-                                       GetScriptToken( false );    // specify the next animation frame
-                                       strcpy( animname, token );
-                                       break;
-                               case pt_altnamevalue:
-                                       GetScriptToken( false );    // specify the alternate texture
-                                       strcpy( altname, token );
-                                       break;
-                               case pt_damagenamevalue:
-                                       GetScriptToken( false );    // specify the damage texture
-                                       strcpy( damagename, token );
-                                       break;
-                               case pt_flags:
-                                       flags |= mp->flags;
-                                       break;
-                               case pt_contents:
-                                       contents |= mp->flags;
-                                       break;
-                               case pt_flagvalue:
-                                       flags |= mp->flags;
-                                       GetScriptToken( false );    // specify the light value
-                                       value = atoi( token );
-                                       break;
-                               case pt_materialvalue:
-                                       GetScriptToken( false );
-                                       for ( mat = materialtypes ; mat->name ; mat++ )
-                                       {
-                                               if ( !strcmp( mat->name, token ) ) {
-                                                       // assumes SURF_MATERIAL is in top 8 bits
-                                                       flags = ( flags & 0x0FFFFFF ) | ( mat->value << 24 );
-                                                       break;
-                                               }
-                                       }
-                                       break;
-                               case pt_scale:
-                                       GetScriptToken( false );    // specify the x scale
-                                       scale_x = atof( token );
-                                       GetScriptToken( false );    // specify the y scale
-                                       scale_y = atof( token );
-                                       break;
-
-                               case pt_mip:
-                                       mip_scale = 1;
-                                       break;
-
-                               case pt_detailer:
-                                       flags2 |= MIP32_DETAILER_FLAG2;
-                                       break;
-
-                               case pt_nomip:
-                                       flags2 |= MIP32_NOMIP_FLAG2;
-                                       break;
-
-                               case pt_detail:
-                                       GetScriptToken( false );
-                                       strcpy( dt_name, token );
-                                       GetScriptToken( false );
-                                       dt_scale_x = atof( token );
-                                       GetScriptToken( false );
-                                       dt_scale_y = atof( token );
-                                       GetScriptToken( false );
-                                       dt_u = atof( token );
-                                       GetScriptToken( false );
-                                       dt_v = atof( token );
-                                       GetScriptToken( false );
-                                       dt_alpha = atof( token );
-                                       GetScriptToken( false );
-                                       for ( mp = mipparms ; mp->name ; mp++ )
-                                       {
-                                               if ( !strcmp( mp->name, token ) ) {
-                                                       if ( mp->type == pt_gl ) {
-                                                               dt_src_blend_mode = mp->flags;
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                                       if ( !mp->name ) {
-                                               Error( "line %i: invalid gl blend mode %s", scriptline, token );
-                                       }
-                                       GetScriptToken( false );
-                                       for ( mp = mipparms ; mp->name ; mp++ )
-                                       {
-                                               if ( !strcmp( mp->name, token ) ) {
-                                                       if ( mp->type == pt_gl ) {
-                                                               dt_dst_blend_mode = mp->flags;
-                                                               break;
-                                                       }
-                                               }
-                                       }
-                                       if ( !mp->name ) {
-                                               Error( "line %i: invalid gl blend mode %s", scriptline, token );
-                                       }
-                                       break;
-                               }
-                               break;
-                       }
-               }
-               if ( !mp->name ) {
-                       Error( "line %i: unknown parm %s", scriptline, token );
-               }
-       }
-
-       if ( g_release ) {
-               return; // textures are only released by $maps
-
-       }
-       xh = xl + w;
-       yh = yl + h;
-       if ( xh * yh > MAX_IMAGE_SIZE * MAX_IMAGE_SIZE ) {
-               Error( "line %i image %s: image is too big!", scriptline, lumpname );
-       }
-
-       if ( TrueColorImage ) {
-               if ( xl >= longimagewidth || xh > longimagewidth ||
-                        yl >= longimageheight || yh > longimageheight ) {
-                       Error( "line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight );
-               }
-
-               sourcel = longimage + ( yl * longimagewidth ) + xl;
-               destl = bufferl;
-               linedelta = ( longimagewidth - w );
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *destl++ = *sourcel++;  // RGBA
-                       }
-                       sourcel += linedelta;
-               }
-
-               qtex32 = CreateMip32( bufferl, w, h, &size, true );
-
-               qtex32->flags |= LittleLong( flags );
-               qtex32->flags2 |= LittleLong( flags2 );
-               qtex32->contents = LittleLong( contents );
-               qtex32->value = LittleLong( value );
-               qtex32->scale_x = scale_x;
-               qtex32->scale_y = scale_y;
-               qtex32->mip_scale = mip_scale;
-               sprintf( qtex32->name, "%s/%s", mip_prefix, lumpname );
-               if ( animname[0] ) {
-                       sprintf( qtex32->animname, "%s/%s", mip_prefix, animname );
-               }
-               if ( altname[0] ) {
-                       sprintf( qtex32->altname, "%s/%s", mip_prefix, altname );
-               }
-               if ( damagename[0] ) {
-                       sprintf( qtex32->damagename, "%s/%s", mip_prefix, damagename );
-               }
-               if ( dt_name[0] & ( ( flags2 & MIP32_DETAILER_FLAG2 ) == 0 ) ) {
-                       sprintf( qtex32->dt_name, "%s/%s", mip_prefix, dt_name );
-                       qtex32->dt_scale_x = dt_scale_x;
-                       qtex32->dt_scale_y = dt_scale_y;
-                       qtex32->dt_u = dt_u;
-                       qtex32->dt_v = dt_v;
-                       qtex32->dt_alpha = dt_alpha;
-                       qtex32->dt_src_blend_mode = dt_src_blend_mode;
-                       qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
-               }
-
-               //
-               // write it out
-               //
-               sprintf( filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname );
-               if ( qtex32->flags & ( SURF_ALPHA_TEXTURE ) ) {
-                       printf( "writing %s with ALPHA\n", filename );
-               }
-               else{
-                       printf( "writing %s\n", filename );
-               }
-               SaveFile( filename, (byte *)qtex32, size );
-
-               free( qtex32 );
-       }
-       else
-       {
-               if ( xl >= byteimagewidth || xh > byteimagewidth ||
-                        yl >= byteimageheight || yh > byteimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
-               }
-
-               source = byteimage + yl * byteimagewidth + xl;
-               dest = buffer;
-               linedelta = byteimagewidth - w;
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *dest++ = *source++;
-                       }
-                       source += linedelta;
-               }
-
-               qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
-
-               qtex->flags = LittleLong( flags );
-               qtex->contents = LittleLong( contents );
-               qtex->value = LittleLong( value );
-               sprintf( qtex->name, "%s/%s", mip_prefix, lumpname );
-               if ( animname[0] ) {
-                       sprintf( qtex->animname, "%s/%s", mip_prefix, animname );
-               }
-
-               //
-               // write it out
-               //
-               sprintf( filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname );
-               printf( "writing %s\n", filename );
-               SaveFile( filename, (byte *)qtex, size );
-
-               free( qtex );
-       }
-}
-
-/*
-   ===============
-   Cmd_Mippal
-   ===============
- */
-void Cmd_Mippal( void ){
-       colormap_issued = true;
-       if ( g_release ) {
-               return;
-       }
-
-       memcpy( colormap_palette, lbmpalette, 768 );
-
-       BuildPalmap();
-}
-
-
-/*
-   ===============
-   Cmd_Mipdir
-   ===============
- */
-void Cmd_Mipdir( void ){
-       char filename[1024];
-
-       GetScriptToken( false );
-       strcpy( mip_prefix, token );
-       // create the directory if needed
-       sprintf( filename, "%stextures", g_outputDir );
-       Q_mkdir( filename );
-       sprintf( filename, "%stextures/%s", g_outputDir, mip_prefix );
-       Q_mkdir( filename );
-}
-
-
-/*
-   =============================================================================
-
-   ENVIRONMENT MAP GRABBING
-
-   Creates six pcx files from tga files without any palette edge seams
-   also copies the tga files for GL rendering.
-   =============================================================================
- */
-
-// 3dstudio environment map suffixes
-char    *suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
-
-/*
-   =================
-   Cmd_Environment
-   =================
- */
-void Cmd_Environment( void ){
-       char name[1024];
-       int i, x, y;
-       byte image[256 * 256];
-       byte    *tga;
-
-       GetScriptToken( false );
-
-       if ( g_release ) {
-               for ( i = 0 ; i < 6 ; i++ )
-               {
-                       sprintf( name, "env/%s%s.pcx", token, suf[i] );
-                       ReleaseFile( name );
-                       sprintf( name, "env/%s%s.tga", token, suf[i] );
-                       ReleaseFile( name );
-               }
-               return;
-       }
-       // get the palette
-       BuildPalmap();
-
-       sprintf( name, "%senv/", gamedir );
-       CreatePath( name );
-
-       // convert the images
-       for ( i = 0 ; i < 6 ; i++ )
-       {
-               sprintf( name, "%senv/%s%s.tga", gamedir, token, suf[i] );
-               printf( "loading %s...\n", name );
-               LoadTGA( name, &tga, NULL, NULL );
-
-               for ( y = 0 ; y < 256 ; y++ )
-               {
-                       for ( x = 0 ; x < 256 ; x++ )
-                       {
-                               image[y * 256 + x] = FindColor( tga[( y * 256 + x ) * 4 + 0],tga[( y * 256 + x ) * 4 + 1],tga[( y * 256 + x ) * 4 + 2] );
-                       }
-               }
-               free( tga );
-               sprintf( name, "%senv/%s%s.pcx", gamedir, token, suf[i] );
-               if ( FileTime( name ) != -1 ) {
-                       printf( "%s already exists, not overwriting.\n", name );
-               }
-               else{
-                       WritePCXfile( name, image, 256, 256, colormap_palette );
-               }
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/jointed.c b/tools/quake2/qdata_heretic2/jointed.c
deleted file mode 100644 (file)
index de8b802..0000000
+++ /dev/null
@@ -1,548 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <assert.h>
-#include <math.h>
-#include "token.h"
-#include "joints.h"
-#include "angles.h"
-#include "inout.h"
-
-char *SKEL_ROOT_NAMES[] =
-{
-       "RAVEN_SPINE"
-};
-
-char *SKEL_NAMES[] =
-{
-       "RAVEN_WAIST1",
-       "RAVEN_WAIST2",
-       "RAVEN_NECK"
-};
-
-int NAME_OFFSETS[] =
-{
-       0
-};
-
-int numJointsForSkeleton[] =
-{
-       NUM_JOINTS_RAVEN,
-       NUM_JOINTS_BOX
-};
-
-float g_scaling[3];
-float g_rotation[3];
-float g_translation[3];
-
-//==========================================================================
-//
-// LoadHRCClustered
-//
-//==========================================================================
-
-static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
-       int i, j;
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       TK_Beyond( TK_CLUSTERS );
-
-       while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
-       {
-               TK_Require( TK_STRING );
-
-               for ( i = 0; i < numJointsForSkeleton[skelType]; ++i )
-               {
-                       if ( stricmp( tk_String, SKEL_NAMES[NAME_OFFSETS[skelType] + i] ) == 0 ) {
-                               i = -i + numJointsForSkeleton[skelType] - 1;
-
-                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
-
-                               num_verts[i + 1] = tk_IntNumber;
-
-                               clusterList[i] = (int *) SafeMalloc( num_verts[i + 1] * sizeof( int ), "LoadHRCClustered" );
-                               assert( clusterList[i] );
-                               // currently this function is only called by LoadTriangleListClustered, which in turn is only
-                               // called by Cmd_Base in qdata.  This is where the only call to free for this memory is being made.
-
-                               TK_Beyond( TK_LBRACE );
-
-                               for ( j = 0; j < num_verts[i + 1]; ++j )
-                               {
-                                       TK_Require( TK_INTNUMBER );
-                                       clusterList[i][j] = tk_IntNumber;
-                                       TK_Fetch();
-                               }
-
-                               break;
-                       }
-               }
-       }
-
-       num_verts[0] = numJointsForSkeleton[skelType];
-}
-
-static void LoadHRCGlobals( char *fileName ){
-       int i;
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-       TK_Beyond( TK_MODEL );
-
-       TK_Beyond( TK_SCALING );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_scaling[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-
-       TK_Beyond( TK_ROTATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_rotation[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-
-       TK_Beyond( TK_TRANSLATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_translation[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-}
-
-static void ParseVec3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = -tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void LoadHRCJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
-#define MAX_STACK 64
-       int i, j;
-       vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
-       int curCorrespondingJoint[MAX_STACK];
-       int currentStack = 0, stackSize;
-       int baseJoint;
-       float cx, sx, cy, sy, cz, sz;
-       float rx, ry, rz;
-       float x2, y2, z2;
-
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       TK_Beyond( TK_MODEL );
-       TK_Beyond( TK_MODEL );
-
-/*     while(1)
-    {
-        TK_Beyond(TK_MODEL);
-        TK_BeyondRequire(TK_NAME, TK_STRING);
-
-        if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
-            break;
-    }*/
-
-       TK_Beyond( TK_SCALING );
-
-       ParseVec3( curScale[currentStack] );
-
-       TK_Beyond( TK_ROTATION );
-
-       ParseRotation3( curRotation[currentStack] );
-
-       TK_Beyond( TK_TRANSLATION );
-
-       ParseVec3( curTranslation[currentStack] );
-
-       // account for global model translation
-       curTranslation[currentStack][1] += g_translation[0];
-       curTranslation[currentStack][2] += g_translation[1];
-       curTranslation[currentStack][0] += g_translation[2];
-
-       ++currentStack;
-
-       for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
-       {
-               while ( 1 )
-               {
-                       TK_Beyond( TK_MODEL );
-
-//                     TK_BeyondRequire(TK_NAME, TK_STRING);
-
-//                     if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
-                       break;
-
-                       TK_Beyond( TK_SCALING );
-
-                       ParseVec3( curScale[currentStack] );
-
-                       TK_Beyond( TK_ROTATION );
-
-                       ParseRotation3( curRotation[currentStack] );
-
-                       TK_Beyond( TK_TRANSLATION );
-
-                       ParseVec3( curTranslation[currentStack] );
-
-                       curCorrespondingJoint[currentStack] = -1;
-
-                       ++currentStack;
-               }
-
-               TK_Beyond( TK_SCALING );
-
-               ParseVec3( curScale[currentStack] );
-
-               TK_Beyond( TK_ROTATION );
-
-               ParseRotation3( curRotation[currentStack] );
-
-               jointList[i].rotation[1] = curRotation[currentStack][1];
-               jointList[i].rotation[2] = curRotation[currentStack][2];
-               jointList[i].rotation[0] = curRotation[currentStack][0];
-
-               TK_Beyond( TK_TRANSLATION );
-
-               ParseVec3( curTranslation[currentStack] );
-
-               jointList[i].placement.origin[1] = curTranslation[currentStack][1];
-               jointList[i].placement.origin[2] = curTranslation[currentStack][2];
-               jointList[i].placement.origin[0] = curTranslation[currentStack][0];
-
-               jointList[i].placement.direction[1] = 7.5;
-               jointList[i].placement.direction[2] = 0.0;
-               jointList[i].placement.direction[0] = 0.0;
-
-               jointList[i].placement.up[1] = 0.0;
-               jointList[i].placement.up[2] = 7.5;
-               jointList[i].placement.up[0] = 0.0;
-
-               curCorrespondingJoint[currentStack] = i;
-
-               ++currentStack;
-       }
-
-       stackSize = currentStack;
-
-       for ( i = 0; i < NUM_JOINTS_RAVEN; ++i )
-       {
-               rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
-               ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
-               rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
-
-               cx = cos( rx );
-               sx = sin( rx );
-
-               cy = cos( ry );
-               sy = sin( ry );
-
-               cz = cos( rz );
-               sz = sin( rz );
-
-               // y-axis rotation for direction
-               x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
-               z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
-               jointList[i].placement.direction[0] = x2;
-               jointList[i].placement.direction[2] = z2;
-
-               // y-axis rotation for up
-               x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
-               z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
-               jointList[i].placement.up[0] = x2;
-               jointList[i].placement.up[2] = z2;
-
-               // z-axis rotation for direction
-               x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
-               y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
-               jointList[i].placement.direction[0] = x2;
-               jointList[i].placement.direction[1] = y2;
-
-               // z-axis rotation for up
-               x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
-               y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
-               jointList[i].placement.up[0] = x2;
-               jointList[i].placement.up[1] = y2;
-
-               // x-axis rotation for direction vector
-               y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
-               z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
-               jointList[i].placement.direction[1] = y2;
-               jointList[i].placement.direction[2] = z2;
-
-               // x-axis rotation for up vector
-               y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
-               z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
-               jointList[i].placement.up[1] = y2;
-               jointList[i].placement.up[2] = z2;
-
-               // translate to position in model
-               jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
-               jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
-               jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
-
-               // translate to position in model
-               jointList[i].placement.up[0] += jointList[i].placement.origin[0];
-               jointList[i].placement.up[1] += jointList[i].placement.origin[1];
-               jointList[i].placement.up[2] += jointList[i].placement.origin[2];
-       }
-
-       baseJoint = NUM_JOINTS_RAVEN;
-
-       for ( i = stackSize /*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i )
-       {
-
-               rx = curRotation[i - 1][0] * ANGLE_TO_RAD;
-               ry = curRotation[i - 1][1] * ANGLE_TO_RAD;
-               rz = curRotation[i - 1][2] * ANGLE_TO_RAD;
-
-               cx = cos( rx );
-               sx = sin( rx );
-
-               cy = cos( ry );
-               sy = sin( ry );
-
-               cz = cos( rz );
-               sz = sin( rz );
-
-               for ( j = i - 1; j < stackSize - 1; ++j )
-               {
-                       // y-axis rotation for origin
-                       x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
-                       z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
-                       jointList[j].placement.origin[0] = x2;
-                       jointList[j].placement.origin[2] = z2;
-
-                       // y-axis rotation for direction
-                       x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
-                       z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
-                       jointList[j].placement.direction[0] = x2;
-                       jointList[j].placement.direction[2] = z2;
-
-                       // y-axis rotation for up
-                       x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
-                       z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
-                       jointList[j].placement.up[0] = x2;
-                       jointList[j].placement.up[2] = z2;
-
-                       // z-axis rotation for origin
-                       x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
-                       y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
-                       jointList[j].placement.origin[0] = x2;
-                       jointList[j].placement.origin[1] = y2;
-
-                       // z-axis rotation for direction
-                       x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
-                       y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
-                       jointList[j].placement.direction[0] = x2;
-                       jointList[j].placement.direction[1] = y2;
-
-                       // z-axis rotation for up
-                       x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
-                       y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
-                       jointList[j].placement.up[0] = x2;
-                       jointList[j].placement.up[1] = y2;
-
-                       // x-axis rotation for origin
-                       y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
-                       z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
-                       jointList[j].placement.origin[1] = y2;
-                       jointList[j].placement.origin[2] = z2;
-
-                       // x-axis rotation for direction vector
-                       y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
-                       z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
-                       jointList[j].placement.direction[1] = y2;
-                       jointList[j].placement.direction[2] = z2;
-
-                       // x-axis rotation for up vector
-                       y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
-                       z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
-                       jointList[j].placement.up[1] = y2;
-                       jointList[j].placement.up[2] = z2;
-
-                       if ( curCorrespondingJoint[j + 1] != -1 ) {
-                               // translate origin
-                               jointList[j].placement.origin[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.origin[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.origin[2] += curTranslation[i - 1][2];
-
-                               // translate back to local coord
-                               jointList[j].placement.direction[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.direction[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.direction[2] += curTranslation[i - 1][2];
-
-                               // translate back to local coord
-                               jointList[j].placement.up[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.up[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.up[2] += curTranslation[i - 1][2];
-                       }
-               }
-       }
-}
-
-void LoadGlobals( char *fileName ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCGlobals( InputFileName );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC match.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-                       printf( "\n" );
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCGlobals( fileName );
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC match.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-                       printf( "\n" );
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCClustered( fileName, clusterList, num_verts, skelType );
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-void LoadJointList( char *fileName, QDataJoint_t *jointList, int skelType ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCJointList( InputFileName, jointList, skelType );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-                       printf( "\n" );
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCJointList( fileName, jointList, skelType );
-
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/jointed.h b/tools/quake2/qdata_heretic2/jointed.h
deleted file mode 100644 (file)
index 264d317..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _JOINTED_H
-#define _JOINTED_H
-
-#include "joints.h"
-
-void LoadGlobals( char *fileName );
-void LoadClusters( char *fileName, int **clusterList, int *num_verts, int skel_type );
-void LoadJointList( char *fileName, struct QDataJoint_s *jointList, int num_verts );
-
-#define NUM_CLUSTERS 8
-
-#define NOT_JOINTED -1
-
-#endif //_JOINTED_H
diff --git a/tools/quake2/qdata_heretic2/joints.h b/tools/quake2/qdata_heretic2/joints.h
deleted file mode 100644 (file)
index f8e64bf..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef JOINTS_H
-#define JOINTS_H
-
-#include "globaldefs.h"
-
-#ifdef _HERETIC2_
-#include "angles.h"
-#endif
-
-//typedef float vec3_t[3];
-//typedef unsigned char byte;
-
-#if !GDEF_OS_WINDOWS
-#define stricmp strcasecmp
-#define strcmpi strcasecmp
-#endif
-
-typedef struct Placement_s
-{
-       vec3_t origin;
-       vec3_t direction;
-       vec3_t up;
-} Placement_t;
-
-#if 1
-typedef struct QDataJoint_s
-{
-       Placement_t placement;
-       vec3_t rotation;
-} QDataJoint_t;
-#endif
-
-typedef struct ArrayedListNode_s
-{
-       int data;
-       int next;
-       int inUse;
-} ArrayedListNode_t;
-
-#define ARRAYEDLISTNODE_NULL -1
-
-typedef struct JointAngles_s
-{
-       float angles[3];
-       int children;
-       int created;
-} JointAngles_t;
-
-typedef struct JointAngles2_s
-{
-       float angles[3];
-       int children;
-       int changed[3];
-       int inUse;
-} JointAngles2_t;
-
-#define MAX_MODELJOINTS         256
-#define MAX_MODELJOINTNODES     255
-
-extern JointAngles_t jointAngles[MAX_MODELJOINTS];
-extern JointAngles2_t jointAngles2[MAX_MODELJOINTS];
-
-extern ArrayedListNode_t jointAngleNodes[MAX_MODELJOINTNODES];
-
-// Skeletal structures enums
-enum {
-       SKEL_RAVEN = 0,
-       SKEL_BOX,
-       NUM_SKELETONS
-};
-
-// Raven Skeletal structures enums
-enum {
-       RAVEN_WAIST1 = 0,
-       RAVEN_WAIST2 = 1,
-       RAVEN_HEAD = 2,
-       NUM_JOINTS_RAVEN
-};
-
-// Box Skeletal structures enums
-enum {
-       BOX_CENTER = 0,
-       NUM_JOINTS_BOX
-};
-
-extern int numJointsForSkeleton[];
-extern char *RAVEN_SKEL_NAMES[];
-
-#define J_NEW_SKELETON      0x00001000
-#define J_YAW_CHANGED       0x00002000
-#define J_PITCH_CHANGED     0x00004000
-#define J_ROLL_CHANGED      0x00008000
-#define MAX_JOINTS          0x00000fff
-/*
-   inline int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
-   {   // yeah, I know this is a sucky, inefficient way to do this, but I didn't feel like taking the time to write a real resource manager in C
-    int i;
-
-    for(i = 0; i < max; ++i)
-    {
-        if(!nodeArray[i].inUse)
-        {
-            nodeArray[i].inUse = 1;
-            return i;
-        }
-    }
-
-    assert(0);
-    return -1;
-   }
-
-   inline void FreeNode(ArrayedListNode_t *nodeArray, int index)
-   {
-    nodeArray[index].inUse = 0;
-   }
- */
-int CreateSkeleton( int structure );
-void CreateSkeletonAtIndex( int structure, int index );
-void FreeSkeleton( int structure, int index );
-void SetJointAngle( int jointIndex, int angleIndex, float angle );
-float ModifyJointAngle( int jointIndex, int angleIndex, float deltaAngle );
-int ZeroJointAngle( int jointIndex, int angleIndex, float angVel );
-int ApplyAngVelToJoint( int jointIndex, int angleIndex, float angVel, float destAng );
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/models.c b/tools/quake2/qdata_heretic2/models.c
deleted file mode 100644 (file)
index 244f24a..0000000
+++ /dev/null
@@ -1,2041 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "qdata.h"
-#include <assert.h>
-#include "jointed.h"
-#include "fmodel.h"
-
-//=================================================================
-
-typedef struct
-{
-       int numnormals;
-       vec3_t normalsum;
-} vertexnormals_t;
-
-typedef struct
-{
-       vec3_t v;
-       int lightnormalindex;
-} trivert_t;
-
-typedef struct
-{
-       vec3_t mins, maxs;
-       char name[16];
-       trivert_t v[MAX_VERTS];
-       QDataJoint_t joints[NUM_CLUSTERS];    // ,this
-} frame_t;
-
-// ,and all of this should get out of here, need to use new stuff in fmodels instead
-
-typedef struct IntListNode_s
-{
-       int data;
-       struct IntListNode_s *next;
-} IntListNode_t;  // gaak
-
-typedef struct
-{
-       float scale[3];         // multiply byte verts by this
-       float translate[3];         // then add this
-} PartialAliasFrame_t;
-
-int jointed;
-int clustered;
-
-int *clusters[NUM_CLUSTERS];
-IntListNode_t *vertLists[NUM_CLUSTERS];
-int num_verts[NUM_CLUSTERS + 1];
-int new_num_verts[NUM_CLUSTERS + 1];
-
-// end that
-
-//================================================================
-
-frame_t g_frames[MAX_FRAMES];
-//frame_t              *g_frames;
-
-static dmdl_t model;
-
-
-float scale_up;                 // set by $scale
-vec3_t adjust;                  // set by $origin
-int g_fixedwidth, g_fixedheight;            // set by $skinsize
-
-
-//
-// base frame info
-//
-dstvert_t base_st[MAX_VERTS];
-dtriangle_t triangles[MAX_TRIANGLES];
-
-static int triangle_st[MAX_TRIANGLES][3][2];
-
-// the command list holds counts, s/t values, and xyz indexes
-// that are valid for every frame
-int commands[16384];
-int numcommands;
-int numglverts;
-int used[MAX_TRIANGLES];
-
-char g_skins[MAX_MD2SKINS][64];
-
-char cdarchive[1024];
-char cdpartial[1024];
-char cddir[1024];
-
-char modelname[64];         // empty unless $modelname issued (players)
-
-extern char        *g_outputDir;
-
-#define NUMVERTEXNORMALS    162
-
-float avertexnormals[NUMVERTEXNORMALS][3] =
-{
-       #include "anorms.h"
-};
-
-unsigned char pic[SKINPAGE_HEIGHT * SKINPAGE_WIDTH], pic_palette[768];
-
-FILE    *headerouthandle = NULL;
-
-//==============================================================
-
-/*
-   ===============
-   ClearModel
-   ===============
- */
-static void ClearModel( void ){
-       memset( &model, 0, sizeof( model ) );
-
-       modelname[0] = 0;
-       jointed = NOT_JOINTED;
-       clustered = 0;
-       scale_up = 1.0;
-       VectorCopy( vec3_origin, adjust );
-       g_fixedwidth = g_fixedheight = 0;
-       g_skipmodel = false;
-}
-
-
-void H_printf( char *fmt, ... ){
-       va_list argptr;
-       char name[1024];
-
-       if ( !headerouthandle ) {
-               sprintf( name, "%s/tris.h", cddir );
-               headerouthandle = SafeOpenWrite( name );
-               fprintf( headerouthandle, "// %s\n\n", cddir );
-               fprintf( headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n" );
-       }
-
-       va_start( argptr, fmt );
-       vfprintf( headerouthandle, fmt, argptr );
-       va_end( argptr );
-}
-
-#if 1
-/*
-   ============
-   WriteModelFile
-   ============
- */
-void WriteCommonModelFile( FILE *modelouthandle, PartialAliasFrame_t *outFrames ){
-       int i;
-       dmdl_t modeltemp;
-       int j, k;
-       frame_t         *in;
-       daliasframe_t   *out;
-       byte buffer[MAX_VERTS * 4 + 128];
-       float v;
-       int c_on, c_off;
-
-       model.version = ALIAS_VERSION;
-       model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
-       model.num_glcmds = numcommands;
-       model.ofs_skins = sizeof( dmdl_t );
-       model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
-       model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
-       model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
-       model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
-       model.ofs_end = model.ofs_glcmds + model.num_glcmds * sizeof( int );
-       //
-       // write out the model header
-       //
-       for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
-               ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
-
-       SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
-
-       //
-       // write out the skin names
-       //
-       SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
-
-       //
-       // write out the texture coordinates
-       //
-       c_on = c_off = 0;
-       for ( i = 0 ; i < model.num_st ; i++ )
-       {
-               base_st[i].s = LittleShort( base_st[i].s );
-               base_st[i].t = LittleShort( base_st[i].t );
-       }
-
-       SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
-
-       //
-       // write out the triangles
-       //
-       for ( i = 0 ; i < model.num_tris ; i++ )
-       {
-               int j;
-               dtriangle_t tri;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
-                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
-               }
-
-               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
-       }
-
-       //
-       // write out the frames
-       //
-       for ( i = 0 ; i < model.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-               out = (daliasframe_t *)buffer;
-
-               strcpy( out->name, in->name );
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
-                       out->translate[j] = in->mins[j];
-
-                       if ( outFrames ) {
-                               outFrames[i].scale[j] = out->scale[j];
-                               outFrames[i].translate[j] = out->translate[j];
-                       }
-               }
-
-               for ( j = 0 ; j < model.num_xyz ; j++ )
-               {
-                       // all of these are byte values, so no need to deal with endianness
-                       out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               // scale to byte values & min/max check
-                               v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
-
-                               // clamp, so rounding doesn't wrap from 255.6 to 0
-                               if ( v > 255.0 ) {
-                                       v = 255.0;
-                               }
-                               if ( v < 0 ) {
-                                       v = 0;
-                               }
-                               out->verts[j].v[k] = v;
-                       }
-               }
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       out->scale[j] = LittleFloat( out->scale[j] );
-                       out->translate[j] = LittleFloat( out->translate[j] );
-               }
-
-               SafeWrite( modelouthandle, out, model.framesize );
-       }
-
-       //
-       // write out glcmds
-       //
-       SafeWrite( modelouthandle, commands, numcommands * 4 );
-}
-
-/*
-   ============
-   WriteModelFile
-   ============
- */
-void WriteModelFile( FILE *modelouthandle ){
-       model.ident = IDALIASHEADER;
-
-       WriteCommonModelFile( modelouthandle, NULL );
-}
-
-/*
-   ============
-   WriteJointedModelFile
-   ============
- */
-void WriteJointedModelFile( FILE *modelouthandle ){
-       int i;
-       int j, k;
-       frame_t         *in;
-       float v;
-       IntListNode_t   *current, *toFree;
-       PartialAliasFrame_t outFrames[MAX_FRAMES];
-
-       model.ident = IDJOINTEDALIASHEADER;
-
-       WriteCommonModelFile( modelouthandle, outFrames );
-
-       // Skeletal Type
-       SafeWrite( modelouthandle, &jointed, sizeof( int ) );
-
-       // number of joints
-       SafeWrite( modelouthandle, &numJointsForSkeleton[jointed], sizeof( int ) );
-
-       // number of verts in each cluster
-       SafeWrite( modelouthandle, &new_num_verts[1], sizeof( int ) * numJointsForSkeleton[jointed] );
-
-       // cluster verts
-       for ( i = 0; i < new_num_verts[0]; ++i )
-       {
-               current = vertLists[i];
-               while ( current )
-               {
-                       SafeWrite( modelouthandle, &current->data, sizeof( int ) );
-                       toFree = current;
-                       current = current->next;
-                       free( toFree );  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-               }
-       }
-
-       for ( i = 0 ; i < model.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-
-               for ( j = 0 ; j < new_num_verts[0]; ++j )
-               {
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               // scale to byte values & min/max check
-                               v = Q_rint( ( in->joints[j].placement.origin[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                               // clamp, so rounding doesn't wrap from 255.6 to 0
-                               if ( v > 255.0 ) {
-                                       v = 255.0;
-                               }
-
-                               if ( v < 0 ) {
-                                       v = 0;
-                               }
-
-                               // write out origin as a float (there's only a few per model, so it's not really
-                               // a size issue)
-                               SafeWrite( modelouthandle, &v, sizeof( float ) );
-                       }
-
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               v = Q_rint( ( in->joints[j].placement.direction[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                               // clamp, so rounding doesn't wrap from 255.6 to 0
-                               if ( v > 255.0 ) {
-                                       v = 255.0;
-                               }
-
-                               if ( v < 0 ) {
-                                       v = 0;
-                               }
-
-                               // write out origin as a float (there's only a few per model, so it's not really
-                               // a size issue)
-                               SafeWrite( modelouthandle, &v, sizeof( float ) );
-                       }
-
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               v = Q_rint( ( in->joints[j].placement.up[k] - outFrames[i].translate[k] ) / outFrames[i].scale[k] );
-
-                               // clamp, so rounding doesn't wrap from 255.6 to 0
-                               if ( v > 255.0 ) {
-                                       v = 255.0;
-                               }
-
-                               if ( v < 0 ) {
-                                       v = 0;
-                               }
-
-                               // write out origin as a float (there's only a few per model, so it's not really
-                               // a size issue)
-                               SafeWrite( modelouthandle, &v, sizeof( float ) );
-                       }
-               }
-       }
-}
-#else
-/*
-   ============
-   WriteModelFile
-   ============
- */
-static void WriteModelFile( FILE *modelouthandle ){
-       int i;
-       dmdl_t modeltemp;
-       int j, k;
-       frame_t         *in;
-       daliasframe_t   *out;
-       byte buffer[MAX_VERTS * 4 + 128];
-       float v;
-       int c_on, c_off;
-
-       model.ident = IDALIASHEADER;
-       model.version = ALIAS_VERSION;
-       model.framesize = (int)&( (daliasframe_t *)0 )->verts[model.num_xyz];
-       model.num_glcmds = numcommands;
-       model.ofs_skins = sizeof( dmdl_t );
-       model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
-       model.ofs_tris = model.ofs_st + model.num_st * sizeof( dstvert_t );
-       model.ofs_frames = model.ofs_tris + model.num_tris * sizeof( dtriangle_t );
-       model.ofs_glcmds = model.ofs_frames + model.num_frames * model.framesize;
-       model.ofs_end = model.ofs_glcmds + model.num_glcmds * 4;
-
-       //
-       // write out the model header
-       //
-       for ( i = 0 ; i < sizeof( dmdl_t ) / 4 ; i++ )
-               ( (int *)&modeltemp )[i] = LittleLong( ( (int *)&model )[i] );
-
-       SafeWrite( modelouthandle, &modeltemp, sizeof( modeltemp ) );
-
-       //
-       // write out the skin names
-       //
-       SafeWrite( modelouthandle, g_skins, model.num_skins * MAX_SKINNAME );
-
-       //
-       // write out the texture coordinates
-       //
-       c_on = c_off = 0;
-       for ( i = 0 ; i < model.num_st ; i++ )
-       {
-               base_st[i].s = LittleShort( base_st[i].s );
-               base_st[i].t = LittleShort( base_st[i].t );
-       }
-
-       SafeWrite( modelouthandle, base_st, model.num_st * sizeof( base_st[0] ) );
-
-       //
-       // write out the triangles
-       //
-       for ( i = 0 ; i < model.num_tris ; i++ )
-       {
-               int j;
-               dtriangle_t tri;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       tri.index_xyz[j] = LittleShort( triangles[i].index_xyz[j] );
-                       tri.index_st[j] = LittleShort( triangles[i].index_st[j] );
-               }
-
-               SafeWrite( modelouthandle, &tri, sizeof( tri ) );
-       }
-
-       //
-       // write out the frames
-       //
-       for ( i = 0 ; i < model.num_frames ; i++ )
-       {
-               in = &g_frames[i];
-               out = (daliasframe_t *)buffer;
-
-               strcpy( out->name, in->name );
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       out->scale[j] = ( in->maxs[j] - in->mins[j] ) / 255;
-                       out->translate[j] = in->mins[j];
-               }
-
-               for ( j = 0 ; j < model.num_xyz ; j++ )
-               {
-                       // all of these are byte values, so no need to deal with endianness
-                       out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-                       for ( k = 0 ; k < 3 ; k++ )
-                       {
-                               // scale to byte values & min/max check
-                               v = Q_rint( ( in->v[j].v[k] - out->translate[k] ) / out->scale[k] );
-
-                               // clamp, so rounding doesn't wrap from 255.6 to 0
-                               if ( v > 255.0 ) {
-                                       v = 255.0;
-                               }
-                               if ( v < 0 ) {
-                                       v = 0;
-                               }
-                               out->verts[j].v[k] = v;
-                       }
-               }
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       out->scale[j] = LittleFloat( out->scale[j] );
-                       out->translate[j] = LittleFloat( out->translate[j] );
-               }
-
-               SafeWrite( modelouthandle, out, model.framesize );
-       }
-
-       //
-       // write out glcmds
-       //
-       SafeWrite( modelouthandle, commands, numcommands * 4 );
-}
-#endif
-
-/*
-   ===============
-   FinishModel
-   ===============
- */
-void FinishModel( void ){
-       FILE        *modelouthandle;
-       int i;
-       char name[1024];
-
-       if ( !model.num_frames ) {
-               return;
-       }
-
-//
-// copy to release directory tree if doing a release build
-//
-       if ( g_release ) {
-               if ( modelname[0] ) {
-                       sprintf( name, "%s", modelname );
-               }
-               else{
-                       sprintf( name, "%s/tris.md2", cdpartial );
-               }
-               ReleaseFile( name );
-
-               for ( i = 0 ; i < model.num_skins ; i++ )
-               {
-                       ReleaseFile( g_skins[i] );
-               }
-               model.num_frames = 0;
-               return;
-       }
-
-//
-// write the model output file
-//
-       if ( modelname[0] ) {
-               sprintf( name, "%s%s", g_outputDir, modelname );
-       }
-       else{
-               sprintf( name, "%s/tris.md2", g_outputDir );
-       }
-       printf( "saving to %s\n", name );
-       CreatePath( name );
-       modelouthandle = SafeOpenWrite( name );
-
-#if 1
-       if ( jointed != NOT_JOINTED ) {
-               WriteJointedModelFile( modelouthandle );
-       }
-       else
-#endif
-       WriteModelFile( modelouthandle );
-
-       printf( "%3dx%3d skin\n", model.skinwidth, model.skinheight );
-       printf( "First frame boundaries:\n" );
-       printf( "       minimum x: %3f\n", g_frames[0].mins[0] );
-       printf( "       maximum x: %3f\n", g_frames[0].maxs[0] );
-       printf( "       minimum y: %3f\n", g_frames[0].mins[1] );
-       printf( "       maximum y: %3f\n", g_frames[0].maxs[1] );
-       printf( "       minimum z: %3f\n", g_frames[0].mins[2] );
-       printf( "       maximum z: %3f\n", g_frames[0].maxs[2] );
-       printf( "%4d vertices\n", model.num_xyz );
-       printf( "%4d triangles\n", model.num_tris );
-       printf( "%4d frame\n", model.num_frames );
-       printf( "%4d glverts\n", numglverts );
-       printf( "%4d glcmd\n", model.num_glcmds );
-       printf( "%4d skins\n", model.num_skins );
-       printf( "file size: %d\n", (int)ftell( modelouthandle ) );
-       printf( "---------------------\n" );
-
-       fclose( modelouthandle );
-
-       // finish writing header file
-       H_printf( "\n" );
-
-       // scale_up is usefull to allow step distances to be adjusted
-       H_printf( "#define MODEL_SCALE\t\t%f\n", scale_up );
-
-       fclose( headerouthandle );
-       headerouthandle = NULL;
-}
-
-
-/*
-   =================================================================
-
-   ALIAS MODEL DISPLAY LIST GENERATION
-
-   =================================================================
- */
-
-int strip_xyz[128];
-int strip_st[128];
-int strip_tris[128];
-int stripcount;
-
-/*
-   ================
-   StripLength
-   ================
- */
-static int  StripLength( int starttri, int startv ){
-       int m1, m2;
-       int st1, st2;
-       int j;
-       dtriangle_t *last, *check;
-       int k;
-
-       used[starttri] = 2;
-
-       last = &triangles[starttri];
-
-       strip_xyz[0] = last->index_xyz[( startv ) % 3];
-       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
-       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
-       strip_st[0] = last->index_st[( startv ) % 3];
-       strip_st[1] = last->index_st[( startv + 1 ) % 3];
-       strip_st[2] = last->index_st[( startv + 2 ) % 3];
-
-       strip_tris[0] = starttri;
-       stripcount = 1;
-
-       m1 = last->index_xyz[( startv + 2 ) % 3];
-       st1 = last->index_st[( startv + 2 ) % 3];
-       m2 = last->index_xyz[( startv + 1 ) % 3];
-       st2 = last->index_st[( startv + 1 ) % 3];
-
-       // look for a matching triangle
-nexttri:
-       for ( j = starttri + 1, check = &triangles[starttri + 1]
-                 ; j < model.num_tris ; j++, check++ )
-       {
-               for ( k = 0 ; k < 3 ; k++ )
-               {
-                       if ( check->index_xyz[k] != m1 ) {
-                               continue;
-                       }
-                       if ( check->index_st[k] != st1 ) {
-                               continue;
-                       }
-                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
-                               continue;
-                       }
-                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
-                               continue;
-                       }
-
-                       // this is the next part of the fan
-
-                       // if we can't use this triangle, this tristrip is done
-                       if ( used[j] ) {
-                               goto done;
-                       }
-
-                       // the new edge
-                       if ( stripcount & 1 ) {
-                               m2 = check->index_xyz[ ( k + 2 ) % 3 ];
-                               st2 = check->index_st[ ( k + 2 ) % 3 ];
-                       }
-                       else
-                       {
-                               m1 = check->index_xyz[ ( k + 2 ) % 3 ];
-                               st1 = check->index_st[ ( k + 2 ) % 3 ];
-                       }
-
-                       strip_xyz[stripcount + 2] = check->index_xyz[ ( k + 2 ) % 3 ];
-                       strip_st[stripcount + 2] = check->index_st[ ( k + 2 ) % 3 ];
-                       strip_tris[stripcount] = j;
-                       stripcount++;
-
-                       used[j] = 2;
-                       goto nexttri;
-               }
-       }
-done:
-
-       // clear the temp used flags
-       for ( j = starttri + 1 ; j < model.num_tris ; j++ )
-               if ( used[j] == 2 ) {
-                       used[j] = 0;
-               }
-
-       return stripcount;
-}
-
-
-/*
-   ===========
-   FanLength
-   ===========
- */
-static int  FanLength( int starttri, int startv ){
-       int m1, m2;
-       int st1, st2;
-       int j;
-       dtriangle_t *last, *check;
-       int k;
-
-       used[starttri] = 2;
-
-       last = &triangles[starttri];
-
-       strip_xyz[0] = last->index_xyz[( startv ) % 3];
-       strip_xyz[1] = last->index_xyz[( startv + 1 ) % 3];
-       strip_xyz[2] = last->index_xyz[( startv + 2 ) % 3];
-       strip_st[0] = last->index_st[( startv ) % 3];
-       strip_st[1] = last->index_st[( startv + 1 ) % 3];
-       strip_st[2] = last->index_st[( startv + 2 ) % 3];
-
-       strip_tris[0] = starttri;
-       stripcount = 1;
-
-       m1 = last->index_xyz[( startv + 0 ) % 3];
-       st1 = last->index_st[( startv + 0 ) % 3];
-       m2 = last->index_xyz[( startv + 2 ) % 3];
-       st2 = last->index_st[( startv + 2 ) % 3];
-
-
-       // look for a matching triangle
-nexttri:
-       for ( j = starttri + 1, check = &triangles[starttri + 1]
-                 ; j < model.num_tris ; j++, check++ )
-       {
-               for ( k = 0 ; k < 3 ; k++ )
-               {
-                       if ( check->index_xyz[k] != m1 ) {
-                               continue;
-                       }
-                       if ( check->index_st[k] != st1 ) {
-                               continue;
-                       }
-                       if ( check->index_xyz[ ( k + 1 ) % 3 ] != m2 ) {
-                               continue;
-                       }
-                       if ( check->index_st[ ( k + 1 ) % 3 ] != st2 ) {
-                               continue;
-                       }
-
-                       // this is the next part of the fan
-
-                       // if we can't use this triangle, this tristrip is done
-                       if ( used[j] ) {
-                               goto done;
-                       }
-
-                       // the new edge
-                       m2 = check->index_xyz[ ( k + 2 ) % 3 ];
-                       st2 = check->index_st[ ( k + 2 ) % 3 ];
-
-                       strip_xyz[stripcount + 2] = m2;
-                       strip_st[stripcount + 2] = st2;
-                       strip_tris[stripcount] = j;
-                       stripcount++;
-
-                       used[j] = 2;
-                       goto nexttri;
-               }
-       }
-done:
-
-       // clear the temp used flags
-       for ( j = starttri + 1 ; j < model.num_tris ; j++ )
-               if ( used[j] == 2 ) {
-                       used[j] = 0;
-               }
-
-       return stripcount;
-}
-
-
-
-/*
-   ================
-   BuildGlCmds
-
-   Generate a list of trifans or strips
-   for the model, which holds for all frames
-   ================
- */
-static void BuildGlCmds( void ){
-       int i, j, k;
-       int startv;
-       float s, t;
-       int len, bestlen, besttype;
-       int best_xyz[1024];
-       int best_st[1024];
-       int best_tris[1024];
-       int type;
-
-       //
-       // build tristrips
-       //
-       numcommands = 0;
-       numglverts = 0;
-       memset( used, 0, sizeof( used ) );
-       for ( i = 0 ; i < model.num_tris ; i++ )
-       {
-               // pick an unused triangle and start the trifan
-               if ( used[i] ) {
-                       continue;
-               }
-
-               bestlen = 0;
-               for ( type = 0 ; type < 2 ; type++ )
-//     type = 1;
-               {
-                       for ( startv = 0 ; startv < 3 ; startv++ )
-                       {
-                               if ( type == 1 ) {
-                                       len = StripLength( i, startv );
-                               }
-                               else{
-                                       len = FanLength( i, startv );
-                               }
-                               if ( len > bestlen ) {
-                                       besttype = type;
-                                       bestlen = len;
-                                       for ( j = 0 ; j < bestlen + 2 ; j++ )
-                                       {
-                                               best_st[j] = strip_st[j];
-                                               best_xyz[j] = strip_xyz[j];
-                                       }
-                                       for ( j = 0 ; j < bestlen ; j++ )
-                                               best_tris[j] = strip_tris[j];
-                               }
-                       }
-               }
-
-               // mark the tris on the best strip/fan as used
-               for ( j = 0 ; j < bestlen ; j++ )
-                       used[best_tris[j]] = 1;
-
-               if ( besttype == 1 ) {
-                       commands[numcommands++] = ( bestlen + 2 );
-               }
-               else{
-                       commands[numcommands++] = -( bestlen + 2 );
-               }
-
-               numglverts += bestlen + 2;
-
-               for ( j = 0 ; j < bestlen + 2 ; j++ )
-               {
-                       // emit a vertex into the reorder buffer
-                       k = best_st[j];
-
-                       // emit s/t coords into the commands stream
-                       s = base_st[k].s;
-                       t = base_st[k].t;
-
-                       s = ( s + 0.5 ) / model.skinwidth;
-                       t = ( t + 0.5 ) / model.skinheight;
-
-                       *(float *)&commands[numcommands++] = s;
-                       *(float *)&commands[numcommands++] = t;
-                       *(int *)&commands[numcommands++] = best_xyz[j];
-               }
-       }
-
-       commands[numcommands++] = 0;        // end of list marker
-}
-
-
-/*
-   ===============================================================
-
-   BASE FRAME SETUP
-
-   ===============================================================
- */
-
-/*
-   ============
-   BuildST
-
-   Builds the triangle_st array for the base frame and
-   model.skinwidth / model.skinheight
-
-   FIXME: allow this to be loaded from a file for
-   arbitrary mappings
-   ============
- */
-#if 0
-static void OldBuildST( triangle_t *ptri, int numtri ){
-       int i, j;
-       int width, height, iwidth, iheight, swidth;
-       float basex, basey;
-       float s_scale, t_scale;
-       float scale;
-       vec3_t mins, maxs;
-       float       *pbasevert;
-       vec3_t vtemp1, vtemp2, normal;
-
-       //
-       // find bounds of all the verts on the base frame
-       //
-       ClearBounds( mins, maxs );
-
-       for ( i = 0 ; i < numtri ; i++ )
-               for ( j = 0 ; j < 3 ; j++ )
-                       AddPointToBounds( ptri[i].verts[j], mins, maxs );
-
-       for ( i = 0 ; i < 3 ; i++ )
-       {
-               mins[i] = floor( mins[i] );
-               maxs[i] = ceil( maxs[i] );
-       }
-
-       width = maxs[0] - mins[0];
-       height = maxs[2] - mins[2];
-
-       if ( !g_fixedwidth ) { // old style
-               scale = 8;
-               if ( width * scale >= 150 ) {
-                       scale = 150.0 / width;
-               }
-               if ( height * scale >= 190 ) {
-                       scale = 190.0 / height;
-               }
-
-               s_scale = t_scale = scale;
-
-               iwidth = ceil( width * s_scale );
-               iheight = ceil( height * t_scale );
-
-               iwidth += 4;
-               iheight += 4;
-       }
-       else
-       {   // new style
-               iwidth = g_fixedwidth / 2;
-               iheight = g_fixedheight;
-
-               s_scale = (float)( iwidth - 4 ) / width;
-               t_scale = (float)( iheight - 4 ) / height;
-       }
-
-//
-// determine which side of each triangle to map the texture to
-//
-       for ( i = 0 ; i < numtri ; i++ )
-       {
-               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-               CrossProduct( vtemp1, vtemp2, normal );
-
-               if ( normal[1] > 0 ) {
-                       basex = iwidth + 2;
-               }
-               else
-               {
-                       basex = 2;
-               }
-               basey = 2;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       pbasevert = ptri[i].verts[j];
-
-                       triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
-                       triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
-               }
-       }
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-       swidth = iwidth * 2;
-       model.skinwidth = ( swidth + 3 ) & ~3;
-       model.skinheight = iheight;
-}
-#endif
-
-//==========================================================================
-//
-// DrawScreen
-//
-//==========================================================================
-
-void DrawScreen( float s_scale, float t_scale, float iwidth, float iheight ){
-       int i;
-       byte *scrpos;
-       char buffer[256];
-
-       // Divider
-       scrpos = &pic[( INFO_Y - 2 ) * SKINPAGE_WIDTH];
-       for ( i = 0; i < SKINPAGE_WIDTH; i++ )
-       {
-               *scrpos++ = 255;
-       }
-
-       sprintf( buffer, "GENSKIN:  " );
-       DrawTextChar( 16, INFO_Y, buffer );
-
-       sprintf( buffer, "( %03d * %03d )   SCALE %f %f, SKINWIDTH %d,"
-                                        " SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth * 2, (int)iheight );
-       DrawTextChar( 80, INFO_Y, buffer );
-}
-
-/*
-   ============
-   BuildST
-
-   Builds the triangle_st array for the base frame and
-   model.skinwidth / model.skinheight
-
-   FIXME: allow this to be loaded from a file for
-   arbitrary mappings
-   ============
- */
-void BuildST( triangle_t *ptri, int numtri, qboolean DrawSkin ){
-       int i, j;
-       int width, height, iwidth, iheight, swidth;
-       float basex, basey;
-       float scale;
-       vec3_t mins, maxs;
-       float       *pbasevert;
-       vec3_t vtemp1, vtemp2, normal;
-       float s_scale, t_scale;
-       float scWidth;
-       float scHeight;
-
-       //
-       // find bounds of all the verts on the base frame
-       //
-       ClearBounds( mins, maxs );
-
-       for ( i = 0 ; i < numtri ; i++ )
-               for ( j = 0 ; j < 3 ; j++ )
-                       AddPointToBounds( ptri[i].verts[j], mins, maxs );
-
-       for ( i = 0 ; i < 3 ; i++ )
-       {
-               mins[i] = floor( mins[i] );
-               maxs[i] = ceil( maxs[i] );
-       }
-
-       width = maxs[0] - mins[0];
-       height = maxs[2] - mins[2];
-
-
-       scWidth = ( ScaleWidth / 2 ) * SCALE_ADJUST_FACTOR;
-       scHeight = ScaleHeight * SCALE_ADJUST_FACTOR;
-
-       scale = scWidth / width;
-
-       if ( height * scale >= scHeight ) {
-               scale = scHeight / height;
-       }
-
-       iwidth = ceil( width * scale ) + 4;
-       iheight = ceil( height * scale ) + 4;
-
-       s_scale = (float)( iwidth - 4 ) / width;
-       t_scale = (float)( iheight - 4 ) / height;
-       t_scale = s_scale;
-
-       if ( DrawSkin ) {
-               DrawScreen( s_scale, t_scale, iwidth, iheight );
-       }
-
-
-/*     if (!g_fixedwidth)
-    {  // old style
-        scale = 8;
-        if (width*scale >= 150)
-            scale = 150.0 / width;
-        if (height*scale >= 190)
-            scale = 190.0 / height;
-
-        s_scale = t_scale = scale;
-
-        iwidth = ceil(width*s_scale);
-        iheight = ceil(height*t_scale);
-
-        iwidth += 4;
-        iheight += 4;
-    }
-    else
-    {  // new style
-        iwidth = g_fixedwidth / 2;
-        iheight = g_fixedheight;
-
-        s_scale = (float)(iwidth-4) / width;
-        t_scale = (float)(iheight-4) / height;
-    }*/
-
-//
-// determine which side of each triangle to map the texture to
-//
-       for ( i = 0 ; i < numtri ; i++ )
-       {
-               if ( ptri[i].HasUV ) {
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               triangle_st[i][j][0] = Q_rint( ptri[i].uv[j][0] * iwidth );
-                               triangle_st[i][j][1] = Q_rint( ( 1.0f - ptri[i].uv[j][1] ) * iheight );
-                       }
-               }
-               else
-               {
-                       VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-                       VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-                       CrossProduct( vtemp1, vtemp2, normal );
-
-                       if ( normal[1] > 0 ) {
-                               basex = iwidth + 2;
-                       }
-                       else
-                       {
-                               basex = 2;
-                       }
-                       basey = 2;
-
-                       for ( j = 0 ; j < 3 ; j++ )
-                       {
-                               pbasevert = ptri[i].verts[j];
-
-                               triangle_st[i][j][0] = Q_rint( ( pbasevert[0] - mins[0] ) * s_scale + basex );
-                               triangle_st[i][j][1] = Q_rint( ( maxs[2] - pbasevert[2] ) * t_scale + basey );
-                       }
-               }
-
-               DrawLine( triangle_st[i][0][0], triangle_st[i][0][1],
-                                 triangle_st[i][1][0], triangle_st[i][1][1] );
-               DrawLine( triangle_st[i][1][0], triangle_st[i][1][1],
-                                 triangle_st[i][2][0], triangle_st[i][2][1] );
-               DrawLine( triangle_st[i][2][0], triangle_st[i][2][1],
-                                 triangle_st[i][0][0], triangle_st[i][0][1] );
-       }
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-       swidth = iwidth * 2;
-       model.skinwidth = ( swidth + 3 ) & ~3;
-       model.skinheight = iheight;
-}
-
-
-static void ReplaceClusterIndex( int newIndex, int oldindex, int **clusters,
-                                                                IntListNode_t **vertLists, int *num_verts, int *new_num_verts ){
-       int i, j;
-       IntListNode_t *next;
-
-       for ( j = 0; j < num_verts[0]; ++j )
-       {
-               for ( i = 0; i < num_verts[j + 1]; ++i )
-               {
-                       if ( clusters[j][i] == oldindex ) {
-                               ++new_num_verts[j + 1];
-
-                               next = vertLists[j];
-
-                               vertLists[j] = (IntListNode_t *) SafeMalloc( sizeof( IntListNode_t ), "ReplaceClusterIndex" );
-                               // Currently freed in WriteJointedModelFile only
-
-                               vertLists[j]->data = newIndex;
-                               vertLists[j]->next = next;
-                       }
-               }
-       }
-}
-
-/*
-   =================
-   Cmd_Base
-   =================
- */
-void Cmd_Base( void ){
-       vec3_t base_xyz[MAX_VERTS];
-       triangle_t  *ptri;
-       int i, j, k;
-#if 1
-#else
-       int time1;
-#endif
-       char file1[1024];
-       char file2[1024];
-
-       GetScriptToken( false );
-
-       if ( g_skipmodel || g_release || g_archive ) {
-               return;
-       }
-
-       printf( "---------------------\n" );
-#if 1
-       sprintf( file1, "%s/%s", cdpartial, token );
-       printf( "%s  ", file1 );
-
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s", cddir, token );
-#else
-       sprintf( file1, "%s/%s.%s", cdarchive, token, trifileext );
-       printf( "%s\n", file1 );
-
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s.%s", cddir, token, trifileext );
-
-       time1 = FileTime( file1 );
-       if ( time1 == -1 ) {
-               Error( "%s doesn't exist", file1 );
-       }
-#endif
-//
-// load the base triangles
-//
-       if ( do3ds ) {
-               Load3DSTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
-       }
-       else{
-               LoadTriangleList( file1, &ptri, &model.num_tris, NULL, NULL );
-       }
-
-
-       GetScriptToken( false );
-       sprintf( file2, "%s/%s.pcx", cddir, token );
-//     sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
-
-       printf( "skin: %s\n", file2 );
-       Load256Image( file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight );
-
-       if ( BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT ) {
-               if ( g_allow_newskin ) {
-                       ScaleWidth = BaseWidth;
-                       ScaleHeight = BaseHeight;
-               }
-               else
-               {
-                       Error( "Invalid skin page size: (%d,%d) should be (%d,%d)",
-                                  BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT );
-               }
-       }
-       else
-       {
-               ScaleWidth = (float)ExtractNumber( BasePixels, ENCODED_WIDTH_X,
-                                                                                  ENCODED_WIDTH_Y );
-               ScaleHeight = (float)ExtractNumber( BasePixels, ENCODED_HEIGHT_X,
-                                                                                       ENCODED_HEIGHT_Y );
-       }
-
-//
-// get the ST values
-//
-       BuildST( ptri, model.num_tris,false );
-
-//
-// run through all the base triangles, storing each unique vertex in the
-// base vertex list and setting the indirect triangles to point to the base
-// vertices
-//
-       for ( i = 0 ; i < model.num_tris ; i++ )
-       {
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       // get the xyz index
-                       for ( k = 0 ; k < model.num_xyz ; k++ )
-                               if ( VectorCompare( ptri[i].verts[j], base_xyz[k] ) ) {
-                                       break;
-                               }           // this vertex is already in the base vertex list
-
-                       if ( k == model.num_xyz ) { // new index
-                               VectorCopy( ptri[i].verts[j], base_xyz[model.num_xyz] );
-
-                               if ( clustered ) {
-                                       ReplaceClusterIndex( k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts );
-                               }
-
-                               model.num_xyz++;
-                       }
-
-                       triangles[i].index_xyz[j] = k;
-
-                       // get the st index
-                       for ( k = 0 ; k < model.num_st ; k++ )
-                               if ( triangle_st[i][j][0] == base_st[k].s
-                                        && triangle_st[i][j][1] == base_st[k].t ) {
-                                       break;
-                               }           // this vertex is already in the base vertex list
-
-                       if ( k == model.num_st ) { // new index
-                               base_st[model.num_st].s = triangle_st[i][j][0];
-                               base_st[model.num_st].t = triangle_st[i][j][1];
-                               model.num_st++;
-                       }
-
-                       triangles[i].index_st[j] = k;
-               }
-       }
-
-       // build triangle strips / fans
-       BuildGlCmds();
-}
-
-//===============================================================
-
-char    *FindFrameFile( char *frame ){
-       int time1;
-       char file1[1024];
-       static char retname[1024];
-       char base[32];
-       char suffix[32];
-       char            *s;
-
-       if ( strstr( frame, "." ) ) {
-               return frame;       // allready in dot format
-
-       }
-       // split 'run1' into 'run' and '1'
-       s = frame + strlen( frame ) - 1;
-
-       while ( s != frame && *s >= '0' && *s <= '9' )
-               s--;
-
-       strcpy( suffix, s + 1 );
-       strcpy( base, frame );
-       base[s - frame + 1] = 0;
-
-       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "hrc" );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s%s.%s", base, suffix, "hrc" );
-               return retname;
-       }
-
-       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "asc" );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s%s.%s", base, suffix, "asc" );
-               return retname;
-       }
-
-       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "tri" );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s%s.%s", base, suffix, "tri" );
-               return retname;
-       }
-
-       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "3ds" );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s%s.%s", base, suffix, "3ds" );
-               return retname;
-       }
-
-       sprintf( file1, "%s/%s%s.%s",cddir, base, suffix, "htr" );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s%s.%s", base, suffix, "htr" );
-               return retname;
-       }
-
-       // check for 'run.1'
-       sprintf( file1, "%s/%s.%s",cddir, base, suffix );
-       time1 = FileTime( file1 );
-       if ( time1 != -1 ) {
-               sprintf( retname, "%s.%s", base, suffix );
-               return retname;
-       }
-
-       Error( "frame %s could not be found",frame );
-       return NULL;
-}
-
-/*
-   ===============
-   GrabFrame
-   ===============
- */
-static void GrabFrame( char *frame ){
-       triangle_t      *ptri;
-       int i, j;
-       trivert_t       *ptrivert;
-       int num_tris;
-       char file1[1024];
-       frame_t         *fr;
-       vertexnormals_t vnorms[MAX_VERTS];
-       int index_xyz;
-       char            *framefile;
-
-       // the frame 'run1' will be looked for as either
-       // run.1 or run1.tri, so the new alias sequence save
-       // feature an be used
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "grabbing %s  ", file1 );
-
-       if ( model.num_frames >= MAX_FRAMES ) {
-               Error( "model.num_frames >= MAX_FRAMES" );
-       }
-       fr = &g_frames[model.num_frames];
-       model.num_frames++;
-
-       strcpy( fr->name, frame );
-
-//
-// load the frame
-//
-       if ( do3ds ) {
-               Load3DSTriangleList( file1, &ptri, &num_tris, NULL, NULL );
-       }
-       else{
-               LoadTriangleList( file1, &ptri, &num_tris, NULL, NULL );
-       }
-
-       if ( num_tris != model.num_tris ) {
-               Error( "%s: number of triangles doesn't match base frame\n", file1 );
-       }
-
-//
-// allocate storage for the frame's vertices
-//
-       ptrivert = fr->v;
-
-       for ( i = 0 ; i < model.num_xyz ; i++ )
-       {
-               vnorms[i].numnormals = 0;
-               VectorClear( vnorms[i].normalsum );
-       }
-       ClearBounds( fr->mins, fr->maxs );
-
-//
-// store the frame's vertices in the same order as the base. This assumes the
-// triangles and vertices in this frame are in exactly the same order as in the
-// base
-//
-       for ( i = 0 ; i < num_tris ; i++ )
-       {
-               vec3_t vtemp1, vtemp2, normal;
-               float ftemp;
-
-               VectorSubtract( ptri[i].verts[0], ptri[i].verts[1], vtemp1 );
-               VectorSubtract( ptri[i].verts[2], ptri[i].verts[1], vtemp2 );
-               CrossProduct( vtemp1, vtemp2, normal );
-
-               VectorNormalize( normal, normal );
-
-               // rotate the normal so the model faces down the positive x axis
-               ftemp = normal[0];
-               normal[0] = -normal[1];
-               normal[1] = ftemp;
-
-               for ( j = 0 ; j < 3 ; j++ )
-               {
-                       index_xyz = triangles[i].index_xyz[j];
-
-                       // rotate the vertices so the model faces down the positive x axis
-                       // also adjust the vertices to the desired origin
-                       ptrivert[index_xyz].v[0] = ( ( -ptri[i].verts[j][1] ) * scale_up ) +
-                                                                          adjust[0];
-                       ptrivert[index_xyz].v[1] = ( ptri[i].verts[j][0] * scale_up ) +
-                                                                          adjust[1];
-                       ptrivert[index_xyz].v[2] = ( ptri[i].verts[j][2] * scale_up ) +
-                                                                          adjust[2];
-
-                       AddPointToBounds( ptrivert[index_xyz].v, fr->mins, fr->maxs );
-
-                       VectorAdd( vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum );
-                       vnorms[index_xyz].numnormals++;
-               }
-       }
-
-//
-// calculate the vertex normals, match them to the template list, and store the
-// index of the best match
-//
-       for ( i = 0 ; i < model.num_xyz ; i++ )
-       {
-               int j;
-               vec3_t v;
-               float maxdot;
-               int maxdotindex;
-               int c;
-
-               c = vnorms[i].numnormals;
-               if ( !c ) {
-                       Error( "Vertex with no triangles attached" );
-               }
-
-               VectorScale( vnorms[i].normalsum, 1.0 / c, v );
-               VectorNormalize( v, v );
-
-               maxdot = -999999.0;
-               maxdotindex = -1;
-
-               for ( j = 0 ; j < NUMVERTEXNORMALS ; j++ )
-               {
-                       float dot;
-
-                       dot = DotProduct( v, avertexnormals[j] );
-                       if ( dot > maxdot ) {
-                               maxdot = dot;
-                               maxdotindex = j;
-                       }
-               }
-
-               ptrivert[i].lightnormalindex = maxdotindex;
-       }
-
-       free( ptri );
-}
-
-/*
-   ===============
-   GrabJointedFrame
-   ===============
- */
-void GrabJointedFrame( char *frame ){
-       char file1[1024];
-       char    *framefile;
-       frame_t     *fr;
-
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "grabbing %s\n", file1 );
-
-       fr = &g_frames[model.num_frames - 1]; // last frame read in
-
-       LoadJointList( file1, fr->joints, jointed );
-}
-
-/*
-   ===============
-   GrabGlobals
-   ===============
- */
-void GrabGlobals( char *frame ){
-       char file1[1024];
-       char    *framefile;
-       frame_t     *fr;
-
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "grabbing %s\n", file1 );
-
-       fr = &g_frames[model.num_frames - 1]; // last frame read in
-
-       LoadGlobals( file1 );
-}
-
-/*
-   ===============
-   Cmd_Frame
-   ===============
- */
-void Cmd_Frame( void ){
-       while ( ScriptTokenAvailable() )
-       {
-               GetScriptToken( false );
-               if ( g_skipmodel ) {
-                       continue;
-               }
-               if ( g_release || g_archive ) {
-                       model.num_frames = 1;   // don't skip the writeout
-                       continue;
-               }
-
-               H_printf( "#define FRAME_%-16s\t%i\n", token, model.num_frames );
-
-               GrabFrame( token );
-       }
-}
-
-/*
-   ===============
-   Cmd_Skin
-
-   Skins aren't actually stored in the file, only a reference
-   is saved out to the header file.
-   ===============
- */
-void Cmd_Skin( void ){
-       byte    *palette;
-       byte    *pixels;
-       int width, height;
-       byte    *cropped;
-       int y;
-       char name[1024], savename[1024];
-
-       GetScriptToken( false );
-
-       if ( model.num_skins == MAX_MD2SKINS ) {
-               Error( "model.num_skins == MAX_MD2SKINS" );
-       }
-
-       if ( g_skipmodel ) {
-               return;
-       }
-
-#if 1
-       sprintf( name, "%s/%s.pcx", cddir, token );
-       sprintf( savename, "%s/!%s.pcx", g_outputDir, token );
-       sprintf( g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token );
-#else
-       sprintf( name, "%s/%s.lbm", cdarchive, token );
-       strcpy( name, ExpandPathAndArchive( name ) );
-//     sprintf (name, "%s/%s.lbm", cddir, token);
-
-       if ( ScriptTokenAvailable() ) {
-               GetScriptToken( false );
-               sprintf( g_skins[model.num_skins], "%s.pcx", token );
-               sprintf( savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins] );
-       }
-       else
-       {
-               sprintf( savename, "%s/%s.pcx", g_outputDir, token );
-               sprintf( g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token );
-       }
-#endif
-
-       model.num_skins++;
-
-       if ( g_skipmodel || g_release || g_archive ) {
-               return;
-       }
-
-       // load the image
-       printf( "loading %s\n", name );
-       Load256Image( name, &pixels, &palette, &width, &height );
-//     RemapZero (pixels, palette, width, height);
-
-       // crop it to the proper size
-       cropped = (byte *) SafeMalloc( model.skinwidth * model.skinheight, "Cmd_Skin" );
-       for ( y = 0 ; y < model.skinheight ; y++ )
-       {
-               memcpy( cropped + y * model.skinwidth,
-                               pixels + y * width, model.skinwidth );
-       }
-
-       // save off the new image
-       printf( "saving %s\n", savename );
-       CreatePath( savename );
-       WritePCXfile( savename, cropped, model.skinwidth,
-                                 model.skinheight, palette );
-
-       free( pixels );
-       free( palette );
-       free( cropped );
-}
-
-
-/*
-   =================
-   Cmd_Origin
-   =================
- */
-void Cmd_Origin( void ){
-       // rotate points into frame of reference so model points down the
-       // positive x axis
-       GetScriptToken( false );
-       adjust[1] = -atof( token );
-
-       GetScriptToken( false );
-       adjust[0] = atof( token );
-
-       GetScriptToken( false );
-       adjust[2] = -atof( token );
-}
-
-
-/*
-   =================
-   Cmd_ScaleUp
-   =================
- */
-void Cmd_ScaleUp( void ){
-       GetScriptToken( false );
-       scale_up = atof( token );
-       if ( g_skipmodel || g_release || g_archive ) {
-               return;
-       }
-
-       printf( "Scale up: %f\n", scale_up );
-}
-
-
-/*
-   =================
-   Cmd_Skinsize
-
-   Set a skin size other than the default
-   =================
- */
-void Cmd_Skinsize( void ){
-       GetScriptToken( false );
-       g_fixedwidth = atoi( token );
-       GetScriptToken( false );
-       g_fixedheight = atoi( token );
-}
-
-/*
-   =================
-   Cmd_Modelname
-
-   Gives a different name/location for the file, instead of the cddir
-   =================
- */
-void Cmd_Modelname( void ){
-       GetScriptToken( false );
-       strcpy( modelname, token );
-}
-
-/*
-   ===============
-   Cmd_Cd
-   ===============
- */
-void Cmd_Cd( void ){
-       char temp[256];
-
-       FinishModel();
-       ClearModel();
-
-       GetScriptToken( false );
-
-       // this is a silly mess...
-       sprintf( cdpartial, "models/%s", token );
-       sprintf( cdarchive, "%smodels/%s", gamedir + strlen( qdir ), token );
-       sprintf( cddir, "%s%s", gamedir, cdpartial );
-
-       // Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
-       sprintf( temp, "%s%s", g_outputDir, cdpartial );
-       strcpy( g_outputDir, temp );
-
-       // if -only was specified and this cd doesn't match,
-       // skip the model (you only need to match leading chars,
-       // so you could regrab all monsters with -only monsters)
-       if ( !g_only[0] ) {
-               return;
-       }
-       if ( strncmp( token, g_only, strlen( g_only ) ) ) {
-               g_skipmodel = true;
-               printf( "skipping %s\n", cdpartial );
-       }
-}
-
-/*
-   =================
-   Cmd_Cluster
-   =================
- */
-void Cmd_Cluster(){
-       char file1[1024];
-
-       GetScriptToken( false );
-
-       printf( "---------------------\n" );
-       sprintf( file1, "%s/%s", cdpartial, token );
-       printf( "%s\n", file1 );
-
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s", cddir, token );
-
-       LoadClusters( file1, (int **)&clusters, (int *)&num_verts, jointed );
-
-       new_num_verts[0] = num_verts[0];
-
-       clustered = 1;
-}
-
-// Model construction cover functions.
-void MODELCMD_Modelname( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       Cmd_Modelname();
-/*
-    switch(modeltype)
-    {
-    case MODEL_MD2:
-        Cmd_Modelname ();
-        break;
-    case MODEL_FM:
-        Cmd_FMModelname ();
-        break;
-    }
- */
-}
-
-void MODELCMD_Cd( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Cd();
-               break;
-       case MODEL_FM:
-               Cmd_FMCd();
-               break;
-       }
-}
-
-void MODELCMD_Origin( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       Cmd_Origin();
-/*     switch(modeltype)
-    {
-    case MODEL_MD2:
-        Cmd_Origin ();
-        break;
-    case MODEL_FM:
-        Cmd_FMOrigin ();
-        break;
-    }
- */
-}
-
-void MODELCMD_Cluster( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Cluster();
-               break;
-       case MODEL_FM:
-               Cmd_FMCluster();
-               break;
-       }
-}
-
-void MODELCMD_Base( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Base();
-               break;
-       case MODEL_FM:
-               Cmd_FMBase( false );
-               break;
-       }
-}
-
-void MODELCMD_BaseST( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Base();
-               break;
-       case MODEL_FM:
-               Cmd_FMBase( true );
-               break;
-       }
-}
-
-void MODELCMD_ScaleUp( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       Cmd_ScaleUp();
-/*     switch(modeltype)
-    {
-    case MODEL_MD2:
-        Cmd_ScaleUp ();
-        break;
-    case MODEL_FM:
-        Cmd_FMScaleUp ();
-        break;
-    }
- */
-}
-
-void MODELCMD_Frame( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Frame();
-               break;
-       case MODEL_FM:
-               Cmd_FMFrame();
-               break;
-       }
-}
-
-void MODELCMD_Skin( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               Cmd_Skin();
-               break;
-       case MODEL_FM:
-               Cmd_FMSkin();
-               break;
-       }
-}
-
-void MODELCMD_Skinsize( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       Cmd_Skinsize();
-/*
-    switch(modeltype)
-    {
-    case MODEL_MD2:
-        Cmd_Skinsize ();
-        break;
-    case MODEL_FM:
-        Cmd_FMSkinsize ();
-        break;
-    }
- */
-}
-
-void MODELCMD_Skeleton( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               break;
-       case MODEL_FM:
-               Cmd_FMSkeleton();
-               break;
-       }
-}
-
-void MODELCMD_BeginGroup( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               break;
-       case MODEL_FM:
-               Cmd_FMBeginGroup();
-               break;
-       }
-}
-
-void MODELCMD_EndGroup( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               break;
-       case MODEL_FM:
-               Cmd_FMEndGroup();
-               break;
-       }
-}
-
-void MODELCMD_Referenced( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               break;
-       case MODEL_FM:
-               Cmd_FMReferenced();
-               break;
-       }
-}
-
-void MODELCMD_NodeOrder( int modeltype ){
-       if ( g_forcemodel ) {
-               modeltype = g_forcemodel;
-       }
-
-       switch ( modeltype )
-       {
-       case MODEL_MD2:
-               break;
-       case MODEL_FM:
-               Cmd_FMNodeOrder();
-               break;
-       }
-}
diff --git a/tools/quake2/qdata_heretic2/pics.c b/tools/quake2/qdata_heretic2/pics.c
deleted file mode 100644 (file)
index e9e91c2..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "qdata.h"
-
-byte            *byteimage, *lbmpalette;
-int byteimagewidth, byteimageheight;
-
-qboolean TrueColorImage;
-unsigned        *longimage;
-int longimagewidth, longimageheight;
-
-char pic_prefix[1024];
-extern char        *g_outputDir;
-
-/*
-   ===============
-   Cmd_Pic
-   ===============
- */
-
-void Cmd_Pic( void ){
-       int xl,yl,xh,yh,w,h;
-       byte            *dest, *source;
-       int flags, value, contents;
-       char lumpname[128];
-       char animname[128];
-       byte buffer[256 * 256];
-       unsigned bufferl[256 * 256];
-       char filename[1024];
-       unsigned        *destl, *sourcel;
-       int linedelta, x, y;
-       int size;
-       miptex_t        *qtex;
-       miptex32_t      *qtex32;
-       float scale_x, scale_y;
-
-       GetScriptToken( false );
-       strcpy( lumpname, token );
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       total_x += w;
-       total_y += h;
-       total_textures++;
-
-       if ( ( w & 7 ) || ( h & 7 ) ) {
-               Error( "line %i: miptex sizes must be multiples of 8", scriptline );
-       }
-
-       flags = 0;
-       contents = 0;
-       value = 0;
-
-       animname[0] = 0;
-
-       scale_x = scale_y = 0.5;
-
-       if ( TrueColorImage ) {
-               sprintf( filename, "%spics/%s/%s.m32", g_outputDir, pic_prefix, lumpname );
-               if ( g_release ) {
-                       return; // textures are only released by $maps
-
-               }
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= longimagewidth || xh > longimagewidth ||
-                        yl >= longimageheight || yh > longimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
-               }
-
-               sourcel = longimage + ( yl * longimagewidth ) + xl;
-               destl = bufferl;
-               linedelta = ( longimagewidth - w );
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *destl++ = *sourcel++;  // RGBA
-                       }
-                       sourcel += linedelta;
-               }
-
-               qtex32 = CreateMip32( bufferl, w, h, &size, false );
-
-               qtex32->flags |= LittleLong( flags );
-               qtex32->contents = contents;
-               qtex32->value = value;
-               qtex32->scale_x = scale_x;
-               qtex32->scale_y = scale_y;
-               sprintf( qtex32->name, "%s/%s", pic_prefix, lumpname );
-               if ( animname[0] ) {
-                       sprintf( qtex32->animname, "%s/%s", pic_prefix, animname );
-               }
-
-               //
-               // write it out
-               //
-               printf( "writing %s\n", filename );
-               SaveFile( filename, (byte *)qtex32, size );
-
-               free( qtex32 );
-       }
-       else
-       {
-               sprintf( filename, "%spics/%s/%s.m8", g_outputDir, pic_prefix, lumpname );
-               if ( g_release ) {
-                       return; // textures are only released by $maps
-
-               }
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= byteimagewidth || xh > byteimagewidth ||
-                        yl >= byteimageheight || yh > byteimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
-               }
-
-               source = byteimage + yl * byteimagewidth + xl;
-               dest = buffer;
-               linedelta = byteimagewidth - w;
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *dest++ = *source++;
-                       }
-                       source += linedelta;
-               }
-
-               qtex = CreateMip( buffer, w, h, lbmpalette, &size, false );
-
-               qtex->flags = flags;
-               qtex->contents = contents;
-               qtex->value = value;
-               sprintf( qtex->name, "%s/%s", pic_prefix, lumpname );
-               if ( animname[0] ) {
-                       sprintf( qtex->animname, "%s/%s", pic_prefix, animname );
-               }
-
-               //
-               // write it out
-               //
-               printf( "writing %s\n", filename );
-               SaveFile( filename, (byte *)qtex, size );
-
-               free( qtex );
-       }
-}
-
-
-/*
-   ===============
-   Cmd_picdir
-   ===============
- */
-void Cmd_Picdir( void ){
-       char filename[1024];
-
-       GetScriptToken( false );
-       strcpy( pic_prefix, token );
-       // create the directory if needed
-       sprintf( filename, "%sPics", g_outputDir );
-       Q_mkdir( filename );
-       sprintf( filename, "%sPics/%s", g_outputDir, pic_prefix );
-       Q_mkdir( filename );
-}
diff --git a/tools/quake2/qdata_heretic2/qcommon/angles.h b/tools/quake2/qdata_heretic2/qcommon/angles.h
deleted file mode 100644 (file)
index b0baf31..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// Angles in radians
-
-#define ANGLE_0         0.0F
-#define ANGLE_1         0.017453292F
-#define ANGLE_5         0.087266462F
-#define ANGLE_10        0.174532925F
-#define ANGLE_15        0.261799387F
-#define ANGLE_20        0.392699081F
-#define ANGLE_30        0.523598775F
-#define ANGLE_45        0.785398163F
-#define ANGLE_60        1.047197551F
-#define ANGLE_72        1.256637061F
-#define ANGLE_90        1.570796327F
-#define ANGLE_120       2.094395102F
-#define ANGLE_135       2.35619449F
-#define ANGLE_144       2.513274123F
-#define ANGLE_180       3.141592653F
-#define ANGLE_225       3.926990817F
-#define ANGLE_270       4.71238898F
-#define ANGLE_315       5.497787144F
-#define ANGLE_360       6.283185307F
-
-// Angles in degrees
-
-#define DEGREE_0        0.0F
-#define DEGREE_180      180.0F
-#define DEGREE_45       ( DEGREE_180 / 4.0F )
-#define DEGREE_90       ( DEGREE_180 / 2.0F )
-#define DEGREE_135      ( DEGREE_90 + DEGREE_45 )
-#define DEGREE_270      ( DEGREE_180 + DEGREE_90 )
-#define DEGREE_360      ( DEGREE_180 * 2.0F )
-
-#define DEGREE_225      ( DEGREE_180 + DEGREE_45 )
-#define DEGREE_315      ( DEGREE_270 + DEGREE_45 )
-
-#define DEGREE_30       ( DEGREE_180 / 6.0F )
-#define DEGREE_60       ( DEGREE_180 / 3.0F )
-#define DEGREE_120      ( DEGREE_360 / 3.0F )
-
-#define DEGREE_1        ( DEGREE_180 / 180.0F )
-#define DEGREE_5        ( DEGREE_180 / 36.0F )
-#define DEGREE_10       ( DEGREE_180 / 18.0F )
-#define DEGREE_15       ( DEGREE_180 / 12.0F )
-#define DEGREE_20       ( DEGREE_180 / 8.0F )
-
-// Conversion routines
-
-#define ANGLE_TO_RAD    ANGLE_1
-#define RAD_TO_ANGLE    ( 180.0F / ANGLE_180 )
-
-#define SHORT_TO_ANGLE  ( 360.0 / 65536 )
-
-#if GDEF_COMPILER_MSVC
-#pragma warning(disable : 4305)     // 'initializing' : truncation from 'const double ' to 'float '
-#endif
diff --git a/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h b/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h
deleted file mode 100644 (file)
index e54ad22..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef _ARRAYEDLIST_H
-#define _ARRAYEDLIST_H
-
-#include <assert.h>
-
-typedef struct ArrayedListNode_s
-{
-       int data;
-       int next;
-       int inUse;
-} ArrayedListNode_t;
-
-#define ARRAYEDLISTNODE_NULL -1
-
-static GDEF_ATTRIBUTE_INLINE int GetFreeNode( ArrayedListNode_t *nodeArray, int max ){
-       int i;
-
-       for ( i = 0; i < max; ++i )
-       {
-               if ( !nodeArray[i].inUse ) {
-                       nodeArray[i].inUse = 1;
-                       return i;
-               }
-       }
-
-       assert( 0 );
-       return -1;
-}
-
-static GDEF_ATTRIBUTE_INLINE void FreeNode( ArrayedListNode_t *nodeArray, int index ){
-       nodeArray[index].inUse = 0;
-}
-
-#endif //_ARRAYEDLIST_H
diff --git a/tools/quake2/qdata_heretic2/qcommon/flex.h b/tools/quake2/qdata_heretic2/qcommon/flex.h
deleted file mode 100644 (file)
index 98184e8..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// Generic flexible format
-
-typedef struct
-{
-       char ident[32];
-       int version;
-       int size;
-} header_t;
-
-void WriteHeader( FILE *, char *, int, int, void * );
-
-// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/fmodel.h b/tools/quake2/qdata_heretic2/qcommon/fmodel.h
deleted file mode 100644 (file)
index e2ebfa8..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-/*
-   ========================================================================
-
-   .FM triangle flexible model file format
-
-   ========================================================================
- */
-
-#ifndef __FMODEL_HEADER
-#define __FMODEL_HEADER
-
-#include "bspfile.h"
-
-//typedef unsigned char         byte;
-//typedef int  qboolean;
-//typedef float vec3_t[3];
-
-#define MAX_FM_TRIANGLES    2048
-#define MAX_FM_VERTS        2048
-#define MAX_FM_FRAMES       2048
-#define MAX_FM_SKINS        64
-#define MAX_FM_SKINNAME     64
-#define MAX_FM_MESH_NODES   16      // also defined in game/qshared.h
-
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-#define SKINPAGE_WIDTH 640
-#define SKINPAGE_HEIGHT 480
-
-#define ENCODED_WIDTH_X 92
-#define ENCODED_WIDTH_Y 475
-#define ENCODED_HEIGHT_X 128
-#define ENCODED_HEIGHT_Y 475
-
-#define SCALE_ADJUST_FACTOR 0.96
-
-#define INFO_HEIGHT 5
-#define INFO_Y ( SKINPAGE_HEIGHT - INFO_HEIGHT )
-
-extern byte     *BasePalette;
-extern byte     *BasePixels,*TransPixels;
-extern int BaseWidth, BaseHeight, TransWidth, TransHeight;
-extern int ScaleWidth, ScaleHeight;
-
-int ExtractNumber( byte *pic, int x, int y );
-void DrawTextChar( int x, int y, char *text );
-void DrawLine( int x1, int y1, int x2, int y2 );
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-// Initial Header
-#define FM_HEADER_NAME  "header"
-#define FM_HEADER_VER   2
-
-typedef struct
-{
-       int skinwidth;
-       int skinheight;
-       int framesize;              // byte size of each frame
-
-       int num_skins;
-       int num_xyz;
-       int num_st;                 // greater than num_xyz for seams
-       int num_tris;
-       int num_glcmds;             // dwords in strip/fan command list
-       int num_frames;
-       int num_mesh_nodes;
-} fmheader_t;
-
-
-// Skin Header
-#define FM_SKIN_NAME    "skin"
-#define FM_SKIN_VER     1
-
-
-// ST Coord Header
-#define FM_ST_NAME      "st coord"
-#define FM_ST_VER       1
-
-typedef struct
-{
-       short s;
-       short t;
-} fmstvert_t;
-
-
-// Tri Header
-#define FM_TRI_NAME     "tris"
-#define FM_TRI_VER      1
-
-typedef struct
-{
-       short index_xyz[3];
-       short index_st[3];
-} fmtriangle_t;
-
-
-// Frame Header
-#define FM_FRAME_NAME   "frames"
-#define FM_FRAME_VER    1
-
-// Frame for compression, just the names
-#define FM_SHORT_FRAME_NAME "short frames"
-#define FM_SHORT_FRAME_VER  1
-
-// Normals for compressed frames
-#define FM_NORMAL_NAME  "normals"
-#define FM_NORMAL_VER   1
-
-// Compressed Frame Data
-#define FM_COMP_NAME    "comp data"
-#define FM_COMP_VER 1
-
-// GL Cmds Header
-#define FM_GLCMDS_NAME  "glcmds"
-#define FM_GLCMDS_VER   1
-
-
-// Mesh Nodes Header
-#define FM_MESH_NAME    "mesh nodes"
-#define FM_MESH_VER     3
-
-// Skeleton Header
-#define FM_SKELETON_NAME "skeleton"
-#define FM_SKELETON_VER 1
-
-// References Header
-#define FM_REFERENCES_NAME "references"
-#define FM_REFERENCES_VER   1
-
-typedef struct
-{
-
-       union
-       {
-
-               byte tris[MAX_FM_TRIANGLES >> 3];
-
-               struct {
-                       short   *triIndicies;
-                       int num_tris;
-               };
-
-       };
-
-       byte verts[MAX_FM_VERTS >> 3];
-       short start_glcmds, num_glcmds;
-} fmmeshnode_t;
-
-//=================================================================
-
-// Frame info
-typedef struct
-{
-       byte v[3];              // scaled byte to fit in frame mins/maxs
-       byte lightnormalindex;
-} fmtrivertx_t;
-
-typedef struct
-{
-       float scale[3];                 // multiply byte verts by this
-       float translate[3];             // then add this
-       char name[16];                  // frame name from grabbing
-       fmtrivertx_t verts[1];          // variable sized
-} fmaliasframe_t;
-
-
-#endif // #define __FMODEL_HEADER
diff --git a/tools/quake2/qdata_heretic2/qcommon/h2common.h b/tools/quake2/qdata_heretic2/qcommon/h2common.h
deleted file mode 100644 (file)
index e1f2559..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef H2COMMON_H
-#define H2COMMON_H
-  #define H2COMMON_API
-#endif
diff --git a/tools/quake2/qdata_heretic2/qcommon/placement.h b/tools/quake2/qdata_heretic2/qcommon/placement.h
deleted file mode 100644 (file)
index 9151183..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef PLACEMENT_H
-#define PLACEMENT_H
-
-#include "q_typedef.h"
-
-//typedef float vec3_t[3];
-
-typedef struct Placement_s
-{
-       vec3_t origin;
-       vec3_t direction;
-       vec3_t up;
-} Placement_t;
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/qcommon/q_typedef.h b/tools/quake2/qdata_heretic2/qcommon/q_typedef.h
deleted file mode 100644 (file)
index cbe69dd..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef Q_TYPEDEF_H
-#define Q_TYPEDEF_H
-
-typedef float vec_t;
-typedef vec_t vec2_t[2];
-typedef vec_t vec3_t[3];
-typedef double vec3d_t[3];
-typedef vec_t vec5_t[5];
-
-typedef float matrix3_t[3][3];
-typedef float matrix3d_t[3][3];
-
-typedef int fixed4_t;
-typedef int fixed8_t;
-typedef int fixed16_t;
-
-typedef unsigned char byte;
-
-#ifndef __cplusplus
-typedef enum {false, true}  qboolean;
-#else
-typedef int qboolean;
-#endif
-
-typedef struct edict_s edict_t;
-
-typedef struct paletteRGBA_s
-{
-       union
-       {
-               struct
-               {
-                       byte r,g,b,a;
-               };
-               unsigned c;
-               byte c_array[4];
-       };
-} paletteRGBA_t;
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/qcommon/qfiles.h b/tools/quake2/qdata_heretic2/qcommon/qfiles.h
deleted file mode 100644 (file)
index 4d0648c..0000000
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-   ========================================================================
-
-   The .pak files are just a linear collapse of a directory tree
-
-   ========================================================================
- */
-
-#define IDPAKHEADER     ( ( 'K' << 24 ) + ( 'C' << 16 ) + ( 'A' << 8 ) + 'P' )
-
-typedef struct
-{
-       char name[56];
-       int filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-       int ident;          // == IDPAKHEADER
-       int dirofs;
-       int dirlen;
-} dpackheader_t;
-
-#define MAX_FILES_IN_PACK   6144
-
-
-/*
-   ========================================================================
-
-   PCX files are used for as many images as possible
-
-   ========================================================================
- */
-
-typedef struct
-{
-       char manufacturer;
-       char version;
-       char encoding;
-       char bits_per_pixel;
-       unsigned short xmin,ymin,xmax,ymax;
-       unsigned short hres,vres;
-       unsigned char palette[48];
-       char reserved;
-       char color_planes;
-       unsigned short bytes_per_line;
-       unsigned short palette_type;
-       char filler[58];
-       unsigned char data;             // unbounded
-} pcx_t;
-
-/*
-   ========================================================================
-
-   .MD2 compressed triangle model file format
-
-   ========================================================================
- */
-#define IDCOMPRESSEDALIASHEADER ( ( '2' << 24 ) + ( 'C' << 16 ) + ( 'D' << 8 ) + 'I' )
-
-/*
-   ========================================================================
-
-   .MD2 compressed triangle model file format
-
-   ========================================================================
- */
-#define IDJOINTEDALIASHEADER    ( ( '2' << 24 ) + ( 'J' << 16 ) + ( 'D' << 8 ) + 'I' )
-
-/*
-   ========================================================================
-
-   .MD2 triangle model file format
-
-   ========================================================================
- */
-
-#define IDALIASHEADER       ( ( '2' << 24 ) + ( 'P' << 16 ) + ( 'D' << 8 ) + 'I' )
-#define ALIAS_VERSION   8
-
-#define MAX_TRIANGLES   4096
-#define MAX_VERTS       2048
-#define MAX_FRAMES      512
-#define MAX_MD2SKINS    64
-#define MAX_SKINNAME    64
-
-typedef struct
-{
-       short s;
-       short t;
-} dstvert_t;
-
-typedef struct
-{
-       short index_xyz[3];
-       short index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-       union
-       {
-               struct
-               {
-                       byte v[3];          // scaled byte to fit in frame mins/maxs
-                       byte lightnormalindex;
-               };
-
-               int vert;
-       };
-} dtrivertx_t;
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-typedef struct
-{
-       float scale[3];         // multiply byte verts by this
-       float translate[3];         // then add this
-       char name[16];          // frame name from grabbing
-       dtrivertx_t verts[1];   // variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-       int ident;
-       int version;
-
-       int skinwidth;
-       int skinheight;
-       int framesize;              // byte size of each frame
-
-       int num_skins;
-       int num_xyz;
-       int num_st;                 // greater than num_xyz for seams
-       int num_tris;
-       int num_glcmds;             // dwords in strip/fan command list
-       int num_frames;
-
-       int ofs_skins;              // each skin is a MAX_SKINNAME string
-       int ofs_st;                 // byte offset from start for stverts
-       int ofs_tris;               // offset for dtriangles
-       int ofs_frames;             // offset for first frame
-       int ofs_glcmds;
-       int ofs_end;                // end of file
-
-} dmdl_t;
-
-// compressed model
-typedef struct dcompmdl_s
-{
-       dmdl_t header;
-       short CompressedFrameSize;
-       short UniqueVerts;
-       short *remap;
-       float *translate;   // then add this
-       float *scale;   // multiply byte verts by this
-       char *mat;
-       char *frames;
-       char *base;
-       float *ctranslate;
-       float *cscale;
-       char data[1];
-} dcompmdl_t;
-
-typedef struct
-{
-       dcompmdl_t compModInfo;
-       int rootCluster;
-       int skeletalType;
-       struct ModelSkeleton_s *skeletons;
-} JointedModel_t;
-
-/*
-   ========================================================================
-
-   .BK file format
-
-   ========================================================================
- */
-
-#define IDBOOKHEADER    ( ( 'K' << 24 ) + ( 'O' << 16 ) + ( 'O' << 8 ) + 'B' )
-#define BOOK_VERSION    2
-
-typedef struct bookframe_s
-{
-       int x;
-       int y;
-       int w;
-       int h;
-       char name[MAX_SKINNAME];            // name of gfx file
-} bookframe_t;
-
-typedef struct bookheader_s
-{
-       unsigned int ident;
-       unsigned int version;
-       int num_segments;
-       int total_w;
-       int total_h;
-} bookheader_t;
-
-typedef struct book_s
-{
-       bookheader_t bheader;
-       bookframe_t bframes[MAX_MD2SKINS];
-} book_t;
-
-/*
-   ========================================================================
-
-   .SP2 sprite file format
-
-   ========================================================================
- */
-
-#define IDSPRITEHEADER  ( ( '2' << 24 ) + ( 'S' << 16 ) + ( 'D' << 8 ) + 'I' )
-// little-endian "IDS2"
-#define SPRITE_VERSION  2
-
-typedef struct
-{
-       int width, height;
-       int origin_x, origin_y;         // raster coordinates inside pic
-       char name[MAX_SKINNAME];        // name of pcx file
-} dsprframe_t;
-
-typedef struct {
-       int ident;
-       int version;
-       int numframes;
-       dsprframe_t frames[1];          // variable sized
-} dsprite_t;
-
-/*
-   ==============================================================================
-
-   .M8 texture file format
-
-   ==============================================================================
- */
-
-typedef struct palette_s
-{
-       union
-       {
-               struct
-               {
-                       byte r,g,b;
-               };
-       };
-} palette_t;
-
-#define MIP_VERSION     2
-#define PAL_SIZE        256
-#define MIPLEVELS       16
-
-typedef struct miptex_s
-{
-       int version;
-       char name[32];
-       unsigned width[MIPLEVELS], height[MIPLEVELS];
-       unsigned offsets[MIPLEVELS];        // four mip maps stored
-       char animname[32];                  // next frame in animation chain
-       palette_t palette[PAL_SIZE];
-       int flags;
-       int contents;
-       int value;
-} miptex_t;
-
-
-
-#define MIP32_VERSION   4
-
-typedef struct miptex32_s
-{
-       int version;
-       char name[128];
-       char altname[128];                  // texture substitution
-       char animname[128];                 // next frame in animation chain
-       char damagename[128];               // image that should be shown when damaged
-       unsigned width[MIPLEVELS], height[MIPLEVELS];
-       unsigned offsets[MIPLEVELS];
-       int flags;
-       int contents;
-       int value;
-       float scale_x, scale_y;
-       int mip_scale;
-
-       // detail texturing info
-       char dt_name[128];              // detailed texture name
-       float dt_scale_x, dt_scale_y;
-       float dt_u, dt_v;
-       float dt_alpha;
-       int dt_src_blend_mode, dt_dst_blend_mode;
-
-       int unused[20];                     // future expansion to maintain compatibility with h2
-} miptex32_t;
-
-
-/*
-   ==============================================================================
-
-   .BSP file format
-
-   ==============================================================================
- */
-
-#define IDBSPHEADER ( ( 'P' << 24 ) + ( 'S' << 16 ) + ( 'B' << 8 ) + 'I' )
-// little-endian "IBSP"
-
-#define BSPVERSION  38
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define MAX_MAP_MODELS      1024
-//#define      MAX_MAP_BRUSHES         8192    // Quake 2 original
-#define MAX_MAP_BRUSHES     10240
-#define MAX_MAP_ENTITIES    2048
-#define MAX_MAP_ENTSTRING   0x40000
-#define MAX_MAP_TEXINFO     8192
-
-#define MAX_MAP_AREAS       256
-#define MAX_MAP_AREAPORTALS 1024
-#define MAX_MAP_PLANES      65536
-#define MAX_MAP_NODES       65536
-#define MAX_MAP_BRUSHSIDES  65536
-#define MAX_MAP_LEAFS       65536
-#define MAX_MAP_VERTS       65536
-#define MAX_MAP_FACES       65536
-#define MAX_MAP_LEAFFACES   65536
-#define MAX_MAP_LEAFBRUSHES 65536
-#define MAX_MAP_PORTALS     65536
-#define MAX_MAP_EDGES       128000
-#define MAX_MAP_SURFEDGES   256000
-#define MAX_MAP_LIGHTING    0x200000
-#define MAX_MAP_VISIBILITY  0x180000
-
-// key / value pair sizes
-
-#define MAX_KEY     32
-#define MAX_VALUE   1024
-
-//=============================================================================
-
-typedef struct
-{
-       int fileofs, filelen;
-} lump_t;
-
-#define LUMP_ENTITIES       0
-#define LUMP_PLANES         1
-#define LUMP_VERTEXES       2
-#define LUMP_VISIBILITY     3
-#define LUMP_NODES          4
-#define LUMP_TEXINFO        5
-#define LUMP_FACES          6
-#define LUMP_LIGHTING       7
-#define LUMP_LEAFS          8
-#define LUMP_LEAFFACES      9
-#define LUMP_LEAFBRUSHES    10
-#define LUMP_EDGES          11
-#define LUMP_SURFEDGES      12
-#define LUMP_MODELS         13
-#define LUMP_BRUSHES        14
-#define LUMP_BRUSHSIDES     15
-#define LUMP_POP            16
-#define LUMP_AREAS          17
-#define LUMP_AREAPORTALS    18
-#define HEADER_LUMPS        19
-
-typedef struct
-{
-       int ident;
-       int version;
-       lump_t lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-       float mins[3], maxs[3];
-       float origin[3];            // for sounds or lights
-       int headnode;
-       int firstface, numfaces;            // submodels just draw faces
-                                           // without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-       float point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define PLANE_X         0
-#define PLANE_Y         1
-#define PLANE_Z         2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define PLANE_ANYX      3
-#define PLANE_ANYY      4
-#define PLANE_ANYZ      5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
-       float normal[3];
-       float dist;
-       int type;           // PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// These definitions also need to be in q_shared.h!
-
-// ************************************************************************************************
-// CONTENTS_XXX
-// ------------
-// Contents flags.
-// ************************************************************************************************
-
-// Lower bits are stronger, and will eat weaker brushes completely.
-
-#define CONTENTS_SOLID          0x00000001  // An eye is never valid in a solid.
-#define CONTENTS_WINDOW         0x00000002  // Translucent, but not watery.
-#define CONTENTS_AUX            0x00000004
-#define CONTENTS_LAVA           0x00000008
-#define CONTENTS_SLIME          0x00000010
-#define CONTENTS_WATER          0x00000020
-#define CONTENTS_MIST           0x00000040
-#define LAST_VISIBLE_CONTENTS   CONTENTS_MIST
-
-// Remaining contents are non-visible, and don't eat brushes.
-
-#define CONTENTS_AREAPORTAL     0x00008000
-#define CONTENTS_PLAYERCLIP     0x00010000
-#define CONTENTS_MONSTERCLIP    0x00020000
-
-// Currents can be added to any other contents, and may be mixed.
-
-#define CONTENTS_CURRENT_0      0x00040000
-#define CONTENTS_CURRENT_90     0x00080000
-#define CONTENTS_CURRENT_180    0x00100000
-#define CONTENTS_CURRENT_270    0x00200000
-#define CONTENTS_CURRENT_UP     0x00400000
-#define CONTENTS_CURRENT_DOWN   0x00800000
-#define CONTENTS_ORIGIN         0x01000000  // Removed before bsping an entity.
-#define CONTENTS_MONSTER        0x02000000  // Should never be on a brush, only in game.
-#define CONTENTS_DEADMONSTER    0x04000000
-#define CONTENTS_DETAIL         0x08000000  // Brushes to be added after vis leaves.
-#define CONTENTS_TRANSLUCENT    0x10000000  // Auto set if any surface has transparency.
-#define CONTENTS_LADDER         0x20000000
-#define CONTENTS_CAMERANOBLOCK  0x40000000  // Camera LOS ignores any brushes with this flag.
-
-typedef struct
-{
-       int planenum;
-       int children[2];            // negative numbers are -(leafs+1), not nodes
-       short mins[3];              // for frustom culling
-       short maxs[3];
-       unsigned short firstface;
-       unsigned short numfaces;    // counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-       float vecs[2][4];           // [s/t][xyz offset]
-       int flags;                  // miptex flags + overrides
-       int value;                  // light emission, etc
-       char texture[32];           // texture name (textures/*.wal)
-       int nexttexinfo;            // for animations, -1 = end of chain
-} texinfo_t;
-
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-       unsigned short v[2];        // vertex numbers
-} dedge_t;
-
-#define MAXLIGHTMAPS    4
-typedef struct
-{
-       unsigned short planenum;
-       short side;
-
-       int firstedge;              // we must support > 64k edges
-       short numedges;
-       short texinfo;
-
-// lighting info
-       byte styles[MAXLIGHTMAPS];
-       int lightofs;               // start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-       int contents;                       // OR of all brushes (not needed?)
-
-       short cluster;
-       short area;
-
-       short mins[3];                      // for frustum culling
-       short maxs[3];
-
-       unsigned short firstleafface;
-       unsigned short numleaffaces;
-
-       unsigned short firstleafbrush;
-       unsigned short numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-       unsigned short planenum;        // facing out of the leaf
-       short texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-       int firstside;
-       int numsides;
-       int contents;
-} dbrush_t;
-
-#define ANGLE_UP    -1
-#define ANGLE_DOWN  -2
-
-
-// the visibility lump consists of a header with a count, then
-// byte offsets for the PVS and PHS of each cluster, then the raw
-// compressed bit vectors
-#define DVIS_PVS    0
-#define DVIS_PHS    1
-typedef struct
-{
-       int numclusters;
-       int bitofs[8][2];           // bitofs[numclusters][2]
-} dvis_t;
-
-// each area has a list of portals that lead into other areas
-// when portals are closed, other areas may not be visible or
-// hearable even if the vis info says that it should be
-typedef struct
-{
-       int portalnum;
-       int otherarea;
-} dareaportal_t;
-
-typedef struct
-{
-       int numareaportals;
-       int firstareaportal;
-} darea_t;
diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.c b/tools/quake2/qdata_heretic2/qcommon/reference.c
deleted file mode 100644 (file)
index 7be9740..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <string.h>
-#include "reference.h"
-#include "arrayedlist.h"
-#include "resourcemanager.h"
-#include "skeletons.h"
-
-char *referenceRootNames[] =
-{
-       "elf_Lhandroot", //0
-       "elf_Rhandroot",
-       "elf_Rfootroot",
-       "elf_Lfootroot",
-       "elf_Bstaffroot",
-       "elf_bladeroot",
-       "elf_hellroot",
-       "StaffBone", //7
-       "SwordBone",
-       "SpearBone",
-       "RFootBone",
-       "LFootBone",
-       "hp_backroot", //12
-       "hp_staffroot",
-       "hp_lhandroot",
-       "hp_rhandroot",
-       "hp_rfootroot",
-       "hp_lfootroot",
-       "staffroot", //18
-       "rfootroot",
-       "lfootroot",
-       "rhandroot",
-       "lhandroot",
-       "leyeroot",
-       "reyeroot"
-};
-
-int referenceRootNameOffsets[NUM_REFERENCED] =
-{
-       0,  // CORVUS
-       7,  // INSECT
-       12, // HIGH PRIESTESS
-       18, // MORCALAVIN
-};
-
-int numReferences[NUM_REFERENCED] =
-{
-       NUM_REFERENCES_CORVUS,
-       NUM_REFERENCES_INSECT,
-       NUM_REFERENCES_PRIESTESS,
-       NUM_REFERENCES_MORK,
-};
-
-int corvusJointIDs[NUM_REFERENCES_CORVUS] =
-{
-       CORVUS_UPPERBACK,
-       CORVUS_UPPERBACK,
-       -1,
-       -1,
-       CORVUS_UPPERBACK,
-       CORVUS_UPPERBACK,
-       CORVUS_UPPERBACK,
-};
-
-int *jointIDs[NUM_REFERENCED] =
-{
-       corvusJointIDs,
-};
-
-static ResourceManager_t ReferenceMngr;
-
-void InitReferenceMngr(){
-#define REFERENCE_BLOCK_SIZE 8
-       char *dummystr = NULL;
-
-       ResMngr_Con( &ReferenceMngr, sizeof( LERPedReferences_t ), REFERENCE_BLOCK_SIZE, dummystr );
-}
-
-void ReleaseReferenceMngr(){
-       ResMngr_Des( &ReferenceMngr );
-}
-
-LERPedReferences_t *LERPedReferences_new( int init_refType ){
-       LERPedReferences_t  *newRefs;
-
-       newRefs = ResMngr_AllocateResource( &ReferenceMngr, sizeof( *newRefs ) );
-       newRefs->refType = init_refType;
-       newRefs->jointIDs = jointIDs[init_refType];
-       newRefs->lastUpdate = -( REF_MINCULLTIME * 2.0 );
-
-       memset( newRefs->references, 0, MAX_REFPOINTS * sizeof( Reference_t ) );
-       memset( newRefs->oldReferences, 0, MAX_REFPOINTS * sizeof( Reference_t ) );
-
-       return newRefs;
-}
-
-void LERPedReferences_delete( LERPedReferences_t *toDelete ){
-       ResMngr_DeallocateResource( &ReferenceMngr, toDelete, sizeof( *toDelete ) );
-}
-
-// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.h b/tools/quake2/qdata_heretic2/qcommon/reference.h
deleted file mode 100644 (file)
index 747c4d4..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef REFERENCE_H
-#define REFERENCE_H
-
-#include "placement.h"
-
-#define MAX_REFPOINTS       16
-#define REF_MINCULLTIME     1.0
-
-typedef struct Reference_s
-{
-       int activecount;
-       Placement_t placement;
-} Reference_t;
-
-typedef struct LERPedReferences_s
-{
-       int refType;
-       int         *jointIDs;
-       float lastUpdate;
-       Reference_t references[MAX_REFPOINTS];
-       Reference_t oldReferences[MAX_REFPOINTS];
-} LERPedReferences_t;
-
-// Reference Types
-enum {
-       REF_NULL = -1,
-       REF_CORVUS, //0
-       REF_INSECT, //1
-       REF_PRIESTESS, //2
-       REF_MORK, //3
-       NUM_REFERENCED //4
-};
-
-// Corvus Reference Points
-enum {
-       CORVUS_LEFTHAND, //0
-       CORVUS_RIGHTHAND,
-       CORVUS_LEFTFOOT,
-       CORVUS_RIGHTFOOT,
-       CORVUS_STAFF,
-       CORVUS_BLADE,
-       CORVUS_HELL_HEAD,
-       NUM_REFERENCES_CORVUS //7
-};
-
-// Tchekrik Reference Points
-enum {
-       INSECT_STAFF, //0
-       INSECT_SWORD,
-       INSECT_SPEAR,
-       INSECT_RIGHTFOOT,
-       INSECT_LEFTFOOT,
-       NUM_REFERENCES_INSECT //5
-};
-
-// High Priestess Reference Points
-enum {
-       PRIESTESS_BACK, //0
-       PRIESTESS_STAFF,
-       PRIESTESS_LHAND,
-       PRIESTESS_RHAND,
-       PRIESTESS_RFOOT,
-       PRIESTESS_LFOOT,
-       NUM_REFERENCES_PRIESTESS //6
-};
-
-// Morcalavin Reference Points
-enum
-{
-       MORK_STAFFREF, //0
-       MORK_RFOOTREF, //1
-       MORK_LFOOTREF, //2
-       MORK_RHANDREF, //3
-       MORK_LHANDREF, //4
-       MORK_LEYEREF, //5
-       MORK_REYEREF, //6
-       NUM_REFERENCES_MORK //7
-};
-
-#define CORVUS_LIMBS_MASK   ( ( 1 << CORVUS_LEFTHAND ) | ( 1 << CORVUS_RIGHTHAND ) | ( 1 << CORVUS_LEFTFOOT ) | ( 1 << CORVUS_RIGHTFOOT ) )
-#define CORVUS_WEAPON_MASK  ( ( 1 << CORVUS_STAFF ) | ( 1 << CORVUS_BLADE ) | ( 1 << CORVUS_HELL_HEAD ) )
-#define CORVUS_MASK         ( CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK )
-
-#define INSECT_MASK         ( ( 1 << INSECT_STAFF ) | ( 1 << INSECT_SWORD ) | ( 1 << INSECT_SPEAR ) | ( 1 << INSECT_RIGHTFOOT ) | ( 1 << INSECT_LEFTFOOT ) )
-
-#define PRIESTESS_MASK      ( ( 1 << PRIESTESS_BACK ) | ( 1 << PRIESTESS_STAFF ) | ( 1 << PRIESTESS_LHAND ) | ( 1 << PRIESTESS_RHAND ) | ( 1 << PRIESTESS_RFOOT ) | ( 1 << PRIESTESS_LFOOT ) )
-
-#define MORK_MASK           ( ( 1 << MORK_STAFFREF ) | ( 1 << MORK_RFOOTREF ) | ( 1 << MORK_LFOOTREF ) | ( 1 << MORK_RHANDREF ) | ( 1 << MORK_LHANDREF ) | ( 1 << MORK_LEYEREF ) | ( 1 << MORK_REYEREF ) )
-
-extern char *referenceRootNames[];
-extern int referenceRootNameOffsets[];
-extern int numReferences[];
-
-void EnableRefPoints( LERPedReferences_t *refInfo, int mask );
-void DisableRefPoints( LERPedReferences_t *refInfo, int mask );
-
-void InitReferenceMngr();
-void ReleaseReferenceMngr();
-
-LERPedReferences_t *LERPedReferences_new( int init_refType );
-void LERPedReferences_delete( LERPedReferences_t *toDelete );
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c
deleted file mode 100644 (file)
index 2eb0140..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-//
-// ResourceManager.c
-//
-
-#include <stdio.h>
-#include "resourcemanager.h"
-#include <assert.h>
-
-typedef struct ResMngr_Block_s
-{
-       char *start;
-       unsigned int size;
-       struct ResMngr_Block_s *next;
-} ResMngr_Block_t;
-
-static void ResMngr_CreateBlock( ResourceManager_t *resource ){
-       unsigned int _blockSize;
-       char *block;
-       char **current;
-       ResMngr_Block_t *temp;
-       unsigned int i;
-
-       _blockSize = resource->nodeSize * resource->resPerBlock;
-
-       block = malloc( _blockSize );
-
-       assert( block );
-
-       temp = malloc( sizeof( *temp ) );
-
-       temp->start = block;
-       temp->size = _blockSize;
-       temp->next = resource->blockList;
-
-       resource->blockList = temp;
-
-       resource->free = (char **)( block );
-
-       current = resource->free;
-
-       for ( i = 1; i < resource->resPerBlock; ++i )
-       {
-               // set current->next to point to next node
-               *current = (char *)( current ) + resource->nodeSize;
-
-               // set current node to current->next
-               current = (char **)( *current );
-       }
-
-       *current = NULL;
-}
-
-H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name ){
-       resource->resSize = init_resSize;
-
-       resource->resPerBlock = init_resPerBlock;
-
-       resource->nodeSize = resource->resSize + sizeof( *resource->free );
-
-       resource->blockList = NULL;
-
-       resource->numResourcesAllocated = 0;
-
-       ResMngr_CreateBlock( resource );
-}
-
-H2COMMON_API void ResMngr_Des( ResourceManager_t *resource ){
-       ResMngr_Block_t *toDelete;
-
-#if 0
-       if ( resource->numResourcesAllocated ) {
-               char mess[100];
-               sprintf( mess,"Potential memory leak %d bytes unfreed\n",resource->resSize * resource->numResourcesAllocated );
-               OutputDebugString( mess );
-       }
-#endif
-
-       while ( resource->blockList )
-       {
-               toDelete = resource->blockList;
-               resource->blockList = resource->blockList->next;
-               free( toDelete->start );
-               free( toDelete );
-       }
-}
-
-H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size ){
-       char **toPop;
-
-       assert( size == resource->resSize );
-
-       ++resource->numResourcesAllocated;
-
-       assert( resource->free ); // constructor not called; possibly due to a static object
-       // containing a static ResourceManagerFastLarge member being
-       // constructed before its own static members
-
-       toPop = resource->free;
-
-       // set unallocated to the next node and check for NULL (end of list)
-       if ( !( resource->free = (char **)( *resource->free ) ) ) { // if at end create new block
-               ResMngr_CreateBlock( resource );
-       }
-
-       // set next to NULL
-       *toPop = NULL;
-
-       // return the resource for the node
-       return (void *)( toPop + 1 );
-}
-
-H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size ){
-       char **toPush;
-
-       assert( size == resource->resSize );
-
-       --resource->numResourcesAllocated;
-
-       toPush = (char **)( toDeallocate ) - 1;
-
-       assert( resource->free ); // see same assert at top of AllocateResource
-
-       // set toPop->next to current unallocated front
-       *toPush = (char *)( resource->free );
-
-       // set unallocated to the node removed from allocated
-       resource->free = toPush;
-}
-
-// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h
deleted file mode 100644 (file)
index be82d78..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// ResourceManager.h
-//
-
-#include "h2common.h"
-#include <stdlib.h>     // needed here for size_t
-
-typedef struct ResourceManager_s
-{
-       size_t resSize;
-       unsigned int resPerBlock;
-       unsigned int nodeSize;
-       struct ResMngr_Block_s *blockList;
-       char **free;
-       char *ResMan_Name;
-
-       unsigned numResourcesAllocated;
-
-} ResourceManager_t;
-
-extern H2COMMON_API void ResMngr_Con( ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name );
-extern H2COMMON_API void ResMngr_Des( ResourceManager_t *resource );
-extern H2COMMON_API void *ResMngr_AllocateResource( ResourceManager_t *resource, size_t size );
-extern H2COMMON_API void ResMngr_DeallocateResource( ResourceManager_t *resource, void *toDeallocate, size_t size );
diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.c b/tools/quake2/qdata_heretic2/qcommon/skeletons.c
deleted file mode 100644 (file)
index 453cb77..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-//
-// Skeletons.c
-//
-
-#include "skeletons.h"
-
-char *skeletonRootNames[] =
-{
-       "RAVEN_ROOT",
-       "BOX_ROOT",
-       "BEETLE_ROOT",
-       "ELFLORD_ROOT",
-       "PLAGUELF_ROOT",
-       "ELF_BACKROOT",
-};
-
-int skeletonRNameOffsets[] =
-{
-       0,  // RAVEN
-       1,  // BOX
-       2,  // BEETLE
-       3,  // ELFLORD
-       4,  // PLAGUE ELF
-       5,  // CORVUS
-};
-
-char *skeletonJointNames[] =
-{
-       "RAVEN_LOWERBACK",  // 0
-       "RAVEN_UPPERBACK",
-       "RAVEN_NECK",
-       "BOX_CENTER",       // 3
-       "BEETLE_NECK",      // 4
-       "BEETLE_HEAD",
-       "PLAGUELF_BACKB",   // 6
-       "PLAGUELF_BACKC",
-       "PLAGUELF_NECK",
-       "ELF_BACKB",        // 9
-       "ELF_BACKC",
-       "ELF_NECKB",
-};
-
-int skeletonNameOffsets[] =
-{
-       0,  // RAVEN
-       3,  // BOX
-       4,  // BEETLE
-       -1, // ELFLORD
-       6,  // PLAGUE ELF
-       9,  // CORVUS
-};
-
-char *skeletonEffectorNames[] =
-{
-       "BEETLE_EYES",      // 0
-       "CORVUS_EYES",      // 1
-};
-
-int skeletonENameOffsets[] =
-{
-       -1, // RAVEN
-       -1, // BOX
-       0,  // BEETLE
-       -1, // ELFLORD
-       1,  // PLAGUE ELF
-};
-
-int numJointsInSkeleton[] =
-{
-       NUM_JOINTS_RAVEN,
-       NUM_JOINTS_BOX,
-       NUM_JOINTS_BEETLE,
-       NUM_JOINTS_ELFLORD,
-       NUM_JOINTS_PLAGUE_ELF,
-       NUM_JOINTS_CORVUS,
-};
-
-int numNodesInSkeleton[] =
-{
-       2,  // RAVEN
-       0,  // BOX
-       1,  // BEETLE
-       -1, // ELFLORD
-       2,  // PLAGUE ELF
-       2,  // CORVUS
-};
-
-void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root );
-void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root );
-void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
-void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
-void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex );
-
-CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] =
-{
-       CreateRavenSkel,
-       CreateBoxSkel,
-       CreateBeetleSkel,
-       CreateElfLordSkel,
-       CreatePlagueElfSkel,
-       CreatePlagueElfSkel,    // Corvus has the same structure as the Plague Elf
-};
-
-void CreateRavenSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
-       char *root;
-       int *children;
-       int nodeIndex;
-
-       root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-       children = (int *)( root + RAVEN_HEAD * jointSize );
-       *children = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + RAVEN_UPPERBACK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + RAVEN_LOWERBACK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateBoxSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
-       char *root;
-       int *children;
-
-       root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-       children = (int *)( root + RAVEN_HEAD * jointSize );
-       *children = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateBeetleSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
-       char *root;
-       int *children;
-       int nodeIndex;
-
-       root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-       children = (int *)( root + BEETLE_HEAD * jointSize );
-       *children = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + BEETLE_NECK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateElfLordSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
-       char *root;
-       int *children;
-       int nodeIndex;
-
-       root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-       children = (int *)( root + BEETLE_HEAD * jointSize );
-       *children = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + BEETLE_NECK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreatePlagueElfSkel( void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex ){
-       char *root;
-       int *children;
-       int nodeIndex;
-
-       root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-       children = (int *)( root + PLAGUE_ELF_HEAD * jointSize );
-       *children = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + PLAGUE_ELF_UPPERBACK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-
-       nodeIndex = GetFreeNode( g_jointNodes, MAX_ARRAYED_JOINT_NODES );
-
-       children = (int *)( root + PLAGUE_ELF_LOWERBACK * jointSize );
-       *children = nodeIndex;
-
-       g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK;
-       g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.h b/tools/quake2/qdata_heretic2/qcommon/skeletons.h
deleted file mode 100644 (file)
index 9d7fe96..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <stdlib.h> // for size_t
-#include "arrayedlist.h"
-
-#define JN_YAW_CHANGED      0x00000001
-#define JN_PITCH_CHANGED    0x00000002
-#define JN_ROLL_CHANGED     0x00000004
-
-// Skeleton types
-enum {
-       SKEL_NULL = -1,
-       SKEL_RAVEN = 0,
-       SKEL_BOX,
-       SKEL_BEETLE,
-       SKEL_ELFLORD,
-       SKEL_PLAGUE_ELF,
-       SKEL_CORVUS,
-       NUM_SKELETONS
-};
-
-// Raven Skeletal joints
-enum {
-       RAVEN_LOWERBACK = 0,
-       RAVEN_UPPERBACK,
-       RAVEN_HEAD,
-       NUM_JOINTS_RAVEN
-};
-
-// Box Skeletal joints
-enum {
-       BOX_CENTER = 0,
-       NUM_JOINTS_BOX
-};
-
-// Beetle Skeletal joints
-enum {
-       BEETLE_NECK = 0,
-       BEETLE_HEAD,
-       NUM_JOINTS_BEETLE
-};
-
-// Elflord Skeletal joints
-enum {
-       ELFLORD_,
-       ELFLORD__,
-       NUM_JOINTS_ELFLORD
-};
-
-// Plague Elf Skeletal joints
-enum {
-       PLAGUE_ELF_LOWERBACK,
-       PLAGUE_ELF_UPPERBACK,
-       PLAGUE_ELF_HEAD,
-       NUM_JOINTS_PLAGUE_ELF
-};
-
-// Corvus Skeletal joints
-enum {
-       CORVUS_LOWERBACK,
-       CORVUS_UPPERBACK,
-       CORVUS_HEAD,
-       NUM_JOINTS_CORVUS
-};
-
-#define NO_SWAP_FRAME -1
-#define NULL_ROOT_JOINT -1
-
-#define MAX_ARRAYED_SKELETAL_JOINTS 255 // has max of 65,535 (if this remains at 255, net code can be changed to reflect)
-#define MAX_ARRAYED_JOINT_NODES ( MAX_ARRAYED_SKELETAL_JOINTS - 1 )
-
-#define MAX_JOINTS_PER_SKELETON 8   // arbitrary small number
-#define MAX_JOINT_NODES_PER_SKELETON ( MAX_JOINTS_PER_SKELETON - 1 )
-
-extern char *skeletonRootNames[];
-extern int skeletonRNameOffsets[];
-extern char *skeletonJointNames[];
-extern int skeletonNameOffsets[];
-extern int numJointsInSkeleton[];
-extern char *skeletonEffectorNames[];
-extern int skeletonENameOffsets[];
-extern int numNodesInSkeleton[];
-
-typedef void ( *CreateSkeleton_t )( void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex );
-
-extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS];
diff --git a/tools/quake2/qdata_heretic2/qd_fmodel.h b/tools/quake2/qdata_heretic2/qd_fmodel.h
deleted file mode 100644 (file)
index 286fb07..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef FMODEL_H
-#define FMODEL_H
-#include "fmodel.h"
-#endif
-#include "qd_skeletons.h"
-
-typedef struct
-{
-       int numnormals;
-       vec3_t normalsum;
-} fmvertexnormals_t;
-
-typedef struct
-{
-       vec3_t v;
-       int lightnormalindex;
-       fmvertexnormals_t vnorm;
-} fmtrivert_t;
-
-#define FRAME_NAME_LEN ( 16 )
-
-typedef struct
-{
-       vec3_t mins, maxs;
-       char name[FRAME_NAME_LEN];
-       fmtrivert_t v[MAX_FM_VERTS];
-       struct QD_SkeletalJoint_s joints[NUM_CLUSTERS];
-       struct QD_SkeletalJoint_s references[NUM_REFERENCES];
-} fmframe_t;
-
-extern fmframe_t g_frames[MAX_FM_FRAMES];
-
-extern fmheader_t fmheader;
-extern char cdarchive[1024];                        // set by $fmcd
-extern char cdpartial[1024];                        // set by $fmcd
-extern char cddir[1024];                            // set by $fmcd
-
-void GrabFrame( char *frame );
-void H_printf( char *fmt, ... );
-char *FindFrameFile( char *frame );
diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.c b/tools/quake2/qdata_heretic2/qd_skeletons.c
deleted file mode 100644 (file)
index 97e2a1f..0000000
+++ /dev/null
@@ -1,1231 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qd_skeletons.h"
-#include "skeletons.h"
-#include "qd_fmodel.h"
-#include "angles.h"
-#include "token.h"
-#include "qdata.h"
-#include "reference.h"
-
-#include <assert.h>
-#include <math.h>
-#include <memory.h>
-
-
-// We're assuming no more than 16 reference points, with no more than 32 characters in the name
-char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
-int RefPointNum = 0;
-
-Skeletalfmheader_t g_skelModel;
-
-void ClearSkeletalModel(){
-       g_skelModel.type = SKEL_NULL;
-       g_skelModel.clustered = false;
-       g_skelModel.references = REF_NULL;
-}
-
-//==========================================================================
-//
-// LoadHRCClustered
-//
-//==========================================================================
-
-// Places the null terminated src string into the dest string less any trailing digits or underscores
-void StripTrailingDigits( char *src, char *dest ){
-#ifndef NDEBUG
-       int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
-#endif
-       int i = 0;
-
-       while ( src[i] != '\0' )
-       {
-               ++i;
-#ifndef NDEBUG
-               assert( i < max );
-#endif
-       }
-
-       while ( ( src[--i] >= '0' && src[i] <= '9' ) || src[i] == '_' )
-       {
-
-       }
-
-       memcpy( dest, src, ++i );
-
-       dest[i] = '\0';
-}
-
-static void LoadHRCClustered( char *fileName, int **clusterList, int *num_verts, int skelType ){
-       extern void HandleHRCModel( triangle_t **triList, int *triangleCount,
-                                                               mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth );
-
-       extern mesh_node_t  *pmnodes;
-
-       triangle_t *triList;
-//      mesh_node_t *nodesList;
-       int num_mesh_nodes = 0, triangleCount = 0;
-
-#if 0
-       int i;
-       int j, numVerts;
-       char stripped[SKELETAL_NAME_MAX];
-
-       for ( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i )
-       {
-               num_verts[i] = 0;
-       }
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       TK_Beyond( TK_CLUSTERS );
-
-       while ( TK_Search( TK_CLUSTER_NAME ) != TK_EOF )
-       {
-               TK_Require( TK_STRING );
-
-               StripTrailingDigits( tk_String, stripped );
-
-               for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
-               {
-                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
-                               i = -i + numJointsInSkeleton[skelType] - 1;
-
-                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
-
-                               numVerts = tk_IntNumber;
-
-                               if ( !num_verts[i + 1] ) { // first set of verts for cluster
-                                       clusterList[i] = SafeMalloc( numVerts * sizeof( int ), "LoadHRCClustered" );
-                                       assert( clusterList[i] );
-                               }
-                               else                // any later sets of verts need to copy current
-                               {
-                                       int *temp;
-
-                                       temp = SafeMalloc( ( num_verts[i + 1] + numVerts ) * sizeof( int ), "LoadHRCClustered" );
-                                       assert( temp );
-
-                                       memcpy( temp + numVerts, clusterList[i], num_verts[i + 1] * sizeof( int ) );
-
-                                       free( clusterList[i] );
-
-                                       clusterList[i] = temp;
-                               }
-
-                               // currently this function is only called by LoadModelClusters.
-                               // Apparently the matching free has disappeared,
-                               // should probably be free at the end of FMCmd_Base
-
-                               TK_Beyond( TK_LBRACE );
-
-                               for ( j = 0; j < numVerts; ++j )
-                               {
-                                       TK_Require( TK_INTNUMBER );
-                                       clusterList[i][j] = tk_IntNumber;
-                                       TK_Fetch();
-                               }
-
-                               num_verts[i + 1] += numVerts;
-
-                               break;
-                       }
-               }
-       }
-
-       num_verts[0] = numJointsInSkeleton[skelType];
-#endif
-
-#if 1   // get the index number localized to the root
-//     for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
-//     {
-//             g_skelModel.num_verts[i] = 0;
-//     }
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       // prime it
-       TK_Beyond( TK_MODEL );
-
-       triList = (triangle_t *) SafeMalloc( MAXTRIANGLES * sizeof( triangle_t ), "Triangle list" );
-       memset( triList,0,MAXTRIANGLES * sizeof( triangle_t ) );
-//     nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-       pmnodes = (mesh_node_t *) SafeMalloc( MAX_FM_MESH_NODES * sizeof( mesh_node_t ), "Mesh Node List" );
-
-       memset( pmnodes, 0, MAX_FM_MESH_NODES * sizeof( mesh_node_t ) );
-
-       // this should eventually use a stripped down version of this
-       HandleHRCModel( &triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0 );
-
-//     free(nodesList);
-       free( triList );
-
-       num_verts[0] = numJointsInSkeleton[skelType];
-#endif
-}
-
-void ReadHRCClusterList( mesh_node_t *meshNode, int baseIndex ){
-       int i, j, numVerts;
-       tokenType_t nextToken;
-       char stripped[SKELETAL_NAME_MAX];
-
-       meshNode->clustered = true;
-
-       nextToken = TK_Get( TK_CLUSTER_NAME );
-
-       while ( nextToken == TK_CLUSTER_NAME )
-       {
-               TK_FetchRequire( TK_STRING );
-
-               StripTrailingDigits( tk_String, stripped );
-
-               for ( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i )
-               {
-                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type] + i] ) == 0 ) {
-                               i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
-
-                               TK_BeyondRequire( TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER );
-
-                               numVerts = tk_IntNumber;
-
-                               if ( !baseIndex ) {
-                                       meshNode->clusters[i] = (int *) SafeMalloc( numVerts * sizeof( int ), "ReadHRCClusterList" );
-                                       assert( meshNode->clusters[i] );
-                               }
-                               else
-                               {
-                                       int *temp;
-
-                                       temp = meshNode->clusters[i];
-                                       meshNode->clusters[i] = (int *) SafeMalloc( ( meshNode->num_verts[i + 1] + numVerts ) * sizeof( int ), "ReadHRCClusterList" );
-                                       assert( meshNode->clusters[i] );
-
-                                       memcpy( meshNode->clusters[i], temp, meshNode->num_verts[i + 1] * sizeof( int ) );
-                                       free( temp );
-                               }
-
-                               // currently this function is only called by LoadModelClusters.
-                               // Apparently the matching free has disappeared,
-                               // should probably be free at the end of FMCmd_Base
-
-                               TK_Beyond( TK_LBRACE );
-
-                               for ( j = 0; j < numVerts; ++j )
-                               {
-                                       TK_Require( TK_INTNUMBER );
-                                       meshNode->clusters[i][baseIndex + j] = tk_IntNumber + baseIndex;
-                                       TK_Fetch();
-                               }
-
-                               if ( baseIndex ) {
-                                       meshNode->num_verts[i + 1] += numVerts;
-                               }
-                               else
-                               {
-                                       meshNode->num_verts[i + 1] = numVerts;
-                               }
-
-                               break;
-                       }
-               }
-
-               TK_BeyondRequire( TK_CLUSTER_STATE, TK_INTNUMBER );
-               nextToken = TK_Fetch();
-       }
-}
-
-static void LoadHRCGlobals( char *fileName ){
-       int i;
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-       TK_Beyond( TK_MODEL );
-
-       TK_Beyond( TK_SCALING );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_skelModel.scaling[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-
-       TK_Beyond( TK_ROTATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_skelModel.rotation[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-
-       TK_Beyond( TK_TRANSLATION );
-       for ( i = 0; i < 3; i++ )
-       {
-               TK_Require( TK_FLOATNUMBER );
-               g_skelModel.translation[i] = tk_FloatNumber;
-               TK_Fetch();
-       }
-}
-
-static void ParseVec3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseVec3d( vec3d_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3d( vec3d_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3( vec3_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3d( vec3d_t in ){
-       TK_Require( TK_FLOATNUMBER );
-       in[1] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[2] = tk_FloatNumber;
-       TK_FetchRequire( TK_FLOATNUMBER );
-       in[0] = tk_FloatNumber;
-}
-
-static void LoadHRCJointList( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
-#define MAX_STACK 64
-       int i, j;
-       vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
-       int curCorrespondingJoint[MAX_STACK];
-       int currentStack = 0, stackSize;
-       double cx, sx, cy, sy, cz, sz;
-       double rx, ry, rz;
-       double x2, y2, z2;
-       char stripped[SKELETAL_NAME_MAX];
-       Placement_d_t *placement;
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       TK_Beyond( TK_MODEL );
-
-       while ( TK_Search( TK_NAME ) != TK_EOF )
-       {
-               TK_Require( TK_STRING );
-
-               StripTrailingDigits( tk_String, stripped );
-
-               if ( stricmp( stripped, skeletonRootNames[skeletonRNameOffsets[skelType]] ) == 0 ) {
-                       break;
-               }
-       }
-
-       if ( tk_Token == TK_EOF ) {
-               Error( "Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]] );
-               return;
-       }
-
-       TK_Beyond( TK_SCALING );
-
-       ParseVec3d( curScale[currentStack] );
-
-       TK_Beyond( TK_ROTATION );
-
-       ParseRotation3d( curRotation[currentStack] );
-
-       TK_Beyond( TK_TRANSLATION );
-
-       ParseVec3d( curTranslation[currentStack] );
-
-       // account for global model translation
-       curTranslation[currentStack][1] += g_skelModel.translation[0];
-       curTranslation[currentStack][2] += g_skelModel.translation[1];
-       curTranslation[currentStack][0] += g_skelModel.translation[2];
-
-       curCorrespondingJoint[currentStack] = -1;
-
-       ++currentStack;
-
-       for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
-       {
-               while ( 1 )
-               {
-                       TK_Beyond( TK_MODEL );
-
-                       TK_BeyondRequire( TK_NAME, TK_STRING );
-
-                       StripTrailingDigits( tk_String, stripped );
-
-                       if ( stricmp( stripped, skeletonJointNames[skeletonNameOffsets[skelType] + i] ) == 0 ) {
-                               break;
-                       }
-
-                       TK_Beyond( TK_SCALING );
-
-                       ParseVec3d( curScale[currentStack] );
-
-                       TK_Beyond( TK_ROTATION );
-
-                       ParseRotation3d( curRotation[currentStack] );
-
-                       TK_Beyond( TK_TRANSLATION );
-
-                       ParseVec3d( curTranslation[currentStack] );
-
-                       curCorrespondingJoint[currentStack] = -1;
-
-                       ++currentStack;
-               }
-
-               TK_Beyond( TK_SCALING );
-
-               ParseVec3d( curScale[currentStack] );
-
-               TK_Beyond( TK_ROTATION );
-
-               ParseRotation3d( curRotation[currentStack] );
-
-               jointList[i].rotation[1] = curRotation[currentStack][1];
-               jointList[i].rotation[2] = curRotation[currentStack][2];
-               jointList[i].rotation[0] = curRotation[currentStack][0];
-
-               TK_Beyond( TK_TRANSLATION );
-
-               ParseVec3d( curTranslation[currentStack] );
-
-//             jointList[i].placement.origin[1] = curTranslation[currentStack][1];
-//             jointList[i].placement.origin[2] = curTranslation[currentStack][2];
-//             jointList[i].placement.origin[0] = curTranslation[currentStack][0];
-
-               jointList[i].placement.origin[1] = 0.0;
-               jointList[i].placement.origin[2] = 0.0;
-               jointList[i].placement.origin[0] = 0.0;
-
-               jointList[i].placement.direction[1] = 20.0;
-               jointList[i].placement.direction[2] = 0.0;
-               jointList[i].placement.direction[0] = 0.0;
-
-               jointList[i].placement.up[1] = 0.0;
-               jointList[i].placement.up[2] = 20.0;
-               jointList[i].placement.up[0] = 0.0;
-
-               curCorrespondingJoint[currentStack] = i;
-
-               ++currentStack;
-       }
-
-       stackSize = currentStack;
-
-#if 0
-       // rotate the direction and up vectors to correspond to the rotation
-       for ( i = 0; i < numJointsInSkeleton[skelType]; ++i )
-       {
-               rx = jointList[i].rotation[0] * ANGLE_TO_RAD;
-               ry = jointList[i].rotation[1] * ANGLE_TO_RAD;
-               rz = jointList[i].rotation[2] * ANGLE_TO_RAD;
-
-               cx = cos( rx );
-               sx = sin( rx );
-
-               cy = cos( ry );
-               sy = sin( ry );
-
-               cz = cos( rz );
-               sz = sin( rz );
-
-               // y-axis rotation for direction
-               x2 = jointList[i].placement.direction[0] * cy + jointList[i].placement.direction[2] * sy;
-               z2 = -jointList[i].placement.direction[0] * sy + jointList[i].placement.direction[2] * cy;
-               jointList[i].placement.direction[0] = x2;
-               jointList[i].placement.direction[2] = z2;
-
-               // y-axis rotation for up
-               x2 = jointList[i].placement.up[0] * cy + jointList[i].placement.up[2] * sy;
-               z2 = -jointList[i].placement.up[0] * sy + jointList[i].placement.up[2] * cy;
-               jointList[i].placement.up[0] = x2;
-               jointList[i].placement.up[2] = z2;
-
-               // z-axis rotation for direction
-               x2 = jointList[i].placement.direction[0] * cz - jointList[i].placement.direction[1] * sz;
-               y2 = jointList[i].placement.direction[0] * sz + jointList[i].placement.direction[1] * cz;
-               jointList[i].placement.direction[0] = x2;
-               jointList[i].placement.direction[1] = y2;
-
-               // z-axis rotation for up
-               x2 = jointList[i].placement.up[0] * cz - jointList[i].placement.up[1] * sz;
-               y2 = jointList[i].placement.up[0] * sz + jointList[i].placement.up[1] * cz;
-               jointList[i].placement.up[0] = x2;
-               jointList[i].placement.up[1] = y2;
-
-               // x-axis rotation for direction vector
-               y2 = jointList[i].placement.direction[1] * cx - jointList[i].placement.direction[2] * sx;
-               z2 = jointList[i].placement.direction[1] * sx + jointList[i].placement.direction[2] * cx;
-               jointList[i].placement.direction[1] = y2;
-               jointList[i].placement.direction[2] = z2;
-
-               // x-axis rotation for up vector
-               y2 = jointList[i].placement.up[1] * cx - jointList[i].placement.up[2] * sx;
-               z2 = jointList[i].placement.up[1] * sx + jointList[i].placement.up[2] * cx;
-               jointList[i].placement.up[1] = y2;
-               jointList[i].placement.up[2] = z2;
-
-               // translate direction to a point in the model
-               jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
-               jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
-               jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
-
-               // translate up to a point in the model
-               jointList[i].placement.up[0] += jointList[i].placement.origin[0];
-               jointList[i].placement.up[1] += jointList[i].placement.origin[1];
-               jointList[i].placement.up[2] += jointList[i].placement.origin[2];
-       }
-#endif
-
-       for ( i = stackSize - 1; i >= 0; --i )
-       {
-               rx = curRotation[i][0] * ANGLE_TO_RAD;
-               ry = curRotation[i][1] * ANGLE_TO_RAD;
-               rz = curRotation[i][2] * ANGLE_TO_RAD;
-
-               cx = cos( rx );
-               sx = sin( rx );
-
-               cy = cos( ry );
-               sy = sin( ry );
-
-               cz = cos( rz );
-               sz = sin( rz );
-
-#if 1
-               for ( j = i; j < stackSize; ++j )
-               {
-                       if ( curCorrespondingJoint[j] != -1 ) {
-                               placement = &jointList[curCorrespondingJoint[j]].placement;
-
-                               // y-axis rotation for origin
-                               x2 = placement->origin[0] * cy + placement->origin[2] * sy;
-                               z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
-                               placement->origin[0] = x2;
-                               placement->origin[2] = z2;
-
-                               // y-axis rotation for direction
-                               x2 = placement->direction[0] * cy + placement->direction[2] * sy;
-                               z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
-                               placement->direction[0] = x2;
-                               placement->direction[2] = z2;
-
-                               // y-axis rotation for up
-                               x2 = placement->up[0] * cy + placement->up[2] * sy;
-                               z2 = -placement->up[0] * sy + placement->up[2] * cy;
-                               placement->up[0] = x2;
-                               placement->up[2] = z2;
-
-                               // z-axis rotation for origin
-                               x2 = placement->origin[0] * cz - placement->origin[1] * sz;
-                               y2 = placement->origin[0] * sz + placement->origin[1] * cz;
-                               placement->origin[0] = x2;
-                               placement->origin[1] = y2;
-
-                               // z-axis rotation for direction
-                               x2 = placement->direction[0] * cz - placement->direction[1] * sz;
-                               y2 = placement->direction[0] * sz + placement->direction[1] * cz;
-                               placement->direction[0] = x2;
-                               placement->direction[1] = y2;
-
-                               // z-axis rotation for up
-                               x2 = placement->up[0] * cz - placement->up[1] * sz;
-                               y2 = placement->up[0] * sz + placement->up[1] * cz;
-                               placement->up[0] = x2;
-                               placement->up[1] = y2;
-
-                               // x-axis rotation for origin
-                               y2 = placement->origin[1] * cx - placement->origin[2] * sx;
-                               z2 = placement->origin[1] * sx + placement->origin[2] * cx;
-                               placement->origin[1] = y2;
-                               placement->origin[2] = z2;
-
-                               // x-axis rotation for direction vector
-                               y2 = placement->direction[1] * cx - placement->direction[2] * sx;
-                               z2 = placement->direction[1] * sx + placement->direction[2] * cx;
-                               placement->direction[1] = y2;
-                               placement->direction[2] = z2;
-
-                               // x-axis rotation for up vector
-                               y2 = placement->up[1] * cx - placement->up[2] * sx;
-                               z2 = placement->up[1] * sx + placement->up[2] * cx;
-                               placement->up[1] = y2;
-                               placement->up[2] = z2;
-
-                               // translate origin
-                               placement->origin[0] += curTranslation[i][0];
-                               placement->origin[1] += curTranslation[i][1];
-                               placement->origin[2] += curTranslation[i][2];
-
-                               // translate back to local coord
-                               placement->direction[0] += curTranslation[i][0];
-                               placement->direction[1] += curTranslation[i][1];
-                               placement->direction[2] += curTranslation[i][2];
-
-                               // translate back to local coord
-                               placement->up[0] += curTranslation[i][0];
-                               placement->up[1] += curTranslation[i][1];
-                               placement->up[2] += curTranslation[i][2];
-                       }
-               }
-#else
-               // This screwed up and needs to be sorted out!!!
-               // The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
-               for ( j = i - 1; j < stackSize - 1; ++j )
-               {
-                       // y-axis rotation for origin
-                       x2 = jointList[j].placement.origin[0] * cy + jointList[j].placement.origin[2] * sy;
-                       z2 = -jointList[j].placement.origin[0] * sy + jointList[j].placement.origin[2] * cy;
-                       jointList[j].placement.origin[0] = x2;
-                       jointList[j].placement.origin[2] = z2;
-
-                       // y-axis rotation for direction
-                       x2 = jointList[j].placement.direction[0] * cy + jointList[j].placement.direction[2] * sy;
-                       z2 = -jointList[j].placement.direction[0] * sy + jointList[j].placement.direction[2] * cy;
-                       jointList[j].placement.direction[0] = x2;
-                       jointList[j].placement.direction[2] = z2;
-
-                       // y-axis rotation for up
-                       x2 = jointList[j].placement.up[0] * cy + jointList[j].placement.up[2] * sy;
-                       z2 = -jointList[j].placement.up[0] * sy + jointList[j].placement.up[2] * cy;
-                       jointList[j].placement.up[0] = x2;
-                       jointList[j].placement.up[2] = z2;
-
-                       // z-axis rotation for origin
-                       x2 = jointList[j].placement.origin[0] * cz - jointList[j].placement.origin[1] * sz;
-                       y2 = jointList[j].placement.origin[0] * sz + jointList[j].placement.origin[1] * cz;
-                       jointList[j].placement.origin[0] = x2;
-                       jointList[j].placement.origin[1] = y2;
-
-                       // z-axis rotation for direction
-                       x2 = jointList[j].placement.direction[0] * cz - jointList[j].placement.direction[1] * sz;
-                       y2 = jointList[j].placement.direction[0] * sz + jointList[j].placement.direction[1] * cz;
-                       jointList[j].placement.direction[0] = x2;
-                       jointList[j].placement.direction[1] = y2;
-
-                       // z-axis rotation for up
-                       x2 = jointList[j].placement.up[0] * cz - jointList[j].placement.up[1] * sz;
-                       y2 = jointList[j].placement.up[0] * sz + jointList[j].placement.up[1] * cz;
-                       jointList[j].placement.up[0] = x2;
-                       jointList[j].placement.up[1] = y2;
-
-                       // x-axis rotation for origin
-                       y2 = jointList[j].placement.origin[1] * cx - jointList[j].placement.origin[2] * sx;
-                       z2 = jointList[j].placement.origin[1] * sx + jointList[j].placement.origin[2] * cx;
-                       jointList[j].placement.origin[1] = y2;
-                       jointList[j].placement.origin[2] = z2;
-
-                       // x-axis rotation for direction vector
-                       y2 = jointList[j].placement.direction[1] * cx - jointList[j].placement.direction[2] * sx;
-                       z2 = jointList[j].placement.direction[1] * sx + jointList[j].placement.direction[2] * cx;
-                       jointList[j].placement.direction[1] = y2;
-                       jointList[j].placement.direction[2] = z2;
-
-                       // x-axis rotation for up vector
-                       y2 = jointList[j].placement.up[1] * cx - jointList[j].placement.up[2] * sx;
-                       z2 = jointList[j].placement.up[1] * sx + jointList[j].placement.up[2] * cx;
-                       jointList[j].placement.up[1] = y2;
-                       jointList[j].placement.up[2] = z2;
-
-                       if ( curCorrespondingJoint[j + 1] != -1 ) {
-                               // translate origin
-                               jointList[j].placement.origin[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.origin[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.origin[2] += curTranslation[i - 1][2];
-
-                               // translate back to local coord
-                               jointList[j].placement.direction[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.direction[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.direction[2] += curTranslation[i - 1][2];
-
-                               // translate back to local coord
-                               jointList[j].placement.up[0] += curTranslation[i - 1][0];
-                               jointList[j].placement.up[1] += curTranslation[i - 1][1];
-                               jointList[j].placement.up[2] += curTranslation[i - 1][2];
-                       }
-               }
-#endif
-       }
-}
-
-void LoadModelTransform( char *fileName ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCGlobals( InputFileName );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC match.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-//                     printf("\n");
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCGlobals( fileName );
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-void LoadModelClusters( char *fileName, int **clusterList, int *num_verts, int skelType ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCClustered( InputFileName, clusterList, num_verts, skelType );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC match.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-//                     printf("\n");
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCClustered( fileName, clusterList, num_verts, skelType );
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-void LoadSkeleton( char *fileName, QD_SkeletalJoint_t *jointList, int skelType ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCJointList( InputFileName, jointList, skelType );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-//                     printf("\n");
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCJointList( fileName, jointList, skelType );
-
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-/*
-   ===============
-   GrabSkeletalFrame
-   ===============
- */
-void GrabSkeletalFrame( char *frame ){
-       char file1[1024];
-       char    *framefile;
-       fmframe_t   *fr;
-
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "Grabbing Skeletal Frame %s\n", file1 );
-
-       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-       LoadSkeleton( file1, fr->joints, g_skelModel.type );
-}
-
-/*
-   ===============
-   GrabModelTransform
-   ===============
- */
-void GrabModelTransform( char *frame ){
-       char file1[1024];
-       char    *framefile;
-       fmframe_t   *fr;
-
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-//     printf ("grabbing %s\n", file1);
-
-       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-       LoadModelTransform( file1 );
-}
-
-void Cmd_FMCluster(){
-       char file1[1024];
-
-       GetScriptToken( false );
-
-       printf( "---------------------\n" );
-       sprintf( file1, "%s/%s", cdpartial, token );
-       printf( "%s\n", file1 );
-
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s", cddir, token );
-
-       g_skelModel.clustered = -1;
-
-       LoadModelClusters( file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type );
-
-       g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
-
-       g_skelModel.clustered = true;
-}
-
-void Cmd_FMSkeleton(){
-       GetScriptToken( false );
-       g_skelModel.type = atoi( token );
-}
-
-void Cmd_FMSkeletalFrame(){
-       while ( ScriptTokenAvailable() )
-       {
-               GetScriptToken( false );
-               if ( g_skipmodel ) {
-                       GetScriptToken( false );
-                       continue;
-               }
-               if ( g_release || g_archive ) {
-                       fmheader.num_frames = 1;    // don't skip the writeout
-                       GetScriptToken( false );
-                       continue;
-               }
-
-               H_printf( "#define FRAME_%-16s\t%i\n", token, fmheader.num_frames );
-
-               GrabModelTransform( token );
-               GrabFrame( token );
-               GrabSkeletalFrame( token );
-
-               // need to add the up and dir points to the frame bounds here
-               // using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-               // then remove fudge in determining scale on frame write out
-       }
-}
-
-static void LoadHRCReferences( char *fileName, fmframe_t *fr ){
-#define MAX_STACK 64
-       int i, j, k;
-       vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
-       int curCorrespondingJoint[MAX_STACK];
-       int currentStack, stackSize;
-       double cx, sx, cy, sy, cz, sz;
-       double rx, ry, rz;
-       double x2, y2, z2;
-       char stripped[SKELETAL_NAME_MAX];
-       Placement_d_t *placement;
-       int refnum;
-
-       TK_OpenSource( fileName );
-       TK_FetchRequire( TK_HRCH );
-       TK_FetchRequire( TK_COLON );
-       TK_FetchRequire( TK_SOFTIMAGE );
-
-       if ( RefPointNum <= 0 ) { // There were no labels indicated in the QDT, so use the hard-coded stuff.
-               refnum = numReferences[g_skelModel.references];
-       }
-       else
-       {
-               refnum = RefPointNum;
-       }
-
-       for ( k = 0; k < refnum; ++k )
-       {
-               currentStack = 0;
-
-               // Load the root to get translation and initial rotation
-//             TK_Beyond(TK_MODEL);
-
-               while ( TK_Search( TK_NAME ) != TK_EOF )
-               {
-                       TK_Require( TK_STRING );
-
-                       StripTrailingDigits( tk_String, stripped );
-
-                       if ( RefPointNum == 0 ) { // Hard coded refpoint labels
-                               if ( stricmp( stripped,
-                                                         referenceRootNames[referenceRootNameOffsets[g_skelModel.references] + k] ) == 0 ) {
-                                       break;
-                               }
-                       }
-                       else
-                       {   // labels indicated by the QDT
-                               if ( stricmp( stripped, RefPointNameList[k] ) == 0 ) {
-                                       break;
-                               }
-                       }
-               }
-
-               if ( tk_Token == TK_EOF ) {
-                       if ( RefPointNum == 0 ) { // Hard coded refpoint labels
-                               Error( "Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]] );
-                       }
-                       else
-                       {   // labels indicated by the QDT
-                               Error( "Bone Chain Root: %s not found\n", RefPointNameList[k] );
-                       }
-                       return;
-               }
-
-//             TK_Beyond(TK_SCALING);
-
-//             ParseVec3d(curScale[currentStack]);
-
-               TK_Beyond( TK_ROTATION );
-
-               ParseRotation3d( curRotation[currentStack] );
-
-               TK_Beyond( TK_TRANSLATION );
-
-               ParseVec3d( curTranslation[currentStack] );
-
-               // account for global model translation
-               curTranslation[currentStack][1] += g_skelModel.translation[0];
-               curTranslation[currentStack][2] += g_skelModel.translation[1];
-               curTranslation[currentStack][0] += g_skelModel.translation[2];
-
-               curCorrespondingJoint[currentStack] = -1;
-
-//             rjr - this one not needed, as there is also a stack increment 20 lines below???
-//             ++currentStack;
-
-               // Load the joint to get orientation
-               TK_Beyond( TK_MODEL );
-
-//             TK_Beyond(TK_SCALING);
-
-//             ParseVec3d(curScale[currentStack]);
-
-               TK_Beyond( TK_ROTATION );
-
-               ParseRotation3d( curRotation[currentStack] );
-
-//             TK_Beyond(TK_TRANSLATION);
-
-//             ParseVec3d(curTranslation[currentStack]);
-
-               fr->references[k].placement.origin[1] = 0.0;
-               fr->references[k].placement.origin[2] = 0.0;
-               fr->references[k].placement.origin[0] = 0.0;
-
-               fr->references[k].placement.direction[1] = 20.0;
-               fr->references[k].placement.direction[2] = 0.0;
-               fr->references[k].placement.direction[0] = 0.0;
-
-               fr->references[k].placement.up[1] = 0.0;
-               fr->references[k].placement.up[2] = 20.0;
-               fr->references[k].placement.up[0] = 0.0;
-
-               curCorrespondingJoint[currentStack] = k;
-
-               ++currentStack;
-
-               stackSize = currentStack;
-
-               for ( i = stackSize - 1; i >= 0; --i )
-               {
-                       rx = curRotation[i][0] * ANGLE_TO_RAD;
-                       ry = curRotation[i][1] * ANGLE_TO_RAD;
-                       rz = curRotation[i][2] * ANGLE_TO_RAD;
-
-                       cx = cos( rx );
-                       sx = sin( rx );
-
-                       cy = cos( ry );
-                       sy = sin( ry );
-
-                       cz = cos( rz );
-                       sz = sin( rz );
-
-                       for ( j = i; j < stackSize; ++j )
-                       {
-                               if ( curCorrespondingJoint[j] != -1 ) {
-                                       placement = &fr->references[curCorrespondingJoint[j]].placement;
-
-                                       // y-axis rotation for origin
-                                       x2 = placement->origin[0] * cy + placement->origin[2] * sy;
-                                       z2 = -placement->origin[0] * sy + placement->origin[2] * cy;
-                                       placement->origin[0] = x2;
-                                       placement->origin[2] = z2;
-
-                                       // y-axis rotation for direction
-                                       x2 = placement->direction[0] * cy + placement->direction[2] * sy;
-                                       z2 = -placement->direction[0] * sy + placement->direction[2] * cy;
-                                       placement->direction[0] = x2;
-                                       placement->direction[2] = z2;
-
-                                       // y-axis rotation for up
-                                       x2 = placement->up[0] * cy + placement->up[2] * sy;
-                                       z2 = -placement->up[0] * sy + placement->up[2] * cy;
-                                       placement->up[0] = x2;
-                                       placement->up[2] = z2;
-
-                                       // z-axis rotation for origin
-                                       x2 = placement->origin[0] * cz - placement->origin[1] * sz;
-                                       y2 = placement->origin[0] * sz + placement->origin[1] * cz;
-                                       placement->origin[0] = x2;
-                                       placement->origin[1] = y2;
-
-                                       // z-axis rotation for direction
-                                       x2 = placement->direction[0] * cz - placement->direction[1] * sz;
-                                       y2 = placement->direction[0] * sz + placement->direction[1] * cz;
-                                       placement->direction[0] = x2;
-                                       placement->direction[1] = y2;
-
-                                       // z-axis rotation for up
-                                       x2 = placement->up[0] * cz - placement->up[1] * sz;
-                                       y2 = placement->up[0] * sz + placement->up[1] * cz;
-                                       placement->up[0] = x2;
-                                       placement->up[1] = y2;
-
-                                       // x-axis rotation for origin
-                                       y2 = placement->origin[1] * cx - placement->origin[2] * sx;
-                                       z2 = placement->origin[1] * sx + placement->origin[2] * cx;
-                                       placement->origin[1] = y2;
-                                       placement->origin[2] = z2;
-
-                                       // x-axis rotation for direction vector
-                                       y2 = placement->direction[1] * cx - placement->direction[2] * sx;
-                                       z2 = placement->direction[1] * sx + placement->direction[2] * cx;
-                                       placement->direction[1] = y2;
-                                       placement->direction[2] = z2;
-
-                                       // x-axis rotation for up vector
-                                       y2 = placement->up[1] * cx - placement->up[2] * sx;
-                                       z2 = placement->up[1] * sx + placement->up[2] * cx;
-                                       placement->up[1] = y2;
-                                       placement->up[2] = z2;
-
-                                       // translate origin
-                                       placement->origin[0] += curTranslation[i][0];
-                                       placement->origin[1] += curTranslation[i][1];
-                                       placement->origin[2] += curTranslation[i][2];
-
-                                       // translate back to local coord
-                                       placement->direction[0] += curTranslation[i][0];
-                                       placement->direction[1] += curTranslation[i][1];
-                                       placement->direction[2] += curTranslation[i][2];
-
-                                       // translate back to local coord
-                                       placement->up[0] += curTranslation[i][0];
-                                       placement->up[1] += curTranslation[i][1];
-                                       placement->up[2] += curTranslation[i][2];
-
-                               }
-                       }
-               }
-               printf( "%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2] );
-       }
-       printf( "\n" );
-}
-
-void Cmd_FMReferenced(){
-       int i;
-
-       GetScriptToken( false );
-       g_skelModel.references = atoi( token );
-
-       // Guess what?  Now, we now want a list of strings to look for here instead of a hard-coded list
-       for ( i = 0; i < REF_MAX_POINTS; i++ )
-       {
-               if ( ScriptTokenAvailable() ) { // There is yet another reference point waiting.
-                       GetScriptToken( false );
-                       strcpy( RefPointNameList[i], token );
-               }
-               else
-               {
-                       break;
-               }
-       }
-
-       RefPointNum = i;
-
-       if ( RefPointNum > 0 ) {
-               printf( "Searching for %d different reference points.\n", RefPointNum );
-       }
-       else
-       {
-               printf( "Using built-in reference points.\n" );
-       }
-
-}
-
-void LoadReferences( char *fileName, fmframe_t *fr ){
-       FILE *file1;
-       int dot = '.';
-       char *dotstart;
-       char InputFileName[256];
-
-       dotstart = strrchr( fileName,dot ); // Does it already have an extension on the file name?
-
-       if ( !dotstart ) {
-               strcpy( InputFileName, fileName );
-               strcat( InputFileName, ".hrc" );
-               if ( ( file1 = fopen( InputFileName, "rb" ) ) != NULL ) {
-                       fclose( file1 );
-
-                       LoadHRCReferences( InputFileName, fr );
-
-                       printf( " - assuming .HRC\n" );
-                       return;
-               }
-
-               Error( "\n Could not open file '%s':\n"
-                          "No HRC.\n", fileName );
-       }
-       else
-       {
-               if ( ( file1 = fopen( fileName, "rb" ) ) != NULL ) {
-                       printf( "\n" );
-                       fclose( file1 );
-                       if ( strcmp( dotstart,".hrc" ) == 0 || strcmp( dotstart,".HRC" ) == 0 ) {
-                               LoadHRCReferences( fileName, fr );
-
-                               return;
-                       }
-               }
-
-               Error( "Could not open file '%s':\n",fileName );
-       }
-}
-
-void GrabReferencedFrame( char *frame ){
-       char file1[1024];
-       char    *framefile;
-       fmframe_t   *fr;
-
-       framefile = FindFrameFile( frame );
-
-       sprintf( file1, "%s/%s", cdarchive, framefile );
-       ExpandPathAndArchive( file1 );
-
-       sprintf( file1, "%s/%s",cddir, framefile );
-
-       printf( "Grabbing Referenced %s\n", file1 );
-
-       fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-       LoadReferences( file1, fr );
-}
diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.h b/tools/quake2/qdata_heretic2/qd_skeletons.h
deleted file mode 100644 (file)
index 7765c57..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#ifndef QD_SKELETONS_H
-#define QD_SKELETONS_H
-
-#include "placement.h"
-
-
-typedef struct Placement_d_s
-{
-       vec3d_t origin;
-       vec3d_t direction;
-       vec3d_t up;
-} Placement_d_t;
-
-typedef struct QD_SkeletalJoint_s
-{
-       Placement_d_t placement;
-       vec3d_t rotation;
-} QD_SkeletalJoint_t;
-
-#define NUM_CLUSTERS 8
-
-typedef struct IntListNode_s
-{
-       int data;
-       struct IntListNode_s *next;
-} IntListNode_t;  // gaak
-
-typedef struct Skeletalfmheader_s
-{
-       int type;
-       int clustered;
-       int references;
-
-       int *clusters[NUM_CLUSTERS];
-       IntListNode_t *vertLists[NUM_CLUSTERS];
-       int num_verts[NUM_CLUSTERS + 1];
-       int new_num_verts[NUM_CLUSTERS + 1];
-
-       float scaling[3];
-       float rotation[3];
-       float translation[3];
-} Skeletalfmheader_t;
-
-#define SKELETAL_NAME_MAX 32
-
-extern Skeletalfmheader_t g_skelModel;
-
-void ClearSkeletalModel();
-void GrabModelTransform( char *frame );
-void GrabSkeletalFrame( char *frame );
-void GrabReferencedFrame( char *frame );
-
-// Reference Stuff
-#define NUM_REFERENCES 8
-
-#define REF_MAX_POINTS  16
-#define REF_MAX_STRLEN  32
-
-// We're assuming no more than 16 reference points, with no more than 32 characters in the name
-extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
-extern int RefPointNum;
-
-#endif
diff --git a/tools/quake2/qdata_heretic2/qdata.c b/tools/quake2/qdata_heretic2/qdata.c
deleted file mode 100644 (file)
index 5ec53a9..0000000
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qdata.h"
-#include "globaldefs.h"
-#include "md4.h"
-
-void TK_Init();
-
-qboolean g_compress_pak;
-qboolean g_release;             // don't grab, copy output data to new tree
-qboolean g_pak;                 // if true, copy to pak instead of release
-char g_releasedir[1024];        // c:\quake2\baseq2, etc
-qboolean g_archive;             // don't grab, copy source data to new tree
-qboolean do3ds;
-char g_only[256];               // if set, only grab this cd
-qboolean g_skipmodel;           // set true when a cd is not g_only
-int g_forcemodel = MODEL_AUTO;
-qboolean g_verbose = false;
-qboolean g_allow_newskin = true;
-qboolean g_ignoreTriUV = false;
-qboolean g_publishOutput = false;
-
-char        *ext_3ds = "3ds";
-char        *ext_tri = "tri";
-char        *trifileext;
-
-char g_materialFile[256] = "none";          // default for Heretic2
-char        *g_outputDir;
-extern char *g_publishDir;
-
-extern qboolean g_nomkdir;
-
-/*
-   =======================================================
-
-   PAK FILES
-
-   =======================================================
- */
-
-typedef struct
-{
-       char name[56];
-       int filepos, filelen;
-} packfile_t;
-
-typedef struct
-{
-       char id[4];
-       int dirofs;
-       int dirlen;
-} packheader_t;
-
-packfile_t pfiles[16384];
-FILE            *pakfile;
-packfile_t      *pf;
-packheader_t pakheader;
-
-
-
-/*
-   ==============
-   BeginPak
-   ==============
- */
-void BeginPak( char *outname ){
-       if ( !g_pak ) {
-               return;
-       }
-
-       pakfile = SafeOpenWrite( outname );
-
-       // leave space for header
-       SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
-
-       pf = pfiles;
-}
-
-
-/*
-   ==============
-   ReleaseFile
-
-   Filename should be gamedir reletive.
-   Either copies the file to the release dir, or adds it to
-   the pak file.
-   ==============
- */
-void ReleaseFile( char *filename ){
-       int len;
-       byte    *buf;
-       char source[1024];
-       char dest[1024];
-
-       if ( !g_release ) {
-               return;
-       }
-
-       sprintf( source, "%s%s", gamedir, filename );
-
-       if ( !g_pak ) { // copy it
-               sprintf( dest, "%s/%s", g_releasedir, filename );
-               printf( "copying to %s\n", dest );
-               QCopyFile( source, dest );
-               return;
-       }
-
-       // pak it
-       printf( "paking %s\n", filename );
-       if ( strlen( filename ) >= sizeof( pf->name ) ) {
-               Error( "Filename too long for pak: %s", filename );
-       }
-
-       len = LoadFile( source, (void **)&buf );
-
-       // segment moved to old.c
-
-       strcpy( pf->name, filename );
-       pf->filepos = LittleLong( ftell( pakfile ) );
-       pf->filelen = LittleLong( len );
-       pf++;
-
-       SafeWrite( pakfile, buf, len );
-
-       free( buf );
-}
-
-
-/*
-   ==============
-   FinishPak
-   ==============
- */
-void FinishPak( void ){
-       int dirlen;
-       int d;
-       int i;
-       unsigned checksum;
-
-       if ( !g_pak ) {
-               return;
-       }
-
-       pakheader.id[0] = 'P';
-       pakheader.id[1] = 'A';
-       pakheader.id[2] = 'C';
-       pakheader.id[3] = 'K';
-       dirlen = (byte *)pf - (byte *)pfiles;
-       pakheader.dirofs = LittleLong( ftell( pakfile ) );
-       pakheader.dirlen = LittleLong( dirlen );
-
-       checksum = Com_BlockChecksum( (void *)pfiles, dirlen );
-
-       SafeWrite( pakfile, pfiles, dirlen );
-
-       i = ftell( pakfile );
-
-       fseek( pakfile, 0, SEEK_SET );
-       SafeWrite( pakfile, &pakheader, sizeof( pakheader ) );
-       fclose( pakfile );
-
-       d = pf - pfiles;
-       printf( "%i files packed in %i bytes\n",d, i );
-       printf( "checksum: 0x%x\n", checksum );
-}
-
-
-/*
-   ===============
-   Cmd_File
-
-   This is only used to cause a file to be copied during a release
-   build (default.cfg, maps, etc)
-   ===============
- */
-void Cmd_File( void ){
-       GetScriptToken( false );
-       ReleaseFile( token );
-}
-
-/*
-   ===============
-   PackDirectory_r
-
-   ===============
- */
-#if GDEF_OS_WINDOWS
-#include "io.h"
-void PackDirectory_r( char *dir ){
-       struct _finddata_t fileinfo;
-       int handle;
-       char dirstring[1024];
-       char filename[1024];
-
-       sprintf( dirstring, "%s%s/*.*", gamedir, dir );
-
-       handle = _findfirst( dirstring, &fileinfo );
-       if ( handle == -1 ) {
-               return;
-       }
-
-       do
-       {
-               sprintf( filename, "%s/%s", dir, fileinfo.name );
-               if ( fileinfo.attrib & _A_SUBDIR ) { // directory
-                       if ( fileinfo.name[0] != '.' ) {  // don't pak . and ..
-                               PackDirectory_r( filename );
-                       }
-                       continue;
-               }
-               // copy or pack the file
-               ReleaseFile( filename );
-       } while ( _findnext( handle, &fileinfo ) != -1 );
-
-       _findclose( handle );
-}
-#else
-
-#include <sys/types.h>
-#ifdef NeXT
-#include <sys/dir.h>
-#else
-#include <dirent.h>
-#endif
-
-void PackDirectory_r( char *dir ){
-#ifdef NeXT
-       struct direct **namelist, *ent;
-#else
-       struct dirent **namelist, *ent;
-#endif
-       int count;
-       struct stat st;
-       int i;
-       int len;
-       char fullname[1024];
-       char dirstring[1024];
-       char        *name;
-
-       sprintf( dirstring, "%s%s", gamedir, dir );
-       count = scandir( dirstring, &namelist, NULL, NULL );
-
-       for ( i = 0 ; i < count ; i++ )
-       {
-               ent = namelist[i];
-               name = ent->d_name;
-
-               if ( name[0] == '.' ) {
-                       continue;
-               }
-
-               sprintf( fullname, "%s/%s", dir, name );
-               sprintf( dirstring, "%s%s/%s", gamedir, dir, name );
-
-               if ( stat( dirstring, &st ) == -1 ) {
-                       Error( "fstating %s", pf->name );
-               }
-               if ( st.st_mode & S_IFDIR ) { // directory
-                       PackDirectory_r( fullname );
-                       continue;
-               }
-
-               // copy or pack the file
-               ReleaseFile( fullname );
-       }
-}
-#endif
-
-
-/*
-   ===============
-   Cmd_Dir
-
-   This is only used to cause a directory to be copied during a
-   release build (sounds, etc)
-   ===============
- */
-void Cmd_Dir( void ){
-       GetScriptToken( false );
-       PackDirectory_r( token );
-}
-
-//========================================================================
-
-#define MAX_RTEX    16384
-int numrtex;
-char rtex[MAX_RTEX][64];
-
-void ReleaseTexture( char *name ){
-       int i;
-       char path[1024];
-
-       for ( i = 0 ; i < numrtex ; i++ )
-               if ( !Q_strcasecmp( name, rtex[i] ) ) {
-                       return;
-               }
-
-       if ( numrtex == MAX_RTEX ) {
-               Error( "numrtex == MAX_RTEX" );
-       }
-
-       strcpy( rtex[i], name );
-       numrtex++;
-
-       sprintf( path, "textures/%s.wal", name );
-       ReleaseFile( path );
-}
-
-/*
-   ===============
-   Cmd_Maps
-
-   Only relevent for release and pak files.
-   Releases the .bsp files for the maps, and scans all of the files to
-   build a list of all textures used, which are then released.
-   ===============
- */
-void Cmd_Maps( void ){
-       char map[1024];
-       int i;
-
-       while ( ScriptTokenAvailable() )
-       {
-               GetScriptToken( false );
-               sprintf( map, "maps/%s.bsp", token );
-               ReleaseFile( map );
-
-               if ( !g_release ) {
-                       continue;
-               }
-
-               // get all the texture references
-               sprintf( map, "%smaps/%s.bsp", gamedir, token );
-               LoadBSPFileTexinfo( map );
-               for ( i = 0 ; i < numtexinfo ; i++ )
-                       ReleaseTexture( texinfo[i].texture );
-       }
-}
-
-
-//==============================================================
-
-/*
-   ===============
-   ParseScript
-   ===============
- */
-void ParseScript( void ){
-       while ( 1 )
-       {
-               do
-               {   // look for a line starting with a $ command
-                       GetScriptToken( true );
-                       if ( endofscript ) {
-                               return;
-                       }
-                       if ( token[0] == '$' ) {
-                               break;
-                       }
-                       while ( ScriptTokenAvailable() )
-                               GetScriptToken( false );
-               } while ( 1 );
-
-               //
-               // model commands
-               //
-               if ( !strcmp( token, "$modelname" ) ) {
-                       MODELCMD_Modelname( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$cd" ) ) {
-                       MODELCMD_Cd( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$origin" ) ) {
-                       MODELCMD_Origin( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$cluster" ) ) {
-                       MODELCMD_Cluster( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$base" ) ) {
-                       MODELCMD_Base( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$scale" ) ) {
-                       MODELCMD_ScaleUp( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$frame" ) ) {
-                       MODELCMD_Frame( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$skin" ) ) {
-                       MODELCMD_Skin( MODEL_MD2 );
-               }
-               else if ( !strcmp( token, "$skinsize" ) ) {
-                       MODELCMD_Skinsize( MODEL_MD2 );
-               }
-               //
-               // flexible model commands
-               //
-               else if ( !strcmp( token, "$fm_modelname" ) ) {
-                       MODELCMD_Modelname( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_base" ) ) {
-                       MODELCMD_Base( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_basest" ) ) {
-                       MODELCMD_BaseST( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_cd" ) ) {
-                       MODELCMD_Cd( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_origin" ) ) {
-                       MODELCMD_Origin( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_cluster" ) ) {
-                       MODELCMD_Cluster( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_skeleton" ) ) {
-                       MODELCMD_Skeleton( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_scale" ) ) {
-                       MODELCMD_ScaleUp( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_frame" ) ) {
-                       MODELCMD_Frame( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_skeletal_frame" ) ) { // left in for compadibility with qdt already using fm_skeletal_frame
-                       MODELCMD_Frame( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_skin" ) ) {
-                       MODELCMD_Skin( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_skinsize" ) ) {
-                       MODELCMD_Skinsize( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_begin_group" ) ) {
-                       MODELCMD_BeginGroup( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_end_group" ) ) {
-                       MODELCMD_EndGroup( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_referenced" ) ) {
-                       MODELCMD_Referenced( MODEL_FM );
-               }
-               else if ( !strcmp( token, "$fm_node_order" ) ) {
-                       MODELCMD_NodeOrder( MODEL_FM );
-               }
-
-               //
-               // sprite commands
-               //
-               else if ( !strcmp( token, "$spritename" ) ) {
-                       Cmd_SpriteName();
-               }
-               else if ( !strcmp( token, "$sprdir" ) ) {
-                       Cmd_Sprdir();
-               }
-               else if ( !strcmp( token, "$load" ) ) {
-                       Cmd_Load();
-               }
-               else if ( !strcmp( token, "$spriteframe" ) ) {
-                       Cmd_SpriteFrame();
-               }
-               //
-               // image commands
-               //
-               else if ( !strcmpi( token, "$grab" ) ) {
-                       Cmd_Grab();
-               }
-               else if ( !strcmpi( token, "$raw" ) ) {
-                       Cmd_Raw();
-               }
-               else if ( !strcmpi( token, "$colormap" ) ) {
-                       Cmd_Colormap();
-               }
-               else if ( !strcmpi( token, "$mippal" ) ) {
-                       Cmd_Mippal();
-               }
-               else if ( !strcmpi( token, "$mipdir" ) ) {
-                       Cmd_Mipdir();
-               }
-               else if ( !strcmpi( token, "$mip" ) ) {
-                       Cmd_Mip();
-               }
-               else if ( !strcmp( token, "$environment" ) ) {
-                       Cmd_Environment();
-               }
-               //
-               // pics
-               //
-               else if ( !strcmp( token, "$picdir" ) ) {
-                       Cmd_Picdir();
-               }
-               else if ( !strcmp( token, "$pic" ) ) {
-                       Cmd_Pic();
-               }
-               //
-               // book
-               //
-               else if ( !strcmp( token, "$bookdir" ) ) {
-                       Cmd_Bookdir();
-               }
-               else if ( !strcmp( token, "$book" ) ) {
-                       Cmd_Book();
-               }
-               //
-               // tmix
-               //
-               else if ( !strcmp( token, "$texturemix" ) ) {
-                       Cmd_TextureMix();
-               }
-               //
-               // video
-               //
-               else if ( !strcmp( token, "$video" ) ) {
-                       Cmd_Video();
-               }
-               //
-               // misc
-               //
-               else if ( !strcmp( token, "$file" ) ) {
-                       Cmd_File();
-               }
-               else if ( !strcmp( token, "$dir" ) ) {
-                       Cmd_Dir();
-               }
-               else if ( !strcmp( token, "$maps" ) ) {
-                       Cmd_Maps();
-               }
-               else if ( !strcmp( token, "$alphalight" ) ) {
-                       Cmd_Alphalight();
-               }
-               else if ( !strcmp( token, "$inverse16table" ) ) {
-                       Cmd_Inverse16Table();
-               }
-               else{
-                       Error( "bad command %s\n", token );
-               }
-       }
-}
-
-//=======================================================
-
-/*
-   ==============
-   main
-   ==============
- */
-int main( int argc, char **argv ){
-       int i;
-       char path[1024];
-       char        *basedir;
-       double starttime, endtime;
-
-       printf( "Qdata Plus : "__TIME__ " "__DATE__ "\n" );
-
-       starttime = I_FloatTime();
-       basedir = NULL;
-
-       TK_Init();
-       ExpandWildcards( &argc, &argv );
-
-       for ( i = 1 ; i < argc ; i++ )
-       {
-               if ( !strcmp( argv[i], "-archive" ) ) {
-                       // -archive f:/quake2/release/dump_11_30
-                       archive = true;
-                       strcpy( archivedir, argv[i + 1] );
-                       printf( "Archiving source to: %s\n", archivedir );
-                       i++;
-               }
-               else if ( !strcmp( argv[i], "-release" ) ) {
-                       g_release = true;
-                       strcpy( g_releasedir, argv[i + 1] );
-                       printf( "Copy output to: %s\n", g_releasedir );
-                       i++;
-               }
-               else if ( !strcmp( argv[i], "-base" ) ) {
-                       i++;
-                       basedir = argv[i];
-               }
-               else if ( !strcmp( argv[i], "-compress" ) ) {
-                       g_compress_pak = true;
-                       printf( "Compressing pakfile\n" );
-               }
-               else if ( !strcmp( argv[i], "-pak" ) ) {
-                       g_release = true;
-                       g_pak = true;
-                       printf( "Building pakfile: %s\n", argv[i + 1] );
-                       BeginPak( argv[i + 1] );
-                       i++;
-               }
-               else if ( !strcmp( argv[i], "-only" ) ) {
-                       strcpy( g_only, argv[i + 1] );
-                       printf( "Only grabbing %s\n", g_only );
-                       i++;
-               }
-               else if ( !strcmpi( argv[i], "-keypress" ) ) {
-                       g_dokeypress = true;
-               }
-               else if ( !strcmp( argv[i], "-3ds" ) ) {
-                       do3ds = true;
-                       printf( "loading .3ds files\n" );
-               }
-               else if ( !strcmp( argv[i], "-materialfile" ) ) {
-                       strcpy( g_materialFile, argv[i + 1] );
-                       printf( "Setting material file to %s\n", g_materialFile );
-                       i++;
-               }
-/*             else if (!strcmpi(argv[i], "-newgen"))
-        {
-            if (i < argc-4)
-            {
-                printf("run new triangle grouping routine here\n");
-                NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
-            }
-            else
-            {
-                printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
-            }
-            return 0;
-        }
- */     else if ( !strcmpi( argv[i], "-genskin" ) ) {
-                       i++;
-                       if ( i < argc - 3 ) {
-                               GenSkin( argv[i],argv[i + 1],atol( argv[i + 2] ),atol( argv[i + 3] ) );
-                       }
-                       else
-                       {
-                               printf( "qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n" );
-                       }
-                       return 0;
-
-               }
-               else if ( !strcmpi( argv[i], "-noopts" ) ) {
-                       g_no_opimizations = true;
-                       printf( "not performing optimizations\n" );
-               }
-               else if ( !strcmpi( argv[i], "-md2" ) ) {
-                       g_forcemodel = MODEL_MD2;
-               }
-               else if ( !strcmpi( argv[i], "-fm" ) ) {
-                       g_forcemodel = MODEL_FM;
-               }
-               else if ( !strcmpi( argv[i], "-verbose" ) ) {
-                       g_verbose = true;
-               }
-               else if ( !strcmpi( argv[i], "-oldskin" ) ) {
-                       g_allow_newskin = false;
-               }
-               else if ( !strcmpi( argv[i], "-ignoreUV" ) ) {
-                       g_ignoreTriUV = true;
-               }
-               else if ( !strcmpi( argv[i], "-publish" ) ) {
-                       g_publishOutput = true;
-               }
-               else if ( !strcmpi( argv[i], "-nomkdir" ) ) {
-                       g_nomkdir = true;
-               }
-               else if ( argv[i][0] == '-' ) {
-                       Error( "Unknown option \"%s\"", argv[i] );
-               }
-               else{
-                       break;
-               }
-       }
-
-       if ( i >= argc ) {
-               Error( "usage: qdata [-archive <directory>]\n"
-                          "             [-release <directory>]\n"
-                          "             [-base <directory>]\n"
-                          "             [-compress]\n"
-                          "             [-pak <file>]\n"
-                          "             [-only <model>]\n"
-                          "             [-keypress]\n"
-                          "             [-3ds]\n"
-                          "             [-materialfile <file>]\n"
-                          "             [-noopts]\n"
-                          "             [-md2]\n"
-                          "             [-fm]\n"
-                          "             [-verbose]\n"
-                          "             [-ignoreUV]\n"
-                          "             [-oldskin]\n"
-                          "             [-publish]\n"
-                          "             [-nomkdir]\n"
-                          "             file.qdt\n"
-                          "or\n"
-                          "       qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>" );
-       }
-
-       if ( do3ds ) {
-               trifileext = ext_3ds;
-       }
-       else{
-               trifileext = ext_tri;
-       }
-
-       for ( ; i < argc ; i++ )
-       {
-               printf( "--------------- %s ---------------\n", argv[i] );
-               // load the script
-               strcpy( path, argv[i] );
-               DefaultExtension( path, ".qdt" );
-               DefaultExtension( g_materialFile, ".mat" );
-               SetQdirFromPath( path );
-
-               printf( "workingdir='%s'\n", gamedir );
-               if ( basedir ) {
-                       qdir[0] = 0;
-                       g_outputDir = basedir;
-               }
-
-               printf( "outputdir='%s'\n", g_outputDir );
-
-               QFile_ReadMaterialTypes( g_materialFile );
-               LoadScriptFile( ExpandArg( path ) );
-
-               //
-               // parse it
-               //
-               ParseScript();
-
-               // write out the last model
-               FinishModel();
-               FMFinishModel();
-               FinishSprite();
-       }
-
-       if ( total_textures ) {
-               printf( "\n" );
-               printf( "Total textures processed: %d\n",total_textures );
-               printf( "Average size: %d x %d\n",total_x / total_textures, total_y / total_textures );
-       }
-
-       if ( g_pak ) {
-               FinishPak();
-       }
-
-       endtime = I_FloatTime();
-       printf( "Time elapsed:  %f\n", endtime - starttime );
-
-       if ( g_dokeypress ) {
-               printf( "Success! ... Hit a key: " );
-               getchar();
-       }
-
-       return 0;
-}
diff --git a/tools/quake2/qdata_heretic2/qdata.h b/tools/quake2/qdata_heretic2/qdata.h
deleted file mode 100644 (file)
index 0cfa606..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// qdata.h
-
-#include "globaldefs.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "scriplib.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "lbmlib.h"
-#include "her2_threads.h"
-#include "l3dslib.h"
-#include "bspfile.h"
-
-#if !GDEF_OS_WINDOWS
-#define stricmp strcasecmp
-#define strcmpi strcasecmp
-#endif
-
-
-#define MODEL_AUTO  0
-#define MODEL_MD2   1
-#define MODEL_FM    2
-
-// Model cover functions (to allow the forcing of a model type)
-void MODELCMD_Modelname( int modeltype );
-void MODELCMD_Cd( int modeltype );
-void MODELCMD_Origin( int modeltype );
-void MODELCMD_Jointed( int modeltype );
-void MODELCMD_Cluster( int modeltype );
-void MODELCMD_Base( int modeltype );
-void MODELCMD_BaseST( int modeltype );
-void MODELCMD_ScaleUp( int modeltype );
-void MODELCMD_Frame( int modeltype );
-void MODELCMD_Skin( int modeltype );
-void MODELCMD_Skinsize( int modeltype );
-void MODELCMD_Skeleton( int modeltype );
-void MODELCMD_SkeletalFrame( int modeltype );
-void MODELCMD_BeginGroup( int modeltype );
-void MODELCMD_EndGroup( int modeltype );
-void MODELCMD_Referenced( int modeltype );
-void MODELCMD_NodeOrder( int modeltype );
-
-void Cmd_Modelname( void );
-void Cmd_Base( void );
-void Cmd_Cd( void );
-void Cmd_Origin( void );
-void Cmd_ScaleUp( void );
-void Cmd_Frame( void );
-void Cmd_Skin( void );
-void Cmd_Skinsize( void );
-void FinishModel( void );
-void Cmd_Cluster( void );
-
-// Flexible Models
-//void Cmd_FMModelname (void);
-void Cmd_FMBase( qboolean GetST );
-void Cmd_FMCd( void );
-//void Cmd_FMOrigin (void);
-void Cmd_FMCluster();
-void Cmd_FMSkeleton();
-//void Cmd_FMScaleUp (void);
-void Cmd_FMFrame( void );
-void Cmd_FMSkeletalFrame();
-void Cmd_FMSkin( void );
-//void Cmd_FMSkinsize (void);
-void Cmd_FMBeginGroup( void );
-void Cmd_FMEndGroup( void );
-void Cmd_FMReferenced();
-void Cmd_FMNodeOrder( void );
-void FMFinishModel( void );
-void GenSkin( char *ModelFile, char *OutputName, int Width, int Height );
-void NewGen( char *ModelFile, char *OutputName, int width, int height );
-
-
-void Cmd_Inverse16Table( void );
-
-void Cmd_SpriteName( void );
-void Cmd_Load( void );
-void Cmd_SpriteFrame( void );
-void Cmd_Sprdir( void );
-void FinishSprite( void );
-
-void Cmd_Grab( void );
-void Cmd_Raw( void );
-void Cmd_Mip( void );
-void Cmd_Environment( void );
-void Cmd_Colormap( void );
-
-void Cmd_File( void );
-void Cmd_Dir( void );
-void Cmd_StartWad( void );
-void Cmd_EndWad( void );
-void Cmd_Mippal( void );
-void Cmd_Mipdir( void );
-void Cmd_Alphalight( void );
-
-void Cmd_Picdir( void );
-void Cmd_Pic( void );
-
-void Cmd_Bookdir( void );
-void Cmd_Book( void );
-
-void Cmd_TextureMix( void );
-
-void Cmd_Video( void );
-
-//void RemapZero (byte *pixels, byte *palette, int width, int height);
-
-void ReleaseFile( char *filename );
-
-extern byte        *byteimage, *lbmpalette;
-extern int byteimagewidth, byteimageheight;
-extern qboolean TrueColorImage;
-extern unsigned    *longimage;
-extern int longimagewidth, longimageheight;
-
-extern qboolean g_release;              // don't grab, copy output data to new tree
-extern char g_releasedir[1024];         // c:\quake2\baseq2, etc
-extern qboolean g_archive;              // don't grab, copy source data to new tree
-extern qboolean do3ds;
-extern char g_only[256];                // if set, only grab this cd
-extern qboolean g_skipmodel;            // set true when a cd is not g_only
-extern qboolean g_no_opimizations;
-extern int g_forcemodel;
-extern qboolean g_verbose;
-extern qboolean g_allow_newskin;
-extern qboolean g_ignoreTriUV;      //from qdata.c
-extern qboolean g_dokeypress;
-
-extern char        *trifileext;
-
-extern char g_materialFile[256];
-
-extern unsigned total_x;
-extern unsigned total_y;
-extern unsigned total_textures;
-
-miptex_t *CreateMip( byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip );
-miptex32_t *CreateMip32( unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip );
diff --git a/tools/quake2/qdata_heretic2/resource.h b/tools/quake2/qdata_heretic2/resource.h
deleted file mode 100644 (file)
index 3d6343e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by Script1.rc
-//
-#define IDI_ICON1                       101
-
-// Next default values for new objects
-//
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NO_MFC                     1
-#define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/tools/quake2/qdata_heretic2/script1.aps b/tools/quake2/qdata_heretic2/script1.aps
deleted file mode 100644 (file)
index 6650b67..0000000
Binary files a/tools/quake2/qdata_heretic2/script1.aps and /dev/null differ
diff --git a/tools/quake2/qdata_heretic2/script1.rc b/tools/quake2/qdata_heretic2/script1.rc
deleted file mode 100644 (file)
index 7d05374..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Icon
-//
-
-// Icon with lowest ID value placed first to ensure application icon
-// remains consistent on all systems.
-IDI_ICON1               ICON    DISCARDABLE     "icon1.ico"
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,0,0,1
- PRODUCTVERSION 1,0,0,1
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-            VALUE "Comments", "Heavily modified from original ID tool\0"
-            VALUE "CompanyName", "Raven Software\0"
-            VALUE "FileDescription", "qdata\0"
-            VALUE "FileVersion", "2.0\0"
-            VALUE "InternalName", "qdata\0"
-            VALUE "LegalCopyright", "Copyright © 1998\0"
-            VALUE "OriginalFilename", "qdata.exe\0"
-            VALUE "ProductName", "Raven Software qdata\0"
-            VALUE "ProductVersion", "2.0\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // !_MAC
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/tools/quake2/qdata_heretic2/sprites.c b/tools/quake2/qdata_heretic2/sprites.c
deleted file mode 100644 (file)
index ecb9d09..0000000
+++ /dev/null
@@ -1,345 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-
-#include "qdata.h"
-
-#define MAX_SPRFRAMES           MAX_MD2SKINS
-
-dsprite_t sprite;
-dsprframe_t frames[MAX_SPRFRAMES];
-
-byte            *byteimage, *lbmpalette;
-int byteimagewidth, byteimageheight;
-
-qboolean TrueColorImage;
-unsigned        *longimage;
-int longimagewidth, longimageheight;
-
-char spritename[1024];
-
-
-void FinishSprite( void );
-void Cmd_Spritename( void );
-
-char spr_prefix[1024];
-char pic_prefix[1024];
-
-extern char        *g_outputDir;
-
-
-/*
-   ==============
-   FinishSprite
-   ==============
- */
-void FinishSprite( void ){
-       FILE    *spriteouthandle;
-       int i, curframe;
-       dsprite_t spritetemp;
-       char savename[1024];
-
-       if ( sprite.numframes == 0 ) {
-               return;
-       }
-
-       if ( !strlen( spritename ) ) {
-               Error( "Didn't name sprite file" );
-       }
-
-       sprintf( savename, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, spritename );
-
-       if ( g_release ) {
-               char name[1024];
-
-               sprintf( name, "%s.sp2", spritename );
-               ReleaseFile( name );
-               spritename[0] = 0;      // clear for a new sprite
-               sprite.numframes = 0;
-               return;
-       }
-
-
-       printf( "saving in %s\n", savename );
-       CreatePath( savename );
-       spriteouthandle = SafeOpenWrite( savename );
-
-
-//
-// write out the sprite header
-//
-       spritetemp.ident = LittleLong( IDSPRITEHEADER );
-       spritetemp.version = LittleLong( SPRITE_VERSION );
-       spritetemp.numframes = LittleLong( sprite.numframes );
-
-       SafeWrite( spriteouthandle, &spritetemp, 12 );
-
-//
-// write out the frames
-//
-       curframe = 0;
-
-       for ( i = 0 ; i < sprite.numframes ; i++ )
-       {
-               frames[i].width = LittleLong( frames[i].width );
-               frames[i].height = LittleLong( frames[i].height );
-               frames[i].origin_x = LittleLong( frames[i].origin_x );
-               frames[i].origin_y = LittleLong( frames[i].origin_y );
-       }
-       SafeWrite( spriteouthandle, frames, sizeof( frames[0] ) * sprite.numframes );
-
-       fclose( spriteouthandle );
-
-       spritename[0] = 0;      // clear for a new sprite
-       sprite.numframes = 0;
-}
-
-
-/*
-   ===============
-   Cmd_Load
-   ===============
- */
-void Cmd_Load( void ){
-       char    *name;
-
-       GetScriptToken( false );
-
-       if ( g_release ) {
-               return;
-       }
-
-       name = ExpandPathAndArchive( token );
-
-       // load the image
-       printf( "loading %s\n", name );
-       TrueColorImage = LoadAnyImage( name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight );
-
-       if ( !TrueColorImage ) {
-//             RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight);
-       }
-       else
-       {
-               if ( longimage ) {
-                       free( longimage );
-               }
-               longimage = (unsigned *)byteimage;
-               longimagewidth = byteimagewidth;
-               longimageheight = byteimageheight;
-
-               byteimage = NULL;
-               byteimagewidth = 0;
-               byteimageheight = 0;
-       }
-}
-
-
-/*
-   ===============
-   Cmd_SpriteFrame
-   ===============
- */
-
-void Cmd_SpriteFrame( void ){
-       int x,y,xl,yl,xh,yh,w,h;
-       dsprframe_t     *pframe;
-       int ox, oy, linedelta, size;
-//     byte                    *cropped;
-       char filename[1024];
-       miptex_t        *qtex;
-       miptex32_t      *qtex32;
-       unsigned        *destl, *sourcel;
-       unsigned bufferl[256 * 256];
-       byte            *dest, *source;
-       byte buffer[256 * 256];
-
-       GetScriptToken( false );
-       xl = atoi( token );
-       GetScriptToken( false );
-       yl = atoi( token );
-       GetScriptToken( false );
-       w = atoi( token );
-       GetScriptToken( false );
-       h = atoi( token );
-
-       // origin offset is optional
-       if ( ScriptTokenAvailable() ) {
-               GetScriptToken( false );
-               ox = atoi( token );
-               GetScriptToken( false );
-               oy = atoi( token );
-       }
-       else
-       {
-               ox = w / 2;
-               oy = h / 2;
-       }
-
-       if ( ( xl & 0x0f ) || ( yl & 0x0f ) || ( w & 0x0f ) || ( h & 0x0f ) ) {
-               Error( "Sprite dimensions not multiples of 16\n" );
-       }
-
-       if ( ( w > 256 ) || ( h > 256 ) ) {
-               Error( "Sprite has a dimension longer than 256" );
-       }
-
-       xh = xl + w;
-       yh = yl + h;
-
-       if ( sprite.numframes >= MAX_SPRFRAMES ) {
-               Error( "Too many frames; increase MAX_SPRFRAMES\n" );
-       }
-
-       pframe = &frames[sprite.numframes];
-       pframe->width = w;
-       pframe->height = h;
-       pframe->origin_x = ox;
-       pframe->origin_y = oy;
-
-       if ( g_release ) {
-               ReleaseFile( pframe->name );
-               return;
-       }
-
-       if ( TrueColorImage ) {
-               sprintf( filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes );
-               sprintf( pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes );
-
-               if ( g_release ) {
-                       return; // textures are only released by $maps
-
-               }
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= longimagewidth || xh > longimagewidth ||
-                        yl >= longimageheight || yh > longimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight );
-               }
-
-               sourcel = longimage + ( yl * longimagewidth ) + xl;
-               destl = bufferl;
-               linedelta = ( longimagewidth - w );
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *destl++ = *sourcel++;  // RGBA
-                       }
-                       sourcel += linedelta;
-               }
-
-               qtex32 = CreateMip32( bufferl, w, h, &size, true );
-
-               qtex32->contents = 0;
-               qtex32->value = 0;
-               strcpy( qtex32->name, pframe->name );
-               //
-               // write it out
-               //
-               printf( "writing %s\n", filename );
-               SaveFile( filename, (byte *)qtex32, size );
-
-               free( qtex32 );
-       }
-       else
-       {
-               sprintf( filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes );
-               sprintf( pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes );
-
-               if ( g_release ) {
-                       return; // textures are only released by $maps
-
-               }
-               xh = xl + w;
-               yh = yl + h;
-
-               if ( xl >= byteimagewidth || xh > byteimagewidth ||
-                        yl >= byteimageheight || yh > byteimageheight ) {
-                       Error( "line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight );
-               }
-
-               source = byteimage + yl * byteimagewidth + xl;
-               dest = buffer;
-               linedelta = byteimagewidth - w;
-
-               for ( y = yl ; y < yh ; y++ )
-               {
-                       for ( x = xl ; x < xh ; x++ )
-                       {
-                               *dest++ = *source++;
-                       }
-                       source += linedelta;
-               }
-
-               qtex = CreateMip( buffer, w, h, lbmpalette, &size, true );
-
-               qtex->flags = 0;
-               qtex->contents = 0;
-               qtex->value = 0;
-               strcpy( qtex->name, pframe->name );
-               //
-               // write it out
-               //
-               printf( "writing %s\n", filename );
-               SaveFile( filename, (byte *)qtex, size );
-
-               free( qtex );
-       }
-
-       sprite.numframes++;
-}
-
-
-/*
-   ==============
-   Cmd_SpriteName
-   ==============
- */
-void Cmd_SpriteName( void ){
-       if ( sprite.numframes ) {
-               FinishSprite();
-       }
-
-       GetScriptToken( false );
-       strcpy( spritename, token );
-       memset( &sprite, 0, sizeof( sprite ) );
-       memset( &frames, 0, sizeof( frames ) );
-}
-
-
-/*
-   ===============
-   Cmd_Sprdir
-   ===============
- */
-void Cmd_Sprdir( void ){
-       char filename[1024];
-
-       GetScriptToken( false );
-       strcpy( spr_prefix, token );
-       // create the directory if needed
-       sprintf( filename, "%sSprites", g_outputDir );
-       Q_mkdir( filename );
-       sprintf( filename, "%sSprites/%s", g_outputDir, spr_prefix );
-       Q_mkdir( filename );
-}
diff --git a/tools/quake2/qdata_heretic2/svdcmp.c b/tools/quake2/qdata_heretic2/svdcmp.c
deleted file mode 100644 (file)
index 14865af..0000000
+++ /dev/null
@@ -1,487 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-
-static double at,bt,ct;
-#define PYTHAG( a,b ) ( ( at = fabs( a ) ) > ( bt = fabs( b ) ) ? \
-                                               ( ct = bt / at,at * sqrt( 1.0 + ct * ct ) ) : ( bt ? ( ct = at / bt,bt * sqrt( 1.0 + ct * ct ) ) : 0.0 ) )
-
-static double maxarg1,maxarg2;
-#define MAX( a,b ) ( maxarg1 = ( a ),maxarg2 = ( b ),( maxarg1 ) > ( maxarg2 ) ? \
-                                        ( maxarg1 ) : ( maxarg2 ) )
-#define SIGN( a,b ) ( ( b ) >= 0.0 ? fabs( a ) : -fabs( a ) )
-
-void ntrerror( char *s ){
-       printf( "%s\n",s );
-       exit( 1 );
-}
-
-double *allocVect( int sz ){
-       double *ret;
-
-       ret = calloc( sizeof( double ), (size_t)sz );
-       return ret;
-}
-
-void freeVect( double *ret ){
-       free( ret );
-}
-
-double **allocMatrix( int r,int c ){
-       double **ret;
-
-       ret = calloc( sizeof( double ), (size_t)( r * c ) );
-       return ret;
-}
-
-void freeMatrix( double **ret,int r ){
-       free( ret );
-}
-
-void svdcmp( double** a, int m, int n, double* w, double** v ){
-       int flag,i,its,j,jj,k,l,nm;
-       double c,f,h,s,x,y,z;
-       double anorm = 0.0,g = 0.0,scale = 0.0;
-       double *rv1;
-       void nrerror();
-
-       if ( m < n ) {
-               ntrerror( "SVDCMP: You must augment A with extra zero rows" );
-       }
-       rv1 = allocVect( n );
-       for ( i = 1; i <= n; i++ ) {
-               l = i + 1;
-               rv1[i] = scale * g;
-               g = s = scale = 0.0;
-               if ( i <= m ) {
-                       for ( k = i; k <= m; k++ ) scale += fabs( a[k][i] );
-                       if ( scale ) {
-                               for ( k = i; k <= m; k++ ) {
-                                       a[k][i] /= scale;
-                                       s += a[k][i] * a[k][i];
-                               }
-                               f = a[i][i];
-                               g = -SIGN( sqrt( s ),f );
-                               h = f * g - s;
-                               a[i][i] = f - g;
-                               if ( i != n ) {
-                                       for ( j = l; j <= n; j++ ) {
-                                               for ( s = 0.0,k = i; k <= m; k++ ) s += a[k][i] * a[k][j];
-                                               f = s / h;
-                                               for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i];
-                                       }
-                               }
-                               for ( k = i; k <= m; k++ ) a[k][i] *= scale;
-                       }
-               }
-               w[i] = scale * g;
-               g = s = scale = 0.0;
-               if ( i <= m && i != n ) {
-                       for ( k = l; k <= n; k++ ) scale += fabs( a[i][k] );
-                       if ( scale ) {
-                               for ( k = l; k <= n; k++ ) {
-                                       a[i][k] /= scale;
-                                       s += a[i][k] * a[i][k];
-                               }
-                               f = a[i][l];
-                               g = -SIGN( sqrt( s ),f );
-                               h = f * g - s;
-                               a[i][l] = f - g;
-                               for ( k = l; k <= n; k++ ) rv1[k] = a[i][k] / h;
-                               if ( i != m ) {
-                                       for ( j = l; j <= m; j++ ) {
-                                               for ( s = 0.0,k = l; k <= n; k++ ) s += a[j][k] * a[i][k];
-                                               for ( k = l; k <= n; k++ ) a[j][k] += s * rv1[k];
-                                       }
-                               }
-                               for ( k = l; k <= n; k++ ) a[i][k] *= scale;
-                       }
-               }
-               anorm = MAX( anorm,( fabs( w[i] ) + fabs( rv1[i] ) ) );
-       }
-       for ( i = n; i >= 1; i-- ) {
-               if ( i < n ) {
-                       if ( g ) {
-                               for ( j = l; j <= n; j++ )
-                                       v[j][i] = ( a[i][j] / a[i][l] ) / g;
-                               for ( j = l; j <= n; j++ ) {
-                                       for ( s = 0.0,k = l; k <= n; k++ ) s += a[i][k] * v[k][j];
-                                       for ( k = l; k <= n; k++ ) v[k][j] += s * v[k][i];
-                               }
-                       }
-                       for ( j = l; j <= n; j++ ) v[i][j] = v[j][i] = 0.0;
-               }
-               v[i][i] = 1.0;
-               g = rv1[i];
-               l = i;
-       }
-       for ( i = n; i >= 1; i-- ) {
-               l = i + 1;
-               g = w[i];
-               if ( i < n ) {
-                       for ( j = l; j <= n; j++ ) a[i][j] = 0.0;
-               }
-               if ( g ) {
-                       g = 1.0 / g;
-                       if ( i != n ) {
-                               for ( j = l; j <= n; j++ ) {
-                                       for ( s = 0.0,k = l; k <= m; k++ ) s += a[k][i] * a[k][j];
-                                       f = ( s / a[i][i] ) * g;
-                                       for ( k = i; k <= m; k++ ) a[k][j] += f * a[k][i];
-                               }
-                       }
-                       for ( j = i; j <= m; j++ ) a[j][i] *= g;
-               }
-               else {
-                       for ( j = i; j <= m; j++ ) a[j][i] = 0.0;
-               }
-               ++a[i][i];
-       }
-       for ( k = n; k >= 1; k-- ) {
-               for ( its = 1; its <= 30; its++ ) {
-                       flag = 1;
-                       for ( l = k; l >= 1; l-- ) {
-                               nm = l - 1;
-                               if ( fabs( rv1[l] ) + anorm == anorm ) {
-                                       flag = 0;
-                                       break;
-                               }
-                               if ( fabs( w[nm] ) + anorm == anorm ) {
-                                       break;
-                               }
-                       }
-                       if ( flag ) {
-                               c = 0.0;
-                               s = 1.0;
-                               for ( i = l; i <= k; i++ ) {
-                                       f = s * rv1[i];
-                                       if ( fabs( f ) + anorm != anorm ) {
-                                               g = w[i];
-                                               h = PYTHAG( f,g );
-                                               w[i] = h;
-                                               h = 1.0 / h;
-                                               c = g * h;
-                                               s = ( -f * h );
-                                               for ( j = 1; j <= m; j++ ) {
-                                                       y = a[j][nm];
-                                                       z = a[j][i];
-                                                       a[j][nm] = y * c + z * s;
-                                                       a[j][i] = z * c - y * s;
-                                               }
-                                       }
-                               }
-                       }
-                       z = w[k];
-                       if ( l == k ) {
-                               if ( z < 0.0 ) {
-                                       w[k] = -z;
-                                       for ( j = 1; j <= n; j++ ) v[j][k] = ( -v[j][k] );
-                               }
-                               break;
-                       }
-                       if ( its == 30 ) {
-                               ntrerror( "No convergence in 30 SVDCMP iterations" );
-                       }
-                       x = w[l];
-                       nm = k - 1;
-                       y = w[nm];
-                       g = rv1[nm];
-                       h = rv1[k];
-                       f = ( ( y - z ) * ( y + z ) + ( g - h ) * ( g + h ) ) / ( 2.0 * h * y );
-                       g = PYTHAG( f,1.0 );
-                       f = ( ( x - z ) * ( x + z ) + h * ( ( y / ( f + SIGN( g,f ) ) ) - h ) ) / x;
-                       c = s = 1.0;
-                       for ( j = l; j <= nm; j++ ) {
-                               i = j + 1;
-                               g = rv1[i];
-                               y = w[i];
-                               h = s * g;
-                               g = c * g;
-                               z = PYTHAG( f,h );
-                               rv1[j] = z;
-                               c = f / z;
-                               s = h / z;
-                               f = x * c + g * s;
-                               g = g * c - x * s;
-                               h = y * s;
-                               y = y * c;
-                               for ( jj = 1; jj <= n; jj++ ) {
-                                       x = v[jj][j];
-                                       z = v[jj][i];
-                                       v[jj][j] = x * c + z * s;
-                                       v[jj][i] = z * c - x * s;
-                               }
-                               z = PYTHAG( f,h );
-                               w[j] = z;
-                               if ( z ) {
-                                       z = 1.0 / z;
-                                       c = f * z;
-                                       s = h * z;
-                               }
-                               f = ( c * g ) + ( s * y );
-                               x = ( c * y ) - ( s * g );
-                               for ( jj = 1; jj <= m; jj++ ) {
-                                       y = a[jj][j];
-                                       z = a[jj][i];
-                                       a[jj][j] = y * c + z * s;
-                                       a[jj][i] = z * c - y * s;
-                               }
-                       }
-                       rv1[l] = 0.0;
-                       rv1[k] = f;
-                       w[k] = x;
-               }
-       }
-       freeVect( rv1 );
-}
-
-
-
-void svbksb( double** u, double* w, double** v,int m, int n, double* b, double* x ){
-       int jj,j,i;
-       double s,*tmp;
-       tmp = allocVect( n );
-       for ( j = 1; j <= n; j++ )
-       {
-               s = 0.0;
-               if ( w[j] ) {
-                       for ( i = 1; i <= m; i++ )
-                               s += u[i][j] * b[i];
-                       s /= w[j];
-               }
-               tmp[j] = s;
-       }
-       for ( j = 1; j <= n; j++ )
-       {
-               s = 0.0;
-               for ( jj = 1; jj <= n; jj++ )
-                       s += v[j][jj] * tmp[jj];
-               x[j] = s;
-       }
-       freeVect( tmp );
-}
-
-#undef SIGN
-#undef MAX
-#undef PYTHAG
-
-
-#if 1
-void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){
-       int usedfs;
-       int *remap;
-       int i,j;
-       double **da;
-       double **v;
-       double *w;
-       int DOFerr;
-       float mx;
-       int bestat;
-
-       if ( nframes > framesize ) {
-               usedfs = nframes;
-       }
-       else{
-               usedfs = framesize;
-       }
-
-       da = allocMatrix( usedfs,nframes );
-       v = allocMatrix( nframes,nframes );
-       w = allocVect( nframes );
-
-       DOFerr = 0; //false
-       for ( i = 0; i < nframes; i++ )
-       {
-               for ( j = 0; j < framesize; j++ )
-                       da[j + 1][i + 1] = a[i * framesize + j];
-               for (; j < usedfs; j++ )
-                       da[j + 1][i + 1] = 0.0;
-       }
-
-       svdcmp( da,usedfs,nframes,w,v );
-
-       remap = calloc( sizeof( int ), (size_t)nframes );
-
-
-       for ( i = 0; i < nframes; i++ )
-               remap[i] = -1;
-       for ( j = 0; j < compressedsize; j++ )
-       {
-               mx = -1.0f;
-               for ( i = 0; i < nframes; i++ )
-               {
-                       if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) {
-                               mx = (float) fabs( w[i + 1] );
-                               bestat = i;
-                       }
-               }
-
-               if ( mx > 0 ) {
-                       remap[bestat] = j;
-               }
-               else
-               {
-                       DOFerr = 1; //true
-               }
-       }
-
-       if ( DOFerr ) {
-               printf( "Warning:  To many degrees of freedom!  File size may increase\n" );
-
-               for ( i = 0; i < compressedsize; i++ )
-               {
-                       values[i] = 0;
-                       for ( j = 0; j < framesize; j++ )
-                               res[i * framesize + j] = 0;
-               }
-       }
-
-       for ( i = 0; i < nframes; i++ )
-       {
-               if ( remap[i] < 0 ) {
-                       w[i + 1] = 0.0;
-               }
-               else
-               {
-                       values[remap[i]] = (float) w[i + 1];
-                       for ( j = 0; j < framesize; j++ )
-                               res[remap[i] * framesize + j] = (float) da[j + 1][i + 1];
-               }
-       }
-       freeVect( w );
-       freeMatrix( v,nframes );
-       freeMatrix( da,framesize );
-       free( remap );
-}
-
-#else
-
-void DOsvd( float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize ){
-       int *remap;
-       int i,j;
-       int nrows;
-       nrows = nframes;
-       if ( nrows < framesize ) {
-               nrows = framesize;
-       }
-       double **da = allocMatrix( nrows,framesize );
-       double **v = allocMatrix( framesize,framesize );
-       double *w = allocVect( framesize );
-       float mx;
-       int bestat;
-
-       for ( j = 0; j < framesize; j++ )
-       {
-               for ( i = 0; i < nframes; i++ )
-                       da[j + 1][i + 1] = a[i * framesize + j];
-               for (; i < nrows; i++ )
-                       da[j + 1][i + 1] = 0.0;
-       }
-
-       svdcmp( da,nrows,framesize,w,v );
-
-       remap = new int[framesize];
-
-
-       for ( i = 0; i < framesize; i++ )
-               remap[i] = -1;
-       for ( j = 0; j < compressedsize; j++ )
-       {
-               mx = -1.0f;
-               for ( i = 0; i < framesize; i++ )
-               {
-                       if ( remap[i] < 0 && fabs( w[i + 1] ) > mx ) {
-                               mx = fabs( w[i + 1] );
-                               bestat = i;
-                       }
-               }
-               assert( mx > -.5f );
-               remap[bestat] = j;
-       }
-       // josh **DO NOT** put your dof>nframes mod here
-       for ( i = 0; i < framesize; i++ )
-       {
-               if ( remap[i] < 0 ) {
-                       w[i + 1] = 0.0;
-               }
-               else
-               {
-                       values[remap[i]] = w[i + 1];
-                       for ( j = 0; j < framesize; j++ )
-                               res[remap[i] * framesize + j] = v[j + 1][i + 1];
-               }
-       }
-       freeVect( w );
-       freeMatrix( v,framesize );
-       freeMatrix( da,nrows );
-       delete[] remap;
-}
-
-#endif
-
-void DOsvdPlane( float *pnts,int npnts,float *n,float *base ){
-       int i,j;
-       double **da = allocMatrix( npnts,3 );
-       double **v = allocMatrix( 3,3 );
-       double *w = allocVect( 3 );
-       float mn = 1E30f;
-       int bestat;
-
-
-       assert( npnts >= 3 );
-       base[0] = pnts[0];
-       base[1] = pnts[1];
-       base[2] = pnts[2];
-       for ( i = 1; i < npnts; i++ )
-       {
-               for ( j = 0; j < 3; j++ )
-                       base[j] += pnts[i * 3 + j];
-       }
-       base[0] /= (float)( npnts );
-       base[1] /= (float)( npnts );
-       base[2] /= (float)( npnts );
-
-       for ( i = 0; i < 3; i++ )
-       {
-               for ( j = 0; j < npnts; j++ )
-                       da[j + 1][i + 1] = pnts[j * 3 + i] - base[i];
-       }
-
-       svdcmp( da,npnts,3,w,v );
-       for ( i = 0; i < 3; i++ )
-       {
-               if ( fabs( w[i + 1] ) < mn ) {
-                       mn = (float) fabs( w[i + 1] );
-                       bestat = i;
-               }
-       }
-       n[0] = (float) v[1][bestat + 1];
-       n[1] = (float) v[2][bestat + 1];
-       n[2] = (float) v[3][bestat + 1];
-       freeVect( w );
-       freeMatrix( v,3 );
-       freeMatrix( da,npnts );
-}
diff --git a/tools/quake2/qdata_heretic2/tables.c b/tools/quake2/qdata_heretic2/tables.c
deleted file mode 100644 (file)
index ad86c1e..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qdata.h"
-
-/*
-   =============================================================================
-
-   ALPHALIGHT GENERATION
-
-   Find alphamap values that best match modulated lightmap values
-
-   This isn't used anymore, but I'm keeping it around...
-   =============================================================================
- */
-
-unsigned short alphamap[32 * 32 * 32];
-unsigned char inverse16to8table[65536];
-
-/*
-   static int FindNearestColor( unsigned int color )
-   {
-    int i;
-    int closest_so_far = 0;
-    float closest_distance_so_far = 100000000;
-    float d;
-    float r[2], g[2], b[2];
-
-    // incoming color is assumed to be in 0xRRGGBB format
-    r[0] = ( color & 31 ) << 3;
-    g[0] = ( ( color >> 5 ) & 63 ) << 2;
-    b[0] = ( ( color >> 11 ) & 31 ) << 3;
-
-    for ( i = 0; i < 256; i++ )
-    {
-        r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
-        g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
-        b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
-
-        d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
-            ( g[1] - g[0] ) * ( g[1] - g[0] ) +
-            ( b[1] - b[0] ) * ( b[1] - b[0] );
-
-        if ( d < closest_distance_so_far )
-        {
-            closest_distance_so_far = d;
-            closest_so_far = i;
-        }
-    }
-
-    return closest_so_far;
-   }
- */
-
-extern byte BestColor( int, int, int, int, int );
-
-void Inverse16_BuildTable( void ){
-       int i;
-
-       /*
-       ** create the 16-to-8 table
-       */
-       for ( i = 0; i < 65536; i++ )
-       {
-               int r = i & 31;
-               int g = ( i >> 5 ) & 63;
-               int b = ( i >> 11 ) & 31;
-
-               r <<= 3;
-               g <<= 2;
-               b <<= 3;
-
-               inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
-       }
-}
-
-void Alphalight_Thread( int i ){
-       int j;
-       float r, g, b;
-       float mr, mg, mb, ma;
-       float distortion, bestdistortion;
-       float v;
-
-       r = ( i >> 10 ) * ( 1.0 / 16 );
-       g = ( ( i >> 5 ) & 31 )  * ( 1.0 / 16 );
-       b = ( i & 31 ) * ( 1.0 / 16 );
-
-       bestdistortion = 999999;
-       for ( j = 0 ; j < 16 * 16 * 16 * 16 ; j++ )
-       {
-               mr = ( j >> 12 ) * ( 1.0 / 16 );
-               mg = ( ( j >> 8 ) & 15 ) * ( 1.0 / 16 );
-               mb = ( ( j >> 4 ) & 15 ) * ( 1.0 / 16 );
-               ma = ( j & 15 ) * ( 1.0 / 16 );
-
-               v = r * 0.5 - ( mr * ma + 0.5 * ( 1.0 - ma ) );
-               distortion = v * v;
-               v = g * 0.5 - ( mg * ma + 0.5 * ( 1.0 - ma ) );
-               distortion += v * v;
-               v = b * 0.5 - ( mb * ma + 0.5 * ( 1.0 - ma ) );
-               distortion += v * v;
-
-               distortion *= 1.0 + ma * 4;
-
-               if ( distortion < bestdistortion ) {
-                       bestdistortion = distortion;
-                       alphamap[i] = j;
-               }
-       }
-}
-
-void Cmd_Alphalight( void ){
-       char savename[1024];
-
-       GetScriptToken( false );
-
-       if ( g_release ) {
-               ReleaseFile( token );
-               return;
-       }
-
-       sprintf( savename, "%s%s", gamedir, token );
-       printf( "Building alphalight table...\n" );
-
-       RunThreadsOnIndividual( 32 * 32 * 32, true, Alphalight_Thread );
-
-       SaveFile( savename, (byte *)alphamap, sizeof( alphamap ) );
-}
-
-
-void Cmd_Inverse16Table( void ){
-       char savename[1024];
-
-       if ( g_release ) {
-               sprintf( savename, "pics/16to8.dat" );
-               ReleaseFile( savename );
-               return;
-       }
-
-       sprintf( savename, "%spics/16to8.dat", gamedir );
-       printf( "Building inverse 16-to-8 table...\n" );
-
-       Inverse16_BuildTable();
-
-       SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
-}
diff --git a/tools/quake2/qdata_heretic2/tmix.c b/tools/quake2/qdata_heretic2/tmix.c
deleted file mode 100644 (file)
index 58cc369..0000000
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-#include "qdata.h"
-#include "flex.h"
-
-#define     MAXFILES    2048
-
-typedef struct
-{
-       int x;
-       int y;
-       int w;
-       int h;
-       int cw;
-       int ch;
-       int rw;
-       int index;
-       int depth;
-       int col;
-       int baseline;
-       char name[128];
-} Coords;
-
-int filenum;
-int valid;
-Coords in[MAXFILES];
-Coords out;
-char outscript[256];
-char sourcedir[256];
-char outusage[256];
-char root[32];
-
-int destsize = 0;
-byte            *pixels = NULL;             // Buffer to load image
-long            *outpixels = NULL;          // Buffer to store combined textures
-long            *usagemap = NULL;           // Buffer of usage map
-void            *bmptemp = NULL;            // Buffer of usage map
-byte            *map = NULL;
-
-int xcharsize;
-int ycharsize;
-int dosort = 0;
-int missed = 0;
-int overlap = 0;
-int nobaseline = 0;
-int percent;
-
-//////////////////////////////////////////////////
-// Setting the char based usage map                            //
-//////////////////////////////////////////////////
-
-byte    TryPlace( Coords *coord ){
-       int x, y;
-       byte entry = 0;
-       byte    *mapitem;
-
-       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
-
-       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
-       {
-               for ( x = 0; x < coord->cw; x++ )
-               {
-                       if ( entry |= *mapitem++ & 8 ) {
-                               return( entry );
-                       }
-               }
-       }
-       return( entry );
-}
-
-void    SetMap( Coords *coord ){
-       int x, y;
-       byte    *mapitem;
-
-       mapitem = map + ( coord->x / xcharsize ) + ( ( coord->y / ycharsize ) * out.cw );
-
-       for ( y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw )
-               for ( x = 0; x < coord->cw; x++ )
-                       *mapitem++ |= 8;
-}
-
-//////////////////////////////////////////////////
-// Setting the pixel based usage map                   //
-//////////////////////////////////////////////////
-
-void    CheckOverlap( Coords *coord ){
-       int x;
-       int y;
-       long        *dest;
-
-       x = coord->x;
-       y = coord->y;
-
-       dest = (long *)( usagemap + x + ( y * out.w ) );
-
-       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
-       {
-               for ( x = 0; x < coord->w; x++ )
-               {
-                       if ( *dest++ ) {
-                               overlap++;
-                               return;
-                       }
-               }
-       }
-}
-
-void    SetUsageMap( Coords *coord ){
-       int x;
-       int y;
-       long        *dest;
-
-       x = coord->x;
-       y = coord->y;
-
-       dest = (long *)( usagemap + x + ( y * out.w ) );
-
-       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
-       {
-               for ( x = 0; x < coord->w; x++ )
-               {
-                       *dest++ = coord->col;
-               }
-       }
-}
-
-//////////////////////////////////////////////////
-// Flips the BMP image to the correct way up   //
-//////////////////////////////////////////////////
-
-void    CopyLine( byte *dest, byte *src, int size ){
-       int x;
-
-       for ( x = 0; x < size; x++ )
-               *dest++ = *src++;
-}
-
-/****************************************************/
-/* Printing headers etc                                                                */
-/****************************************************/
-
-void RemoveLeading( char *name ){
-       int i;
-       char temp[128];
-
-       for ( i = strlen( name ) - 1; i > 0; i-- )
-       {
-               if ( ( name[i] == '\\' ) || ( name[i] == '/' ) ) {
-                       strcpy( temp, name + i + 1 );
-                       strcpy( name, temp );
-                       return;
-               }
-       }
-}
-
-void RemoveExt( char *name ){
-       while ( ( *name != '.' ) && *name )
-               name++;
-       *name = 0;
-}
-
-/****************************************************/
-/* Misc calcualtions                                                           */
-/****************************************************/
-
-int TotalArea(){
-       int i;
-       int total = 0;
-
-       for ( i = 0; i < ( filenum + 2 ); i++ )
-               total += in[i].w * in[i].h;
-
-       return( total );
-}
-
-/****************************************************/
-/* Setup and checking of all info                                      */
-/****************************************************/
-
-void    InitVars(){
-       filenum = 0;
-       valid = 0;
-       dosort = 0;
-       missed = 0;
-       overlap = 0;
-       nobaseline = 0;
-
-       memset( outscript, 0, sizeof( outscript ) );
-       memset( outscript, 0, sizeof( sourcedir ) );
-       memset( outscript, 0, sizeof( outusage ) );
-       memset( outscript, 0, sizeof( root ) );
-
-       memset( in, 0, sizeof( in ) );
-       memset( &out, 0, sizeof( out ) );
-}
-void Cleanup(){
-       if ( pixels ) {
-               free( pixels );
-       }
-       if ( usagemap ) {
-               free( usagemap );
-       }
-       if ( outpixels ) {
-               free( outpixels );
-       }
-       if ( bmptemp ) {
-               free( bmptemp );
-       }
-       if ( map ) {
-               free( map );
-       }
-}
-
-typedef struct glxy_s
-{
-       float xl, yt, xr, yb;
-       int w, h, baseline;
-} glxy_t;
-
-int SaveScript( char *name ){
-       FILE        *fp;
-       int i, j;
-       glxy_t buff;
-
-       if ( fp = fopen( name, "wb" ) ) {
-               for ( j = 0; j < filenum; j++ )
-               {
-                       for ( i = 0; i < filenum; i++ )
-                       {
-                               if ( in[i].index == j ) {
-                                       if ( in[i].depth ) {
-                                               buff.xl = (float)in[i].x / (float)out.w;
-                                               buff.yt = (float)in[i].y / (float)out.h;
-                                               buff.xr = ( (float)in[i].w + (float)in[i].x ) / (float)out.w;
-                                               buff.yb = ( (float)in[i].h + (float)in[i].y ) / (float)out.h;
-                                               buff.w = in[i].w;
-                                               buff.h = in[i].h;
-                                               buff.baseline = in[i].baseline;
-                                       }
-                                       else
-                                       {
-                                               memset( &buff, 0, sizeof( glxy_t ) );
-                                       }
-                                       fwrite( &buff, 1, sizeof( glxy_t ), fp );
-                                       i = filenum;
-                               }
-                       }
-               }
-               fclose( fp );
-               return( true );
-       }
-       else{
-               return( false );
-       }
-}
-
-int     GetScriptInfo( char *name ){
-       FILE        *fp;
-       char buffer[256];
-       char tempbuff[256];
-       char delims[] = {" \t,\n"};
-
-       printf( "Opening script file %s.\n", name );
-
-       if ( fp = fopen( name, "r" ) ) {
-               while ( fgets( buffer, 256, fp ) )
-               {
-                       if ( strncmp( buffer, "//", 2 ) && strncmp( buffer, "\n", 1 ) ) {
-                               strupr( buffer );
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "OUTPUT" ) == 0 ) {
-                                       strcpy( out.name, strtok( NULL, delims ) );
-                                       strlwr( out.name );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "SOURCEDIR" ) == 0 ) {
-                                       strcpy( tempbuff, strtok( NULL, delims ) );
-                                       strcpy( sourcedir, ExpandPathAndArchive( tempbuff ) );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "DOSORT" ) == 0 ) {
-                                       dosort = 1;
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "XCHARSIZE" ) == 0 ) {
-                                       xcharsize = strtol( strtok( NULL, delims ), NULL, 0 );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "YCHARSIZE" ) == 0 ) {
-                                       ycharsize = strtol( strtok( NULL, delims ), NULL, 0 );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "OUTSCRIPT" ) == 0 ) {
-                                       strcpy( outscript, strtok( NULL, delims ) );
-                                       strlwr( outscript );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "OUTUSAGE" ) == 0 ) {
-                                       strcpy( outusage, strtok( NULL, delims ) );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "POS" ) == 0 ) {
-                                       out.w = strtol( strtok( NULL, delims ), NULL, 0 );
-                                       out.h = strtol( strtok( NULL, delims ), NULL, 0 );
-                               }
-
-                               strcpy( tempbuff, buffer );
-                               if ( strcmp( strtok( tempbuff, delims ), "FILE" ) == 0 ) {
-                                       strcpy( in[filenum].name, strtok( NULL, delims ) );
-                                       in[filenum].x = strtol( strtok( NULL, delims ), NULL, 0 );
-                                       in[filenum].y = strtol( strtok( NULL, delims ), NULL, 0 );
-                                       in[filenum].col = strtol( strtok( NULL, delims ), NULL, 0 );
-                                       filenum++;
-                               }
-                       }
-               }
-               fclose( fp );
-               return( true );
-       }
-       else
-       {
-               printf( "ERROR : Could not open script file.\n" );
-               return( false );
-       }
-}
-
-int CheckVars(){
-       int i;
-
-       if ( out.name[0] == 0 ) {
-               printf( "ERROR : No output name specified.\n" );
-               return( false );
-       }
-       if ( ( out.w <= 0 ) || ( out.h <= 0 ) ) {
-               printf( "ERROR : Invalid VRAM coordinates.\n" );
-               return( false );
-       }
-       if ( filenum == 0 ) {
-               printf( "ERROR : No input files specified.\n" );
-               return( false );
-       }
-       for ( i = 0; i < filenum; i++ )
-               if ( in[i].name[0] == 0 ) {
-                       printf( "ERROR : Input filename invalid.\n" );
-                       return( false );
-               }
-       return( true );
-}
-
-// Makes sure texture is totally within the output area
-
-int CheckCoords( Coords *coord ){
-       if ( ( coord->x + coord->w ) > out.w ) {
-               return( false );
-       }
-       if ( ( coord->y + coord->h ) > out.h ) {
-               return( false );
-       }
-
-       return( true );
-}
-// Gets the width, height, palette width and palette height of each BMP file
-
-int     GetFileDimensions(){
-       int i;
-       int width, height;
-       char name[128];
-
-       for ( i = 0; i < filenum; i++ )
-       {
-               in[i].index = i;
-
-               strcpy( name, sourcedir );
-               strcat( name, in[i].name );
-               printf( "Getting file dimensions, file : %s        \r", in[i].name );
-               if ( FileExists( name ) ) {
-                       LoadAnyImage( name, NULL, NULL, &width, &height );
-                       in[i].depth = 32;
-                       in[i].rw = width;
-                       in[i].w = width;                        // makes it width in
-                       in[i].h = height;
-                       in[i].cw = ( in[i].w + ( xcharsize - 1 ) ) / xcharsize;
-                       in[i].ch = ( in[i].h + ( ycharsize - 1 ) ) / ycharsize;
-
-                       if ( !CheckCoords( &in[i] ) && ( in[i].x >= 0 ) ) {
-                               printf( "Error : texture %s out of bounds.\n", in[i].name );
-                               return( false );
-                       }
-                       valid++;
-               }
-               else
-               {
-                       in[i].depth = 0;
-                       in[i].x = -1;
-                       in[i].y = -1;
-                       in[i].w = 0;
-                       in[i].h = 0;
-               }
-       }
-       printf( "\n\n" );
-       return( true );
-}
-
-// Sorts files into order for optimal space finding
-// Fixed position ones first, followed by the others in descending size
-// The theory being that it is easier to find space for smaller textures.
-// size = (width + height)
-// For space finding it is easier to place a 32x32 than a 128x2
-
-#define WEIGHT  0x8000
-
-void    Swap( Coords *a, Coords *b ){
-       Coords c;
-
-       c = *a;
-       *a = *b;
-       *b = c;
-}
-
-void    SortInNames(){
-       int i, j;
-       int largest, largcount;
-       int size;
-
-       printf( "Sorting filenames by size.\n\n" );
-
-       for ( j = 0; j < filenum; j++ )
-       {
-               largest = -1;
-               largcount = -1;
-
-               for ( i = j; i < filenum; i++ )
-               {
-                       if ( in[i].depth ) {
-                               size = in[i].w + in[i].h;
-
-                               if ( ( in[i].x < 0 ) && ( size > largest ) ) {
-                                       largcount = i;
-                                       largest = size;
-                               }
-                       }
-               }
-               if ( ( largcount >= 0 ) && ( largcount != j ) ) {
-                       Swap( &in[j], &in[largcount] );
-               }
-       }
-}
-
-int SetVars( char *name ){
-       if ( !GetScriptInfo( name ) ) {
-               return( false );
-       }
-
-       if ( !CheckVars() ) {
-               return( false );
-       }
-
-       destsize = out.w * out.h;
-
-       out.cw = out.w / xcharsize;
-       out.ch = out.h / ycharsize;
-
-       if ( ( usagemap = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
-               return( false );
-       }
-       if ( ( outpixels = (long *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
-               return( false );
-       }
-       if ( ( bmptemp = (void *)SafeMalloc( destsize * 4, "" ) ) == NULL ) {
-               return( false );
-       }
-       if ( ( map = (byte *)SafeMalloc( destsize / ( xcharsize * ycharsize ), "" ) ) == NULL ) {
-               return( false );
-       }
-
-       if ( GetFileDimensions() == false ) {
-               return( false );
-       }
-
-       if ( dosort ) {
-               SortInNames();
-       }
-
-       return( true );
-}
-/****************************************************/
-/* Actual copying routines                                                     */
-/****************************************************/
-
-int FindCoords( Coords *coord ){
-       int tx, ty;
-
-       if ( coord->x >= 0 ) {
-               SetMap( coord );
-               return( true );
-       }
-       else
-       {
-               for ( ty = 0; ty < out.ch; ty++ )
-               {
-                       for ( tx = 0; tx < out.cw; tx++ )
-                       {
-                               coord->x = ( tx * xcharsize );
-                               coord->y = ( ty * ycharsize );
-
-                               if ( CheckCoords( coord ) && !TryPlace( coord ) ) {
-                                       SetMap( coord );
-                                       return( true );
-                               }
-                       }
-               }
-       }
-       coord->x = -1;
-       coord->y = -1;
-
-       return( false );
-}
-
-void CheckBaseline( int i ){
-       int y;
-       long    *pix;
-
-       in[i].baseline = -1;
-       pix = (long *)pixels;
-
-       for ( y = 0; y < in[i].h; y++, pix += in[i].w )
-       {
-               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
-                       in[i].baseline = y;
-                       break;
-               }
-       }
-       pix = (long *)pixels;
-       for ( y = 0; y < in[i].w * in[i].h; y++, pix++ )
-       {
-               if ( ( *pix & 0x00ffffff ) == 0x00ff00ff ) {
-                       *pix = 0;
-               }
-       }
-
-       if ( in[i].baseline == -1 ) {
-               printf( "\nERROR : %s has no baseline\n", in[i].name );
-               nobaseline++;
-       }
-}
-
-void    CopyToMain32( Coords *coord ){
-       int x;
-       int y;
-       long        *source;
-       long        *dest;
-
-       x = coord->x;
-       y = coord->y;
-
-       source = (long *)pixels;
-       dest = (long *)( outpixels + x + ( y * out.w ) );
-
-       for ( y = 0; y < coord->h; y++, dest += out.w - coord->w )
-       {
-               for ( x = 0; x < coord->w; x++ )
-               {
-                       *dest++ = *source++;
-               }
-       }
-}
-
-void CreateMain(){
-       int i, count;
-       int width, height;
-       char name[128];
-
-       for ( i = 0, count = 0; i < filenum; i++ )
-       {
-               if ( in[i].depth ) {
-                       printf( "\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline );
-                       count++;
-                       if ( !FindCoords( &in[i] ) ) {
-                               missed++;
-                       }
-                       else
-                       {
-                               strcpy( name, sourcedir );
-                               strcat( name, in[i].name );
-                               LoadAnyImage( name, &pixels, NULL, &width, &height );
-                               CheckBaseline( i );
-                               CheckOverlap( &in[i] );
-                               CopyToMain32( &in[i] );
-                               SetUsageMap( &in[i] );
-                       }
-               }
-       }
-}
-
-void Cmd_TextureMix(){
-       miptex32_t      *qtex32;
-       char filename[1024];
-       int size;
-
-       InitVars();
-
-       GetScriptToken( false );
-
-       strcpy( root, token );
-       RemoveExt( root );
-       RemoveLeading( root );
-
-       strcpy( filename, ExpandPathAndArchive( token ) );
-       if ( SetVars( filename ) ) {
-               // Create combined texture
-               percent = ( ( TotalArea() * 100 ) / ( out.w * out.h ) );
-               printf( "Total area consumed : %d%%\n", percent );
-               printf( "Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize );
-               CreateMain();
-
-               // Save image as m32
-               sprintf( filename, "%spics/misc/%s.m32", gamedir, out.name );
-               qtex32 = CreateMip32( (unsigned *)outpixels, out.w, out.h, &size, false );
-
-               qtex32->contents = 0;
-               qtex32->value = 0;
-               qtex32->scale_x = 1.0;
-               qtex32->scale_y = 1.0;
-               sprintf( qtex32->name, "misc/%s", out.name );
-
-               printf( "\n\nwriting %s\n", filename );
-               SaveFile( filename, (byte *)qtex32, size );
-               free( qtex32 );
-
-               // Save out script file
-               sprintf( filename, "%spics/misc/%s.fnt", gamedir, outscript );
-               printf( "Writing %s as script file\n", filename );
-               if ( !SaveScript( filename ) ) {
-                       printf( "Unable to save output script.\n" );
-               }
-       }
-       printf( "Everythings groovy.\n" );
-       Cleanup();
-}
-
-// end
diff --git a/tools/quake2/qdata_heretic2/video.c b/tools/quake2/qdata_heretic2/video.c
deleted file mode 100644 (file)
index 51bf462..0000000
+++ /dev/null
@@ -1,1154 +0,0 @@
-/*
-   Copyright (C) 1999-2007 id Software, Inc. and contributors.
-   For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-   This file is part of GtkRadiant.
-
-   GtkRadiant is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
-
-   GtkRadiant is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GtkRadiant; if not, write to the Free Software
-   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- */
-
-// To do
-
-// Sound error handling (when sound too short)
-// rle b4 huffing
-// adpcm encoding of sound
-
-#if 0
-#include "qdata.h"
-#include "flex.h"
-#include "fc.h"
-#include "adpcm.h"
-
-#define MIN_REPT    15
-#define MAX_REPT    0
-#define HUF_TOKENS  ( 256 + MAX_REPT )
-
-#define BLOCKSIZE   8
-
-#define M_PI        3.14159265358979323846  // matches value in gcc v2 math.h
-#define SQRT2       1.414213562
-
-typedef struct hnode_s
-{
-       int count;
-       qboolean used;
-       int children[2];
-} hnode_t;
-
-typedef struct
-{
-       int rate;
-       int width;
-       int channels;
-       int loopstart;
-       int samples;
-       int dataofs;                // chunk starts this many bytes from file start
-} wavinfo_t;
-
-// These weren`t picked out my ass....
-// They were defined at http://www.rahul.net/jfm/dct.html
-// However, I think he plucked them out of his ass.....
-
-float Quantise[BLOCKSIZE * BLOCKSIZE];
-
-float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
-{
-       16.0F / 16.0F, 11.0F / 16.0F, 10.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 51.0F / 16.0F, 61.0F / 16.0F,
-       12.0F / 16.0F, 13.0F / 16.0F, 14.0F / 16.0F, 19.0F / 16.0F, 26.0F / 16.0F, 58.0F / 16.0F, 60.0F / 16.0F, 55.0F / 16.0F,
-       14.0F / 16.0F, 13.0F / 16.0F, 16.0F / 16.0F, 24.0F / 16.0F, 40.0F / 16.0F, 57.0F / 16.0F, 69.0F / 16.0F, 56.0F / 16.0F,
-       14.0F / 16.0F, 17.0F / 16.0F, 22.0F / 16.0F, 29.0F / 16.0F, 51.0F / 16.0F, 87.0F / 16.0F, 80.0F / 16.0F, 62.0F / 16.0F,
-       18.0F / 16.0F, 22.0F / 16.0F, 37.0F / 16.0F, 56.0F / 16.0F, 68.0F / 16.0F,109.0F / 16.0F,103.0F / 16.0F, 77.0F / 16.0F,
-       24.0F / 16.0F, 35.0F / 16.0F, 55.0F / 16.0F, 64.0F / 16.0F, 81.0F / 16.0F,104.0F / 16.0F,113.0F / 16.0F, 92.0F / 16.0F,
-       49.0F / 16.0F, 64.0F / 16.0F, 78.0F / 16.0F, 87.0F / 16.0F,103.0F / 16.0F,121.0F / 16.0F,120.0F / 16.0F,101.0F / 16.0F,
-       72.0F / 16.0F, 92.0F / 16.0F, 95.0F / 16.0F, 98.0F / 16.0F,112.0F / 16.0F,100.0F / 16.0F,103.0F / 16.0F, 99.0F / 16.0F
-};
-
-int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
-{
-       0,
-       1,  8,
-       16,  9,  2,
-       3, 10, 17, 24,
-       32, 25, 18, 11,  4,
-       5, 12, 19, 26, 33, 40,
-       48, 41, 34, 27, 20, 13, 6,
-       7, 14, 21, 28, 35, 42, 49, 56,
-       57, 50, 43, 36, 29, 22, 15,
-       23, 30, 37, 44, 51, 58,
-       59, 52, 45, 38, 31,
-       39, 46, 53, 60,
-       61, 54, 47,
-       55, 62,
-       63
-};
-
-char base[32];
-
-byte            *soundtrack;
-
-byte scaled[256][HUF_TOKENS];
-unsigned int charbits1[256][HUF_TOKENS];
-int charbitscount1[256][HUF_TOKENS];
-hnode_t hnodes1[256][HUF_TOKENS * 2];
-int numhnodes1[256];
-int order0counts[256];
-int numhnodes;
-hnode_t hnodes[512];
-unsigned charbits[256];
-int charbitscount[256];
-
-CineHead_t cinehead;
-
-byte            *data_p;
-byte            *iff_end;
-byte            *last_chunk;
-byte            *iff_data;
-int iff_chunk_len;
-
-float dctbase[BLOCKSIZE][BLOCKSIZE];
-float red[BLOCKSIZE * BLOCKSIZE];
-float green[BLOCKSIZE * BLOCKSIZE];
-float blue[BLOCKSIZE * BLOCKSIZE];
-float temp[BLOCKSIZE * BLOCKSIZE];
-
-wavinfo_t wavinfo;
-adpcm_t adpcm;
-
-/*
-   ===============================================================================
-
-   WAV loading
-
-   ===============================================================================
- */
-
-/* Intel ADPCM step variation table */
-static int indexTable[16] =
-{
-       -1, -1, -1, -1, 2, 4, 6, 8,
-       -1, -1, -1, -1, 2, 4, 6, 8,
-};
-
-static int stepsizeTable[89] =
-{
-       7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
-       19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
-       50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
-       130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
-       337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
-       876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
-       2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
-       5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
-       15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
-#if 0
-static void adpcm_decoder( char *indata, short *outdata, int len, adpcm_state_t *state ){
-       signed char *inp;       /* Input buffer pointer */
-       short *outp;        /* output buffer pointer */
-       int sign;           /* Current adpcm sign bit */
-       int delta;          /* Current adpcm output value */
-       int step;           /* Stepsize */
-       int valpred;        /* Predicted value */
-       int vpdiff;         /* Current change to valpred */
-       int index;          /* Current step change index */
-       int inputbuffer;        /* place to keep next 4-bit value */
-       int bufferstep;     /* toggle between inputbuffer/input */
-
-       outp = outdata;
-       inp = (signed char *)indata;
-
-       valpred = state->valprev;
-       index = state->index;
-       step = stepsizeTable[index];
-
-       bufferstep = 0;
-
-       for (; len > 0; len-- )
-       {
-               /* Step 1 - get the delta value */
-               if ( bufferstep ) {
-                       delta = inputbuffer & 0xf;
-               }
-               else
-               {
-                       inputbuffer = *inp++;
-                       delta = ( inputbuffer >> 4 ) & 0xf;
-               }
-               bufferstep = !bufferstep;
-
-               /* Step 2 - Find new index value (for later) */
-               index += indexTable[delta];
-               if ( index < 0 ) {
-                       index = 0;
-               }
-               if ( index > 88 ) {
-                       index = 88;
-               }
-
-               /* Step 3 - Separate sign and magnitude */
-               sign = delta & 8;
-               delta = delta & 7;
-
-               /* Step 4 - Compute difference and new predicted value */
-               /*
-               ** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
-               ** in adpcm_coder.
-               */
-               vpdiff = step >> 3;
-               if ( delta & 4 ) {
-                       vpdiff += step;
-               }
-               if ( delta & 2 ) {
-                       vpdiff += step >> 1;
-               }
-               if ( delta & 1 ) {
-                       vpdiff += step >> 2;
-               }
-
-               if ( sign ) {
-                       valpred -= vpdiff;
-               }
-               else{
-                       valpred += vpdiff;
-               }
-
-               /* Step 5 - clamp output value */
-               if ( valpred > 32767 ) {
-                       valpred = 32767;
-               }
-               else if ( valpred < -32768 ) {
-                       valpred = -32768;
-               }
-
-               /* Step 6 - Update step value */
-               step = stepsizeTable[index];
-
-               /* Step 7 - Output value */
-               *outp++ = valpred;
-       }
-
-       state->valprev = valpred;
-       state->index = index;
-}
-#endif
-
-void adpcm_coder( short *inp, adpcm_t *adpcm ){
-       int val;                        /* Current input sample value */
-       int sign;                       /* Current adpcm sign bit */
-       int delta;                      /* Current adpcm output value */
-       int diff;                       /* Difference between val and valprev */
-       int step;                       /* Stepsize */
-       int valpred;                    /* Predicted output value */
-       int vpdiff;                     /* Current change to valpred */
-       int index;                      /* Current step change index */
-       int outputbuffer;               /* place to keep previous 4-bit value */
-       int bufferstep;                 /* toggle between outputbuffer/output */
-       adpcm_state_t   *state;
-       char            *outp;
-       int len;
-
-       state = &adpcm->state;
-       len = state->count;
-       outp = adpcm->adpcm;
-
-       valpred = state->in_valprev;
-       index = state->in_index;
-       step = stepsizeTable[index];
-
-       bufferstep = 1;
-       while ( len-- )
-       {
-               val = *inp++;
-
-               /* Step 1 - compute difference with previous value */
-               diff = val - valpred;
-               sign = ( diff < 0 ) ? 8 : 0;
-               if ( sign ) {
-                       diff = -diff;
-               }
-
-               /* Step 2 - Divide and clamp */
-               /* Note:
-               ** This code *approximately* computes:
-               **        delta = diff*4/step;
-               **        vpdiff = (delta+0.5)*step/4;
-               ** but in shift step bits are dropped. The net result of this is
-               ** that even if you have fast mul/div hardware you cannot put it to
-               ** good use since the fixup would be too expensive.
-               */
-               delta = 0;
-               vpdiff = ( step >> 3 );
-
-               if ( diff >= step ) {
-                       delta = 4;
-                       diff -= step;
-                       vpdiff += step;
-               }
-               step >>= 1;
-               if ( diff >= step ) {
-                       delta |= 2;
-                       diff -= step;
-                       vpdiff += step;
-               }
-               step >>= 1;
-               if ( diff >= step ) {
-                       delta |= 1;
-                       vpdiff += step;
-               }
-
-               /* Step 3 - Update previous value */
-               if ( sign ) {
-                       valpred -= vpdiff;
-               }
-               else{
-                       valpred += vpdiff;
-               }
-
-               /* Step 4 - Clamp previous value to 16 bits */
-               if ( valpred > 32767 ) {
-                       valpred = 32767;
-               }
-               else if ( valpred < -32768 ) {
-                       valpred = -32768;
-               }
-
-               /* Step 5 - Assemble value, update index and step values */
-               delta |= sign;
-
-               index += indexTable[delta];
-               if ( index < 0 ) {
-                       index = 0;
-               }
-               if ( index > 88 ) {
-                       index = 88;
-               }
-               step = stepsizeTable[index];
-
-               /* Step 6 - Output value */
-               if ( bufferstep ) {
-                       outputbuffer = ( delta << 4 ) & 0xf0;
-               }
-               else{
-                       *outp++ = ( delta & 0x0f ) | outputbuffer;
-               }
-
-               bufferstep = !bufferstep;
-       }
-
-       /* Output last step, if needed */
-       if ( !bufferstep ) {
-               *outp++ = outputbuffer;
-       }
-
-       state->out_valprev = valpred;
-       state->out_index = index;
-}
-
-void FindNextChunk( char *name ){
-       while ( 1 )
-       {
-               data_p = last_chunk;
-
-               if ( data_p >= iff_end ) {         // didn't find the chunk
-                       data_p = NULL;
-                       return;
-               }
-
-               data_p += 4;
-               iff_chunk_len = *(long *)data_p;
-               data_p += 4;
-               if ( iff_chunk_len < 0 ) {
-                       data_p = NULL;
-                       return;
-               }
-
-               data_p -= 8;
-               last_chunk = data_p + 8 + ( ( iff_chunk_len + 1 ) & ~1 );
-               if ( !strncmp( data_p, name, 4 ) ) {
-                       return;
-               }
-       }
-}
-
-void FindChunk( char *name ){
-       last_chunk = iff_data;
-       FindNextChunk( name );
-}
-
-void DumpChunks( void ){
-       char str[5];
-
-       str[4] = 0;
-       data_p = iff_data;
-       do
-       {
-               memcpy( str, data_p, 4 );
-               data_p += 4;
-               iff_chunk_len = *(long *)data_p;
-               data_p += 4;
-               printf( "0x%x : %s (%d)\n", (int)( data_p - 4 ), str, iff_chunk_len );
-               data_p += ( iff_chunk_len + 1 ) & ~1;
-       }
-       while ( data_p < iff_end );
-}
-
-/*
-   ============
-   GetWavinfo
-   ============
- */
-wavinfo_t GetWavinfo( char *name, byte *wav, int wavlength ){
-       wavinfo_t info;
-       int i;
-       int format;
-       int samples;
-
-       memset( &info, 0, sizeof( info ) );
-
-       if ( !wav ) {
-               return( info );
-       }
-
-       iff_data = wav;
-       iff_end = wav + wavlength;
-
-// find "RIFF" chunk
-       FindChunk( "RIFF" );
-       if ( !( data_p && !strncmp( data_p + 8, "WAVE", 4 ) ) ) {
-               printf( "Missing RIFF/WAVE chunks\n" );
-               return( info );
-       }
-
-// get "fmt " chunk
-       iff_data = data_p + 12;
-
-       FindChunk( "fmt " );
-       if ( !data_p ) {
-               printf( "Missing fmt chunk\n" );
-               return( info );
-       }
-       data_p += 8;
-       format = *(short *)data_p;
-       data_p += 2;
-       if ( format != 1 ) {
-               printf( "Microsoft PCM format only\n" );
-               return( info );
-       }
-
-       info.channels = *(short *)data_p;
-       data_p += 2;
-       info.rate = *(long *)data_p;
-       data_p += 4;
-       data_p += 6;
-       info.width = *(short *)data_p / 8;
-       data_p += 2;
-
-// get cue chunk
-       FindChunk( "cue " );
-       if ( data_p ) {
-               data_p += 32;
-               info.loopstart = *(long *)data_p;
-               data_p += 4;
-
-// if the next chunk is a LIST chunk, look for a cue length marker
-               FindNextChunk( "LIST" );
-               if ( data_p ) {
-// this is not a proper parse, but it works with cooledit...
-                       if ( !strncmp( data_p + 28, "mark", 4 ) ) {
-                               data_p += 24;
-                               i = *(long *)data_p;                    // samples in loop
-                               data_p += 4;
-                               info.samples = info.loopstart + i;
-                       }
-               }
-       }
-       else{
-               info.loopstart = -1;
-       }
-
-// find data chunk
-       FindChunk( "data" );
-       if ( !data_p ) {
-               printf( "Missing data chunk\n" );
-               return( info );
-       }
-
-       data_p += 4;
-       samples = *(long *)data_p;
-       data_p += 4;
-
-       if ( info.samples ) {
-               if ( samples < info.samples ) {
-                       Error( "Sound %s has a bad loop length", name );
-               }
-       }
-       else{
-               info.samples = samples;
-       }
-
-       info.dataofs = data_p - wav;
-       return( info );
-}
-
-// ==============
-// LoadSoundtrack
-// ==============
-
-void LoadSoundtrack(){
-       char name[1024];
-       FILE    *f;
-       int len;
-
-       soundtrack = NULL;
-       sprintf( name, "%svideo/%s/%s.wav", gamedir, base, base );
-       printf( "\nLoading sound    : %s\n", name );
-       f = fopen( name, "rb" );
-       if ( !f ) {
-               printf( "\nNo soundtrack for %s\n", base );
-               return;
-       }
-       len = Q_filelength( f );
-       soundtrack = SafeMalloc( len, "LoadSoundtrack" );
-       fread( soundtrack, 1, len, f );
-       fclose( f );
-
-       wavinfo = GetWavinfo( name, soundtrack, len );
-       adpcm.state.out_valprev = 0;
-       adpcm.state.out_index = 0;
-}
-
-// ==================
-// WriteSound
-// ==================
-
-int WriteSound( FILE *output, int frame, int numframes ){
-       int start, end;
-       int count;
-       int empty = 0;
-       int width;
-       char    *work;
-
-       width = wavinfo.width * wavinfo.channels;
-       start = ( ( frame * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;                // start sample
-       end = ( ( ( frame + numframes ) * wavinfo.rate / 14 ) + 31 ) & 0xffffffe0;    // end sample
-       count = end - start;
-
-       work = soundtrack + wavinfo.dataofs + ( start * width );
-       adpcm.state.count = count * wavinfo.channels;           // Number of samples
-       adpcm.state.in_valprev = adpcm.state.out_valprev;
-       adpcm.state.in_index = adpcm.state.out_index;
-       adpcm_coder( (short *)work, &adpcm );
-       WriteHeader( output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, ( adpcm.state.count / 2 ) + sizeof( adpcm_state_t ), (char *)&adpcm );
-       return( count / 2 );
-}
-// ==============================
-// Basic run length encoder
-// ==============================
-
-char *RLEZZ( char *in, char *out ){
-       int srun;
-       char count;
-       int idx = 0;
-
-       while ( idx < 64 )
-       {
-               srun = idx;                             // Start of run
-
-               while ( idx < 63 )
-               {
-                       if ( in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]] ) {
-                               break;
-                       }
-                       idx++;
-               }
-               count = (char)( idx - srun );             // count of repeated bytes
-
-               if ( !count ) {
-                       while ( idx < 63 )
-                       {
-                               if ( in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]] ) {
-                                       break;
-                               }
-                               idx++;
-                       }
-                       if ( idx == 63 ) {
-                               idx++;
-                       }
-
-                       count = (char)( idx - srun );         // count of unique bytes
-                       *out++ = count;
-                       while ( count-- )
-                               *out++ = in[LUT_ZZ[srun++]];
-               }
-               else
-               {
-                       *out++ = -( count + 1 );
-                       *out++ = in[LUT_ZZ[idx]];
-                       idx++;
-               }
-       }
-       return( out );
-}
-
-// ==============================
-// Discrete Cosine Transformation
-// ==============================
-
-void init_base( float quant ){
-       int y, x;
-
-       for ( y = 0; y < BLOCKSIZE; y++ )
-               for ( x = 0; x < BLOCKSIZE; x++ )
-               {
-                       if ( y == 0 ) {
-                               dctbase[y][x] = 1;
-                       }
-                       else{
-                               dctbase[y][x] = SQRT2 * cos( ( ( x * 2 + 1 ) * y * M_PI ) / ( BLOCKSIZE * 2 ) );
-                       }
-               }
-
-       for ( y = 0; y < BLOCKSIZE * BLOCKSIZE; y++ )
-               Quantise[y] = LUT_Quantise[y] / quant;
-}
-
-void SplitComponents( byte *src, int width, int height ){
-       int i, j;
-       float   *tr = red;
-       float   *tg = green;
-       float   *tb = blue;
-
-       for ( i = 0; i < BLOCKSIZE; i++, src += ( width - BLOCKSIZE ) * 4 )
-               for ( j = 0; j < BLOCKSIZE; j++ )
-               {
-                       *tr++ = ( (float)*src++ ) - 128.0F;
-                       *tg++ = ( (float)*src++ ) - 128.0F;
-                       *tb++ = ( (float)*src++ ) - 128.0F;
-                       src++;
-               }
-}
-
-void transferH( float *src, float *dst ){
-       int y, dx, dy;
-       float sum;
-       float   *work;
-
-       for ( y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE )
-       {
-               for ( dy = 0; dy < BLOCKSIZE; dy++ )
-               {
-                       sum = 0;
-                       work = src;
-                       for ( dx = 0; dx < BLOCKSIZE; dx++, work++ )
-                               sum += dctbase[dy][dx] * *work;
-
-                       *dst++ = sum / BLOCKSIZE;
-               }
-       }
-}
-
-void transferV( float *src, float *dst ){
-       int x, dy, fy;
-       float sum;
-       float   *work;
-
-       for ( x = 0; x < BLOCKSIZE; x++, src++, dst++ )
-       {
-               for ( fy = 0; fy < BLOCKSIZE; fy++ )
-               {
-                       sum = 0;
-                       work = src;
-                       for ( dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE )
-                               sum += dctbase[fy][dy] * *work;
-
-                       dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
-               }
-       }
-}
-
-char *Combine( byte *dst, float *p, float *q ){
-       int i, j;
-       byte rlesrc[BLOCKSIZE * BLOCKSIZE];
-       int c;
-       byte    *work;
-
-       work = rlesrc;
-       for ( j = 0; j < BLOCKSIZE; j++ )
-               for ( i = 0; i < BLOCKSIZE; i++ )
-               {
-                       c = (int)( ( *p++ / *q++ ) + 128.5F );
-                       c -= 128;
-
-                       if ( c < -128 ) {
-                               c = -128;
-                       }
-                       if ( c > 127 ) {
-                               c = 127;
-                       }
-
-                       *work++ = (char)c;
-               }
-
-       dst = RLEZZ( rlesrc, dst );
-       return( dst );
-}
-
-char *CombineComponents( char *dst, int width, int height ){
-       dst = Combine( dst, red, Quantise );
-       dst = Combine( dst, green, Quantise );
-       dst = Combine( dst, blue, Quantise );
-       return( dst );
-}
-
-void DCT( cblock_t *out, cblock_t in, int width, int height ){
-       int x, y;
-       char    *cursrc;
-       char    *curdst;
-
-       curdst = out->data;
-       for ( y = 0; y < height; y += BLOCKSIZE )
-               for ( x = 0; x < width; x += BLOCKSIZE )
-               {
-                       cursrc = in.data + ( ( y * width ) + x ) * 4;
-                       SplitComponents( cursrc, width, height );
-                       transferH( red, temp );
-                       transferV( temp, red );
-                       transferH( green, temp );
-                       transferV( temp, green );
-                       transferH( blue, temp );
-                       transferV( temp, blue );
-                       curdst = CombineComponents( curdst, width, height );
-               }
-       out->count = curdst - out->data;
-}
-
-// ==================
-// BuildChars1
-// ==================
-
-void BuildChars1( int prev, int nodenum, unsigned bits, int bitcount ){
-       hnode_t     *node;
-
-       if ( nodenum < HUF_TOKENS ) {
-               if ( bitcount > 32 ) {
-                       Error( "bitcount > 32" );
-               }
-               charbits1[prev][nodenum] = bits;
-               charbitscount1[prev][nodenum] = bitcount;
-               return;
-       }
-
-       node = &hnodes1[prev][nodenum];
-       bits <<= 1;
-       BuildChars1( prev, node->children[0], bits, bitcount + 1 );
-       bits |= 1;
-       BuildChars1( prev, node->children[1], bits, bitcount + 1 );
-}
-
-// ==================
-// SmallestNode1
-// ==================
-
-int SmallestNode1( hnode_t *hnodes, int numhnodes ){
-       int i;
-       int best, bestnode;
-
-       best = 99999999;
-       bestnode = -1;
-       for ( i = 0; i < numhnodes; i++ )
-       {
-               if ( hnodes[i].used ) {
-                       continue;
-               }
-               if ( !hnodes[i].count ) {
-                       continue;
-               }
-               if ( hnodes[i].count < best ) {
-                       best = hnodes[i].count;
-                       bestnode = i;
-               }
-       }
-
-       if ( bestnode == -1 ) {
-               return( -1 );
-       }
-
-       hnodes[bestnode].used = true;
-       return( bestnode );
-}
-
-// ==================
-// BuildTree1
-// ==================
-
-void BuildTree1( int prev ){
-       hnode_t     *node, *nodebase;
-       int numhnodes;
-
-       // build the nodes
-       numhnodes = HUF_TOKENS;
-       nodebase = hnodes1[prev];
-       while ( 1 )
-       {
-               node = &nodebase[numhnodes];
-
-               // pick two lowest counts
-               node->children[0] = SmallestNode1( nodebase, numhnodes );
-               if ( node->children[0] == -1 ) {
-                       break;  // no more
-
-               }
-               node->children[1] = SmallestNode1( nodebase, numhnodes );
-               if ( node->children[1] == -1 ) {
-                       break;
-               }
-
-               node->count = nodebase[node->children[0]].count +
-                                         nodebase[node->children[1]].count;
-               numhnodes++;
-       }
-       numhnodes1[prev] = numhnodes - 1;
-       BuildChars1( prev, numhnodes - 1, 0, 0 );
-}
-
-// ==================
-// Huffman1_Count
-// ==================
-
-void Huffman1_Count( cblock_t in ){
-       int i;
-       int prev;
-       int v;
-       int rept;
-
-       prev = 0;
-       for ( i = 0; i < in.count; i++ )
-       {
-               v = in.data[i];
-               order0counts[v]++;
-               hnodes1[prev][v].count++;
-               prev = v;
-
-               for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
-                       if ( in.data[i + rept] != v ) {
-                               break;
-                       }
-               if ( rept > MIN_REPT ) {
-                       hnodes1[prev][255 + rept].count++;
-                       i += rept - 1;
-               }
-       }
-}
-
-// ==================
-// Huffman1_Build
-// ==================
-
-void Huffman1_Build(){
-       int i, j, v;
-       int max;
-       int total;
-
-       for ( i = 0; i < 256; i++ )
-       {
-// normalize and save the counts
-               max = 0;
-               for ( j = 0; j < HUF_TOKENS; j++ )
-               {
-                       if ( hnodes1[i][j].count > max ) {
-                               max = hnodes1[i][j].count;
-                       }
-               }
-               if ( max == 0 ) {
-                       max = 1;
-               }
-               total = 0;
-// easy to overflow 32 bits here!
-               for ( j = 0; j < HUF_TOKENS; j++ )
-               {
-                       v = ( hnodes1[i][j].count * (double) 255 + max - 1 ) / max;
-                       if ( v > 255 ) {
-                               Error( "v > 255" );
-                       }
-                       scaled[i][j] = hnodes1[i][j].count = v;
-                       if ( v ) {
-                               total++;
-                       }
-               }
-               if ( total == 1 ) { // must have two tokens
-                       if ( !scaled[i][0] ) {
-                               scaled[i][0] = hnodes1[i][0].count = 1;
-                       }
-                       else{
-                               scaled[i][1] = hnodes1[i][1].count = 1;
-                       }
-               }
-               BuildTree1( i );
-       }
-}
-
-// ==================
-// Huffman1
-// Order 1 compression with pre-built table
-// ==================
-
-cblock_t Huffman1( cblock_t in ){
-       int i;
-       int outbits, c;
-       unsigned bits;
-       byte        *out_p;
-       cblock_t out;
-       int prev;
-       int v;
-       int rept;
-
-       out_p = out.data = SafeMalloc( ( in.count * 2 ) + 1024 + 4, "Huffman" );
-       memset( out_p, 0, ( in.count * 2 ) + 1024 + 4 );
-
-       // leave space for compressed count
-       out_p += 4;
-       // write count
-       *(long *)out_p = in.count;
-       out_p += 4;
-
-       // write bits
-       outbits = 0;
-       prev = 0;
-       for ( i = 0; i < in.count; i++ )
-       {
-               v = in.data[i];
-
-               c = charbitscount1[prev][v];
-               bits = charbits1[prev][v];
-               if ( !c ) {
-                       Error( "!bits" );
-               }
-               while ( c )
-               {
-                       c--;
-                       if ( bits & ( 1 << c ) ) {
-                               out_p[outbits >> 3] |= 1 << ( outbits & 7 );
-                       }
-                       outbits++;
-               }
-
-               prev = v;
-               // check for repeat encodes
-               for ( rept = 1; ( i + rept < in.count ) && ( rept < MAX_REPT ); rept++ )
-                       if ( in.data[i + rept] != v ) {
-                               break;
-                       }
-               if ( rept > MIN_REPT ) {
-                       c = charbitscount1[prev][255 + rept];
-                       bits = charbits1[prev][255 + rept];
-                       if ( !c ) {
-                               Error( "!bits" );
-                       }
-                       while ( c )
-                       {
-                               c--;
-                               if ( bits & ( 1 << c ) ) {
-                                       out_p[outbits >> 3] |= 1 << ( outbits & 7 );
-                               }
-                               outbits++;
-                       }
-                       i += rept - 1;
-               }
-       }
-       out_p += ( outbits + 7 ) >> 3;
-       out.count = out_p - out.data;
-
-       out_p = out.data;
-       *(long *)out_p = out.count;
-       return( out );
-}
-// ===================
-// LoadFrame
-// ===================
-
-void LoadFrame( cblock_t *out, char *base, int frame ){
-       cblock_t in;
-       int width, height;
-       char name[1024];
-       FILE        *f;
-
-       in.data = NULL;
-       in.count = -1;
-       sprintf( name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame );
-
-       f = fopen( name, "rb" );
-       if ( !f ) {
-               out->data = NULL;
-               return;
-       }
-       fclose( f );
-
-       LoadTGA( name, &in.data, &width, &height );
-       if ( ( width != cinehead.Width ) || ( height != cinehead.Height ) ) {
-               free( in.data );
-               printf( "Invalid picture size\n" );
-               out->data = NULL;
-               return;
-       }
-       out->data = SafeMalloc( width * height * 3, "LoadFrame" );        // rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
-       DCT( out, in, width, height );
-       free( in.data );
-}
-
-// ==================================
-// Cmd_Video
-//
-// video <directory> <framedigits>
-// ==================================
-
-void Cmd_Video(){
-       char savename[256];
-       char name[256];
-       FILE        *output;
-       int frame;
-       int width, height;
-       cblock_t in, huffman;
-       int size;
-       float dctconst;
-       int maxsize, ssize;
-       int min_rle_size, warnings;
-       int ave_image, ave_sound;
-
-       GetScriptToken( false );
-       strcpy( base, token );
-       if ( g_release ) {
-               return;
-       }
-
-       GetScriptToken( false );
-       dctconst = atof( token );
-       GetScriptToken( false );
-       maxsize = atoi( token );
-
-       sprintf( savename, "%svideo/%s.cin", gamedir, base );
-
-       // clear stuff
-       memset( charbits1, 0, sizeof( charbits1 ) );
-       memset( charbitscount1, 0, sizeof( charbitscount1 ) );
-       memset( hnodes1, 0, sizeof( hnodes1 ) );
-       memset( numhnodes1, 0, sizeof( numhnodes1 ) );
-       memset( order0counts, 0, sizeof( order0counts ) );
-
-       // load the entire sound wav file if present
-       LoadSoundtrack();
-
-       cinehead.SndRate = wavinfo.rate;
-       cinehead.SndWidth = wavinfo.width;
-       cinehead.SndChannels = wavinfo.channels;
-
-       sprintf( name, "%svideo/%s/%s0000.tga", gamedir, base, base );
-       printf( "Loading sequence : %s\n", name );
-       printf( "DCT constant     : %f\n", dctconst );
-
-       LoadTGA( name, NULL, &width, &height );
-
-       output = fopen( savename, "wb" );
-       if ( !output ) {
-               Error( "Can't open %s", savename );
-       }
-
-       if ( ( width % BLOCKSIZE ) || ( height % BLOCKSIZE ) ) {
-               Error( "Width and height must be a multiple of %d", BLOCKSIZE );
-       }
-
-       cinehead.Width = width;
-       cinehead.Height = height;
-       init_base( dctconst );
-
-       // build the dictionary
-       printf( "Counting         : " );
-       min_rle_size = 0;
-       for ( frame = 0;  ; frame++ )
-       {
-               printf( "." );
-               LoadFrame( &in, base, frame );
-               if ( !in.data ) {
-                       break;
-               }
-               Huffman1_Count( in );
-               if ( in.count > min_rle_size ) {
-                       min_rle_size = in.count;
-               }
-               free( in.data );
-       }
-       printf( "\n" );
-       cinehead.NumFrames = frame;
-       printf( "Num Frames       : %d\n", frame );
-       cinehead.MaxRleSize = ( min_rle_size + 0x1f ) & 0xfffffe0;
-       cinehead.MaxSndSize = ( ( 4 * wavinfo.rate * wavinfo.channels / 14 ) + 0x1f ) & 0xffffffe0;
-
-       WriteHeader( output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof( CineHead_t ), &cinehead );
-
-       // build nodes and write counts
-       Huffman1_Build();
-       WriteHeader( output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof( scaled ), scaled );
-       WriteHeader( output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof( Quantise ), Quantise );
-
-       ave_image = 0;
-       ave_sound = 0;
-       warnings = 0;
-       // compress it with the dictionary
-       if ( soundtrack ) {
-               ssize = WriteSound( output, frame, 4 );
-               ave_sound += ssize;
-       }
-
-       for ( frame = 0; frame < cinehead.NumFrames; frame++ )
-       {
-               // save some sound samples
-               printf( "Packing          : ", frame );
-               LoadFrame( &in, base, frame );
-
-               // save the image
-               huffman = Huffman1( in );
-               printf( "%d bytes rle, %d bytes huffman", in.count, huffman.count );
-               size = ( huffman.count + 3 ) & 0xfffffffc;                    // round up to longwords
-               if ( size > maxsize ) {
-                       printf( " ** WARNING **" );
-                       warnings++;
-               }
-               printf( "\n" );
-               ave_image += huffman.count;
-
-               WriteHeader( output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data );
-               if ( soundtrack ) {
-                       ssize = WriteSound( output, frame + 4, 1 );
-                       ave_sound += ssize;
-               }
-
-               free( in.data );
-               free( huffman.data );
-       }
-       printf( "\nTotal size: %d (headers + %d image + %d sound)\n", ftell( output ), ave_image, ave_sound );
-       printf( "Data rate : %d bytes per sec (image and sound)\n", ( ave_image + ave_sound ) / cinehead.NumFrames );
-       printf( "Cin created ok with %d warnings.\n", warnings );
-       fclose( output );
-
-       if ( soundtrack ) {
-               free( soundtrack );
-       }
-}
-#endif
-
-void Cmd_Video(){
-}
-
-// end
index b1e8e67b3dd8fbd29af0d142a6147908db94b6a5..638d867c4969dd48053d2e6454ec00fac739f98c 100644 (file)
@@ -1,16 +1,11 @@
 include_directories(BEFORE common)
 
 set(Q3MAP_VERSION 2.5.17n)
-find_package(Git REQUIRED)
-execute_process(
-        COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
-        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
-        OUTPUT_VARIABLE GIT_VERSION
-        OUTPUT_STRIP_TRAILING_WHITESPACE
-)
+
 if (GIT_VERSION)
     set(Q3MAP_VERSION "${Q3MAP_VERSION}-git-${GIT_VERSION}")
 endif ()
+
 add_definitions(-DQ3MAP_VERSION="${Q3MAP_VERSION}")
 
 find_package(GLIB REQUIRED)
@@ -28,9 +23,6 @@ include_directories(${WEBP_INCLUDE_DIR})
 find_package(LibXml2 REQUIRED)
 include_directories(${LIBXML2_INCLUDE_DIR})
 
-find_package(ZLIB REQUIRED)
-include_directories(${ZLIB_INCLUDE_DIRS})
-
 find_package(Minizip REQUIRED)
 include_directories(${Minizip_INCLUDE_DIRS})
 
@@ -44,21 +36,29 @@ set(q3map2_games
         q3map2/game_ja.h
         q3map2/game_jk2.h
         q3map2/game_nexuiz.h
+        q3map2/game_oa.h
         q3map2/game_prophecy.h
+        q3map2/game_q3rally.h
         q3map2/game_qfusion.h
         q3map2/game_quake3.h
         q3map2/game_quakelive.h
         q3map2/game_reaction.h
+        q3map2/game_smokinguns.h
         q3map2/game_sof2.h
         q3map2/game_tenebrae.h
         q3map2/game_tremulous.h
         q3map2/game_unvanquished.h
+        q3map2/game_warfork.h
+        q3map2/game_warsow.h
         q3map2/game_wolf.h
         q3map2/game_wolfet.h
+        q3map2/game_wop.h
         q3map2/game_xonotic.h
         )
 
 radiant_tool(q3map2
+        q3map2/q3map2.rc
+
         common/cmdlib.c common/cmdlib.h
         common/imagelib.c common/imagelib.h
         common/inout.c common/inout.h
@@ -141,7 +141,6 @@ target_link_libraries(q3map2
         ${WEBP_LIBRARIES}
         ${LIBXML2_LIBRARIES}
         ${Minizip_LIBRARIES}
-        ${ZLIB_LIBRARIES}
         ${OPTIONAL_IMAGE_LIBRARIES}
         ddslib
         etclib
@@ -152,6 +151,8 @@ target_link_libraries(q3map2
         )
 
 radiant_tool(q3data
+        q3data/q3data.rc
+
         common/aselib.c common/aselib.h
         common/bspfile.c common/bspfile.h
         common/cmdlib.c common/cmdlib.h
@@ -178,7 +179,6 @@ target_link_libraries(q3data
         ${GLIB_LIBRARIES}
         ${LIBXML2_LIBRARIES}
         ${Minizip_LIBRARIES}
-        ${ZLIB_LIBRARIES}
         filematch
         etclib
         l_net
@@ -192,3 +192,5 @@ if (UNIX)
     target_link_libraries(q3map2 pthread m)
     target_link_libraries(q3data m)
 endif ()
+
+target_link_libraries(q3map2)
index bb3be0ea50b1ce99bda7178dc50e3c0b6d9a993d..78549ad098774268925da2b903367c4c771f0b86 100644 (file)
 
 #define VERBOSE( x ) { if ( ase.verbose ) { Sys_Printf x ; } }
 
+#if !GDEF_OS_WINDOWS
+#define strlwr strlower
+#endif // !GDEF_OS_WINDOWS
+
 typedef struct
 {
        float x, y, z;
@@ -114,22 +118,6 @@ static char gl_filename[1024];
 static void ASE_Process( void );
 static void ASE_FreeGeomObject( int ndx );
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-
-static char* strlwr( char* string ){
-       char *cp;
-       for ( cp = string; *cp; ++cp )
-       {
-               if ( 'A' <= *cp && *cp <= 'Z' ) {
-                       *cp += 'a' - 'A';
-               }
-       }
-
-       return string;
-}
-
-#endif
-
 /*
 ** ASE_Load
 */
index 4fc45bd6af7d347f9d6bbf4d44e7c9c8e555f944..c65da46d593dfa9dbd3b9dba7c2d34d6edb8e284 100644 (file)
@@ -96,9 +96,7 @@ void SetLightBytes( int n ){
                return;
        }
 
-       lightBytes = safe_malloc_info( numLightBytes, "SetLightBytes" );
-
-       memset( lightBytes, 0, numLightBytes );
+       lightBytes = safe_malloc0_info( numLightBytes, "SetLightBytes" );
 }
 
 void SetGridPoints( int n ){
@@ -112,9 +110,7 @@ void SetGridPoints( int n ){
                return;
        }
 
-       gridData = safe_malloc_info( numGridPoints * 8, "SetGridPoints" );
-
-       memset( gridData, 0, numGridPoints * 8 );
+       gridData = safe_malloc0_info( numGridPoints * 8, "SetGridPoints" );
 }
 
 void IncDrawVerts(){
@@ -152,9 +148,7 @@ void SetDrawVerts( int n ){
        numDrawVerts = n;
        numDrawVertsBuffer = numDrawVerts;
 
-       drawVerts = safe_malloc_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
-
-       memset( drawVerts, 0, n * sizeof( drawVert_t ) );
+       drawVerts = safe_malloc0_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
 }
 
 void SetDrawSurfacesBuffer(){
@@ -164,9 +158,7 @@ void SetDrawSurfacesBuffer(){
 
        numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
 
-       drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
-
-       memset( drawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( drawVert_t ) );
+       drawSurfaces = safe_malloc0_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
 }
 
 void SetDrawSurfaces( int n ){
@@ -177,9 +169,7 @@ void SetDrawSurfaces( int n ){
        numDrawSurfaces = n;
        numDrawSurfacesBuffer = numDrawSurfaces;
 
-       drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
-
-       memset( drawSurfaces, 0, n * sizeof( drawVert_t ) );
+       drawSurfaces = safe_malloc0_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
 }
 
 void BspFilesCleanup(){
@@ -522,8 +512,7 @@ void StripTrailing( char *e ) {
 epair_t *ParseEpair( void ) {
        epair_t *e;
 
-       e = safe_malloc( sizeof( epair_t ) );
-       memset( e, 0, sizeof( epair_t ) );
+       e = safe_malloc0( sizeof( epair_t ) );
 
        if ( strlen( token ) >= MAX_KEY - 1 ) {
                Error( "ParseEpar: token too long" );
index b74c7b3362ba47b5bfeaa1edfff692bf8fbf5c63..60edebad465e5ca22c5d1b156a96b2e932fee5f2 100644 (file)
 #if GDEF_OS_WINDOWS
 #include <direct.h>
 #include <windows.h>
-#endif
-
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
+#elif GDEF_OS_NEXT
 #include <libc.h>
-#endif
+#else // OTHER OS
+#include <unistd.h>
+#endif // OTHER OS
 
-#define BASEDIRNAME "quake"     // assumed to have a 2 or 3 following
-#define PATHSEPERATOR   '/'
+#define BASEDIRNAME "quake" // assumed to have a 2 or 3 following
+#define PATHSEPERATOR '/'
 
-#ifdef SAFE_MALLOC
 void *safe_malloc( size_t size ){
        void *p;
 
@@ -73,7 +68,28 @@ void *safe_malloc_info( size_t size, char* info ){
 
        return p;
 }
-#endif
+
+void *safe_malloc0( size_t size ){
+       void *p;
+
+       p = calloc( 1, size );
+       if ( !p ) {
+               Error( "safe_malloc0 failed on allocation of %i bytes", size );
+       }
+
+       return p;
+}
+
+void *safe_malloc0_info( size_t size, char* info ){
+       void *p;
+
+       p = calloc( 1, size );
+       if ( !p ) {
+               Error( "%s: safe_malloc0 failed on allocation of %i bytes", info, size );
+       }
+
+       return p;
+}
 
 // set these before calling CheckParm
 int myargc;
@@ -96,6 +112,7 @@ char archivedir[1024];
 #define MAX_EX_ARGC 1024
 int ex_argc;
 char    *ex_argv[MAX_EX_ARGC];
+
 #if GDEF_OS_WINDOWS
 #include "io.h"
 void ExpandWildcards( int *argc, char ***argv ){
@@ -135,10 +152,10 @@ void ExpandWildcards( int *argc, char ***argv ){
        *argc = ex_argc;
        *argv = ex_argv;
 }
-#else
+#else // !GDEF_OS_WINDOWS
 void ExpandWildcards( int *argc, char ***argv ){
 }
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 /*
 
@@ -296,13 +313,13 @@ void Q_getwd( char *out ){
 #if GDEF_OS_WINDOWS
        _getcwd( out, 256 );
        strcat( out, "\\" );
-#else
+#else // !GDEF_OS_WINDOWS
        // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
        if ( !getcwd( out, 256 ) ) {
                *out = 0;
        }
        strcat( out, "/" );
-#endif
+#endif // !GDEF_OS_WINDOWS
        while ( out[i] != 0 )
        {
                if ( out[i] == '\\' ) {
@@ -331,14 +348,14 @@ void Q_mkdir( const char *path ){
                                p = q;
                        }
                }
-#else
+#else // !GDEF_OS_WINDOWS
                if ( mkdir( path, 0777 ) != -1 ) {
                        return;
                }
                if ( errno == ENOENT ) {
                        p = strrchr( path, '/' );
                }
-#endif
+#endif // !GDEF_OS_WINDOWS
                if ( p ) {
                        strncpy( parentbuf, path, sizeof( parentbuf ) );
                        if ( (int) ( p - path ) < (int) sizeof( parentbuf ) ) {
@@ -482,23 +499,6 @@ int Q_stricmp( const char *s1, const char *s2 ){
        return Q_strncasecmp( s1, s2, 99999 );
 }
 
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-   char *strupr (char *start)
-   {
-    char       *in;
-    in = start;
-    while (*in)
-    {
-   *in = toupper(*in);
-        in++;
-    }
-    return start;
-   }
- */
-
 char *strlower( char *start ){
        char    *in;
        in = start;
@@ -658,8 +658,7 @@ int    LoadFileBlock( const char *filename, void **bufferptr ){
        if ( nBlock > 0 ) {
                nAllocSize += MEM_BLOCKSIZE - nBlock;
        }
-       buffer = safe_malloc( nAllocSize + 1 );
-       memset( buffer, 0, nAllocSize + 1 );
+       buffer = safe_malloc0( nAllocSize + 1 );
        SafeRead( f, buffer, length );
        fclose( f );
 
@@ -931,9 +930,7 @@ float   BigFloat( float l ){
        return l;
 }
 
-
-#else
-
+#else // !GDEF_ARCH_ENDIAN_BIG
 
 short   BigShort( short l ){
        byte b1,b2;
@@ -980,8 +977,7 @@ float   LittleFloat( float l ){
        return l;
 }
 
-
-#endif
+#endif // !GDEF_ARCH_ENDIAN_BIG
 
 
 //=======================================================
@@ -1062,7 +1058,7 @@ void    CreatePath( const char *path ){
                olddrive = _getdrive();
                _chdrive( toupper( path[0] ) - 'A' + 1 );
        }
-#endif
+#endif // !GDEF_OS_WINDOWS
 
        if ( path[1] == ':' ) {
                path += 2;
@@ -1082,7 +1078,7 @@ void    CreatePath( const char *path ){
        if ( olddrive != -1 ) {
                _chdrive( olddrive );
        }
-#endif
+#endif // !>GDEF_OS_WINDOWS
 }
 
 
@@ -1106,8 +1102,7 @@ void QCopyFile( const char *from, const char *to ){
 void Sys_Sleep( int n ){
 #if GDEF_OS_WINDOWS
        Sleep( n );
-#endif
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#else // !GDEF_OS_WINDOWS
        usleep( n * 1000 );
-#endif
+#endif // !GDEF_OS_WINDOWS
 }
index b57c81a9e760bef4c87512081236027c2740698b..ecdcf6e1afd6dc42bd0375958efa36affdc5bb58 100644 (file)
 // the dec offsetof macro doesnt work very well...
 #define myoffsetof( type,identifier ) ( (size_t)& ( (type *)0 )->identifier )
 
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
 void *safe_malloc( size_t size );
 void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc( a ) malloc( a )
-#endif /* SAFE_MALLOC */
+void *safe_malloc0( size_t size );
+void *safe_malloc0_info( size_t size, char* info );
 
 // set these before calling CheckParm
 extern int myargc;
index 5bc5ff71df9a0e2fee1c039f4224d2f300d17057..661b9ed32436e7aa3fd9c6dc9713857ac6bafd2b 100644 (file)
@@ -256,8 +256,7 @@ void LoadLBM( const char *filename, byte **picture, byte **palette ){
                        break;
 
                case CMAPID:
-                       cmapbuffer = safe_malloc( 768 );
-                       memset( cmapbuffer, 0, 768 );
+                       cmapbuffer = safe_malloc0( 768 );
                        memcpy( cmapbuffer, LBM_P, chunklength );
                        break;
 
@@ -572,8 +571,7 @@ void WritePCXfile( const char *filename, byte *data,
        pcx_t   *pcx;
        byte        *pack;
 
-       pcx = safe_malloc( width * height * 2 + 1000 );
-       memset( pcx, 0, sizeof( *pcx ) );
+       pcx = safe_malloc0( width * height * 2 + 1000 );
 
        pcx->manufacturer = 0x0a;   // PCX id
        pcx->version = 5;           // 256 color
@@ -1145,6 +1143,8 @@ void WriteTGA( const char *filename, byte *data, int width, int height ) {
        FILE    *f;
 
        buffer = safe_malloc( width * height * 4 + 18 );
+       /* we may also use safe_malloc0 on the whole instead,
+        * this would just be a bit slower */
        memset( buffer, 0, 18 );
        buffer[2] = 2;      // uncompressed type
        buffer[12] = width & 255;
index bef8fbd4d917313a0880d335a58daf75e3744641..21afcbcc9b3d2e482c61775c4912c6857f4ac05c 100644 (file)
@@ -66,8 +66,7 @@ winding_t   *AllocWinding( int points ){
                }
        }
        s = sizeof( *w ) + ( points ? sizeof( w->p[0] ) * ( points - 1 ) : 0 );
-       w = safe_malloc( s );
-       memset( w, 0, s );
+       w = safe_malloc0( s );
        return w;
 }
 
@@ -94,8 +93,7 @@ winding_accu_t *AllocWindingAccu( int points ){
                }
        }
        s = sizeof( *w ) + ( points ? sizeof( w->p[0] ) * ( points - 1 ) : 0 );
-       w = safe_malloc( s );
-       memset( w, 0, s );
+       w = safe_malloc0( s );
        return w;
 }
 
index d726c04b072d3d3bc2cc461b77441c91f76dd2d7..3caa6879111b777558dcd348c71fd66777bea49f 100644 (file)
@@ -227,7 +227,7 @@ qboolean GetToken( qboolean crossline ){
 // skip space
 //
 skipspace:
-       while ( *script->script_p <= 32 )
+       while ( script->script_p < script->end_p && *script->script_p <= 32 )
        {
                if ( script->script_p >= script->end_p ) {
                        return EndOfScript( crossline );
index 0fb78ac4bd5963251b6c9a165fd38bdc2403c1f6..5d81cf5eded55ca542f7db18e90a69e1bf8385f7 100644 (file)
 
 #include "globaldefs.h"
 #include <stdint.h>
+
 #if !GDEF_OS_WINDOWS
 // The below define is necessary to use
 // pthreads extensions like pthread_mutexattr_settype
 #define _GNU_SOURCE
-#include <pthread.h>
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 #include "cmdlib.h"
 #include "mathlib.h"
@@ -111,6 +111,8 @@ void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )(
 }
 
 
+#if GDEF_OS_WINDOWS
+
 /*
    ===================================================================
 
@@ -118,9 +120,6 @@ void RunThreadsOnIndividual( int workcnt, qboolean showpacifier, void ( *func )(
 
    ===================================================================
  */
-#if GDEF_OS_WINDOWS
-
-#define USED
 
 #include <windows.h>
 
@@ -221,7 +220,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
+#elif GDEF_OS_OSF1
 
 /*
    ===================================================================
@@ -231,9 +230,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    ===================================================================
  */
 
-#ifdef __osf__
-#define USED
-
 int numthreads = 4;
 
 void ThreadSetDefault( void ){
@@ -242,7 +238,6 @@ void ThreadSetDefault( void ){
        }
 }
 
-
 #include <pthread.h>
 
 pthread_mutex_t *my_mutex;
@@ -328,7 +323,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
+#elif GDEF_OS_IRIX
 
 /*
    ===================================================================
@@ -338,7 +333,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    ===================================================================
  */
 
-#ifdef _MIPS_ISA
 #define USED
 
 #include <task.h>
@@ -346,7 +340,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 #include <sys/types.h>
 #include <sys/prctl.h>
 
-
 int numthreads = -1;
 abilock_t lck;
 
@@ -415,8 +408,7 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
 }
 
 
-#endif
-
+#elif GDEF_OS_LINUX || GDEF_OS_BSD || GDEF_OS_MACOS
 
 /*
    =======================================================================
@@ -426,9 +418,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    =======================================================================
  */
 
-#if GDEF_OS_LINUX || ( GDEF_OS_MACOS && !MAC_STATIC_HACK )
-#define USED
-
 #include <unistd.h>
 
 int numthreads = -1;
@@ -597,9 +586,10 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
                Sys_Printf( " (%i)\n", end - start );
        }
 }
-#endif // ifdef __linux__
 
 
+#else // UNKNOWN OS
+
 /*
    =======================================================================
 
@@ -608,8 +598,6 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
    =======================================================================
  */
 
-#ifndef USED
-
 int numthreads = 1;
 
 void ThreadSetDefault( void ){
@@ -643,4 +631,4 @@ void RunThreadsOn( int workcnt, qboolean showpacifier, void ( *func )( int ) ){
        }
 }
 
-#endif
+#endif // UNKNOWN OS
index 5f403418ff449077f8c7a2f1a83d5451ac0b4278..72dd5f3c4f71f886e886df5cf8701e22910e82cb 100644 (file)
 #define FLOAT_END   -FLOAT_START
 #define MAGIC       123322
 
-//#define NOISY 1
+// #define NOISY 1
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#if !GDEF_OS_WINDOWS
 #define strlwr strlower
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 typedef struct {
        float v[3];
index 48a1f86fbde046b5b81b411cb15f18167991125e..345846e67045436c0a7a45acae85fe0df3b8aa1c 100644 (file)
@@ -50,7 +50,7 @@
 #include "mathlib.h"
 #include "inout.h"
 #include "vfs.h"
-#include <minizip/unzip.h>
+#include <unzip.h>
 #include <glib.h>
 #define GARUX_DISABLE_BAD_MINIZ
 #ifndef GARUX_DISABLE_BAD_MINIZ
@@ -192,6 +192,7 @@ void vfsInitDirectory( const char *path ){
        }
 
        if ( g_numDirs == VFS_MAXDIRS ) {
+               Sys_FPrintf( SYS_WRN, "WARNING: too many VFS directories, can't init %s\n", path );
                return;
        }
 
@@ -233,6 +234,7 @@ void vfsInitDirectory( const char *path ){
 
                                        if ( ext != NULL && ( !Q_stricmp( ext, ".pk3dir" ) || !Q_stricmp( ext, ".dpkdir" ) ) ) {
                                                if ( g_numDirs == VFS_MAXDIRS ) {
+                                                       g_free( dirlist );
                                                        continue;
                                                }
                                                snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s/%s", path, name );
@@ -243,6 +245,7 @@ void vfsInitDirectory( const char *path ){
                                        }
 
                                        if ( ext == NULL || ( Q_stricmp( ext, ".pk3" ) != 0 && Q_stricmp( ext, ".dpk" ) != 0 ) ) {
+                                               g_free( dirlist );
                                                continue;
                                        }
                                }
@@ -372,6 +375,56 @@ int vfsGetFileCount( const char *filename ){
        return count;
 }
 
+static qboolean isSymlink(const unz_file_info64 *fileInfo) {
+       // see https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/stat.h
+       // redefine so it works outside of Unices
+       const unsigned long Q3MAP_S_IFMT = 00170000;
+       const unsigned long Q3MAP_S_IFLNK = 0120000;
+       // see https://trac.edgewall.org/attachment/ticket/8919/ZipDownload.patch
+       const unsigned long PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT = 16;
+
+       unsigned long attr = fileInfo->external_fa >> PKZIP_EXTERNAL_ATTR_FILE_TYPE_SHIFT;
+       return (attr & Q3MAP_S_IFMT) == Q3MAP_S_IFLNK;
+}
+
+// The zip format has a maximum filename size of 64K
+static const int MAX_FILENAME_BUF = 65537;
+
+/* The symlink implementation is ported from Dæmon engine implementation by slipher which was a complete rewrite of one illwieckz did on Dæmon by taking inspiration from Darkplaces engine.
+
+See:
+
+- https://github.com/DaemonEngine/Daemon/blob/master/src/common/FileSystem.cpp
+- https://gitlab.com/xonotic/darkplaces/-/blob/div0-stable/fs.c
+
+Some words by slipher:
+
+> Symlinks are a bad feature which you should not use. Therefore, the implementation is as
+> slow as possible with a full iteration of the archive performed for each symlink.
+
+> The symlink path `relative` must be relative to the symlink's location.
+> Only supports paths consisting of "../" 0 or more times, followed by non-magical path components.
+*/
+void resolveSymlinkPath( const char* base, const char* relative, char* resolved ){
+
+       base = g_path_get_dirname( base );
+
+       while( g_str_has_prefix( relative, "../" ) )
+       {
+               if ( base[0] == '\0' )
+               {
+                       Sys_FPrintf( SYS_WRN, "Error while reading symbolic link: \"%s\": no such directory\n", base );
+                       resolved[0] = '\0';
+                       return;
+               }
+
+               base = g_path_get_dirname( base );
+               relative += 3;
+       }
+
+       snprintf( resolved, MAX_FILENAME_BUF, "%s/%s", base, relative);
+}
+
 // NOTE: when loading a file, you have to allocate one extra byte and set it to \0
 int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        int i, count = 0;
@@ -412,7 +465,7 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
        }
 
        *bufferptr = NULL;
-       strcpy( fixed, filename );
+       strncpy( fixed, filename, sizeof( fixed ) );
        vfsFixDOSName( fixed );
        lower = g_ascii_strdown( fixed, -1 );
 
@@ -456,6 +509,11 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
                }
        }
 
+       // Do not resolve more than 5 recursive symbolic links to
+       // prevent circular symbolic links.
+       int max_symlink_depth = 5;
+
+       openSymlinkTarget:
        for ( lst = g_pakFiles; lst != NULL; lst = g_slist_next( lst ) )
        {
                VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
@@ -473,13 +531,47 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
                                return -1;
                        }
 
+                       unz_file_info64 fileInfo;
+                       if ( unzGetCurrentFileInfo64( file->zipfile, &fileInfo, filename, sizeof(filename), NULL, 0, NULL, 0 ) != UNZ_OK ) {
+                               return -1;
+                       }
+
                        *bufferptr = safe_malloc( file->size + 1 );
                        // we need to end the buffer with a 0
                        ( (char*) ( *bufferptr ) )[file->size] = 0;
 
                        i = unzReadCurrentFile( file->zipfile, *bufferptr, file->size );
                        unzCloseCurrentFile( file->zipfile );
+
+                       if ( isSymlink( &fileInfo ) ) {
+                               Sys_FPrintf( SYS_VRB, "Found symbolic link: \"%s\"\n", filename );
+
+                               if ( max_symlink_depth == 0 ) {
+                                       Sys_FPrintf( SYS_WRN, "Maximum symbolic link depth reached\n" );
+                                       g_free( lower );
+                                       return -1;
+                               }
+
+                               max_symlink_depth--;
+
+                               const char* relative = (const char*) *bufferptr;
+                               char resolved[MAX_FILENAME_BUF];
+
+                               resolveSymlinkPath( file->name, relative, resolved );
+
+                               Sys_FPrintf( SYS_VRB, "Resolved symbolic link: \"%s\"\n", resolved );
+
+                               g_free( lower );
+                               strncpy( fixed, resolved, sizeof( fixed ) );
+                               vfsFixDOSName( fixed );
+                               lower = g_ascii_strdown( fixed, -1 );
+
+                               // slow as possible full iteration of the archive
+                               goto openSymlinkTarget;
+                       }
+
                        if ( i < 0 ) {
+                               g_free( lower );
                                return -1;
                        }
                        else{
@@ -490,6 +582,7 @@ int vfsLoadFile( const char *filename, void **bufferptr, int index ){
 
                count++;
        }
+
        g_free( lower );
        return -1;
 }
index efa4257d04cbd7899be8c73807b57b73d416c9cd..15dd5e3b41f427965ed6a425ab6041904c870c92 100644 (file)
 
 // to get PATH_MAX
 #include <stdio.h>
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-#include <dirent.h>
-#include <unistd.h>
-#else
+
+#if GDEF_OS_WINDOWS
 #include <wtypes.h>
 #include <io.h>
 
 #endif
 
 #define S_ISDIR( mode ) ( mode & _S_IFDIR )
+#else // !GDEF_OS_WINDOWS
+#include <dirent.h>
+#include <unistd.h>
+#endif // !GDEF_OS_WINDOWS
+
+#ifndef PATH_MAX
 #define PATH_MAX 260
+#endif // PATH_MAX
+
+// PATH_MAX
+#if defined( __FreeBSD__ )
+#include <sys/syslimits.h>
 #endif
 
-#define VFS_MAXDIRS 64
+// Multiple pakpaths with many pk3dirs can lead
+// to high list of VFS directories
+#define VFS_MAXDIRS 256
 
 void vfsInitDirectory( const char *path );
 void vfsShutdown();
index 93b1dfe0028787d2a015149839f62ca7788c54df..2bc7e09a7f03c59f07539a5e3e496af2f0347d05 100644 (file)
 
 #include "globaldefs.h"
 #include <assert.h>
+
 #if GDEF_OS_WINDOWS
 #include <io.h>
-#endif
+#endif // GDEF_OS_WINDOWS
+
 #include "md3lib.h"
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-#define filelength(f) Q_filelength(f)
-#else
+#if GDEF_OS_WINDOWS
 #define filelength(f) filelength(fileno(f))
-#endif
+#else // !GDEF_OS_WINDOWS
+#define filelength(f) Q_filelength(f)
+#endif // ! GDEF_OS_WINDOWS
 
 /*
 ** MD3_ComputeTagFromTri
index 97cc3f6a229510eda76ba7932e1773e94575113f..ea59bb4d1eeafe2e62ae729aa13a7a3d9c1d1823 100644 (file)
 
 #if GDEF_OS_WINDOWS
 #include <io.h>
-#endif
+#endif // GDEF_OS_WINDOWS
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
 #define MAX_POLYSETS 64
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#if GDEF_OS_WINDOWS
+       #define filelength(f) filelength(fileno(f))
+#else // !GDEF_OS_WINDOWS
        #include "cmdlib.h"
        #define _strcmpi Q_stricmp
        #define strlwr strlower
        #define filelength(f) Q_filelength(f)
-#else
-       #define filelength(f) filelength(fileno(f))
-#endif
+#endif // !GDEF_OS_WINDOWS
+
 typedef struct
 {
        long len;
index 331f6138c352448d04e97fc5bcef5c2940b898ea..3f74d27f44a96ec98070f293a42069bcf4740b45 100644 (file)
  */
 
 #include "globaldefs.h"
+
 #if GDEF_OS_WINDOWS
 #include <io.h>
-#endif
+#endif // GDEF_OS_WINDOWS
+
 #include "q3data.h"
 #include "md3lib.h"
 
@@ -38,12 +40,10 @@ qboolean g_skipmodel;           // set true when a cd is not g_only
 
 // bogus externs for some TA hacks (common/ using them against q3map)
 char *moddir = NULL;
-// some old defined that was in cmdlib lost during merge
-char writedir[1024];
 
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
+#if !GDEF_OS_WINDOWS
 #define strlwr strlower
-#endif
+#endif // !GDEF_OS_WINDOWS
 
 /*
    =======================================================
@@ -561,8 +561,6 @@ void ParseScript( void ){
 
 //=======================================================
 
-#include "version.h"
-
 /*
    ==============
    main
@@ -574,7 +572,7 @@ int main( int argc, char **argv ){
 
        // using GtkRadiant's versioning next to Id's versioning
        printf( "Q3Data      - (c) 1999 Id Software Inc.\n" );
-       printf( "NetRadiant  - v" RADIANT_VERSION " " __DATE__ "\n" );
+       printf( RADIANT_NAME " - v" RADIANT_VERSION " " __DATE__ "\n" );
 
        ExpandWildcards( &argc, &argv );
 
diff --git a/tools/quake3/q3data/q3data.rc b/tools/quake3/q3data/q3data.rc
new file mode 100644 (file)
index 0000000..dd5c1d4
--- /dev/null
@@ -0,0 +1 @@
+101                     ICON    DISCARDABLE     "..\\..\\..\\icons\\q3data.ico"
index c6400cbc1ac3fc4859e2e917a34b3516b7c754bb..db04b8805e2faf08bc61ec8993df13e5c09964d8 100644 (file)
@@ -98,8 +98,7 @@ brush_t *AllocBrush( int numSides ){
                Error( "AllocBrush called with numsides = %d", numSides );
        }
        c = (size_t)&( ( (brush_t*) 0 )->sides[ numSides ] );
-       bb = safe_malloc( c );
-       memset( bb, 0, c );
+       bb = safe_malloc0( c );
        if ( numthreads == 1 ) {
                numActiveBrushes++;
        }
@@ -829,8 +828,7 @@ void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
 tree_t *AllocTree( void ){
        tree_t  *tree;
 
-       tree = safe_malloc( sizeof( *tree ) );
-       memset( tree, 0, sizeof( *tree ) );
+       tree = safe_malloc0( sizeof( *tree ) );
        ClearBounds( tree->mins, tree->maxs );
 
        return tree;
@@ -844,8 +842,7 @@ tree_t *AllocTree( void ){
 node_t *AllocNode( void ){
        node_t  *node;
 
-       node = safe_malloc( sizeof( *node ) );
-       memset( node, 0, sizeof( *node ) );
+       node = safe_malloc0( sizeof( *node ) );
 
        return node;
 }
index dff448507055cfcf8c0cd1d40f87337e7f4383da..7e504a6a2f8fee3bba0f43d6a84622989716a2fc 100644 (file)
@@ -716,14 +716,17 @@ int BSPMain( int argc, char **argv ){
        portalFilePath[0] = 0;
        surfaceFilePath[0] = 0;
 
+       if ( argc >= 2 && !strcmp( argv[ 1 ], "-bsp" ) ) {
+               argv++;
+               argc--;
+       }
 
        /* note it */
        Sys_Printf( "--- BSP ---\n" );
 
        doingBSP = qtrue;
        SetDrawSurfacesBuffer();
-       mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
-       memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+       mapDrawSurfs = safe_malloc0( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
        numMapDrawSurfs = 0;
 
        tempSource[ 0 ] = '\0';
@@ -831,7 +834,37 @@ int BSPMain( int argc, char **argv ){
                        i++;
                        Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
                }
-               else if ( !strcmp( argv[ i ],  "-mv" ) ) {
+               else if ( !strcmp( argv[ i ], "-fastmeta" ) ) {
+                       maxLMSurfaceVerts = 64;
+                       maxSurfaceVerts = 999;
+                       maxSurfaceIndexes = 6000;
+                       Sys_Printf( "Maximum per-surface vertex count set to %d\n", maxSurfaceVerts );
+                       Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
+                       Sys_Printf( "Maximum lightmapped surface vertex count set to %d\n", maxLMSurfaceVerts );
+               }
+               else if ( !strcmp( argv[ i ], "-maxsurfacevertices" ) ) {
+                       maxSurfaceVerts = atoi( argv[ i + 1 ] );
+                       if ( maxSurfaceVerts < 3 ) {
+                               maxSurfaceVerts = 3;
+                       }
+                       i++;
+                       Sys_Printf( "Maximum per-surface vertex count set to %d\n", maxSurfaceVerts );
+               }
+               else if ( !strcmp( argv[ i ], "-maxsurfaceindexes" ) || !strcmp( argv[ i ], "-mi" ) ) {
+                       maxSurfaceIndexes = atoi( argv[ i + 1 ] );
+                       if ( maxSurfaceIndexes < 3 ) {
+                               maxSurfaceIndexes = 3;
+                       }
+                       i++;
+
+                       if ( !strcmp( argv[ i ], "-mi" ) ) {
+                               Sys_Printf( "The -mi argument is deprecated, use \"-maxsurfaceindexes\" instead\n" );
+                       }
+                       else {
+                               Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
+                       }
+               }
+               else if ( !strcmp( argv[ i ], "-maxlightmapvertices" ) || !strcmp( argv[ i ], "-mv" ) ) {
                        maxLMSurfaceVerts = atoi( argv[ i + 1 ] );
                        if ( maxLMSurfaceVerts < 3 ) {
                                maxLMSurfaceVerts = 3;
@@ -840,15 +873,13 @@ int BSPMain( int argc, char **argv ){
                                maxSurfaceVerts = maxLMSurfaceVerts;
                        }
                        i++;
+
+                       if ( !strcmp( argv[ i ], "-mv" ) ) {
+                               Sys_Printf( "The -mv argument is deprecated, use \"-maxlightmapvertices\" instead\n" );
+                       }
+                       else {
                        Sys_Printf( "Maximum lightmapped surface vertex count set to %d\n", maxLMSurfaceVerts );
                }
-               else if ( !strcmp( argv[ i ],  "-mi" ) ) {
-                       maxSurfaceIndexes = atoi( argv[ i + 1 ] );
-                       if ( maxSurfaceIndexes < 3 ) {
-                               maxSurfaceIndexes = 3;
-                       }
-                       i++;
-                       Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
                }
                else if ( !strcmp( argv[ i ], "-np" ) ) {
                        npDegrees = atof( argv[ i + 1 ] );
@@ -1004,30 +1035,35 @@ int BSPMain( int argc, char **argv ){
                else if ( !strcmp( argv[ i ], "-bspfile" ) )
                {
                        strcpy( BSPFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as bsp file\n", BSPFilePath );
                }
                else if ( !strcmp( argv[ i ], "-linfile" ) )
                {
                        strcpy( lineFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as line file\n", lineFilePath );
                }
                else if ( !strcmp( argv[ i ], "-prtfile" ) )
                {
                        strcpy( portalFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as portal file\n", portalFilePath );
                }
                else if ( !strcmp( argv[ i ], "-srffile" ) )
                {
                        strcpy( surfaceFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as surface file\n", surfaceFilePath );
                }
-               else if ( !strcmp( argv[ i ], "-bsp" ) ) {
-                       Sys_Printf( "-bsp argument unnecessary\n" );
-               }
                else if ( !strcmp( argv[ i ], "-noob" ) ) {
                        Sys_Printf( "No oBs!\n" );
                        noob = qtrue;
index e84439d3599037d40057e4d73872c4a1af30460f..08575f3271f9e639f160594f61ac335de89a8bfa 100644 (file)
@@ -83,7 +83,7 @@ int AnalyzeBSPMain( int argc, char **argv ){
 
 
        /* arg checking */
-       if ( argc < 1 ) {
+       if ( argc < 2 ) {
                Sys_Printf( "Usage: q3map -analyze [-lumpswap] [-v] <mapname>\n" );
                return 0;
        }
index 33583126e0c4ffbc8a72c4cf97205c5880842217..55d358f0e69b65c9d5aa859bcb5036f12beb3d98 100644 (file)
@@ -94,9 +94,7 @@ void SetDrawVerts( int n ){
        numBSPDrawVerts = n;
        numBSPDrawVertsBuffer = numBSPDrawVerts;
 
-       bspDrawVerts = safe_malloc_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" );
-
-       memset( bspDrawVerts, 0, n * sizeof( bspDrawVert_t ) );
+       bspDrawVerts = safe_malloc0_info( sizeof( bspDrawVert_t ) * numBSPDrawVertsBuffer, "IncDrawVerts" );
 }
 
 int numBSPDrawSurfacesBuffer = 0;
@@ -107,9 +105,7 @@ void SetDrawSurfacesBuffer(){
 
        numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
 
-       bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
-
-       memset( bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( bspDrawSurface_t ) );
+       bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 }
 
 void SetDrawSurfaces( int n ){
@@ -120,9 +116,7 @@ void SetDrawSurfaces( int n ){
        numBSPDrawSurfaces = n;
        numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
 
-       bspDrawSurfaces = safe_malloc_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
-
-       memset( bspDrawSurfaces, 0, n * sizeof( bspDrawSurface_t ) );
+       bspDrawSurfaces = safe_malloc0_info( sizeof( bspDrawSurface_t ) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces" );
 }
 
 void BSPFilesCleanup(){
@@ -350,14 +344,16 @@ int CopyLump_Allocate( bspHeader_t *header, int lump, void **dest, int size, int
 void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length ){
        bspLump_t   *lump;
 
-
        /* add lump to bsp file header */
        lump = &header->lumps[ lumpNum ];
        lump->offset = LittleLong( ftell( file ) );
        lump->length = LittleLong( length );
 
        /* write lump to file */
-       SafeWrite( file, data, ( length + 3 ) & ~3 );
+       SafeWrite( file, data, length );
+
+       /* write padding zeros */
+       SafeWrite( file, (const byte[3]){ 0, 0, 0 }, ( ( length + 3 ) & ~3 ) - length );
 }
 
 
@@ -536,8 +532,7 @@ epair_t *ParseEPair( void ){
 
 
        /* allocate and clear new epair */
-       e = safe_malloc( sizeof( epair_t ) );
-       memset( e, 0, sizeof( epair_t ) );
+       e = safe_malloc0( sizeof( epair_t ) );
 
        /* handle key */
        if ( strlen( token ) >= ( MAX_KEY - 1 ) ) {
@@ -652,6 +647,9 @@ if (nocmdline)
 
        for ( i = beginArgs; i < endArgs; ++i )
        {
+               if ( argv[i] == NULL ) {
+                       continue;
+               }
                if ( outpos != sentinel && i != beginArgs ) {
                        *outpos++ = ' ';
                }
index c4daffd94644a4a339f83368a78101bfecd63f01..433d4457d220b41afe8593ef367d966c3cad14a1 100644 (file)
@@ -120,8 +120,7 @@ static void AddBrushSidesLump( FILE *file, ibspHeader_t *header ){
 
        /* allocate output buffer */
        size = numBSPBrushSides * sizeof( *buffer );
-       buffer = safe_malloc( size );
-       memset( buffer, 0, size );
+       buffer = safe_malloc0( size );
 
        /* convert */
        in = bspBrushSides;
@@ -232,8 +231,7 @@ static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header ){
 
        /* allocate output buffer */
        size = numBSPDrawSurfaces * sizeof( *buffer );
-       buffer = safe_malloc( size );
-       memset( buffer, 0, size );
+       buffer = safe_malloc0( size );
 
        /* convert */
        in = bspDrawSurfaces;
@@ -330,8 +328,7 @@ static void AddDrawVertsLump( FILE *file, ibspHeader_t *header ){
 
        /* allocate output buffer */
        size = numBSPDrawVerts * sizeof( *buffer );
-       buffer = safe_malloc( size );
-       memset( buffer, 0, size );
+       buffer = safe_malloc0( size );
 
        /* convert */
        in = bspDrawVerts;
@@ -385,8 +382,7 @@ static void CopyLightGridLumps( ibspHeader_t *header ){
        numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
 
        /* allocate buffer */
-       bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-       memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+       bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
 
        /* copy */
        in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
@@ -562,7 +558,6 @@ void WriteIBSPFile( const char *filename ){
        ibspHeader_t outheader, *header;
        FILE            *file;
        time_t t;
-       char marker[ 1024 ];
        int size;
 
 
@@ -581,9 +576,8 @@ void WriteIBSPFile( const char *filename ){
        SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );    /* overwritten later */
 
        /* add marker lump */
-       time( &t );
-       sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
-       AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
+       const char marker[] = "I LOVE MY Q3MAP2";
+       AddLump( file, header, 0, marker, strlen( marker ) + 1 );
 
        /* add lumps */
        AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
index b1ff0304dde7dd4888c53e77b6ae5df054cc12d6..598cf2de9dd75c44d30903de697095d60ed8f770 100644 (file)
@@ -96,8 +96,7 @@ static void CopyLightGridLumps( rbspHeader_t *header ){
        numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
 
        /* allocate buffer */
-       bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-       memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+       bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
 
        /* copy */
        inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
@@ -285,7 +284,6 @@ void WriteRBSPFile( const char *filename ){
        rbspHeader_t outheader, *header;
        FILE            *file;
        time_t t;
-       char marker[ 1024 ];
        int size;
 
 
@@ -304,9 +302,8 @@ void WriteRBSPFile( const char *filename ){
        SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );    /* overwritten later */
 
        /* add marker lump */
-       time( &t );
-       sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
-       AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
+       const char marker[] = "I LOVE MY Q3MAP2";
+       AddLump( file, header, 0, marker, strlen( marker ) + 1 );
 
        /* add lumps */
        AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
index 9db3260954f45cdaf5950eca08fb53ef6c67b533..9a0e05516e239e274470fea2a26fc3a4a67d7e58 100644 (file)
@@ -49,8 +49,7 @@ void PseudoCompileBSP( qboolean need_tree, const char *BSPFilePath, const char *
        int i;
 
        SetDrawSurfacesBuffer();
-       mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
-       memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+       mapDrawSurfs = safe_malloc0( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
        numMapDrawSurfs = 0;
 
        BeginBSPFile();
@@ -151,7 +150,7 @@ int ConvertBSPMain( int argc, char **argv ){
        force_map = qfalse;
 
        /* arg checking */
-       if ( argc < 1 ) {
+       if ( argc < 2 ) {
                Sys_Printf( "Usage: q3map -convert [-format <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\n" );
                return 0;
        }
index f7471c96ccea19869331abff927a067d81371b6f..dfa8dacec7e37636a6bfa34e267d4a493fded792 100644 (file)
@@ -620,8 +620,7 @@ static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds,
        ds2->lightmapScale = ds->lightmapScale;
        ds2->shadeAngleDegrees = ds->shadeAngleDegrees;
        ds2->numVerts = w->numpoints;
-       ds2->verts = safe_malloc( ds2->numVerts * sizeof( *ds2->verts ) );
-       memset( ds2->verts, 0, ds2->numVerts * sizeof( *ds2->verts ) );
+       ds2->verts = safe_malloc0( ds2->numVerts * sizeof( *ds2->verts ) );
 
        /* set vertexes */
        for ( i = 0; i < ds2->numVerts; i++ )
index b123660843acfc4cdfc7a962bf5d96c6bdae2cbc..50eed8978c66cc088820d73a7b4e1b319f5b226e 100644 (file)
@@ -90,7 +90,7 @@ void ExportEntities( void ){
 
 int ExportEntitiesMain( int argc, char **argv ){
         /* arg checking */
-        if ( argc < 1 ) {
+        if ( argc < 2 ) {
                 Sys_Printf( "Usage: q3map -exportents [-v] <mapname>\n" );
                 return 0;
         }
@@ -109,4 +109,4 @@ int ExportEntitiesMain( int argc, char **argv ){
                
         /* return to sender */
         return 0;
-}
\ No newline at end of file
+}
index e5390ede45a1fcc32da6a2893b4df1d17674e161..48cf798de98f0ef99ae14441b994626ea0ed1084 100644 (file)
@@ -49,8 +49,7 @@ int c_faceLeafs;
 face_t  *AllocBspFace( void ) {
        face_t  *f;
 
-       f = safe_malloc( sizeof( *f ) );
-       memset( f, 0, sizeof( *f ) );
+       f = safe_malloc0( sizeof( *f ) );
 
        return f;
 }
index a8bbec9cf1351ac715c4ed04eef22638a73545c3..a4a7441de5a34f776f8a40a8178db0d3b9f2ed9e 100644 (file)
@@ -58,6 +58,7 @@
        0,              /* max lightmapped surface verts */
        0,              /* max surface verts */
        0,              /* max surface indexes */
+       qfalse,         /* enable per shader prefix surface flags and .tex file */
        qfalse,         /* flares */
        NULL,           /* default flare shader */
        qfalse,         /* wolf lighting model? */
@@ -83,6 +84,7 @@
        qfalse,         /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        NULL,           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        NULL,           /* bsp file prefix */
        0,              /* bsp file version */
        qfalse,         /* cod-style lump len/ofs order */
index 2f998d24ee3f9f9b619f3690a4d812ef217aeaed..b697deb928fa900acd3ac0fc0f5014291b0830d5 100644 (file)
@@ -49,6 +49,7 @@
        999,                /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -74,6 +75,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 4d691b4662f227146ef5d7d64566fffec8a01901..66f1cd8378aa662ae8ff1b64275e814aef384839 100644 (file)
@@ -49,6 +49,7 @@
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -74,6 +75,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 9ef109038e31a590302ea8b31929b3b2eb06c2d4..bcb35b226a2fbecf4389f9c822c695648e710792 100644 (file)
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index f4303f2e63153470c2f3431d8d14567239c923f2..f02fdb0a3f79dd0c593dda6e200cb55afc6244e1 100644 (file)
        1024,               /* max lightmapped surface verts */
        1024,               /* max surface verts */
        6144,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        47,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index b598a09662d2270dba8d336850c3cc296eea2549..6265ba3cacf3f8f34dddb21749f77f28a4a84dcb 100644 (file)
@@ -62,6 +62,7 @@
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qtrue,              /* flares */
        "gfx/misc/flare",   /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -87,6 +88,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "RBSP",             /* bsp file prefix */
        1,                  /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 69c80edba4646785d069cd6e7ab6b5b44ee17416..52e1c9932f80c37f1d5a3a1dae7582b75065f9cc 100644 (file)
@@ -59,6 +59,7 @@
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qtrue,              /* flares */
        "gfx/misc/flare",   /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -84,6 +85,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "RBSP",             /* bsp file prefix */
        1,                  /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index f299f4d182e3e9c53a4b689c9f0871edd44776da..d91b1ae6803bb45bbfc09ac05ec6c3f53bf4352b 100644 (file)
@@ -58,6 +58,7 @@
        999,                /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -83,6 +84,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "../gfx/%s_mini.tga", /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
diff --git a/tools/quake3/q3map2/game_oa.h b/tools/quake3/q3map2/game_oa.h
new file mode 100644 (file)
index 0000000..293a6a8
--- /dev/null
@@ -0,0 +1,163 @@
+/* -------------------------------------------------------------------------------
+
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+   ----------------------------------------------------------------------------------
+
+   This code has been altered significantly from its original form, to support
+   several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+   ------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_OPENARENA_H
+#define GAME_OPENARENA_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+   content and surface flags
+
+   ------------------------------------------------------------------------------- */
+
+// reuses defines from game_quake3.h
+
+
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "oa",               /* -game x */
+       "baseoa",           /* default base game data dir */
+       ".openarena",       /* unix home sub-dir */
+       "openarena",        /* magic path word */
+       "scripts",          /* shader directory */
+       64,                 /* max lightmapped surface verts */
+       999,                /* max surface verts */
+       6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
+       qfalse,             /* flares */
+       "flareshader",      /* default flare shader */
+       qfalse,             /* wolf lighting model? */
+       128,                /* lightmap width/height */
+       1.0f,               /* lightmap gamma */
+       qfalse,             /* lightmap sRGB */
+       qfalse,             /* texture sRGB */
+       qfalse,             /* color sRGB */
+       0.0f,               /* lightmap exposure */
+       1.0f,               /* lightmap compensate */
+       1.0f,               /* lightgrid scale */
+       1.0f,               /* lightgrid ambient scale */
+       qfalse,             /* light angle attenuation uses half-lambert curve */
+       qfalse,             /* disable shader lightstyles hack */
+       qfalse,             /* keep light entities on bsp */
+       8,                  /* default patchMeta subdivisions tolerance */
+       qfalse,             /* patch casting enabled */
+       qfalse,             /* compile deluxemaps */
+       0,                  /* deluxemaps default mode */
+       512,                /* minimap size */
+       1.0f,               /* minimap sharpener */
+       0.0f,               /* minimap border */
+       qtrue,              /* minimap keep aspect */
+       MINIMAP_MODE_GRAY,  /* minimap mode */
+       "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
+       "IBSP",             /* bsp file prefix */
+       46,                 /* bsp file version */
+       qfalse,             /* cod-style lump len/ofs order */
+       LoadIBSPFile,       /* bsp load function */
+       WriteIBSPFile,      /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        Q_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         Q_CONT_ORIGIN,              Q_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     Q_CONT_AREAPORTAL,          Q_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          Q_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         Q_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     Q_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          Q_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          Q_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          Q_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          Q_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          Q_CONT_SOLID,               Q_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        Q_CONT_TRIGGER,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          Q_CONT_WATER,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          Q_CONT_SLIME,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           Q_CONT_LAVA,                Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     Q_CONT_PLAYERCLIP,          Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    Q_CONT_MONSTERCLIP,         Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         Q_CONT_NODROP,              Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  Q_CONT_CLUSTERPORTAL,       Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     Q_CONT_DONOTENTER,          Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        Q_CONT_BOTCLIP,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            Q_CONT_FOG,                 Q_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          Q_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          Q_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          Q_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          Q_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          Q_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          Q_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          Q_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          Q_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          Q_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          Q_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          Q_SURF_DUST,                0,                          0,                          0 },
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+
+
+/* end marker */
+#endif
index a5e11cb73e76363156583fd07d5294c8cd1dd5d7..e446057ba7542a7969a7bc5e9866f5bb6b4eadcd 100644 (file)
@@ -49,6 +49,7 @@
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -74,6 +75,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
diff --git a/tools/quake3/q3map2/game_q3rally.h b/tools/quake3/q3map2/game_q3rally.h
new file mode 100644 (file)
index 0000000..628859e
--- /dev/null
@@ -0,0 +1,163 @@
+/* -------------------------------------------------------------------------------
+
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+   ----------------------------------------------------------------------------------
+
+   This code has been altered significantly from its original form, to support
+   several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+   ------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_Q3RALLY_H
+#define GAME_Q3RALLY_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+   content and surface flags
+
+   ------------------------------------------------------------------------------- */
+
+// reuses defines from game_quake3.h
+
+
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "q3rally",          /* -game x */
+       "baseq3r",          /* default base game data dir */
+       ".q3rally",         /* unix home sub-dir */
+       "q3rally",          /* magic path word */
+       "scripts",          /* shader directory */
+       64,                 /* max lightmapped surface verts */
+       999,                /* max surface verts */
+       6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
+       qfalse,             /* flares */
+       "flareshader",      /* default flare shader */
+       qfalse,             /* wolf lighting model? */
+       128,                /* lightmap width/height */
+       1.0f,               /* lightmap gamma */
+       qfalse,             /* lightmap sRGB */
+       qfalse,             /* texture sRGB */
+       qfalse,             /* color sRGB */
+       0.0f,               /* lightmap exposure */
+       1.0f,               /* lightmap compensate */
+       1.0f,               /* lightgrid scale */
+       1.0f,               /* lightgrid ambient scale */
+       qfalse,             /* light angle attenuation uses half-lambert curve */
+       qfalse,             /* disable shader lightstyles hack */
+       qfalse,             /* keep light entities on bsp */
+       8,                  /* default patchMeta subdivisions tolerance */
+       qfalse,             /* patch casting enabled */
+       qfalse,             /* compile deluxemaps */
+       0,                  /* deluxemaps default mode */
+       512,                /* minimap size */
+       1.0f,               /* minimap sharpener */
+       0.0f,               /* minimap border */
+       qtrue,              /* minimap keep aspect */
+       MINIMAP_MODE_GRAY,  /* minimap mode */
+       "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
+       "IBSP",             /* bsp file prefix */
+       46,                 /* bsp file version */
+       qfalse,             /* cod-style lump len/ofs order */
+       LoadIBSPFile,       /* bsp load function */
+       WriteIBSPFile,      /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        Q_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         Q_CONT_ORIGIN,              Q_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     Q_CONT_AREAPORTAL,          Q_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          Q_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         Q_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     Q_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          Q_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          Q_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          Q_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          Q_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          Q_CONT_SOLID,               Q_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        Q_CONT_TRIGGER,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          Q_CONT_WATER,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          Q_CONT_SLIME,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           Q_CONT_LAVA,                Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     Q_CONT_PLAYERCLIP,          Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    Q_CONT_MONSTERCLIP,         Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         Q_CONT_NODROP,              Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  Q_CONT_CLUSTERPORTAL,       Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     Q_CONT_DONOTENTER,          Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        Q_CONT_BOTCLIP,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            Q_CONT_FOG,                 Q_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          Q_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          Q_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          Q_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          Q_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          Q_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          Q_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          Q_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          Q_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          Q_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          Q_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          Q_SURF_DUST,                0,                          0,                          0 },
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+
+
+/* end marker */
+#endif
index 5cd5b0386648ffc7c493778cfddf107399b2fad4..1348724bb1ea92fcb45099d464aa614ad5fb2da5 100644 (file)
        65535,              /* max lightmapped surface verts */
        65535,              /* max surface verts */
        393210,             /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "../minimaps/%s.tga", /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "FBSP",             /* bsp file prefix */
        1,                  /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 3526a781c1020e8d831b313785ef535839ae4339..6362369ae085e42e09e6807ba688ec036a0af21c 100644 (file)
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 3f7a29daa659119121701e1b59164a702223e7b5..df368a9562a3a2a644c955980bbaca7c12853f1b 100644 (file)
 {
        "quakelive",        /* -game x */
        "baseq3",           /* default base game data dir */
-       ".quakelive/quakelive/home",             /* unix home sub-dir */
+       ".quakelive",       /* unix home sub-dir */
        "quake",            /* magic path word */
        "scripts",          /* shader directory */
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -96,6 +97,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        47,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 2474274e73fbb9bf5a56d82637818e8a67b1e381..ab26f9ebc94cfadc06b6c4d419a226981f5a35c5 100644 (file)
    ------------------------------------------------------------------------------- */
 
 #define REACTION_SURF_GRAVEL    0x80000
-#define REACTION_SURF_WOOD  0x81000
+#define REACTION_SURF_WOOD      0x81000
 #define REACTION_SURF_CARPET    0x100000
 #define REACTION_SURF_METAL2    0x101000
-#define REACTION_SURF_GLASS 0x180000
-#define REACTION_SURF_GRASS 0x181000
-#define REACTION_SURF_SNOW  0x200000
-#define REACTION_SURF_MUD   0x201000
-#define REACTION_SURF_WOOD2 0x280000
+#define REACTION_SURF_GLASS     0x180000
+#define REACTION_SURF_GRASS     0x181000
+#define REACTION_SURF_SNOW      0x200000
+#define REACTION_SURF_MUD       0x201000
+#define REACTION_SURF_WOOD2     0x280000
 #define REACTION_SURF_HARDMETAL 0x281000
 #define REACTION_SURF_LEAVES    0x300000
 #define REACTION_SURF_CEMENT    0x301000
 #define REACTION_SURF_MARBLE    0x380000
-#define REACTION_SURF_SNOW2 0x381000
+#define REACTION_SURF_SNOW2     0x381000
 #define REACTION_SURF_HARDSTEPS 0x400000
-#define REACTION_SURF_SAND  0x401000
+#define REACTION_SURF_SAND      0x401000
 
 
 
@@ -79,6 +79,7 @@
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
diff --git a/tools/quake3/q3map2/game_smokinguns.h b/tools/quake3/q3map2/game_smokinguns.h
new file mode 100644 (file)
index 0000000..6f6a594
--- /dev/null
@@ -0,0 +1,179 @@
+/* -------------------------------------------------------------------------------
+
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_SMOKINGUNS_H
+#define GAME_SMOKINGUNS_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags - also uses defines from game_quake3.h
+
+------------------------------------------------------------------------------- */
+
+/* game flags */
+
+// support content making dynamite explodes and molotov burns
+#define SG_CONT_EXPLOSIVE              2
+#define SG_CONT_FLAMMABLE              4
+#define SG_CONT_BURNING_SOLID  (Q_CONT_SOLID | SG_CONT_EXPLOSIVE | SG_CONT_FLAMMABLE )
+
+// see q3map2.h for tex surface flags
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "smokinguns",           /* -game x */
+       "smokinguns",           /* default base game data dir */
+       ".smokinguns",          /* unix home sub-dir */
+       "smokinguns",           /* magic path word */
+       "scripts",              /* shader directory */
+       1048575,                /* max lightmapped surface verts */
+       1048575,                /* max surface verts */
+       1048575,                /* max surface indexes */
+       qtrue,                  /* enable per shader prefix surface flags and .tex file */
+       qfalse,                 /* flares */
+       "flareshader",          /* default flare shader */
+       qfalse,                 /* wolf lighting model? */
+       128,                    /* lightmap width/height */
+       1.0f,                   /* lightmap gamma */
+       qfalse,                 /* lightmap sRGB */
+       qfalse,                 /* texture sRGB */
+       qfalse,                 /* color sRGB */
+       0.0f,                   /* lightmap exposure */
+       1.0f,                   /* lightmap compensate */
+       1.0f,                   /* lightgrid scale */
+       1.0f,                   /* lightgrid ambient scale */
+       qfalse,                 /* light angle attenuation uses half-lambert curve */
+       qfalse,                 /* disable shader lightstyles hack */
+       qtrue,                  /* keep light entities on bsp */
+       8,                      /* default patchMeta subdivisions tolerance */
+       qfalse,                 /* patch casting enabled */
+       qfalse,                 /* compile deluxemaps */
+       0,                      /* deluxemaps default mode */
+       512,                    /* minimap size */
+       1.0f,                   /* minimap sharpener */
+       0.0f,                   /* minimap border */
+       qtrue,                  /* minimap keep aspect */
+       MINIMAP_MODE_WHITE,     /* minimap mode */
+       "../minimaps/%s.tga",   /* minimap name format */
+       MINIMAP_SIDECAR_UNVANQUISHED, /* minimap sidecar format */
+       "IBSP",                 /* bsp file prefix */
+       46,                     /* bsp file version */
+       qfalse,                 /* cod-style lump len/ofs order */
+       LoadIBSPFile,           /* bsp load function */
+       WriteIBSPFile,          /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        Q_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         Q_CONT_ORIGIN,              Q_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     Q_CONT_AREAPORTAL,          Q_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          Q_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         Q_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     Q_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          Q_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          Q_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          Q_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          Q_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          Q_CONT_SOLID,               Q_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        Q_CONT_TRIGGER,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          Q_CONT_WATER,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          Q_CONT_SLIME,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           Q_CONT_LAVA,                SG_CONT_BURNING_SOLID,      0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     Q_CONT_PLAYERCLIP,          Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    Q_CONT_MONSTERCLIP,         Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         Q_CONT_NODROP,              Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  Q_CONT_CLUSTERPORTAL,       Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     Q_CONT_DONOTENTER,          Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        Q_CONT_BOTCLIP,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            Q_CONT_FOG,                 Q_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          Q_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          Q_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          Q_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          Q_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          Q_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          Q_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          Q_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          Q_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          Q_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          Q_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          Q_SURF_DUST,                0,                          0,                          0 },
+
+               /* materials */
+               { "metal",          0,                          0,                          TEX_SURF_METAL,        0,                          0,                          0 },
+               { "wood",           0,                          0,                          TEX_SURF_WOOD,              0,                          0,                          0 },
+               { "cloth",          0,                          0,                          TEX_SURF_CLOTH,             0,                          0,                          0 },
+               { "dirt",           0,                          0,                          TEX_SURF_DIRT,              0,                          0,                          0 },
+               { "glass",          0,                          0,                          TEX_SURF_GLASS,             0,                          0,                          0 },
+               { "plant",          0,                          0,                          TEX_SURF_PLANT,             0,                          0,                          0 },
+               { "sand",           0,                          0,                          TEX_SURF_SAND,              0,                          0,                          0 },
+               { "snow",           0,                          0,                          TEX_SURF_SNOW,              0,                          0,                          0 },
+               { "stone",          0,                          0,                          TEX_SURF_STONE,             0,                          0,                          0 },
+               { "water",          0,                          0,                          TEX_SURF_WATER,             0,                          0,                          0 },
+               { "grass",          0,                          0,                          TEX_SURF_GRASS,             0,                          0,                          0 }, 
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+/* end marker */
+#endif
index 2e72270b0d636f64a7f9461e284d79e49beffd18..2ca335ace5a6863dc7fed8a8f495872b75b11367 100644 (file)
        64,                     /* max lightmapped surface verts */
        999,                    /* max surface verts */
        6000,                   /* max surface indexes */
+       qfalse,                 /* enable per shader prefix surface flags and .tex file */
        qtrue,                  /* flares */
        "gfx/misc/lens_flare",  /* default flare shader */
        qfalse,                 /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "RBSP",                 /* bsp file prefix */
        1,                      /* bsp file version */
        qfalse,                 /* cod-style lump len/ofs order */
index 243f756c0ee1d6d068813880afe9ac4c2f9ee43c..debe6c1c796cf68f0fd8b4679da4ab92021013f0 100644 (file)
        1024,               /* max lightmapped surface verts */
        1024,               /* max surface verts */
        6144,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index 6853e61746f9b4ac7cf6428d96b91d73b4f445ea..6a5fd0f1f4777c89ce55337360e83a3a1ca5fce2 100644 (file)
@@ -40,6 +40,7 @@
    content and surface flags - also uses defines from game_quake3.h
 
    ------------------------------------------------------------------------------- */
+
 #define TREM_CONT_NOALIENBUILD         0x1000
 #define TREM_CONT_NOHUMANBUILD         0x2000
 #define TREM_CONT_NOBUILD              0x4000
    ------------------------------------------------------------------------------- */
 
 {
-       "tremulous",            /* -game x */
-       "base",         /* default base game data dir */
-       ".tremulous",               /* unix home sub-dir */
-       "tremulous",            /* magic path word - think this is right for trem*/
+       "tremulous",        /* -game x */
+       "base",             /* default base game data dir */
+       ".tremulous",       /* unix home sub-dir */
+       "tremulous",        /* magic path word - think this is right for trem*/
        "scripts",          /* shader directory */
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qfalse,             /* wolf lighting model? */
@@ -90,6 +92,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        46,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index cf749731303e6b9750541f6eb6cf89b9f6fd88ef..b3cb4f572ddfbb150f4b2d9f4d6e88f9b46e9b8c 100644 (file)
@@ -61,12 +61,13 @@ game_t struct
 {
        "unvanquished",         /* -game x */
        "pkg",                  /* default base game data dir */
-       ".local/share/unvanquished", /* unix home sub-dir */
+       ".unvanquished",        /* unix home sub-dir */
        "unvanquished",         /* magic path word */
        "scripts",              /* shader directory */
        1048575,                /* max lightmapped surface verts */
        1048575,                /* max surface verts */
        1048575,                /* max surface indexes */
+       qfalse,                 /* enable per shader prefix surface flags and .tex file */
        qfalse,                 /* flares */
        "flareshader",          /* default flare shader */
        qfalse,                 /* wolf lighting model? */
@@ -92,6 +93,7 @@ game_t struct
        qtrue,                  /* minimap keep aspect */
        MINIMAP_MODE_WHITE,     /* minimap mode */
        "../minimaps/%s.tga",   /* minimap name format */
+       MINIMAP_SIDECAR_UNVANQUISHED, /* minimap sidecar format */
        "IBSP",                 /* bsp file prefix */
        46,                     /* bsp file version */
        qfalse,                 /* cod-style lump len/ofs order */
diff --git a/tools/quake3/q3map2/game_warfork.h b/tools/quake3/q3map2/game_warfork.h
new file mode 100644 (file)
index 0000000..44cf39e
--- /dev/null
@@ -0,0 +1,167 @@
+/* -------------------------------------------------------------------------------
+
+   This code is based on source provided under the terms of the Id Software
+   LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with the
+   GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of
+   LICENSE_ID, please contact Id Software immediately at info@idsoftware.com.
+
+   All changes and additions to the original source which have been developed by
+   other contributors (see CONTRIBUTORS) are provided under the terms of the
+   license the contributors choose (see LICENSE), to the extent permitted by the
+   LICENSE_ID. If you did not receive a copy of the contributor license,
+   please contact the GtkRadiant maintainers at info@gtkradiant.com immediately.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------------------------
+
+   This code has been altered significantly from its original form, to support
+   several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+   ------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_WARFORK_H
+#define GAME_WARFORK_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+   content and surface flags
+
+   ------------------------------------------------------------------------------- */
+
+// reuses defines from game_qfusion.h
+
+
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "warfork",          /* -game x */
+       "basewf",           /* default base game data dir */
+       ".warfork",         /* unix home sub-dir */
+       "warfork",          /* magic path word */
+       "scripts",          /* shader directory */
+       65535,              /* max lightmapped surface verts */
+       65535,              /* max surface verts */
+       393210,             /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
+       qfalse,             /* flares */
+       "flareshader",      /* default flare shader */
+       qfalse,             /* wolf lighting model? */
+       512,                /* lightmap width/height */
+       1.0f,               /* lightmap gamma */
+       qtrue,              /* lightmap sRGB */
+       qtrue,              /* texture sRGB */
+       qtrue,              /* color sRGB */
+       0.0f,               /* lightmap exposure */
+       1.0f,               /* lightmap compensate */
+       1.0f,               /* lightgrid scale */
+       1.0f,               /* lightgrid ambient scale */
+       qtrue,              /* light angle attenuation uses half-lambert curve */
+       qtrue,              /* disable shader lightstyles hack */
+       qtrue,              /* keep light entities on bsp */
+       4,                  /* default patchMeta subdivisions tolerance */
+       qtrue,              /* patch casting enabled */
+       qtrue,              /* compile deluxemaps */
+       0,                  /* deluxemaps default mode */
+       512,                /* minimap size */
+       1.0f,               /* minimap sharpener */
+       1.0f / 66.0f,       /* minimap border */
+       qtrue,              /* minimap keep aspect */
+       MINIMAP_MODE_GRAY,  /* minimap mode */
+       "../minimaps/%s.tga", /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
+       "FBSP",             /* bsp file prefix */
+       1,                  /* bsp file version */
+       qfalse,             /* cod-style lump len/ofs order */
+       LoadRBSPFile,       /* bsp load function */
+       WriteRBSPFile,      /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        F_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         F_CONT_ORIGIN,              F_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     F_CONT_AREAPORTAL,          F_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          F_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         F_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     F_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          F_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          F_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          F_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          F_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          F_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          F_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          F_CONT_SOLID,               F_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        F_CONT_TRIGGER,             F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          F_CONT_WATER,               F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          F_CONT_SLIME,               F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           F_CONT_LAVA,                F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     F_CONT_PLAYERCLIP,          F_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    F_CONT_MONSTERCLIP,         F_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         F_CONT_NODROP,              F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  F_CONT_CLUSTERPORTAL,       F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     F_CONT_DONOTENTER,          F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        F_CONT_BOTCLIP,             F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            F_CONT_FOG,                 F_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          F_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          F_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          F_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          F_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          F_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          F_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          F_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          F_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          F_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          F_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          F_SURF_DUST,                0,                          0,                          0 },
+
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+
+
+/* end marker */
+#endif
diff --git a/tools/quake3/q3map2/game_warsow.h b/tools/quake3/q3map2/game_warsow.h
new file mode 100644 (file)
index 0000000..e10355f
--- /dev/null
@@ -0,0 +1,167 @@
+/* -------------------------------------------------------------------------------
+
+   This code is based on source provided under the terms of the Id Software
+   LIMITED USE SOFTWARE LICENSE AGREEMENT, a copy of which is included with the
+   GtkRadiant sources (see LICENSE_ID). If you did not receive a copy of
+   LICENSE_ID, please contact Id Software immediately at info@idsoftware.com.
+
+   All changes and additions to the original source which have been developed by
+   other contributors (see CONTRIBUTORS) are provided under the terms of the
+   license the contributors choose (see LICENSE), to the extent permitted by the
+   LICENSE_ID. If you did not receive a copy of the contributor license,
+   please contact the GtkRadiant maintainers at info@gtkradiant.com immediately.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+   DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+   ----------------------------------------------------------------------------------
+
+   This code has been altered significantly from its original form, to support
+   several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+   ------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_WARSOW_H
+#define GAME_WARSOW_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+   content and surface flags
+
+   ------------------------------------------------------------------------------- */
+
+// reuses defines from game_qfusion.h
+
+
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "warsow",           /* -game x */
+       "basewsw",          /* default base game data dir */
+       ".warsow",          /* unix home sub-dir */
+       "warsow",           /* magic path word */
+       "scripts",          /* shader directory */
+       65535,              /* max lightmapped surface verts */
+       65535,              /* max surface verts */
+       393210,             /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
+       qfalse,             /* flares */
+       "flareshader",      /* default flare shader */
+       qfalse,             /* wolf lighting model? */
+       512,                /* lightmap width/height */
+       1.0f,               /* lightmap gamma */
+       qtrue,              /* lightmap sRGB */
+       qtrue,              /* texture sRGB */
+       qtrue,              /* color sRGB */
+       0.0f,               /* lightmap exposure */
+       1.0f,               /* lightmap compensate */
+       1.0f,               /* lightgrid scale */
+       1.0f,               /* lightgrid ambient scale */
+       qtrue,              /* light angle attenuation uses half-lambert curve */
+       qtrue,              /* disable shader lightstyles hack */
+       qtrue,              /* keep light entities on bsp */
+       4,                  /* default patchMeta subdivisions tolerance */
+       qtrue,              /* patch casting enabled */
+       qtrue,              /* compile deluxemaps */
+       0,                  /* deluxemaps default mode */
+       512,                /* minimap size */
+       1.0f,               /* minimap sharpener */
+       1.0f / 66.0f,       /* minimap border */
+       qtrue,              /* minimap keep aspect */
+       MINIMAP_MODE_GRAY,  /* minimap mode */
+       "../minimaps/%s.tga", /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
+       "FBSP",             /* bsp file prefix */
+       1,                  /* bsp file version */
+       qfalse,             /* cod-style lump len/ofs order */
+       LoadRBSPFile,       /* bsp load function */
+       WriteRBSPFile,      /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        F_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         F_CONT_ORIGIN,              F_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     F_CONT_AREAPORTAL,          F_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          F_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         F_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     F_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          F_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          F_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          F_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          F_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          F_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          F_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          F_CONT_SOLID,               F_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        F_CONT_TRIGGER,             F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          F_CONT_WATER,               F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          F_CONT_SLIME,               F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           F_CONT_LAVA,                F_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     F_CONT_PLAYERCLIP,          F_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    F_CONT_MONSTERCLIP,         F_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         F_CONT_NODROP,              F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  F_CONT_CLUSTERPORTAL,       F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     F_CONT_DONOTENTER,          F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        F_CONT_BOTCLIP,             F_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            F_CONT_FOG,                 F_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          F_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          F_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          F_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          F_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          F_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          F_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          F_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          F_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          F_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          F_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          F_SURF_DUST,                0,                          0,                          0 },
+
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+
+
+/* end marker */
+#endif
index fcfd17ec964f65a877d118b9b496d3fd3f995a62..81e2c22a21df0bfc2481d133518f25d6d1d11add 100644 (file)
        64,                 /* max lightmapped surface verts */
        999,                /* max surface verts */
        6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qtrue,              /* wolf lighting model? */
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        47,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
index c783b9a0805a89a4b3d7799171668c8ab2f57f1c..ee520627498649125a263162c4e8f07f830298ff 100644 (file)
@@ -61,6 +61,7 @@
        1024,               /* max lightmapped surface verts */
        1024,               /* max surface verts */
        6144,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
        qfalse,             /* flares */
        "flareshader",      /* default flare shader */
        qtrue,              /* wolf lighting model? */
@@ -86,6 +87,7 @@
        qtrue,              /* minimap keep aspect */
        MINIMAP_MODE_GRAY,  /* minimap mode */
        "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP",             /* bsp file prefix */
        47,                 /* bsp file version */
        qfalse,             /* cod-style lump len/ofs order */
diff --git a/tools/quake3/q3map2/game_wop.h b/tools/quake3/q3map2/game_wop.h
new file mode 100644 (file)
index 0000000..37502af
--- /dev/null
@@ -0,0 +1,163 @@
+/* -------------------------------------------------------------------------------
+
+   Copyright (C) 1999-2007 id Software, Inc. and contributors.
+   For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+   This file is part of GtkRadiant.
+
+   GtkRadiant is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   GtkRadiant is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GtkRadiant; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+   ----------------------------------------------------------------------------------
+
+   This code has been altered significantly from its original form, to support
+   several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+   ------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_WOP_H
+#define GAME_WOP_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+   content and surface flags
+
+   ------------------------------------------------------------------------------- */
+
+// reuses defines from game_quake3.h
+
+
+
+/* -------------------------------------------------------------------------------
+
+   game_t struct
+
+   ------------------------------------------------------------------------------- */
+
+{
+       "wop",              /* -game x */
+       "wop",              /* default base game data dir */
+       ".WoPadman",        /* unix home sub-dir */
+       "wop",              /* magic path word */
+       "scripts",          /* shader directory */
+       64,                 /* max lightmapped surface verts */
+       999,                /* max surface verts */
+       6000,               /* max surface indexes */
+       qfalse,             /* enable per shader prefix surface flags and .tex file */
+       qfalse,             /* flares */
+       "flareshader",      /* default flare shader */
+       qfalse,             /* wolf lighting model? */
+       128,                /* lightmap width/height */
+       1.0f,               /* lightmap gamma */
+       qfalse,             /* lightmap sRGB */
+       qfalse,             /* texture sRGB */
+       qfalse,             /* color sRGB */
+       0.0f,               /* lightmap exposure */
+       1.0f,               /* lightmap compensate */
+       1.0f,               /* lightgrid scale */
+       1.0f,               /* lightgrid ambient scale */
+       qfalse,             /* light angle attenuation uses half-lambert curve */
+       qfalse,             /* disable shader lightstyles hack */
+       qfalse,             /* keep light entities on bsp */
+       8,                  /* default patchMeta subdivisions tolerance */
+       qfalse,             /* patch casting enabled */
+       qfalse,             /* compile deluxemaps */
+       0,                  /* deluxemaps default mode */
+       512,                /* minimap size */
+       1.0f,               /* minimap sharpener */
+       0.0f,               /* minimap border */
+       qtrue,              /* minimap keep aspect */
+       MINIMAP_MODE_GRAY,  /* minimap mode */
+       "%s.tga",           /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
+       "IBSP",             /* bsp file prefix */
+       46,                 /* bsp file version */
+       qfalse,             /* cod-style lump len/ofs order */
+       LoadIBSPFile,       /* bsp load function */
+       WriteIBSPFile,      /* bsp write function */
+
+       {
+               /* name                         contentFlags                            contentFlagsClear                       surfaceFlags                            surfaceFlagsClear                       compileFlags                            compileFlagsClear */
+
+               /* default */
+               { "default",        Q_CONT_SOLID,               -1,                         0,                          -1,                         C_SOLID,                    -1 },
+
+
+               /* ydnar */
+               { "lightgrid",      0,                          0,                          0,                          0,                          C_LIGHTGRID,                0 },
+               { "antiportal",     0,                          0,                          0,                          0,                          C_ANTIPORTAL,               0 },
+               { "skip",           0,                          0,                          0,                          0,                          C_SKIP,                     0 },
+
+
+               /* compiler */
+               { "origin",         Q_CONT_ORIGIN,              Q_CONT_SOLID,               0,                          0,                          C_ORIGIN | C_TRANSLUCENT,   C_SOLID },
+               { "areaportal",     Q_CONT_AREAPORTAL,          Q_CONT_SOLID,               0,                          0,                          C_AREAPORTAL | C_TRANSLUCENT,   C_SOLID },
+               { "trans",          Q_CONT_TRANSLUCENT,         0,                          0,                          0,                          C_TRANSLUCENT,              0 },
+               { "detail",         Q_CONT_DETAIL,              0,                          0,                          0,                          C_DETAIL,                   0 },
+               { "structural",     Q_CONT_STRUCTURAL,          0,                          0,                          0,                          C_STRUCTURAL,               0 },
+               { "hint",           0,                          0,                          Q_SURF_HINT,                0,                          C_HINT,                     0 },
+               { "nodraw",         0,                          0,                          Q_SURF_NODRAW,              0,                          C_NODRAW,                   0 },
+
+               { "alphashadow",    0,                          0,                          Q_SURF_ALPHASHADOW,         0,                          C_ALPHASHADOW | C_TRANSLUCENT,  0 },
+               { "lightfilter",    0,                          0,                          Q_SURF_LIGHTFILTER,         0,                          C_LIGHTFILTER | C_TRANSLUCENT,  0 },
+               { "nolightmap",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+               { "pointlight",     0,                          0,                          Q_SURF_VERTEXLIT,           0,                          C_VERTEXLIT,                0 },
+
+
+               /* game */
+               { "nonsolid",       0,                          Q_CONT_SOLID,               Q_SURF_NONSOLID,            0,                          0,                          C_SOLID },
+
+               { "trigger",        Q_CONT_TRIGGER,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "water",          Q_CONT_WATER,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "slime",          Q_CONT_SLIME,               Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+               { "lava",           Q_CONT_LAVA,                Q_CONT_SOLID,               0,                          0,                          C_LIQUID | C_TRANSLUCENT,   C_SOLID },
+
+               { "playerclip",     Q_CONT_PLAYERCLIP,          Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "monsterclip",    Q_CONT_MONSTERCLIP,         Q_CONT_SOLID,               0,                          0,                          C_DETAIL | C_TRANSLUCENT,   C_SOLID },
+               { "nodrop",         Q_CONT_NODROP,              Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "clusterportal",  Q_CONT_CLUSTERPORTAL,       Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "donotenter",     Q_CONT_DONOTENTER,          Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+               { "botclip",        Q_CONT_BOTCLIP,             Q_CONT_SOLID,               0,                          0,                          C_TRANSLUCENT,              C_SOLID },
+
+               { "fog",            Q_CONT_FOG,                 Q_CONT_SOLID,               0,                          0,                          C_FOG,                      C_SOLID },
+               { "sky",            0,                          0,                          Q_SURF_SKY,                 0,                          C_SKY,                      0 },
+
+               { "slick",          0,                          0,                          Q_SURF_SLICK,               0,                          0,                          0 },
+
+               { "noimpact",       0,                          0,                          Q_SURF_NOIMPACT,            0,                          0,                          0 },
+               { "nomarks",        0,                          0,                          Q_SURF_NOMARKS,             0,                          C_NOMARKS,                  0 },
+               { "ladder",         0,                          0,                          Q_SURF_LADDER,              0,                          0,                          0 },
+               { "nodamage",       0,                          0,                          Q_SURF_NODAMAGE,            0,                          0,                          0 },
+               { "metalsteps",     0,                          0,                          Q_SURF_METALSTEPS,          0,                          0,                          0 },
+               { "flesh",          0,                          0,                          Q_SURF_FLESH,               0,                          0,                          0 },
+               { "nosteps",        0,                          0,                          Q_SURF_NOSTEPS,             0,                          0,                          0 },
+               { "nodlight",       0,                          0,                          Q_SURF_NODLIGHT,            0,                          0,                          0 },
+               { "dust",           0,                          0,                          Q_SURF_DUST,                0,                          0,                          0 },
+
+               /* null */
+               { NULL, 0, 0, 0, 0, 0, 0 }
+       }
+}
+
+
+
+/* end marker */
+#endif
index b0ac53959b5f1a1691bad763da742fda6eb9e3b0..97ccff222d5ac7cbfccabd2032db83e9374d4c73 100644 (file)
@@ -58,6 +58,7 @@
        1048575, /* max lightmapped surface verts */
        1048575, /* max surface verts */
        1048575, /* max surface indexes */
+       qfalse, /* enable per shader prefix surface flags and .tex file */
        qfalse, /* flares */
        "flareshader", /* default flare shader */
        qfalse, /* wolf lighting model? */
@@ -83,6 +84,7 @@
        qtrue, /* minimap keep aspect */
        MINIMAP_MODE_GRAY, /* minimap mode */
        "../gfx/%s_mini.tga", /* minimap name format */
+       MINIMAP_SIDECAR_NONE, /* minimap sidecar format */
        "IBSP", /* bsp file prefix */
        46, /* bsp file version */
        qfalse, /* cod-style lump len/ofs order */
index 104213b2724062f39389878b2e37dab4bcf83032..60631e3d72f175a38c581b28a50df232ea8289ab 100644 (file)
 /* dependencies */
 #include "q3map2.h"
 
+#if GDEF_OS_POSIX
+#include <sys/ioctl.h>
+#endif // GDEF_OS_POSIX
 
+static unsigned terminalColumns = 80;
 
 struct HelpOption
 {
@@ -39,6 +43,7 @@ struct HelpOption
        const char* description;
 };
 
+// FIXME: low column width cause an endless loop
 void HelpOptions(const char* group_name, int indentation, int width, struct HelpOption* options, int count)
 {
        indentation *= 2;
@@ -68,6 +73,7 @@ void HelpOptions(const char* group_name, int indentation, int width, struct Help
                        putchar('\n');
                        printed = indentation+26;
                }
+
                if ( j == 0 )
                {
                        printf("%s\n",options[i].description+j);
@@ -86,7 +92,7 @@ void HelpOptions(const char* group_name, int indentation, int width, struct Help
 void HelpBsp()
 {
        struct HelpOption bsp[] = {
-               {"-bsp <filename.map>", "Switch that enters this stage"},
+               {"-bsp [options] <filename.map>", "Switch that enters this stage"},
                {"-altsplit", "Alternate BSP tree splitting weights (should give more fps)"},
                {"-bspfile <filename.bsp>", "BSP file to write"},
                {"-celshader <shadername>", "Sets a global cel shader name"},
@@ -97,21 +103,33 @@ void HelpBsp()
                {"-deep", "Use detail brushes in the BSP tree, but at lowest priority (should give more fps)"},
                {"-de <F>", "Distance epsilon for plane snapping etc."},
                {"-fakemap", "Write fakemap.map containing all world brushes"},
-               {"-flares", "Turn on support for flares (TEST?)"},
+               {"-fastmeta", "Use small lightmap/surface verts/number maximum numbers (like Q3A), to be used with `-meta`"},
+               {"-flares", "Turn on support for flares"},
                {"-flat", "Enable flat shading (good for combining with -celshader)"},
                {"-fulldetail", "Treat detail brushes as structural ones"},
+               {"-keeplights", "Keep light entities in the BSP file after compile"},
                {"-leaktest", "Abort if a leak was found"},
                {"-linfile <filename.lin>", "Line file to write"},
+               {"-maxarea", "Use Max Area face surface generation"},
+               {"-maxlightmapvertices <N>", "Sets the maximum number of vertices per lightmapped surface"},
+               {"-maxsurfaceindexes <N>", "Sets the maximum number of indexes per surface"},
+               {"-maxsurfacevertices <N>", "Sets the maximum number of vertices per surface"},
                {"-meta", "Combine adjacent triangles of the same texture to surfaces (ALWAYS USE THIS)"},
+               {"-metaadequatescore <N>", "Adequate score for adding triangles to meta surfaces"},
+               {"-metagoodscore <N>", "Good score for adding triangles to meta surfaces"},
+               {"-metamaxbboxdistance <F>", "Maximum bounding box distance for meta surfaces"},
                {"-minsamplesize <N>", "Sets minimum lightmap resolution in luxels/qu"},
-               {"-mi <N>", "Sets the maximum number of indexes per surface"},
-               {"-mv <N>", "Sets the maximum number of vertices of a lightmapped surface"},
+               {"-mi <N>", "Deprecated alias for `-maxsurfaceindexes`"},
+               {"-mv <N>", "Deprecated alias for `-maxlightmapverts`"},
                {"-ne <F>", "Normal epsilon for plane snapping etc."},
                {"-nocurves", "Turn off support for patches"},
                {"-nodetail", "Leave out detail brushes"},
                {"-noflares", "Turn off support for flares"},
                {"-nofog", "Turn off support for fog volumes"},
                {"-nohint", "Turn off support for hint brushes"},
+               {"-nosRGB", "Treat colors and textures as linear colorspace"},
+               {"-nosRGBcolor", "Treat shader and light entity colors as linear colorspace"},
+               {"-nosRGBtex", "Treat textures as linear colorspace"},
                {"-nosubdivide", "Turn off support for `q3map_tessSize` (breaks water vertex deforms)"},
                {"-notjunc", "Do not fix T-junctions (causes cracks between triangles, do not use)"},
                {"-nowater", "Turn off support for water, slime or lava (Stef, this is for you)"},
@@ -124,18 +142,21 @@ void HelpBsp()
                {"-skyfix", "Turn sky box into six surfaces to work around ATI problems"},
                {"-snap <N>", "Snap brush bevel planes to the given number of units"},
                {"-srffile <filename.srf>", "Surface file to write"},
+               {"-sRGBcolor", "Treat shader and light entity colors as sRGB colorspace"},
+               {"-sRGBtex", "Treat textures as sRGB colorspace"},
                {"-tempname <filename.map>", "Read the MAP file from the given file name"},
                {"-texrange <N>", "Limit per-surface texture range to the given number of units, and subdivide surfaces like with `q3map_tessSize` if this is not met"},
                {"-tmpout", "Write the BSP file to /tmp"},
                {"-verboseentities", "Enable `-v` only for map entities, not for the world"},
        };
-       HelpOptions("BSP Stage", 0, 80, bsp, sizeof(bsp)/sizeof(struct HelpOption));
+
+       HelpOptions("BSP Stage", 0, terminalColumns, bsp, sizeof(bsp)/sizeof(struct HelpOption));
 }
 
 void HelpVis()
 {
        struct HelpOption vis[] = {
-               {"-vis <filename.map>", "Switch that enters this stage"},
+               {"-vis [options] <filename.map>", "Switch that enters this stage"},
                {"-fast", "Very fast and crude vis calculation"},
                {"-hint", "Merge all but hint portals"},
                {"-mergeportals", "The less crude half of `-merge`, makes vis sometimes much faster but doesn't hurt fps usually"},
@@ -147,15 +168,17 @@ void HelpVis()
                {"-saveprt", "Keep the Portal file after running vis (so you can run vis again)"},
                {"-tmpin", "Use /tmp folder for input"},
                {"-tmpout", "Use /tmp folder for output"},
+               {"-v -v", "Extra verbose mode for cluster debug"}, // q3map2 common takes first -v
        };
-       HelpOptions("VIS Stage", 0, 80, vis, sizeof(vis)/sizeof(struct HelpOption));
+
+       HelpOptions("VIS Stage", 0, terminalColumns, vis, sizeof(vis)/sizeof(struct HelpOption));
 }
 
 void HelpLight()
 {
        struct HelpOption light[] = {
-               {"-light <filename.map>", "Switch that enters this stage"},
-               {"-vlight <filename.map>", "Deprecated alias for `-light -fast` ... filename.map"},
+               {"-light [options] <filename.map>", "Switch that enters this stage"},
+               {"-vlight [options] <filename.map>", "Deprecated alias for `-light -fast` ... filename.map"},
                {"-approx <N>", "Vertex light approximation tolerance (never use in conjunction with deluxemapping)"},
                {"-areascale <F, `-area` F>", "Scaling factor for area lights (surfacelight)"},
                {"-border", "Add a red border to lightmaps for debugging"},
@@ -192,20 +215,26 @@ void HelpLight()
                {"-export", "Export lightmaps when compile finished (like `-export` mode)"},
                {"-exposure <F>", "Lightmap exposure to better support overbright spots"},
                {"-external", "Force external lightmaps even if at size of internal lightmaps"},
+               {"-extradist <F>", "Extra distance for lights in map units"},
                {"-extravisnudge", "Broken feature to nudge the luxel origin to a better vis cluster"},
                {"-extrawide", "Deprecated alias for `-super 2 -filter`"},
                {"-extra", "Deprecated alias for `-super 2`"},
-               {"-fastallocate", "Use `-fastallocate` to trade lightmap size against allocation time (useful with hi res lightmaps on large maps: reduce allocation time from days to minutes for only some extra bytes)"},
+               {"-fastallocate",  "Trade lightmap size against packing time (useful with hi res lightmaps on large maps: reduce allocation time from days to minutes for only some extra bytes)"},
                {"-fastbounce", "Use `-fast` style lighting for radiosity"},
                {"-faster", "Use a faster falloff curve for lighting; also implies `-fast`"},
                {"-fastgrid", "Use `-fast` style lighting for the light grid"},
+               {"-fastlightmapsearch", "Deprecated alias for `-fastallocate`"},
                {"-fast", "Ignore tiny light contributions"},
-               {"-filter", "Lightmap filtering"},
+               {"-fill", "Fill lightmap colors from surrounding pixels to improve JPEG compression"},
+               {"-filter", "Lightmap filtering, doesn't play nice with some other effects, don't use it, use `-samples` instead"},
                {"-floodlight", "Enable floodlight (zero-effort somewhat decent lighting)"},
                {"-gamma <F>", "Lightmap gamma"},
+               {"-gridambientdirectionality <F>", "Ambient directional lighting received (default: 0.0)"},
                {"-gridambientscale <F>", "Scaling factor for the light grid ambient components only"},
+               {"-griddirectionality <F>", "Directional lighting received (default: 1.0)"},
                {"-gridscale <F>", "Scaling factor for the light grid only"},
-               {"-keeplights", "Keep light entities in the BSP file after compile"},
+               {"-lightanglehl 0", "Disable half lambert light angle attenuation"},
+               {"-lightanglehl 1", "Enable half lambert light angle attenuation"},
                {"-lightmapdir <directory>", "Directory to store external lightmaps (default: same as map name without extension)"},
                {"-lightmapsearchblocksize <N>", "Restrict lightmap search to block size <N>"},
                {"-lightmapsearchpower <N>", "Optimize for lightmap merge power <N>"},
@@ -214,80 +243,103 @@ void HelpLight()
                {"-lomem", "Low memory but slower lighting mode"},
                {"-lowquality", "Low quality floodlight (appears to currently break floodlight)"},
                {"-minsamplesize <N>", "Sets minimum lightmap resolution in luxels/qu"},
+               {"-nobouncestore", "Do not store BSP, lightmap and shader files between bounces"},
                {"-nocollapse", "Do not collapse identical lightmaps"},
                {"-nodeluxe, -nodeluxemap", "Disable deluxemapping"},
+               {"-nofastpoint", "Disable fast point light calculation"},
                {"-nogrid", "Disable grid light calculation (makes all entities fullbright)"},
                {"-nolightmapsearch", "Do not optimize lightmap packing for GPU memory usage (as doing so costs fps)"},
                {"-normalmap", "Color the lightmaps according to the direction of the surface normal (TODO is this identical to `-debugnormals`?)"},
+               {"-nosRGB", "Treat colors, textures, and lightmaps as linear colorspace"},
+               {"-nosRGBcolor", "Treat shader and light entity colors as linear colorspace"},
+               {"-nosRGBlight", "Write lightmaps as linear colorspace"},
+               {"-nosRGBtex", "Treat textures as linear colorspace"},
                {"-nostyle, -nostyles", "Disable support for light styles"},
                {"-nosurf", "Disable tracing against surfaces (only uses BSP nodes then)"},
                {"-notrace", "Disable shadow occlusion"},
                {"-novertex", "Disable vertex lighting"},
                {"-patchshadows", "Cast shadows from patches"},
-               {"-pointscale <F, `-point` F>", "Scaling factor for point lights (light entities)"},
+               {"-pointscale <F, `-point` F>", "Scaling factor for spherical and spot point lights (light entities)"},
                {"-q3", "Use nonlinear falloff curve by default (like Q3A)"},
+               {"-randomsamples", "Use random sampling for lightmaps"},
+               {"-rawlightmapsizelimit <N>", "Sets maximum lightmap resolution in luxels/qu (only affects patches if used -patchmeta in BSP stage)"},
                {"-samplescale <F>", "Scales all lightmap resolutions"},
                {"-samplesize <N>", "Sets default lightmap resolution in luxels/qu"},
+               {"-samplessearchboxsize <N>", "Search box size (1 to 4) for lightmap adaptive supersampling"},
                {"-samples <N>", "Adaptive supersampling quality"},
                {"-scale <F>", "Scaling factor for all light types"},
                {"-shadeangle <A>", "Angle for phong shading"},
                {"-shade", "Enable phong shading at default shade angle"},
                {"-skyscale <F, `-sky` F>", "Scaling factor for sky and sun light"},
+               {"-slowallocate", "Use old (a bit more careful, but much slower) lightmaps packing algorithm (default)"},
                {"-smooth", "Deprecated alias for `-samples 2`"},
+               {"-sphericalscale <F, `-spherical` F>", "Scaling factor for spherical point light entities"},
+               {"-spotscale <F, `-spot` F>", "Scaling factor for spot point light entities"},
                {"-srffile <filename.srf>", "Surface file to read"},
+               {"-sRGB", "Treat colors, textures, and lightmaps as sRGB colorspace"},
+               {"-sRGBcolor", "Treat shader and light entity colors as sRGB colorspace"},
+               {"-sRGBlight", "Write lightmaps as sRGB colorspace"},
+               {"-sRGBtex", "Treat textures as sRGB colorspace"},
                {"-style, -styles", "Enable support for light styles"},
                {"-sunonly", "Only compute sun light"},
-               {"-super <N, `-supersample` N>", "Ordered grid supersampling quality"},
+               {"-super <N, `-supersample` N>", "Ordered grid supersampling quality, much slower than `-samples`"},
                {"-thresh <F>", "Triangle subdivision threshold"},
                {"-trianglecheck", "Broken check that should ensure luxels apply to the right triangle"},
                {"-trisoup", "Convert brush faces to triangle soup"},
                {"-wolf", "Use linear falloff curve by default (like W:ET)"},
        };
 
-       HelpOptions("Light Stage", 0, 80, light, sizeof(light)/sizeof(struct HelpOption));
+       HelpOptions("Light Stage", 0, terminalColumns, light, sizeof(light)/sizeof(struct HelpOption));
 }
 
 void HelpAnalyze()
 {
        struct HelpOption analyze[] = {
-               {"-analyze <filename.bsp>", "Switch that enters this mode"},
+               {"-analyze [options] <filename.bsp>", "Switch that enters this mode"},
                {"-lumpswap", "Swap byte order in the lumps"},
        };
 
-       HelpOptions("Analyzing BSP-like file structure", 0, 80, analyze, sizeof(analyze)/sizeof(struct HelpOption));
+       HelpOptions("Analyzing BSP-like file structure", 0, terminalColumns, analyze, sizeof(analyze)/sizeof(struct HelpOption));
 }
 
 void HelpScale()
 {
        struct HelpOption scale[] = {
-               {"-scale <S filename.bsp>", "Scale uniformly"},
-               {"-scale <SX SY SZ filename.bsp>", "Scale non-uniformly"},
-               {"-scale -tex <S filename.bsp>", "Scale uniformly without texture lock"},
-               {"-scale -tex <SX SY SZ filename.bsp>", "Scale non-uniformly without texture lock"},
+               {"-scale [options] <S filename.bsp>", "Scale uniformly"},
+               {"-scale [options] <SX SY SZ filename.bsp>", "Scale non-uniformly"},
+               {"-tex", "Scale without texture lock"},
+               {"-spawn_ref <F>", "Vertical offset for info_player_* entities (adds spawn_ref, scales, subtracts spawn_ref)"},
        };
-       HelpOptions("Scaling", 0, 80, scale, sizeof(scale)/sizeof(struct HelpOption));
+
+       HelpOptions("Scaling", 0, terminalColumns, scale, sizeof(scale)/sizeof(struct HelpOption));
 }
 
 void HelpConvert()
 {
        struct HelpOption convert[] = {
-               {"-convert <filename.bsp>", "Switch that enters this mode"},
-               {"-de <number>", "Distance epsilon for the conversion"},
-               {"-format <converter>", "Select the converter (available: map, ase, or game names)"},
-               {"-ne <F>", "Normal epsilon for the conversion"},
-               {"-shadersasbitmap", "(only for ase) use the shader names as \\*BITMAP key so they work as prefabs"},
+               {"-convert [options] <filename.bsp>", "Switch that enters this mode"},
+               {"-deluxemapsastexcoord", "Save deluxemap names and texcoords instead of textures (only when writing ase and obj)"},
+               {"-de <F>", "Distance epsilon for the conversion (only when reading map)"},
+               {"-format <converter>", "Select the converter, default ase (available: map, map_bp, ase, obj, or game names)"},
+               {"-lightmapsastexcoord", "Save lightmap names and texcoords instead of textures (only when writing ase and obj)"},
+               {"-meta", "Combine adjacent triangles of the same texture to surfaces (only when reading map)"},
+               {"-ne <F>", "Normal epsilon for the conversion (only when reading map)"},
+               {"-patchmeta", "Turn patches into triangle meshes for display (only when reading map)"},
+               {"-readbsp", "Force converting bsp to selected format"},
+               {"-readmap", "Force converting map to selected format"},
+               {"-shadersasbitmap", "Save shader names as bitmap names in the model so it works as a prefab (only when writing ase and obj)"},
        };
 
-       HelpOptions("Converting & Decompiling", 0, 80, convert, sizeof(convert)/sizeof(struct HelpOption));
+       HelpOptions("Converting & Decompiling", 0, terminalColumns, convert, sizeof(convert)/sizeof(struct HelpOption));
 }
 
 void HelpExport()
 {
        struct HelpOption exportl[] = {
-               {"-export <filename.bsp>", "Copies lightmaps from the BSP to `filename/lightmap_0000.tga` ff"}
+               {"-export <filename.bsp>", "Copies lightmaps from the BSP to `filename/lightmap_0000.tga`"}
        };
 
-       HelpOptions("Exporting lightmaps", 0, 80, exportl, sizeof(exportl)/sizeof(struct HelpOption));
+       HelpOptions("Exporting lightmaps", 0, terminalColumns, exportl, sizeof(exportl)/sizeof(struct HelpOption));
 }
 
 void HelpExportEnts()
@@ -295,7 +347,7 @@ void HelpExportEnts()
        struct HelpOption exportents[] = {
                {"-exportents <filename.bsp>", "Exports the entities to a text file (.ent)"},
        };
-       HelpOptions("ExportEnts Stage", 0, 80, exportents, sizeof(exportents)/sizeof(struct HelpOption));
+       HelpOptions("ExportEnts Stage", 0, terminalColumns, exportents, sizeof(exportents)/sizeof(struct HelpOption));
 }
 
 void HelpFixaas()
@@ -304,7 +356,7 @@ void HelpFixaas()
                {"-fixaas <filename.bsp>", "Switch that enters this mode"},
        };
 
-       HelpOptions("Fixing AAS checksum", 0, 80, fixaas, sizeof(fixaas)/sizeof(struct HelpOption));
+       HelpOptions("Fixing AAS checksum", 0, terminalColumns, fixaas, sizeof(fixaas)/sizeof(struct HelpOption));
 }
 
 void HelpInfo()
@@ -313,7 +365,7 @@ void HelpInfo()
                {"-info <filename.bsp>", "Switch that enters this mode"},
        };
 
-       HelpOptions("Get info about BSP file", 0, 80, info, sizeof(info)/sizeof(struct HelpOption));
+       HelpOptions("Get info about BSP file", 0, terminalColumns, info, sizeof(info)/sizeof(struct HelpOption));
 }
 
 void HelpImport()
@@ -322,19 +374,23 @@ void HelpImport()
                {"-import <filename.bsp>", "Copies lightmaps from `filename/lightmap_0000.tga` ff into the BSP"},
        };
 
-       HelpOptions("Importing lightmaps", 0, 80, import, sizeof(import)/sizeof(struct HelpOption));
+       HelpOptions("Importing lightmaps", 0, terminalColumns, import, sizeof(import)/sizeof(struct HelpOption));
 }
 
 void HelpMinimap()
 {
        struct HelpOption minimap[] = {
-               {"-minimap <filename.bsp>", "Creates a minimap of the BSP, by default writes to `../gfx/filename_mini.tga`"},
+               {"-minimap [options] <filename.bsp>", "Creates a minimap of the BSP, by default writes to `../gfx/filename_mini.tga`"},
+               {"-autolevel", "Automatically level brightness and contrast"},
                {"-black", "Write the minimap as a black-on-transparency RGBA32 image"},
                {"-boost <F>", "Sets the contrast boost value (higher values make a brighter image); contrast boost is somewhat similar to gamma, but continuous even at zero"},
                {"-border <F>", "Sets the amount of border pixels relative to the total image size"},
+               {"-brightness <F>", "Sets brightness value to add to minimap values"},
+               {"-contrast <F>", "Sets contrast value to scale minimap values (doesn't affect brightness)"},
                {"-gray", "Write the minimap as a white-on-black GRAY8 image"},
                {"-keepaspect", "Ensure the aspect ratio is kept (the minimap is then letterboxed to keep aspect)"},
                {"-minmax <xmin ymin zmin xmax ymax zmax>", "Forces specific map dimensions (note: the minimap actually uses these dimensions, scaled to the target size while keeping aspect with centering, and 1/64 of border appended to all sides)"},
+               {"-noautolevel", "Do not automatically level brightness and contrast"},
                {"-nokeepaspect", "Do not ensure the aspect ratio is kept (makes it easier to use the image in your code, but looks bad together with sharpening)"},
                {"-o <filename.tga>", "Sets the output file name"},
                {"-random <N>", "Sets the randomized supersampling count (cannot be combined with `-samples`)"},
@@ -344,40 +400,84 @@ void HelpMinimap()
                {"-white", "Write the minimap as a white-on-transparency RGBA32 image"},
        };
 
-       HelpOptions("MiniMap", 0, 80, minimap, sizeof(minimap)/sizeof(struct HelpOption));
+       HelpOptions("MiniMap", 0, terminalColumns, minimap, sizeof(minimap)/sizeof(struct HelpOption));
 }
 
 void HelpCommon()
 {
        struct HelpOption common[] = {
-               {"-connect <address>", "Talk to a NetRadiant instance using a specific XML based protocol"},
+               {"-connect <address>", "Talk to a " RADIANT_NAME " instance using a specific XML based protocol"},
                {"-force", "Allow reading some broken/unsupported BSP files e.g. when decompiling, may also crash"},
                {"-fs_basepath <path>", "Sets the given path as main directory of the game (can be used more than once to look in multiple paths)"},
+               {"-fs_forbiddenpath <pattern>", "Pattern to ignore directories, pk3, and pk3dir; example pak?.pk3 (can be used more than once to look for multiple patterns)"},
                {"-fs_game <gamename>", "Sets a different game directory name (default for Q3A: baseq3, can be used more than once)"},
-               {"-fs_homebase <dir>", "Specifies where the user home directory name is on Linux (default for Q3A: .q3a)"},
-               {"-fs_homepath <path>", "Sets the given path as home directory name"},
+               {"-fs_home <dir>", "Specifies where the user home directory is on Linux"},
+               {"-fs_homebase <dir>", "Specifies game home directory relative to user home directory on Linux (default for Q3A: .q3a)"},
+               {"-fs_homepath <path>", "Sets the given path as the game home directory name (fs_home + fs_homebase)"},
                {"-fs_nobasepath", "Do not load base paths in VFS, imply -fs_nomagicpath"},
                {"-fs_nomagicpath", "Do not try to guess base path magically"},
                {"-fs_nohomepath", "Do not load home path in VFS"},
                {"-fs_pakpath <path>", "Specify a package directory (can be used more than once to look in multiple paths)"},
                {"-game <gamename>", "Load settings for the given game (default: quake3)"},
-               {"-subdivisions <F>", "multiplier for patch subdivisions quality"},
-               {"-threads <N>", "number of threads to use"},
+               {"-subdivisions <F>", "Multiplier for patch subdivisions quality"},
+               {"-threads <N>", "Number of threads to use"},
                {"-v", "Verbose mode"},
                {"-werror", "Make all warnings into errors"}
        };
 
-       HelpOptions("Common Options", 0, 80, common, sizeof(common)/sizeof(struct HelpOption));
+       HelpOptions("Common Options", 0, terminalColumns, common, sizeof(common)/sizeof(struct HelpOption));
+}
+
+void HelpGames()
+{
+       printf("Games:\n");
+       qboolean begin = qtrue;
+
+       // TODO: sort alphabetically
+       for ( unsigned i = 0, length = 0; games[ i ].arg != NULL; i++ )
+       {
+               // 3 for two whitespaces at the beginning and one (optional) comma a the end
+               if ( length + 3 + strlen( games[ i ].arg ) > terminalColumns )
+               {
+                       printf(",\n");
+                       length = 0;
+                       begin = qtrue;
+               }
+
+               if ( begin )
+               {
+                       printf("  %s", games[ i ].arg );
+                       begin = qfalse;
+               }
+               else
+               {
+                       printf(", %s", games[ i ].arg );
+               }
+
+               length += 2 + strlen( games[ i ].arg );
+       }
 
+       printf("\n\n");
 }
 
 void HelpMain(const char* arg)
 {
        printf("Usage: q3map2 [stage] [common options...] [stage options...] [stage source file]\n");
-       printf("       q3map2 -help [stage]\n\n");
+       printf("       q3map2 -help [stage]\n");
+       printf("       q3map2 -help all\n\n");
+
+#if GDEF_OS_POSIX
+       struct winsize ws;
+       ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
+       if (ws.ws_col > 60) {
+               terminalColumns = ws.ws_col;
+       }
+#endif // GDEF_OS_POSIX
 
        HelpCommon();
 
+       HelpGames();
+
        struct HelpOption stages[] = {
                {"-bsp", "BSP Stage"},
                {"-vis", "VIS Stage"},
@@ -392,6 +492,7 @@ void HelpMain(const char* arg)
                {"-import", "Importing lightmaps"},
                {"-minimap", "MiniMap"},
        };
+
        void(*help_funcs[])() = {
                HelpBsp,
                HelpVis,
@@ -410,16 +511,30 @@ void HelpMain(const char* arg)
        if ( arg && strlen(arg) > 0 )
        {
                if ( arg[0] == '-' )
+               {
                        arg++;
+               }
 
-               unsigned i;
-               for ( i = 0; i < sizeof(stages)/sizeof(struct HelpOption); i++ )
+               if ( strcmp(arg, "all") == 0 )
+               {
+                       HelpOptions("Stages", 0, terminalColumns, stages, sizeof(stages)/sizeof(struct HelpOption));
+
+                       for ( unsigned i = 0; i < sizeof(stages)/sizeof(struct HelpOption); i++ )
+                       {
+                               help_funcs[i]();
+                       }
+                       return;
+               }
+
+               for ( unsigned i = 0; i < sizeof(stages)/sizeof(struct HelpOption); i++ )
+               {
                        if ( strcmp(arg, stages[i].name+1) == 0 )
                        {
                                help_funcs[i]();
                                return;
                        }
+               }
        }
 
-       HelpOptions("Stages", 0, 80, stages, sizeof(stages)/sizeof(struct HelpOption));
+       HelpOptions("Stages", 0, terminalColumns, stages, sizeof(stages)/sizeof(struct HelpOption));
 }
index e5f97a40c1dbc8d4d71531bbc237926ef033020f..f5c0b1e90f7c4082bad7b6e41785e545087c282a 100644 (file)
@@ -230,7 +230,8 @@ static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, in
        /* create image pixel buffer */
        *width = w;
        *height = h;
-       *pixels = safe_malloc( w * h * 4 );
+       /* initialize with zeros, this memory area may not be entirely rewritten */
+       *pixels = safe_malloc0( w * h * 4 );
 
        /* create row pointers */
        rowPointers = safe_malloc( h * sizeof( byte* ) );
@@ -243,7 +244,6 @@ static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, in
        /* clean up */
        free( rowPointers );
        png_destroy_read_struct( &png, &info, &end );
-
 }
 
 
@@ -396,112 +396,138 @@ image_t *ImageLoad( const char *filename ){
                return NULL;
        }
 
-       /* strip file extension off name */
-       strcpy( name, filename );
-       StripExtension( name );
+       /* try with extension then without extension
+       so light.blend will be unfortunately first
+       tried as light.tga like it always did, but
+       then, light.blend.tga will be tried as well */
+       for ( i = 0; i < 2; i++ )
+       {
+               strcpy( name, filename );
 
-       /* try to find existing image */
-       image = ImageFind( name );
-       if ( image != NULL ) {
-               image->refCount++;
-               return image;
-       }
+               if ( i == 0 )
+               {
+                       /* strip file extension off name */
+                       StripExtension( name );
+               }
 
-       /* none found, so find first non-null image */
-       image = NULL;
-       for ( i = 0; i < MAX_IMAGES; i++ )
-       {
-               if ( images[ i ].name == NULL ) {
-                       image = &images[ i ];
-                       break;
+               /* try to find existing image */
+               image = ImageFind( name );
+               if ( image != NULL ) {
+                       image->refCount++;
+                       return image;
                }
-       }
 
-       /* too many images? */
-       if ( image == NULL ) {
-               Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
-       }
+               /* none found, so find first non-null image */
+               image = NULL;
+               for ( i = 0; i < MAX_IMAGES; i++ )
+               {
+                       if ( images[ i ].name == NULL ) {
+                               image = &images[ i ];
+                               break;
+                       }
+               }
+
+               /* too many images? */
+               if ( image == NULL ) {
+                       Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
+               }
 
-       /* set it up */
-       image->name = safe_malloc( strlen( name ) + 1 );
-       strcpy( image->name, name );
+               /* set it up */
+               image->name = safe_malloc( strlen( name ) + 1 );
+               strcpy( image->name, name );
 
-       /* attempt to load tga */
-       StripExtension( name );
-       strcat( name, ".tga" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadTGABuffer( buffer, buffer + size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
+               /* add a dummy extension that can be removed */
+               strcat( name, ".tga" );
 
-       /* attempt to load png */
-       StripExtension( name );
-       strcat( name, ".png" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
+               /* Sys_FPrintf( SYS_WRN, "==> Looking for %s\n", name ); */
 
-       /* attempt to load jpg */
-       StripExtension( name );
-       strcat( name, ".jpg" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               if ( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL ) {
-                       // On error, LoadJPGBuff might store a pointer to the error message in image->pixels
-                       Sys_FPrintf( SYS_WRN, "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
+               /* attempt to load tga */
+               StripExtension( name );
+               strcat( name, ".tga" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       LoadTGABuffer( buffer, buffer + size, &image->pixels, &image->width, &image->height );
+                       break;
                }
-               alphaHack = qtrue;
-               goto image_load_success;
-       }
 
-       /* attempt to load dds */
-       StripExtension( name );
-       strcat( name, ".dds" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
+               /* attempt to load png */
+               StripExtension( name );
+               strcat( name, ".png" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+                       break;
+               }
 
-       /* attempt to load ktx */
-       StripExtension( name );
-       strcat( name, ".ktx" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadKTXBufferFirstImage( buffer, size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
+               /* attempt to load jpg */
+               StripExtension( name );
+               strcat( name, ".jpg" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       if ( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL ) {
+                               // On error, LoadJPGBuff might store a pointer to the error message in image->pixels
+                               Sys_FPrintf( SYS_WRN, "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
+                       }
+                       alphaHack = qtrue;
+                       break;
+               }
 
-       #ifdef BUILD_CRUNCH
-       /* attempt to load crn */
-       StripExtension( name );
-       strcat( name, ".crn" );
-       size = vfsLoadFile( ( const char* ) name, ( void** ) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadCRNBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
-       #endif // BUILD_CRUNCH
+               /* attempt to load dds */
+               StripExtension( name );
+               strcat( name, ".dds" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
 
-       /* attempt to load webp */
-       StripExtension( name );
-       strcat( name, ".webp" );
-       size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-       if ( size > 0 ) {
-               LoadWEBPBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-               goto image_load_success;
-       }
+               /* also look for .dds image in dds/ prefix like Doom3 or DarkPlaces */
+               if ( size <= 0 ) {
+                       char ddsname[ 1024 ];
+                       strcpy( ddsname, "dds/" );
+                       strcat( ddsname, image->name );
+                       StripExtension( ddsname );
+                       strcat( ddsname, ".dds" );
+                       size = vfsLoadFile( (const char*) ddsname, (void**) &buffer, 0 );
+               }
 
-       image_load_success:
+               if ( size > 0 ) {
+                       LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+                       break;
+               }
+
+               /* attempt to load ktx */
+               StripExtension( name );
+               strcat( name, ".ktx" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       LoadKTXBufferFirstImage( buffer, size, &image->pixels, &image->width, &image->height );
+                       break;
+               }
+
+               #ifdef BUILD_CRUNCH
+               /* attempt to load crn */
+               StripExtension( name );
+               strcat( name, ".crn" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       LoadCRNBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+                       break;
+               }
+               #endif // BUILD_CRUNCH
+
+               /* attempt to load webp */
+               StripExtension( name );
+               strcat( name, ".webp" );
+               size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+               if ( size > 0 ) {
+                       LoadWEBPBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+                       break;
+               }
+       }
 
        /* free file buffer */
        free( buffer );
 
        /* make sure everything's kosher */
        if ( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL ) {
+               // Sys_FPrintf( SYS_WRN, "WARNING: Image not found: \"%s\"\n", filename );
                //%     Sys_Printf( "size = %d  width = %d  height = %d  pixels = 0x%08x (%s)\n",
                //%             size, image->width, image->height, image->pixels, name );
                free( image->name );
@@ -509,6 +535,9 @@ image_t *ImageLoad( const char *filename ){
                return NULL;
        }
 
+       /* tell user which image file is found for the given texture path */
+       Sys_FPrintf( SYS_VRB, "Loaded image: \"%s\"\n", name );
+
        /* set filename */
        image->filename = safe_malloc( strlen( name ) + 1 );
        strcpy( image->filename, name );
index 100bed593a748c7e0e2657ce235b08ab6eef5d7a..f14cc43c843c4f8c8efdb30d632767832898ca82 100644 (file)
@@ -107,8 +107,7 @@ static void CreateSunLight( sun_t *sun ){
 
                /* create a light */
                numSunLights++;
-               light = safe_malloc( sizeof( *light ) );
-               memset( light, 0, sizeof( *light ) );
+               light = safe_malloc0( sizeof( *light ) );
                light->next = lights;
                lights = light;
 
@@ -254,8 +253,7 @@ void CreateEntityLights( void ){
 
                /* create a light */
                numPointLights++;
-               light = safe_malloc( sizeof( *light ) );
-               memset( light, 0, sizeof( *light ) );
+               light = safe_malloc0( sizeof( *light ) );
                light->next = lights;
                lights = light;
 
@@ -592,8 +590,7 @@ void CreateSurfaceLights( void ){
                        VectorScale( origin, 0.5f, origin );
 
                        /* create a light */
-                       light = safe_malloc( sizeof( *light ) );
-                       memset( light, 0, sizeof( *light ) );
+                       light = safe_malloc0( sizeof( *light ) );
                        light->next = lights;
                        lights = light;
 
@@ -1774,7 +1771,17 @@ void TraceGrid( int num ){
                        }
 
                /* vortex: apply gridscale and gridambientscale here */
-               ColorToBytes( color, bgp->ambient[ i ], gridScale * gridAmbientScale );
+               if (gp->directed[i][0] || gp->directed[i][1] || gp->directed[i][2]) {
+                       /*
+                        * HACK: if there's a non-zero directed component, this
+                        * lightgrid cell is useful. However, ioq3 skips grid
+                        * cells with zero ambient. So let's force ambient to be
+                        * nonzero unless directed is zero too.
+                        */
+                       ColorToBytesNonZero(color, bgp->ambient[i], gridScale * gridAmbientScale);
+               } else {
+                       ColorToBytes(color, bgp->ambient[i], gridScale * gridAmbientScale);
+               }
                ColorToBytes( gp->directed[ i ], bgp->directed[ i ], gridScale );
        }
 
@@ -1857,14 +1864,12 @@ void SetupGrid( void ){
        numBSPGridPoints = numRawGridPoints;
 
        /* allocate lightgrid */
-       rawGridPoints = safe_malloc( numRawGridPoints * sizeof( *rawGridPoints ) );
-       memset( rawGridPoints, 0, numRawGridPoints * sizeof( *rawGridPoints ) );
+       rawGridPoints = safe_malloc0( numRawGridPoints * sizeof( *rawGridPoints ) );
 
        if ( bspGridPoints != NULL ) {
                free( bspGridPoints );
        }
-       bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-       memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+       bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
 
        /* clear lightgrid */
        for ( i = 0; i < numRawGridPoints; i++ )
@@ -1890,14 +1895,13 @@ void SetupGrid( void ){
    does what it says...
  */
 
-void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
+void LightWorld( const char *BSPFilePath, qboolean fastAllocate, qboolean noBounceStore ){
        vec3_t color;
        float f;
        int b, bt;
        qboolean minVertex, minGrid;
        const char  *value;
 
-
        /* ydnar: smooth normals */
        if ( shade ) {
                Sys_Printf( "--- SmoothNormals ---\n" );
@@ -2031,13 +2035,19 @@ void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
        /* radiosity */
        b = 1;
        bt = bounce;
+
        while ( bounce > 0 )
        {
+               qboolean storeForReal = !noBounceStore;
+
                /* store off the bsp between bounces */
-               StoreSurfaceLightmaps( fastAllocate );
+               StoreSurfaceLightmaps( fastAllocate, storeForReal );
                UnparseEntities();
-               Sys_Printf( "Writing %s\n", BSPFilePath );
-               WriteBSPFile( BSPFilePath );
+
+               if ( storeForReal ) {
+                       Sys_Printf( "Writing %s\n", BSPFilePath );
+                       WriteBSPFile( BSPFilePath );
+               }
 
                /* note it */
                Sys_Printf( "\n--- Radiosity (bounce %d of %d) ---\n", b, bt );
@@ -2055,6 +2065,9 @@ void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
                SetupEnvelopes( qfalse, fastbounce );
                if ( numLights == 0 ) {
                        Sys_Printf( "No diffuse light to calculate, ending radiosity.\n" );
+                       if ( noBounceStore ) {
+                               break;
+                       }
                        return;
                }
 
@@ -2098,8 +2111,29 @@ void LightWorld( const char *BSPFilePath, qboolean fastAllocate ){
                bounce--;
                b++;
        }
+
        /* ydnar: store off lightmaps */
-       StoreSurfaceLightmaps( fastAllocate );
+       StoreSurfaceLightmaps( fastAllocate, qtrue );
+}
+
+
+
+/*
+   LoadSurfaceFlags()
+   added by spoon to get back the changed surfaceflags
+   from tex file
+*/
+
+void LoadSurfaceFlags( char *filename ) {
+       int i;
+
+       for( i = 0; i < numBSPShaders; i++ ) {
+               shaderInfo_t *si;
+
+               si = ShaderInfoForShader( bspShaders[i].shader );
+
+               bspShaders[ i ].surfaceFlags = si->surfaceFlags;
+       }
 }
 
 
@@ -2120,6 +2154,7 @@ int LightMain( int argc, char **argv ){
        int lightmapMergeSize = 0;
        qboolean lightSamplesInsist = qfalse;
        qboolean fastAllocate = qfalse;
+       qboolean noBounceStore = qfalse;
 
        /* note it */
        Sys_Printf( "--- Light ---\n" );
@@ -2587,7 +2622,9 @@ int LightMain( int argc, char **argv ){
 
                else if ( !strcmp( argv[ i ], "-lightmapdir" ) ) {
                        lmCustomDir = argv[i + 1];
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Lightmap directory set to %s\n", lmCustomDir );
                        externalLightmaps = qtrue;
                        Sys_Printf( "Storing all lightmaps externally\n" );
@@ -2630,6 +2667,11 @@ int LightMain( int argc, char **argv ){
                        Sys_Printf( "Storing bounced light (radiosity) only\n" );
                }
 
+               else if ( !strcmp( argv[ i ], "-nobouncestore" ) ) {
+                       noBounceStore = qtrue;
+                       Sys_Printf( "Do not store BSP, lightmap and shader files between bounces\n" );
+               }
+
                else if ( !strcmp( argv[ i ], "-nocollapse" ) ) {
                        noCollapse = qtrue;
                        Sys_Printf( "Identical lightmap collapsing disabled\n" );
@@ -2689,9 +2731,20 @@ int LightMain( int argc, char **argv ){
                        Sys_Printf( "Faster mode enabled\n" );
                }
 
-               else if ( !strcmp( argv[ i ], "-fastallocate" ) ) {
+               else if ( !strcmp( argv[ i ], "-fastallocate" ) || !strcmp( argv[ i ], "-fastlightmapsearch" ) ) {
                        fastAllocate = qtrue;
-                       Sys_Printf( "Fast allocation mode enabled\n" );
+
+                       if ( !strcmp( argv[ i ], "-fastlightmapsearch" ) ) {
+                               Sys_Printf( "The -fastlightmapsearch argument is deprecated, use \"-fastallocate\" instead\n" );
+                       }
+                       else {
+                               Sys_Printf( "Fast lightmap allocation mode enabled\n" );
+                       }
+               }
+
+               else if ( !strcmp( argv[ i ], "-slowallocate" ) ) {
+                       fastAllocate = qfalse;
+                       Sys_Printf( "Slow lightmap allocation mode enabled (default)\n" );
                }
 
                else if ( !strcmp( argv[ i ], "-fastgrid" ) ) {
@@ -2943,13 +2996,17 @@ int LightMain( int argc, char **argv ){
                else if ( !strcmp( argv[ i ], "-bspfile" ) )
                {
                        strcpy( BSPFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as bsp file\n", BSPFilePath );
                }
                else if ( !strcmp( argv[ i ], "-srffile" ) )
                {
                        strcpy( surfaceFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as surface file\n", surfaceFilePath );
                }
                /* unhandled args */
@@ -3005,6 +3062,11 @@ int LightMain( int argc, char **argv ){
                Sys_Printf( "Restricted lightmap searching enabled - block size adjusted to %d\n", lightmapSearchBlockSize );
        }
 
+       /* arg checking */
+       if ( i != ( argc - 1 ) ) {
+               Error( "usage: q3map -light [options] <bspfile>" );
+       }
+
        strcpy( source, ExpandArg( argv[ i ] ) );
        StripExtension( source );
        DefaultExtension( source, ".map" );
@@ -3062,7 +3124,7 @@ int LightMain( int argc, char **argv ){
        SetupTraceNodes();
 
        /* light the world */
-       LightWorld( BSPFilePath, fastAllocate );
+       LightWorld( BSPFilePath, fastAllocate, noBounceStore );
 
        /* write out the bsp */
        UnparseEntities();
index acf2eacd3ce4af54d09239f04ee93cf19b1ebce8..e738429008fbb6362e93ddf9e194419b14fd3e91 100644 (file)
@@ -195,6 +195,23 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
 
 
 
+/*
+   Modulo1IfNegative()
+   Previously the bias computation was doing:
+
+      while ( f < 0.0f ) {
+         f += 1.0f;
+      }
+
+   That may end in infinite loop in some case.
+   It may also be slower because of useless loops.
+   I don't know what that computation is for.
+   -- illwieckz
+*/
+float Modulo1IfNegative( float f ){
+       return f < 0.0f ? f - floor( f ) : f;
+}
+
 
 
 /*
@@ -204,10 +221,8 @@ static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
  */
 
 qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] ){
-       float sto[ 2 ];
        int x, y;
 
-
        /* clear color first */
        color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255;
 
@@ -216,18 +231,10 @@ qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], flo
                return qfalse;
        }
 
-       /* bias st */
-       sto[ 0 ] = st[ 0 ];
-       while ( sto[ 0 ] < 0.0f )
-               sto[ 0 ] += 1.0f;
-       sto[ 1 ] = st[ 1 ];
-       while ( sto[ 1 ] < 0.0f )
-               sto[ 1 ] += 1.0f;
-
        /* get offsets */
-       x = ( (float) width * sto[ 0 ] ) + 0.5f;
+       x = ( (float) width * Modulo1IfNegative( st[ 0 ] ) ) + 0.5f;
        x %= width;
-       y = ( (float) height * sto[ 1 ] )  + 0.5f;
+       y = ( (float) height * Modulo1IfNegative( st[ 1 ] ) ) + 0.5f;
        y %= height;
 
        /* get pixel */
@@ -536,8 +543,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
        }
 
        /* create a light */
-       light = safe_malloc( sizeof( *light ) );
-       memset( light, 0, sizeof( *light ) );
+       light = safe_malloc0( sizeof( *light ) );
 
        /* attach it */
        ThreadLock();
@@ -583,8 +589,7 @@ static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, raw
                /* optionally create a point backsplash light for first pass */
                if ( original && si->backsplashFraction > 0 ) {
                        /* allocate a new point light */
-                       splash = safe_malloc( sizeof( *splash ) );
-                       memset( splash, 0, sizeof( *splash ) );
+                       splash = safe_malloc0( sizeof( *splash ) );
                        splash->next = lights;
                        lights = splash;
 
index bc10b2f65f50131c55c6985a6f2781775a123289..c024dd3eb39fe4597f88b2c7b45b16d507ae0e46 100644 (file)
@@ -151,6 +151,19 @@ void ColorToBytes( const float *color, byte *colorBytes, float scale ){
        colorBytes[ 2 ] = sample[ 2 ];
 }
 
+/*
+ * Same as ColorToBytes, but if the output color will never contain zero
+ * components. Used to avoid returning 0 0 0 due to an ioq3 issue. Reason
+ * to also map 0 0 1 to 1 1 1 is to ensure monotonicity in the color mapping
+ * to prevent banding-like artifacts on lightmaps.
+ */
+void ColorToBytesNonZero( const float *color, byte *colorBytes, float scale) {
+       int i;
+       ColorToBytes(color, colorBytes, scale);
+       for (i = 0; i < 3; ++i)
+               if (colorBytes[i] == 0)
+                       colorBytes[i] = 1;
+}
 
 
 /* -------------------------------------------------------------------------------
@@ -181,13 +194,11 @@ void SmoothNormals( void ){
 
 
        /* allocate shade angle table */
-       shadeAngles = safe_malloc( numBSPDrawVerts * sizeof( float ) );
-       memset( shadeAngles, 0, numBSPDrawVerts * sizeof( float ) );
+       shadeAngles = safe_malloc0( numBSPDrawVerts * sizeof( float ) );
 
        /* allocate smoothed table */
        cs = ( numBSPDrawVerts / 8 ) + 1;
-       smoothed = safe_malloc( cs );
-       memset( smoothed, 0, cs );
+       smoothed = safe_malloc0( cs );
 
        /* set default shade angle */
        defaultShadeAngle = DEG2RAD( shadeAngleDegrees );
@@ -2411,8 +2422,7 @@ void IlluminateRawLightmap( int rawLightmapNum ){
                        if ( lm->superLuxels[ lightmapNum ] == NULL ) {
                                /* allocate sampling lightmap storage */
                                size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
-                               lm->superLuxels[ lightmapNum ] = safe_malloc( size );
-                               memset( lm->superLuxels[ lightmapNum ], 0, size );
+                               lm->superLuxels[ lightmapNum ] = safe_malloc0( size );
                        }
 
                        /* set style */
@@ -2749,7 +2759,7 @@ void IlluminateVertexes( int num ){
        int i, x, y, z, x1, y1, z1, sx, sy, radius, maxRadius, *cluster;
        int lightmapNum, numAvg;
        float samples, *vertLuxel, *radVertLuxel, *luxel, dirt;
-       vec3_t origin, temp, temp2, colors[ MAX_LIGHTMAPS ], avgColors[ MAX_LIGHTMAPS ];
+       vec3_t temp, temp2, colors[ MAX_LIGHTMAPS ], avgColors[ MAX_LIGHTMAPS ];
        bspDrawSurface_t    *ds;
        surfaceInfo_t       *info;
        rawLightmap_t       *lm;
@@ -2804,7 +2814,7 @@ void IlluminateVertexes( int num ){
                        else if ( debugOrigin ) {
                                VectorSubtract( info->maxs, info->mins, temp );
                                VectorScale( temp, ( 1.0f / 255.0f ), temp );
-                               VectorSubtract( origin, lm->mins, temp2 );
+                               VectorSubtract( verts[ i ].xyz, info->mins, temp2 );
                                radVertLuxel[ 0 ] = info->mins[ 0 ] + ( temp[ 0 ] * temp2[ 0 ] );
                                radVertLuxel[ 1 ] = info->mins[ 1 ] + ( temp[ 1 ] * temp2[ 1 ] );
                                radVertLuxel[ 2 ] = info->mins[ 2 ] + ( temp[ 2 ] * temp2[ 2 ] );
@@ -2898,7 +2908,7 @@ void IlluminateVertexes( int num ){
                                                                trace.origin[ 2 ] = verts[ i ].xyz[ 2 ] + ( VERTEX_NUDGE * z1 );
 
                                                                /* try at nudged origin */
-                                                               trace.cluster = ClusterForPointExtFilter( origin, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
+                                                               trace.cluster = ClusterForPointExtFilter( trace.origin, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
                                                                if ( trace.cluster < 0 ) {
                                                                        continue;
                                                                }
@@ -4457,6 +4467,9 @@ void FloodlightIlluminateLightmap( rawLightmap_t *lm ){
                        continue;
                }
 
+               if( lm->styles[lightmapNum] != LS_NORMAL && lm->styles[lightmapNum] != LS_NONE ) // isStyleLight
+                       continue;
+
                /* apply floodlight to each luxel */
                for ( y = 0; y < lm->sh; y++ )
                {
index ea36b921f8bd6a41b75be713a64286de5ae7019c..3c08c8b60d13c1223ba795bdf08a556121300bf1 100644 (file)
@@ -67,6 +67,8 @@ void WriteTGA24( char *filename, byte *data, int width, int height, qboolean fli
 
        /* allocate a buffer and set it up */
        buffer = safe_malloc( width * height * 3 + 18 );
+       /* we may also use safe_malloc0 on the whole instead,
+        * this would just be a bit slower */
        memset( buffer, 0, 18 );
        buffer[ 2 ] = 2;
        buffer[ 12 ] = width & 255;
@@ -153,7 +155,7 @@ void ExportLightmaps( void ){
 
 int ExportLightmapsMain( int argc, char **argv ){
        /* arg checking */
-       if ( argc < 1 ) {
+       if ( argc < 2 ) {
                Sys_Printf( "Usage: q3map -export [-v] <mapname>\n" );
                return 0;
        }
@@ -188,7 +190,7 @@ int ImportLightmapsMain( int argc, char **argv ){
 
 
        /* arg checking */
-       if ( argc < 1 ) {
+       if ( argc < 2 ) {
                Sys_Printf( "Usage: q3map -import [-v] <mapname>\n" );
                return 0;
        }
@@ -826,8 +828,7 @@ qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm ){
        /* for planar surfaces, create lightmap vectors for st->xyz conversion */
        if ( VectorLength( ds->lightmapVecs[ 2 ] ) || 1 ) {  /* ydnar: can't remember what exactly i was thinking here... */
                /* allocate space for the vectors */
-               lm->vecs = safe_malloc( 3 * sizeof( vec3_t ) );
-               memset( lm->vecs, 0, 3 * sizeof( vec3_t ) );
+               lm->vecs = safe_malloc0( 3 * sizeof( vec3_t ) );
                VectorCopy( ds->lightmapVecs[ 2 ], lm->vecs[ 2 ] );
 
                /* project stepped lightmap blocks and subtract to get planevecs */
@@ -997,18 +998,15 @@ void SetupSurfaceLightmaps( void ){
        /* allocate a list of surface clusters */
        numSurfaceClusters = 0;
        maxSurfaceClusters = numBSPLeafSurfaces;
-       surfaceClusters = safe_malloc( maxSurfaceClusters * sizeof( *surfaceClusters ) );
-       memset( surfaceClusters, 0, maxSurfaceClusters * sizeof( *surfaceClusters ) );
+       surfaceClusters = safe_malloc0( maxSurfaceClusters * sizeof( *surfaceClusters ) );
 
        /* allocate a list for per-surface info */
-       surfaceInfos = safe_malloc( numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
-       memset( surfaceInfos, 0, numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
+       surfaceInfos = safe_malloc0( numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
        for ( i = 0; i < numBSPDrawSurfaces; i++ )
                surfaceInfos[ i ].childSurfaceNum = -1;
 
        /* allocate a list of surface indexes to be sorted */
-       sortSurfaces = safe_malloc( numBSPDrawSurfaces * sizeof( int ) );
-       memset( sortSurfaces, 0, numBSPDrawSurfaces * sizeof( int ) );
+       sortSurfaces = safe_malloc0( numBSPDrawSurfaces * sizeof( int ) );
 
        /* walk each model in the bsp */
        for ( i = 0; i < numBSPModels; i++ )
@@ -1129,14 +1127,12 @@ void SetupSurfaceLightmaps( void ){
 
        /* allocate a list of surfaces that would go into raw lightmaps */
        numLightSurfaces = 0;
-       lightSurfaces = safe_malloc( numSurfsLightmapped * sizeof( int ) );
-       memset( lightSurfaces, 0, numSurfsLightmapped * sizeof( int ) );
+       lightSurfaces = safe_malloc0( numSurfsLightmapped * sizeof( int ) );
 
        /* allocate a list of raw lightmaps */
        numRawSuperLuxels = 0;
        numRawLightmaps = 0;
-       rawLightmaps = safe_malloc( numSurfsLightmapped * sizeof( *rawLightmaps ) );
-       memset( rawLightmaps, 0, numSurfsLightmapped * sizeof( *rawLightmaps ) );
+       rawLightmaps = safe_malloc0( numSurfsLightmapped * sizeof( *rawLightmaps ) );
 
        /* walk the list of sorted surfaces */
        for ( i = 0; i < numBSPDrawSurfaces; i++ )
@@ -1225,10 +1221,8 @@ void SetupSurfaceLightmaps( void ){
        /* allocate vertex luxel storage */
        for ( k = 0; k < MAX_LIGHTMAPS; k++ )
        {
-               vertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-               memset( vertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-               radVertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-               memset( radVertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
+               vertexLuxels[ k ] = safe_malloc0( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
+               radVertexLuxels[ k ] = safe_malloc0( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
        }
 
        /* emit some stats */
@@ -1979,13 +1973,10 @@ static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm ){
        olm->numShaders = 0;
 
        /* allocate buffers */
-       olm->lightBits = safe_malloc( ( olm->customWidth * olm->customHeight / 8 ) + 8 );
-       memset( olm->lightBits, 0, ( olm->customWidth * olm->customHeight / 8 ) + 8 );
-       olm->bspLightBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
-       memset( olm->bspLightBytes, 0, olm->customWidth * olm->customHeight * 3 );
+       olm->lightBits = safe_malloc0( ( olm->customWidth * olm->customHeight / 8 ) + 8 );
+       olm->bspLightBytes = safe_malloc0( olm->customWidth * olm->customHeight * 3 );
        if ( deluxemap ) {
-               olm->bspDirBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
-               memset( olm->bspDirBytes, 0, olm->customWidth * olm->customHeight * 3 );
+               olm->bspDirBytes = safe_malloc0( olm->customWidth * olm->customHeight * 3 );
        }
 }
 
@@ -2007,7 +1998,6 @@ static void FindOutLightmaps( rawLightmap_t *lm, qboolean fastAllocate ){
        qboolean ok;
        int xIncrement, yIncrement;
 
-
        /* set default lightmap number (-3 = LIGHTMAP_BY_VERTEX) */
        for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
                lm->outLightmapNums[ lightmapNum ] = -3;
@@ -2488,7 +2478,7 @@ void FillOutLightmap( outLightmap_t *olm ){
    stores the surface lightmaps into the bsp as byte rgb triplets
  */
 
-void StoreSurfaceLightmaps( qboolean fastAllocate ){
+void StoreSurfaceLightmaps( qboolean fastAllocate, qboolean storeForReal ){
        int i, j, k, x, y, lx, ly, sx, sy, *cluster, mappedSamples;
        int style, size, lightmapNum, lightmapNum2;
        float               *normal, *luxel, *bspLuxel, *bspLuxel2, *radLuxel, samples, occludedSamples;
@@ -2553,8 +2543,7 @@ void StoreSurfaceLightmaps( qboolean fastAllocate ){
                        /* allocate bsp luxel storage */
                        if ( lm->bspLuxels[ lightmapNum ] == NULL ) {
                                size = lm->w * lm->h * BSP_LUXEL_SIZE * sizeof( float );
-                               lm->bspLuxels[ lightmapNum ] = safe_malloc( size );
-                               memset( lm->bspLuxels[ lightmapNum ], 0, size );
+                               lm->bspLuxels[ lightmapNum ] = safe_malloc0( size );
                        }
 
                        /* allocate radiosity lightmap storage */
@@ -2996,7 +2985,7 @@ void StoreSurfaceLightmaps( qboolean fastAllocate ){
           collapse non-unique lightmaps
           ----------------------------------------------------------------- */
 
-       if ( noCollapse == qfalse && deluxemap == qfalse ) {
+       if ( storeForReal && noCollapse == qfalse && deluxemap == qfalse ) {
                /* note it */
                Sys_FPrintf( SYS_VRB, "collapsing..." );
 
@@ -3083,52 +3072,54 @@ void StoreSurfaceLightmaps( qboolean fastAllocate ){
           allocate output lightmaps
           ----------------------------------------------------------------- */
 
-       /* note it */
-       Sys_FPrintf( SYS_VRB, "allocating..." );
+       if ( storeForReal ) {
+               /* note it */
+               Sys_FPrintf( SYS_VRB, "allocating..." );
 
-       /* kill all existing output lightmaps */
-       if ( outLightmaps != NULL ) {
-               for ( i = 0; i < numOutLightmaps; i++ )
-               {
-                       free( outLightmaps[ i ].lightBits );
-                       free( outLightmaps[ i ].bspLightBytes );
+               /* kill all existing output lightmaps */
+               if ( outLightmaps != NULL ) {
+                       for ( i = 0; i < numOutLightmaps; i++ )
+                       {
+                               free( outLightmaps[ i ].lightBits );
+                               free( outLightmaps[ i ].bspLightBytes );
+                       }
+                       free( outLightmaps );
+                       outLightmaps = NULL;
                }
-               free( outLightmaps );
-               outLightmaps = NULL;
-       }
-
-       numLightmapShaders = 0;
-       numOutLightmaps = 0;
-       numBSPLightmaps = 0;
-       numExtLightmaps = 0;
 
-       /* find output lightmap */
-       for ( i = 0; i < numRawLightmaps; i++ )
-       {
-               lm = &rawLightmaps[ sortLightmaps[ i ] ];
-               FindOutLightmaps( lm, fastAllocate );
-       }
+               numLightmapShaders = 0;
+               numOutLightmaps = 0;
+               numBSPLightmaps = 0;
+               numExtLightmaps = 0;
 
-       /* set output numbers in twinned lightmaps */
-       for ( i = 0; i < numRawLightmaps; i++ )
-       {
-               /* get lightmap */
-               lm = &rawLightmaps[ sortLightmaps[ i ] ];
+               /* find output lightmap */
+               for ( i = 0; i < numRawLightmaps; i++ )
+               {
+                       lm = &rawLightmaps[ sortLightmaps[ i ] ];
+                       FindOutLightmaps( lm, fastAllocate );
+               }
 
-               /* walk lightmaps */
-               for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+               /* set output numbers in twinned lightmaps */
+               for ( i = 0; i < numRawLightmaps; i++ )
                {
-                       /* get twin */
-                       lm2 = lm->twins[ lightmapNum ];
-                       if ( lm2 == NULL ) {
-                               continue;
-                       }
-                       lightmapNum2 = lm->twinNums[ lightmapNum ];
+                       /* get lightmap */
+                       lm = &rawLightmaps[ sortLightmaps[ i ] ];
 
-                       /* find output lightmap from twin */
-                       lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ];
-                       lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ];
-                       lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ];
+                       /* walk lightmaps */
+                       for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+                       {
+                               /* get twin */
+                               lm2 = lm->twins[ lightmapNum ];
+                               if ( lm2 == NULL ) {
+                                       continue;
+                               }
+                               lightmapNum2 = lm->twinNums[ lightmapNum ];
+
+                               /* find output lightmap from twin */
+                               lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ];
+                               lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ];
+                               lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ];
+                       }
                }
        }
 
@@ -3136,373 +3127,376 @@ void StoreSurfaceLightmaps( qboolean fastAllocate ){
           store output lightmaps
           ----------------------------------------------------------------- */
 
-       /* note it */
-       Sys_FPrintf( SYS_VRB, "storing..." );
-
-       /* count the bsp lightmaps and allocate space */
-       if ( bspLightBytes != NULL ) {
-               free( bspLightBytes );
-       }
-       if ( numBSPLightmaps == 0 || externalLightmaps ) {
-               numBSPLightBytes = 0;
-               bspLightBytes = NULL;
-       }
-       else
-       {
-               numBSPLightBytes = ( numBSPLightmaps * game->lightmapSize * game->lightmapSize * 3 );
-               bspLightBytes = safe_malloc( numBSPLightBytes );
-               memset( bspLightBytes, 0, numBSPLightBytes );
-       }
-
-       /* walk the list of output lightmaps */
-       for ( i = 0; i < numOutLightmaps; i++ )
-       {
-               /* get output lightmap */
-               olm = &outLightmaps[ i ];
+       if ( storeForReal ) {
+               /* note it */
+               Sys_FPrintf( SYS_VRB, "storing..." );
 
-               /* fill output lightmap */
-               if ( lightmapFill ) {
-                       FillOutLightmap( olm );
+               /* count the bsp lightmaps and allocate space */
+               if ( bspLightBytes != NULL ) {
+                       free( bspLightBytes );
+               }
+               if ( numBSPLightmaps == 0 || externalLightmaps ) {
+                       numBSPLightBytes = 0;
+                       bspLightBytes = NULL;
+               }
+               else
+               {
+                       numBSPLightBytes = ( numBSPLightmaps * game->lightmapSize * game->lightmapSize * 3 );
+                       bspLightBytes = safe_malloc0( numBSPLightBytes );
                }
 
-               /* is this a valid bsp lightmap? */
-               if ( olm->lightmapNum >= 0 && !externalLightmaps ) {
-                       /* copy lighting data */
-                       lb = bspLightBytes + ( olm->lightmapNum * game->lightmapSize * game->lightmapSize * 3 );
-                       memcpy( lb, olm->bspLightBytes, game->lightmapSize * game->lightmapSize * 3 );
+               /* walk the list of output lightmaps */
+               for ( i = 0; i < numOutLightmaps; i++ )
+               {
+                       /* get output lightmap */
+                       olm = &outLightmaps[ i ];
 
-                       /* copy direction data */
-                       if ( deluxemap ) {
-                               lb = bspLightBytes + ( ( olm->lightmapNum + 1 ) * game->lightmapSize * game->lightmapSize * 3 );
-                               memcpy( lb, olm->bspDirBytes, game->lightmapSize * game->lightmapSize * 3 );
+                       /* fill output lightmap */
+                       if ( lightmapFill ) {
+                               FillOutLightmap( olm );
                        }
-               }
 
-               /* external lightmap? */
-               if ( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps ) {
-                       /* make a directory for the lightmaps */
-                       Q_mkdir( dirname );
+                       /* is this a valid bsp lightmap? */
+                       if ( olm->lightmapNum >= 0 && !externalLightmaps ) {
+                               /* copy lighting data */
+                               lb = bspLightBytes + ( olm->lightmapNum * game->lightmapSize * game->lightmapSize * 3 );
+                               memcpy( lb, olm->bspLightBytes, game->lightmapSize * game->lightmapSize * 3 );
 
-                       /* set external lightmap number */
-                       olm->extLightmapNum = numExtLightmaps;
+                               /* copy direction data */
+                               if ( deluxemap ) {
+                                       lb = bspLightBytes + ( ( olm->lightmapNum + 1 ) * game->lightmapSize * game->lightmapSize * 3 );
+                                       memcpy( lb, olm->bspDirBytes, game->lightmapSize * game->lightmapSize * 3 );
+                               }
+                       }
+
+                       /* external lightmap? */
+                       if ( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps ) {
+                               /* make a directory for the lightmaps */
+                               Q_mkdir( dirname );
 
-                       /* write lightmap */
-                       sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
-                       Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
-                       WriteTGA24( filename, olm->bspLightBytes, olm->customWidth, olm->customHeight, qtrue );
-                       numExtLightmaps++;
+                               /* set external lightmap number */
+                               olm->extLightmapNum = numExtLightmaps;
 
-                       /* write deluxemap */
-                       if ( deluxemap ) {
+                               /* write lightmap */
                                sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
                                Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
-                               WriteTGA24( filename, olm->bspDirBytes, olm->customWidth, olm->customHeight, qtrue );
+                               WriteTGA24( filename, olm->bspLightBytes, olm->customWidth, olm->customHeight, qtrue );
                                numExtLightmaps++;
 
-                               if ( debugDeluxemap ) {
-                                       olm->extLightmapNum++;
+                               /* write deluxemap */
+                               if ( deluxemap ) {
+                                       sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
+                                       Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
+                                       WriteTGA24( filename, olm->bspDirBytes, olm->customWidth, olm->customHeight, qtrue );
+                                       numExtLightmaps++;
+
+                                       if ( debugDeluxemap ) {
+                                               olm->extLightmapNum++;
+                                       }
                                }
                        }
                }
-       }
-
-       if ( numExtLightmaps > 0 ) {
-               Sys_FPrintf( SYS_VRB, "\n" );
-       }
 
-       /* delete unused external lightmaps */
-       for ( i = numExtLightmaps; i; i++ )
-       {
-               /* determine if file exists */
-               sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i );
-               if ( !FileExists( filename ) ) {
-                       break;
+               if ( numExtLightmaps > 0 ) {
+                       Sys_FPrintf( SYS_VRB, "\n" );
                }
 
-               /* delete it */
-               remove( filename );
+               /* delete unused external lightmaps */
+               for ( i = numExtLightmaps; i; i++ )
+               {
+                       /* determine if file exists */
+                       sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i );
+                       if ( !FileExists( filename ) ) {
+                               break;
+                       }
+
+                       /* delete it */
+                       remove( filename );
+               }
        }
 
        /* -----------------------------------------------------------------
           project the lightmaps onto the bsp surfaces
           ----------------------------------------------------------------- */
 
-       /* note it */
-       Sys_FPrintf( SYS_VRB, "projecting..." );
+       if ( storeForReal ) {
+               /* note it */
+               Sys_FPrintf( SYS_VRB, "projecting..." );
 
-       /* walk the list of surfaces */
-       for ( i = 0; i < numBSPDrawSurfaces; i++ )
-       {
-               /* get the surface and info */
-               ds = &bspDrawSurfaces[ i ];
-               info = &surfaceInfos[ i ];
-               lm = info->lm;
-               olm = NULL;
-
-               /* handle surfaces with identical parent */
-               if ( info->parentSurfaceNum >= 0 ) {
-                       /* preserve original data and get parent */
-                       parent = &bspDrawSurfaces[ info->parentSurfaceNum ];
-                       memcpy( &dsTemp, ds, sizeof( *ds ) );
-
-                       /* overwrite child with parent data */
-                       memcpy( ds, parent, sizeof( *ds ) );
-
-                       /* restore key parts */
-                       ds->fogNum = dsTemp.fogNum;
-                       ds->firstVert = dsTemp.firstVert;
-                       ds->firstIndex = dsTemp.firstIndex;
-                       memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) );
-
-                       /* set vertex data */
-                       dv = &bspDrawVerts[ ds->firstVert ];
-                       dvParent = &bspDrawVerts[ parent->firstVert ];
-                       for ( j = 0; j < ds->numVerts; j++ )
-                       {
-                               memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) );
-                               memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) );
-                       }
+               /* walk the list of surfaces */
+               for ( i = 0; i < numBSPDrawSurfaces; i++ )
+               {
+                       /* get the surface and info */
+                       ds = &bspDrawSurfaces[ i ];
+                       info = &surfaceInfos[ i ];
+                       lm = info->lm;
+                       olm = NULL;
 
-                       /* skip the rest */
-                       continue;
-               }
+                       /* handle surfaces with identical parent */
+                       if ( info->parentSurfaceNum >= 0 ) {
+                               /* preserve original data and get parent */
+                               parent = &bspDrawSurfaces[ info->parentSurfaceNum ];
+                               memcpy( &dsTemp, ds, sizeof( *ds ) );
 
-               /* handle vertex lit or approximated surfaces */
-               else if ( lm == NULL || lm->outLightmapNums[ 0 ] < 0 ) {
-                       for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-                       {
-                               ds->lightmapNum[ lightmapNum ] = -3;
-                               ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ];
-                       }
-               }
+                               /* overwrite child with parent data */
+                               memcpy( ds, parent, sizeof( *ds ) );
 
-               /* handle lightmapped surfaces */
-               else
-               {
-                       /* walk lightmaps */
-                       for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-                       {
-                               /* set style */
-                               ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
+                               /* restore key parts */
+                               ds->fogNum = dsTemp.fogNum;
+                               ds->firstVert = dsTemp.firstVert;
+                               ds->firstIndex = dsTemp.firstIndex;
+                               memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) );
 
-                               /* handle unused style */
-                               if ( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) {
+                               /* set vertex data */
+                               dv = &bspDrawVerts[ ds->firstVert ];
+                               dvParent = &bspDrawVerts[ parent->firstVert ];
+                               for ( j = 0; j < ds->numVerts; j++ )
+                               {
+                                       memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) );
+                                       memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) );
+                               }
+
+                               /* skip the rest */
+                               continue;
+                       }
+
+                       /* handle vertex lit or approximated surfaces */
+                       else if ( lm == NULL || lm->outLightmapNums[ 0 ] < 0 ) {
+                               for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+                               {
                                        ds->lightmapNum[ lightmapNum ] = -3;
-                                       continue;
+                                       ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ];
                                }
+                       }
 
-                               /* get output lightmap */
-                               olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
+                       /* handle lightmapped surfaces */
+                       else
+                       {
+                               /* walk lightmaps */
+                               for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+                               {
+                                       /* set style */
+                                       ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
 
-                               /* set bsp lightmap number */
-                               ds->lightmapNum[ lightmapNum ] = olm->lightmapNum;
+                                       /* handle unused style */
+                                       if ( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) {
+                                               ds->lightmapNum[ lightmapNum ] = -3;
+                                               continue;
+                                       }
 
-                               /* deluxemap debugging makes the deluxemap visible */
-                               if ( deluxemap && debugDeluxemap && lightmapNum == 0 ) {
-                                       ds->lightmapNum[ lightmapNum ]++;
-                               }
+                                       /* get output lightmap */
+                                       olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
 
-                               /* calc lightmap origin in texture space */
-                               lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth;
-                               lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight;
+                                       /* set bsp lightmap number */
+                                       ds->lightmapNum[ lightmapNum ] = olm->lightmapNum;
 
-                               /* calc lightmap st coords */
-                               dv = &bspDrawVerts[ ds->firstVert ];
-                               ydv = &yDrawVerts[ ds->firstVert ];
-                               for ( j = 0; j < ds->numVerts; j++ )
-                               {
-                                       if ( lm->solid[ lightmapNum ] ) {
-                                               dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( 0.5f / (float) olm->customWidth );
-                                               dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( 0.5f / (float) olm->customWidth );
+                                       /* deluxemap debugging makes the deluxemap visible */
+                                       if ( deluxemap && debugDeluxemap && lightmapNum == 0 ) {
+                                               ds->lightmapNum[ lightmapNum ]++;
                                        }
-                                       else
+
+                                       /* calc lightmap origin in texture space */
+                                       lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth;
+                                       lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight;
+
+                                       /* calc lightmap st coords */
+                                       dv = &bspDrawVerts[ ds->firstVert ];
+                                       ydv = &yDrawVerts[ ds->firstVert ];
+                                       for ( j = 0; j < ds->numVerts; j++ )
                                        {
-                                               dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( ydv[ j ].lightmap[ 0 ][ 0 ] / ( superSample * olm->customWidth ) );
-                                               dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( ydv[ j ].lightmap[ 0 ][ 1 ] / ( superSample * olm->customHeight ) );
+                                               if ( lm->solid[ lightmapNum ] ) {
+                                                       dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( 0.5f / (float) olm->customWidth );
+                                                       dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( 0.5f / (float) olm->customWidth );
+                                               }
+                                               else
+                                               {
+                                                       dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( ydv[ j ].lightmap[ 0 ][ 0 ] / ( superSample * olm->customWidth ) );
+                                                       dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( ydv[ j ].lightmap[ 0 ][ 1 ] / ( superSample * olm->customHeight ) );
+                                               }
                                        }
                                }
                        }
-               }
 
-               /* store vertex colors */
-               dv = &bspDrawVerts[ ds->firstVert ];
-               for ( j = 0; j < ds->numVerts; j++ )
-               {
-                       /* walk lightmaps */
-                       for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+                       /* store vertex colors */
+                       dv = &bspDrawVerts[ ds->firstVert ];
+                       for ( j = 0; j < ds->numVerts; j++ )
                        {
-                               /* handle unused style */
-                               if ( ds->vertexStyles[ lightmapNum ] == LS_NONE ) {
-                                       VectorClear( color );
-                               }
-                               else
+                               /* walk lightmaps */
+                               for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
                                {
-                                       /* get vertex color */
-                                       luxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + j );
-                                       VectorCopy( luxel, color );
+                                       /* handle unused style */
+                                       if ( ds->vertexStyles[ lightmapNum ] == LS_NONE ) {
+                                               VectorClear( color );
+                                       }
+                                       else
+                                       {
+                                               /* get vertex color */
+                                               luxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + j );
+                                               VectorCopy( luxel, color );
 
-                                       /* set minimum light */
-                                       if ( lightmapNum == 0 ) {
-                                               for ( k = 0; k < 3; k++ )
-                                                       if ( color[ k ] < minVertexLight[ k ] ) {
-                                                               color[ k ] = minVertexLight[ k ];
-                                                       }
+                                               /* set minimum light */
+                                               if ( lightmapNum == 0 ) {
+                                                       for ( k = 0; k < 3; k++ )
+                                                               if ( color[ k ] < minVertexLight[ k ] ) {
+                                                                       color[ k ] = minVertexLight[ k ];
+                                                               }
+                                               }
                                        }
-                               }
 
-                               /* store to bytes */
-                               if ( !info->si->noVertexLight ) {
-                                       ColorToBytes( color, dv[ j ].color[ lightmapNum ], info->si->vertexScale );
+                                       /* store to bytes */
+                                       if ( !info->si->noVertexLight ) {
+                                               ColorToBytes( color, dv[ j ].color[ lightmapNum ], info->si->vertexScale );
+                                       }
                                }
                        }
-               }
-
-               /* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */
-               if ( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && game->load != LoadRBSPFile ) { //%      info->si->styleMarker > 0 )
-                       qboolean dfEqual;
-                       char key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ];
-
 
-                       /* setup */
-                       sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" );
-                       dv = &bspDrawVerts[ ds->firstVert ];
-
-                       /* depthFunc equal? */
-                       if ( info->si->styleMarker == 2 || info->si->implicitMap == IM_MASKED ) {
-                               dfEqual = qtrue;
-                       }
-                       else{
-                               dfEqual = qfalse;
-                       }
+                       /* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */
+                       if ( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && game->load != LoadRBSPFile ) { //%      info->si->styleMarker > 0 )
+                               qboolean dfEqual;
+                               char key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ];
 
-                       /* generate stages for styled lightmaps */
-                       for ( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-                       {
-                               /* early out */
-                               style = lm->styles[ lightmapNum ];
-                               if ( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) {
-                                       continue;
-                               }
 
-                               /* get output lightmap */
-                               olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
+                               /* setup */
+                               sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" );
+                               dv = &bspDrawVerts[ ds->firstVert ];
 
-                               /* lightmap name */
-                               if ( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] ) {
-                                       strcpy( lightmapName, "$lightmap" );
+                               /* depthFunc equal? */
+                               if ( info->si->styleMarker == 2 || info->si->implicitMap == IM_MASKED ) {
+                                       dfEqual = qtrue;
                                }
                                else{
-                                       sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
+                                       dfEqual = qfalse;
                                }
 
-                               /* get rgbgen string */
-                               if ( rgbGenValues[ style ] == NULL ) {
-                                       sprintf( key, "_style%drgbgen", style );
-                                       rgbGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
-                                       if ( rgbGenValues[ style ][ 0 ] == '\0' ) {
-                                               rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37";
+                               /* generate stages for styled lightmaps */
+                               for ( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+                               {
+                                       /* early out */
+                                       style = lm->styles[ lightmapNum ];
+                                       if ( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) {
+                                               continue;
+                                       }
+
+                                       /* get output lightmap */
+                                       olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
+
+                                       /* lightmap name */
+                                       if ( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] ) {
+                                               strcpy( lightmapName, "$lightmap" );
+                                       }
+                                       else{
+                                               sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
+                                       }
+
+                                       /* get rgbgen string */
+                                       if ( rgbGenValues[ style ] == NULL ) {
+                                               sprintf( key, "_style%drgbgen", style );
+                                               rgbGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
+                                               if ( rgbGenValues[ style ][ 0 ] == '\0' ) {
+                                                       rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37";
+                                               }
                                        }
-                               }
-                               rgbGen[ 0 ] = '\0';
-                               if ( rgbGenValues[ style ][ 0 ] != '\0' ) {
-                                       sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style );
-                               }
-                               else{
                                        rgbGen[ 0 ] = '\0';
-                               }
+                                       if ( rgbGenValues[ style ][ 0 ] != '\0' ) {
+                                               sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style );
+                                       }
+                                       else{
+                                               rgbGen[ 0 ] = '\0';
+                                       }
 
-                               /* get alphagen string */
-                               if ( alphaGenValues[ style ] == NULL ) {
-                                       sprintf( key, "_style%dalphagen", style );
-                                       alphaGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
-                               }
-                               if ( alphaGenValues[ style ][ 0 ] != '\0' ) {
-                                       sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style );
-                               }
-                               else{
-                                       alphaGen[ 0 ] = '\0';
-                               }
+                                       /* get alphagen string */
+                                       if ( alphaGenValues[ style ] == NULL ) {
+                                               sprintf( key, "_style%dalphagen", style );
+                                               alphaGenValues[ style ] = ValueForKey( &entities[ 0 ], key );
+                                       }
+                                       if ( alphaGenValues[ style ][ 0 ] != '\0' ) {
+                                               sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style );
+                                       }
+                                       else{
+                                               alphaGen[ 0 ] = '\0';
+                                       }
 
-                               /* calculate st offset */
-                               lmx = dv[ 0 ].lightmap[ lightmapNum ][ 0 ] - dv[ 0 ].lightmap[ 0 ][ 0 ];
-                               lmy = dv[ 0 ].lightmap[ lightmapNum ][ 1 ] - dv[ 0 ].lightmap[ 0 ][ 1 ];
-
-                               /* create additional stage */
-                               if ( lmx == 0.0f && lmy == 0.0f ) {
-                                       sprintf( styleStage,    "\t{\n"
-                                                                                       "\t\tmap %s\n"                                      /* lightmap */
-                                                                                       "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
-                                                                                       "%s"                                                /* depthFunc equal */
-                                                                                       "%s"                                                /* rgbGen */
-                                                                                       "%s"                                                /* alphaGen */
-                                                                                       "\t\ttcGen lightmap\n"
-                                                                                       "\t}\n",
-                                                        lightmapName,
-                                                        ( dfEqual ? "\t\tdepthFunc equal\n" : "" ),
-                                                        rgbGen,
-                                                        alphaGen );
+                                       /* calculate st offset */
+                                       lmx = dv[ 0 ].lightmap[ lightmapNum ][ 0 ] - dv[ 0 ].lightmap[ 0 ][ 0 ];
+                                       lmy = dv[ 0 ].lightmap[ lightmapNum ][ 1 ] - dv[ 0 ].lightmap[ 0 ][ 1 ];
+
+                                       /* create additional stage */
+                                       if ( lmx == 0.0f && lmy == 0.0f ) {
+                                               sprintf( styleStage,    "\t{\n"
+                                                                                               "\t\tmap %s\n"                                      /* lightmap */
+                                                                                               "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
+                                                                                               "%s"                                                /* depthFunc equal */
+                                                                                               "%s"                                                /* rgbGen */
+                                                                                               "%s"                                                /* alphaGen */
+                                                                                               "\t\ttcGen lightmap\n"
+                                                                                               "\t}\n",
+                                                                lightmapName,
+                                                                ( dfEqual ? "\t\tdepthFunc equal\n" : "" ),
+                                                                rgbGen,
+                                                                alphaGen );
+                                       }
+                                       else
+                                       {
+                                               sprintf( styleStage,    "\t{\n"
+                                                                                               "\t\tmap %s\n"                                      /* lightmap */
+                                                                                               "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
+                                                                                               "%s"                                                /* depthFunc equal */
+                                                                                               "%s"                                                /* rgbGen */
+                                                                                               "%s"                                                /* alphaGen */
+                                                                                               "\t\ttcGen lightmap\n"
+                                                                                               "\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n"         /* st offset */
+                                                                                               "\t}\n",
+                                                                lightmapName,
+                                                                ( dfEqual ? "\t\tdepthFunc equal\n" : "" ),
+                                                                rgbGen,
+                                                                alphaGen,
+                                                                lmx, lmy );
+
+                                       }
+
+                                       /* concatenate */
+                                       strcat( styleStages, styleStage );
                                }
-                               else
-                               {
-                                       sprintf( styleStage,    "\t{\n"
-                                                                                       "\t\tmap %s\n"                                      /* lightmap */
-                                                                                       "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
-                                                                                       "%s"                                                /* depthFunc equal */
-                                                                                       "%s"                                                /* rgbGen */
-                                                                                       "%s"                                                /* alphaGen */
-                                                                                       "\t\ttcGen lightmap\n"
-                                                                                       "\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n"         /* st offset */
-                                                                                       "\t}\n",
-                                                        lightmapName,
-                                                        ( dfEqual ? "\t\tdepthFunc equal\n" : "" ),
-                                                        rgbGen,
-                                                        alphaGen,
-                                                        lmx, lmy );
 
+                               /* create custom shader */
+                               if ( info->si->styleMarker == 2 ) {
+                                       csi = CustomShader( info->si, "q3map_styleMarker2", styleStages );
+                               }
+                               else{
+                                       csi = CustomShader( info->si, "q3map_styleMarker", styleStages );
                                }
 
-                               /* concatenate */
-                               strcat( styleStages, styleStage );
-                       }
+                               /* emit remap command */
+                               //%     EmitVertexRemapShader( csi->shader, info->si->shader );
 
-                       /* create custom shader */
-                       if ( info->si->styleMarker == 2 ) {
-                               csi = CustomShader( info->si, "q3map_styleMarker2", styleStages );
-                       }
-                       else{
-                               csi = CustomShader( info->si, "q3map_styleMarker", styleStages );
+                               /* store it */
+                               //%     Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
+                               ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+                               //%     Sys_Printf( ")\n" );
                        }
 
-                       /* emit remap command */
-                       //%     EmitVertexRemapShader( csi->shader, info->si->shader );
-
-                       /* store it */
-                       //%     Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
-                       ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
-                       //%     Sys_Printf( ")\n" );
-               }
-
-               /* devise a custom shader for this surface (fixme: make this work with light styles) */
-               else if ( olm != NULL && lm != NULL && !externalLightmaps &&
-                                 ( olm->customWidth != game->lightmapSize || olm->customHeight != game->lightmapSize ) ) {
-                       /* get output lightmap */
-                       olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
+                       /* devise a custom shader for this surface (fixme: make this work with light styles) */
+                       else if ( olm != NULL && lm != NULL && !externalLightmaps &&
+                                         ( olm->customWidth != game->lightmapSize || olm->customHeight != game->lightmapSize ) ) {
+                               /* get output lightmap */
+                               olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
 
-                       /* do some name mangling */
-                       sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
+                               /* do some name mangling */
+                               sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
 
-                       /* create custom shader */
-                       csi = CustomShader( info->si, "$lightmap", lightmapName );
+                               /* create custom shader */
+                               csi = CustomShader( info->si, "$lightmap", lightmapName );
 
-                       /* store it */
-                       //%     Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
-                       ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
-                       //%     Sys_Printf( ")\n" );
-               }
+                               /* store it */
+                               //%     Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
+                               ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+                               //%     Sys_Printf( ")\n" );
+                       }
 
-               /* use the normal plain-jane shader */
-               else{
-                       ds->shaderNum = EmitShader( info->si->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+                       /* use the normal plain-jane shader */
+                       else{
+                               ds->shaderNum = EmitShader( info->si->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+                       }
                }
        }
 
@@ -3515,17 +3509,19 @@ void StoreSurfaceLightmaps( qboolean fastAllocate ){
                                 ? 0
                                 : (float) numUsed / (float) numStored;
 
-       /* print stats */
-       Sys_Printf( "%9d luxels used\n", numUsed );
-       Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f );
-       Sys_Printf( "%9d solid surface lightmaps\n", numSolidLightmaps );
-       Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels );
-       Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced );
-       Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated );
-       Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps );
-       Sys_Printf( "%9d total lightmaps\n", numOutLightmaps );
-       Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders );
-
-       /* write map shader file */
-       WriteMapShaderFile();
+       if ( storeForReal ) {
+               /* print stats */
+               Sys_Printf( "%9d luxels used\n", numUsed );
+               Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f );
+               Sys_Printf( "%9d solid surface lightmaps\n", numSolidLightmaps );
+               Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels );
+               Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced );
+               Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated );
+               Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps );
+               Sys_Printf( "%9d total lightmaps\n", numOutLightmaps );
+               Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders );
+
+               /* write map shader file */
+               WriteMapShaderFile();
+       }
 }
index 1e2e67d5b07379670e6d449fe1c7a2011d30d49f..0021ba92257a5b52fa75b3a39afd7a21e4d80c11 100644 (file)
@@ -2096,14 +2096,16 @@ int main( int argc, char **argv ){
                /* -help */
                if ( !strcmp( argv[ i ], "-h" ) || !strcmp( argv[ i ], "--help" )
                        || !strcmp( argv[ i ], "-help" ) ) {
-                       HelpMain(argv[i+1]);
+                       HelpMain( ( i + 1 < argc ) ? argv[ i + 1 ] : NULL );
                        return 0;
                }
 
                /* -connect */
                if ( !strcmp( argv[ i ], "-connect" ) ) {
-                       argv[ i ] = NULL;
-                       i++;
+                       if ( ++i >= argc || !argv[ i ] ) {
+                               Error( "Out of arguments: No address specified after %s", argv[ i - 1 ] );
+                       }
+                       argv[ i - 1 ] = NULL;
                        Broadcast_Setup( argv[ i ] );
                        argv[ i ] = NULL;
                }
@@ -2130,8 +2132,10 @@ int main( int argc, char **argv ){
 
                /* patch subdivisions */
                else if ( !strcmp( argv[ i ], "-subdivisions" ) ) {
-                       argv[ i ] = NULL;
-                       i++;
+                       if ( ++i >= argc || !argv[ i ] ) {
+                               Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] );
+                       }
+                       argv[ i - 1 ] = NULL;
                        patchSubdivisions = atoi( argv[ i ] );
                        argv[ i ] = NULL;
                        if ( patchSubdivisions <= 0 ) {
@@ -2141,8 +2145,10 @@ int main( int argc, char **argv ){
 
                /* threads */
                else if ( !strcmp( argv[ i ], "-threads" ) ) {
-                       argv[ i ] = NULL;
-                       i++;
+                       if ( ++i >= argc || !argv[ i ] ) {
+                               Error( "Out of arguments: No value specified after %s", argv[ i - 1 ] );
+                       }
+                       argv[ i - 1 ] = NULL;
                        numthreads = atoi( argv[ i ] );
                        argv[ i ] = NULL;
                }
@@ -2179,7 +2185,7 @@ int main( int argc, char **argv ){
 
        Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
        Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
-       Sys_Printf( "NetRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
+       Sys_Printf( RADIANT_NAME "    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
        Sys_Printf( "%s\n", Q3MAP_MOTD );
        Sys_Printf( "%s\n", argv[0] );
 
@@ -2277,6 +2283,9 @@ int main( int argc, char **argv ){
 
        /* ydnar: otherwise create a bsp */
        else{
+               /* used to write Smokin'Guns like tex file */
+               compile_map = qtrue;
+
                r = BSPMain( argc, argv );
        }
 
index 7fb21bbf79be8f1c6446d8b97b075978260e1f4f..eba484198bb43349f80b00043d9dc4e301f37921 100644 (file)
@@ -1589,8 +1589,7 @@ void LoadEntityIndexMap( entity_t *e ){
        }
 
        /* create a new index map */
-       im = safe_malloc( sizeof( *im ) );
-       memset( im, 0, sizeof( *im ) );
+       im = safe_malloc0( sizeof( *im ) );
 
        /* set it up */
        im->w = w;
index 023afe392fc21f8359e6c8d4f7f3926b14a22d2c..caaffa94ba4eabe68a84275a69540d30b04b5951 100644 (file)
@@ -381,8 +381,7 @@ mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ){
        float len;
        mesh_t out;
 
-       /* ydnar: static for os x */
-       MAC_STATIC bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
+       bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
 
 
        out.width = in.width;
@@ -547,8 +546,7 @@ mesh_t *SubdivideMesh2( mesh_t in, int iterations ){
        bspDrawVert_t prev, next, mid;
        mesh_t out;
 
-       /* ydnar: static for os x */
-       MAC_STATIC bspDrawVert_t expand[ MAX_EXPANDED_AXIS ][ MAX_EXPANDED_AXIS ];
+       bspDrawVert_t expand[ MAX_EXPANDED_AXIS ][ MAX_EXPANDED_AXIS ];
 
 
        /* initial setup */
@@ -654,8 +652,7 @@ mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
        vec3_t proj, dir;
        mesh_t out;
 
-       /* ydnar: static for os x */
-       MAC_STATIC bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
+       bspDrawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
 
 
        out.width = in->width;
index 204e396c4cf2857095baab916e64bc756a92116b..7b582ee12787a9500f170099b800eba33a664ccf 100644 (file)
@@ -282,10 +282,9 @@ static void MiniMapBrightnessContrast( int y ){
        }
 }
 
-void MiniMapMakeMinsMaxs( vec3_t mins_in, vec3_t maxs_in, float border, qboolean keepaspect ){
-       vec3_t mins, maxs, extend;
-       VectorCopy( mins_in, mins );
-       VectorCopy( maxs_in, maxs );
+// modify maxs and mins in place, copy them before calling this!
+void MiniMapMakeMinsMaxs( vec3_t mins, vec3_t maxs, float border, qboolean keepaspect ){
+       vec3_t extend;
 
        // line compatible to nexuiz mapinfo
        Sys_Printf( "size %f %f %f %f %f %f\n", mins[0], mins[1], mins[2], maxs[0], maxs[1], maxs[2] );
@@ -601,7 +600,10 @@ int MiniMapBSPMain( int argc, char **argv ){
                }
        }
 
-       MiniMapMakeMinsMaxs( mins, maxs, border, keepaspect );
+       vec3_t mins_out, maxs_out;
+       VectorCopy( mins, mins_out );
+       VectorCopy( maxs, maxs_out );
+       MiniMapMakeMinsMaxs( mins_out, maxs_out, border, keepaspect );
 
        if ( !*minimapFilename ) {
                ExtractFileBase( source, basename );
@@ -773,6 +775,55 @@ int MiniMapBSPMain( int argc, char **argv ){
 
        Sys_Printf( " done.\n" );
 
+       switch ( game->miniMapSidecarFormat )
+       {
+               case MINIMAP_SIDECAR_UNVANQUISHED:
+               {
+                       char minimapPathWithoutExt[ 1024 ];
+                       char minimapSidecarFilename[ 1024 ];
+                       char *minimapSidecarExtension = ".minimap";
+                       char *minimapSidecarFormat = ""
+                               "{\n"
+                               "\tbackgroundColor 0.0 0.0 0.0 0.333\n"
+                               "\tzone {\n"
+                               "\t\tbounds 0 0 0 0 0 0\n"
+                               "\t\timage \"minimaps/%s\" %f %f %f %f\n"
+                               "\t}\n"
+                               "}\n";
+
+                       strcpy( minimapPathWithoutExt, minimapFilename );
+                       StripExtension( minimapPathWithoutExt );
+                       snprintf( minimapSidecarFilename,
+                               1024 - strlen(minimapSidecarExtension),
+                               "%s%s",
+                               minimapPathWithoutExt,
+                               minimapSidecarExtension );
+
+                       Sys_Printf( "Writing minimap sidecar to %s...", minimapSidecarFilename );
+
+                       FILE *file = fopen( minimapSidecarFilename, "w" );
+                       if ( file == NULL ) {
+                               Sys_FPrintf( SYS_WRN, "WARNING: Unable to open minimap sidecarr file %s for writing\n", minimapSidecarFilename );
+                               break;
+                       }
+
+                       fprintf( file,
+                               minimapSidecarFormat,
+                               basename,
+                               mins_out[0], mins_out[1],
+                               maxs_out[0], maxs_out[1] );
+
+                       fflush( file );
+                       fclose( file );
+
+                       Sys_Printf( " done.\n" );
+
+                       break;
+               }
+               case MINIMAP_SIDECAR_NONE:
+                       break;
+       }
+
        /* return to sender */
        return 0;
 }
index 6bbbe5c532c1b1b3d11b8413bd8ae648f6e502e1..17e690e7a1c67d1a97c1523f62685aaefb2d8095 100644 (file)
@@ -447,12 +447,10 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap
 
                /* set particulars */
                ds->numVerts = PicoGetSurfaceNumVertexes( surface );
-               ds->verts = safe_malloc( ds->numVerts * sizeof( ds->verts[ 0 ] ) );
-               memset( ds->verts, 0, ds->numVerts * sizeof( ds->verts[ 0 ] ) );
+               ds->verts = safe_malloc0( ds->numVerts * sizeof( ds->verts[ 0 ] ) );
 
                ds->numIndexes = PicoGetSurfaceNumIndexes( surface );
-               ds->indexes = safe_malloc( ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
-               memset( ds->indexes, 0, ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
+               ds->indexes = safe_malloc0( ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
 
                /* copy vertexes */
                for ( i = 0; i < ds->numVerts; i++ )
index 3b3949ced6ede9147272e7c0f28db19792966a98..95d478f647f3d5b0833bd8a2178aede53c5b40c0 100644 (file)
@@ -348,8 +348,7 @@ void ParsePatch( qboolean onlyLights ){
        }
 
        /* allocate patch mesh */
-       pm = safe_malloc( sizeof( *pm ) );
-       memset( pm, 0, sizeof( *pm ) );
+       pm = safe_malloc0( sizeof( *pm ) );
 
        /* ydnar: add entity/brush numbering */
        pm->entityNum = mapEnt->mapEntityNum;
@@ -428,10 +427,9 @@ void PatchMapDrawSurfs( entity_t *e ){
        vec3_t bounds[ 2 ];
        byte                    *bordering;
 
-       /* ydnar: mac os x fails with these if not static */
-       MAC_STATIC parseMesh_t  *meshes[ MAX_MAP_DRAW_SURFS ];
-       MAC_STATIC qb_t grouped[ MAX_MAP_DRAW_SURFS ];
-       MAC_STATIC byte group[ MAX_MAP_DRAW_SURFS ];
+       parseMesh_t  *meshes[ MAX_MAP_DRAW_SURFS ];
+       qb_t grouped[ MAX_MAP_DRAW_SURFS ];
+       byte group[ MAX_MAP_DRAW_SURFS ];
 
 
        /* note it */
@@ -446,8 +444,7 @@ void PatchMapDrawSurfs( entity_t *e ){
        if ( !patchCount ) {
                return;
        }
-       bordering = safe_malloc( patchCount * patchCount );
-       memset( bordering, 0, patchCount * patchCount );
+       bordering = safe_malloc0( patchCount * patchCount );
 
        // build the bordering matrix
        for ( k = 0 ; k < patchCount ; k++ ) {
index f8d978040ed5d6c22627ceb365dd31b81f2fc165..9bc5dd340c75c414b55001c41d0a53fb6f5047a6 100644 (file)
 
    ------------------------------------------------------------------------------- */
 
-
-
 /* marker */
 #define PATH_INIT_C
 
-
-
 /* dependencies */
 #include "q3map2.h"
 
-
-
 /* path support */
 #define MAX_BASE_PATHS  10
 #define MAX_GAME_PATHS  10
 #define MAX_PAK_PATHS  200
 
+qboolean                               customHomePath = qfalse;
 char                    *homePath;
+
+#if GDEF_OS_MACOS
+char                                   *macLibraryApplicationSupportPath;
+#elif GDEF_OS_XDG
+char                    *xdgDataHomePath;
+#endif // GDEF_OS_XDG
+
 char installPath[ MAX_OS_PATH ];
 
 int numBasePaths;
@@ -66,31 +68,27 @@ char                    *homeBasePath = NULL;
  */
 
 char *LokiGetHomeDir( void ){
-       #ifndef Q_UNIX
+       #if GDEF_OS_WINDOWS
        return NULL;
-       #else
+       #else // !GDEF_OS_WINDOWS
        static char     buf[ 4096 ];
        struct passwd   pw, *pwp;
        char            *home;
-       static char homeBuf[MAX_OS_PATH];
-
 
        /* get the home environment variable */
        home = getenv( "HOME" );
 
        /* look up home dir in password database */
-       if(!home)
+       if( home == NULL )
        {
                if ( getpwuid_r( getuid(), &pw, buf, sizeof( buf ), &pwp ) == 0 ) {
                        return pw.pw_dir;
                }
        }
 
-       snprintf( homeBuf, sizeof( homeBuf ), "%s/.", home );
-
        /* return it */
-       return homeBuf;
-       #endif
+       return home;
+       #endif // !GDEF_OS_WINDOWS
 }
 
 
@@ -103,7 +101,7 @@ char *LokiGetHomeDir( void ){
 void LokiInitPaths( char *argv0 ){
        char *home;
 
-       if ( !homePath ) {
+       if ( homePath == NULL ) {
                /* get home dir */
                home = LokiGetHomeDir();
                if ( home == NULL ) {
@@ -113,14 +111,28 @@ void LokiInitPaths( char *argv0 ){
                /* set home path */
                homePath = home;
        }
-       else{
+       else {
                home = homePath;
        }
 
-       #ifndef Q_UNIX
+       #if GDEF_OS_MACOS
+       char *subPath = "/Library/Application Support";
+       macLibraryApplicationSupportPath = safe_malloc( sizeof( char ) * ( strlen( home ) + strlen( subPath ) ) + 1 );
+       sprintf( macLibraryApplicationSupportPath, "%s%s", home, subPath );
+       #elif GDEF_OS_XDG
+       xdgDataHomePath = getenv( "XDG_DATA_HOME" );
+
+       if ( xdgDataHomePath == NULL ) {
+               char *subPath = "/.local/share";
+               xdgDataHomePath = safe_malloc( sizeof( char ) * ( strlen( home ) + strlen( subPath ) ) + 1 );
+               sprintf( xdgDataHomePath, "%s%s", home, subPath );
+       }
+       #endif // GDEF_OS_XDG
+
+       #if GDEF_OS_WINDOWS
        /* this is kinda crap, but hey */
        strcpy( installPath, "../" );
-       #else
+       #else // !GDEF_OS_WINDOWS
 
        char temp[ MAX_OS_PATH ];
        char *path;
@@ -135,7 +147,7 @@ void LokiInitPaths( char *argv0 ){
        if ( strrchr( temp, '/' ) ) {
                argv0 = strrchr( argv0, '/' ) + 1;
        }
-       else if ( path ) {
+       else if ( path != NULL ) {
 
                /*
                   This code has a special behavior when q3map2 is a symbolic link.
@@ -203,7 +215,7 @@ void LokiInitPaths( char *argv0 ){
                *( strrchr( installPath, '/' ) ) = '\0';
                *( strrchr( installPath, '/' ) ) = '\0';
        }
-       #endif
+       #endif // !GDEF_OS_WINDOWS
 }
 
 
@@ -291,15 +303,14 @@ void AddBasePath( char *path ){
 
 /*
    AddHomeBasePath() - ydnar
-   adds a base path to the beginning of the list, prefixed by ~/
+   adds a base path to the beginning of the list
  */
 
 void AddHomeBasePath( char *path ){
        int i;
        char temp[ MAX_OS_PATH ];
-       int homePathLen;
 
-       if ( !homePath ) {
+       if ( homePath == NULL ) {
                return;
        }
 
@@ -308,28 +319,55 @@ void AddHomeBasePath( char *path ){
                return;
        }
 
-       /* strip leading dot, if homePath does not end in /. */
-       homePathLen = strlen( homePath );
-       if ( !strcmp( path, "." ) ) {
+       if ( strcmp( path, "." ) == 0 ) {
                /* -fs_homebase . means that -fs_home is to be used as is */
                strcpy( temp, homePath );
        }
-       else if ( homePathLen >= 2 && !strcmp( homePath + homePathLen - 2, "/." ) ) {
-               /* remove trailing /. of homePath */
-               homePathLen -= 2;
+       else {
+               char *tempHomePath;
+               tempHomePath = homePath;
 
-               /* concatenate home dir and path */
-               sprintf( temp, "%.*s/%s", homePathLen, homePath, path );
-       }
-       else
-       {
-               /* remove leading . of path */
-               if ( path[0] == '.' ) {
-                       ++path;
+               /* homePath is . on Windows if not user supplied */
+
+               #if GDEF_OS_MACOS
+               /*
+                  use ${HOME}/Library/Application as ${HOME}
+                  if home path is not user supplied
+                  and strip the leading dot from prefix in any case
+                 
+                  basically it produces
+                  ${HOME}/Library/Application/unvanquished
+                  /user/supplied/home/path/unvanquished
+               */
+               tempHomePath = macLibraryApplicationSupportPath;
+               path = path + 1;
+               #elif GDEF_OS_XDG
+               /*
+                  on Linux, check if game uses ${XDG_DATA_HOME}/prefix instead of ${HOME}/.prefix
+                  if yes and home path is not user supplied
+                  use XDG_DATA_HOME instead of HOME
+                  and strip the leading dot
+
+                  basically it produces
+                  ${XDG_DATA_HOME}/unvanquished
+                  /user/supplied/home/path/unvanquished
+
+                  or
+                  ${HOME}/.q3a
+                  /user/supplied/home/path/.q3a
+                */
+
+               sprintf( temp, "%s/%s", xdgDataHomePath, ( path + 1 ) );
+               if ( access( temp, X_OK ) == 0 ) {
+                       if ( customHomePath == qfalse ) {
+                               tempHomePath = xdgDataHomePath;
+                       }
+                       path = path + 1;
                }
+               #endif // GDEF_OS_XDG
 
                /* concatenate home dir and path */
-               sprintf( temp, "%s/%s", homePath, path );
+               sprintf( temp, "%s/%s", tempHomePath, path );
        }
 
        /* make a hole */
@@ -435,7 +473,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -game */
                if ( strcmp( argv[ i ], "-game" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -448,7 +486,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_forbiddenpath */
                else if ( strcmp( argv[ i ], "-fs_forbiddenpath" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -476,7 +514,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_basepath */
                else if ( strcmp( argv[ i ], "-fs_basepath" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -486,7 +524,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_game */
                else if ( strcmp( argv[ i ], "-fs_game" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -496,10 +534,11 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_home */
                else if ( strcmp( argv[ i ], "-fs_home" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
+                       customHomePath = qtrue;
                        homePath = argv[i];
                        argv[ i ] = NULL;
                }
@@ -512,7 +551,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_homebase */
                else if ( strcmp( argv[ i ], "-fs_homebase" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -522,7 +561,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_homepath - sets both of them */
                else if ( strcmp( argv[ i ], "-fs_homepath" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
@@ -533,7 +572,7 @@ void InitPaths( int *argc, char **argv ){
 
                /* -fs_pakpath */
                else if ( strcmp( argv[ i ], "-fs_pakpath" ) == 0 ) {
-                       if ( ++i >= *argc ) {
+                       if ( ++i >= *argc || !argv[ i ] ) {
                                Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
                        }
                        argv[ i - 1 ] = NULL;
index 676fa31599df4754276c9580b5e532edd709912c..27ae8c31f31d8705d0eb06109ba3323386c69b6d 100644 (file)
@@ -62,8 +62,7 @@ portal_t *AllocPortal( void ){
                c_peak_portals = c_active_portals;
        }
 
-       p = safe_malloc( sizeof( portal_t ) );
-       memset( p, 0, sizeof( portal_t ) );
+       p = safe_malloc0( sizeof( portal_t ) );
 
        return p;
 }
index ff97ba02eb6a6d59cbdc8f9b6d1ab5d6edb003ed..1a7dd34e205e1a30b6679b46c6f24a11cc34cc81 100644 (file)
    ------------------------------------------------------------------------------- */
 
 /* platform-specific */
-#if GDEF_OS_LINUX || GDEF_OS_MACOS
-       #define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
+#if GDEF_OS_POSIX
        #include <unistd.h>
        #include <pwd.h>
        #include <limits.h>
@@ -66,8 +62,6 @@
 
 
 /* general */
-#include "version.h"            /* ttimo: might want to guard that if built outside of the GtkRadiant tree */
-
 #include "cmdlib.h"
 #include "mathlib.h"
 #include "md5lib.h"
 
    ------------------------------------------------------------------------------- */
 
-#define MAC_STATIC_HACK         0
-#if GDEF_OS_MACOS && MAC_STATIC_HACK
-       #define MAC_STATIC          static
-#else
-       #define MAC_STATIC
-#endif
-
-#if 1
        #if GDEF_OS_WINDOWS
                #define Q_stricmp           stricmp
                #define Q_strncasecmp       strnicmp
                #define Q_stricmp           strcasecmp
                #define Q_strncasecmp       strncasecmp
        #endif
+
+// hack to declare and define in the same file
+#ifdef MAIN_C
+       #define Q_EXTERN
+       #define Q_ASSIGN( a )   = a
+#else
+       #define Q_EXTERN extern
+       #define Q_ASSIGN( a )
 #endif
 
 /* macro version */
 /* general */
 #define MAX_QPATH               64
 
-#define MAX_IMAGES              512
+#define MAX_IMAGES              2048
 #define DEFAULT_IMAGE           "*default"
 
-#define MAX_MODELS              512
+#define MAX_MODELS              2048
 
 #define DEF_BACKSPLASH_FRACTION 0.05f   /* 5% backsplash by default */
 #define DEF_BACKSPLASH_DISTANCE 23
 #define C_DETAIL                0x08000000  /* THIS MUST BE THE SAME AS IN RADIANT! */
 
 
+/* new tex surface flags, like Smokin'Guns */
+#define TEX_SURF_METAL             0x00001000
+#define TEX_SURF_WOOD              0x00080000
+#define TEX_SURF_CLOTH             0x00100000
+#define TEX_SURF_DIRT              0x00200000
+#define TEX_SURF_GLASS             0x00400000
+#define TEX_SURF_PLANT             0x00800000
+#define TEX_SURF_SAND              0x01000000
+#define TEX_SURF_SNOW              0x02000000
+#define TEX_SURF_STONE             0x04000000
+#define TEX_SURF_WATER             0x08000000
+#define TEX_SURF_GRASS             0x10000000
+#define TEX_SURF_BREAKABLE         0x20000000
+
+
 /* shadow flags */
 #define WORLDSPAWN_CAST_SHADOWS 1
 #define WORLDSPAWN_RECV_SHADOWS 1
 #define HINT_PRIORITY           1000        /* ydnar: force hint splits first and antiportal/areaportal splits last */
 #define ANTIPORTAL_PRIORITY     -1000
 #define AREAPORTAL_PRIORITY     -1000
-#define DETAIL_PRIORITY     -3000
+#define DETAIL_PRIORITY         -3000
 
 #define PSIDE_FRONT             1
 #define PSIDE_BACK              2
 #define RAD_LUXEL_SIZE          3
 #define SUPER_LUXEL_SIZE        4
 #define SUPER_FLAG_SIZE         4
-#define FLAG_FORCE_SUBSAMPLING 1
+#define FLAG_FORCE_SUBSAMPLING  1
 #define FLAG_ALREADY_SUBSAMPLED 2
 #define SUPER_ORIGIN_SIZE       3
 #define SUPER_NORMAL_SIZE       4
@@ -551,6 +560,13 @@ typedef enum
 }
 miniMapMode_t;
 
+typedef enum
+{
+       MINIMAP_SIDECAR_NONE,
+       MINIMAP_SIDECAR_UNVANQUISHED
+}
+miniMapSidecarFormat_t;
+
 typedef struct game_s
 {
        char                *arg;                           /* -game matches this */
@@ -561,6 +577,7 @@ typedef struct game_s
        int maxLMSurfaceVerts;                              /* default maximum meta surface verts */
        int maxSurfaceVerts;                                /* default maximum surface verts */
        int maxSurfaceIndexes;                              /* default maximum surface indexes (tris * 3) */
+       qboolean texFile;                                   /* enable per shader prefix surface flags and .tex file */
        qboolean emitFlares;                                /* when true, emit flare surfaces */
        char                *flareShader;                   /* default flare shader (MUST BE SET) */
        qboolean wolfLight;                                 /* when true, lights work like wolf q3map  */
@@ -586,6 +603,7 @@ typedef struct game_s
        qboolean miniMapKeepAspect;                         /* minimap keep aspect ratio by letterboxing */
        miniMapMode_t miniMapMode;                          /* minimap mode */
        char                *miniMapNameFormat;             /* minimap name format */
+       miniMapSidecarFormat_t miniMapSidecarFormat;        /* minimap sidecar format */
        char                *bspIdent;                      /* 4-letter bsp file prefix */
        int bspVersion;                                     /* bsp version to use */
        qboolean lumpSwap;                                  /* cod-style len/ofs order */
@@ -830,7 +848,7 @@ typedef struct face_s
        struct face_s       *next;
        int planenum;
        int priority;
-       //qboolean                      checked;
+       //qboolean checked;
        int compileFlags;
        winding_t           *w;
 }
@@ -1006,7 +1024,7 @@ typedef enum
 }
 surfaceType_t;
 
-char            *surfaceTypes[ NUM_SURFACE_TYPES ]
+Q_EXTERN char *surfaceTypes[ NUM_SURFACE_TYPES ]
 #ifndef MAIN_C
 ;
 #else
@@ -1472,7 +1490,7 @@ typedef struct rawLightmap_s
        float                   *bspLuxels[ MAX_LIGHTMAPS ];
        float                   *radLuxels[ MAX_LIGHTMAPS ];
        float                   *superLuxels[ MAX_LIGHTMAPS ];
-       unsigned char               *superFlags;
+       unsigned char           *superFlags;
        float                   *superOrigins;
        float                   *superNormals;
        int                     *superClusters;
@@ -1820,6 +1838,7 @@ void                        RadFreeLights();
 
 /* light_ydnar.c */
 void                        ColorToBytes( const float *color, byte *colorBytes, float scale );
+void                        ColorToBytesNonZero( const float *color, byte *colorBytes, float scale );
 void                        SmoothNormals( void );
 
 void                        MapRawLightmap( int num );
@@ -1860,7 +1879,7 @@ int                         ImportLightmapsMain( int argc, char **argv );
 
 void                        SetupSurfaceLightmaps( void );
 void                        StitchSurfaceLightmaps( void );
-void                        StoreSurfaceLightmaps( qboolean fastAllocate );
+void                        StoreSurfaceLightmaps( qboolean fastAllocate, qboolean storeForReal );
 
 
 /* exportents.c */
@@ -1917,6 +1936,11 @@ void                        PartialLoadBSPFile( const char *filename );
 void                        WriteBSPFile( const char *filename );
 void                        PrintBSPFileSizes( void );
 
+void                        WriteTexFile( char *name );
+void                        LoadSurfaceFlags( char *filename );
+int                         GetSurfaceParm( const char *tex );
+void                        RestoreSurfaceFlags( char *filename );
+
 epair_t                     *ParseEPair( void );
 void                        ParseEntities( void );
 void                        UnparseEntities( void );
@@ -1952,14 +1976,6 @@ void                        WriteRBSPFile( const char *filename );
 
    ------------------------------------------------------------------------------- */
 
-#ifdef MAIN_C
-       #define Q_EXTERN
-       #define Q_ASSIGN( a )   = a
-#else
-       #define Q_EXTERN extern
-       #define Q_ASSIGN( a )
-#endif
-
 /* game support */
 Q_EXTERN game_t games[]
 #ifndef MAIN_C
@@ -1968,16 +1984,26 @@ Q_EXTERN game_t games[]
        =
        {
                                                                #include "game_quake3.h"
+       ,
+                                                               #include "game_nexuiz.h" /* must be after game_quake3.h as they share defines! */
+       ,
+                                                               #include "game_oa.h" /* must be after game_quake3.h as they share defines! */
+       ,
+                                                               #include "game_q3rally.h" /* must be after game_quake3.h as they share defines! */
        ,
                                                                #include "game_quakelive.h" /* must be after game_quake3.h as they share defines! */
        ,
-                                                               #include "game_nexuiz.h" /* must be after game_quake3.h as they share defines! */
+                                                               #include "game_reaction.h" /* must be after game_quake3.h */
        ,
-                                                               #include "game_xonotic.h" /* must be after game_quake3.h as they share defines! */
+                                                               #include "game_smokinguns.h" /* must be after game_quake3.h */
        ,
                                                                #include "game_tremulous.h" /*LinuxManMikeC: must be after game_quake3.h, depends on #define's set in it */
        ,
                                                                #include "game_unvanquished.h" /* must be after game_tremulous.h as they share defines! */
+       ,
+                                                               #include "game_wop.h" /* must be after game_quake3.h as they share defines! */
+       ,
+                                                               #include "game_xonotic.h" /* must be after game_quake3.h as they share defines! */
        ,
                                                                #include "game_tenebrae.h"
        ,
@@ -1997,11 +2023,13 @@ Q_EXTERN game_t games[]
        ,
                                                                #include "game_qfusion.h"   /* qfusion game */
        ,
-                                                               #include "game_reaction.h" /* must be after game_quake3.h */
+                                                               #include "game_warsow.h" /* must be after game_qfusion.h as they share defines! */
+       ,
+                                                               #include "game_warfork.h" /* must be after game_qfusion.h as they share defines! */
        ,
-                                                               #include "game_darkplaces.h"    /* vortex: darkplaces q1 engine */
+                                                               #include "game_darkplaces.h" /* darkplaces q1 engine */
        ,
-                                                               #include "game_dq.h"    /* vortex: deluxe quake game ( darkplaces q1 engine) */
+                                                               #include "game_dq.h" /* deluxe quake game ( darkplaces q1 engine) */
        ,
                                                                #include "game_prophecy.h"  /* vortex: prophecy game ( darkplaces q1 engine) */
        ,
@@ -2037,7 +2065,6 @@ Q_EXTERN qboolean doingBSP Q_ASSIGN( qfalse );
 
 /* commandline arguments */
 Q_EXTERN qboolean nocmdline Q_ASSIGN( qfalse );
-Q_EXTERN qboolean verbose;
 Q_EXTERN qboolean verboseEntities Q_ASSIGN( qfalse );
 Q_EXTERN qboolean force Q_ASSIGN( qfalse );
 Q_EXTERN qboolean infoMode Q_ASSIGN( qfalse );
@@ -2056,8 +2083,8 @@ Q_EXTERN qboolean nofog Q_ASSIGN( qfalse );
 Q_EXTERN qboolean noHint Q_ASSIGN( qfalse );                        /* ydnar */
 Q_EXTERN qboolean renameModelShaders Q_ASSIGN( qfalse );            /* ydnar */
 Q_EXTERN qboolean skyFixHack Q_ASSIGN( qfalse );                    /* ydnar */
-Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse );                      /* 27 */
-Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse );                   /* div0 */
+Q_EXTERN qboolean bspAlternateSplitWeights Q_ASSIGN( qfalse );      /* 27 */
+Q_EXTERN qboolean deepBSP Q_ASSIGN( qfalse );                       /* div0 */
 Q_EXTERN qboolean maxAreaFaceSurface Q_ASSIGN( qfalse );                    /* divVerent */
 
 Q_EXTERN int patchSubdivisions Q_ASSIGN( 8 );                       /* ydnar: -patchmeta subdivisions */
@@ -2554,7 +2581,7 @@ Q_EXTERN int allocatedBSPBrushSides Q_ASSIGN( 0 );
 Q_EXTERN bspBrushSide_t*    bspBrushSides Q_ASSIGN( NULL );
 
 Q_EXTERN int numBSPLightBytes Q_ASSIGN( 0 );
-Q_EXTERN byte               *bspLightBytes Q_ASSIGN( NULL );
+Q_EXTERN byte *bspLightBytes Q_ASSIGN( NULL );
 
 //%    Q_EXTERN int                            numBSPGridPoints Q_ASSIGN( 0 );
 //%    Q_EXTERN byte                           *bspGridPoints Q_ASSIGN( NULL );
@@ -2566,11 +2593,11 @@ Q_EXTERN int numBSPVisBytes Q_ASSIGN( 0 );
 Q_EXTERN byte bspVisBytes[ MAX_MAP_VISIBILITY ];
 
 Q_EXTERN int numBSPDrawVerts Q_ASSIGN( 0 );
-Q_EXTERN bspDrawVert_t          *bspDrawVerts Q_ASSIGN( NULL );
+Q_EXTERN bspDrawVert_t *bspDrawVerts Q_ASSIGN( NULL );
 
 Q_EXTERN int numBSPDrawIndexes Q_ASSIGN( 0 );
 Q_EXTERN int allocatedBSPDrawIndexes Q_ASSIGN( 0 );
-Q_EXTERN int                *bspDrawIndexes Q_ASSIGN( NULL );
+Q_EXTERN int *bspDrawIndexes Q_ASSIGN( NULL );
 
 Q_EXTERN int numBSPDrawSurfaces Q_ASSIGN( 0 );
 Q_EXTERN bspDrawSurface_t   *bspDrawSurfaces Q_ASSIGN( NULL );
@@ -2581,27 +2608,45 @@ Q_EXTERN bspFog_t bspFogs[ MAX_MAP_FOGS ];
 Q_EXTERN int numBSPAds Q_ASSIGN( 0 );
 Q_EXTERN bspAdvertisement_t bspAds[ MAX_MAP_ADVERTISEMENTS ];
 
-#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) \
+// Used for tex file support, Smokin'Guns globals
+Q_EXTERN qboolean compile_map;
+
+#define _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, fillWithZeros ) \
        do \
        { \
+               int prevAllocated = allocated; \
                if ( reqitem >= allocated )     \
                { \
                        if ( allocated == 0 ) { \
-                               allocated = def; } \
+                               allocated = def; \
+                       } \
                        while ( reqitem >= allocated && allocated )     \
+                       { \
                                allocated *= 2; \
+                       } \
                        if ( !allocated || allocated > 2147483647 / (int)sizeof( *ptr ) ) \
                        { \
-                               Error( # ptr " over 2 GB" ); \
+                               Error( #ptr " over 2 GB" ); \
                        } \
                        ptr = realloc( ptr, sizeof( *ptr ) * allocated ); \
                        if ( !ptr ) { \
-                               Error( # ptr " out of memory" ); } \
+                               Error( #ptr " out of memory" ); \
+                       } \
+                       if ( fillWithZeros ) \
+                       { \
+                               memset( ptr + ( sizeof( *ptr ) * prevAllocated ), 0 , sizeof( *ptr ) * ( allocated - prevAllocated ) ); \
+                       } \
                } \
        } \
        while ( 0 )
 
-#define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp ## suffix, numBSP ## suffix, allocatedBSP ## suffix, def )
+#define AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def ) _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, qfalse )
+
+#define AUTOEXPAND_BY_REALLOC0( ptr, reqitem, allocated, def ) _AUTOEXPAND_BY_REALLOC( ptr, reqitem, allocated, def, qtrue )
+
+#define AUTOEXPAND_BY_REALLOC_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC( bsp##suffix, numBSP##suffix, allocatedBSP##suffix, def )
+
+#define AUTOEXPAND_BY_REALLOC0_BSP( suffix, def ) AUTOEXPAND_BY_REALLOC0( bsp##suffix, numBSP##suffix, allocatedBSP##suffix, def )
 
 #define Image_LinearFloatFromsRGBFloat( c ) ( ( ( c ) <= 0.04045f ) ? ( c ) * ( 1.0f / 12.92f ) : (float)pow( ( ( c ) + 0.055f ) * ( 1.0f / 1.055f ), 2.4f ) )
 #define Image_sRGBFloatFromLinearFloat( c ) ( ( ( c ) < 0.0031308f ) ? ( c ) * 12.92f : 1.055f * (float)pow( ( c ), 1.0f / 2.4f ) - 0.055f )
index bc12037506f726d44a4150ba969b36477a2b36e8..d3db89b124f7478206d0f72a5a0c64219b6e9da9 100644 (file)
@@ -1 +1 @@
-101                     ICON    DISCARDABLE     "q3map2.ico"
+101                     ICON    DISCARDABLE     "..\\..\\..\\icons\\q3map2.ico"
index 10b2b414fcf70181aaec69e0e10a3ead9ad1ddd8..cfa0db86047362e2777b73bf949bf9e1c1c60e2f 100644 (file)
@@ -1276,8 +1276,7 @@ static void ParseShaderFile( const char *filename ){
                        else if ( !Q_stricmp( token, "sun" ) /* sof2 */ || !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) ) {
                                float a, b;
                                sun_t       *sun;
-                               qboolean ext;
-
+                               qboolean ext = qfalse;
 
                                /* ydnar: extended sun directive? */
                                if ( !Q_stricmp( token, "q3map_sunext" ) ) {
@@ -1285,8 +1284,7 @@ static void ParseShaderFile( const char *filename ){
                                }
 
                                /* allocate sun */
-                               sun = safe_malloc( sizeof( *sun ) );
-                               memset( sun, 0, sizeof( *sun ) );
+                               sun = safe_malloc0( sizeof( *sun ) );
 
                                /* set style */
                                sun->style = si->lightStyle;
@@ -1386,8 +1384,7 @@ static void ParseShaderFile( const char *filename ){
                                        surfaceModel_t  *model;
 
                                        /* allocate new model and attach it */
-                                       model = safe_malloc( sizeof( *model ) );
-                                       memset( model, 0, sizeof( *model ) );
+                                       model = safe_malloc0( sizeof( *model ) );
                                        model->next = si->surfaceModel;
                                        si->surfaceModel = model;
 
@@ -1420,8 +1417,7 @@ static void ParseShaderFile( const char *filename ){
 
 
                                        /* allocate new foliage struct and attach it */
-                                       foliage = safe_malloc( sizeof( *foliage ) );
-                                       memset( foliage, 0, sizeof( *foliage ) );
+                                       foliage = safe_malloc0( sizeof( *foliage ) );
                                        foliage->next = si->foliage;
                                        si->foliage = foliage;
 
@@ -1751,8 +1747,7 @@ static void ParseShaderFile( const char *filename ){
                                        alpha = ( !Q_stricmp( token, "q3map_alphaGen" ) || !Q_stricmp( token, "q3map_alphaMod" ) ) ? 1 : 0;
 
                                        /* allocate new colormod */
-                                       cm = safe_malloc( sizeof( *cm ) );
-                                       memset( cm, 0, sizeof( *cm ) );
+                                       cm = safe_malloc0( sizeof( *cm ) );
 
                                        /* attach to shader */
                                        if ( si->colorMod == NULL ) {
index 22e41cc5dbdfd8699b8df4eec1df878950dbb196..77765fe4ed8a63243b9c71f3895f1544c27c8848 100644 (file)
@@ -961,8 +961,7 @@ mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, windin
        ds->sampleSize = b->lightmapSampleSize;
        ds->lightmapScale = b->lightmapScale;
        ds->numVerts = w->numpoints;
-       ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-       memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+       ds->verts = safe_malloc0( ds->numVerts * sizeof( *ds->verts ) );
 
        /* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
        ComputeAxisBase( mapplanes[ s->planenum ].normal, texX, texY );
@@ -3032,8 +3031,7 @@ static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si ){
                        VectorCopy( p->plane.normal, ds->lightmapVecs[ 2 ] );
                        ds->fogNum = -1;
                        ds->numVerts = w->numpoints;
-                       ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-                       memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+                       ds->verts = safe_malloc0( ds->numVerts * sizeof( *ds->verts ) );
 
                        /* walk the winding */
                        for ( i = 0; i < ds->numVerts; i++ )
@@ -3124,11 +3122,9 @@ void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader ){
        ds->shaderInfo = si;
        ds->fogNum = -1;
        ds->numVerts = 8;
-       ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-       memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+       ds->verts = safe_malloc0( ds->numVerts * sizeof( *ds->verts ) );
        ds->numIndexes = 36;
-       ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) );
-       memset( ds->indexes, 0, ds->numIndexes * sizeof( *ds->indexes ) );
+       ds->indexes = safe_malloc0( ds->numIndexes * sizeof( *ds->indexes ) );
 
        /* set verts */
        VectorSet( ds->verts[ 0 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMins[ 2 ] );
index fc3ce0727ed855dae030ab288c54b843d3a7a7e3..263e03bfe19e5cb5741428f40866bc8f1b537b7d 100644 (file)
@@ -301,8 +301,7 @@ void Foliage( mapDrawSurface_t *src ){
                        ds->fogNum = src->fogNum;
 
                        /* add a drawvert for every instance */
-                       verts = safe_malloc( ( ds->numVerts + ds->numFoliageInstances ) * sizeof( *verts ) );
-                       memset( verts, 0, ( ds->numVerts + ds->numFoliageInstances ) * sizeof( *verts ) );
+                       verts = safe_malloc0( ( ds->numVerts + ds->numFoliageInstances ) * sizeof( *verts ) );
                        memcpy( verts, ds->verts, ds->numVerts * sizeof( *verts ) );
                        free( ds->verts );
                        ds->verts = verts;
index 994b3a1920fbc1407ccc651217a5742a791edcfe..e569e070d8c0cd41e77bf5868e3b8af6450aa7e9 100644 (file)
@@ -656,6 +656,7 @@ void FanFaceSurface( mapDrawSurface_t *ds ){
 
        /* add a new vertex at the beginning of the surface */
        verts = safe_malloc( ( ds->numVerts + 1 ) * sizeof( bspDrawVert_t ) );
+       /* beware to only zero the new vertexi at the beginning, nor more! */
        memset( verts, 0, sizeof( bspDrawVert_t ) );
        memcpy( &verts[ 1 ], ds->verts, ds->numVerts * sizeof( bspDrawVert_t ) );
        free( ds->verts );
@@ -1202,13 +1203,11 @@ void SmoothMetaTriangles( void ){
        Sys_FPrintf( SYS_VRB, "--- SmoothMetaTriangles ---\n" );
 
        /* allocate shade angle table */
-       shadeAngles = safe_malloc( numMetaVerts * sizeof( float ) );
-       memset( shadeAngles, 0, numMetaVerts * sizeof( float ) );
+       shadeAngles = safe_malloc0( numMetaVerts * sizeof( float ) );
 
        /* allocate smoothed table */
        cs = ( numMetaVerts / 8 ) + 1;
-       smoothed = safe_malloc( cs );
-       memset( smoothed, 0, cs );
+       smoothed = safe_malloc0( cs );
 
        /* set default shade angle */
        defaultShadeAngle = DEG2RAD( npDegrees );
index c6924dbe63f384880c354cb4901fd345ebac0938..fe180508ee3ee8ab3df9df58d04eb64b0875656b 100644 (file)
@@ -335,6 +335,8 @@ void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
        float start, end, frac, c;
        vec3_t delta;
 
+       // zero the verts array, verts are tested to not be null in FindMetaVertex()
+       memset( verts, 0, sizeof( verts ) );
 
        numVerts = 0;
        for ( i = 0 ; i < ds->numVerts ; i++ )
index df398c3ec5d4fd5b02967d4f62946bffa0b7eeae..5e3bf7efeb64b320f6d31b0be1fde93c94b63c3a 100644 (file)
@@ -66,8 +66,7 @@ fixedWinding_t *NewFixedWinding( int points ){
        }
 
        size = (int)( (size_t)( (fixedWinding_t *)0 )->points[points] );
-       w = safe_malloc( size );
-       memset( w, 0, size );
+       w = safe_malloc0( size );
 
        return w;
 }
@@ -945,11 +944,9 @@ void LoadPortals( char *name ){
        portallongs = portalbytes / sizeof( long );
 
        // each file portal is split into two memory portals
-       portals = safe_malloc( 2 * numportals * sizeof( vportal_t ) );
-       memset( portals, 0, 2 * numportals * sizeof( vportal_t ) );
+       portals = safe_malloc0( 2 * numportals * sizeof( vportal_t ) );
 
-       leafs = safe_malloc( portalclusters * sizeof( leaf_t ) );
-       memset( leafs, 0, portalclusters * sizeof( leaf_t ) );
+       leafs = safe_malloc0( portalclusters * sizeof( leaf_t ) );
 
        for ( i = 0; i < portalclusters; i++ )
                leafs[i].merged = -1;
@@ -1045,11 +1042,9 @@ void LoadPortals( char *name ){
 
        }
 
-       faces = safe_malloc( 2 * numfaces * sizeof( vportal_t ) );
-       memset( faces, 0, 2 * numfaces * sizeof( vportal_t ) );
+       faces = safe_malloc0( 2 * numfaces * sizeof( vportal_t ) );
 
-       faceleafs = safe_malloc( portalclusters * sizeof( leaf_t ) );
-       memset( faceleafs, 0, portalclusters * sizeof( leaf_t ) );
+       faceleafs = safe_malloc0( portalclusters * sizeof( leaf_t ) );
 
        for ( i = 0, p = faces; i < numfaces; i++ )
        {
@@ -1151,7 +1146,7 @@ int VisMain( int argc, char **argv ){
                }
                else if ( !strcmp( argv[ i ], "-v" ) ) {
                        debugCluster = qtrue;
-                       Sys_Printf( "Extra verbous mode enabled\n" );
+                       Sys_Printf( "Extra verbose mode enabled\n" );
                }
                else if ( !strcmp( argv[i],"-tmpin" ) ) {
                        strcpy( inbase, "/tmp" );
@@ -1169,7 +1164,9 @@ int VisMain( int argc, char **argv ){
                else if ( !strcmp( argv[ i ], "-prtfile" ) )
                {
                        strcpy( portalFilePath, argv[i + 1] );
+                       argv[ i ] = NULL;
                        i++;
+                       argv[ i ] = NULL;
                        Sys_Printf( "Use %s as portal file\n", portalFilePath );
                }
 
@@ -1190,6 +1187,16 @@ int VisMain( int argc, char **argv ){
        Sys_Printf( "Loading %s\n", source );
        LoadBSPFile( source );
 
+       if ( game->texFile )
+       {
+               // smokinguns-like tex file
+               StripExtension( source );
+               strcat( source, ".tex" );
+               LoadSurfaceFlags( source );
+               StripExtension( source );
+               strcat( source, ".bsp" );
+       }
+
        /* load the portal file */
        if (!portalFilePath[0]) {
                sprintf( portalFilePath, "%s%s", inbase, ExpandArg( argv[ i ] ) );
@@ -1232,6 +1239,14 @@ int VisMain( int argc, char **argv ){
                remove( portalFilePath );
        }
 
+       if ( game->texFile )
+       {
+               // smokinguns-like tex file
+               StripExtension( source );
+               WriteTexFile( source );
+               DefaultExtension( source, ".bsp" );
+       }
+
        /* write the bsp file */
        Sys_Printf( "Writing %s\n", source );
        WriteBSPFile( source );
index 0247691f9f046d44dd910f78eb00f0f4dfa3e7e5..adc0676110c942e492a094d17d6ddc5592d5bc36 100644 (file)
@@ -72,8 +72,6 @@ int CountBits( byte *bits, int numbits ){
 }
 
 int c_fullskip;
-int c_portalskip, c_leafskip;
-int c_vistest, c_mighttest;
 
 int c_chop, c_nochop;
 
@@ -1364,8 +1362,7 @@ void CreatePassages( int portalnum ){
                        continue;
                }
 
-               passage = (passage_t *) safe_malloc( sizeof( passage_t ) + portalbytes );
-               memset( passage, 0, sizeof( passage_t ) + portalbytes );
+               passage = (passage_t *) safe_malloc0( sizeof( passage_t ) + portalbytes );
                numseperators = AddSeperators( portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS * 2 );
                numseperators += AddSeperators( target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS * 2 - numseperators );
 
@@ -1585,14 +1582,11 @@ void BasePortalVis( int portalnum ){
                return;
        }
 
-       p->portalfront = safe_malloc( portalbytes );
-       memset( p->portalfront, 0, portalbytes );
+       p->portalfront = safe_malloc0( portalbytes );
 
-       p->portalflood = safe_malloc( portalbytes );
-       memset( p->portalflood, 0, portalbytes );
+       p->portalflood = safe_malloc0( portalbytes );
 
-       p->portalvis = safe_malloc( portalbytes );
-       memset( p->portalvis, 0, portalbytes );
+       p->portalvis = safe_malloc0( portalbytes );
 
        for ( j = 0, tp = portals ; j < numportals * 2 ; j++, tp++ )
        {
index c3262a04fb2129994f944f3209126923edec0fdf..3e043a40f192e47da6911d31743276cc633e6474 100644 (file)
 
 
 
+//prefixInfo-stats
+typedef struct {
+       char    *name;
+       int             surfaceFlags;
+} prefixInfo_t;
+
+static prefixInfo_t prefixInfo[] = {
+       { "metal",      TEX_SURF_METAL},
+       { "wood",       TEX_SURF_WOOD},
+       { "cloth",      TEX_SURF_CLOTH},
+       { "dirt",       TEX_SURF_DIRT},
+       { "glass",      TEX_SURF_GLASS},
+       { "plant",      TEX_SURF_PLANT},
+       { "sand",       TEX_SURF_SAND},
+       { "snow",       TEX_SURF_SNOW},
+       { "stone",      TEX_SURF_STONE},
+       { "water",      TEX_SURF_WATER},
+       { "grass",      TEX_SURF_GRASS},
+};
+
+#define NUM_PREFIXINFO 11 /* very important */
+
+//Added by Spoon to recognize surfaceparms by shadernames
+int GetSurfaceParm(const char *tex){
+       char surf[MAX_QPATH], tex2[MAX_QPATH];
+       int     i, j = 0;
+
+       strcpy(tex2, tex);
+
+       /* find last dir */
+       for(i = 0; i < 64 && tex2[i] != '\0'; i++){
+               if(tex2[i] == '\\' || tex2[i] == '/')
+                       j=i+1;
+       }
+
+       strcpy(surf, tex2+j);
+
+       for(i=0; i<10; i++){
+               if(surf[i] == '_')
+                       break;
+       }
+       surf[i] = '\0';
+
+       /* Sys_Printf("%s\n", surf); */
+
+       for(i=0; i < NUM_PREFIXINFO; i++){
+               if(!Q_stricmp(surf, prefixInfo[i].name)){
+                       return prefixInfo[i].surfaceFlags;
+               }
+       }
+       return 0;
+}
+
+
+
 /*
    EmitShader()
    emits a bsp shader entry
@@ -56,13 +111,17 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
        /* try to find an existing shader */
        for ( i = 0; i < numBSPShaders; i++ )
        {
-                       /* ydnar: handle custom surface/content flags */
+               /* if not Smokin'Guns like tex file */
+               if ( !game->texFile )
+               {
+               /* ydnar: handle custom surface/content flags */
                if ( surfaceFlags != NULL && bspShaders[ i ].surfaceFlags != *surfaceFlags ) {
                        continue;
                }
                if ( contentFlags != NULL && bspShaders[ i ].contentFlags != *contentFlags ) {
                        continue;
                }
+               }
                if ( !doingBSP ){
                        si = ShaderInfoForShader( shader );
                        if ( si->remapShader && si->remapShader[ 0 ] ) {
@@ -79,13 +138,23 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
        si = ShaderInfoForShader( shader );
 
        /* emit a new shader */
-       AUTOEXPAND_BY_REALLOC_BSP( Shaders, 1024 );
+       AUTOEXPAND_BY_REALLOC0_BSP( Shaders, 1024 );
 
        numBSPShaders++;
        strcpy( bspShaders[ i ].shader, shader );
        bspShaders[ i ].surfaceFlags = si->surfaceFlags;
+
+       if ( game->texFile )
+       {
+               /* Smokin'Guns like tex file */
+               bspShaders[ i ].surfaceFlags |= GetSurfaceParm(si->shader);
+       }
+
        bspShaders[ i ].contentFlags = si->contentFlags;
 
+       /* if not Smokin'Guns like tex file */
+       if ( !game->texFile )
+       {
        /* handle custom content/surface flags */
        if ( surfaceFlags != NULL ) {
                bspShaders[ i ].surfaceFlags = *surfaceFlags;
@@ -93,6 +162,7 @@ int EmitShader( const char *shader, int *contentFlags, int *surfaceFlags ){
        if ( contentFlags != NULL ) {
                bspShaders[ i ].contentFlags = *contentFlags;
        }
+       }
 
        /* recursively emit any damage shaders */
        if ( si->damageShader != NULL && si->damageShader[ 0 ] != '\0' ) {
@@ -400,6 +470,79 @@ void BeginBSPFile( void ){
 
 
 
+/*
+   RestoreSurfaceFlags()
+   read Smokin'Guns like tex file
+   added by spoon to get back the changed surfaceflags
+ */
+
+void RestoreSurfaceFlags( char *filename ) {
+       int i;
+       FILE *texfile;
+       int surfaceFlags[ MAX_MAP_DRAW_SURFS ];
+       int numTexInfos;
+
+       /* first parse the tex file */
+       texfile = fopen( filename, "r" );
+
+       if ( texfile ) {
+               fscanf( texfile, "TEXFILE\n%i\n", &numTexInfos );
+
+               /* Sys_Printf( "%i\n", numTexInfos ); */
+
+               for ( i = 0; i < numTexInfos; i++ ) {
+                       vec3_t color;
+
+                       fscanf( texfile, "%i %f %f %f\n", &surfaceFlags[ i ],
+                               &color[ 0 ], &color[ 1 ], &color[ 2 ]);
+
+                       bspShaders[ i ].surfaceFlags = surfaceFlags[ i ];
+
+                       /* Sys_Printf( "%i\n", surfaceFlags[ i ] ); */
+               }
+       } else {
+               Sys_Printf("couldn't find %s not tex-file is now writed without surfaceFlags!\n", filename);
+       }
+}
+
+
+
+/*
+   WriteTexFile()
+   write Smokin'Guns like tex file
+   added by spoon
+ */
+
+void WriteTexFile( char* filename ) {
+       FILE *texfile;
+       int i;
+
+       if ( !compile_map ) {
+               RestoreSurfaceFlags( filename );
+       }
+
+       Sys_Printf( "Writing %s ...\n", filename );
+
+       texfile = fopen ( filename, "w" );
+
+       fprintf( texfile, "TEXFILE\n" );
+
+       fprintf( texfile, "%i\n", numBSPShaders );
+
+       for ( i = 0 ; i < numBSPShaders ; i++ ) {
+               shaderInfo_t *se = ShaderInfoForShader( bspShaders[ i ].shader );
+
+               fprintf( texfile, "\n%i %f %f %f", bspShaders[ i ].surfaceFlags,
+                       se->color[ 0 ], se->color[ 1 ], se->color[ 2 ] );
+
+               bspShaders[ i ].surfaceFlags = i;
+       }
+
+       fclose( texfile );
+}
+
+
+
 /*
    EndBSPFile()
    finishes a new bsp and writes to disk
@@ -418,6 +561,18 @@ void EndBSPFile( qboolean do_write, const char *BSPFilePath, const char *surface
                /* write the surface extra file */
                WriteSurfaceExtraFile( surfaceFilePath );
 
+               if ( game->texFile )
+               {
+                       char basename[ 1024 ];  
+                       char filename[ 1024 ];
+                       strncpy( basename, BSPFilePath, sizeof(basename) );
+                       StripExtension( basename );
+                       sprintf( filename, "%s.tex", basename );
+
+                       /* only create tex file if it is the first compile */
+                       WriteTexFile( filename );
+               }
+
                /* write the bsp */
                Sys_Printf( "Writing %s\n", BSPFilePath );
                WriteBSPFile( BSPFilePath );
diff --git a/tools/unvanquished/CMakeLists.txt b/tools/unvanquished/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ed9ed82
--- /dev/null
@@ -0,0 +1,9 @@
+if (BUILD_DAEMONMAP)
+    # Always keep daemonmap libs/
+    # up-to-date with NetRadiant libs/
+    include_directories(daemonmap/libs)
+    include_directories(daemonmap/tools)
+
+    add_subdirectory(daemonmap/libs)
+    add_subdirectory(daemonmap/tools)
+endif()
diff --git a/tools/unvanquished/daemonmap b/tools/unvanquished/daemonmap
new file mode 160000 (submodule)
index 0000000..18be9d8
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 18be9d84e42c21da6876f7dffa1d25f28e383360
diff --git a/uncrustify.cfg b/uncrustify.cfg
deleted file mode 100644 (file)
index 4951686..0000000
+++ /dev/null
@@ -1,925 +0,0 @@
-# Uncrustify 0.44
-
-#
-# General options
-#
-
-# The type of line endings
-newlines                                 = lf       # auto/lf/crlf/cr
-
-# The original size of tabs in the input
-input_tab_size                           = 4        # number
-
-# The size of tabs in the output (only used if align_with_tabs=true)
-output_tab_size                          = 4        # number
-
-# The ascii value of the string escape char, usually 92 (\) or 94 (^). (Pawn)
-string_escape_char                       = 92       # number
-
-# Alternate string escape char for Pawn. Only works right before the quote char.
-string_escape_char2                      = 0        # number
-
-#
-# Indenting
-#
-
-# The number of columns to indent per level.
-# Usually 2, 3, 4, or 8.
-indent_columns                           = 4        # number
-
-# How to use tabs when indenting code
-# 0=spaces only
-# 1=indent with tabs, align with spaces
-# 2=indent and align with tabs
-indent_with_tabs                         = 2        # number
-
-# Whether to indent strings broken by '\' so that they line up
-indent_align_string                      = true    # false/true
-
-# The number of spaces to indent multi-line XML strings.
-# Requires indent_align_string=True
-indent_xml_string                        = 0        # number
-
-# Spaces to indent '{' from level
-indent_brace                             = 0        # number
-
-# Whether braces are indented to the body level
-indent_braces                            = false    # false/true
-
-# Disabled indenting function braces if indent_braces is true
-indent_braces_no_func                    = false    # false/true
-
-# Indent based on the size of the brace parent, ie 'if' => 3 spaces, 'for' => 4 spaces, etc.
-indent_brace_parent                      = false    # false/true
-
-# Whether the 'namespace' body is indented
-indent_namespace                         = false    # false/true
-
-# Whether the 'class' body is indented
-indent_class                             = false    # false/true
-
-# Whether to indent the stuff after a leading class colon
-indent_class_colon                       = false    # false/true
-
-# True:  indent continued function call parameters one indent level
-# False: align parameters under the open paren
-indent_func_call_param                   = false    # false/true
-
-# Same as indent_func_call_param, but for function defs
-indent_func_def_param                    = false    # false/true
-
-# Same as indent_func_call_param, but for function protos
-indent_func_proto_param                  = false    # false/true
-
-# Same as indent_func_call_param, but for class declarations
-indent_func_class_param                  = false    # false/true
-
-# Same as indent_func_call_param, but for class variable constructors
-indent_func_ctor_var_param               = false    # false/true
-
-# Double the indent for indent_func_xxx_param options
-indent_func_param_double                 = false    # false/true
-
-# The number of spaces to indent a continued '->' or '.'
-# Usually set to 0, 1, or indent_columns.
-indent_member                            = 0        # number
-
-# Spaces to indent single line ('//') comments on lines before code
-indent_sing_line_comments                = 0        # number
-
-# Spaces to indent 'case' from 'switch'
-# Usually 0 or indent_columns.
-indent_switch_case                       = 0        # number
-
-# Spaces to shift the 'case' line, without affecting any other lines
-# Usually 0.
-indent_case_shift                        = 0        # number
-
-# Spaces to indent '{' from 'case'.
-# By default, the brace will appear under the 'c' in case.
-# Usually set to 0 or indent_columns.
-indent_case_brace                        = 0        # number
-
-# Whether to indent comments found in first column
-indent_col1_comment                      = false    # false/true
-
-# How to indent goto labels
-#  >0 : absolute column where 1 is the leftmost column
-#  <=0 : subtract from brace indent
-indent_label                             = 1        # number
-
-# Same as indent_label, but for access specifiers that are followed by a colon
-indent_access_spec                       = 1        # number
-
-# If an open paren is followed by a newline, indent the next line so that it lines up after the open paren (not recommended)
-indent_paren_nl                          = false    # false/true
-
-# Controls the indent of a close paren after a newline.
-# 0: Indent to body level
-# 1: Align under the open paren
-# 2: Indent to the brace level
-indent_paren_close                       = 0        # number
-
-# Controls the indent of a comma when inside a paren.If TRUE, aligns under the open paren
-indent_comma_paren                       = false    # false/true
-
-# Controls the indent of a BOOL operator when inside a paren.If TRUE, aligns under the open paren
-indent_bool_paren                        = false    # false/true
-
-# If an open square is followed by a newline, indent the next line so that it lines up after the open square (not recommended)
-indent_square_nl                         = false    # false/true
-
-# Don't change the relative indent of ESQL/C 'EXEC SQL' bodies
-indent_preserve_sql                      = false    # false/true
-
-#
-# Spacing options
-#
-
-# Add or remove space around arithmetic operator '+', '-', '/', '*', etc
-sp_arith                                 = add     # ignore/add/remove/force
-
-# Add or remove space around assignment operator '=', '+=', etc
-sp_assign                                = add     # ignore/add/remove/force
-
-# Add or remove space around boolean operators '&&' and '||'
-sp_bool                                  = add         # ignore/add/remove/force
-
-# Add or remove space around compare operator '<', '>', '==', etc
-sp_compare                               = add     # ignore/add/remove/force
-
-# Add or remove space inside '(' and ')'
-sp_inside_paren                          = add         # ignore/add/remove/force
-
-# Add or remove space between nested parens
-sp_paren_paren                           = add      # ignore/add/remove/force
-
-# Whether to balance spaces inside nested parens
-sp_balance_nested_parens                 = false    # false/true
-
-# Add or remove space between ')' and '{'
-sp_paren_brace                           = add         # ignore/add/remove/force
-
-# Add or remove space before pointer star '*'
-sp_before_ptr_star                       = ignore   # ignore/add/remove/force
-
-# Add or remove space between pointer stars '*'
-sp_between_ptr_star                      = ignore   # ignore/add/remove/force
-
-# Add or remove space after pointer star '*', if followed by a word.
-sp_after_ptr_star                        = ignore   # ignore/add/remove/force
-
-# Add or remove space before reference sign '&'
-sp_before_byref                          = ignore   # ignore/add/remove/force
-
-# Add or remove space after reference sign '&', if followed by a word.
-sp_after_byref                           = ignore   # ignore/add/remove/force
-
-# Add or remove space before '<>'
-sp_before_angle                          = ignore   # ignore/add/remove/force
-
-# Add or remove space after '<>'
-sp_after_angle                           = ignore   # ignore/add/remove/force
-
-# Add or remove space between '<>' and '(' as found in 'new List<byte>();'
-sp_angle_paren                           = ignore   # ignore/add/remove/force
-
-# Add or remove space between '<>' and a word as in 'List<byte> m;'
-sp_angle_word                            = ignore   # ignore/add/remove/force
-
-# Add or remove space before '(' of 'if', 'for', 'switch', and 'while'
-sp_before_sparen                         = add   # ignore/add/remove/force
-
-# Add or remove space inside if-condition '(' and ')'
-sp_inside_sparen                         = add   # ignore/add/remove/force
-
-# Add or remove space after ')' of 'if', 'for', 'switch', and 'while'
-sp_after_sparen                          = ignore   # ignore/add/remove/force
-
-# Add or remove space between ')' and '{' of 'if', 'for', 'switch', and 'while'
-sp_sparen_brace                          = add   # ignore/add/remove/force
-
-# Add or remove space before empty statement ';' on 'if', 'for' and 'while'
-sp_special_semi                          = ignore   # ignore/add/remove/force
-
-# Add or remove space before ';'
-sp_before_semi                           = ignore   # ignore/add/remove/force
-
-# Add or remove space before ';' in non-empty 'for' statements
-sp_before_semi_for                       = ignore   # ignore/add/remove/force
-
-# Add or remove space before a semicolon of an empty part of a for statment.
-sp_before_semi_for_empty                 = ignore   # ignore/add/remove/force
-
-# Add or remove space after the final semicolon of an empty part of a for statment: for ( ; ; <here> ).
-sp_after_semi_for_empty                  = ignore   # ignore/add/remove/force
-
-# Add or remove space before '[' (except '[]')
-sp_before_square                         = ignore   # ignore/add/remove/force
-
-# Add or remove space before '[]'
-sp_before_squares                        = ignore   # ignore/add/remove/force
-
-# Add or remove space inside '[' and ']'
-sp_inside_square                         = ignore   # ignore/add/remove/force
-
-# Add or remove space after ','
-sp_after_comma                           = ignore   # ignore/add/remove/force
-
-# Add or remove space before ','
-sp_before_comma                          = remove   # ignore/add/remove/force
-
-# Add or remove space between 'operator' and operator sign
-sp_after_operator                        = ignore   # ignore/add/remove/force
-
-# Add or remove space after cast
-sp_after_cast                            = ignore   # ignore/add/remove/force
-
-# Add or remove spaces inside cast parens
-sp_inside_paren_cast                     = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'sizeof' and '('
-sp_sizeof_paren                          = remove   # ignore/add/remove/force
-
-# Add or remove space after the tag keyword (Pawn)
-sp_after_tag                             = ignore   # ignore/add/remove/force
-
-# Add or remove space inside enum '{' and '}'
-sp_inside_braces_enum                    = ignore   # ignore/add/remove/force
-
-# Add or remove space inside struct/union '{' and '}'
-sp_inside_braces_struct                  = ignore   # ignore/add/remove/force
-
-# Add or remove space inside '{' and '}'
-sp_inside_braces                         = ignore   # ignore/add/remove/force
-
-# Add or remove space inside '<' and '>'
-sp_inside_angle                          = ignore   # ignore/add/remove/force
-
-# Add or remove space between return type and function name
-# A minimum of 1 is forced except for pointer return types.
-sp_type_func                             = ignore   # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function declaration
-sp_func_proto_paren                      = remove   # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function definition
-sp_func_def_paren                        = remove   # ignore/add/remove/force
-
-# Add or remove space inside empty function '()'
-sp_inside_fparens                        = remove   # ignore/add/remove/force
-
-# Add or remove space inside function '(' and ')'
-sp_inside_fparen                         = add         # ignore/add/remove/force
-
-# Add or remove space between ']' and '(' when part of a function call.
-sp_square_fparen                         = ignore   # ignore/add/remove/force
-
-# Add or remove space between ')' and '{' of function
-sp_fparen_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove space between function name and '(' on function calls
-sp_func_call_paren                       = remove   # ignore/add/remove/force
-
-# Add or remove space between a constructor/destructor and the open paren
-sp_func_class_paren                      = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'return' and '('
-sp_return_paren                          = ignore   # ignore/add/remove/force
-
-# Add or remove space between '__attribute__' and '('
-sp_attribute_paren                       = ignore   # ignore/add/remove/force
-
-# Add or remove space between macro and value
-sp_macro                                 = ignore   # ignore/add/remove/force
-
-# Add or remove space between macro function ')' and value
-sp_macro_func                            = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'else' and '{' if on the same line
-sp_else_brace                            = ignore   # ignore/add/remove/force
-
-# Add or remove space between '}' and 'else' if on the same line
-sp_brace_else                            = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'catch' and '{' if on the same line
-sp_catch_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove space between '}' and 'catch' if on the same line
-sp_brace_catch                           = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'finally' and '{' if on the same line
-sp_finally_brace                         = ignore   # ignore/add/remove/force
-
-# Add or remove space between '}' and 'finally' if on the same line
-sp_brace_finally                         = ignore   # ignore/add/remove/force
-
-# Add or remove space between 'try' and '{' if on the same line
-sp_try_brace                             = ignore   # ignore/add/remove/force
-
-# Add or remove space between get/set and '{' if on the same line
-sp_getset_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove space before the '::' operator
-sp_before_dc                             = ignore   # ignore/add/remove/force
-
-# Add or remove space after the '::' operator
-sp_after_dc                              = ignore   # ignore/add/remove/force
-
-# Add or remove around the D named array initializer ':' operator
-sp_d_array_colon                         = ignore   # ignore/add/remove/force
-
-# Add or remove space after the '!' (not) operator.
-sp_not                                   = remove   # ignore/add/remove/force
-
-# Add or remove space after the '~' (invert) operator.
-sp_inv                                   = remove   # ignore/add/remove/force
-
-# Add or remove space after the '&' (address-of) operator.
-# This does not affect the spacing after a '&' that is part of a type.
-sp_addr                                  = remove   # ignore/add/remove/force
-
-# Add or remove space around the '.' or '->' operators
-sp_member                                = remove   # ignore/add/remove/force
-
-# Add or remove space after the '*' (dereference) operator.
-# This does not affect the spacing after a '*' that is part of a type.
-sp_deref                                 = remove   # ignore/add/remove/force
-
-# Add or remove space after '+' or '-', as in 'x = -5' or 'y = +7'
-sp_sign                                  = remove   # ignore/add/remove/force
-
-# Add or remove space before or after '++' and '--', as in '(--x)' or 'y++;'
-sp_incdec                                = remove   # ignore/add/remove/force
-
-# Add or remove space after the scope '+' or '-', as in '-(void) foo;' or '+(int) bar;'
-sp_after_oc_scope                        = ignore   # ignore/add/remove/force
-
-# Add or remove space after the colon in message specs
-# '-(int) f: (int) x;' vs '+(int) f : (int) x;'
-sp_before_oc_colon                       = ignore   # ignore/add/remove/force
-
-# Add or remove space after the (type) in message specs
-# '-(int) f: (int) x;' vs '+(int)f : (int)x;'
-sp_after_oc_type                         = ignore   # ignore/add/remove/force
-
-#
-# Code alignment (not left column spaces/tabs)
-#
-
-# Whether to keep non-indenting tabs
-align_keep_tabs                          = false    # false/true
-
-# Whether to use tabs for alinging
-align_with_tabs                          = true            # false/true
-
-# Whether to bump out to the next tab when aligning
-align_on_tabstop                         = false    # false/true
-
-# Whether to left-align numbers
-align_number_left                        = false    # false/true
-
-# Align variable definitions in prototypes and functions
-align_func_params                        = false    # false/true
-
-# The span for aligning variable definitions (0=don't align)
-align_var_def_span                       = 0        # number
-
-# How to align the star in variable definitions.
-#  0=Part of the type
-#  1=Part of the variable
-#  2=Dangling
-align_var_def_star_style                 = 0        # number
-
-# How to align the '&' in variable definitions.
-#  0=Part of the type
-#  1=Part of the variable
-#  2=Dangling
-align_var_def_amp_style                  = 0        # number
-
-# The threshold for aligning variable definitions (0=no limit)
-align_var_def_thresh                     = 0        # number
-
-# Whether to align the colon in struct bit fields
-align_var_def_colon                      = false    # false/true
-
-# Whether to align inline struct/enum/union variable definitions
-align_var_def_inline                     = false    # false/true
-
-# The span for aligning on '=' in assignments (0=don't align)
-align_assign_span                        = 0        # number
-
-# The threshold for aligning on '=' in assignments (0=no limit)
-align_assign_thresh                      = 0        # number
-
-# The span for aligning on '=' in enums (0=don't align)
-align_enum_equ_span                      = 0        # number
-
-# The threshold for aligning on '=' in enums (0=no limit)
-align_enum_equ_thresh                    = 0        # number
-
-# The span for aligning struct/union (0=don't align)
-align_var_struct_span                    = 0        # number
-
-# The threshold for aligning struct/union member definitions (0=no limit)
-align_var_struct_thresh                  = 0        # number
-
-# The span for aligning struct initializer values (0=don't align)
-align_struct_init_span                   = 0        # number
-
-# The minimum space between the type and the synonym of a typedef
-align_typedef_gap                        = 0        # number
-
-# The span for aligning single-line typedefs (0=don't align)
-align_typedef_span                       = 0        # number
-
-# How to align typedef'd functions with other typedefs
-# 0: Don't mix them at all
-# 1: align the open paren with the types
-# 2: align the function type name with the other type names
-align_typedef_func                       = 0        # number
-
-# Controls the positioning of the '*' in typedefs. Just try it.
-# 0: Align on typdef type, ignore '*'
-# 1: The '*' is part of type name: typedef int  *pint;
-# 2: The '*' is part of the type, but dangling: typedef int *pint;
-align_typedef_star_style                 = 0        # number
-
-# Controls the positioning of the '&' in typedefs. Just try it.
-# 0: Align on typdef type, ignore '&'
-# 1: The '&' is part of type name: typedef int  &pint;
-# 2: The '&' is part of the type, but dangling: typedef int &pint;
-align_typedef_amp_style                  = 0        # number
-
-# The span for aligning comments that end lines (0=don't align)
-align_right_cmt_span                     = 0        # number
-
-# If aligning comments, mix with comments after '}' and #endif with less than 3 spaces before the comment
-align_right_cmt_mix                      = false    # false/true
-
-# The span for aligning function prototypes (0=don't align)
-align_func_proto_span                    = 0        # number
-
-# The span for aligning function prototypes (0=don't align)
-align_oc_msg_spec_span                   = 0        # number
-
-# Whether to align macros wrapped with a backslash and a newline.
-# This will not work right if the macro contains a multi-line comment.
-align_nl_cont                            = false    # false/true
-
-# The minimum space between label and value of a preprocessor define
-align_pp_define_gap                      = 0        # number
-
-# The span for aligning on '#define' bodies (0=don't align)
-align_pp_define_span                     = 0        # number
-
-#
-# Newline adding and removing options
-#
-
-# Whether to collapse empty blocks between '{' and '}'
-nl_collapse_empty_body                   = false    # false/true
-
-# Don't split one-line braced assignments - 'foo_t f = { 1, 2 };'
-nl_assign_leave_one_liners               = true    # false/true
-
-# Don't split one-line braced statements inside a class xx { } body
-nl_class_leave_one_liners                = false    # false/true
-
-# Don't split one-line enums: 'enum foo { BAR = 15 };'
-nl_enum_leave_one_liners                 = true    # false/true
-
-# Don't split one-line get or set functions
-nl_getset_leave_one_liners               = true    # false/true
-
-# Don't split one-line function definitions - 'int foo() { return 0; }'
-nl_func_leave_one_liners                 = true    # false/true
-
-# Don't split one-line if/else statements - 'if(a) b++;'
-nl_if_leave_one_liners                   = false    # false/true
-
-# Add or remove newlines at the start of the file
-nl_start_of_file                         = ignore   # ignore/add/remove/force
-
-# The number of newlines at the start of the file (only used if nl_start_of_file is 'add' or 'force'
-nl_start_of_file_min                     = 0        # number
-
-# Add or remove newline at the end of the file
-nl_end_of_file                           = add   # ignore/add/remove/force
-
-# The number of newlines at the end of the file (only used if nl_end_of_file is 'add' or 'force')
-nl_end_of_file_min                       = 0        # number
-
-# Add or remove newline between '=' and '{'
-nl_assign_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline between '=' and '[' (D only)
-nl_assign_square                         = ignore   # ignore/add/remove/force
-
-# Add or remove newline after '= [' (D only). Will also affect the newline before the ']'
-nl_after_square_assign                   = ignore   # ignore/add/remove/force
-
-# The number of newlines after a block of variable definitions
-nl_func_var_def_blk                      = 0        # number
-
-# Add or remove newline between a function call's ')' and '{', as in:
-# list_for_each(item, &list) { }
-nl_fcall_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'enum' and '{'
-nl_enum_brace                            = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'struct and '{'
-nl_struct_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'union' and '{'
-nl_union_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'if' and '{'
-nl_if_brace                              = remove   # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'else'
-nl_brace_else                            = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'else if' and '{'
-# If set to ignore, nl_if_brace is used instead
-nl_elseif_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'else' and '{'
-nl_else_brace                            = ignore   # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'finally'
-nl_brace_finally                         = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'finally' and '{'
-nl_finally_brace                         = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'try' and '{'
-nl_try_brace                             = ignore   # ignore/add/remove/force
-
-# Add or remove newline between get/set and '{'
-nl_getset_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'for' and '{'
-nl_for_brace                             = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'catch' and '{'
-nl_catch_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'catch'
-nl_brace_catch                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'while' and '{'
-nl_while_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'do' and '{'
-nl_do_brace                              = ignore   # ignore/add/remove/force
-
-# Add or remove newline between '}' and 'while' of 'do' statement
-nl_brace_while                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'switch' and '{'
-nl_switch_brace                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline when condition spans two or more lines
-nl_multi_line_cond                       = false    # false/true
-
-# Force a newline in a define after the macro name for multi-line defines.
-nl_multi_line_define                     = false    # false/true
-
-# Whether to put a newline before 'case' statement
-nl_before_case                           = false    # false/true
-
-# Whether to put a newline after 'case' statement
-nl_after_case                            = false    # false/true
-
-# Newline between namespace and {
-nl_namespace_brace                       = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'template<>' and 'class'
-nl_template_class                        = ignore   # ignore/add/remove/force
-
-# Add or remove newline between 'class' and '{'
-nl_class_brace                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline after each ',' in the constructor member initialization
-nl_class_init_args                       = ignore   # ignore/add/remove/force
-
-# Add or remove newline between return type and function name in definition
-nl_func_type_name                        = ignore   # ignore/add/remove/force
-
-# Add or remove newline between return type and function name in a prototype
-nl_func_proto_type_name                  = ignore   # ignore/add/remove/force
-
-# Add or remove newline between a function name and the opening '('
-nl_func_paren                            = ignore   # ignore/add/remove/force
-
-# Add or remove newline after '(' in a function declaration
-nl_func_decl_start                       = ignore   # ignore/add/remove/force
-
-# Add or remove newline after each ',' in a function declaration
-nl_func_decl_args                        = ignore   # ignore/add/remove/force
-
-# Add or remove newline before the ')' in a function declaration
-nl_func_decl_end                         = ignore   # ignore/add/remove/force
-
-# Add or remove newline between function signature and '{'
-nl_fdef_brace                            = remove   # ignore/add/remove/force
-
-# Whether to put a newline after 'return' statement
-nl_after_return                          = false    # false/true
-
-# Whether to put a newline after semicolons, except in 'for' statements
-nl_after_semicolon                       = false    # false/true
-
-# Whether to put a newline after brace open.
-# This also adds a newline before the matching brace close.
-nl_after_brace_open                      = false    # false/true
-
-# If nl_after_brace_open and nl_after_brace_open_cmt are true, a newline is
-# placed between the open brace and a trailing single-line comment.
-nl_after_brace_open_cmt                  = false    # false/true
-
-# Whether to put a newline after a virtual brace open.
-# These occur in un-braced if/while/do/for statement bodies.
-nl_after_vbrace_open                     = false    # false/true
-
-# Whether to alter newlines in '#define' macros
-nl_define_macro                          = false    # false/true
-
-# Whether to not put blanks after '#ifxx', '#elxx', or before '#endif'
-nl_squeeze_ifdef                         = false    # false/true
-
-# Add or remove newline before 'if'
-nl_before_if                             = ignore   # ignore/add/remove/force
-
-# Add or remove newline after 'if'
-nl_after_if                              = ignore   # ignore/add/remove/force
-
-# Add or remove newline before 'for'
-nl_before_for                            = ignore   # ignore/add/remove/force
-
-# Add or remove newline after 'for'
-nl_after_for                             = ignore   # ignore/add/remove/force
-
-# Add or remove newline before 'while'
-nl_before_while                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline after 'while'
-nl_after_while                           = ignore   # ignore/add/remove/force
-
-# Add or remove newline before 'switch'
-nl_before_switch                         = ignore   # ignore/add/remove/force
-
-# Add or remove newline after 'switch'
-nl_after_switch                          = ignore   # ignore/add/remove/force
-
-# Add or remove newline before 'do'
-nl_before_do                             = ignore   # ignore/add/remove/force
-
-# Add or remove newline after 'do'
-nl_after_do                              = ignore   # ignore/add/remove/force
-
-# Whether to double-space commented-entries in struct/enum
-nl_ds_struct_enum_cmt                    = false    # false/true
-
-# Whether to double-space before the close brace of a struct/union/enum
-nl_ds_struct_enum_close_brace            = false    # false/true
-
-# Add or remove a newline around a class colon.
-# Related to pos_class_colon, nl_class_init_args, and pos_comma.
-nl_class_colon                           = ignore   # ignore/add/remove/force
-
-# Change simple unbraced if statements into a one-liner
-# 'if(b)\n i++;' => 'if(b) i++;'
-nl_create_if_one_liner                   = true    # false/true
-
-# Change simple unbraced for statements into a one-liner
-# 'for (i=0;i<5;i++)\n foo(i);' => 'for (i=0;i<5;i++) foo(i);'
-nl_create_for_one_liner                  = false    # false/true
-
-# Change simple unbraced while statements into a one-liner
-# 'while (i<5)\n foo(i++);' => 'while (i<5) foo(i++);'
-nl_create_while_one_liner                = false    # false/true
-
-#
-# Positioning options
-#
-
-# The position of boolean operators in wrapped expressions
-pos_bool                                 = ignore   # ignore/lead/trail
-
-# The position of the comma in wrapped expressions
-pos_comma                                = ignore   # ignore/lead/trail
-
-# The position of the comma in the constructor initialization list
-pos_class_comma                          = ignore   # ignore/lead/trail
-
-# The position of colons between constructor and member initialization
-pos_class_colon                          = ignore   # ignore/lead/trail
-
-#
-# Line Splitting options
-#
-
-# Try to limit code width to N number of columns
-code_width                               = 0        # number
-
-# Whether to fully split long 'for' statements at semi-colons
-ls_for_split_full                        = false    # false/true
-
-# Whether to fully split long function protos/calls at commas
-ls_func_split_full                       = false    # false/true
-
-#
-# Blank line options
-#
-
-# The maximum consecutive newlines
-nl_max                                   = 0        # number
-
-# The number of newlines after a function prototype, if followed by another function prototype
-nl_after_func_proto                      = 0        # number
-
-# The number of newlines after a function prototype, if not followed by another function prototype
-nl_after_func_proto_group                = 0        # number
-
-# The number of newlines after '}' of a multi-line function body
-nl_after_func_body                       = 0        # number
-
-# The number of newlines after '}' of a single line function body
-nl_after_func_body_one_liner             = 0        # number
-
-# The minimum number of newlines before a multi-line comment.
-# Doesn't apply if after a brace open or another multi-line comment.
-nl_before_block_comment                  = 0        # number
-
-# The minimum number of newlines before a single-line C comment.
-# Doesn't apply if after a brace open or other single-line C comments.
-nl_before_c_comment                      = 0        # number
-
-# The minimum number of newlines before a CPP comment.
-# Doesn't apply if after a brace open or other CPP comments.
-nl_before_cpp_comment                    = 0        # number
-
-# Whether to force a newline after a mulit-line comment.
-nl_after_multiline_comment               = false    # false/true
-
-# The number of newlines before a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# Will not change the newline count if after a brace open.
-# 0 = No change.
-nl_before_access_spec                    = 0        # number
-
-# The number of newlines after a 'private:', 'public:', 'protected:', 'signals:', or 'slots:' label.
-# 0 = No change.
-nl_after_access_spec                     = 0        # number
-
-# Whether to remove blank lines after '{'
-eat_blanks_after_open_brace              = false    # false/true
-
-# Whether to remove blank lines before '}'
-eat_blanks_before_close_brace            = false    # false/true
-
-#
-# Code modifying options (non-whitespace)
-#
-
-# Add or remove braces on single-line 'do' statement
-mod_full_brace_do                        = ignore   # ignore/add/remove/force
-
-# Add or remove braces on single-line 'for' statement
-mod_full_brace_for                       = ignore   # ignore/add/remove/force
-
-# Add or remove braces on single-line function defintions. (Pawn)
-mod_full_brace_function                  = ignore   # ignore/add/remove/force
-
-# Add or remove braces on single-line 'if' statement
-mod_full_brace_if                        = add      # ignore/add/remove/force
-
-# Don't remove braces around statements that span N newlines
-mod_full_brace_nl                        = 0        # number
-
-# Add or remove braces on single-line 'while' statement
-mod_full_brace_while                     = ignore   # ignore/add/remove/force
-
-# Add or remove unnecessary paren on 'return' statement
-mod_paren_on_return                      = ignore   # ignore/add/remove/force
-
-# Whether to change optional semicolons to real semicolons
-mod_pawn_semicolon                       = false    # false/true
-
-# Add parens on 'while' and 'if' statement around bools
-mod_full_paren_if_bool                   = false    # false/true
-
-# Whether to remove superfluous semicolons
-mod_remove_extra_semicolon               = false    # false/true
-
-# If a function body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_function_closebrace_comment = 0        # number
-
-# If a switch body exceeds the specified number of newlines and doesn't have a comment after
-# the close brace, a comment will be added.
-mod_add_long_switch_closebrace_comment   = 0        # number
-
-# If TRUE, will sort consecutive single-line 'import' statements [Java, D]
-mod_sort_import                          = false    # false/true
-
-# If TRUE, will sort consecutive single-line 'using' statements [C#]
-mod_sort_using                           = false    # false/true
-
-# If TRUE, will sort consecutive single-line '#include' statements [C/C++] and '#import' statements [Obj-C]
-# This is generally a bad idea, as it may break your code.
-mod_sort_include                         = false    # false/true
-
-#
-# Comment modifications
-#
-
-# Try to wrap comments at cmt_witdth columns
-cmt_width                                = 0        # number
-
-# Whether to group c-comments that look like they are in a block
-cmt_c_group                              = false    # false/true
-
-# Whether to put an empty '/*' on the first line of the combined c-comment
-cmt_c_nl_start                           = false    # false/true
-
-# Whether to put a newline before the closing '*/' of the combined c-comment
-cmt_c_nl_end                             = false    # false/true
-
-# Whether to group cpp-comments that look like they are in a block
-cmt_cpp_group                            = false    # false/true
-
-# Whether to put an empty '/*' on the first line of the combined cpp-comment
-cmt_cpp_nl_start                         = false    # false/true
-
-# Whether to put a newline before the closing '*/' of the combined cpp-comment
-cmt_cpp_nl_end                           = false    # false/true
-
-# Whether to change cpp-comments into c-comments
-cmt_cpp_to_c                             = false    # false/true
-
-# Whether to put a star on subsequent comment lines
-cmt_star_cont                            = false    # false/true
-
-# The number of spaces to insert at the start of subsequent comment lines
-cmt_sp_before_star_cont                  = 0        # number
-
-# The number of spaces to insert after the star on subsequent comment lines
-cmt_sp_after_star_cont                   = 0        # number
-
-# The filename that contains text to insert at the head of a file if the file doesn't start with a C/C++ comment.
-# Will substitue $(filename) with the current file's name.
-cmt_insert_file_header                   = ""         # string
-
-# The filename that contains text to insert before a function implementation if the function isn't preceeded with a C/C++ comment.
-# Will substitue $(function) with the function name and $(javaparam) with the javadoc @param and @return stuff.
-# Will also substitute $(fclass) with the class name: void CFoo::Bar() { ... }
-cmt_insert_func_header                   = ""         # string
-
-# The filename that contains text to insert before a class if the class isn't preceeded with a C/C++ comment.
-# Will substitue $(class) with the class name.
-cmt_insert_class_header                  = ""         # string
-
-#
-# Preprocessor options
-#
-
-# Control indent of preprocessors inside #if blocks at brace level 0
-pp_indent                                = ignore   # ignore/add/remove/force
-
-# Whether to indent #if/#else/#endif at the brace level (true) or from column 1 (false)
-pp_indent_at_level                       = false    # false/true
-
-# Add or remove space after # based on pp_level of #if blocks
-pp_space                                 = ignore   # ignore/add/remove/force
-
-# Sets the number of spaces added with pp_space
-pp_space_count                           = 0        # number
-
-# The indent for #region and #endregion in C# and '#pragma region' in C/C++
-pp_indent_region                         = 0        # number
-
-# Whether to indent the code between #region and #endregion
-pp_region_indent_code                    = false    # false/true
-
-# If pp_indent_at_level=true, sets the indent for #if, #else, and #endif when not at file-level
-pp_indent_if                             = 0        # number
-
-# Control whether to indent the code between #if, #else and #endif when not at file-level
-pp_if_indent_code                        = false    # false/true
-
-# Whether to indent '#define' at the brace level (true) or from column 1 (false)
-pp_define_at_level                       = false    # false/true
-
-# You can force a token to be a type with the 'type' option.
-# Example:
-# type myfoo1 myfoo2
-#
-# You can create custom macro-based indentation using macro-open, 
-# macro-else and macro-close.
-# Example:
-# macro-open  BEGIN_TEMPLATE_MESSAGE_MAP
-# macro-open  BEGIN_MESSAGE_MAP
-# macro-close END_MESSAGE_MAP