2025-07-02 00:29 CEST

View Issue Details Jump to Notes ]
IDProjectCategoryView StatusLast Update
0000928Spring engineGeneralpublic2008-11-02 11:32
ReporterjK 
Assigned ToAuswaschbar 
PrioritynormalSeverityfeatureReproducibilityN/A
StatusresolvedResolutionfixed 
Product Version0.76b1+svn 
Target VersionFixed in Version 
Summary0000928: [PATCH] huge patch (hwCursors,LuaStuff,Rendering,BumpWater,Speedup)
DescriptionYeah, finally it got finished. ^-^

Sorry that it took a bit longer and grow in size a bit, but nothing was really finshed until now, so I couldn't commit it further.

It's subdivided in 8 patches + 1 zip with images (for new BumpWater).

(Test compiled it under windows and linux.)
Additional Informationchangelog:

*hwCursor.patch
added full hardware cursor support for x11 and windows (with alpha blending and animations)
use "-finline-functions -funroll-loops" when optimize flag is set (they aren't part of -O2!)


*units.patch
removed redundant dependencies to CursorIcons.h
removed 50% capture progress, after an unit got captured
replaced some f3Dist with f3SqLen
added moveState and fixed fireState tag (unitdef)


*LuaCallins.patch
new IsGameOver LuaRules callin (can force and prevent gameend)
fixed DrawUnit and some other callins (-> removed "args=n" checks, those caused wierd error messages (wrong argument count))


*LuaCallouts.patch
 OpenGL
added gl.Texture($shading) & gl.Texture($grass)
fixed missing return;'s in LoadMatrix() and MulMatrix()
Allow to use CopyToTexture with non GL_TEXTURE2D, i.e. GL_TEXTURE_RECTANGLE
 Read
new Spring.GetUnitVectors(unitID) -> {front_x,front_y,front_z},{up_x,up_y,up_z},{right_x,right_y,right_z}
new Spring.GetUnitWeaponVectors(unitID,weaponNum) -> wpos_x,wpos_y,wpos_z, wdir_x,wdir_y,wdir_z
new Spring.GetPlayerStates(playerID) -> mousePixels,mouseClicks,keyPresses,numCmds,unitCmds
 Ctrl
new Spring.HeightMapFunc(lua_func,arg1,arg2,..)
  This new function allows, in contrast to the old existing heightmap interfaces,
  to make non-planar heightmap changes (like mounds) with a decent performance
  (a whole 16x16 map takes 1:30min, using multiple Spring.LevelHeightMap() took >30mins!).
  Now instead of calling Spring.LevelHeightMap() multiple times, you call
  Spring.HeightMapFunc() once and use the following sub-functions:

  new Spring.SetHeight(x,z,h)
    only valid in Spring.HeightMapFunc!
  new Spring.SetTerraform(x,z,h,terraform)
    only valid in Spring.HeightMapFunc!
    with 0<=terraform<=1 . It is the same equation the engine use internal,
    terraform is 0 at the beginning and goes upto 1 when finished.

 example:
   Spring.HeightMapFunc(function(x1,z1,x2,z2)
     local scale = math.pi/300
     for x=x1,x2 do
       for z=z1,z2 do
         Spring.SetHeight(x,z,(math.sin(scale*x)+math.cos(scale*z))*50)
       end
     end
   end, 0,0,Game.mapSizeX,Game.mapSizeZ)


*rendering.patch
extended /wiremap to BasicSkybox
fixed smoke textures loading from resource.tdf (resources/graphics/smoke/smoke00 .. smoke11)
enabled polygon offset for all units begin built (fixs a clipping issue)
fixed a wrong rotation in ApplyTransform() (which is used by lua's gl.UnitPieceMultMatrix)
removed some redundant texture unbindings in dynWater and removed 256*256 foamTex limit
fixed glyph (vertical) spacing in fontatlas
fixed spacing in particle atlas
new TextureLODBias option (global mipmapping bias)
new CompressTextures option (It is only used by the new mygl.cpp::glBuildMipmaps() function,
  so the 3do texture atlas won't be compressed)
merged all mipmap creation functions into mygl.cpp::glBuildMipmaps()
fixed dds mipmapping filter setting. (yeah smoth was always true, there was something wrong with s3o textures ;)
added PBO (PixelBufferObject) support to smf groundtexture loader.
  info: PBO use DMA and are async (-> 0% cpu usage). Under some conditions PBOs can be slower than the old mechanism,
  so you can turn them off with "UsePBO".
(note: DynWater.cpp needs the mapInfo.[cpp|h] change in bumpwater.patch)


*ui.patch
new /unitreplyvolume [0.0-1.0]
new /hardwarecursor [0|1]
new /minimap drawprojectiles [0|1] + implementation
  (you can turn off drawing of projectiles on the minimap now)
added /grounddecals [0|1] to word completion
added /water 4


*speedups.patch
inlined all VertexArray::AddVertex()
  (note: -O2 doesn't handle inlines! that's why the hwCursor.patch adds "-finline-functions" when optimize flag is set)
speedup CMatrix44f by ~5x! (Translate(),Rotate[X|Y|Z](),Invert())
  this can be a huge speed improvement in late games (IIRC profiler had shown CMatrix44f in top10 of most time consuming functions)


*bumpwater.patch + bumpwater.zip (needs changes of the rendering.patch: mygl.h::glBuildMipmaps() )
yeah, a new water shader!
It is modular so, you can turn off reflections and refractions to get the same speed as /water 0 and still get
a nice looking enviroment. Also it's the first water shader in spring that gives the water an ambient color,
so the water doesn't look always like puddle.

Features:
  normal map
  ambient/diffuse lighting
  specular lighting
  fresnel (refraction)
  caustics

new map water options (with defaults) are:
  FresnelMin(0.2), FresnelMax(0.3), FresnelPower(4.0) (define the refraction)
  WaterSpecularFactor(20.0)
  WaterSpecularColor(groundSunColor)
  WaterSurfaceAlpha(0.55)
  WaterFoamTexture(DynWater uses this, too)
  WaterNormalTexture(bumpmap)

new resource.tdf options:
  resources\\graphics\\caustics\\caustic00 .. caustic32

new .springrc/registry settings:
  BumpWaterTexSizeReflection(256)
  BumpWaterReflection(1)
  BumpWaterRefraction(1)
TagsNo tags attached.
Checked infolog.txt for Errors
Attached Files
  • patch file icon hwCursor.patch (36,598 bytes) 2008-05-10 16:27 -
    Index: rts/build/scons/config.py
    ===================================================================
    --- rts/build/scons/config.py	(revision 5850)
    +++ rts/build/scons/config.py	(working copy)
    @@ -301,6 +301,8 @@
     		d += [Dependency(['SDLmain'],  [])]
     	else:
     		d += [Dependency(['openal', 'openal32'], ['AL/al.h'])]
    +		d += [Dependency(['Xcursor'], ['X11/Xcursor/Xcursor.h'])]
    +		d += [Dependency(['X11'], ['X11/X.h'])]
     
     	d += [Dependency(['vorbisfile'], ['vorbis/vorbisfile.h'])]
     	d += [Dependency(['vorbis'], [])]
    Index: rts/build/scons/rts.py
    ===================================================================
    --- rts/build/scons/rts.py	(revision 5850)
    +++ rts/build/scons/rts.py	(working copy)
    @@ -270,6 +270,8 @@
     			level = args['optimize']
     			if level == 'no' or level == 'false': level = '0'
     			elif level == 'yes' or level == 'true': level = '2'
    +
    +			env.AppendUnique(CCFLAGS=['-finline-functions','-funroll-loops'])
     		else:
     			if env['debug']: level = '0'
     			else: level = '2'
    @@ -392,9 +394,11 @@
     			include_path += ['/usr/local/include', '/usr/X11R6/include', '/usr/X11R6/include/GL']
     			lib_path += ['/usr/local/lib', '/usr/X11R6/lib']
     			env.AppendUnique(CCFLAGS = ['-pthread'], CXXFLAGS = ['-pthread'])
    +			env.AppendUnique(CCFLAGS = ['-lX11','-lXcursor'], CXXFLAGS = ['-lX11','-lXcursor'])
     		elif env['platform'] == 'linux':
     			include_path += ['/usr/include', '/usr/include/GL']
     			env.AppendUnique(CCFLAGS = ['-pthread'], CXXFLAGS = ['-pthread'], LINKFLAGS = ['-Wl,-E'])
    +			env.AppendUnique(CCFLAGS = ['-lX11','-lXcursor'], CXXFLAGS = ['-lX11','-lXcursor'])
     		elif env['platform'] == 'darwin':
     			include_path += ['/usr/include', '/usr/local/include', '/opt/local/include', '/usr/X11R6/include']
     			lib_path += ['/opt/local/lib', '/usr/local/lib']
    Index: rts/Game/UI/GuiHandler.cpp
    ===================================================================
    --- rts/Game/UI/GuiHandler.cpp	(revision 5850)
    +++ rts/Game/UI/GuiHandler.cpp	(working copy)
    @@ -966,32 +966,30 @@
     
     void CGuiHandler::SetCursorIcon() const
     {
    -	mouse->cursorText = "";
    +	string newCursor = "cursornormal";
     	mouse->cursorScale = 1.0f;
     
     	CInputReceiver* ir = NULL;
    -	if (!game->hideInterface) {
    +	if (!game->hideInterface)
     		ir = GetReceiverAt(mouse->lastx, mouse->lasty);
    -	}
     
     	if ((ir != NULL) && (ir != minimap)) {
    +		mouse->SetCursor(newCursor);
     		return;
     	}
     
    -	if (ir == minimap) {
    +	if (ir == minimap)
     		mouse->cursorScale = minimap->CursorScale();
    -	}
     
    -	const bool useMinimap =
    -		(minimap->ProxyMode() || ((activeReceiver != this) && (ir == minimap)));
    +	const bool useMinimap = (minimap->ProxyMode() || ((activeReceiver != this) && (ir == minimap)));
     
     	if ((inCommand >= 0) && (inCommand<commands.size())) {
     		const CommandDescription& cmdDesc = commands[inCommand];
     
     		if (!cmdDesc.mouseicon.empty()) {
    -			mouse->cursorText = cmdDesc.mouseicon;
    +			newCursor=cmdDesc.mouseicon;
     		} else {
    -			mouse->cursorText = cmdDesc.name;
    +			newCursor=cmdDesc.name;
     		}
     
     		if (useMinimap && (cmdDesc.id < 0)) {
    @@ -1004,9 +1002,9 @@
     			// does not consider it when checking for position blocking
     			CFeature* feature;
     			if(!uh->TestUnitBuildSquare(bi, feature, gu->myAllyTeam)) {
    -				mouse->cursorText = "BuildBad";
    +				newCursor="BuildBad";
     			} else {
    -				mouse->cursorText = "BuildGood";
    +				newCursor="BuildGood";
     			}
     		}
     	}
    @@ -1021,16 +1019,17 @@
     		if ((defcmd >= 0) && (defcmd < commands.size())) {
     			const CommandDescription& cmdDesc = commands[defcmd];
     			if (!cmdDesc.mouseicon.empty()) {
    -				mouse->cursorText = cmdDesc.mouseicon;
    +				newCursor=cmdDesc.mouseicon;
     			} else {
    -				mouse->cursorText = cmdDesc.name;
    +				newCursor=cmdDesc.name;
     			}
     		}
     	}
     
    -	if (gatherMode && (mouse->cursorText == "Move")) {
    -		mouse->cursorText = "GatherWait";
    -	}
    +	if (gatherMode && (mouse->cursorText == "Move"))
    +		newCursor = "GatherWait";
    +	
    +	mouse->SetCursor(newCursor);
     }
     
     
    @@ -4014,11 +4013,6 @@
     	}
     	glEnd();
     
    -	if(sizeDiv!=0){
    -		char c[40];
    -		SNPRINTF(c, 40, "%d", (int)(frontLen / sizeDiv) );
    -		mouse->cursorTextRight=c;
    -	}
     	glEnable(GL_FOG);
     }
     
    Index: rts/Game/UI/HwMouseCursor.cpp
    ===================================================================
    --- rts/Game/UI/HwMouseCursor.cpp	(revision 0)
    +++ rts/Game/UI/HwMouseCursor.cpp	(revision 0)
    @@ -0,0 +1,543 @@
    +#include "StdAfx.h"
    +#include "bitops.h"
    +#include "CommandColors.h"
    +#include "FileSystem/FileHandler.h"
    +#include "FileSystem/SimpleParser.h"
    +#include "LogOutput.h"
    +#include "MouseCursor.h"
    +#include "HwMouseCursor.h"
    +#include "myMath.h"
    +#include "Rendering/GL/myGL.h"
    +#include "Rendering/Textures/Bitmap.h"
    +#include "mmgr.h"
    +#include <SDL_syswm.h>
    +
    +#ifdef WIN32
    +	#include "windows.h"
    +	#include "MouseInput.h"
    +#elif defined(__APPLE__)
    +	/*do nothing (duno how to create cursors on runtime on macs)*/
    +#else
    +	#include <X11/Xcursor/Xcursor.h>
    +#endif
    +
    +//int savedcount=0;
    +
    +//////////////////////////////////////////////////////////////////////
    +// Platform dependent classes
    +//////////////////////////////////////////////////////////////////////
    +
    +#ifdef __APPLE__
    +// no hardware cursor support for mac's
    +class CHwDummyCursor : public IHwCursor {
    +	public:
    +		void PushImage(int xsize, int ysize, void* mem){};
    +		void SetDelay(float delay){};
    +		void PushFrame(int index, float delay){};
    +		void Finish(){};
    +
    +		bool needsYFlip() {return false;};
    +
    +		bool IsValid(){return false;};
    +		void Bind(){};
    +};
    +#elif defined(WIN32)
    +class CHwWinCursor : public IHwCursor {
    +	public:
    +		CHwWinCursor(void);
    +		~CHwWinCursor(void);
    +
    +		void PushImage(int xsize, int ysize, void* mem);
    +		void SetDelay(float delay);
    +		void PushFrame(int index, float delay);
    +		void Finish();
    +
    +		bool needsYFlip() {return true;};
    +
    +		void Bind();
    +
    +		bool IsValid() {return (cursor!=NULL);};
    +	protected:
    +		HCURSOR cursor;
    +
    +		struct CursorDirectoryHeader {
    +			byte  xsize,ysize,ncolors,reserved1;
    +			short hotx,hoty;
    +			DWORD size,offset;
    +		};
    +
    +		struct CursorInfoHeader {
    +			DWORD size,width,height;
    +			WORD  planes, bpp;
    +			DWORD res1,res2,res3,res4,res5,res6;
    +		};
    +
    +		struct AnihStructure {
    +			DWORD size,images,frames,width,height,bpp,planes,rate,flags;
    +		};
    +
    +	protected:
    +		struct ImageData {
    +			unsigned char* data;
    +			int width,height;
    +		};
    +
    +		void buildIco(unsigned char* dst, ImageData &image);
    +		void resizeImage(ImageData *image, int new_x, int new_y);
    +
    +		int xmaxsize, ymaxsize;
    +		short hotx, hoty;
    +
    +		byte image_count;
    +
    +		std::vector<ImageData> icons;
    +		std::vector<byte>  frames;
    +		std::vector<int>   framerates;
    +};
    +#else
    +class CHwX11Cursor : public IHwCursor {
    +	public:
    +		CHwX11Cursor(void);
    +		~CHwX11Cursor(void);
    +
    +		void PushImage(int xsize, int ysize, void* mem);
    +		void SetDelay(float delay);
    +		void PushFrame(int index, float delay);
    +		void Finish();
    +
    +		bool needsYFlip() {return false;};
    +
    +		bool IsValid() {return (cursor!=0);};
    +		void Bind();
    +	protected:
    +		int xmaxsize, ymaxsize;
    +
    +		void resizeImage(XcursorImage*& image, const int new_x, const int new_y);
    +
    +		Cursor cursor;
    +		std::vector<XcursorImage*> cimages;
    +};
    +#endif
    +
    +//////////////////////////////////////////////////////////////////////
    +// GetHwCursor()
    +//////////////////////////////////////////////////////////////////////
    +
    +IHwCursor* GetNewHwCursor()
    +{
    +#ifdef WIN32
    +	return SAFE_NEW CHwWinCursor();
    +#elif defined(__APPLE__)
    +	return SAFE_NEW CHwDummyCursor();
    +#else
    +	return SAFE_NEW CHwX11Cursor();
    +#endif
    +}
    +
    +
    +//////////////////////////////////////////////////////////////////////
    +// Implementation 
    +//////////////////////////////////////////////////////////////////////
    +
    +
    +#ifdef __APPLE__
    +	// no hardware cursor support for mac's
    +#elif defined(WIN32)
    +
    +void CHwWinCursor::PushImage(int xsize, int ysize, void* mem)
    +{
    +	xmaxsize=std::max(xmaxsize,xsize);
    +	ymaxsize=std::max(ymaxsize,ysize);
    +
    +	ImageData icon;
    +	icon.data = new unsigned char[xsize*ysize*4];
    +	icon.width = xsize;
    +	icon.height = ysize;
    +	memcpy(icon.data,mem,xsize*ysize*4);
    +
    +	icons.push_back(icon);
    +
    +	frames.push_back(image_count);
    +	framerates.push_back(std::max((int)(defFrameLength*60.0f),1));
    +	image_count++;
    +}
    +
    +void CHwWinCursor::SetDelay(float delay)
    +{
    +	int &last_item = framerates.back();
    +	last_item = std::max((int)(delay*60.0f),1);
    +}
    +
    +void CHwWinCursor::PushFrame(int index, float delay)
    +{
    +	if (index>=image_count)
    +		return;
    +
    +	frames.push_back((byte)index);
    +	framerates.push_back(std::max((int)(delay*60.0f),1));
    +}
    +
    +void CHwWinCursor::resizeImage(ImageData *image, int new_x, int new_y)
    +{
    +	if (image->width==new_x && image->height==new_y)
    +		return;
    +
    +	unsigned char* newdata = new unsigned char[new_x*new_y*4];
    +	memset(newdata, 0, new_x*new_y*4);
    +
    +	for (int y = 0; y < image->height; ++y)
    +		for (int x = 0; x < image->width; ++x)
    +			for (int v = 0; v < 4; ++v)
    +				newdata[((y + (new_y-image->height))*new_x+x)*4+v] = image->data[(y*image->width+x)*4+v];
    +
    +	delete[] image->data;
    +
    +	image->data = newdata;
    +
    +	image->width  = new_x;
    +	image->height = new_y;
    +}
    +
    +void CHwWinCursor::buildIco(unsigned char* dst, ImageData &image)
    +{
    +	const int xsize = image.width;
    +	const int ysize = image.height;
    +
    +	//small header needed in .ani
    +	strcpy((char*)dst,"icon");
    +	dst += 4;
    +	DWORD* cursize = (DWORD*)&dst[0];
    +	cursize[0] = 3*sizeof(WORD)+sizeof(CursorDirectoryHeader)+sizeof(CursorInfoHeader)+xsize*ysize*4+xsize*ysize/8;
    +	dst += 4;
    +
    +	////////////////////////////////////////////////////////////////////////////////////////////////
    +	// the following code writes a full working .cur file in the memory (in a .ani container)
    +
    +	//file header
    +	WORD* header = (WORD*)&dst[0]; int i=0;
    +	header[i++] = 0;		//reserved
    +	header[i++] = 2;		//is cursor
    +	header[i++] = 1;		//number of cursor in this file
    +	dst += 3*sizeof(WORD);
    +
    +	CursorDirectoryHeader curHeader;
    +	memset(&curHeader,0,sizeof(CursorDirectoryHeader));
    +	curHeader.xsize  = (byte)xsize;		//width
    +	curHeader.ysize  = (byte)ysize;		//height
    +	curHeader.hotx   = hotx;
    +	curHeader.hoty   = hoty;
    +	curHeader.size   = 40+xsize*ysize*4+xsize*ysize/8;	//size of the bmp data (infoheader 40byte, 32bit color, 1bit mask)
    +	curHeader.offset = 22;			//offset, where the infoHeader starts
    +	memcpy(dst, &curHeader, sizeof(CursorDirectoryHeader));
    +	dst += sizeof(CursorDirectoryHeader);
    +
    +	CursorInfoHeader infoHeader;
    +	memset(&infoHeader,0,sizeof(CursorInfoHeader));
    +	infoHeader.size   = 40;		//size of the infoHeader
    +	infoHeader.width  = xsize;		//cursor width
    +	infoHeader.height = ysize*2;		//cursor height + mask height
    +	infoHeader.planes = 1;		//number of color planes
    +	infoHeader.bpp    = 32;		//bits per pixel
    +	memcpy(dst, &infoHeader, sizeof(CursorInfoHeader));
    +	dst += sizeof(CursorInfoHeader);
    +
    +	//copy colormap
    +	unsigned char* src = image.data;
    +	unsigned char* end = src+xsize*ysize*4;
    +	do{
    +		if (src[3]==0) {
    +			dst[0] = dst[1] = dst[2] = dst[3] = 0;
    +		}else{
    +			dst[0]=src[2];      // B
    +			dst[1]=src[1];      // G
    +			dst[2]=src[0];      // R
    +			dst[3]=src[3];      // A
    +		}
    +		dst+=4;
    +		src+=4;
    +	}while(src<end);
    +
    +	//create mask
    +	src -= xsize*ysize*4;
    +	int b = 0;
    +	do{
    +		dst[0] = 0x00;
    +		for (b=0; b<8; b++) {
    +			if (src[3]==0) //alpha greater zero?
    +				dst[0] |= 128>>b;
    +			src+=4;
    +		}
    +		dst++;
    +	}while(src<end);
    +
    +/*	char fname[256];
    +	SNPRINTF(fname, sizeof(fname), "mycursor%d.cur", ++savedcount);
    +	FILE * pFile = fopen( fname , "wb" );
    +	fwrite(curs.back(), 1 , curmem-curs.back(), pFile );
    +	fclose(pFile); */
    +}
    +
    +void CHwWinCursor::Finish()
    +{
    +	if (frames.size()<1)
    +		return;
    +
    +	hotx = (hotSpot==CMouseCursor::TopLeft) ? 0 : (short)xmaxsize/2;
    +	hoty = (hotSpot==CMouseCursor::TopLeft) ? 0 : (short)ymaxsize/2;
    +
    +	//note: windows only except 16x16,32x32,64x64,etc. (and some more not 2^n ones)
    +	int squaresize =  next_power_of_2( std::max(xmaxsize,ymaxsize) );
    +
    +	//resize images
    +	for (std::vector<ImageData>::iterator it=icons.begin(); it<icons.end(); it++)
    +		resizeImage(&*it,squaresize,squaresize);
    +
    +	const int riffsize  = 32 + sizeof(AnihStructure) + (frames.size()+2) * 2 * sizeof(DWORD);
    +	const int iconssize = icons.size() * (2*sizeof(DWORD) + 3*sizeof(WORD) +
    +					       sizeof(CursorDirectoryHeader) +
    +					       sizeof(CursorInfoHeader) +
    +					       squaresize*squaresize*4 +
    +					       squaresize*squaresize/8);
    +	const int totalsize = riffsize + iconssize;
    +	unsigned char* mem = SAFE_NEW unsigned char[ totalsize ];
    +
    +	unsigned char* curmem = mem;
    +	DWORD* dwmem;
    +
    +	//write RIFF header
    +		strcpy((char*)curmem,"RIFF");	curmem+=4;
    +		dwmem = (DWORD*)&curmem[0];
    +		dwmem[0] = totalsize-8;		curmem+=4; //filesize
    +		strcpy((char*)curmem,"ACON");	curmem+=4;
    +
    +	//Anih header
    +		strcpy((char*)curmem,"anih");
    +		curmem += 4;
    +		curmem[0] = 36;
    +		curmem[1] = curmem[2] = curmem[3] = 0;
    +		curmem += 4;
    +
    +		AnihStructure anih;
    +		memset(&anih,0,sizeof(AnihStructure));
    +		anih.size   = 36;		//anih structure size
    +		anih.images = image_count;		//number of images
    +		anih.frames = framerates.size();	//number of frames
    +		anih.flags  = 0x3L;		//using seq structure and .cur format for saving bmp data
    +		memcpy(curmem, &anih, sizeof(AnihStructure));
    +		curmem += sizeof(AnihStructure);
    +
    +	//LIST + icons
    +		strcpy((char*)curmem,"LIST");	curmem+=4;
    +		dwmem = (DWORD*)&curmem[0];
    +		dwmem[0] = iconssize+4;		curmem+=4;
    +		strcpy((char*)curmem,"fram");	curmem+=4;
    +
    +		for (std::vector<ImageData>::iterator it=icons.begin(); it<icons.end(); it++) {
    +			buildIco(curmem,*it);
    +			curmem += 2*sizeof(DWORD) + 3*sizeof(WORD)+sizeof(CursorDirectoryHeader)+sizeof(CursorInfoHeader)+squaresize*squaresize*4+squaresize*squaresize/8;
    +		}
    +
    +	//SEQ header
    +		strcpy((char*)curmem,"seq ");
    +		curmem += 4;
    +		DWORD* seq = (DWORD*)&curmem[0];
    +		seq[0] = frames.size()*sizeof(DWORD);
    +		seq++;
    +		for (int i=0; i<frames.size(); i++)
    +			seq[i] = frames.at(i);
    +		curmem += (frames.size()+1)*sizeof(DWORD);
    +
    +	//RATE header
    +		strcpy((char*)curmem,"rate");
    +		curmem += 4;
    +		DWORD* rate = (DWORD*)&curmem[0];
    +		rate[0] = framerates.size()*sizeof(DWORD);
    +		rate++;
    +		for (int i=0; i<framerates.size(); i++)
    +			rate[i] = framerates.at(i);
    +		curmem += (framerates.size()+1)*sizeof(DWORD);
    +
    +	/*char fname[256];
    +	SNPRINTF(fname, sizeof(fname), "cursors/mycursor%d.ani", ++savedcount);
    +	FILE * pFile = fopen( fname , "wb" );
    +	fwrite(mem , 1 , curmem-mem, pFile );
    +	fclose(pFile);*/
    +
    +	cursor = (HCURSOR)CreateIconFromResourceEx((PBYTE)mem,totalsize,FALSE,0x00030000,squaresize,squaresize,0);
    +
    +	delete[] mem;
    +	for (std::vector<ImageData>::iterator it=icons.begin(); it<icons.end(); it++)
    +		delete[] (*it).data;
    +	icons.clear();
    +
    +	//if (cursor==NULL) logOutput.Print("hw cursor failed: x%d y%d",squaresize,squaresize);
    +}
    +
    +void CHwWinCursor::Bind()
    +{
    +	/*SDL_SysWMinfo info;
    +	SDL_VERSION(&info.version);
    +	if (!SDL_GetWMInfo(&info)) {
    +		logOutput.Print("SDL error: can't get window handle");
    +		return;
    +	}
    +	SetClassLong(info.window,GCL_HCURSOR,(LONG)cursor);*/ //SDL doesn't let us use it :<
    +
    +	SetCursor(cursor);
    +	mouseInput->SetWMMouseCursor(cursor);
    +}
    +
    +CHwWinCursor::CHwWinCursor(void)
    +{
    +	cursor = NULL;
    +	hotSpot= CMouseCursor::Center;
    +	image_count = 0;
    +	xmaxsize = ymaxsize = 0;
    +}
    +
    +CHwWinCursor::~CHwWinCursor(void)
    +{
    +	if (cursor!=NULL)
    +		DestroyCursor(cursor);
    +
    +	for (std::vector<ImageData>::iterator it=icons.begin(); it<icons.end(); it++)
    +		delete[] (*it).data;
    +	icons.clear();
    +}
    +
    +#else
    +
    +void CHwX11Cursor::resizeImage(XcursorImage*& image, const int new_x, const int new_y)
    +{
    +	if (image->width==new_x && image->height==new_y)
    +		return;
    +
    +	const int old_x = image->width;
    +	const int old_y = image->height;
    +
    +	XcursorImage* new_image = XcursorImageCreate(new_x, new_y);
    +	new_image->delay = image->delay;
    +
    +	unsigned char* src = (unsigned char*)image->pixels;
    +	unsigned char* dst = (unsigned char*)new_image->pixels;
    +	memset(dst, 0, new_x*new_y*4);
    +
    +	for (int y = 0; y < old_y; ++y)
    +		for (int x = 0; x < old_x; ++x)
    +			for (int v = 0; v < 4; ++v)
    +				dst[(y*new_x+x)*4+v] = src[(y*old_x+x)*4+v];
    +
    +	XcursorImageDestroy(image);
    +	image = new_image;
    +}
    +
    +void CHwX11Cursor::PushImage(int xsize, int ysize, void* mem)
    +{
    +	xmaxsize=std::max(xmaxsize,xsize);
    +	ymaxsize=std::max(ymaxsize,ysize);
    +
    +	XcursorImage* image = XcursorImageCreate(xsize,ysize);
    +	image->delay = (XcursorUInt)(defFrameLength*1000.0f);
    +	char* dst=(char*)image->pixels;
    +	char* src=(char*)mem;
    +	char* end=src+xsize*ysize*4;
    +	do{
    +		dst[0]=src[2];      // B
    +		dst[1]=src[1];      // G
    +		dst[2]=src[0];      // R
    +		dst[3]=src[3];      // A
    +		dst+=4;
    +		src+=4;
    +	}while(src<end);
    +
    +	cimages.push_back(image);
    +}
    +
    +void CHwX11Cursor::SetDelay(float delay)
    +{
    +	cimages.back()->delay = (XcursorUInt)(delay*1000.0f); //in millseconds
    +}
    +
    +void CHwX11Cursor::PushFrame(int index, float delay)
    +{
    +	if (index>=cimages.size())
    +		return;
    +
    +	if (cimages[index]->delay!=delay) {
    +		// make a copy of the existing one
    +		XcursorImage* ci = cimages[index];
    +		PushImage( ci->width, ci->height, ci->pixels );
    +		SetDelay(delay);
    +	}else{
    +		cimages.push_back( cimages[index] );
    +	}
    +}
    +
    +void CHwX11Cursor::Finish()
    +{
    +	if (cimages.size()<1)
    +		return;
    +
    +	//resize images
    +	for (std::vector<XcursorImage*>::iterator it=cimages.begin(); it<cimages.end(); it++)
    +		resizeImage(*it,xmaxsize,ymaxsize);
    +
    +	XcursorImages *cis = XcursorImagesCreate(cimages.size());
    +	cis->nimage = cimages.size();
    +	for (int i=0; i < cimages.size(); i++ ) {
    +		XcursorImage* ci = cimages[i];
    +		ci->xhot = (hotSpot==CMouseCursor::TopLeft) ? 0 : ci->width/2;
    +		ci->yhot = (hotSpot==CMouseCursor::TopLeft) ? 0 : ci->height/2;
    +		cis->images[i] = ci;
    +	}
    +
    +	SDL_SysWMinfo info;
    +	SDL_VERSION(&info.version);
    +	if (!SDL_GetWMInfo(&info)) {
    +		XcursorImagesDestroy(cis);
    +		cimages.clear();
    +		logOutput.Print("SDL error: can't get X11 window info");
    +		return;
    +	}
    +
    +	cursor = XcursorImagesLoadCursor(info.info.x11.display,cis);
    +	XcursorImagesDestroy(cis);
    +	cimages.clear();
    +}
    +
    +void CHwX11Cursor::Bind()
    +{
    +	SDL_SysWMinfo info;
    +	SDL_VERSION(&info.version);
    +	if (!SDL_GetWMInfo(&info)) {
    +		logOutput.Print("SDL error: can't get X11 window info");
    +		return;
    +	}
    +	XDefineCursor(info.info.x11.display,info.info.x11.window,cursor);
    +}
    +
    +CHwX11Cursor::CHwX11Cursor(void)
    +{
    +	cursor = 0;
    +	hotSpot=CMouseCursor::Center;
    +	xmaxsize = ymaxsize = 0;
    +}
    +
    +CHwX11Cursor::~CHwX11Cursor(void)
    +{
    +	for (std::vector<XcursorImage*>::iterator it=cimages.begin() ; it < cimages.end(); it++ )
    +		XcursorImageDestroy(*it);
    +	cimages.clear();
    +
    +	if (cursor!=0) {
    +		SDL_SysWMinfo info;
    +		SDL_VERSION(&info.version);
    +		if (!SDL_GetWMInfo(&info)) {
    +			logOutput.Print("SDL error: can't get X11 window info");
    +			return;
    +		}
    +		XFreeCursor(info.info.x11.display,cursor);
    +	}
    +}
    +
    +#endif
    Index: rts/Game/UI/HwMouseCursor.h
    ===================================================================
    --- rts/Game/UI/HwMouseCursor.h	(revision 0)
    +++ rts/Game/UI/HwMouseCursor.h	(revision 0)
    @@ -0,0 +1,27 @@
    +#ifndef HWMOUSECURSOR_H
    +#define HWMOUSECURSOR_H
    +
    +#include <string>
    +#include <vector>
    +#include "MouseCursor.h"
    +
    +class CMouseCursor;
    +
    +class IHwCursor {
    +	public:
    +		virtual void PushImage(int xsize, int ysize, void* mem) {}
    +		virtual void SetDelay(float delay) {}
    +		virtual void PushFrame(int index, float delay) {}
    +		virtual void Finish() {}
    +
    +		virtual bool needsYFlip() {} //windows needs flipped Y axis
    +
    +		virtual bool IsValid() {}
    +		virtual void Bind() {}
    +
    +		CMouseCursor::HotSpot hotSpot;
    +};
    +
    +IHwCursor* GetNewHwCursor();
    +
    +#endif /* HWMOUSECURSOR_H */
    Index: rts/Game/UI/MouseCursor.cpp
    ===================================================================
    --- rts/Game/UI/MouseCursor.cpp	(revision 5850)
    +++ rts/Game/UI/MouseCursor.cpp	(working copy)
    @@ -5,16 +5,16 @@
     #include "FileSystem/SimpleParser.h"
     #include "LogOutput.h"
     #include "MouseCursor.h"
    +#include "HwMouseCursor.h"
     #include "myMath.h"
     #include "Rendering/GL/myGL.h"
     #include "Rendering/Textures/Bitmap.h"
     #include "mmgr.h"
     
    +//////////////////////////////////////////////////////////////////////
    +// CMouseCursor Class
    +//////////////////////////////////////////////////////////////////////
     
    -static const float minFrameLength = 0.010f;  // seconds
    -static const float defFrameLength = 0.100f;  // seconds
    -
    -
     CMouseCursor* CMouseCursor::New(const string &name, HotSpot hs)
     {
     	CMouseCursor* c = SAFE_NEW CMouseCursor(name, hs);
    @@ -25,20 +25,21 @@
     	return c;
     }
     
    -
    -//Would be nice if these were read from a gaf-file instead.
     CMouseCursor::CMouseCursor(const string &name, HotSpot hs)
     {
    +	hwCursor = GetNewHwCursor();
    +	hwCursor->hotSpot = hs;
     	hotSpot = hs;
     
    -	if (!BuildFromSpecFile(name)) {
    +	if (!BuildFromSpecFile(name))
     		BuildFromFileNames(name, 123456);
    -	}
     
    -	if (frames.size() <= 0) {
    +	if (frames.size() <= 0)
     		return;
    -	}
     
    +	animated = (frames.size() > 1);
    +	hwValid  = hwCursor->IsValid();
    +
     	animTime = 0.0f;
     	animPeriod = 0.0f;
     	currentFrame = 0;
    @@ -66,10 +67,11 @@
     
     CMouseCursor::~CMouseCursor(void)
     {
    +	delete hwCursor;
    +
     	std::vector<ImageData>::iterator it;
    -	for (it = images.begin(); it != images.end(); ++it) {
    +	for (it = images.begin(); it != images.end(); ++it)
     		glDeleteTextures(1, &it->texture);
    -	}
     }
     
     
    @@ -100,10 +102,12 @@
     			if (iit != imageIndexMap.end()) {
     				FrameData frame(images[iit->second], length);
     				frames.push_back(frame);
    +				hwCursor->PushFrame(iit->second,length);
     			}
     			else {
     				ImageData image;
     				if (LoadCursorImage(imageName, image)) {
    +					hwCursor->SetDelay(length);
     					imageIndexMap[imageName] = images.size();
     					images.push_back(image);
     					FrameData frame(image, length);
    @@ -114,13 +118,15 @@
     		else if ((command == "hotspot") && (words.size() >= 1)) {
     			if (words[1] == "topleft") {
     				hotSpot = TopLeft;
    +				hwCursor->hotSpot = TopLeft;
     			}
     			else if (words[1] == "center") {
     				hotSpot = Center;
    +				hwCursor->hotSpot = Center;
     			}
     			else {
     				logOutput.Print("%s: unknown hotspot  (%s)\n",
    -												specFile.c_str(), words[1].c_str());
    +							specFile.c_str(), words[1].c_str());
     			}
     		}
     		else if ((command == "lastframe") && (words.size() >= 1)) {
    @@ -136,6 +142,8 @@
     		return BuildFromFileNames(name, lastFrame);
     	}
     
    +	hwCursor->Finish();
    +
     	return true;
     }
     
    @@ -168,14 +176,15 @@
     		SNPRINTF(namebuf, sizeof(namebuf), "anims/%s_%d.%s",
     		         name.c_str(), frames.size(), ext);
     		ImageData image;
    -		if (!LoadCursorImage(namebuf, image)) {
    +		if (!LoadCursorImage(namebuf, image))
     			break;
    -		}
     		images.push_back(image);
     		FrameData frame(image, defFrameLength);
     		frames.push_back(frame);
     	}
     
    +	hwCursor->Finish();
    +
     	return true;
     }
     
    @@ -193,16 +202,24 @@
     		return false;
     	}
     
    -	b.ReverseYAxis();
    -
    -	CBitmap* final = getAlignedBitmap(b);
    -
    -	// coded bmp transparency mask
    +	// hardcoded bmp transparency mask
     	if ((name.size() >= 3) &&
     	    (StringToLower(name.substr(name.size() - 3)) == "bmp")) {
    -		setBitmapTransparency(*final, 84, 84, 252);
    +		setBitmapTransparency(b, 84, 84, 252);
     	}
     
    +	if (hwCursor->needsYFlip()) {
    +		//WINDOWS
    +		b.ReverseYAxis();
    +		hwCursor->PushImage(b.xsize,b.ysize,b.mem);
    +	}else{
    +		//X11
    +		hwCursor->PushImage(b.xsize,b.ysize,b.mem);
    +		b.ReverseYAxis();
    +	}
    +
    +	CBitmap* final = getAlignedBitmap(b);
    +
     	GLuint texID = 0;
     	glGenTextures(1, &texID);
     	glBindTexture(GL_TEXTURE_2D, texID);
    @@ -267,6 +284,8 @@
     
     void CMouseCursor::Draw(int x, int y, float scale)
     {
    +	if (scale<0) scale=-scale;
    +
     	const FrameData& frame = frames[currentFrame];
     	const int xs = int(float(frame.image.xAlignedSize) * scale);
     	const int ys = int(float(frame.image.yAlignedSize) * scale);
    @@ -346,3 +365,8 @@
     	const FrameData& frame = frames[currentFrame];
     	glBindTexture(GL_TEXTURE_2D, frame.image.texture);
     }
    +
    +bool CMouseCursor::BindHwCursor()
    +{
    +	hwCursor->Bind();	
    +}
    Index: rts/Game/UI/MouseCursor.h
    ===================================================================
    --- rts/Game/UI/MouseCursor.h	(revision 5850)
    +++ rts/Game/UI/MouseCursor.h	(working copy)
    @@ -4,22 +4,27 @@
     #include <string>
     #include <vector>
     #include "Rendering/GL/myGL.h"
    +//#include "HwMouseCursor.h"
     
     class CBitmap;
    +class IHwCursor;
     
    -
     class CMouseCursor {
     	public:
     		enum HotSpot {TopLeft, Center};
     
    +		bool animated;
    +		bool hwValid; //if hardware cursor is valid
    +
     		static CMouseCursor* New(const std::string &name, HotSpot hs);
     
     		~CMouseCursor(void);
     
     		void Update();
    -		void Draw(int x, int y, float scale);
    -		void DrawQuad(int x, int y);
    -		void BindTexture();
    +		void Draw(int x, int y, float scale);	// software cursor draw
    +		void DrawQuad(int x, int y);		// draw command queue icon
    +		void BindTexture(); 			// software mouse cursor
    +		bool BindHwCursor(); 			// hardware mouse cursor
     
     		int GetMaxSizeX() const { return xmaxsize; }
     		int GetMaxSizeY() const { return ymaxsize; }
    @@ -55,6 +60,8 @@
     		std::vector<ImageData> images;
     		std::vector<FrameData> frames;
     
    +		IHwCursor* hwCursor; // hardware cursor
    +
     		float animTime;
     		float animPeriod;
     		int currentFrame;
    @@ -67,4 +74,8 @@
     };
     
     
    +static const float minFrameLength = 0.010f;  // seconds
    +static const float defFrameLength = 0.100f;  // seconds
    +
    +
     #endif /* MOUSECURSOR_H */
    Index: rts/Game/UI/MouseHandler.cpp
    ===================================================================
    --- rts/Game/UI/MouseHandler.cpp	(revision 5850)
    +++ rts/Game/UI/MouseHandler.cpp	(working copy)
    @@ -61,7 +61,9 @@
     {
     	lastx=300;
     	lasty=200;
    -	hide=false;
    +	hide=true;
    +	hwHide=true;
    +	currentCursor=NULL;
     
     	for(int a=1;a<=NUM_BUTTONS;a++){
     		buttons[a].pressed=false;
    @@ -73,11 +75,18 @@
     
     	LoadCursors();
     
    +	// hide the cursor until we are ingame (not in loading screen etc.)
     	SDL_ShowCursor(SDL_DISABLE);
     
    +#ifndef __APPLE__
    +	hardwareCursor = !!configHandler.GetInt("HardwareCursor", 0);
    +#else
    +	hardwareCursor = false;
    +#endif
    +
     	soundMultiselID = sound->GetWaveId("sounds/button9.wav");
     
    -	invertMouse=!!configHandler.GetInt("InvertMouse",1);
    +	invertMouse = !!configHandler.GetInt("InvertMouse",1);
     	doubleClickTime = (float)configHandler.GetInt("DoubleClickTime", 200) / 1000.0f;
     
     	scrollWheelSpeed = (float)configHandler.GetInt("ScrollWheelSpeed", 25);
    @@ -86,7 +95,8 @@
     
     CMouseHandler::~CMouseHandler()
     {
    -	SDL_ShowCursor(SDL_ENABLE);
    +	if (hwHide)
    +		SDL_ShowCursor(SDL_ENABLE);
     
     	std::map<std::string, CMouseCursor*>::iterator ci;
     	for (ci = cursorFileMap.begin(); ci != cursorFileMap.end(); ++ci) {
    @@ -533,37 +543,7 @@
     	}
     }
     
    -void CMouseHandler::ShowMouse()
    -{
    -	if(hide){
    -		SDL_ShowCursor(SDL_DISABLE);
    -		hide=false;
    -	}
    -}
     
    -
    -void CMouseHandler::HideMouse()
    -{
    -	if (!hide) {
    -		lastx = gu->viewSizeX / 2 + gu->viewPosX;
    -		lasty = gu->viewSizeY / 2 + gu->viewPosY;
    -    	SDL_ShowCursor(SDL_DISABLE);
    -		mouseInput->SetPos(int2(lastx, lasty));
    -		hide = true;
    -	}
    -}
    -
    -void CMouseHandler::ToggleState()
    -{
    -	if(locked){
    -		locked=false;
    -		ShowMouse();
    -	} else {
    -		locked=true;
    -		HideMouse();
    -}
    -}
    -
     void CMouseHandler::WarpMouse(int x, int y)
     {
     	if (!locked) {
    @@ -631,6 +611,7 @@
     	return "";
     }
     
    +
     void CMouseHandler::EmptyMsgQueUpdate(void)
     {
     	if (!hide) {
    @@ -653,29 +634,115 @@
     	}
     }
     
    +
    +void CMouseHandler::ShowMouse()
    +{
    +	if(hide){
    +		// I don't use SDL_ShowCursor here 'cos it would cause a flicker (with hwCursor)
    +		// instead update state and cursor at the same time
    +		if (hardwareCursor){
    +			hwHide=true; //call SDL_ShowCursor(SDL_ENABLE) later!
    +		}else{
    +			SDL_ShowCursor(SDL_DISABLE);
    +		}
    +		cursorText=""; //force hardware cursor rebinding (else we have standard b&w cursor)
    +		hide=false;
    +	}
    +}
    +
    +
    +void CMouseHandler::HideMouse()
    +{
    +	if (!hide) {
    +		hwHide = true;
    +		SDL_ShowCursor(SDL_DISABLE);
    +		mouseInput->SetWMMouseCursor(NULL);
    +		lastx = gu->viewSizeX / 2 + gu->viewPosX;
    +		lasty = gu->viewSizeY / 2 + gu->viewPosY;
    +		mouseInput->SetPos(int2(lastx, lasty));
    +		hide = true;
    +	}
    +}
    +
    +
    +void CMouseHandler::ToggleState()
    +{
    +	if(locked){
    +		locked=false;
    +		ShowMouse();
    +	} else {
    +		locked=true;
    +		HideMouse();
    +	}
    +}
    +
    +
    +void CMouseHandler::UpdateHwCursor()
    +{
    +	if (hardwareCursor){
    +		hwHide=true; //call SDL_ShowCursor(SDL_ENABLE) later!
    +	}else{
    +		mouseInput->SetWMMouseCursor(NULL);
    +		SDL_ShowCursor(SDL_DISABLE);
    +	}
    +	cursorText = "";
    +}
    +
    +
     /******************************************************************************/
     
    +void CMouseHandler::SetCursor(const std::string& cmdName)
    +{
    +	if (cursorText.compare(cmdName)==0)
    +		return;
    +
    +	cursorText = cmdName;
    +	map<string, CMouseCursor*>::iterator it = cursorCommandMap.find(cmdName);
    +	if (it != cursorCommandMap.end()) {
    +		currentCursor = it->second;
    +	} else {
    +		currentCursor = cursorFileMap["cursornormal"];
    +	}
    +
    +	if (hardwareCursor && !hide && currentCursor) {
    +		if (currentCursor->hwValid) {
    +			if (hwHide) {
    +				SDL_ShowCursor(SDL_ENABLE);
    +				hwHide = false;
    +			}
    +			currentCursor->BindHwCursor();
    +		}else{
    +			hwHide = true;
    +			SDL_ShowCursor(SDL_DISABLE);
    +			mouseInput->SetWMMouseCursor(NULL);
    +		}
    +	}
    +}
    +
    +
     void CMouseHandler::UpdateCursors()
     {
    +	//we update all cursors, 'cos of the command queue icons
     	map<string, CMouseCursor *>::iterator it;
     	for (it = cursorFileMap.begin(); it != cursorFileMap.end(); ++it) {
    -		if (it->second != NULL) {
    +		if (it->second != NULL)
     			it->second->Update();
    -		}
     	}
     }
     
     
     void CMouseHandler::DrawCursor(void)
     {
    -	if (guihandler) {
    +	if (guihandler)
     		guihandler->DrawCentroidCursor();
    -	}
     
    -	if (hide || (cursorText == "none")) {
    +	if (hide || (cursorText == "none"))
     		return;
    -	}
     
    +	if (currentCursor && (!hardwareCursor || !currentCursor->hwValid) )
    +		currentCursor->Draw(lastx, lasty, cursorScale);
    +
    +/*
     	CMouseCursor* mc;
     	map<string, CMouseCursor*>::iterator it = cursorCommandMap.find(cursorText);
     	if (it != cursorCommandMap.end()) {
    @@ -699,11 +766,10 @@
     		else {
     			nc->Draw(lastx, lasty, 1.0f);
     			if (mc != nc) {
    -				mc->Draw(lastx + nc->GetMaxSizeX(),
    -								 lasty + nc->GetMaxSizeY(), -cursorScale);
    +				mc->Draw(lastx + nc->GetMaxSizeX(),  lasty + nc->GetMaxSizeY(), -cursorScale);
     			}
     		}
    -	}
    +	}*/
     }
     
     
    Index: rts/Game/UI/MouseHandler.h
    ===================================================================
    --- rts/Game/UI/MouseHandler.h	(revision 5850)
    +++ rts/Game/UI/MouseHandler.h	(working copy)
    @@ -16,15 +16,20 @@
     class CCameraController;
     
     
    -class CMouseHandler  
    +class CMouseHandler
     {
     public:
    +	void SetCursor(const std::string& cmdName);
    +
    +	bool hardwareCursor;
    +	void UpdateHwCursor(); //calls SDL_ShowCursor, used for ingame hwcursor enabling
    +
     	void UpdateCursors();
     	void HideMouse();
     	void ShowMouse();
    -	void ToggleState();
    +	void ToggleState(); // lock+hide (used by fps camera and middle click scrolling)
     	void WarpMouse(int x, int y);
    -	void Draw();
    +	void Draw(); // draw mousebox (selection box)
     	void MouseRelease(int x,int y,int button);
     	void MousePress(int x,int y,int button);
     	void MouseMove(int x,int y);
    @@ -32,9 +37,10 @@
     	CMouseHandler();
     	virtual ~CMouseHandler();
     
    -	int lastx;  
    -	int lasty;  
    +	int lastx;
    +	int lasty;
     	bool hide;
    +	bool hwHide;
     	bool locked;
     	bool invertMouse;
     	float doubleClickTime;
    @@ -53,23 +59,19 @@
     	};
     
     	ButtonPress buttons[NUM_BUTTONS + 1]; /* One-bottomed. */
    +	int activeButton;
     	float3 dir;
     
    -	int activeButton;
    +	int soundMultiselID;
     
    -	unsigned int cursorTex;
    -	std::string cursorText;
    -	std::string cursorTextRight;
    -	float cursorScale;	
    +	float cursorScale;
     	void DrawCursor(void);
     	std::string GetCurrentTooltip(void);
     
    +	std::string cursorText; //current cursor name
    +	CMouseCursor *currentCursor;
     	std::map<std::string, CMouseCursor*> cursorFileMap;
     	std::map<std::string, CMouseCursor*> cursorCommandMap;
    -	//CMouseCursor *mc;
    -
    -	int soundMultiselID;
    -
     	bool AssignMouseCursor(const std::string& cmdName,
     	                       const std::string& fileName,
     	                       CMouseCursor::HotSpot hotSpot,
    Index: rts/System/MouseInput.cpp
    ===================================================================
    --- rts/System/MouseInput.cpp	(revision 5850)
    +++ rts/System/MouseInput.cpp	(working copy)
    @@ -3,12 +3,17 @@
     	The code hacks around the mouse input from DirectInput, which SDL uses in fullscreen mode.
     	Instead it installs a window message proc and reads input from WM_MOUSEMOVE.
     	On non-windows, the normal SDL events are used for mouse input
    +
    +	new:
    +	It also workarounds a issue with SDL+windows and hardware cursors (->it has to block WM_SETCURSOR),
    +	so it is used now always even in window mode!
     */
     
     #include "StdAfx.h"
     #include "Platform/Win/win32.h"
     #include "MouseInput.h"
     #include "Game/UI/MouseHandler.h"
    +#include "LogOutput.h"
     
     #include <SDL_events.h>
     #include <SDL_syswm.h>
    @@ -24,6 +29,7 @@
     //////////////////////////////////////////////////////////////////////
     
     #ifdef WIN32
    +
     class CWin32MouseInput : public IMouseInput
     {
     public:
    @@ -33,6 +39,7 @@
     	int2 mousepos;
     	bool mousemoved;
     	HWND wnd;
    +	HCURSOR hCursor;
     
     	// SDL runs the window in a different thread, hence the indirectness of the mouse pos handling
     	static LRESULT CALLBACK SpringWndProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam)
    @@ -41,10 +48,23 @@
     			inst->mousepos = int2(LOWORD(lparam),HIWORD(lparam));
     			inst->mousemoved = true;
     			return FALSE;
    +		}else if (msg==WM_SETCURSOR) {
    +			if (inst->hCursor!=NULL) {
    +				Uint16 hittest = LOWORD(lparam);
    +				if ( hittest == HTCLIENT ) {
    +					SetCursor(inst->hCursor);
    +					return TRUE;
    +				}
    +			}
     		}
     		return CallWindowProc((WNDPROC)inst->sdl_wndproc, wnd, msg, wparam, lparam);
     	}
     
    +	void SetWMMouseCursor(void* wmcursor)
    +	{
    +		hCursor = (HCURSOR)wmcursor;
    +	}
    +
     	void InstallWndCallback()
     	{
     		sdl_wndproc = GetWindowLongPtr(wnd, GWLP_WNDPROC);
    @@ -55,6 +75,8 @@
     	{
     		inst = this;
     
    +		hCursor = NULL;
    +
     		mousemoved = false;
     		sdl_wndproc = 0;
     
    @@ -65,9 +87,7 @@
     
     		wnd = info.window;
     
    -		// In windowed mode, SDL uses straight Win32 API to handle mouse movement, which works ok.
    -		if (fullscreen)
    -			InstallWndCallback();
    +		InstallWndCallback();
     	}
     	~CWin32MouseInput()
     	{
    @@ -83,7 +103,7 @@
     	{
     		mousepos = pos;
     		if (fullscreen)
    -			SetCursorPos (pos.x, pos.y);
    +			SetCursorPos(pos.x, pos.y);
     		else
     			SDL_WarpMouse(pos.x, pos.y);
     	}
    @@ -111,12 +131,12 @@
     					mouse->MousePress (mousepos.x, mousepos.y, 5);
     			}
     			break;}
    -		case SDL_MOUSEMOTION: // the normal SDL method works fine in windowed mode 
    +		/*case SDL_MOUSEMOTION: // the normal SDL method works fine in windowed mode 
     			if(!fullscreen) {
     				mousepos = int2(event.motion.x, event.motion.y);
     				mouse->MouseMove(mousepos.x, mousepos.y);
     			}
    -			break;
    +			break;*/
     		case SDL_MOUSEBUTTONDOWN:
     			if (event.button.button == SDL_BUTTON_WHEELUP)
     				mouse->MouseWheel(true);
    Index: rts/System/MouseInput.h
    ===================================================================
    --- rts/System/MouseInput.h	(revision 5850)
    +++ rts/System/MouseInput.h	(working copy)
    @@ -17,6 +17,8 @@
     	virtual void Update () {}
     
     	virtual void HandleSDLMouseEvent (SDL_Event& event) = 0;
    +
    +	virtual void SetWMMouseCursor (void* wmcursor) {}
     };
     
     
    
    patch file icon hwCursor.patch (36,598 bytes) 2008-05-10 16:27 +
  • patch file icon units.patch (9,126 bytes) 2008-05-10 16:28 -
    Index: rts/Lua/LuaUnitDefs.cpp
    ===================================================================
    --- rts/Lua/LuaUnitDefs.cpp	(revision 5850)
    +++ rts/Lua/LuaUnitDefs.cpp	(working copy)
    @@ -799,6 +799,7 @@
     	ADD_BOOL("canCrash",              ud.canCrash);
     	ADD_BOOL("canFireControl",        ud.canFireControl);
     	ADD_INT( "fireState",             ud.fireState);
    +	ADD_INT( "moveState",             ud.moveState);
     	ADD_BOOL("fullHealthFactory",     ud.fullHealthFactory);
     	ADD_BOOL("factoryHeadingTakeoff", ud.factoryHeadingTakeoff);
     
    Index: rts/Sim/Units/CommandAI/AirCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/AirCAI.cpp	(revision 5850)
    +++ rts/Sim/Units/CommandAI/AirCAI.cpp	(working copy)
    @@ -5,7 +5,7 @@
     #include "Game/GameHelper.h"
     #include "Game/SelectedUnits.h"
     #include "Game/UI/CommandColors.h"
    -#include "Game/UI/CursorIcons.h"
    +//#include "Game/UI/CursorIcons.h"
     #include "Map/Ground.h"
     #include "Rendering/GL/glExtra.h"
     #include "Rendering/GL/myGL.h"
    Index: rts/Sim/Units/CommandAI/BuilderCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/BuilderCAI.cpp	(revision 5850)
    +++ rts/Sim/Units/CommandAI/BuilderCAI.cpp	(working copy)
    @@ -1102,7 +1102,7 @@
     		const CFeature* f = *fi;
     		if (f->def->reclaimable &&
     		    (recAnyTeam || (f->allyteam != owner->allyteam))) {
    -			const float dist = f3Dist(f->pos, owner->pos);
    +			const float dist = f3SqLen(f->pos - owner->pos);
     			if ((dist < bestDist) &&
     			    (noResCheck ||
     			     ((f->def->metal  > 0.0f) && (team->metal  < team->metalStorage)) ||
    @@ -1146,7 +1146,7 @@
     	for (fi = features.begin(); fi != features.end(); ++fi) {
     		const CFeature* f = *fi;
     		if (f->def->destructable && f->createdFromUnit != "") {
    -			const float dist = f3Dist(f->pos, owner->pos);
    +			const float dist = f3SqLen(f->pos - owner->pos);
     			if (dist < bestDist) {
     				// dont lock-on to units outside of our reach (for immobile builders)
     				if (!owner->unitDef->canmove && !ObjInBuildRange(f)) {
    @@ -1186,7 +1186,7 @@
     
     		if (!gs->Ally(myAllyteam, unit->allyteam) && (unit != owner) &&
     			!unit->beingBuilt && unit->unitDef->capturable) {
    -			const float dist = f3Dist(unit->pos, owner->pos);
    +			const float dist = f3SqLen(unit->pos - owner->pos);
     
     			if (dist < bestDist) {
     				// dont lock-on to units outside of our reach (for immobile builders)
    @@ -1251,7 +1251,7 @@
     					trySelfRepair = true;
     					continue;
     				}
    -				const float dist = f3Dist(unit->pos, owner->pos);
    +				const float dist = f3SqLen(unit->pos - owner->pos);
     				if (dist < bestDist) {
     					bestDist = dist;
     					best = unit;
    @@ -1260,7 +1260,7 @@
     		}
     		else {
     			if (attackEnemy && owner->unitDef->canAttack && (owner->maxRange > 0)) {
    -				const float dist = f3Dist(unit->pos, owner->pos);
    +				const float dist = f3SqLen(unit->pos - owner->pos);
     				if ((dist < bestDist) || !haveEnemy) {
     					if (!owner->unitDef->canmove &&
     					    ((dist - unit->radius) > owner->maxRange)) {
    Index: rts/Sim/Units/CommandAI/CommandAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/CommandAI.cpp	(revision 5850)
    +++ rts/Sim/Units/CommandAI/CommandAI.cpp	(working copy)
    @@ -219,7 +219,6 @@
     		c.params.push_back("Roam");
     		c.tooltip="Move State: Sets how far out of its way\n an unit will move to attack enemies";
     		possibleCommands.push_back(c);
    -		owner->moveState=1;
     		nonQueingCommands.insert(CMD_MOVE_STATE);
     	} else {
     		owner->moveState=0;
    Index: rts/Sim/Units/CommandAI/MobileCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/MobileCAI.cpp	(revision 5850)
    +++ rts/Sim/Units/CommandAI/MobileCAI.cpp	(working copy)
    @@ -7,7 +7,7 @@
     #include "Game/SelectedUnits.h"
     #include "Game/Team.h"
     #include "Game/UI/CommandColors.h"
    -#include "Game/UI/CursorIcons.h"
    +//#include "Game/UI/CursorIcons.h"
     #include "Map/Ground.h"
     #include "Rendering/GL/myGL.h"
     #include "Sim/Misc/AirBaseHandler.h"
    Index: rts/Sim/Units/CommandAI/TransportCAI.cpp
    ===================================================================
    --- rts/Sim/Units/CommandAI/TransportCAI.cpp	(revision 5850)
    +++ rts/Sim/Units/CommandAI/TransportCAI.cpp	(working copy)
    @@ -9,7 +9,7 @@
     #include "Map/Ground.h"
     #include "Sim/Misc/QuadField.h"
     #include "Game/UI/CommandColors.h"
    -#include "Game/UI/CursorIcons.h"
    +//#include "Game/UI/CursorIcons.h"
     #include "LogOutput.h"
     #include "Rendering/GL/myGL.h"
     #include "Rendering/GL/glExtra.h"
    Index: rts/Sim/Units/Unit.cpp
    ===================================================================
    --- rts/Sim/Units/Unit.cpp	(revision 5850)
    +++ rts/Sim/Units/Unit.cpp	(working copy)
    @@ -1452,7 +1452,7 @@
     	//All units are set as ground-blocking.
     	blocking = true;
     
    -	if(pos.y+model->height<1)	//some torp launchers etc is exactly in the surface and should be considered uw anyway
    +	if(pos.y+model->height<1)	//some torp launchers etc are exactly in the surface and should be considered uw anyway
     		isUnderWater=true;
     
     	if(!unitDef->canKamikaze || unitDef->type=="Building" || unitDef->type=="Factory")	//semi hack to make mines not block ground
    @@ -1460,6 +1460,41 @@
     
     	UpdateTerrainType();
     
    +	Command c;
    +	if (unitDef->canmove || unitDef->builder) {
    +		if (unitDef->moveState<0) {
    +			if (builder!=NULL) {
    +				moveState = builder->moveState;
    +			}else{
    +				moveState = 1;
    +			}
    +		} else {
    +			moveState = unitDef->moveState;
    +		}
    +
    +		c.id = CMD_MOVE_STATE;
    +		c.params.push_back(moveState);
    +		commandAI->GiveCommand(c);
    +		c.params.clear();
    +	}
    +
    +	if (commandAI->CanChangeFireState()) {
    +		if (unitDef->fireState<0) {
    +			if (builder!=NULL) {
    +				fireState = builder->fireState;
    +			}else{
    +				fireState = 2;
    +			}
    +		} else {
    +			fireState = unitDef->fireState;
    +		}
    +
    +		c.id = CMD_FIRE_STATE;
    +		c.params.push_back(fireState);
    +		commandAI->GiveCommand(c);
    +		c.params.clear();
    +	}
    +
     	luaCallIns.UnitCreated(this, builder);
     	globalAI->UnitCreated(this); // FIXME -- add builder?
     }
    Index: rts/Sim/Units/UnitDef.h
    ===================================================================
    --- rts/Sim/Units/UnitDef.h	(revision 5850)
    +++ rts/Sim/Units/UnitDef.h	(working copy)
    @@ -263,6 +263,7 @@
     	bool canFireControl;
     
     	int fireState;
    +	int moveState;
     
     	//aircraft stuff
     	float wingDrag;
    Index: rts/Sim/Units/UnitDefHandler.cpp
    ===================================================================
    --- rts/Sim/Units/UnitDefHandler.cpp	(revision 5850)
    +++ rts/Sim/Units/UnitDefHandler.cpp	(working copy)
    @@ -341,9 +341,6 @@
     	ud.canPatrol   = udTable.GetBool("canPatrol",   true);
     	ud.canGuard    = udTable.GetBool("canGuard",    true);
     	ud.canRepeat   = udTable.GetBool("canRepeat",   true);
    -	bool noAutoFire  = udTable.GetBool("noAutoFire",  false);
    -	ud.canFireControl = udTable.GetBool("canFireControl", !noAutoFire);
    -	ud.fireState = udTable.GetInt("fireState", ud.canFireControl ? -1 : 0);
     
     	ud.builder = udTable.GetBool("builder", true);
     
    @@ -386,6 +383,13 @@
     	ud.maxDec   = fabs(udTable.GetFloat("brakeRate",    3.0f*ud.maxAcc)) * (ud.canfly ? 0.1f : 1.f); // no negative values
     	ud.turnRate = udTable.GetFloat("turnRate",     0.0f);
     
    +	bool noAutoFire  = udTable.GetBool("noAutoFire",  false);
    +	ud.canFireControl = udTable.GetBool("canFireControl", !noAutoFire);
    +	ud.fireState = udTable.GetInt("fireState", ud.canFireControl ? -1 : 2);
    +	ud.fireState = std::min(ud.fireState,2);
    +	ud.moveState = udTable.GetInt("moveState", (ud.canmove && ud.speed>0.0f)  ? -1 : 1);
    +	ud.moveState = std::min(ud.moveState,2);
    +
     	ud.buildRange3D = udTable.GetBool("buildRange3D", false);
     	ud.buildDistance = udTable.GetFloat("buildDistance", 128.0f);
     	ud.buildDistance = std::max(128.0f, ud.buildDistance);
    Index: rts/Sim/Units/UnitTypes/Builder.cpp
    ===================================================================
    --- rts/Sim/Units/UnitTypes/Builder.cpp	(revision 5850)
    +++ rts/Sim/Units/UnitTypes/Builder.cpp	(working copy)
    @@ -327,7 +327,7 @@
     					curCapture->lineage = this->lineage;
     					gs->Team(oldLineage)->LeftLineage(curCapture);
     				}
    -				curCapture->captureProgress=0.5f;	//make units somewhat easier to capture back after first capture
    +				curCapture->captureProgress=0.0f;
     				StopBuild(true);
     			}
     		} else {
    Index: rts/Sim/Units/UnitTypes/Factory.cpp
    ===================================================================
    --- rts/Sim/Units/UnitTypes/Factory.cpp	(revision 5850)
    +++ rts/Sim/Units/UnitTypes/Factory.cpp	(working copy)
    @@ -193,20 +193,6 @@
     				curBuild->SetGroup(group);
     			}
     
    -			Command c;
    -			c.options = 0;
    -
    -			c.id = CMD_MOVE_STATE;
    -			c.params.push_back(moveState);
    -			curBuild->commandAI->GiveCommand(c);
    -			c.params.clear();
    -
    -			if(curBuild->unitDef->fireState < 0) {
    -				c.id = CMD_FIRE_STATE;
    -				c.params.push_back(fireState);
    -				curBuild->commandAI->GiveCommand(c);
    -			}
    -
     			bool userOrders = true;
     			if (curBuild->commandAI->commandQue.empty() ||
     					(dynamic_cast<CMobileCAI*>(curBuild->commandAI) &&
    
    patch file icon units.patch (9,126 bytes) 2008-05-10 16:28 +
  • patch file icon LuaCallins.patch (4,845 bytes) 2008-05-10 16:28 -
    Index: rts/Game/GameServer.cpp
    ===================================================================
    --- rts/Game/GameServer.cpp	(revision 5850)
    +++ rts/Game/GameServer.cpp	(working copy)
    @@ -27,6 +27,7 @@
     #include "Player.h"
     #include "Team.h"
     #include "Server/MsgStrings.h"
    +#include "Lua/LuaRules.h"
     
     #ifdef DEDICATED
     #include <iostream>
    @@ -1214,8 +1215,8 @@
     		if (numActiveTeams[a] != 0)
     			++numActiveAllyTeams;
     
    -	if (numActiveAllyTeams <= 1)
    -	{
    +	bool gameOver = (numActiveAllyTeams <= 1);
    +	if (luaRules!=NULL && luaRules->IsGameOver(gameOver)) {
     		gameEndTime=SDL_GetTicks();
     		serverNet->SendSendPlayerStat();
     	}
    Index: rts/Lua/LuaRules.cpp
    ===================================================================
    --- rts/Lua/LuaRules.cpp	(revision 5850)
    +++ rts/Lua/LuaRules.cpp	(working copy)
    @@ -109,6 +109,7 @@
     		return;
     	}
     
    +	haveIsGameOver                 = HasCallIn("IsGameOver");
     	haveCommandFallback          = HasCallIn("CommandFallback");
     	haveAllowCommand             = HasCallIn("AllowCommand");
     	haveAllowUnitCreation        = HasCallIn("AllowUnitCreation");
    @@ -222,7 +223,9 @@
     
     bool CLuaRules::SyncedUpdateCallIn(const string& name)
     {
    -	if (name == "CommandFallback") {
    +	if (name == "IsGameOver") {
    +		haveIsGameOver                 = HasCallIn("IsGameOver");
    +	} else if (name == "CommandFallback") {
     		haveCommandFallback          = HasCallIn("CommandFallback");
     	} else if (name == "AllowCommand") {
     		haveAllowCommand             = HasCallIn("AllowCommand");
    @@ -265,6 +268,43 @@
     }
     
     
    +bool CLuaRules::IsGameOver(const bool gameOver)
    +{
    +	if (!haveIsGameOver) {
    +		return gameOver; // the call is not defined
    +	}
    +
    +	LUA_CALL_IN_CHECK(L);
    +	lua_checkstack(L, 8);
    +	static const LuaHashString cmdStr("IsGameOver");
    +	if (!cmdStr.GetGlobalFunc(L)) {
    +		return gameOver; // the call is not defined
    +	}
    +
    +	lua_pushboolean(L, gameOver);
    +
    +	// call the function
    +	if (!RunCallIn(cmdStr, 1, 1)) {
    +		return gameOver;
    +	}
    +
    +	// get the results
    +	const int args = lua_gettop(L);
    +	if (!lua_isboolean(L, -1)) {
    +		logOutput.Print("%s() bad return value (%i)\n",
    +				cmdStr.GetString().c_str(), args);
    +		lua_pop(L, 1);
    +		return gameOver;
    +	}
    +
    +	const bool retval = !!lua_toboolean(L, -1);
    +	lua_pop(L, 1);
    +
    +	// return 'true' to remove the command
    +	return retval;
    +}
    +
    +
     bool CLuaRules::CommandFallback(const CUnit* unit, const Command& cmd)
     {
     	if (!haveCommandFallback) {
    @@ -493,7 +533,7 @@
     
     	// get the results
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    @@ -533,7 +573,7 @@
     
     	// get the results
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    @@ -573,7 +613,7 @@
     
     	// get the results
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    @@ -649,7 +689,7 @@
     
     	// get the results
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    @@ -687,7 +727,7 @@
     
     	// get the results
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    @@ -815,7 +855,7 @@
     	}
     
     	const int args = lua_gettop(L);
    -	if ((args != 1) || !lua_isboolean(L, -1)) {
    +	if (!lua_isboolean(L, -1)) {
     		logOutput.Print("%s() bad return value (%i)\n",
     		                cmdStr.GetString().c_str(), args);
     		lua_pop(L, 1);
    Index: rts/Lua/LuaRules.h
    ===================================================================
    --- rts/Lua/LuaRules.h	(revision 5850)
    +++ rts/Lua/LuaRules.h	(working copy)
    @@ -43,6 +43,7 @@
     		bool SyncedUpdateCallIn(const string& name);
     		bool UnsyncedUpdateCallIn(const string& name);
     
    +		bool IsGameOver(const bool gameOver);
     		bool CommandFallback(const CUnit* unit, const Command& cmd);
     		bool BuilderTerraformComplete(const CUnit* unit, const CUnit* build);
     		bool AllowCommand(const CUnit* unit, const Command& cmd, bool fromSynced);
    @@ -105,6 +106,7 @@
     		static void CobCallback(int retCode, void* p1, void* p2);
     
     	private:
    +		bool haveIsGameOver;
     		bool haveCommandFallback;
     		bool haveAllowCommand;
     		bool haveAllowUnitCreation;
    
    patch file icon LuaCallins.patch (4,845 bytes) 2008-05-10 16:28 +
  • patch file icon LuaCallouts.patch (12,807 bytes) 2008-05-10 16:29 -
    Index: rts/Lua/LuaOpenGL.cpp
    ===================================================================
    --- rts/Lua/LuaOpenGL.cpp	(revision 5850)
    +++ rts/Lua/LuaOpenGL.cpp	(working copy)
    @@ -3404,6 +3404,16 @@
     				lua_pushboolean(L, true);
     			}
     		}
    +		else if (texture == "$shading") {
    +			glBindTexture(GL_TEXTURE_2D, readmap->GetShadingTexture());
    +			glEnable(GL_TEXTURE_2D);
    +			lua_pushboolean(L, true);
    +		}
    +		else if (texture == "$grass") {
    +			glBindTexture(GL_TEXTURE_2D, readmap->GetGrassShadingTexture());
    +			glEnable(GL_TEXTURE_2D);
    +			lua_pushboolean(L, true);
    +		}
     		else {
     			lua_pushboolean(L, false);
     		}
    @@ -3634,6 +3644,16 @@
     				HSTR_PUSH_NUMBER(L, "ysize", heightMapTexture.GetSizeY());
     			}
     		}
    +		else if (texture == "$shading") {
    +			lua_newtable(L);
    +			HSTR_PUSH_NUMBER(L, "xsize", gs->pwr2mapx);
    +			HSTR_PUSH_NUMBER(L, "ysize", gs->pwr2mapy);
    +		}
    +		else if (texture == "$grass") {
    +			lua_newtable(L);
    +			HSTR_PUSH_NUMBER(L, "xsize", 1024);
    +			HSTR_PUSH_NUMBER(L, "ysize", 1024);
    +		}
     	}
     	else {
     		const CNamedTextures::TexInfo* texInfo;
    @@ -3664,8 +3684,8 @@
     	if (tex == NULL) {
     		return 0;
     	}
    -	glBindTexture(GL_TEXTURE_2D, tex->id);
    -	glEnable(GL_TEXTURE_2D); // leave it bound and enabled
    +	glBindTexture(tex->target, tex->id);
    +	glEnable(tex->target); // leave it bound and enabled
     
     	const GLint xoff =   (GLint)luaL_checknumber(L, 2);
     	const GLint yoff =   (GLint)luaL_checknumber(L, 3);
    @@ -3673,11 +3693,13 @@
     	const GLint    y =   (GLint)luaL_checknumber(L, 5);
     	const GLsizei  w = (GLsizei)luaL_checknumber(L, 6);
     	const GLsizei  h = (GLsizei)luaL_checknumber(L, 7);
    -	const GLenum target = (GLenum)luaL_optnumber(L, 8, GL_TEXTURE_2D);
    +	const GLenum target = (GLenum)luaL_optnumber(L, 8, tex->target);
     	const GLenum level  = (GLenum)luaL_optnumber(L, 9, 0);
     
     	glCopyTexSubImage2D(target, level, xoff, yoff, x, y, w, h);
     
    +	if (tex->target != GL_TEXTURE_2D) {glDisable(tex->target);}
    +
     	return 0;
     }
     
    @@ -4232,6 +4254,7 @@
     		} else {
     			luaL_error(L, "Incorrect arguments to gl.LoadMatrix()");
     		}
    +		return 0;
     	}
     	else if (luaType == LUA_TTABLE) {
     		if (ParseFloatArray(L, matrix, 16) != 16) {
    @@ -4262,6 +4285,7 @@
     		} else {
     			luaL_error(L, "Incorrect arguments to gl.MultMatrix()");
     		}
    +		return 0;
     	}
     	else if (luaType == LUA_TTABLE) {
     		if (ParseFloatArray(L, matrix, 16) != 16) {
    Index: rts/Lua/LuaSyncedCtrl.cpp
    ===================================================================
    --- rts/Lua/LuaSyncedCtrl.cpp	(revision 5850)
    +++ rts/Lua/LuaSyncedCtrl.cpp	(working copy)
    @@ -59,6 +59,12 @@
     using namespace std;
     
     
    +static int heightMapx1;
    +static int heightMapx2;
    +static int heightMapz1;
    +static int heightMapz2;
    +
    +
     /******************************************************************************/
     /******************************************************************************/
     
    @@ -68,6 +74,7 @@
     bool LuaSyncedCtrl::inCreateFeature = false;
     bool LuaSyncedCtrl::inDestroyFeature = false;
     bool LuaSyncedCtrl::inGiveOrder = false;
    +bool LuaSyncedCtrl::inHeightMap = false;
     
     
     /******************************************************************************/
    @@ -164,11 +171,14 @@
     	REGISTER_LUA_CFUNC(GiveOrderArrayToUnitMap);
     	REGISTER_LUA_CFUNC(GiveOrderArrayToUnitArray);
     
    -
     	REGISTER_LUA_CFUNC(LevelHeightMap);
     	REGISTER_LUA_CFUNC(AdjustHeightMap);
     	REGISTER_LUA_CFUNC(RevertHeightMap);
     
    +	REGISTER_LUA_CFUNC(SetHeight);
    +	REGISTER_LUA_CFUNC(SetTerraform);
    +	REGISTER_LUA_CFUNC(HeightMapFunc);
    +
     	REGISTER_LUA_CFUNC(EditUnitCmdDesc);
     	REGISTER_LUA_CFUNC(InsertUnitCmdDesc);
     	REGISTER_LUA_CFUNC(RemoveUnitCmdDesc);
    @@ -2401,6 +2411,116 @@
     /******************************************************************************/
     /******************************************************************************/
     
    +int LuaSyncedCtrl::SetHeight(lua_State* L)
    +{
    +	if (!inHeightMap) {
    +		luaL_error(L, "SetHeight() can only be called in Spring.HeightMapFunc()");
    +	}
    +
    +	const int args = lua_gettop(L);
    +
    +	if (args != 3 || !lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3)) {
    +		luaL_error(L, "Incorrect arguments to Spring.SetHeight(x,z,h)");
    +	}
    +
    +	const float xl = (float)lua_tonumber(L, 1);
    +	const float zl = (float)lua_tonumber(L, 2);
    +	const float h  = (float)lua_tonumber(L, 3);
    +
    +	// quantize and clamp
    +	const int x = (int)max(0 , min(gs->mapx, (int)(xl / SQUARE_SIZE)));
    +	const int z = (int)max(0 , min(gs->mapy, (int)(zl / SQUARE_SIZE)));
    +
    +	const int index = (z * (gs->mapx + 1)) + x;
    +
    +	readmap->GetHeightmap()[index] = h;
    +
    +	//update RecalcArea()
    +	if (x<heightMapx1) heightMapx1 = x;
    +	if (x>heightMapx2) heightMapx2 = x;
    +	if (z<heightMapz1) heightMapz1 = z;
    +	if (z>heightMapz2) heightMapz2 = z;
    +
    +	return 0;
    +}
    +
    +
    +int LuaSyncedCtrl::SetTerraform(lua_State* L)
    +{
    +	if (!inHeightMap) {
    +		luaL_error(L, "SetTerraform() can only be called in Spring.HeightMapFunc()");
    +	}
    +
    +	const int args = lua_gettop(L);
    +
    +	if (args != 4 || !lua_isnumber(L, 1) || !lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4)) {
    +		luaL_error(L, "Incorrect arguments to Spring.SetTerraform(x,z,height,terraformScale)");
    +	}
    +
    +	const float xl = (float)lua_tonumber(L, 1);
    +	const float zl = (float)lua_tonumber(L, 2);
    +	const float h  = (float)lua_tonumber(L, 3);
    +	const float t  = (float)lua_tonumber(L, 3);
    +
    +	// quantize and clamp
    +	const int x = (int)max(0 , min(gs->mapx, (int)(xl / SQUARE_SIZE)));
    +	const int z = (int)max(0 , min(gs->mapy, (int)(zl / SQUARE_SIZE)));
    +
    +	const int index = (z * (gs->mapx + 1)) + x;
    +
    +	float& heightMap = readmap->GetHeightmap()[index];
    +	heightMap += (h - heightMap) * t;
    +
    +	//update RecalcArea()
    +	if (x<heightMapx1) heightMapx1 = x;
    +	if (x>heightMapx2) heightMapx2 = x;
    +	if (z<heightMapz1) heightMapz1 = z;
    +	if (z>heightMapz2) heightMapz2 = z;
    +
    +	return 0;
    +}
    +
    +
    +int LuaSyncedCtrl::HeightMapFunc(lua_State* L)
    +{
    +	if (mapDamage->disabled) {
    +		return 0;
    +	}
    +
    +	const int args = lua_gettop(L); // number of arguments
    +	if ((args < 1) || !lua_isfunction(L, 1)) {
    +		luaL_error(L, "Incorrect arguments to Spring.HeightMapFunc(func, ...)");
    +	}
    +
    +	if (inHeightMap) {
    +		luaL_error(L, "HeightMapFunc() recursion is not permitted");
    +	}
    +
    +	heightMapx1 = -1;
    +	heightMapx2 = gs->mapx;
    +	heightMapz1 = -1;
    +	heightMapz2 = gs->mapy;
    +
    +	inHeightMap = true;
    +	const int error = lua_pcall(L, (args-1), 0, 0);
    +	inHeightMap = false;
    +
    +	if (error != 0) {
    +		logOutput.Print("Spring.HeightMapFunc: error(%i) = %s",
    +		                error, lua_tostring(L, -1));
    +		lua_error(L);
    +	}
    +
    +	if (heightMapx1 != -1) {
    +		mapDamage->RecalcArea(heightMapx1, heightMapx2, heightMapz1, heightMapz2);
    +	}
    +	return 0;
    +}
    +
    +
    +/******************************************************************************/
    +/******************************************************************************/
    +
     int LuaSyncedCtrl::SetNoPause(lua_State* L)
     {
     	if (!FullCtrl()) {
    Index: rts/Lua/LuaSyncedCtrl.h
    ===================================================================
    --- rts/Lua/LuaSyncedCtrl.h	(revision 5850)
    +++ rts/Lua/LuaSyncedCtrl.h	(working copy)
    @@ -20,6 +20,7 @@
     		static bool inCreateFeature;
     		static bool inDestroyFeature;
     		static bool inGiveOrder;
    +		static bool inHeightMap;
     
     	private:
     		// all LuaHandleSynced
    @@ -95,6 +96,10 @@
     		static int AdjustHeightMap(lua_State* L);
     		static int RevertHeightMap(lua_State* L);
     
    +		static int SetHeight(lua_State* L);
    +		static int SetTerraform(lua_State* L);
    +		static int HeightMapFunc(lua_State* L);
    +
     		// LuaRules  (fullCtrl)
     		static int EditUnitCmdDesc(lua_State* L);
     		static int InsertUnitCmdDesc(lua_State* L);
    Index: rts/Lua/LuaSyncedRead.cpp
    ===================================================================
    --- rts/Lua/LuaSyncedRead.cpp	(revision 5850)
    +++ rts/Lua/LuaSyncedRead.cpp	(working copy)
    @@ -56,6 +56,7 @@
     #include "Sim/Units/CommandAI/LineDrawer.h"
     #include "Sim/Weapons/PlasmaRepulser.h"
     #include "Sim/Weapons/Weapon.h"
    +#include "Sim/Weapons/WeaponDefHandler.h"
     #include "System/myMath.h"
     #include "System/LogOutput.h"
     #include "System/TdfParser.h"
    @@ -139,6 +140,7 @@
     
     	REGISTER_LUA_CFUNC(GetPlayerInfo);
     	REGISTER_LUA_CFUNC(GetPlayerControlledUnit);
    +	REGISTER_LUA_CFUNC(GetPlayerStats);
     
     	REGISTER_LUA_CFUNC(GetTeamInfo);
     	REGISTER_LUA_CFUNC(GetTeamResources);
    @@ -190,6 +192,7 @@
     	REGISTER_LUA_CFUNC(GetUnitRadius);
     	REGISTER_LUA_CFUNC(GetUnitPosition);
     	REGISTER_LUA_CFUNC(GetUnitBasePosition);
    +	REGISTER_LUA_CFUNC(GetUnitVectors);
     	REGISTER_LUA_CFUNC(GetUnitDirection);
     	REGISTER_LUA_CFUNC(GetUnitHeading);
     	REGISTER_LUA_CFUNC(GetUnitVelocity);
    @@ -199,6 +202,7 @@
     	REGISTER_LUA_CFUNC(GetUnitIsTransporting);
     	REGISTER_LUA_CFUNC(GetUnitShieldState);
     	REGISTER_LUA_CFUNC(GetUnitWeaponState);
    +	REGISTER_LUA_CFUNC(GetUnitWeaponVectors);
     	REGISTER_LUA_CFUNC(GetUnitTravel);
     	REGISTER_LUA_CFUNC(GetUnitEstimatedPath);
     	REGISTER_LUA_CFUNC(GetUnitLosState);
    @@ -1247,6 +1251,31 @@
     }
     
     
    +int LuaSyncedRead::GetPlayerStats(lua_State* L)
    +{
    +	const int args = lua_gettop(L); // number of arguments
    +	if ((args != 1) || !lua_isnumber(L, 1)) {
    +		luaL_error(L, "Incorrect arguments to GetPlayerStats(playerID)");
    +	}
    +
    +	const CPlayer* player = ParsePlayer(L, __FUNCTION__, 1);
    +	if (player == NULL) {
    +		return 0;
    +	}
    +
    +	if (!IsAlliedTeam(player->team)) {
    +		return 0;
    +	}
    +
    +	lua_pushnumber(L, player->currentStats->mousePixels);
    +	lua_pushnumber(L, player->currentStats->mouseClicks);
    +	lua_pushnumber(L, player->currentStats->keyPresses);
    +	lua_pushnumber(L, player->currentStats->numCommands);
    +	lua_pushnumber(L, player->currentStats->unitCommands);
    +	return 5;
    +}
    +
    +
     int LuaSyncedRead::AreTeamsAllied(lua_State* L)
     {
     	const int args = lua_gettop(L); // number of arguments
    @@ -2556,7 +2585,29 @@
     	return 3;
     }
     
    +int LuaSyncedRead::GetUnitVectors(lua_State* L)
    +{
    +	CUnit* unit = ParseInLosUnit(L, __FUNCTION__, 1);
    +	if (unit == NULL) {
    +		return 0;
    +	}
     
    +#define PACK_VECTOR(n) \
    +	HSTR_PUSH(L, #n);           \
    +	lua_newtable(L);            \
    +	lua_pushnumber(L, 1); lua_pushnumber(L, unit-> n .x); lua_rawset(L, -3); \
    +	lua_pushnumber(L, 2); lua_pushnumber(L, unit-> n .y); lua_rawset(L, -3); \
    +	lua_pushnumber(L, 3); lua_pushnumber(L, unit-> n .z); lua_rawset(L, -3); \
    +	lua_rawset(L, -3)
    +
    +	PACK_VECTOR(frontdir);
    +	PACK_VECTOR(updir);
    +	PACK_VECTOR(rightdir);
    +
    +	return 3;
    +}
    +
    +
     int LuaSyncedRead::GetUnitDirection(lua_State* L)
     {
     	CUnit* unit = ParseInLosUnit(L, __FUNCTION__, 1);
    @@ -2704,6 +2755,39 @@
     }
     
     
    +int LuaSyncedRead::GetUnitWeaponVectors(lua_State* L)
    +{
    +	CUnit* unit = ParseAllyUnit(L, __FUNCTION__, 1);
    +	if (unit == NULL) {
    +		return 0;
    +	}
    +	const int args = lua_gettop(L); // number of arguments
    +	if ((args < 2) || !lua_isnumber(L, 2)) {
    +		luaL_error(L, "Incorrect arguments to GetUnitWeaponVectors(unitID,weaponNum)");
    +	}
    +	const int weaponNum = (int)lua_tonumber(L, 2);
    +	if ((weaponNum < 0) || (weaponNum >= unit->weapons.size())) {
    +		return 0;
    +	}
    +	const float3& weaponPos = unit->weapons[weaponNum]->weaponMuzzlePos;
    +	float3& weaponDir = unit->weapons[weaponNum]->wantedDir;
    +	const string& wtype = unit->weapons[weaponNum]->weaponDef->type;
    +
    +	if (wtype=="StarburstLauncher" || wtype=="TorpedoLauncher" || wtype=="MissileLauncher")
    +		weaponDir = unit->weapons[weaponNum]->weaponDir;
    +
    +	lua_pushnumber(L, weaponPos.x);
    +	lua_pushnumber(L, weaponPos.y);
    +	lua_pushnumber(L, weaponPos.z);
    +
    +	lua_pushnumber(L, weaponDir.x);
    +	lua_pushnumber(L, weaponDir.y);
    +	lua_pushnumber(L, weaponDir.z);
    +
    +	return 6;
    +}
    +
    +
     int LuaSyncedRead::GetUnitTravel(lua_State* L)
     {
     	CUnit* unit = ParseAllyUnit(L, __FUNCTION__, 1);
    Index: rts/Lua/LuaSyncedRead.h
    ===================================================================
    --- rts/Lua/LuaSyncedRead.h	(revision 5850)
    +++ rts/Lua/LuaSyncedRead.h	(working copy)
    @@ -51,6 +51,7 @@
     
     		static int GetPlayerInfo(lua_State* L); // no name for synced scripts
     		static int GetPlayerControlledUnit(lua_State* L);
    +		static int GetPlayerStats(lua_State* L);
     
     		static int GetTeamInfo(lua_State* L);
     		static int GetTeamResources(lua_State* L);
    @@ -102,6 +103,7 @@
     		static int GetUnitRadius(lua_State* L);
     		static int GetUnitPosition(lua_State* L);
     		static int GetUnitBasePosition(lua_State* L);
    +		static int GetUnitVectors(lua_State* L);
     		static int GetUnitDirection(lua_State* L);
     		static int GetUnitHeading(lua_State* L);
     		static int GetUnitVelocity(lua_State* L);
    @@ -111,6 +113,7 @@
     		static int GetUnitIsTransporting(lua_State* L);
     		static int GetUnitShieldState(lua_State* L);
     		static int GetUnitWeaponState(lua_State* L);
    +		static int GetUnitWeaponVectors(lua_State* L);
     		static int GetUnitTravel(lua_State* L);
     		static int GetUnitEstimatedPath(lua_State* L);
     
    
    patch file icon LuaCallouts.patch (12,807 bytes) 2008-05-10 16:29 +
  • patch file icon rendering.patch (90,543 bytes) 2008-05-10 16:29 -
    Index: rts/Map/SM3/terrain/Lightcalc.cpp
    ===================================================================
    --- rts/Map/SM3/terrain/Lightcalc.cpp	(revision 5850)
    +++ rts/Map/SM3/terrain/Lightcalc.cpp	(working copy)
    @@ -33,6 +33,7 @@
     #include "Textures.h"
     #include "Lightcalc.h"
     #include "Map/ReadMap.h"
    +#include "Rendering/GL/myGL.h"
     
     #include <SDL.h>
     #include <IL/il.h>
    @@ -171,7 +172,7 @@
     
     	SaveImage ("lightmap.png", 4, IL_UNSIGNED_BYTE, w,w, shadingTexData);
     
    -	gluBuild2DMipmaps(GL_TEXTURE_2D, 4, w,w, GL_RGBA, GL_UNSIGNED_BYTE, shadingTexData);
    +	glBuildMipmaps(GL_TEXTURE_2D, 4, w,w, GL_RGBA, GL_UNSIGNED_BYTE, shadingTexData);
     	delete[] shadingTexData;
     
     	id = shadingTex;
    Index: rts/Map/SMF/BFGroundTextures.cpp
    ===================================================================
    --- rts/Map/SMF/BFGroundTextures.cpp	(revision 5850)
    +++ rts/Map/SMF/BFGroundTextures.cpp	(working copy)
    @@ -9,11 +9,19 @@
     #include "Platform/errorhandler.h"
     #include "SmfReadMap.h"
     #include "mmgr.h"
    +#include "FastMath.h"
     
     using namespace std;
     
     CBFGroundTextures::CBFGroundTextures(CSmfReadMap* rm)
     {
    +	usePBO = false;
    +	if (GLEW_EXT_pixel_buffer_object && rm->usePBO) {
    +		glGenBuffers(30, pboIDs);
    +		currentPBO=0;
    +		usePBO = true;
    +	}
    +
     	CFileHandler* ifs = rm->ifs;
     	map = rm;
     
    @@ -98,7 +106,6 @@
     			GroundSquare* square = &squares[y * numBigTexX + x];
     			square->texLevel = 1;
     			square->lastUsed = -100;
    -
     			LoadSquare(x, y, 2);
     		}
     	}
    @@ -111,6 +118,9 @@
     	delete[] squares;
     	delete[] tileMap;
     	delete[] tiles;
    +	if (usePBO) {
    +		glDeleteBuffers(30,pboIDs);
    +	}
     }
     
     
    @@ -126,7 +136,7 @@
     	static const int heightDataX = gs->mapx + 1;
     	static const int bigTexW = (gs->mapx << 3) / numBigTexX;
     	static const int bigTexH = (gs->mapy << 3) / numBigTexY;
    -	static const float bigTexSquareRadius = sqrt(float(bigTexW * bigTexW + bigTexH * bigTexH));
    +	static const float bigTexSquareRadius = fastmath::sqrt(float(bigTexW * bigTexW + bigTexH * bigTexH));
     
     	const int x = btx * bigTexW + (bigTexW >> 1);
     	const int y = bty * bigTexH + (bigTexH >> 1);
    @@ -160,7 +170,7 @@
     
     			float dx = cam2->pos.x - x * bigSquareSize * SQUARE_SIZE - 64 * SQUARE_SIZE;
     			dx = max(0.0f, float(fabs(dx) - 64.0f * SQUARE_SIZE));
    -			float dist = sqrt(dx * dx + dy * dy);
    +			float dist = fastmath::sqrt(dx * dx + dy * dy);
     
     			if (square->lastUsed < gs->frameNum - 60)
     				dist = 8000;
    @@ -204,11 +214,29 @@
     
     void CBFGroundTextures::LoadSquare(int x, int y, int level)
     {
    +	int size = 1024 >> level;
    +
    +	GLubyte* buf=NULL; bool usedPBO=false;
    +
    +	if (usePBO) {
    +		if (currentPBO > 29) currentPBO=0;
    +		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboIDs[currentPBO++]);
    +
    +		glBufferData(GL_PIXEL_UNPACK_BUFFER, size * size / 2, 0, GL_STREAM_DRAW);
    +
    +		//map the buffer object into client's memory
    +		buf = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
    +		usedPBO = true;
    +	}
    +
    +	if(buf==NULL) {
    +		buf = SAFE_NEW GLubyte[size * size / 2];
    +		usedPBO = false;
    +	}
    +
     	GroundSquare* square = &squares[y * numBigTexX + x];
     	square->texLevel = level;
     
    -	int size = 1024 >> level;
    -	char* buf = SAFE_NEW char[size * size / 2];
     	int numblocks = 8 / (1 << level);
     
     	for (int y1 = 0; y1 < 32; y1++) {
    @@ -217,10 +245,11 @@
     
     			for (int yt = 0; yt < numblocks; yt++) {
     				for (int xt = 0; xt < numblocks; xt++) {
    -					char* sbuf = &tile[(xt + yt * numblocks) * 8];
    -					char* dbuf = &buf[(x1 * numblocks+xt + (y1 * numblocks + yt) * (numblocks * 32)) * 8];
    +					GLfloat* sbuf = (GLfloat*)&tile[(xt + yt * numblocks) * 8];
    +					GLfloat* dbuf = (GLfloat*)&buf[(x1 * numblocks + xt + (y1 * numblocks + yt) * (numblocks * 32)) * 8];
     
    -					for (int i = 0; i < 8; i++) {
    +					//copy 4 bytes at once
    +					for (int i = 0; i < 2; i++) {
     						dbuf[i] = sbuf[i];
     					}
     				}
    @@ -234,12 +263,16 @@
     	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    +	if (map->anisotropy != 0.0f)
    +		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, map->anisotropy);
     
    -	if (map->anisotropy != 0.0f) {
    -		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, map->anisotropy);
    +	if (usedPBO) {
    +		glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
    +		glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, size, size, 0, size * size / 2, 0);
    +		glBufferData(GL_PIXEL_UNPACK_BUFFER, 0, 0, GL_STREAM_DRAW); //free it
    +		glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    +	}else{
    +		glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, size, size, 0, size * size / 2, buf);
    +		delete[] buf;
     	}
    -
    -	glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, size, size, 0, size * size / 2, buf);
    -
    -	delete[] buf;
     }
    Index: rts/Map/SMF/BFGroundTextures.h
    ===================================================================
    --- rts/Map/SMF/BFGroundTextures.h	(revision 5850)
    +++ rts/Map/SMF/BFGroundTextures.h	(working copy)
    @@ -52,6 +52,11 @@
     	int tileMapXSize;
     	int tileMapYSize;
     
    +	// use Pixel Buffer Objects for async. uploading (DMA)?
    +	bool usePBO;
    +	GLuint pboIDs[30];
    +	int currentPBO;
    +
     	float anisotropy;
     
     	inline bool TexSquareInView(int, int);
    Index: rts/Map/SMF/SmfReadMap.cpp
    ===================================================================
    --- rts/Map/SMF/SmfReadMap.cpp	(revision 5850)
    +++ rts/Map/SMF/SmfReadMap.cpp	(working copy)
    @@ -34,6 +34,7 @@
     	PrintLoadMsg("Opening map file");
     
     	ConfigureAnisotropy();
    +	usePBO = !!configHandler.GetInt("UsePBO", 1);
     
     	for(int a=0;a<1024;++a){
     		for(int b=0;b<3;++b){
    @@ -104,7 +105,7 @@
     	glBindTexture(GL_TEXTURE_2D, detailTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
     	if (anisotropy != 0.0f) {
     		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
     	}
    Index: rts/Map/SMF/SmfReadMap.h
    ===================================================================
    --- rts/Map/SMF/SmfReadMap.h	(revision 5850)
    +++ rts/Map/SMF/SmfReadMap.h	(working copy)
    @@ -36,6 +36,7 @@
     	MapHeader header;
     	CFileHandler *ifs;
     
    +	bool usePBO;
     	float anisotropy;
     
     	unsigned char waterHeightColors[1024*4];
    Index: rts/Rendering/Env/AdvSky.cpp
    ===================================================================
    --- rts/Rendering/Env/AdvSky.cpp	(revision 5850)
    +++ rts/Rendering/Env/AdvSky.cpp	(working copy)
    @@ -246,7 +246,7 @@
     	glBindTexture(GL_TEXTURE_2D, cdtex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_LUMINANCE ,256, 256, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_LUMINANCE ,256, 256, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
     
     	unsigned char randDetailMatrix[32*32];
     	glGenTextures(12, detailTextures);
    @@ -290,7 +290,7 @@
     	glBindTexture(GL_TEXTURE_2D, skyTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, skytex[0][0]);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, skytex[0][0]);
     	delete[] skytex;
     
     	unsigned char skytex2[256][256][4];
    @@ -311,7 +311,7 @@
     	glBindTexture(GL_TEXTURE_2D, skyDot3Tex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 256, GL_RGBA, GL_UNSIGNED_BYTE, skytex2[0][0]);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 256, GL_RGBA, GL_UNSIGNED_BYTE, skytex2[0][0]);
     
     	for(int a=0;a<CLOUD_DETAIL;a++){
     		CreateRandMatrix(randMatrix[a],1-a*0.03f);
    @@ -660,7 +660,7 @@
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);
     
     	for(int y=0;y<4;++y){
     		for(int x=0;x<32;++x){
    Index: rts/Rendering/Env/AdvTreeDrawer.cpp
    ===================================================================
    --- rts/Rendering/Env/AdvTreeDrawer.cpp	(revision 5850)
    +++ rts/Rendering/Env/AdvTreeDrawer.cpp	(working copy)
    @@ -158,7 +158,7 @@
     				SetArray(TEX_LEAF_END_X1+xdif  ,TEX_LEAF_END_Y4+ydif  ,base-side*width+float3(0,height,0));
     				SetArray(TEX_LEAF_END_X1+xdif  ,TEX_LEAF_START_Y4+ydif,base-side*width);
     			}
    -			glNewList(td->trees[y*treesX+x].farDisplist,GL_COMPILE);
    +			glNewList(tss->farDisplist,GL_COMPILE);
     			va->DrawArrayT(GL_QUADS);
     			glEndList();
     		}
    Index: rts/Rendering/Env/AdvTreeGenerator.cpp
    ===================================================================
    --- rts/Rendering/Env/AdvTreeGenerator.cpp	(revision 5850)
    +++ rts/Rendering/Env/AdvTreeGenerator.cpp	(working copy)
    @@ -58,7 +58,7 @@
     	glBindTexture(GL_TEXTURE_2D, leafTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
     
     	CreateLeafTex(leafTex,256,0,tree);
     	CreateLeafTex(leafTex,512,0,tree);
    Index: rts/Rendering/Env/BaseSky.cpp
    ===================================================================
    --- rts/Rendering/Env/BaseSky.cpp	(revision 5850)
    +++ rts/Rendering/Env/BaseSky.cpp	(working copy)
    @@ -13,6 +13,7 @@
     
     CBaseSky::CBaseSky(void)
     {
    +	wireframe = false;
     }
     
     CBaseSky::~CBaseSky(void)
    Index: rts/Rendering/Env/BaseSky.h
    ===================================================================
    --- rts/Rendering/Env/BaseSky.h	(revision 5850)
    +++ rts/Rendering/Env/BaseSky.h	(working copy)
    @@ -21,6 +21,8 @@
     	bool dynamicSky;
     	float cloudDensity;
     
    +	bool wireframe;
    +
     	float fogStart;
     	float3 skyColor;
     	float3 sunColor;
    Index: rts/Rendering/Env/BasicSky.cpp
    ===================================================================
    --- rts/Rendering/Env/BasicSky.cpp	(revision 5850)
    +++ rts/Rendering/Env/BasicSky.cpp	(working copy)
    @@ -75,6 +75,7 @@
     	glGetError();
     	displist=glGenLists(1);
     	glNewList(displist, GL_COMPILE);
    +
     	glDisable(GL_TEXTURE_2D);
     	glDisable(GL_LIGHTING);
     	glDisable(GL_ALPHA_TEST);
    @@ -245,6 +246,8 @@
     	glDisable(GL_DEPTH_TEST);
     	glEnable(GL_BLEND);
     
    +	if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    +
     	glPushMatrix();
     //	glTranslatef(camera->pos.x,camera->pos.y,camera->pos.z);
     	CMatrix44f m(camera->pos,sundir1,UpVector,sundir2);
    @@ -257,8 +260,6 @@
     		glTranslatef((gs->frameNum%20000)*0.00005f+modCamera.x*0.000025f,modCamera.z*0.000025f,0);
     	glMatrixMode(GL_MODELVIEW);
     
    -
    -
     	glCallList(displist);
     
     	glMatrixMode(GL_TEXTURE);						// Select The Projection Matrix
    @@ -267,6 +268,8 @@
     
     	glPopMatrix();
     
    +	if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    +
     	glEnable(GL_DEPTH_TEST);
     	glDisable(GL_BLEND);
     	if (gu->drawFog) {
    @@ -338,7 +341,7 @@
     	glBindTexture(GL_TEXTURE_2D, skyTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, skytex[0][0]);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, skytex[0][0]);
     //	delete[] skytex;
     
     	for(y=0;y<256;y++){
    @@ -359,7 +362,7 @@
     	glBindTexture(GL_TEXTURE_2D, skyDot3Tex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 256, GL_RGBA, GL_UNSIGNED_BYTE, skytex2[0][0]);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 256, GL_RGBA, GL_UNSIGNED_BYTE, skytex2[0][0]);
     
     	for(int a=0;a<CLOUD_DETAIL;a++){
     		CreateRandMatrix(randMatrix[a],1-a*0.03f);
    @@ -685,7 +688,7 @@
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);
     
     	for(int y=0;y<2;++y){
     		for(int x=0;x<32;++x){
    Index: rts/Rendering/Env/BasicTreeDrawer.cpp
    ===================================================================
    --- rts/Rendering/Env/BasicTreeDrawer.cpp	(revision 5850)
    +++ rts/Rendering/Env/BasicTreeDrawer.cpp	(working copy)
    @@ -246,7 +246,7 @@
     		glCallList(tss->farDisplist);
     	}
     
    -	if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance){	//midle distance trees
    +	if(dist<SQUARE_SIZE*TREE_SQUARE_SIZE*treeDistance){	//middle distance trees
     		tss->lastSeen=gs->frameNum;
     		if(!tss->displist){
     			va=GetVertexArray();
    @@ -376,52 +376,7 @@
     	glBindTexture(GL_TEXTURE_2D, texnum);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	int mipnum=0;
    -	glTexImage2D(GL_TEXTURE_2D,mipnum,GL_RGBA8 ,xsize, ysize,0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    -	while(xsize!=1 || ysize!=1){
    -		mipnum++;
    -		if(xsize!=1)
    -			xsize/=2;
    -		if(ysize!=1)
    -			ysize/=2;
    -		for(int y=0;y<ysize;++y){
    -			for(int x=0;x<xsize;++x){
    -/*				for(int a=0;a<3;a++){
    -					int temp=0;
    -					int num=0;
    -					if(data[(y*2*xsize*2+x*2)*4+3]){
    -						temp+=data[(y*2*xsize*2+x*2)*4+a];
    -						num++;
    -					}
    -					if(data[((y*2+1)*xsize*2+x*2)*4+3]){
    -						temp+=data[((y*2+1)*xsize*2+x*2)*4+a];
    -						num++;
    -					}
    -					if(data[((y*2)*xsize*2+x*2+1)*4+3]){
    -						temp+=data[((y*2)*xsize*2+x*2+1)*4+a];
    -						num++;
    -					}
    -					if(data[((y*2+1)*xsize*2+x*2+1)*4+3]){
    -						temp+=data[((y*2+1)*xsize*2+x*2+1)*4+a];
    -						num++;
    -					}
    -					if(num>1)
    -						temp/=num;
    -					data[(y*xsize+x)*4+a]=temp;
    -				}
    -*/			data[(y*xsize+x)*4+0]=(data[(y*2*xsize*2+x*2)*4+0]+data[((y*2+1)*xsize*2+x*2)*4+0]+data[(y*2*xsize*2+x*2+1)*4+0]+data[((y*2+1)*xsize*2+x*2+1)*4+0])/4;
    -				data[(y*xsize+x)*4+1]=(data[(y*2*xsize*2+x*2)*4+1]+data[((y*2+1)*xsize*2+x*2)*4+1]+data[(y*2*xsize*2+x*2+1)*4+1]+data[((y*2+1)*xsize*2+x*2+1)*4+1])/4;
    -				data[(y*xsize+x)*4+2]=(data[(y*2*xsize*2+x*2)*4+2]+data[((y*2+1)*xsize*2+x*2)*4+2]+data[(y*2*xsize*2+x*2+1)*4+2]+data[((y*2+1)*xsize*2+x*2+1)*4+2])/4;
    -				data[(y*xsize+x)*4+3]=(data[(y*2*xsize*2+x*2)*4+3]+data[((y*2+1)*xsize*2+x*2)*4+3]+data[(y*2*xsize*2+x*2+1)*4+3]+data[((y*2+1)*xsize*2+x*2+1)*4+3])/4;
    -				if(data[(y*xsize+x)*4+3]>=127){
    -					data[(y*xsize+x)*4+3]=255;
    -				} else {
    -					data[(y*xsize+x)*4+3]=0;
    -				}
    -			}
    -		}
    -		glTexImage2D(GL_TEXTURE_2D,mipnum,GL_RGBA8 ,xsize, ysize,0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    -	}
    +	glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, data);
     }
     
     void CBasicTreeDrawer::ResetPos(const float3& pos)
    Index: rts/Rendering/Env/BasicWater.cpp
    ===================================================================
    --- rts/Rendering/Env/BasicWater.cpp	(revision 5850)
    +++ rts/Rendering/Env/BasicWater.cpp	(working copy)
    @@ -26,7 +26,7 @@
     	glBindTexture(GL_TEXTURE_2D, texture);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,pic.xsize, pic.ysize, GL_RGBA, GL_UNSIGNED_BYTE, pic.mem);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,pic.xsize, pic.ysize, GL_RGBA, GL_UNSIGNED_BYTE, pic.mem);
     
     	displist=0;
     
    Index: rts/Rendering/Env/DynWater.cpp
    ===================================================================
    --- rts/Rendering/Env/DynWater.cpp	(revision 5850)
    +++ rts/Rendering/Env/DynWater.cpp	(working copy)
    @@ -8,6 +8,7 @@
     #include "Map/MapInfo.h"
     #include "Map/ReadMap.h"
     #include "LogOutput.h"
    +#include "bitops.h"
     #include "Map/BaseGroundDrawer.h"
     #include "Rendering/Env/BaseSky.h"
     #include "Rendering/UnitModels/UnitDrawer.h"
    @@ -80,18 +81,20 @@
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
     	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA16F_ARB ,64, 64, 0,GL_RGBA, GL_FLOAT, temp);
     
    -	unsigned char* scrap=SAFE_NEW unsigned char[256*256*4];
     	CBitmap foam;
    -	if (!foam.Load("bitmaps/foam.jpg") || foam.xsize != 256 || foam.ysize != 256)
    -		throw content_error("Could not load foam from file bitmaps/foam.jpg");
    -	for(int a=0;a<256*256;++a)
    +	if (!foam.Load(mapInfo->water.foamTexture))
    +		throw content_error("Could not load foam from file " + mapInfo->water.foamTexture);
    +	if (count_bits_set(foam.xsize)!=1 || count_bits_set(foam.ysize)!=1)
    +		throw content_error("Foam texture not power of two!");
    +	unsigned char* scrap=SAFE_NEW unsigned char[foam.xsize*foam.ysize*4];
    +	for(int a=0;a<foam.xsize*foam.ysize;++a)
     		scrap[a]=foam.mem[a*4];
     
     	glGenTextures(1, &foamTex);
     	glBindTexture(GL_TEXTURE_2D, foamTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE,256, 256, GL_LUMINANCE, GL_UNSIGNED_BYTE, scrap);
    +	glBuildMipmaps(GL_TEXTURE_2D, GL_LUMINANCE,foam.xsize,foam.ysize, GL_LUMINANCE, GL_UNSIGNED_BYTE, scrap);
     
     	delete[] scrap;
     
    @@ -331,7 +334,7 @@
     
     	glDisable( GL_FRAGMENT_PROGRAM_ARB );
     	glDisable( GL_VERTEX_PROGRAM_ARB );
    -
    +/*
     	glBindTexture(GL_TEXTURE_2D, 0);
     	glActiveTextureARB(GL_TEXTURE1_ARB);
     	glBindTexture(GL_TEXTURE_2D,0);
    @@ -348,6 +351,7 @@
     	glActiveTextureARB(GL_TEXTURE7_ARB);
     	glBindTexture(GL_TEXTURE_2D,0);
     	glActiveTextureARB(GL_TEXTURE0_ARB);
    +	*/
     }
     
     void CDynWater::UpdateWater(CGame* game)
    Index: rts/Rendering/Env/GrassDrawer.cpp
    ===================================================================
    --- rts/Rendering/Env/GrassDrawer.cpp	(revision 5850)
    +++ rts/Rendering/Env/GrassDrawer.cpp	(working copy)
    @@ -103,7 +103,7 @@
     	glBindTexture(GL_TEXTURE_2D, grassBladeTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 64, GL_RGBA, GL_UNSIGNED_BYTE, gbt);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,256, 64, GL_RGBA, GL_UNSIGNED_BYTE, gbt);
     
     	CreateFarTex();
     
    @@ -759,7 +759,7 @@
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,1024*sizeMod, 64*sizeMod, GL_RGBA, GL_UNSIGNED_BYTE, buf);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,1024*sizeMod, 64*sizeMod, GL_RGBA, GL_UNSIGNED_BYTE, buf);
     
     	delete[] buf;
     	delete[] buf2;
    Index: rts/Rendering/GL/myGL.cpp
    ===================================================================
    --- rts/Rendering/GL/myGL.cpp	(revision 5850)
    +++ rts/Rendering/GL/myGL.cpp	(working copy)
    @@ -13,15 +13,16 @@
     #include "FPUCheck.h"
     #include <SDL.h>
     #include "mmgr.h"
    +#include "System/GlobalStuff.h"
     
     #include "IFramebuffer.h"
     
     using namespace std;
     
     
    -static CVertexArray* vertexArray1 = 0;
    -static CVertexArray* vertexArray2 = 0;
    -static CVertexArray* currentVertexArray = 0;
    +static CVertexArray* vertexArray1 = NULL;
    +static CVertexArray* vertexArray2 = NULL;
    +static CVertexArray* currentVertexArray = NULL;
     
     static GLuint startupTexture = 0;
     
    @@ -56,6 +57,24 @@
     	logOutput.Print("GL:   %s\n", glGetString(GL_RENDERER));
     	logOutput.Print("GLEW: %s\n", glewGetString(GLEW_VERSION));
     
    +	/* Get available fullscreen/hardware modes */
    +/*
    +	SDL_Rect **modes=SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_OPENGL|SDL_RESIZABLE);
    +
    +	if (modes == (SDL_Rect **)0) {
    +		logOutput.Print("SDL_ListModes: No modes available!\n");
    +	}else if (modes == (SDL_Rect **)-1) {
    +		logOutput.Print("SDL_ListModes: Resolution is restricted.\n");
    +	}else{
    +		char buffer[512];
    +		unsigned char n = 0;
    +		for(int i=0;modes[i];++i) {
    +			n += SNPRINTF(&buffer[n], 512-n, "%dx%d, ", modes[i]->w, modes[i]->h);
    +		}
    +		logOutput.Print("SDL_ListModes: %s\n",buffer);
    +	}
    +*/
    +
     	if(!GLEW_ARB_multitexture || !GLEW_ARB_texture_env_combine){
     		handleerror(0,"Needed extension GL_ARB_texture_env_combine not found","Update drivers",0);
     		exit(0);
    @@ -83,10 +102,41 @@
     {
     	delete vertexArray1;
     	delete vertexArray2;
    +}
     
    +/******************************************************************************/
    +
    +void glBuildMipmaps(const GLenum target,GLint internalFormat,const GLsizei width,const GLsizei height,const GLenum format,const GLenum type,const void *data)
    +{
    +	if (gu->compressTextures) {
    +		switch ( internalFormat ) {
    +			case 3:
    +			case GL_RGB8 :
    +			case GL_RGB :   internalFormat = GL_COMPRESSED_RGB_ARB; break;
    +			
    +			case 4:
    +			case GL_RGBA8 :
    +			case GL_RGBA : internalFormat = GL_COMPRESSED_RGBA_ARB; break;
    +			
    +			case GL_LUMINANCE: internalFormat = GL_COMPRESSED_LUMINANCE_ARB; break;
    +		}
    +	}
    +	
    +	// create mipmapped texture
    +	if (glGenerateMipmapEXT) {
    +	//if (GLEW_EXT_framebuffer_object) { // Hurray (again), ATi only supports half of the extension
    +		// newest method
    +		glTexImage2D(target, 0, internalFormat, width, height, 0, format, type, data);
    +		glGenerateMipmapEXT(GL_TEXTURE_2D);
    +	}else if (GLEW_VERSION_1_4) {
    +		// This required GL-1.4
    +		// instead of using glu, we rely on glTexImage2D to create the Mipmaps.
    +		glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,true);
    +		glTexImage2D(target, 0, internalFormat, width, height, 0, format, type, data);
    +	} else
    +		gluBuild2DMipmaps(target, internalFormat, width, height, format, type, data);
     }
     
    -
     /******************************************************************************/
     
     static void AppendStringVec(vector<string>& dst, const vector<string>& src)
    Index: rts/Rendering/GL/myGL.h
    ===================================================================
    --- rts/Rendering/GL/myGL.h	(revision 5850)
    +++ rts/Rendering/GL/myGL.h	(working copy)
    @@ -27,9 +27,28 @@
     	glTranslatef(v.x,v.y,v.z);
     }
     
    +inline void glSecondaryColorf3(const float3& v)
    +{
    +	glSecondaryColor3f(v.x,v.y,v.z);
    +}
    +
    +inline void glColorf4(const float3& v, const float& alpha)
    +{
    +	glColor4f(v.x,v.y,v.z,alpha);
    +}
    +
    +inline void glUniformf3(const GLint& location, const float3 &v)
    +{
    +	glUniform3f(location, v.x,v.y,v.z);
    +}
    +
    +
    +void glBuildMipmaps(const GLenum target,GLint internalFormat,const GLsizei width,const GLsizei height,const GLenum format,const GLenum type,const void *data);
    +
     void LoadStartPicture(const std::string& sidePref);
     void PrintLoadMsg(const char* text, bool swapbuffers = true);
     void UnloadStartPicture();
    +
     bool ProgramStringIsNative(GLenum target, const char* filename);
     unsigned int LoadVertexProgram(const char* filename);
     unsigned int LoadFragmentProgram(const char* filename);
    Index: rts/Rendering/glFont.cpp
    ===================================================================
    --- rts/Rendering/glFont.cpp	(revision 5850)
    +++ rts/Rendering/glFont.cpp	(working copy)
    @@ -14,16 +14,20 @@
     
     using namespace std;
     
    -//////////////////////////////////////////////////////////////////////
    -// Construction/Destruction
    -//////////////////////////////////////////////////////////////////////
    +/*******************************************************************************/
    +/*******************************************************************************/
     
     CglFont *font, *smallFont;
     
    +#define GLYPH_MARGIN 3 // margin between glyphs in texture-atlas
    +
     class texture_size_exception : public std::exception
     {
     };
     
    +/*******************************************************************************/
    +/*******************************************************************************/
    +
     /**
      * A utility class for CglFont which collects all glyphs of
      * a font into one square luminance/alpha texture.
    @@ -82,15 +86,15 @@
     	}
     	outX = curX; outY = curY;
     
    -	curX += bmp.width + 1;		// leave one pixel space between each glyph
    -	cur += 2*(bmp.width + 1);
    +	curX += bmp.width + GLYPH_MARGIN;	// leave one pixel space between each glyph
    +	cur  += 2*(bmp.width + GLYPH_MARGIN); 	// 2channels (luminance and alpha))
     	curHeight = max(curHeight, bmp.rows);
     }
     
     void CFontTextureRenderer::BreakLine()
     {
     	curX = 0;
    -	curY += curHeight;
    +	curY += curHeight + GLYPH_MARGIN;
     	curHeight = 0;
     
     	if (curY >= height)
    Index: rts/Rendering/GroundDecalHandler.cpp
    ===================================================================
    --- rts/Rendering/GroundDecalHandler.cpp	(revision 5850)
    +++ rts/Rendering/GroundDecalHandler.cpp	(working copy)
    @@ -49,7 +49,7 @@
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
     //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, buf);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,512, 512, GL_RGBA, GL_UNSIGNED_BYTE, buf);
     
     	scarFieldX=gs->mapx/32;
     	scarFieldY=gs->mapy/32;
    Index: rts/Rendering/InMapDraw.cpp
    ===================================================================
    --- rts/Rendering/InMapDraw.cpp	(revision 5850)
    +++ rts/Rendering/InMapDraw.cpp	(working copy)
    @@ -124,7 +124,7 @@
     	glBindTexture(GL_TEXTURE_2D, texture);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]);
    +	glBuildMipmaps(GL_TEXTURE_2D, GL_RGBA8, 128, 64, GL_RGBA, GL_UNSIGNED_BYTE, tex[0]);
     
     	blippSound=sound->GetWaveId("sounds/beep6.wav");
     }
    Index: rts/Rendering/Textures/Bitmap.cpp
    ===================================================================
    --- rts/Rendering/Textures/Bitmap.cpp	(revision 5850)
    +++ rts/Rendering/Textures/Bitmap.cpp	(working copy)
    @@ -343,14 +343,7 @@
     	{
     		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
     
    -		// create mipmapped texture
    -		if (GLEW_VERSION_1_4) {
    -			// This required GL-1.4
    -			// instead of using glu, we rely on glTexImage2D to create the Mipmaps.
    -			glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,true);
    -			glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8 ,xsize, ysize, 0,GL_RGBA, GL_UNSIGNED_BYTE, mem);
    -		} else
    -			gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize,GL_RGBA, GL_UNSIGNED_BYTE, mem);
    +		glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize,GL_RGBA, GL_UNSIGNED_BYTE, mem);
     	}
     	else
     	{
    @@ -380,6 +373,7 @@
     	case nv_dds::TextureFlat:    // 1D, 2D, and rectangle textures
     		glEnable(GL_TEXTURE_2D);
     		glBindTexture(GL_TEXTURE_2D, texobj);
    +		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
     		if(!ddsimage->upload_texture2D()) {
     			glDeleteTextures(1, &texobj);
     			texobj = 0;
    Index: rts/Rendering/Textures/NamedTextures.cpp
    ===================================================================
    --- rts/Rendering/Textures/NamedTextures.cpp	(revision 5850)
    +++ rts/Rendering/Textures/NamedTextures.cpp	(working copy)
    @@ -138,7 +138,7 @@
     			             GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
     		} else {
     			gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize,
    -			                  GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
    +			                  GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem); // make power of two!
     		}
     	} else {
     		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    @@ -147,8 +147,9 @@
     		} else {
     			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
     		}
    -		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8, bitmap.xsize, bitmap.ysize,
    -											GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
    +
    +		glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bitmap.xsize, bitmap.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.mem);
    +		
     	}
     
     	if (aniso && GLEW_EXT_texture_filter_anisotropic) {
    Index: rts/Rendering/Textures/TextureAtlas.cpp
    ===================================================================
    --- rts/Rendering/Textures/TextureAtlas.cpp	(revision 5850)
    +++ rts/Rendering/Textures/TextureAtlas.cpp	(working copy)
    @@ -9,6 +9,9 @@
     CR_BIND(AtlasedTexture, );
     CR_BIND_DERIVED(GroundFXTexture, AtlasedTexture, );
     
    +//texture spacing in the atlas (in pixels)
    +#define TEXMARGIN 1
    +
     bool CTextureAtlas::debug;
     
     CTextureAtlas::CTextureAtlas(int maxxsize, int maxysize)
    @@ -99,7 +102,7 @@
     					if(maxy>ysize){
     						if(IncreaseSize())
     						{
    -                            nextSub.clear();
    + 							nextSub.clear();
     							thisSub.clear();
     							cury=maxy=curx=0;
     							recalc=true;
    @@ -131,11 +134,11 @@
     
     			done=true;
     
    -			if(thisSub.front().y+curtex->ysize<maxy){
    -				nextSub.push_back(int2(thisSub.front().x,thisSub.front().y+curtex->ysize));
    +			if(thisSub.front().y+curtex->ysize+TEXMARGIN<maxy){
    +				nextSub.push_back(int2(thisSub.front().x+TEXMARGIN,thisSub.front().y+curtex->ysize+TEXMARGIN));
     			}
     
    -			thisSub.front().x+=curtex->xsize;
    +			thisSub.front().x+=curtex->xsize+TEXMARGIN;
     			while(thisSub.size()>1 && thisSub.front().x >= (++thisSub.begin())->x){
     				(++thisSub.begin())->x=thisSub.front().x;
     				thisSub.erase(thisSub.begin());
    @@ -179,54 +182,17 @@
     {
     
     	unsigned char *data;
    -	//for(int i=0,xmip=0,ymip=0; (xsize>>i) || (ysize>>i); i++)
    -	//{
    -	//	data[i] = SAFE_NEW unsigned char[(xsize>>xmip)*(ysize>>ymip)*4];
    -
    -	//	xmip = (xsize>>i)>1 ? xmip+=1 : xmip;
    -	//	ymip = (ysize>>i)>1 ? ymip+=1 : ymip;
    -	//}
    -
    -	//for(int i=0; i<memtextures.size(); i++)
    -	//{
    -	//	MemTex *tex = memtextures[i];
    -	//	for(int mip=0,xmip=0,ymip=0; (tex->xsize>>mip) || (tex->ysize>>mip); mip++)
    -	//	{
    -	//		unsigned char *mipcell;
    -
    -	//		if(mip==0)
    -	//			mipcell = (unsigned char*)tex->data;
    -	//		else
    -	//		{
    -	//			mipcell = SAFE_NEW unsigned char[(tex->xsize>>xmip)*(tex->ysize>>ymip)*4];
    -	//			gluScaleImage(GL_RGBA, tex->xsize, tex->ysize, GL_UNSIGNED_BYTE, tex->data, (tex->xsize>>xmip), (tex->ysize>>ymip), GL_UNSIGNED_BYTE, mipcell);
    -	//		}
    -
    -	//		for(int x=0; x<tex->xsize>>xmip; x++)
    -	//		{
    -	//			for(int y=0; y<tex->ysize>>ymip; y++)
    -	//			{
    -	//				((int*)data[mip])[(tex->xpos>>xmip)+x+((tex->ypos>>ymip)+y)*(xsize>>mip)] = ((int*)mipcell)[x+y*(tex->xsize>>xmip)];
    -	//			}
    -	//		}
    -
    -	//		if(mip)
    -	//			delete [] mipcell;
    -	//		xmip = (xsize>>mip)>1 ? xmip+=1 : xmip;
    -	//		ymip = (ysize>>mip)>1 ? ymip+=1 : ymip;
    -	//	}
    -	//}
    -
     	data = SAFE_NEW unsigned char[xsize*ysize*4];
    +	memset(data,0,xsize*ysize*4); // make spacing between textures black transparent to avoid ugly lines with linear filtering
     
     	for(int i=0; i<memtextures.size(); i++)
     	{
     		MemTex *tex = memtextures[i];
    -        for(int x=0; x<tex->xsize; x++)
    -			for(int y=0; y<tex->ysize; y++)
    -			{
    +		for(int x=0; x<tex->xsize; x++) {
    +			for(int y=0; y<tex->ysize; y++) {
     				((int*)data)[tex->xpos+x+(tex->ypos+y)*xsize] = ((int*)tex->data)[x+y*tex->xsize];
     			}
    +		}			
     	}
     
     	if (debug) {
    @@ -248,20 +214,18 @@
     	glBindTexture(GL_TEXTURE_2D, gltex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,/*GL_NEAREST_MIPMAP_LINEAR*/GL_NEAREST);
    -	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
    -	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
    +	if (GLEW_EXT_texture_edge_clamp) {
    +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    +	} else {
    +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    +		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    +	}
     
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, data);
    +	glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,xsize, ysize, GL_RGBA, GL_UNSIGNED_BYTE, data);
     
     	delete [] data;
     
    -	//for(int i=0; (xsize>>i) || (ysize>>i); i++)
    -	//{
    -	//	glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, xsize>>i, ysize>>i, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[i]);
    -	//	delete [] data[i];
    -	//}
    -	
    -
     	initialized=true;
     }
     
    Index: rts/Rendering/Textures/TextureHandler.cpp
    ===================================================================
    --- rts/Rendering/Textures/TextureHandler.cpp	(revision 5850)
    +++ rts/Rendering/Textures/TextureHandler.cpp	(working copy)
    @@ -210,7 +210,8 @@
     	glBindTexture(GL_TEXTURE_2D, globalTex);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR/*_MIPMAP_NEAREST*/);
    -	gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, tex);
    +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8 ,bigTexX, bigTexY, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex);
    +	//glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,bigTexX, bigTexY, GL_RGBA, GL_UNSIGNED_BYTE, tex);
     //	CBitmap save(tex,bigTexX,bigTexY);
     	//save.Save("unittex-1x.jpg");
     
    Index: rts/Rendering/UnitModels/3DModelParser.cpp
    ===================================================================
    --- rts/Rendering/UnitModels/3DModelParser.cpp	(revision 5850)
    +++ rts/Rendering/UnitModels/3DModelParser.cpp	(working copy)
    @@ -352,9 +352,9 @@
     	glTranslatef(offset.x, offset.y, offset.z);
     
     	if (anim) {
    -		glTranslatef(-anim->coords[0] / CORDDIV,
    -									anim->coords[1] / CORDDIV,
    -									anim->coords[2] / CORDDIV);
    +		glTranslatef(anim->coords[0] / CORDDIV,
    +				 anim->coords[1] / CORDDIV,
    +				 anim->coords[2] / CORDDIV);
     		if (anim->rot[1]) { glRotatef( anim->rot[1] / ANGDIV, 0.0f, 1.0f, 0.0f); }
     		if (anim->rot[0]) { glRotatef( anim->rot[0] / ANGDIV, 1.0f, 0.0f, 0.0f); }
     		if (anim->rot[2]) { glRotatef(-anim->rot[2] / ANGDIV, 0.0f, 0.0f, 1.0f); }
    Index: rts/Rendering/UnitModels/UnitDrawer.cpp
    ===================================================================
    --- rts/Rendering/UnitModels/UnitDrawer.cpp	(revision 5850)
    +++ rts/Rendering/UnitModels/UnitDrawer.cpp	(working copy)
    @@ -1810,16 +1810,16 @@
     		const double plane0[4] = {0, -1, 0 , start + height * (unit->buildProgress * 3 - 2)};
     		glClipPlane(GL_CLIP_PLANE0, plane0);
     
    -		if (shadowHandler->drawShadows && !water->drawReflection) {
    +		//if (shadowHandler->drawShadows && !water->drawReflection) {
     			glPolygonOffset(1.0f, 1.0f);
     			glEnable(GL_POLYGON_OFFSET_FILL);
    -		}
    +		//}
     
     		DrawUnitModel(unit);
     
    -		if (shadowHandler->drawShadows && !water->drawReflection) {
    +		//if (shadowHandler->drawShadows && !water->drawReflection) {
     			glDisable(GL_POLYGON_OFFSET_FILL);
    -		}
    +		//}
     	}
     
     	glDisable(GL_CLIP_PLANE0);
    Index: rts/Sim/Projectiles/ProjectileHandler.cpp
    ===================================================================
    --- rts/Sim/Projectiles/ProjectileHandler.cpp	(revision 5850)
    +++ rts/Sim/Projectiles/ProjectileHandler.cpp	(working copy)
    @@ -93,7 +93,7 @@
     	for (int i = 0; i < 12; i++) {
     		char num[10];
     		sprintf(num, "%02i", i);
    -		textureAtlas->AddTexFromFile(std::string("ismoke") + num, std::string("bitmaps/")+resources.SGetValueDef(std::string("smoke/smoke") + num +".tga",std::string("resources\\graphics\\smoke\\smoke")+num+"alpha"));
    +		textureAtlas->AddTexFromFile(std::string("ismoke") + num, std::string("bitmaps/")+resources.SGetValueDef(std::string("smoke/smoke") + num +".tga",std::string("resources\\graphics\\smoke\\smoke")+num));
     		blockMapTexNames.insert(std::string("ismoke") + num);
     	}
     
    @@ -240,7 +240,7 @@
     		glBindTexture(GL_TEXTURE_2D, perlinTex[a]);
     		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
     		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    -		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA8,16, 16, GL_RGBA, GL_UNSIGNED_BYTE, tempmem);
    +		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16,16, 0, GL_RGBA, GL_UNSIGNED_BYTE, tempmem);
     	}
     
     	drawPerlinTex=false;
    Index: rts/System/GlobalStuff.cpp
    ===================================================================
    --- rts/System/GlobalStuff.cpp	(revision 5850)
    +++ rts/System/GlobalStuff.cpp	(working copy)
    @@ -218,6 +218,7 @@
     	viewRange=MAX_VIEW_RANGE;
     	timeOffset=0;
     	drawFog=true;
    +	compressTextures=false;
     	teamNanospray=false;
     	autoQuit=false;
     	quitTime=0;
    Index: rts/System/GlobalStuff.h
    ===================================================================
    --- rts/System/GlobalStuff.h	(revision 5850)
    +++ rts/System/GlobalStuff.h	(working copy)
    @@ -442,7 +442,7 @@
     public:
     	CR_DECLARE(CGlobalUnsyncedStuff);
     	CGlobalUnsyncedStuff(); 		//!< Constructor
    -	~CGlobalUnsyncedStuff(); 	//!< Destructor
    +	~CGlobalUnsyncedStuff();	 	//!< Destructor
     
     	int usRandInt(); 			//!< Unsynced random int
     	float usRandFloat(); 			//!< Unsynced random float
    @@ -586,6 +586,13 @@
     	 * Whether fog (of war) is drawn or not
     	 */
     	bool drawFog;
    +	
    +	/**
    +	 * @brief compressTextures
    +	 *
    +	 * If set, many (not all) textures will compressed on run-time.
    +	*/
    +	bool compressTextures;
     
     	/**
     	 * @brief quit automatically?
    Index: rts/System/SpringApp.cpp
    ===================================================================
    --- rts/System/SpringApp.cpp	(revision 5850)
    +++ rts/System/SpringApp.cpp	(working copy)
    @@ -1,987 +1,997 @@
    -#include "StdAfx.h"
    -#include "SpringApp.h"
    -
    -#include <signal.h>
    -#include <SDL.h>
    -#include <SDL_syswm.h>
    -
    -#include "Game/GameVersion.h"
    -#include "Game/GameSetup.h"
    -#include "Game/GameController.h"
    -#include "Game/PreGame.h"
    -#include "Game/Game.h"
    -#include "Game/Team.h"
    -#include "Game/UI/KeyBindings.h"
    -#include "Lua/LuaGaia.h"
    -#include "Lua/LuaRules.h"
    -#include "Lua/LuaOpenGL.h"
    -#include "Platform/BaseCmd.h"
    -#include "Platform/ConfigHandler.h"
    -#include "Platform/errorhandler.h"
    -#include "Platform/FileSystem.h"
    -#include "Rendering/glFont.h"
    -#include "Rendering/GLContext.h"
    -#include "Rendering/GL/myGL.h"
    -#include "Rendering/VerticalSync.h"
    -#include "Rendering/Textures/TAPalette.h"
    -#include "Rendering/Textures/NamedTextures.h"
    -#include "Rendering/Textures/TextureAtlas.h"
    -#include "Sim/Projectiles/ExplosionGenerator.h"
    -#include "LogOutput.h"
    -#include "MouseInput.h"
    -#include "bitops.h"
    -#include "Sync/Syncify.h"
    -
    -#include "mmgr.h"
    -
    -#ifdef WIN32
    -#ifdef __GNUC__
    -	#include "Platform/Win/CrashHandler.h"
    -#endif
    -	#include "Platform/Win/win32.h"
    -	#include <winreg.h>
    -	#include <direct.h>
    -	#include "Platform/Win/seh.h"
    -#endif // WIN32
    -
    -using std::string;
    -
    -CGameController* activeController = 0;
    -bool globalQuit = false;
    -Uint8 *keys = 0;
    -bool fullscreen = true;
    -char *win_lpCmdLine = 0;
    -
    -/**
    - * @brief xres default
    - *
    - * Defines the default X resolution as 1024
    - */
    -const int XRES_DEFAULT = 1024;
    -
    -/**
    - * @brief yres default
    - *
    - * Defines the default Y resolution as 768
    - */
    -const int YRES_DEFAULT = 768;
    -
    -void SpringApp::SigAbrtHandler(int unused)
    -{
    -	// cause an exception if on windows
    -	// TODO FIXME do a proper stacktrace dump here
    -	#ifdef WIN32
    -	*((int*)(0)) = 0;
    -	#endif
    -}
    -
    -/**
    - * Initializes SpringApp variables
    - */
    -SpringApp::SpringApp ()
    -{
    -	cmdline = 0;
    -	screenWidth = screenHeight = 0;
    -	FSAA = false;
    -
    -	signal(SIGABRT, SigAbrtHandler);
    -}
    -
    -/**
    - * Destroys SpringApp variables
    - */
    -SpringApp::~SpringApp()
    -{
    -	if (cmdline) delete cmdline;
    -	if (keys) delete[] keys;
    -
    -	creg::System::FreeClasses ();
    -}
    -
    -#ifdef _CRASHRPT_H_
    -/**
    - * @brief crash callback
    - * @return whether callback was successful
    - * @param crState current state
    - *
    - * Callback function executed when
    - * game crashes (win32 only)
    - */
    -bool crashCallback(void* crState)
    -{
    -	logOutput.RemoveAllSubscribers();
    -	logOutput.Print("Spring has crashed");
    -
    -	// Stop writing to infolog.txt
    -	logOutput.End();
    -
    -	// FIXME needs to be updated for new netcode
    -	//bool wasRecording = false;
    -	//if (net->recordDemo) {
    -	//	delete net->recordDemo;
    -	//	wasRecording = true;
    -	//}
    -
    -	AddFile("infolog.txt", "Spring information log");
    -
    -	//if (wasRecording)
    -	//	AddFile(net->demoName.c_str(), "Spring game demo");
    -
    -	SDL_Quit();
    -
    -	return true;
    -}
    -#endif
    -
    -/**
    - * @brief Initializes the SpringApp instance
    - * @return whether initialization was successful
    - */
    -bool SpringApp::Initialize ()
    -{
    -	logOutput.SetMirrorToStdout(!!configHandler.GetInt("StdoutDebug",0));
    -
    -	// Initialize class system
    -	creg::System::InitializeClasses ();
    -
    -	// Initialize crash reporting
    -#ifdef _WIN32
    -#if defined(_CRASHRPT_H_)
    -	Install( (LPGETLOGFILE) crashCallback, "taspringcrash@clan-sy.com", "Spring Crashreport");
    -	if (!GetInstance())
    -	{
    -		ErrorMessageBox("Error installing crash reporter", "CrashReport error:", MBF_OK);
    -		return false;
    -	}
    -#elif defined(CRASHHANDLER_H)
    -	CrashHandler::Install();
    -#endif
    -	InitializeSEH();
    -#endif
    -
    -	ParseCmdLine();
    -	FileSystemHandler::Initialize(true);
    -
    -	if (!InitWindow(("Spring " + std::string(VERSION_STRING)).c_str())) {
    -		SDL_Quit();
    -		return false;
    -	}
    -
    -	mouseInput = IMouseInput::Get ();
    -
    -	// Global structures
    -	ENTER_SYNCED;
    -	gs=SAFE_NEW CGlobalSyncedStuff();
    -	ENTER_UNSYNCED;
    -	gu=SAFE_NEW CGlobalUnsyncedStuff();
    -
    -	if (cmdline->result("minimise")) {
    -		gu->active = false;
    -		SDL_WM_IconifyWindow();
    -	}
    -
    -	// Enable auto quit?
    -	int quit_time;
    -	if (cmdline->result("quit", quit_time)) {
    -		gu->autoQuit = true;
    -		gu->quitTime = quit_time;
    -	}
    -
    -	InitOpenGL();
    -	palette.Init();
    -
    -	// Initialize keyboard
    -	SDL_EnableUNICODE(1);
    -	SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
    -	SDL_SetModState (KMOD_NONE);
    -
    -	keys = SAFE_NEW Uint8[SDLK_LAST];
    -	memset (keys,0,sizeof(Uint8)*SDLK_LAST);
    -
    -	// Initialize font
    -	const int charFirst = configHandler.GetInt("FontCharFirst", 32);
    -	const int charLast  = configHandler.GetInt("FontCharLast", 255);
    -	std::string fontFile = configHandler.GetString("FontFile", "fonts/Luxi.ttf");
    -
    -	const float fontSize = 0.027f;      // ~20 pixels at 1024x768
    -	const float smallFontSize = 0.016f; // ~12 pixels at 1024x768
    -
    -	try {
    -		font = CglFont::TryConstructFont(fontFile, charFirst, charLast, fontSize);
    -		smallFont = CglFont::TryConstructFont(fontFile, charFirst, charLast, smallFontSize);
    -	} catch(content_error&) {
    -		// If the standard location fails, retry in fonts directory or vice versa.
    -		if (fontFile.substr(0, 6) == "fonts/")
    -			fontFile = fontFile.substr(6);
    -		else
    -			fontFile = "fonts/" + fontFile;
    -		font = CglFont::TryConstructFont(fontFile, charFirst, charLast, fontSize);
    -		smallFont = CglFont::TryConstructFont(fontFile, charFirst, charLast, smallFontSize);
    -	}
    -
    -	// Initialize GLEW
    -	LoadExtensions();
    -	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    -	SDL_GL_SwapBuffers();
    -
    -	// Initialize named texture handler
    -	CNamedTextures::Init();
    -
    -	// Initialize Lua GL
    -	LuaOpenGL::Init();
    -
    -	// Create CGameSetup and CPreGame objects
    -	CreateGameSetup ();
    -
    -	return true;
    -}
    -
    -/**
    - * @brief multisample test
    - * @return whether the multisampling test was successful
    - *
    - * Tests if a user has requested FSAA, if it's a valid
    - * FSAA mode, and if it's supported by the current GL context
    - */
    -static bool MultisampleTest(void)
    -{
    -	if (!GL_ARB_multisample)
    -		return false;
    -	GLuint fsaa = configHandler.GetInt("FSAA",0);
    -	if (!fsaa)
    -		return false;
    -	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,1);
    -	GLuint fsaalevel = std::max(std::min(configHandler.GetInt("FSAALevel", 2), 8), 0);
    -
    -	make_even_number(fsaalevel);
    -
    -	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,fsaalevel);
    -	return true;
    -}
    -
    -/**
    - * @brief multisample verify
    - * @return whether verification passed
    - *
    - * Tests whether FSAA was actually enabled
    - */
    -static bool MultisampleVerify(void)
    -{
    -	GLint buffers, samples;
    -	glGetIntegerv(GL_SAMPLE_BUFFERS_ARB, &buffers);
    -	glGetIntegerv(GL_SAMPLES_ARB, &samples);
    -	if (buffers && samples) {
    -		return true;
    -	}
    -	return false;
    -}
    -
    -
    -/**
    - * @return whether window initialization succeeded
    - * @param title char* string with window title
    - *
    - * Initializes the game window
    - */
    -bool SpringApp::InitWindow (const char* title)
    -{
    -	unsigned int sdlInitFlags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
    -#ifdef WIN32
    -	// the crash reporter should be catching the errors
    -	sdlInitFlags |= SDL_INIT_NOPARACHUTE;
    -#endif
    -	if ((SDL_Init(sdlInitFlags) == -1)) {
    -		handleerror(NULL,"Could not initialize SDL.","ERROR",MBF_OK|MBF_EXCL);
    -		return false;
    -	}
    -
    -	// Sets window manager properties
    -	SDL_WM_SetIcon(SDL_LoadBMP("spring.bmp"),NULL);
    -	SDL_WM_SetCaption(title, title);
    -
    -	if (!SetSDLVideoMode ())
    -		return false;
    -
    -	return true;
    -}
    -
    -/**
    - * @return whether setting the video mode was successful
    - *
    - * Sets SDL video mode options/settings
    - */
    -bool SpringApp::SetSDLVideoMode ()
    -{
    -	int sdlflags = SDL_OPENGL | SDL_RESIZABLE;
    -
    -	//conditionally_set_flag(sdlflags, SDL_FULLSCREEN, fullscreen);
    -	sdlflags |= fullscreen ? SDL_FULLSCREEN : 0;
    -
    -	int bitsPerPixel = configHandler.GetInt("BitsPerPixel", 0);
    -	
    -	if (bitsPerPixel == 32)
    -	{
    -		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    -		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    -		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    -		SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); // enable alpha channel
    -	}
    -	else
    -	{
    -		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    -		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
    -		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
    -		// no alpha in 16bit mode
    -
    -        if (bitsPerPixel != 16 && bitsPerPixel != 0)
    -           bitsPerPixel = 0; // it should be either 0, 16, or 32
    -	}
    -
    -#ifdef __APPLE__
    -	const int defaultDepthSize = 32;
    -#else
    -	const int defaultDepthSize = 16;
    -#endif
    -	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, configHandler.GetInt("DepthBufferBits", defaultDepthSize));
    -	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, configHandler.GetInt("StencilBufferBits", 1));
    -
    -	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    -
    -	FSAA = MultisampleTest();
    -
    -	SDL_Surface *screen = SDL_SetVideoMode(screenWidth, screenHeight, bitsPerPixel, sdlflags);
    -	if (!screen) {
    -		char buf[1024];
    -		SNPRINTF(buf, sizeof(buf), "Could not set video mode:\n%s", SDL_GetError());
    -		handleerror(NULL, buf, "ERROR", MBF_OK|MBF_EXCL);
    -		return false;
    -	}
    -
    -#ifdef STREFLOP_H
    -	// Something in SDL_SetVideoMode (OpenGL drivers?) messes with the FPU control word.
    -	// Set single precision floating point math.
    -	streflop_init<streflop::Simple>();
    -#endif
    -
    -	if (FSAA) {
    - 		FSAA = MultisampleVerify();
    -	}
    -
    -	// setup GL smoothing
    -	const int defaultSmooth = 0; // FSAA ? 0 : 3;  // until a few things get fixed
    -	const int lineSmoothing = configHandler.GetInt("SmoothLines", defaultSmooth);
    -	if (lineSmoothing > 0) {
    -		GLenum hint = GL_FASTEST;
    -		if (lineSmoothing >= 3) {
    -			hint = GL_NICEST;
    -		} else if (lineSmoothing >= 2) {
    -			hint = GL_DONT_CARE;
    -		}
    -		glEnable(GL_LINE_SMOOTH);
    -		glHint(GL_LINE_SMOOTH_HINT, hint);
    -	}
    -	const int pointSmoothing = configHandler.GetInt("SmoothPoints", defaultSmooth);
    -	if (pointSmoothing > 0) {
    -		GLenum hint = GL_FASTEST;
    -		if (pointSmoothing >= 3) {
    -			hint = GL_NICEST;
    -		} else if (pointSmoothing >= 2) {
    -			hint = GL_DONT_CARE;
    -		}
    -		glEnable(GL_POINT_SMOOTH);
    -		glHint(GL_POINT_SMOOTH_HINT, hint);
    -	}
    -
    -	// there must be a way to see if this is necessary, compare old/new context pointers?
    -	if (!!configHandler.GetInt("FixAltTab", 0)) {
    -		// free GL resources
    -		GLContext::Free();
    -
    -		// initialize any GL resources that were lost
    -		GLContext::Init();
    -	}
    -
    -	// initialize the stencil
    -	glClearStencil(0);
    -	glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    -	glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    -
    -	int bits;
    -	SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &bits);
    -	logOutput.Print("Video mode set to  %i x %i / %i bit", screenWidth, screenHeight, bits );
    -	VSync.Init();
    -
    -	return true;
    -}
    -
    -
    -// origin for our coordinates is the bottom left corner
    -bool SpringApp::GetDisplayGeometry()
    -{
    -	SDL_SysWMinfo info;
    -	SDL_VERSION(&info.version);
    -
    -	if (!SDL_GetWMInfo(&info)) {
    -		return false;
    -	}
    -
    -#ifdef __APPLE__
    -	return false;
    -#elif !defined(_WIN32)
    -	info.info.x11.lock_func();
    -	{
    -		Display* display = info.info.x11.display;
    -		Window   window  = info.info.x11.window;
    -
    -		XWindowAttributes attrs;
    -		XGetWindowAttributes(display, window, &attrs);
    -		const Screen* screen = attrs.screen;
    -		gu->screenSizeX = WidthOfScreen(screen);
    -		gu->screenSizeY = HeightOfScreen(screen);
    -		gu->winSizeX = attrs.width;
    -		gu->winSizeY = attrs.height;
    -
    -		Window tmp;
    -		int xp, yp;
    -		XTranslateCoordinates(display, window, attrs.root, 0, 0, &xp, &yp, &tmp);
    -		gu->winPosX = xp;
    -		gu->winPosY = gu->screenSizeY - gu->winSizeY - yp;
    -	}
    -	info.info.x11.unlock_func();
    -#else
    -	gu->screenSizeX = GetSystemMetrics(SM_CXFULLSCREEN);
    -	gu->screenSizeY = GetSystemMetrics(SM_CYFULLSCREEN);
    -
    -	RECT rect;
    -	if (!GetClientRect(info.window, &rect)) {
    -		return false;
    -	}
    -
    -	if((rect.right - rect.left)==0 || (rect.bottom - rect.top)==0)
    -		return false;
    -
    -	gu->winSizeX = rect.right - rect.left;
    -	gu->winSizeY = rect.bottom - rect.top;
    -
    -	// translate from client coords to screen coords
    -	MapWindowPoints(info.window, HWND_DESKTOP, (LPPOINT)&rect, 2);
    -	gu->winPosX = rect.left;
    -	gu->winPosY = gu->screenSizeY - gu->winSizeY - rect.top;
    -#endif // _WIN32
    -	return true;
    -}
    -
    -
    -void SpringApp::SetupViewportGeometry()
    -{
    -	if (!GetDisplayGeometry()) {
    -		gu->screenSizeX = screenWidth;
    -		gu->screenSizeY = screenHeight;
    -		gu->winSizeX = screenWidth;
    -		gu->winSizeY = screenHeight;
    -		gu->winPosX = 0;
    -		gu->winPosY = 0;
    -	}
    -
    -	gu->dualScreenMode = !!configHandler.GetInt("DualScreenMode", 0);
    -	if (gu->dualScreenMode) {
    -		gu->dualScreenMiniMapOnLeft =
    -			!!configHandler.GetInt("DualScreenMiniMapOnLeft", 0);
    -	} else {
    -		gu->dualScreenMiniMapOnLeft = false;
    -	}
    -
    -	if (!gu->dualScreenMode) {
    -		gu->viewSizeX = gu->winSizeX;
    -		gu->viewSizeY = gu->winSizeY;
    -		gu->viewPosX = 0;
    -		gu->viewPosY = 0;
    -	}
    -	else {
    -		gu->viewSizeX = gu->winSizeX / 2;
    -		gu->viewSizeY = gu->winSizeY;
    -		if (gu->dualScreenMiniMapOnLeft) {
    -			gu->viewPosX = gu->winSizeX / 2;
    -			gu->viewPosY = 0;
    -		} else {
    -			gu->viewPosX = 0;
    -			gu->viewPosY = 0;
    -		}
    -	}
    -
    -	gu->pixelX = 1.0f / (float)gu->viewSizeX;
    -	gu->pixelY = 1.0f / (float)gu->viewSizeY;
    -
    -	// NOTE:  gu->viewPosY is not currently used
    -
    -	gu->aspectRatio = (float)gu->viewSizeX / (float)gu->viewSizeY;
    -}
    -
    -
    -/**
    - * Initializes OpenGL
    - */
    -void SpringApp::InitOpenGL ()
    -{
    -	SetupViewportGeometry();
    -
    -	glViewport(gu->viewPosX, gu->viewPosY, gu->viewSizeX, gu->viewSizeY);
    -
    -	gluPerspective(45.0f, (GLfloat)gu->viewSizeX / (GLfloat)gu->viewSizeY, 2.8f, MAX_VIEW_RANGE);
    -
    -	// Initialize some GL states
    -	glShadeModel(GL_SMOOTH);
    -	glClearDepth(1.0f);
    -	glEnable(GL_DEPTH_TEST);
    -	glDepthFunc(GL_LEQUAL);
    -}
    -
    -/**
    - * @return whether commandline parsing was successful
    - *
    - * Parse command line arguments
    - */
    -void SpringApp::ParseCmdLine()
    -{
    -	cmdline->addoption('f', "fullscreen",     OPTPARM_NONE,   "",  "Run in fullscreen mode");
    -	cmdline->addoption('w', "window",         OPTPARM_NONE,   "",  "Run in windowed mode");
    -	cmdline->addoption('x', "xresolution",    OPTPARM_INT,    "",  "Set X resolution");
    -	cmdline->addoption('y', "yresolution",    OPTPARM_INT,    "",  "Set Y resolution");
    -	cmdline->addoption('m', "minimise",       OPTPARM_NONE,   "",  "Start minimised");
    -	cmdline->addoption('s', "server",         OPTPARM_NONE,   "",  "Run as a server");
    -	cmdline->addoption('c', "client",         OPTPARM_NONE,   "",  "Run as a client");
    -	cmdline->addoption('p', "projectiledump", OPTPARM_NONE,   "",  "Dump projectile class info in projectiles.txt");
    -	cmdline->addoption('t', "textureatlas",   OPTPARM_NONE,   "",  "Dump each finalized textureatlas in textureatlasN.tga");
    -	cmdline->addoption('q', "quit",           OPTPARM_INT,    "T", "Quit immediately on game over or after T seconds");
    -	cmdline->addoption('n', "name",           OPTPARM_STRING, "",  "Set your player name");
    -	cmdline->parse();
    -
    -#ifdef _DEBUG
    -	fullscreen = false;
    -#else
    -	fullscreen = configHandler.GetInt("Fullscreen", 1) != 0;
    -#endif
    -
    -	// mutually exclusive options that cause spring to quit immediately
    -	if (cmdline->result("help")) {
    -		cmdline->usage("Spring",VERSION_STRING);
    -		exit(0);
    -	} else if (cmdline->result("version")) {
    -		std::cout << "Spring " << VERSION_STRING << std::endl;
    -		exit(0);
    -	} else if (cmdline->result("projectiledump")) {
    -		CCustomExplosionGenerator::OutputProjectileClassInfo();
    -		exit(0);
    -	}
    -
    -	// flags
    -	if (cmdline->result("window")) {
    -		fullscreen = false;
    -	} else if (cmdline->result("fullscreen")) {
    -		fullscreen = true;
    -	}
    -
    -	if (cmdline->result("textureatlas")) {
    -		CTextureAtlas::debug = true;
    -	}
    -
    -	string name;
    -	if (cmdline->result("name", name)) {
    -		configHandler.SetString("name", name);
    -	}
    -
    -
    -	if (!cmdline->result("xresolution", screenWidth)) {
    -		screenWidth = configHandler.GetInt("XResolution", XRES_DEFAULT);
    -	} else {
    -		screenWidth = std::max(screenWidth, 1);
    -	}
    -	
    -	if (!cmdline->result("yresolution", screenHeight)) {
    -		screenHeight = configHandler.GetInt("YResolution", YRES_DEFAULT);
    -	} else {
    -		screenHeight = std::max(screenHeight, 1);
    -	}
    -	
    -}
    -
    -/**
    - * @param argc argument count
    - * @param argv array of argument strings
    - *
    - * Checks if a demo SDF file or a startscript has
    - * been specified on the command line
    - */
    -void SpringApp::CheckCmdLineFile(int argc, char *argv[])
    -{
    -	// Check if the commandline parameter is specifying a demo file
    -#ifdef _WIN32
    -	// find the correct dir
    -	char exe[128];
    -	GetModuleFileName(0, exe, sizeof(exe));
    -	int a,s = strlen(exe);
    -	for (a=s-1;a>0;a--)
    -	    // Running in gdb causes the last dir separator to be a forward slash.
    -		if (exe[a] == '\\' || exe[a] == '/') break;
    -	if (a > 0) {
    -		string path(exe, exe+a);
    -		if (path.at(0) == '"')
    -			path.append(1,'"');
    -		_chdir(path.c_str());
    -	}
    -
    -	// If there are any options, they will start before the demo file name.
    -
    -   if (win_lpCmdLine == 0)
    -   logOutput.Print("ERROR");
    -	string cmdLineStr = win_lpCmdLine;
    -	string::size_type offset = 0;
    -	//Simply assumes that any argument coming after a argument starting with /q is a variable to /q.
    -	for(int i=1; i < argc && (argv[i][0] == '/' || (argv[i-1][0] == '/' && (argv[i-1][1] == 'q' || argv[i-1][1] == 'a'))); i++){
    -		offset += strlen(argv[i]);
    -		offset = cmdLineStr.find_first_not_of(' ', offset);
    -		if(offset == string::npos)
    -			break;
    -	}
    -
    -	string command;
    -	if(offset != string::npos)
    -		command = cmdLineStr.substr(offset);
    -
    -
    -	if (!command.empty()) {
    -		if (command[0] == '"' && *command.rbegin() == '"' && command.length() > 2)
    -			command = command.substr(1, command.length()-2);
    -		if (command.rfind("sdf") == command.size()-3) {
    -			demofile = command;
    -			logOutput << "Using demofile " << demofile.c_str() << "\n";
    -		} else if (command.rfind("ssf") == command.size()-3) {
    -			savefile = command;
    -			logOutput << "Using savefile " << savefile.c_str() << "\n";
    -		} else {
    -			startscript = command;
    -			logOutput << "Using script " << startscript.c_str() << "\n";
    -		}
    -	}
    -#else
    -	// is there a reason for not using this in windows?
    -	for (int i = 1; i < argc; i++)
    -		if (argv[i][0] != '-')
    -		{
    -			string command(argv[i]);
    -			int idx = command.rfind("sdf");
    -			if (idx == command.size()-3) {
    -				demofile = command;
    -				logOutput << "Using demofile " << demofile.c_str() << "\n";
    -			} else if (command.rfind("ssf") == command.size()-3) {
    -				savefile = command;
    -				logOutput << "Using savefile " << savefile.c_str() << "\n";
    -			} else {
    -				startscript = command;
    -				logOutput << "Using script " << startscript.c_str() << "\n";
    -			}
    -		}
    -#endif
    -}
    -
    -/**
    - * Initializes instance of GameSetup
    - */
    -void SpringApp::CreateGameSetup()
    -{
    -	ENTER_SYNCED;
    -
    -	if (!startscript.empty()) {
    -		gameSetup = SAFE_NEW CGameSetup();
    -		if (!gameSetup->Init(startscript)) {
    -			delete gameSetup;
    -			gameSetup = 0;
    -		}
    -	}
    -
    -	if (!gameSetup && demofile.empty()) {
    -		gs->noHelperAIs = !!configHandler.GetInt("NoHelperAIs", 0);
    -		const string luaGaiaStr  = configHandler.GetString("LuaGaia",  "1");
    -		const string luaRulesStr = configHandler.GetString("LuaRules", "1");
    -		gs->useLuaGaia  = CLuaGaia::SetConfigString(luaGaiaStr);
    -		gs->useLuaRules = CLuaRules::SetConfigString(luaRulesStr);
    -		if (gs->useLuaGaia) {
    -			gs->gaiaTeamID = gs->activeTeams;
    -			gs->gaiaAllyTeamID = gs->activeAllyTeams;
    -			gs->activeTeams++;
    -			gs->activeAllyTeams++;
    -			CTeam* team = gs->Team(gs->gaiaTeamID);
    -			team->color[0] = 255;
    -			team->color[1] = 255;
    -			team->color[2] = 255;
    -			team->color[3] = 255;
    -			team->gaia = true;
    -			gs->SetAllyTeam(gs->gaiaTeamID, gs->gaiaAllyTeamID);
    -		}
    -	}
    -
    -	ENTER_MIXED;
    -
    -	bool server = true;
    -
    -	if (!demofile.empty()) {
    -		server = false;
    -	}
    -	else if (gameSetup) {
    -		// first real player is demo host
    -		server = (gameSetup->myPlayerNum == gameSetup->numDemoPlayers) && !cmdline->result("client");
    -	}
    -	else {
    -		server = !cmdline->result("client") || cmdline->result("server");
    -	}
    -
    -#ifdef SYNCDEBUG
    -	// initialize sync debugger as soon as we know whether we will be server
    -	CSyncDebugger::GetInstance()->Initialize(server);
    -#endif
    -
    -	if (!demofile.empty()) {
    -		pregame = SAFE_NEW CPreGame(false, demofile, "");
    -	} else {
    -		pregame = SAFE_NEW CPreGame(server, "", savefile);
    -	}
    -}
    -
    -
    -/**
    - * @return return code of activecontroller draw function
    - *
    - * Draw function repeatedly called, it calls all the
    - * other draw functions
    - */
    -int SpringApp::Update ()
    -{
    -	if (FSAA)
    -		glEnable(GL_MULTISAMPLE_ARB);
    -
    -	mouseInput->Update();
    -
    -	int ret = 1;
    -	if (activeController) {
    -		if (!activeController->Update()) {
    -			ret = 0;
    -		} else {
    -			ret = activeController->Draw();
    -		}
    -	}
    -
    -	VSync.Delay();
    -	SDL_GL_SwapBuffers();
    -
    -	if (FSAA)
    -		glDisable(GL_MULTISAMPLE_ARB);
    -
    -	return ret;
    -}
    -
    -/**
    - * Tests SDL keystates and sets values
    - * in key array
    - */
    -void SpringApp::UpdateSDLKeys ()
    -{
    -	int numkeys;
    -	Uint8 *state;
    -	state = SDL_GetKeyState(&numkeys);
    -	memcpy(keys, state, sizeof(Uint8) * numkeys);
    -
    -	const SDLMod mods = SDL_GetModState();
    -	keys[SDLK_LALT]   = (mods & KMOD_ALT)   ? 1 : 0;
    -	keys[SDLK_LCTRL]  = (mods & KMOD_CTRL)  ? 1 : 0;
    -	keys[SDLK_LMETA]  = (mods & KMOD_META)  ? 1 : 0;
    -	keys[SDLK_LSHIFT] = (mods & KMOD_SHIFT) ? 1 : 0;
    -}
    -
    -/**
    - * @param argc argument count
    - * @param argv array of argument strings
    - *
    - * Executes the application
    - * (contains main game loop)
    - */
    -int SpringApp::Run (int argc, char *argv[])
    -{
    -	INIT_SYNCIFY;
    -	CheckCmdLineFile (argc, argv);
    -	cmdline = BaseCmd::initialize(argc,argv);
    -/*
    -	logOutput.Print ("Testing error catching");
    -	try {
    -		int *i_=0;
    -		*i_=1;
    -		logOutput.Print ("Error catching doesn't work!");
    -	} catch(...) {
    -		logOutput.Print ("Error catching works!");
    -	}
    -*/
    -	if (!Initialize ())
    -		return -1;
    -
    -#ifdef WIN32
    -	SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE);
    -#endif
    -
    -	SDL_Event event;
    -	bool done = false;
    -
    -	while (!done) {
    -		ENTER_UNSYNCED;
    -		while (SDL_PollEvent(&event)) {
    -			switch (event.type) {
    -				case SDL_VIDEORESIZE: {
    -					screenWidth = event.resize.w;
    -					screenHeight = event.resize.h;
    -#ifndef WIN32
    -					// HACK   We don't want to break resizing on windows (again?),
    -					//        so someone should test this very well before enabling it.
    -					SetSDLVideoMode();
    -#endif
    -					InitOpenGL();
    -					activeController->ResizeEvent();
    -					break;
    -				}
    -				case SDL_VIDEOEXPOSE: {
    -					// re-initialize the stencil
    -					glClearStencil(0);
    -					glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    -					glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    -					SetupViewportGeometry();
    -					break;
    -				}
    -				case SDL_QUIT: {
    -					done = true;
    -					break;
    -				}
    -				case SDL_ACTIVEEVENT: {
    -					if (event.active.state & SDL_APPACTIVE) {
    -						gu->active = !!event.active.gain;
    -					}
    -					break;
    -				}
    -				case SDL_MOUSEMOTION:
    -				case SDL_MOUSEBUTTONDOWN:
    -				case SDL_MOUSEBUTTONUP:
    -				case SDL_SYSWMEVENT: {
    -					mouseInput->HandleSDLMouseEvent (event);
    -					break;
    -				}
    -				case SDL_KEYDOWN: {
    -					int i = event.key.keysym.sym;
    -
    -					const bool isRepeat = !!keys[i];
    -
    -					UpdateSDLKeys ();
    -
    -					if (activeController) {
    -						if (i <= SDLK_DELETE) {
    -							i = tolower(i);
    -						}
    -						else if (i == SDLK_RSHIFT) { i = SDLK_LSHIFT; }
    -						else if (i == SDLK_RCTRL)  { i = SDLK_LCTRL;  }
    -						else if (i == SDLK_RMETA)  { i = SDLK_LMETA;  }
    -						else if (i == SDLK_RALT)   { i = SDLK_LALT;   }
    -
    -						if (keyBindings) {
    -							const int fakeMetaKey = keyBindings->GetFakeMetaKey();
    -							if (fakeMetaKey >= 0) {
    -								keys[SDLK_LMETA] |= keys[fakeMetaKey];
    -							}
    -						}
    -
    -						activeController->KeyPressed(i, isRepeat);
    -
    -						if (activeController->userWriting){
    -							// use unicode for printed characters
    -							i = event.key.keysym.unicode;
    -							if ((i >= SDLK_SPACE) && (i <= SDLK_DELETE)) {
    -								CGameController* ac = activeController;
    -								if (ac->ignoreNextChar || ac->ignoreChar == char(i)) {
    -									ac->ignoreNextChar = false;
    -								} else {
    -									if (i < SDLK_DELETE) {
    -										const int len = (int)ac->userInput.length();
    -										ac->writingPos = std::max(0, std::min(len, ac->writingPos));
    -										char str[2] = { char(i), 0 };
    -										ac->userInput.insert(ac->writingPos, str);
    -										ac->writingPos++;
    -									}
    -								}
    -							}
    -						}
    -					}
    -					activeController->ignoreNextChar = false;
    -					break;
    -				}
    -				case SDL_KEYUP: {
    -					int i = event.key.keysym.sym;
    -
    -					UpdateSDLKeys();
    -
    -					if (activeController) {
    -						if (i <= SDLK_DELETE) {
    -							i = tolower(i);
    -						}
    -						else if (i == SDLK_RSHIFT) { i = SDLK_LSHIFT; }
    -						else if (i == SDLK_RCTRL)  { i = SDLK_LCTRL;  }
    -						else if (i == SDLK_RMETA)  { i = SDLK_LMETA;  }
    -						else if (i == SDLK_RALT)   { i = SDLK_LALT;   }
    -
    -						if (keyBindings) {
    -							const int fakeMetaKey = keyBindings->GetFakeMetaKey();
    -							if (fakeMetaKey >= 0) {
    -								keys[SDLK_LMETA] |= keys[fakeMetaKey];
    -							}
    -						}
    -
    -						activeController->KeyReleased(i);
    -					}
    -					break;
    -				}
    -				default:
    -					break;
    -			}
    -		}
    -		if (globalQuit)
    -			break;
    -
    -		if (!Update())
    -			break;
    -	}
    -	ENTER_MIXED;
    -
    -	// Shutdown
    -	Shutdown();
    -	return 0;
    -}
    -
    -/**
    - * Deallocates and shuts down game
    - */
    -void SpringApp::Shutdown()
    -{
    -	if (pregame)
    -		delete pregame;			//in case we exit during init
    -	if (game)
    -		delete game;
    -	if (gameSetup)
    -		delete gameSetup;
    -	delete font;
    -	CNamedTextures::Kill();
    -	GLContext::Free();
    -	ConfigHandler::Deallocate();
    -	UnloadExtensions();
    -	delete mouseInput;
    -	SDL_WM_GrabInput(SDL_GRAB_OFF);
    -	SDL_Quit();
    -	delete gs;
    -	delete gu;
    -	END_SYNCIFY;
    -#ifdef USE_MMGR
    -	m_dumpMemoryReport();
    -#endif
    -}
    +#include "StdAfx.h"
    +#include "SpringApp.h"
    +
    +#include <signal.h>
    +#include <SDL.h>
    +#include <SDL_syswm.h>
    +
    +#include "Game/GameVersion.h"
    +#include "Game/GameSetup.h"
    +#include "Game/GameController.h"
    +#include "Game/PreGame.h"
    +#include "Game/Game.h"
    +#include "Game/Team.h"
    +#include "Game/UI/KeyBindings.h"
    +#include "Lua/LuaGaia.h"
    +#include "Lua/LuaRules.h"
    +#include "Lua/LuaOpenGL.h"
    +#include "Platform/BaseCmd.h"
    +#include "Platform/ConfigHandler.h"
    +#include "Platform/errorhandler.h"
    +#include "Platform/FileSystem.h"
    +#include "Rendering/glFont.h"
    +#include "Rendering/GLContext.h"
    +#include "Rendering/GL/myGL.h"
    +#include "Rendering/VerticalSync.h"
    +#include "Rendering/Textures/TAPalette.h"
    +#include "Rendering/Textures/NamedTextures.h"
    +#include "Rendering/Textures/TextureAtlas.h"
    +#include "Sim/Projectiles/ExplosionGenerator.h"
    +#include "LogOutput.h"
    +#include "MouseInput.h"
    +#include "bitops.h"
    +#include "Sync/Syncify.h"
    +
    +#include "mmgr.h"
    +
    +#ifdef WIN32
    +#ifdef __GNUC__
    +	#include "Platform/Win/CrashHandler.h"
    +#endif
    +	#include "Platform/Win/win32.h"
    +	#include <winreg.h>
    +	#include <direct.h>
    +	#include "Platform/Win/seh.h"
    +#endif // WIN32
    +
    +using std::string;
    +
    +CGameController* activeController = 0;
    +bool globalQuit = false;
    +Uint8 *keys = 0;
    +bool fullscreen = true;
    +char *win_lpCmdLine = 0;
    +
    +/**
    + * @brief xres default
    + *
    + * Defines the default X resolution as 1024
    + */
    +const int XRES_DEFAULT = 1024;
    +
    +/**
    + * @brief yres default
    + *
    + * Defines the default Y resolution as 768
    + */
    +const int YRES_DEFAULT = 768;
    +
    +void SpringApp::SigAbrtHandler(int unused)
    +{
    +	// cause an exception if on windows
    +	// TODO FIXME do a proper stacktrace dump here
    +	#ifdef WIN32
    +	*((int*)(0)) = 0;
    +	#endif
    +}
    +
    +/**
    + * Initializes SpringApp variables
    + */
    +SpringApp::SpringApp ()
    +{
    +	cmdline = 0;
    +	screenWidth = screenHeight = 0;
    +	FSAA = false;
    +
    +	signal(SIGABRT, SigAbrtHandler);
    +}
    +
    +/**
    + * Destroys SpringApp variables
    + */
    +SpringApp::~SpringApp()
    +{
    +	if (cmdline) delete cmdline;
    +	if (keys) delete[] keys;
    +
    +	creg::System::FreeClasses ();
    +}
    +
    +#ifdef _CRASHRPT_H_
    +/**
    + * @brief crash callback
    + * @return whether callback was successful
    + * @param crState current state
    + *
    + * Callback function executed when
    + * game crashes (win32 only)
    + */
    +bool crashCallback(void* crState)
    +{
    +	logOutput.RemoveAllSubscribers();
    +	logOutput.Print("Spring has crashed");
    +
    +	// Stop writing to infolog.txt
    +	logOutput.End();
    +
    +	// FIXME needs to be updated for new netcode
    +	//bool wasRecording = false;
    +	//if (net->recordDemo) {
    +	//	delete net->recordDemo;
    +	//	wasRecording = true;
    +	//}
    +
    +	AddFile("infolog.txt", "Spring information log");
    +
    +	//if (wasRecording)
    +	//	AddFile(net->demoName.c_str(), "Spring game demo");
    +
    +	SDL_Quit();
    +
    +	return true;
    +}
    +#endif
    +
    +/**
    + * @brief Initializes the SpringApp instance
    + * @return whether initialization was successful
    + */
    +bool SpringApp::Initialize ()
    +{
    +	logOutput.SetMirrorToStdout(!!configHandler.GetInt("StdoutDebug",0));
    +
    +	// Initialize class system
    +	creg::System::InitializeClasses ();
    +
    +	// Initialize crash reporting
    +#ifdef _WIN32
    +#if defined(_CRASHRPT_H_)
    +	Install( (LPGETLOGFILE) crashCallback, "taspringcrash@clan-sy.com", "Spring Crashreport");
    +	if (!GetInstance())
    +	{
    +		ErrorMessageBox("Error installing crash reporter", "CrashReport error:", MBF_OK);
    +		return false;
    +	}
    +#elif defined(CRASHHANDLER_H)
    +	CrashHandler::Install();
    +#endif
    +	InitializeSEH();
    +#endif
    +
    +	ParseCmdLine();
    +	FileSystemHandler::Initialize(true);
    +
    +	if (!InitWindow(("Spring " + std::string(VERSION_STRING)).c_str())) {
    +		SDL_Quit();
    +		return false;
    +	}
    +
    +	mouseInput = IMouseInput::Get ();
    +
    +	// Global structures
    +	ENTER_SYNCED;
    +	gs=SAFE_NEW CGlobalSyncedStuff();
    +	ENTER_UNSYNCED;
    +	gu=SAFE_NEW CGlobalUnsyncedStuff();
    +
    +	if (cmdline->result("minimise")) {
    +		gu->active = false;
    +		SDL_WM_IconifyWindow();
    +	}
    +
    +	// Enable auto quit?
    +	int quit_time;
    +	if (cmdline->result("quit", quit_time)) {
    +		gu->autoQuit = true;
    +		gu->quitTime = quit_time;
    +	}
    +
    +	InitOpenGL();
    +	palette.Init();
    +
    +	// Initialize keyboard
    +	SDL_EnableUNICODE(1);
    +	SDL_EnableKeyRepeat (SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
    +	SDL_SetModState (KMOD_NONE);
    +
    +	keys = SAFE_NEW Uint8[SDLK_LAST];
    +	memset (keys,0,sizeof(Uint8)*SDLK_LAST);
    +
    +	// Initialize font
    +	const int charFirst = configHandler.GetInt("FontCharFirst", 32);
    +	const int charLast  = configHandler.GetInt("FontCharLast", 255);
    +	std::string fontFile = configHandler.GetString("FontFile", "fonts/Luxi.ttf");
    +
    +	const float fontSize = 0.027f;      // ~20 pixels at 1024x768
    +	const float smallFontSize = 0.016f; // ~12 pixels at 1024x768
    +
    +	try {
    +		font = CglFont::TryConstructFont(fontFile, charFirst, charLast, fontSize);
    +		smallFont = CglFont::TryConstructFont(fontFile, charFirst, charLast, smallFontSize);
    +	} catch(content_error&) {
    +		// If the standard location fails, retry in fonts directory or vice versa.
    +		if (fontFile.substr(0, 6) == "fonts/")
    +			fontFile = fontFile.substr(6);
    +		else
    +			fontFile = "fonts/" + fontFile;
    +		font = CglFont::TryConstructFont(fontFile, charFirst, charLast, fontSize);
    +		smallFont = CglFont::TryConstructFont(fontFile, charFirst, charLast, smallFontSize);
    +	}
    +
    +	// Initialize GLEW
    +	LoadExtensions();
    +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    +	SDL_GL_SwapBuffers();
    +
    +	// Runtime compress textures?
    +	if (GLEW_ARB_texture_compression)  // we don't even need to check it, 'cos groundtextures must have that extension
    +		gu->compressTextures = !!configHandler.GetInt("CompressTextures", 1);
    +
    +	// Initialize named texture handler
    +	CNamedTextures::Init();
    +
    +	// Initialize Lua GL
    +	LuaOpenGL::Init();
    +
    +	// Create CGameSetup and CPreGame objects
    +	CreateGameSetup ();
    +
    +	return true;
    +}
    +
    +/**
    + * @brief multisample test
    + * @return whether the multisampling test was successful
    + *
    + * Tests if a user has requested FSAA, if it's a valid
    + * FSAA mode, and if it's supported by the current GL context
    + */
    +static bool MultisampleTest(void)
    +{
    +	if (!GL_ARB_multisample)
    +		return false;
    +	GLuint fsaa = configHandler.GetInt("FSAA",0);
    +	if (!fsaa)
    +		return false;
    +	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS,1);
    +	GLuint fsaalevel = std::max(std::min(configHandler.GetInt("FSAALevel", 2), 8), 0);
    +
    +	make_even_number(fsaalevel);
    +
    +	SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES,fsaalevel);
    +	return true;
    +}
    +
    +/**
    + * @brief multisample verify
    + * @return whether verification passed
    + *
    + * Tests whether FSAA was actually enabled
    + */
    +static bool MultisampleVerify(void)
    +{
    +	GLint buffers, samples;
    +	glGetIntegerv(GL_SAMPLE_BUFFERS_ARB, &buffers);
    +	glGetIntegerv(GL_SAMPLES_ARB, &samples);
    +	if (buffers && samples) {
    +		return true;
    +	}
    +	return false;
    +}
    +
    +
    +/**
    + * @return whether window initialization succeeded
    + * @param title char* string with window title
    + *
    + * Initializes the game window
    + */
    +bool SpringApp::InitWindow (const char* title)
    +{
    +	unsigned int sdlInitFlags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
    +#ifdef WIN32
    +	// the crash reporter should be catching the errors
    +	sdlInitFlags |= SDL_INIT_NOPARACHUTE;
    +#endif
    +	if ((SDL_Init(sdlInitFlags) == -1)) {
    +		handleerror(NULL,"Could not initialize SDL.","ERROR",MBF_OK|MBF_EXCL);
    +		return false;
    +	}
    +
    +	// Sets window manager properties
    +	SDL_WM_SetIcon(SDL_LoadBMP("spring.bmp"),NULL);
    +	SDL_WM_SetCaption(title, title);
    +
    +	if (!SetSDLVideoMode ())
    +		return false;
    +
    +	return true;
    +}
    +
    +/**
    + * @return whether setting the video mode was successful
    + *
    + * Sets SDL video mode options/settings
    + */
    +bool SpringApp::SetSDLVideoMode ()
    +{
    +	int sdlflags = SDL_OPENGL | SDL_RESIZABLE;
    +
    +	//conditionally_set_flag(sdlflags, SDL_FULLSCREEN, fullscreen);
    +	sdlflags |= fullscreen ? SDL_FULLSCREEN : 0;
    +
    +	int bitsPerPixel = configHandler.GetInt("BitsPerPixel", 0);
    +	
    +	if (bitsPerPixel == 32)
    +	{
    +		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    +		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    +		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    +		SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); // enable alpha channel
    +	}
    +	else
    +	{
    +		SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    +		SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
    +		SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
    +		// no alpha in 16bit mode
    +
    +        if (bitsPerPixel != 16 && bitsPerPixel != 0)
    +           bitsPerPixel = 0; // it should be either 0, 16, or 32
    +	}
    +
    +#ifdef __APPLE__
    +	const int defaultDepthSize = 32;
    +#else
    +	const int defaultDepthSize = 16;
    +#endif
    +	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, configHandler.GetInt("DepthBufferBits", defaultDepthSize));
    +	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, configHandler.GetInt("StencilBufferBits", 1));
    +
    +	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    +
    +	FSAA = MultisampleTest();
    +
    +	SDL_Surface *screen = SDL_SetVideoMode(screenWidth, screenHeight, bitsPerPixel, sdlflags);
    +	if (!screen) {
    +		char buf[1024];
    +		SNPRINTF(buf, sizeof(buf), "Could not set video mode:\n%s", SDL_GetError());
    +		handleerror(NULL, buf, "ERROR", MBF_OK|MBF_EXCL);
    +		return false;
    +	}
    +
    +#ifdef STREFLOP_H
    +	// Something in SDL_SetVideoMode (OpenGL drivers?) messes with the FPU control word.
    +	// Set single precision floating point math.
    +	streflop_init<streflop::Simple>();
    +#endif
    +
    +	if (FSAA) {
    + 		FSAA = MultisampleVerify();
    +	}
    +
    +	// setup GL smoothing
    +	const int defaultSmooth = 0; // FSAA ? 0 : 3;  // until a few things get fixed
    +	const int lineSmoothing = configHandler.GetInt("SmoothLines", defaultSmooth);
    +	if (lineSmoothing > 0) {
    +		GLenum hint = GL_FASTEST;
    +		if (lineSmoothing >= 3) {
    +			hint = GL_NICEST;
    +		} else if (lineSmoothing >= 2) {
    +			hint = GL_DONT_CARE;
    +		}
    +		glEnable(GL_LINE_SMOOTH);
    +		glHint(GL_LINE_SMOOTH_HINT, hint);
    +	}
    +	const int pointSmoothing = configHandler.GetInt("SmoothPoints", defaultSmooth);
    +	if (pointSmoothing > 0) {
    +		GLenum hint = GL_FASTEST;
    +		if (pointSmoothing >= 3) {
    +			hint = GL_NICEST;
    +		} else if (pointSmoothing >= 2) {
    +			hint = GL_DONT_CARE;
    +		}
    +		glEnable(GL_POINT_SMOOTH);
    +		glHint(GL_POINT_SMOOTH_HINT, hint);
    +	}
    +
    +	// setup LOD bias factor
    +	const float lodBias = std::max(std::min( configHandler.GetFloat("TextureLODBias", 0.0f) , 4.0f), -4.0f);
    +	if (fabs(lodBias)>0.01f) {
    +		glTexEnvf(GL_TEXTURE_FILTER_CONTROL,GL_TEXTURE_LOD_BIAS, lodBias );
    +	}
    +
    +	// there must be a way to see if this is necessary, compare old/new context pointers?
    +	if (!!configHandler.GetInt("FixAltTab", 0)) {
    +		// free GL resources
    +		GLContext::Free();
    +
    +		// initialize any GL resources that were lost
    +		GLContext::Init();
    +	}
    +
    +	// initialize the stencil
    +	glClearStencil(0);
    +	glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    +	glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    +
    +	int bits;
    +	SDL_GL_GetAttribute(SDL_GL_BUFFER_SIZE, &bits);
    +	logOutput.Print("Video mode set to  %i x %i / %i bit", screenWidth, screenHeight, bits );
    +	VSync.Init();
    +
    +	return true;
    +}
    +
    +
    +// origin for our coordinates is the bottom left corner
    +bool SpringApp::GetDisplayGeometry()
    +{
    +	SDL_SysWMinfo info;
    +	SDL_VERSION(&info.version);
    +
    +	if (!SDL_GetWMInfo(&info)) {
    +		return false;
    +	}
    +
    +#ifdef __APPLE__
    +	return false;
    +#elif !defined(_WIN32)
    +	info.info.x11.lock_func();
    +	{
    +		Display* display = info.info.x11.display;
    +		Window   window  = info.info.x11.window;
    +
    +		XWindowAttributes attrs;
    +		XGetWindowAttributes(display, window, &attrs);
    +		const Screen* screen = attrs.screen;
    +		gu->screenSizeX = WidthOfScreen(screen);
    +		gu->screenSizeY = HeightOfScreen(screen);
    +		gu->winSizeX = attrs.width;
    +		gu->winSizeY = attrs.height;
    +
    +		Window tmp;
    +		int xp, yp;
    +		XTranslateCoordinates(display, window, attrs.root, 0, 0, &xp, &yp, &tmp);
    +		gu->winPosX = xp;
    +		gu->winPosY = gu->screenSizeY - gu->winSizeY - yp;
    +	}
    +	info.info.x11.unlock_func();
    +#else
    +	gu->screenSizeX = GetSystemMetrics(SM_CXFULLSCREEN);
    +	gu->screenSizeY = GetSystemMetrics(SM_CYFULLSCREEN);
    +
    +	RECT rect;
    +	if (!GetClientRect(info.window, &rect)) {
    +		return false;
    +	}
    +
    +	if((rect.right - rect.left)==0 || (rect.bottom - rect.top)==0)
    +		return false;
    +
    +	gu->winSizeX = rect.right - rect.left;
    +	gu->winSizeY = rect.bottom - rect.top;
    +
    +	// translate from client coords to screen coords
    +	MapWindowPoints(info.window, HWND_DESKTOP, (LPPOINT)&rect, 2);
    +	gu->winPosX = rect.left;
    +	gu->winPosY = gu->screenSizeY - gu->winSizeY - rect.top;
    +#endif // _WIN32
    +	return true;
    +}
    +
    +
    +void SpringApp::SetupViewportGeometry()
    +{
    +	if (!GetDisplayGeometry()) {
    +		gu->screenSizeX = screenWidth;
    +		gu->screenSizeY = screenHeight;
    +		gu->winSizeX = screenWidth;
    +		gu->winSizeY = screenHeight;
    +		gu->winPosX = 0;
    +		gu->winPosY = 0;
    +	}
    +
    +	gu->dualScreenMode = !!configHandler.GetInt("DualScreenMode", 0);
    +	if (gu->dualScreenMode) {
    +		gu->dualScreenMiniMapOnLeft =
    +			!!configHandler.GetInt("DualScreenMiniMapOnLeft", 0);
    +	} else {
    +		gu->dualScreenMiniMapOnLeft = false;
    +	}
    +
    +	if (!gu->dualScreenMode) {
    +		gu->viewSizeX = gu->winSizeX;
    +		gu->viewSizeY = gu->winSizeY;
    +		gu->viewPosX = 0;
    +		gu->viewPosY = 0;
    +	}
    +	else {
    +		gu->viewSizeX = gu->winSizeX / 2;
    +		gu->viewSizeY = gu->winSizeY;
    +		if (gu->dualScreenMiniMapOnLeft) {
    +			gu->viewPosX = gu->winSizeX / 2;
    +			gu->viewPosY = 0;
    +		} else {
    +			gu->viewPosX = 0;
    +			gu->viewPosY = 0;
    +		}
    +	}
    +
    +	gu->pixelX = 1.0f / (float)gu->viewSizeX;
    +	gu->pixelY = 1.0f / (float)gu->viewSizeY;
    +
    +	// NOTE:  gu->viewPosY is not currently used
    +
    +	gu->aspectRatio = (float)gu->viewSizeX / (float)gu->viewSizeY;
    +}
    +
    +
    +/**
    + * Initializes OpenGL
    + */
    +void SpringApp::InitOpenGL ()
    +{
    +	SetupViewportGeometry();
    +
    +	glViewport(gu->viewPosX, gu->viewPosY, gu->viewSizeX, gu->viewSizeY);
    +
    +	gluPerspective(45.0f, (GLfloat)gu->viewSizeX / (GLfloat)gu->viewSizeY, 2.8f, MAX_VIEW_RANGE);
    +
    +	// Initialize some GL states
    +	glShadeModel(GL_SMOOTH);
    +	glClearDepth(1.0f);
    +	glEnable(GL_DEPTH_TEST);
    +	glDepthFunc(GL_LEQUAL);
    +}
    +
    +/**
    + * @return whether commandline parsing was successful
    + *
    + * Parse command line arguments
    + */
    +void SpringApp::ParseCmdLine()
    +{
    +	cmdline->addoption('f', "fullscreen",     OPTPARM_NONE,   "",  "Run in fullscreen mode");
    +	cmdline->addoption('w', "window",         OPTPARM_NONE,   "",  "Run in windowed mode");
    +	cmdline->addoption('x', "xresolution",    OPTPARM_INT,    "",  "Set X resolution");
    +	cmdline->addoption('y', "yresolution",    OPTPARM_INT,    "",  "Set Y resolution");
    +	cmdline->addoption('m', "minimise",       OPTPARM_NONE,   "",  "Start minimised");
    +	cmdline->addoption('s', "server",         OPTPARM_NONE,   "",  "Run as a server");
    +	cmdline->addoption('c', "client",         OPTPARM_NONE,   "",  "Run as a client");
    +	cmdline->addoption('p', "projectiledump", OPTPARM_NONE,   "",  "Dump projectile class info in projectiles.txt");
    +	cmdline->addoption('t', "textureatlas",   OPTPARM_NONE,   "",  "Dump each finalized textureatlas in textureatlasN.tga");
    +	cmdline->addoption('q', "quit",           OPTPARM_INT,    "T", "Quit immediately on game over or after T seconds");
    +	cmdline->addoption('n', "name",           OPTPARM_STRING, "",  "Set your player name");
    +	cmdline->parse();
    +
    +#ifdef _DEBUG
    +	fullscreen = false;
    +#else
    +	fullscreen = configHandler.GetInt("Fullscreen", 1) != 0;
    +#endif
    +
    +	// mutually exclusive options that cause spring to quit immediately
    +	if (cmdline->result("help")) {
    +		cmdline->usage("Spring",VERSION_STRING);
    +		exit(0);
    +	} else if (cmdline->result("version")) {
    +		std::cout << "Spring " << VERSION_STRING << std::endl;
    +		exit(0);
    +	} else if (cmdline->result("projectiledump")) {
    +		CCustomExplosionGenerator::OutputProjectileClassInfo();
    +		exit(0);
    +	}
    +
    +	// flags
    +	if (cmdline->result("window")) {
    +		fullscreen = false;
    +	} else if (cmdline->result("fullscreen")) {
    +		fullscreen = true;
    +	}
    +
    +	if (cmdline->result("textureatlas")) {
    +		CTextureAtlas::debug = true;
    +	}
    +
    +	string name;
    +	if (cmdline->result("name", name)) {
    +		configHandler.SetString("name", name);
    +	}
    +
    +
    +	if (!cmdline->result("xresolution", screenWidth)) {
    +		screenWidth = configHandler.GetInt("XResolution", XRES_DEFAULT);
    +	} else {
    +		screenWidth = std::max(screenWidth, 1);
    +	}
    +	
    +	if (!cmdline->result("yresolution", screenHeight)) {
    +		screenHeight = configHandler.GetInt("YResolution", YRES_DEFAULT);
    +	} else {
    +		screenHeight = std::max(screenHeight, 1);
    +	}
    +	
    +}
    +
    +/**
    + * @param argc argument count
    + * @param argv array of argument strings
    + *
    + * Checks if a demo SDF file or a startscript has
    + * been specified on the command line
    + */
    +void SpringApp::CheckCmdLineFile(int argc, char *argv[])
    +{
    +	// Check if the commandline parameter is specifying a demo file
    +#ifdef _WIN32
    +	// find the correct dir
    +	char exe[128];
    +	GetModuleFileName(0, exe, sizeof(exe));
    +	int a,s = strlen(exe);
    +	for (a=s-1;a>0;a--)
    +	    // Running in gdb causes the last dir separator to be a forward slash.
    +		if (exe[a] == '\\' || exe[a] == '/') break;
    +	if (a > 0) {
    +		string path(exe, exe+a);
    +		if (path.at(0) == '"')
    +			path.append(1,'"');
    +		_chdir(path.c_str());
    +	}
    +
    +	// If there are any options, they will start before the demo file name.
    +
    +   if (win_lpCmdLine == 0)
    +   logOutput.Print("ERROR");
    +	string cmdLineStr = win_lpCmdLine;
    +	string::size_type offset = 0;
    +	//Simply assumes that any argument coming after a argument starting with /q is a variable to /q.
    +	for(int i=1; i < argc && (argv[i][0] == '/' || (argv[i-1][0] == '/' && (argv[i-1][1] == 'q' || argv[i-1][1] == 'a'))); i++){
    +		offset += strlen(argv[i]);
    +		offset = cmdLineStr.find_first_not_of(' ', offset);
    +		if(offset == string::npos)
    +			break;
    +	}
    +
    +	string command;
    +	if(offset != string::npos)
    +		command = cmdLineStr.substr(offset);
    +
    +
    +	if (!command.empty()) {
    +		if (command[0] == '"' && *command.rbegin() == '"' && command.length() > 2)
    +			command = command.substr(1, command.length()-2);
    +		if (command.rfind("sdf") == command.size()-3) {
    +			demofile = command;
    +			logOutput << "Using demofile " << demofile.c_str() << "\n";
    +		} else if (command.rfind("ssf") == command.size()-3) {
    +			savefile = command;
    +			logOutput << "Using savefile " << savefile.c_str() << "\n";
    +		} else {
    +			startscript = command;
    +			logOutput << "Using script " << startscript.c_str() << "\n";
    +		}
    +	}
    +#else
    +	// is there a reason for not using this in windows?
    +	for (int i = 1; i < argc; i++)
    +		if (argv[i][0] != '-')
    +		{
    +			string command(argv[i]);
    +			int idx = command.rfind("sdf");
    +			if (idx == command.size()-3) {
    +				demofile = command;
    +				logOutput << "Using demofile " << demofile.c_str() << "\n";
    +			} else if (command.rfind("ssf") == command.size()-3) {
    +				savefile = command;
    +				logOutput << "Using savefile " << savefile.c_str() << "\n";
    +			} else {
    +				startscript = command;
    +				logOutput << "Using script " << startscript.c_str() << "\n";
    +			}
    +		}
    +#endif
    +}
    +
    +/**
    + * Initializes instance of GameSetup
    + */
    +void SpringApp::CreateGameSetup()
    +{
    +	ENTER_SYNCED;
    +
    +	if (!startscript.empty()) {
    +		gameSetup = SAFE_NEW CGameSetup();
    +		if (!gameSetup->Init(startscript)) {
    +			delete gameSetup;
    +			gameSetup = 0;
    +		}
    +	}
    +
    +	if (!gameSetup && demofile.empty()) {
    +		gs->noHelperAIs = !!configHandler.GetInt("NoHelperAIs", 0);
    +		const string luaGaiaStr  = configHandler.GetString("LuaGaia",  "1");
    +		const string luaRulesStr = configHandler.GetString("LuaRules", "1");
    +		gs->useLuaGaia  = CLuaGaia::SetConfigString(luaGaiaStr);
    +		gs->useLuaRules = CLuaRules::SetConfigString(luaRulesStr);
    +		if (gs->useLuaGaia) {
    +			gs->gaiaTeamID = gs->activeTeams;
    +			gs->gaiaAllyTeamID = gs->activeAllyTeams;
    +			gs->activeTeams++;
    +			gs->activeAllyTeams++;
    +			CTeam* team = gs->Team(gs->gaiaTeamID);
    +			team->color[0] = 255;
    +			team->color[1] = 255;
    +			team->color[2] = 255;
    +			team->color[3] = 255;
    +			team->gaia = true;
    +			gs->SetAllyTeam(gs->gaiaTeamID, gs->gaiaAllyTeamID);
    +		}
    +	}
    +
    +	ENTER_MIXED;
    +
    +	bool server = true;
    +
    +	if (!demofile.empty()) {
    +		server = false;
    +	}
    +	else if (gameSetup) {
    +		// first real player is demo host
    +		server = (gameSetup->myPlayerNum == gameSetup->numDemoPlayers) && !cmdline->result("client");
    +	}
    +	else {
    +		server = !cmdline->result("client") || cmdline->result("server");
    +	}
    +
    +#ifdef SYNCDEBUG
    +	// initialize sync debugger as soon as we know whether we will be server
    +	CSyncDebugger::GetInstance()->Initialize(server);
    +#endif
    +
    +	if (!demofile.empty()) {
    +		pregame = SAFE_NEW CPreGame(false, demofile, "");
    +	} else {
    +		pregame = SAFE_NEW CPreGame(server, "", savefile);
    +	}
    +}
    +
    +
    +/**
    + * @return return code of activecontroller draw function
    + *
    + * Draw function repeatedly called, it calls all the
    + * other draw functions
    + */
    +int SpringApp::Update ()
    +{
    +	if (FSAA)
    +		glEnable(GL_MULTISAMPLE_ARB);
    +
    +	mouseInput->Update();
    +
    +	int ret = 1;
    +	if (activeController) {
    +		if (!activeController->Update()) {
    +			ret = 0;
    +		} else {
    +			ret = activeController->Draw();
    +		}
    +	}
    +
    +	VSync.Delay();
    +	SDL_GL_SwapBuffers();
    +
    +	if (FSAA)
    +		glDisable(GL_MULTISAMPLE_ARB);
    +
    +	return ret;
    +}
    +
    +/**
    + * Tests SDL keystates and sets values
    + * in key array
    + */
    +void SpringApp::UpdateSDLKeys ()
    +{
    +	int numkeys;
    +	Uint8 *state;
    +	state = SDL_GetKeyState(&numkeys);
    +	memcpy(keys, state, sizeof(Uint8) * numkeys);
    +
    +	const SDLMod mods = SDL_GetModState();
    +	keys[SDLK_LALT]   = (mods & KMOD_ALT)   ? 1 : 0;
    +	keys[SDLK_LCTRL]  = (mods & KMOD_CTRL)  ? 1 : 0;
    +	keys[SDLK_LMETA]  = (mods & KMOD_META)  ? 1 : 0;
    +	keys[SDLK_LSHIFT] = (mods & KMOD_SHIFT) ? 1 : 0;
    +}
    +
    +/**
    + * @param argc argument count
    + * @param argv array of argument strings
    + *
    + * Executes the application
    + * (contains main game loop)
    + */
    +int SpringApp::Run (int argc, char *argv[])
    +{
    +	INIT_SYNCIFY;
    +	CheckCmdLineFile (argc, argv);
    +	cmdline = BaseCmd::initialize(argc,argv);
    +/*
    +	logOutput.Print ("Testing error catching");
    +	try {
    +		int *i_=0;
    +		*i_=1;
    +		logOutput.Print ("Error catching doesn't work!");
    +	} catch(...) {
    +		logOutput.Print ("Error catching works!");
    +	}
    +*/
    +	if (!Initialize ())
    +		return -1;
    +
    +#ifdef WIN32
    +	SDL_EventState (SDL_SYSWMEVENT, SDL_ENABLE);
    +#endif
    +
    +	SDL_Event event;
    +	bool done = false;
    +
    +	while (!done) {
    +		ENTER_UNSYNCED;
    +		while (SDL_PollEvent(&event)) {
    +			switch (event.type) {
    +				case SDL_VIDEORESIZE: {
    +					screenWidth = event.resize.w;
    +					screenHeight = event.resize.h;
    +#ifndef WIN32
    +					// HACK   We don't want to break resizing on windows (again?),
    +					//        so someone should test this very well before enabling it.
    +					SetSDLVideoMode();
    +#endif
    +					InitOpenGL();
    +					activeController->ResizeEvent();
    +					break;
    +				}
    +				case SDL_VIDEOEXPOSE: {
    +					// re-initialize the stencil
    +					glClearStencil(0);
    +					glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    +					glClear(GL_STENCIL_BUFFER_BIT); SDL_GL_SwapBuffers();
    +					SetupViewportGeometry();
    +					break;
    +				}
    +				case SDL_QUIT: {
    +					done = true;
    +					break;
    +				}
    +				case SDL_ACTIVEEVENT: {
    +					if (event.active.state & SDL_APPACTIVE) {
    +						gu->active = !!event.active.gain;
    +					}
    +					break;
    +				}
    +				case SDL_MOUSEMOTION:
    +				case SDL_MOUSEBUTTONDOWN:
    +				case SDL_MOUSEBUTTONUP:
    +				case SDL_SYSWMEVENT: {
    +					mouseInput->HandleSDLMouseEvent (event);
    +					break;
    +				}
    +				case SDL_KEYDOWN: {
    +					int i = event.key.keysym.sym;
    +
    +					const bool isRepeat = !!keys[i];
    +
    +					UpdateSDLKeys ();
    +
    +					if (activeController) {
    +						if (i <= SDLK_DELETE) {
    +							i = tolower(i);
    +						}
    +						else if (i == SDLK_RSHIFT) { i = SDLK_LSHIFT; }
    +						else if (i == SDLK_RCTRL)  { i = SDLK_LCTRL;  }
    +						else if (i == SDLK_RMETA)  { i = SDLK_LMETA;  }
    +						else if (i == SDLK_RALT)   { i = SDLK_LALT;   }
    +
    +						if (keyBindings) {
    +							const int fakeMetaKey = keyBindings->GetFakeMetaKey();
    +							if (fakeMetaKey >= 0) {
    +								keys[SDLK_LMETA] |= keys[fakeMetaKey];
    +							}
    +						}
    +
    +						activeController->KeyPressed(i, isRepeat);
    +
    +						if (activeController->userWriting){
    +							// use unicode for printed characters
    +							i = event.key.keysym.unicode;
    +							if ((i >= SDLK_SPACE) && (i <= SDLK_DELETE)) {
    +								CGameController* ac = activeController;
    +								if (ac->ignoreNextChar || ac->ignoreChar == char(i)) {
    +									ac->ignoreNextChar = false;
    +								} else {
    +									if (i < SDLK_DELETE) {
    +										const int len = (int)ac->userInput.length();
    +										ac->writingPos = std::max(0, std::min(len, ac->writingPos));
    +										char str[2] = { char(i), 0 };
    +										ac->userInput.insert(ac->writingPos, str);
    +										ac->writingPos++;
    +									}
    +								}
    +							}
    +						}
    +					}
    +					activeController->ignoreNextChar = false;
    +					break;
    +				}
    +				case SDL_KEYUP: {
    +					int i = event.key.keysym.sym;
    +
    +					UpdateSDLKeys();
    +
    +					if (activeController) {
    +						if (i <= SDLK_DELETE) {
    +							i = tolower(i);
    +						}
    +						else if (i == SDLK_RSHIFT) { i = SDLK_LSHIFT; }
    +						else if (i == SDLK_RCTRL)  { i = SDLK_LCTRL;  }
    +						else if (i == SDLK_RMETA)  { i = SDLK_LMETA;  }
    +						else if (i == SDLK_RALT)   { i = SDLK_LALT;   }
    +
    +						if (keyBindings) {
    +							const int fakeMetaKey = keyBindings->GetFakeMetaKey();
    +							if (fakeMetaKey >= 0) {
    +								keys[SDLK_LMETA] |= keys[fakeMetaKey];
    +							}
    +						}
    +
    +						activeController->KeyReleased(i);
    +					}
    +					break;
    +				}
    +				default:
    +					break;
    +			}
    +		}
    +		if (globalQuit)
    +			break;
    +
    +		if (!Update())
    +			break;
    +	}
    +	ENTER_MIXED;
    +
    +	// Shutdown
    +	Shutdown();
    +	return 0;
    +}
    +
    +/**
    + * Deallocates and shuts down game
    + */
    +void SpringApp::Shutdown()
    +{
    +	if (pregame)
    +		delete pregame;			//in case we exit during init
    +	if (game)
    +		delete game;
    +	if (gameSetup)
    +		delete gameSetup;
    +	delete font;
    +	CNamedTextures::Kill();
    +	GLContext::Free();
    +	ConfigHandler::Deallocate();
    +	UnloadExtensions();
    +	delete mouseInput;
    +	SDL_WM_GrabInput(SDL_GRAB_OFF);
    +	SDL_Quit();
    +	delete gs;
    +	delete gu;
    +	END_SYNCIFY;
    +#ifdef USE_MMGR
    +	m_dumpMemoryReport();
    +#endif
    +}
    
    patch file icon rendering.patch (90,543 bytes) 2008-05-10 16:29 +
  • patch file icon ui.patch (12,472 bytes) 2008-05-10 16:29 -
    Index: Documentation/cmds.txt
    ===================================================================
    --- Documentation/cmds.txt	(revision 5850)
    +++ Documentation/cmds.txt	(working copy)
    @@ -80,7 +80,7 @@
     pause
     
     shadows [<0|1> [mapsize]]
    -water   [0|1|2|3]
    +water   [0|1|2|3|4]
     vsync   [-1|0|1|2|...]  --  -1 will use default setting in windows,
                             --  numbers higher then 1 will result in
                             --  rendering every N frames.
    @@ -145,6 +145,7 @@
     cross <size>  -- locked mouse cross size
     
     volume <float>  -- 0.0 to 1.0
    +unitreplyvolume <float>  -- 0.0 to 1.0
     
     toggleoverview
     showhealthbars
    @@ -188,6 +189,7 @@
     screenshot ["png"]
     
     grabinput
    +hardwarecursor [0|1]
     
     bind
     unbind
    @@ -222,6 +224,7 @@
     minimap <"fullproxy">    [0|1]
     minimap <"icons">        [0|1]
     minimap <"drawcommands"> [0|1]
    +minimap <"drawprojectiles"> [0|1]
     minimap <"simplecolors"> [0|1]
     minimap <"min" | "minimize"> [0|1]
     minimap <"max" | "maximize"> [0|1]
    Index: rts/Game/Game.cpp
    ===================================================================
    --- rts/Game/Game.cpp	(revision 5850)
    +++ rts/Game/Game.cpp	(working copy)
    @@ -193,6 +193,7 @@
     
     	CR_MEMBER(soundEnabled),
     	CR_MEMBER(gameSoundVolume),
    +	CR_MEMBER(unitReplyVolume),
     
     //	CR_MEMBER(script),
     	CR_RESERVED(64),
    @@ -283,9 +284,10 @@
     	ENTER_UNSYNCED;
     	sound = CSound::GetSoundSystem();
     	gameSoundVolume = configHandler.GetInt("SoundVolume", 60) * 0.01f;
    +	unitReplyVolume = configHandler.GetInt("UnitReplyVolume", configHandler.GetInt("UnitReplySoundVolume", 80) ) * 0.01f;
     	soundEnabled = true;
     	sound->SetVolume(gameSoundVolume);
    -	sound->SetUnitReplyVolume(configHandler.GetInt ("UnitReplySoundVolume", 80) * 0.01f);
    +	sound->SetUnitReplyVolume(unitReplyVolume);
     
     	camera = SAFE_NEW CCamera();
     	cam2 = SAFE_NEW CCamera();
    @@ -496,6 +498,8 @@
     		net->SendStartPlaying(0);
     
     	lastCpuUsageTime = gu->gameTime + 10;
    +
    +	mouse->ShowMouse();
     }
     
     
    @@ -906,14 +910,14 @@
     	else if (cmd == "water") {
     		delete water;
     
    -		static char rmodes[4][32] = {"basic", "reflective", "dynamic", "reflective&refractive"};
    +		static char rmodes[5][32] = {"basic", "reflective", "dynamic", "reflective&refractive", "bumpmapped"};
     		int next = 0;
     
     		if (!action.extra.empty()) {
    -			next = std::max(0, atoi(action.extra.c_str()) % 4);
    +			next = std::max(0, atoi(action.extra.c_str()) % 5);
     		} else {
     			const int current = configHandler.GetInt("ReflectiveWater", 1);
    -			next = (std::max(0, current) + 1) % 4;
    +			next = (std::max(0, current) + 1) % 5;
     		}
     		configHandler.SetInt("ReflectiveWater", next);
     		logOutput.Print("Set water rendering mode to %i (%s)", next, rmodes[next]);
    @@ -1206,6 +1210,16 @@
     			configHandler.SetInt("SoundVolume", (int)(gameSoundVolume * 100.0f));
     		}
     	}
    +	else if (cmd == "unitreplyvolume") {
    +		char* endPtr;
    +		const char* startPtr = action.extra.c_str();
    +		float volume = (float)strtod(startPtr, &endPtr);
    +		if (endPtr != startPtr) {
    +			unitReplyVolume = std::max(0.0f, std::min(1.0f, volume));
    +			sound->SetUnitReplyVolume(unitReplyVolume);
    +			configHandler.SetInt("UnitReplyVolume",(int)(unitReplyVolume * 100.0f));
    +		}
    +	}
     	else if (cmd == "savegame"){
     		if (filesystem.CreateDirectory("Saves")) {
     			CLoadSaveHandler ls;
    @@ -1292,6 +1306,15 @@
     			hideInterface = !!atoi(action.extra.c_str());
     		}
     	}
    +	else if (cmd == "hardwarecursor") {
    +		if (action.extra.empty()) {
    +			mouse->hardwareCursor = !mouse->hardwareCursor;
    +		} else {
    +			mouse->hardwareCursor = !!atoi(action.extra.c_str());
    +		}
    +		mouse->UpdateHwCursor();
    +		configHandler.SetInt("HardwareCursor", (int)mouse->hardwareCursor);
    +	}
     	else if (cmd == "increaseviewradius") {
     		gd->IncreaseDetail();
     	}
    @@ -1315,8 +1338,12 @@
     		logOutput << "Cloud density " << 1/sky->cloudDensity << "\n";
     	}
     
    +	// Break up the if/else chain to workaround MSVC compiler limit
    +	// "fatal error C1061: compiler limit : blocks nested too deeply"
    +	else notfound1=true;
    +	if (notfound1)
     
    -	else if (cmd == "speedup") {
    +	if (cmd == "speedup") {
     		float speed = gs->userSpeedFactor;
     		if (speed < 1) {
     			speed /= 0.8f;
    @@ -1351,11 +1378,7 @@
     	}
     #endif
     
    -	// Break up the if/else chain to workaround MSVC compiler limit
    -	// "fatal error C1061: compiler limit : blocks nested too deeply"
    -	else notfound1=true;
    -	if (notfound1)
    -	if (cmd == "showshadowmap") {
    +	else if (cmd == "showshadowmap") {
     		shadowHandler->showShadowMap = !shadowHandler->showShadowMap;
     	}
     	else if (cmd == "showstandard") {
    @@ -1753,9 +1776,11 @@
     	}
     	else if (cmd == "wiremap") {
     		if (action.extra.empty()) {
    -			gd->wireframe = !gd->wireframe;
    +			gd->wireframe  = !gd->wireframe;
    +			sky->wireframe = gd->wireframe;
     		} else {
    -			gd->wireframe = !atoi(action.extra.c_str());
    +			gd->wireframe  = !atoi(action.extra.c_str());
    +			sky->wireframe = gd->wireframe;
     		}
     	}
     	else if (cmd == "setgamma") {
    @@ -2384,7 +2409,7 @@
     	SCOPED_TIMER("Draw world");
     
     	CBaseGroundDrawer* gd = readmap->GetGroundDrawer();
    -
    +	
     	if (drawSky) {
     		sky->Draw();
     	}
    @@ -2420,6 +2445,7 @@
     			water->Draw();
     		}
     	}
    +
     	unitDrawer->DrawCloakedUnits();
     	ph->Draw(false);
     
    Index: rts/Game/Game.h
    ===================================================================
    --- rts/Game/Game.h	(revision 5850)
    +++ rts/Game/Game.h	(working copy)
    @@ -97,6 +97,7 @@
     
     	bool soundEnabled;
     	float gameSoundVolume;
    +	float unitReplyVolume;
     
     	CScript* script;
     
    Index: rts/Game/UI/MiniMap.cpp
    ===================================================================
    --- rts/Game/UI/MiniMap.cpp	(revision 5850)
    +++ rts/Game/UI/MiniMap.cpp	(working copy)
    @@ -115,6 +115,8 @@
     
     	drawCommands = std::max(0, configHandler.GetInt("MiniMapDrawCommands", 1));
     
    +	drawProjectiles = !!configHandler.GetInt("MiniMapDrawProjectiles", 1);
    +
     	simpleColors = !!configHandler.GetInt("SimpleMiniMapColors", 0);
     
     	myColor[0]    = (unsigned char)(0.2f * 255);
    @@ -352,6 +354,14 @@
     			drawCommands = (drawCommands > 0) ? 0 : 1;
     		}
     	}
    +	else if (command == "drawprojectiles") {
    +		if (words.size() >= 2) {
    +			drawProjectiles = !!atoi(words[1].c_str());
    +
    +		} else {
    +			drawProjectiles = !drawProjectiles;
    +		}
    +	}
     	else if (command == "simplecolors") {
     		if (words.size() >= 2) {
     			simpleColors = !!atoi(words[1].c_str());
    @@ -1060,57 +1070,59 @@
     	// draw the projectiles
     	glRotatef(-90.0f, +1.0f, 0.0f, 0.0f); // real 'world' coordinates
     
    -	Projectile_List::iterator psi;
    -	for(psi = ph->ps.begin(); psi != ph->ps.end(); ++psi) {
    -		CProjectile* p = *psi;
    +	if (drawProjectiles) {
    +		Projectile_List::iterator psi;
    +		for(psi = ph->ps.begin(); psi != ph->ps.end(); ++psi) {
    +			CProjectile* p = *psi;
     
    -		if ((p->owner && (p->owner->allyteam == gu->myAllyTeam)) ||
    -			gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam)) {
    +			if ((p->owner && (p->owner->allyteam == gu->myAllyTeam)) ||
    +				gu->spectatingFullView || loshandler->InLos(p, gu->myAllyTeam)) {
     
    -			if (dynamic_cast<CGeoThermSmokeProjectile*>(p)) {
    -			} else if (dynamic_cast<CGfxProjectile*>(p)) {//Nano-piece
    -				glBegin(GL_POINTS);
    -				glColor4f(0,1,0,0.1);
    -				glVertexf3(p->pos);
    -				glEnd();
    -			} else if (dynamic_cast<CBeamLaserProjectile*>(p)) {
    -				glBegin(GL_LINES);
    -				glColor4f(((CBeamLaserProjectile*)p)->kocolstart[0]/255.0,((CBeamLaserProjectile*)p)->kocolstart[1]/255.0,((CBeamLaserProjectile*)p)->kocolstart[2]/255.0,1);
    -				glVertexf3(((CBeamLaserProjectile*)p)->startPos);
    -				glVertexf3(((CBeamLaserProjectile*)p)->endPos);
    -				glEnd();
    -			} else if (dynamic_cast<CLargeBeamLaserProjectile*>(p)) {
    -				glBegin(GL_LINES);
    -				glColor4f(((CLargeBeamLaserProjectile*)p)->kocolstart[0]/255.0,((CLargeBeamLaserProjectile*)p)->kocolstart[1]/255.0,((CLargeBeamLaserProjectile*)p)->kocolstart[2]/255.0,1);
    -				glVertexf3(((CLargeBeamLaserProjectile*)p)->startPos);
    -				glVertexf3(((CLargeBeamLaserProjectile*)p)->endPos);
    -				glEnd();
    -			} else if (dynamic_cast<CLightingProjectile*>(p)) {
    -				glBegin(GL_LINES);
    -				glColor4f(((CLightingProjectile*)p)->color[0],((CLightingProjectile*)p)->color[1],((CLightingProjectile*)p)->color[2],1);
    -				glVertexf3(((CLightingProjectile*)p)->pos);
    -				glVertexf3(((CLightingProjectile*)p)->endPos);
    -				glEnd();
    -			} else if (dynamic_cast<CPieceProjectile*>(p)) {
    -				glBegin(GL_POINTS);
    -				glColor4f(1,0,0,1);
    -				glVertexf3(p->pos);
    -				glEnd();
    -			} else if (dynamic_cast<CWreckProjectile*>(p)) {
    -				glBegin(GL_POINTS);
    -				glColor4f(1,0,0,0.5);
    -				glVertexf3(p->pos);
    -				glEnd();
    -			} else if (dynamic_cast<CWeaponProjectile*>(p)) {
    -				glBegin(GL_POINTS);
    -				glColor4f(1,1,0,1);
    -				glVertexf3(p->pos);
    -				glEnd();
    -			} else {
    -				glBegin(GL_POINTS);
    -				glColor4f(1,1,1,0.1/*0.0002f*(width+height)*/);
    -				glVertexf3(p->pos);
    -				glEnd();
    +				if (dynamic_cast<CGeoThermSmokeProjectile*>(p)) {
    +				} else if (dynamic_cast<CGfxProjectile*>(p)) {//Nano-piece
    +					glBegin(GL_POINTS);
    +					glColor4f(0,1,0,0.1);
    +					glVertexf3(p->pos);
    +					glEnd();
    +				} else if (dynamic_cast<CBeamLaserProjectile*>(p)) {
    +					glBegin(GL_LINES);
    +					glColor4f(((CBeamLaserProjectile*)p)->kocolstart[0]/255.0,((CBeamLaserProjectile*)p)->kocolstart[1]/255.0,((CBeamLaserProjectile*)p)->kocolstart[2]/255.0,1);
    +					glVertexf3(((CBeamLaserProjectile*)p)->startPos);
    +					glVertexf3(((CBeamLaserProjectile*)p)->endPos);
    +					glEnd();
    +				} else if (dynamic_cast<CLargeBeamLaserProjectile*>(p)) {
    +					glBegin(GL_LINES);
    +					glColor4f(((CLargeBeamLaserProjectile*)p)->kocolstart[0]/255.0,((CLargeBeamLaserProjectile*)p)->kocolstart[1]/255.0,((CLargeBeamLaserProjectile*)p)->kocolstart[2]/255.0,1);
    +					glVertexf3(((CLargeBeamLaserProjectile*)p)->startPos);
    +					glVertexf3(((CLargeBeamLaserProjectile*)p)->endPos);
    +					glEnd();
    +				} else if (dynamic_cast<CLightingProjectile*>(p)) {
    +					glBegin(GL_LINES);
    +					glColor4f(((CLightingProjectile*)p)->color[0],((CLightingProjectile*)p)->color[1],((CLightingProjectile*)p)->color[2],1);
    +					glVertexf3(((CLightingProjectile*)p)->pos);
    +					glVertexf3(((CLightingProjectile*)p)->endPos);
    +					glEnd();
    +				} else if (dynamic_cast<CPieceProjectile*>(p)) {
    +					glBegin(GL_POINTS);
    +					glColor4f(1,0,0,1);
    +					glVertexf3(p->pos);
    +					glEnd();
    +				} else if (dynamic_cast<CWreckProjectile*>(p)) {
    +					glBegin(GL_POINTS);
    +					glColor4f(1,0,0,0.5);
    +					glVertexf3(p->pos);
    +					glEnd();
    +				} else if (dynamic_cast<CWeaponProjectile*>(p)) {
    +					glBegin(GL_POINTS);
    +					glColor4f(1,1,0,1);
    +					glVertexf3(p->pos);
    +					glEnd();
    +				} else {
    +					glBegin(GL_POINTS);
    +					glColor4f(1,1,1,0.1/*0.0002f*(width+height)*/);
    +					glVertexf3(p->pos);
    +					glEnd();
    +				}
     			}
     		}
     	}
    @@ -1120,7 +1132,7 @@
     	// NOTE: this needlessly adds to the CursorIcons list, but at least
     	//       they are not drawn  (because the input receivers are drawn
     	//       after the command queues)
    -  LuaUnsyncedCtrl::DrawUnitCommandQueues();
    +	LuaUnsyncedCtrl::DrawUnitCommandQueues();
     	if ((drawCommands > 0) && guihandler->GetQueueKeystate()) {
     	  selectedUnits.DrawCommands();
     	}
    Index: rts/Game/UI/MiniMap.h
    ===================================================================
    --- rts/Game/UI/MiniMap.h	(revision 5850)
    +++ rts/Game/UI/MiniMap.h	(working copy)
    @@ -122,6 +122,7 @@
     		int lastWindowSizeX;
     		int lastWindowSizeY;
     		
    +		bool drawProjectiles;
     		bool useIcons;
     		int drawCommands;
     		float cursorScale;
    Index: rts/Game/WordCompletion.cpp
    ===================================================================
    --- rts/Game/WordCompletion.cpp	(revision 5850)
    +++ rts/Game/WordCompletion.cpp	(working copy)
    @@ -30,12 +30,14 @@
     
     	// local commands
     	words["/advshading "] = sl;
    +	words["/hardwarecursor "] = sl;
     	words["/clock"] = sl;
     	words["/cmdcolors "] = sl;
     	words["/ctrlpanel "] = sl;
     	words["/echo "] = sl;
     	words["/font "] = sl;
     	words["/gameinfo"] = sl;
    +	words["/grounddecals "] = sl;
     	words["/info "] = sl;
     	words["/luaui "] = sl;
     	words["/maxparticles "] = sl;
    @@ -58,12 +60,15 @@
     	words["/keydebug"] = sl;
     	words["/fakemeta "] = sl;
     	words["/volume "] = sl;
    +	words["/unitreplyvolume "] = sl;
     	words["/vsync "] = sl;
    +	words["/wiremap "] = sl;
     
     	// minimap sub-commands
     	WordProperties mm(false, false, true);
     	words["fullproxy "] = mm;
     	words["drawcommands "] = mm;
    +	words["drawprojectiles "] = mm;
     	words["icons "] = mm;
     	words["unitexp "] = mm;
     	words["unitsize "] = mm;
    
    patch file icon ui.patch (12,472 bytes) 2008-05-10 16:29 +
  • patch file icon speedups.patch (15,652 bytes) 2008-05-10 16:29 -
    Index: rts/Rendering/GL/VertexArray.cpp
    ===================================================================
    --- rts/Rendering/GL/VertexArray.cpp	(revision 5850)
    +++ rts/Rendering/GL/VertexArray.cpp	(working copy)
    @@ -6,6 +6,7 @@
     #include "VertexArray.h"
     #include "myGL.h"
     #include "mmgr.h"
    +#include <GL/glew.h>
     
     //////////////////////////////////////////////////////////////////////
     // Construction/Destruction
    @@ -34,7 +35,7 @@
     
     bool CVertexArray::IsReady()
     {
    -	return true; 
    +	return true;
     }
     
     void CVertexArray::EndStrip()
    @@ -45,20 +46,11 @@
     	stripArray[stripIndex++]=drawIndex;
     }
     
    -void CVertexArray::AddVertex0(const float3& pos)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -}
    -
     void CVertexArray::DrawArray0(int drawType,int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    +
     	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
     	glEnableClientState(GL_VERTEX_ARRAY);
     	int oldIndex=0;
    @@ -66,89 +58,54 @@
     		glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
     		oldIndex=stripArray[a];
     	}
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);
     }
     
    -void CVertexArray::AddVertexC(const float3& pos,unsigned char* color)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -	drawArray[drawIndex++]=*((float*)(color));
    -}
    -
     void CVertexArray::DrawArrayC(int drawType,int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    -	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    -	glColorPointer(4,GL_UNSIGNED_BYTE,stride,&drawArray[3]);
    +
     	glEnableClientState(GL_VERTEX_ARRAY);
     	glEnableClientState(GL_COLOR_ARRAY);
    +	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    +	glColorPointer(4,GL_UNSIGNED_BYTE,stride,&drawArray[3]);
     	int oldIndex=0;
     	for(int a=0;a<stripIndex;a++){
     		glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
     		oldIndex=stripArray[a];
     	}
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);	
     	glDisableClientState(GL_COLOR_ARRAY);
     }
     
    -void CVertexArray::AddVertexT(const float3& pos,float tx,float ty)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -	drawArray[drawIndex++]=tx;
    -	drawArray[drawIndex++]=ty;
    -}
    -
     void CVertexArray::DrawArrayT(int drawType,int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    -	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    -	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    +
     	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     	glEnableClientState(GL_VERTEX_ARRAY);
    +	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    +	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
     	int oldIndex=0;
     	for(int a=0;a<stripIndex;a++){
     		glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
     		oldIndex=stripArray[a];
     	}
     	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);
     }
     
    -void CVertexArray::AddVertexT2(const float3& pos,float tx,float ty,float t2x,float t2y)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -	drawArray[drawIndex++]=tx;
    -	drawArray[drawIndex++]=ty;
    -	drawArray[drawIndex++]=t2x;
    -	drawArray[drawIndex++]=t2y;
    -}
    -
     void CVertexArray::DrawArrayT2(int drawType,int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    -	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    -	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    +
     	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     	glEnableClientState(GL_VERTEX_ARRAY);
    -
    +	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    +	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
     	glClientActiveTextureARB(GL_TEXTURE1_ARB);
     	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[5]);
     	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    @@ -164,76 +121,48 @@
     	glClientActiveTextureARB(GL_TEXTURE0_ARB);
     
     	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);
     }
     
    -void CVertexArray::AddVertexTN(const float3& pos,float tx,float ty, const float3& norm)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -	drawArray[drawIndex++]=tx;
    -	drawArray[drawIndex++]=ty;
    -	drawArray[drawIndex++]=norm.x;
    -	drawArray[drawIndex++]=norm.y;
    -	drawArray[drawIndex++]=norm.z;
    -}
    -
     void CVertexArray::DrawArrayTN(int drawType, int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    -	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    -	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    -	glNormalPointer(GL_FLOAT,stride,&drawArray[5]);
    +
     	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     	glEnableClientState(GL_VERTEX_ARRAY);
     	glEnableClientState(GL_NORMAL_ARRAY);
    -	
    +	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    +	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    +	glNormalPointer(GL_FLOAT,stride,&drawArray[5]);
     	int oldIndex=0;
     	for(int a=0;a<stripIndex;a++){
     		glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
     		oldIndex=stripArray[a];
     	}
     	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);
     	glDisableClientState(GL_NORMAL_ARRAY);
     }
     
    -void CVertexArray::AddVertexTC(const float3& pos,float tx,float ty,unsigned char* col)
    -{
    -	if(drawIndex>drawArraySize-10)
    -		EnlargeDrawArray();
    -
    -	drawArray[drawIndex++]=pos.x;
    -	drawArray[drawIndex++]=pos.y;
    -	drawArray[drawIndex++]=pos.z;
    -	drawArray[drawIndex++]=tx;
    -	drawArray[drawIndex++]=ty;
    -	drawArray[drawIndex++]=*((float*)(col));
    -}
    -
     void CVertexArray::DrawArrayTC(int drawType, int stride)
     {
     	if(stripIndex==0 || stripArray[stripIndex-1]!=drawIndex)
     		EndStrip();
    -	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    -	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    -	glColorPointer(4,GL_UNSIGNED_BYTE,stride,&drawArray[5]);
    +
     	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     	glEnableClientState(GL_VERTEX_ARRAY);
     	glEnableClientState(GL_COLOR_ARRAY);
    -	
    +	glVertexPointer(3,GL_FLOAT,stride,&drawArray[0]);
    +	glTexCoordPointer(2,GL_FLOAT,stride,&drawArray[3]);
    +	glColorPointer(4,GL_UNSIGNED_BYTE,stride,&drawArray[5]);
     	int oldIndex=0;
     	for(int a=0;a<stripIndex;a++){
     		glDrawArrays(drawType,oldIndex*4/stride,stripArray[a]*4/stride-oldIndex*4/stride);
     		oldIndex=stripArray[a];
     	}
     	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    -	glDisableClientState(GL_VERTEX_ARRAY);						
    +	glDisableClientState(GL_VERTEX_ARRAY);
     	glDisableClientState(GL_COLOR_ARRAY);
     }
     
    Index: rts/Rendering/GL/VertexArray.h
    ===================================================================
    --- rts/Rendering/GL/VertexArray.h	(revision 5850)
    +++ rts/Rendering/GL/VertexArray.h	(working copy)
    @@ -4,30 +4,32 @@
     //
     //////////////////////////////////////////////////////////////////////
     
    -class CVertexArray  
    +#include "myGL.h"
    +
    +class CVertexArray
     {
     public:
     	CVertexArray();
     	~CVertexArray();
     	void Initialize();
    +	bool IsReady();
     
    -	void AddVertexTC(const float3 &pos,float tx,float ty,unsigned char* color);
    +	inline void AddVertexTC(const float3 &pos,float tx,float ty,unsigned char* color);
     	void DrawArrayTC(int drawType,int stride=24);
    -	void AddVertexTN(const float3 &pos,float tx,float ty,const float3& norm);
    +	inline void AddVertexTN(const float3 &pos,float tx,float ty,const float3& norm);
     	void DrawArrayTN(int drawType,int stride=32);
    -	void AddVertexT2(const float3& pos,float t1x,float t1y,float t2x,float t2y);
    +	inline void AddVertexT2(const float3& pos,float t1x,float t1y,float t2x,float t2y);
     	void DrawArrayT2(int drawType,int stride=28);
    -	void AddVertexT(const float3& pos,float tx,float ty);
    +	inline void AddVertexT(const float3& pos,float tx,float ty);
     	void DrawArrayT(int drawType,int stride=20);
    -	void AddVertex0(const float3& pos);
    +	inline void AddVertex0(const float3& pos);
     	void DrawArray0(int drawType,int stride=12);
    -	void AddVertexC(const float3& pos,unsigned char* color);
    +	inline void AddVertexC(const float3& pos,unsigned char* color);
     	void DrawArrayC(int drawType,int stride=16);
     
     	void EnlargeStripArray();
     	void EnlargeDrawArray();
     	void EndStrip();
    -	bool IsReady();
     
     	float* drawArray;
     	int drawArraySize;
    @@ -38,4 +40,83 @@
     	int stripIndex;
     };
     
    +/***************************************************************************************************/
    +/***************************************************************************************************/
    +
    +inline void CVertexArray::AddVertexTC(const float3 &pos,float tx,float ty,unsigned char* color)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +	drawArray[drawIndex++]=tx;
    +	drawArray[drawIndex++]=ty;
    +	drawArray[drawIndex++]=*((float*)(color));
    +}
    +
    +inline void CVertexArray::AddVertexTN(const float3 &pos,float tx,float ty,const float3& norm)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +	drawArray[drawIndex++]=tx;
    +	drawArray[drawIndex++]=ty;
    +	drawArray[drawIndex++]=norm.x;
    +	drawArray[drawIndex++]=norm.y;
    +	drawArray[drawIndex++]=norm.z;
    +}
    +
    +inline void CVertexArray::AddVertexT2(const float3& pos,float t1x,float t1y,float t2x,float t2y)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +	drawArray[drawIndex++]=t1x;
    +	drawArray[drawIndex++]=t1y;
    +	drawArray[drawIndex++]=t2x;
    +	drawArray[drawIndex++]=t2y;
    +}
    +
    +inline void CVertexArray::AddVertexT(const float3& pos,float tx,float ty)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +	drawArray[drawIndex++]=tx;
    +	drawArray[drawIndex++]=ty;
    +}
    +
    +inline void CVertexArray::AddVertex0(const float3& pos)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +}
    +
    +inline void CVertexArray::AddVertexC(const float3& pos,unsigned char* color)
    +{
    +	if(drawIndex>drawArraySize-10)
    +		EnlargeDrawArray();
    +
    +	drawArray[drawIndex++]=pos.x;
    +	drawArray[drawIndex++]=pos.y;
    +	drawArray[drawIndex++]=pos.z;
    +	drawArray[drawIndex++]=*((float*)(color));
    +}
    +
    +
     #endif /* VERTEXARRAY_H */
    Index: rts/System/Matrix44f.cpp
    ===================================================================
    --- rts/System/Matrix44f.cpp	(revision 5850)
    +++ rts/System/Matrix44f.cpp	(working copy)
    @@ -8,11 +8,6 @@
     CR_REG_METADATA(CMatrix44f, CR_MEMBER(m));
     
     
    -/*
    -float globalArf=15;
    -extern void arfurf();
    -extern void TestDenormal(float f);
    -*/
     CMatrix44f::CMatrix44f(void)
     {
     	LoadIdentity();
    @@ -28,6 +23,15 @@
     }
     
     
    +CMatrix44f::CMatrix44f(const CMatrix44f& n)
    +{
    +	m[0]  = n[0];   m[1]  = n[1];   m[2]  = n[2];   m[3]  = n[3];
    +	m[4]  = n[4];   m[5]  = n[5];   m[6]  = n[6];   m[7]  = n[7];
    +	m[8]  = n[8];   m[9]  = n[9];   m[10] = n[10];  m[11] = n[11];
    +	m[12] = n[12];  m[13] = n[13];  m[14] = n[14];  m[15] = n[15];
    +}
    +
    +
     CMatrix44f::~CMatrix44f(void)
     {
     }
    @@ -48,6 +52,7 @@
     
     void CMatrix44f::RotateX(float rad)
     {
    +/*
     	const float sr = sin(rad);
     	const float cr = cos(rad);
     
    @@ -58,11 +63,31 @@
     	rm[6]  = -sr;
     
     	*this=Mul(rm);
    +*/
    +	const float sr = sin(rad);
    +	const float cr = cos(rad);
    +
    +	float a=m[4];
    +	m[4] = cr*a - sr*m[8];
    +	m[8] = sr*a + cr*m[8];
    +
    +	a=m[5];
    +	m[5] = cr*a - sr*m[9];
    +	m[9] = sr*a + cr*m[9];
    +
    +	a=m[6];
    +	m[6]  = cr*a - sr*m[10];
    +	m[10] = sr*a + cr*m[10];
    +
    +	a=m[7];
    +	m[7]  = cr*a - sr*m[11];
    +	m[11] = sr*a + cr*m[11];
     }
     
     
     void CMatrix44f::RotateY(float rad)
     {
    +/*
     	const float sr = sin(rad);
     	const float cr = cos(rad);
     
    @@ -73,11 +98,31 @@
     	rm[8]  = -sr;
     
     	*this = Mul(rm);
    +*/
    +	const float sr = sin(rad);
    +	const float cr = cos(rad);
    +
    +	float a=m[0];
    +	m[0] =  cr*a + sr*m[8];
    +	m[8] = -sr*a + cr*m[8];
    +
    +	a=m[1];
    +	m[1] =  cr*a + sr*m[9];
    +	m[9] = -sr*a + cr*m[9];
    +
    +	a=m[2];
    +	m[2]  =  cr*a + sr*m[10];
    +	m[10] = -sr*a + cr*m[10];
    +
    +	a=m[3];
    +	m[3]  =  cr*a + sr*m[11];
    +	m[11] = -sr*a + cr*m[11];
     }
     
     
     void CMatrix44f::RotateZ(float rad)
     {
    +/*
     	const float sr = sin(rad);
     	const float cr = cos(rad);
     
    @@ -88,11 +133,31 @@
     	rm[1] = -sr;
     
     	*this = Mul(rm);
    +*/
    +	const float sr = sin(rad);
    +	const float cr = cos(rad);
    +
    +	float a=m[0];
    +	m[0] = cr*a - sr*m[4];
    +	m[4] = sr*a + cr*m[4];
    +
    +	a=m[1];
    +	m[1] = cr*a - sr*m[5];
    +	m[5] = sr*a + cr*m[5];
    +
    +	a=m[2];
    +	m[2] = cr*a - sr*m[6];
    +	m[6] = sr*a + cr*m[6];
    +
    +	a=m[3];
    +	m[3] = cr*a - sr*m[7];
    +	m[7] = sr*a + cr*m[7];
     }
     
     
     void CMatrix44f::Translate(float x, float y, float z)
     {
    +/*
     	CMatrix44f tm;
     
     	tm[12] = x;
    @@ -100,11 +165,18 @@
     	tm[14] = z;
     
     	*this = Mul(tm);
    +*/
    +
    +	m[12] += x*m[0] + y*m[4] + z*m[8];
    +	m[13] += x*m[1] + y*m[5] + z*m[9];
    +	m[14] += x*m[2] + y*m[6] + z*m[10];
    +	m[15] += x*m[3] + y*m[7] + z*m[11];
     }
     
     
     void CMatrix44f::Translate(const float3& pos)
     {
    +/*
     	CMatrix44f tm;
     
     	tm[12] = pos.x;
    @@ -112,6 +184,15 @@
     	tm[14] = pos.z;
     
     	*this = Mul(tm);
    +*/
    +
    +	const float x=pos.x;
    +	const float y=pos.y;
    +	const float z=pos.z;
    +	m[12] += x*m[0] + y*m[4] + z*m[8];
    +	m[13] += x*m[1] + y*m[5] + z*m[9];
    +	m[14] += x*m[2] + y*m[6] + z*m[10];
    +	m[15] += x*m[3] + y*m[7] + z*m[11];
     }
     
     
    @@ -148,24 +229,10 @@
     
     float3 CMatrix44f::Mul(const float3& vect) const
     {
    -/*	float3 res;
    -
    -	for (int x = 0; x < 3; ++x) {
    -		res[x] = 0;
    -		for (int y = 0; y < 3; ++y) {
    -			res[x] += vect[y] * m[x * 4 + y];
    -		}
    -	}
    -
    -	return res;
    -/*/	const float v0(vect[0]), v1(vect[1]), v2(vect[2]);
    -	//return float3(	v0*m[0] + v1*m[1] + v2*m[2] + m[3],
    -	//				v0*m[4] + v1*m[5] + v2*m[6] + m[7],
    -	//				v0*m[8] + v1*m[9] + v2*m[10] + m[11]);/**/
    -
    +	const float v0(vect[0]), v1(vect[1]), v2(vect[2]);
     	return float3(	v0*m[0] + v1*m[4] + v2*m[8] + m[12],
    -					v0*m[1] + v1*m[5] + v2*m[9] + m[13],
    -					v0*m[2] + v1*m[6] + v2*m[10] + m[14]);/**/
    +				v0*m[1] + v1*m[5] + v2*m[9] + m[13],
    +				v0*m[2] + v1*m[6] + v2*m[10] + m[14]);
     }
     
     
    @@ -236,13 +303,8 @@
     // m.Mul(m.Invert()) is identity
     CMatrix44f CMatrix44f::Invert() const
     {
    -	CMatrix44f mInv;
    +	CMatrix44f mInv(*this);
     
    -	// copy m
    -	mInv[0] = m[0];  mInv[4] = m[4];  mInv[ 8] = m[ 8];  mInv[12] = m[12];
    -	mInv[1] = m[1];  mInv[5] = m[5];  mInv[ 9] = m[ 9];  mInv[13] = m[13];
    -	mInv[2] = m[2];  mInv[6] = m[6];  mInv[10] = m[10];  mInv[14] = m[14];
    -
     	// transpose the rotation
     	mInv[1] = m[4]; mInv[4] = m[1];
     	mInv[2] = m[8]; mInv[8] = m[2];
    Index: rts/System/Matrix44f.h
    ===================================================================
    --- rts/System/Matrix44f.h	(revision 5850)
    +++ rts/System/Matrix44f.h	(working copy)
    @@ -10,6 +10,7 @@
     
     	CMatrix44f(void);
     	CMatrix44f(const float3& pos, const float3& x, const float3& y, const float3& z);
    +	CMatrix44f(const CMatrix44f& n);
     	~CMatrix44f(void);
     
     	void LoadIdentity();
    
    patch file icon speedups.patch (15,652 bytes) 2008-05-10 16:29 +
  • patch file icon bumpwater.patch (23,466 bytes) 2008-05-10 16:30 -
    Index: installer/builddata/bitmaps/README.txt
    ===================================================================
    --- installer/builddata/bitmaps/README.txt	(revision 5850)
    +++ installer/builddata/bitmaps/README.txt	(working copy)
    @@ -65,3 +65,5 @@
     tracks/ComTrack.bmp	SJ
     tracks/StdTank.bmp	SJ
     wake.tga		Yeha
    +waterbump.png		jK
    +caustics/*		jK (with GPL app: http://www.lysator.liu.se/~kand/caustics/)
    Index: rts/Lua/LuaConstGame.cpp
    ===================================================================
    --- rts/Lua/LuaConstGame.cpp	(revision 5850)
    +++ rts/Lua/LuaConstGame.cpp	(working copy)
    @@ -85,8 +85,14 @@
     	LuaPushNamedColor(L,  "waterBaseColor",    mapInfo->water.baseColor);
     	LuaPushNamedColor(L,  "waterMinColor",     mapInfo->water.minColor);
     	LuaPushNamedColor(L,  "waterSurfaceColor", mapInfo->water.surfaceColor);
    +	LuaPushNamedNumber(L, "waterSurfaceAlpha", mapInfo->water.surfaceAlpha);
    +	LuaPushNamedColor(L,  "waterSpecularColor",  mapInfo->water.specularColor);
    +	LuaPushNamedNumber(L, "waterSpecularFactor", mapInfo->water.specularFactor);
     	LuaPushNamedColor(L,  "waterPlaneColor",   mapInfo->water.planeColor);
     	LuaPushNamedColor(L,  "fogColor",          fogColor);
    +	LuaPushNamedColor(L,  "groundAmbientColor",      mapInfo->light.groundAmbientColor);
    +	LuaPushNamedColor(L,  "groundSpecularColor",     mapInfo->light.groundSpecularColor);
    +	LuaPushNamedColor(L,  "groundSunColor",          mapInfo->light.groundSunColor);
     
     	LuaPushNamedString(L, "modName",         modInfo.humanName);
     	LuaPushNamedString(L, "modShortName",    modInfo.shortName);
    Index: rts/Map/MapInfo.cpp
    ===================================================================
    --- rts/Map/MapInfo.cpp	(revision 5850)
    +++ rts/Map/MapInfo.cpp	(working copy)
    @@ -139,17 +139,46 @@
     	hasWaterPlane = !tmp.empty();
     	water.planeColor = mapDefParser->GetFloat3(float3(0.0f, 0.4f, 0.0f), "MAP\\WATER\\WaterPlaneColor");
     
    +	mapDefParser->GetDef(water.fresnelMin,"0.2","MAP\\WATER\\FresnelMin");
    +	mapDefParser->GetDef(water.fresnelMax,"0.3","MAP\\WATER\\FresnelMax");
    +	mapDefParser->GetDef(water.fresnelPower,"4.0","MAP\\WATER\\FresnelPower");
    +
    +	mapDefParser->GetDef(water.specularFactor,"20.0","MAP\\WATER\\WaterSpecularFactor");
    +
    +	water.specularColor = mapDefParser->GetFloat3(light.groundSunColor,"MAP\\WATER\\WaterSpecularColor");
     	water.surfaceColor = mapDefParser->GetFloat3(float3(0.75f, 0.8f, 0.85f), "MAP\\WATER\\WaterSurfaceColor");
    +	mapDefParser->GetDef(water.surfaceAlpha,"0.55","MAP\\WATER\\WaterSurfaceAlpha");
     	water.absorb = mapDefParser->GetFloat3(float3(0, 0, 0), "MAP\\WATER\\WaterAbsorb");
     	water.baseColor = mapDefParser->GetFloat3(float3(0, 0, 0), "MAP\\WATER\\WaterBaseColor");
     	water.minColor = mapDefParser->GetFloat3(float3(0, 0, 0), "MAP\\WATER\\WaterMinColor");
    +
     	mapDefParser->GetDef(water.texture, "", "MAP\\WATER\\WaterTexture");
    +	mapDefParser->GetDef(water.foamTexture, "", "MAP\\WATER\\WaterFoamTexture");
    +	mapDefParser->GetDef(water.normalTexture, "", "MAP\\WATER\\WaterNormalTexture");
     
     	//default water is ocean.jpg in bitmaps, map specific water textures is saved in the map dir
     	if(water.texture.empty())
     		water.texture = "bitmaps/" + resources->SGetValueDef("ocean.jpg", "resources\\graphics\\maps\\watertex");
     	else
     		water.texture = "maps/" + water.texture;
    +
    +	
    +	if(water.foamTexture.empty())
    +		water.foamTexture = "bitmaps/"+resources->SGetValueDef("foam.jpg","resources\\graphics\\maps\\waterfoamtex");
    +	else
    +		water.foamTexture = "maps/" + water.foamTexture;
    +
    +	if(water.normalTexture.empty())
    +		water.normalTexture = "bitmaps/"+resources->SGetValueDef("waterbump.png","resources\\graphics\\maps\\waternormaltex");
    +	else
    +		water.normalTexture = "maps/" + water.normalTexture;
    +
    +	char num[10];
    +	for (int i = 0; i < 32; i++) {
    +		sprintf(num, "%02i", i);
    +		water.causticTextures[i] = std::string("bitmaps/") + resources->SGetValueDef(std::string("caustics/caustic")+num+".jpg",
    +								std::string("resources\\graphics\\caustics\\caustic")+num);
    +	}
     }
     
     
    Index: rts/Map/MapInfo.h
    ===================================================================
    --- rts/Map/MapInfo.h	(revision 5850)
    +++ rts/Map/MapInfo.h	(working copy)
    @@ -106,8 +106,17 @@
     		float3 baseColor;
     		float3 minColor;
     		float3 surfaceColor;
    +		float surfaceAlpha;
     		float3 planeColor;
    +		float3 specularColor;
    +		float specularFactor;
    +		float fresnelMin;
    +		float fresnelMax;
    +		float fresnelPower;
     		std::string texture;
    +		std::string foamTexture;
    +		std::string normalTexture;
    +		std::string causticTextures[32];
     	} water;
     	bool hasWaterPlane; ///< true if "MAP\WATER\WaterPlaneColor" is set
     
    Index: rts/Rendering/Env/BaseWater.cpp
    ===================================================================
    --- rts/Rendering/Env/BaseWater.cpp	(revision 5850)
    +++ rts/Rendering/Env/BaseWater.cpp	(working copy)
    @@ -2,6 +2,7 @@
     #include "BaseWater.h"
     #include "BasicWater.h"
     #include "AdvWater.h"
    +#include "BumpWater.h"
     #include "Rendering/GL/myGL.h"
     #include "Platform/ConfigHandler.h"
     #include "LogOutput.h"
    @@ -42,6 +43,20 @@
     			return water;
     		}
     	}
    +
    +	if(configValue==4 && GLEW_ARB_shading_language_100) {
    +		try {
    +			water = SAFE_NEW CBumpWater;
    +		} catch (content_error& e) {
    +			delete water;
    +			water = NULL;
    +			logOutput.Print("Loading Bumpmapped Water failed");
    +			logOutput.Print("Error: %s", e.what());
    +		}
    +		if (water) {
    +			return water;
    +		}
    +	}
     	
     	if(configValue==3 && GLEW_ARB_fragment_program && GLEW_ARB_texture_rectangle){
     		try {
    Index: rts/Rendering/Env/BumpWater.cpp
    ===================================================================
    --- rts/Rendering/Env/BumpWater.cpp	(revision 0)
    +++ rts/Rendering/Env/BumpWater.cpp	(revision 0)
    @@ -0,0 +1,468 @@
    +/**
    + * @file BumpWater.cpp
    + * @brief extended bumpmapping water shader
    + * @author jK
    + *
    + * Copyright (C) 2008.  Licensed under the terms of the
    + * GNU GPL, v2 or later.
    + */
    +
    +#include "StdAfx.h"
    +#include "bitops.h"
    +#include "FileSystem/FileHandler.h"
    +#include "BumpWater.h"
    +#include "Game/Game.h"
    +#include "Rendering/GL/myGL.h"
    +#include "Rendering/Textures/Bitmap.h"
    +#include "Game/Camera.h"
    +#include "Map/MapInfo.h"
    +#include "Map/ReadMap.h"
    +#include "LogOutput.h"
    +#include "Map/BaseGroundDrawer.h"
    +#include "BaseSky.h"
    +#include "Rendering/UnitModels/UnitDrawer.h"
    +#include "Sim/Projectiles/ProjectileHandler.h"
    +#include "Sim/Features/FeatureHandler.h"
    +#include "Lua/LuaCallInHandler.h"
    +#include "System/Platform/ConfigHandler.h"
    +#include <boost/format.hpp>
    +
    +using std::string;
    +
    +//////////////////////////////////////////////////////////////////////
    +// Construction/Destruction
    +//////////////////////////////////////////////////////////////////////
    +
    +extern GLfloat FogLand[];
    +
    +
    +void PrintLog(GLuint obj)
    +{
    +	int infologLength = 0;
    +	int maxLength;
    +	
    +	if(glIsShader(obj))
    +		glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
    +	else
    +		glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
    +			
    +	char infoLog[maxLength];
    + 
    +	if (glIsShader(obj))
    +		glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog);
    +	else
    +		glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog);
    + 
    +	if (infologLength > 0)
    +		throw content_error(string("BumpWater shader error: "+string(infoLog,infologLength)));
    +}
    +
    +
    +void PrintFboError(GLenum error)
    +{
    +	switch(error) {
    +		case GL_FRAMEBUFFER_COMPLETE_EXT:
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
    +			logOutput.Print("BumpWater-FBO: missing a required image/buffer attachment!");
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
    +			logOutput.Print("BumpWater-FBO: has no images/buffers attached!");
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
    +			logOutput.Print("BumpWater-FBO: has mismatched image/buffer dimensions!");
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
    +			logOutput.Print("BumpWater-FBO: colorbuffer attachments have different types!");
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
    +			logOutput.Print("BumpWater-FBO: trying to draw to non-attached color buffer!");
    +			break;
    +		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
    +			logOutput.Print("BumpWater-FBO: trying to read from a non-attached color buffer!");
    +			break;
    +		case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
    +			logOutput.Print("BumpWater-FBO: format is not supported by current graphics card/driver!");
    +			break;
    +		default:
    +			logOutput.Print("BumpWater-FBO: *UNKNOWN ERROR*");
    +			break;
    +	}
    +}
    +
    +string LoadShaderSource(const string& file)
    +{
    +	CFileHandler fh(file);
    +	if (!fh.FileExists())
    +		throw content_error("Can't load shader " + file);
    +
    +	string text;
    +	text.resize(fh.FileSize());
    +	//char* cstr = SAFE_NEW char[fh.FileSize()+1];
    +
    +	fh.Read(&text[0], text.length());
    +	//fh.Read(cstr,fh.FileSize());
    +	//cstr[fh.FileSize()] = 0;
    +
    +	return text;
    +}
    +
    +void GLSLDefineConstf4(string& str, const string& name, const float3& v, const float& alpha)
    +{
    +	str += boost::str(boost::format(string("#define ")+name+" vec4(%1$.12f,%2$.12f,%3$.12f,%4$.12f)\n") % (v.x) % (v.y) % (v.z) % (alpha));
    +}
    +
    +void GLSLDefineConstf3(string& str, const string& name, const float3& v)
    +{
    +	str += boost::str(boost::format(string("#define ")+name+" vec3(%1$.12f,%2$.12f,%3$.12f)\n") % (v.x) % (v.y) % (v.z));
    +}
    +
    +void GLSLDefineConstf2(string& str, const string& name, const float& x, const float& y)
    +{
    +	str += boost::str(boost::format(string("#define ")+name+" vec2(%1$.12f,%2$.12f)\n") % x % y);
    +}
    +
    +void GLSLDefineConstf1(string& str, const string& name, const float& x)
    +{
    +	str += boost::str(boost::format(string("#define ")+name+" %1$.12f\n") % x);
    +}
    +
    +GLuint LoadTexture(const string& filename)
    +{
    +	GLuint texID;
    +	CBitmap bm;
    +	if (!bm.Load(filename))
    +		throw content_error("Could not load texture from file "+filename);
    +	
    +	glGenTextures(1, &texID);
    +	glBindTexture(GL_TEXTURE_2D, texID);
    +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    +	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    +	//glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 3.0f);
    +	glBuildMipmaps(GL_TEXTURE_2D, GLEW_ARB_texture_compression?GL_COMPRESSED_RGB_ARB:GL_RGB8, bm.xsize, bm.ysize, GL_RGBA, GL_UNSIGNED_BYTE, bm.mem);
    +	return texID;
    +}
    +
    +CBumpWater::CBumpWater()
    +{
    +	reflTexSize = next_power_of_2(configHandler.GetInt("BumpWaterTexSizeReflection", 256));
    +	reflection = !!configHandler.GetInt("BumpWaterReflection", 1);
    +	refraction = configHandler.GetInt("BumpWaterRefraction", 1);  //0:=off, 1:=screencopy, 2:=own rendering cycle
    +	waves = !!configHandler.GetInt("BumpBeachWaves", 1);
    +
    +	if (!GLEW_EXT_framebuffer_object) {
    +		reflection = false;
    +	}
    +	
    +	if (refraction>0) {
    +		// CREATE REFRACTION TEXTURE
    +		glGenTextures(1, &refractTexture);
    +		//if(GLEW_ARB_texture_non_power_of_two || GLEW_EXT_texture_non_power_of_two)
    +		//	target = GL_TEXTURE_2D;
    +		//else //if(GLEW_ARB_texture_rectangle || GLEW_EXT_texture_rectangle)
    +			target = GL_TEXTURE_RECTANGLE_ARB;
    +		glBindTexture(target, refractTexture);
    +		glTexParameteri(target,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
    +		glTexParameteri(target,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
    +		if (GLEW_EXT_texture_edge_clamp) {
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    +		} else {
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    +		}
    +		if(target == GL_TEXTURE_RECTANGLE_ARB) {
    +			refrSizeX = gu->viewSizeX;
    +			refrSizeY = gu->viewSizeY;
    +		} else{
    +			refrSizeX = next_power_of_2(gu->viewSizeX);
    +			refrSizeY = next_power_of_2(gu->viewSizeY);	
    +		}
    +		glTexImage2D(target, 0, GL_RGB8, refrSizeX, refrSizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    +	}
    +
    +	if (reflection) {
    +		// CREATE REFLECTION TEXTURE
    +		glGenTextures(1, &reflectTexture);
    +		glBindTexture(GL_TEXTURE_2D, reflectTexture);
    +		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    +		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    +		if (GLEW_EXT_texture_edge_clamp) {
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    +		} else {
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    +			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    +		}
    +		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, reflTexSize, reflTexSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    +
    +		// CREATE DEPTH RBO FOR REFLECTION FBO
    +		glGenRenderbuffersEXT(1, &rbo);
    +		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo);
    +		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, reflTexSize, reflTexSize);
    +
    +		// CREATE REFLECTION FBO AND BIND TEXTURE&RBO
    +		glGenFramebuffersEXT(1,&fbo);
    +		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    +		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, reflectTexture, 0);
    +		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo);
    +		GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    +		if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
    +			PrintFboError(status);
    +			//logOutput.Print("BumpWater: FBO not ready");
    +		}
    +		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    +	}
    +
    +
    +	foamTexture = LoadTexture( mapInfo->water.foamTexture );
    +	normalTexture = LoadTexture( mapInfo->water.normalTexture );
    +	for (int i = 0; i < 32; i++) {
    +		caustTextures[i] = LoadTexture( mapInfo->water.causticTextures[i] );
    +	}
    +
    +	//heightTexture = readmap->GetShadingTexture();
    +	/*
    +	
    +	*/
    +
    +	/* DEFINE SOME RUNTIME CONSTANTS (I don't use Uniforms for that, 'cos the glsl compiler can't optimize those!) */
    +	string definitions;
    +	if (reflection)     	definitions += "#define use_reflection\n";
    +	if (refraction>0)	definitions += "#define use_refraction\n\n";
    +	GLSLDefineConstf4(definitions, "SurfaceColor", mapInfo->water.surfaceColor*0.4, mapInfo->water.surfaceAlpha );
    +	GLSLDefineConstf3(definitions, "SpecularColor", mapInfo->water.specularColor );
    +	GLSLDefineConstf1(definitions, "SpecularFactor", mapInfo->water.specularFactor);
    +	GLSLDefineConstf3(definitions, "SunDir", mapInfo->light.sunDir );
    +	GLSLDefineConstf3(definitions, "MapMid", float3(readmap->width*SQUARE_SIZE*0.5f,0.0f,readmap->height*SQUARE_SIZE*0.5f) );
    +	GLSLDefineConstf2(definitions, "ScreenInverse", -1.0f/gu->viewSizeX, 1.0f/gu->viewSizeY );
    +	GLSLDefineConstf2(definitions, "ViewPos", gu->viewPosX,gu->viewPosY );
    +	GLSLDefineConstf1(definitions, "FresnelMin",  mapInfo->water.fresnelMin);
    +	GLSLDefineConstf1(definitions, "FresnelMax",  mapInfo->water.fresnelMax);
    +	GLSLDefineConstf1(definitions, "FresnelPower", mapInfo->water.fresnelPower);
    +	
    +	/* LOAD SHADERS */
    +	string vsSource = LoadShaderSource("shaders/bumpWaterVS.glsl");
    +	string fsSource = LoadShaderSource("shaders/bumpWaterFS.glsl");
    +
    +	vector<GLint> lengths(2);
    +	vector<const GLchar*> strings(2);
    +	lengths[0]=definitions.length();
    +	strings[0]=definitions.c_str();
    +
    +	waterVP = glCreateShader(GL_VERTEX_SHADER);
    +	lengths[1]=vsSource.length();
    +	strings[1]=vsSource.c_str();
    +	glShaderSource(waterVP, strings.size(), &strings.front(), &lengths.front());
    +	glCompileShader(waterVP);
    +	PrintLog(waterVP);
    +
    +	waterFP = glCreateShader(GL_FRAGMENT_SHADER);
    +	lengths[1]= fsSource.length();
    +	strings[1] = fsSource.c_str();
    +	glShaderSource(waterFP, strings.size(), &strings.front(), &lengths.front());
    +	glCompileShader(waterFP);
    +	PrintLog(waterFP);
    +	
    +	//delete vsSource; delete fsSource;
    + 
    +	waterShader = glCreateProgram();
    +	glAttachShader(waterShader, waterVP);
    +	glAttachShader(waterShader, waterFP);
    +	glLinkProgram(waterShader);
    +	PrintLog(waterShader);
    +
    +	/* BIND TEXTURE UNIFORMS */
    +	glUseProgram(waterShader);
    +		eyePosLoc	= glGetUniformLocation(waterShader, "eyePos");
    +		frameLoc		= glGetUniformLocation(waterShader, "frame");
    +		normalmapLoc	= glGetUniformLocation(waterShader, "normalmap");
    + 		heightmapLoc	= glGetUniformLocation(waterShader, "heightmap");
    +		causticLoc	= glGetUniformLocation(waterShader, "caustic");
    + 		foamLoc		= glGetUniformLocation(waterShader, "foam");
    +		reflectionLoc	= glGetUniformLocation(waterShader, "reflection");
    +		refractionLoc	= glGetUniformLocation(waterShader, "refraction");
    +
    +		glUniform1i(normalmapLoc, 0);
    +		glUniform1i(heightmapLoc, 1);
    +		glUniform1i(causticLoc, 2);
    +		glUniform1i(foamLoc, 3);
    +		glUniform1i(reflectionLoc, 4);
    +		glUniform1i(refractionLoc, 5);
    +	glUseProgram(0);
    +}
    +
    +CBumpWater::~CBumpWater()
    +{
    +	if (reflection) {
    +		glDeleteTextures(1, &reflectTexture);
    +		glDeleteRenderbuffersEXT(1, &rbo);
    +		glDeleteFramebuffersEXT(1, &fbo);
    +	}
    +	if (refraction>0)
    +		glDeleteTextures(1, &refractTexture);
    +
    +	glDeleteTextures(1, &foamTexture);
    +	glDeleteTextures(32, caustTextures);
    +	glDeleteTextures(1, &normalTexture);
    +
    +	glDeleteShader(waterVP);
    +	glDeleteShader(waterFP);
    +	glDeleteProgram(waterShader);
    +}
    +
    +void CBumpWater::Draw()
    +{
    +	if(readmap->minheight>10)
    +		return;
    +
    +	if (refraction == 1) {
    +		// _SCREENCOPY_ REFRACT TEXTURE
    +		glBindTexture(target, refractTexture);
    +		glEnable(target);
    +		glCopyTexSubImage2D(target, 0, 0, 0, gu->viewPosX, 0, gu->viewSizeX, gu->viewSizeY);
    +		glDisable(target);
    +	}
    +
    +	glDisable(GL_ALPHA_TEST);
    +	if (refraction>0)
    +		glDisable(GL_BLEND);
    +	if (refraction<2)
    +		glDepthMask(0);
    +
    +	glActiveTexture(GL_TEXTURE1);
    +		glBindTexture(GL_TEXTURE_2D, readmap->GetShadingTexture());
    +	glActiveTexture(GL_TEXTURE2);
    +		glBindTexture(GL_TEXTURE_2D, caustTextures[gs->frameNum%32]);
    +	glActiveTexture(GL_TEXTURE3);
    +		glBindTexture(GL_TEXTURE_2D, foamTexture);
    +	glActiveTexture(GL_TEXTURE4);
    +		glBindTexture(GL_TEXTURE_2D, reflectTexture);
    +	glActiveTexture(GL_TEXTURE5);
    +		glBindTexture(target, refractTexture);
    +	glActiveTexture(GL_TEXTURE0);
    +		glBindTexture(GL_TEXTURE_2D, normalTexture);
    +
    +	glUseProgram(waterShader);
    +	glUniform1f(frameLoc,gs->frameNum/15000.0f);
    +	glUniformf3(eyePosLoc,camera->pos);
    +
    +	glBegin(GL_QUADS);
    +		glTexCoord4f(0.0f,0.0f,0.0f,0.0f);
    +			glVertex3i(0,0,0);
    +		glTexCoord4f(0.0f,1.0f,0.0f,(float)gs->mapy/gs->pwr2mapy);
    +			glVertex3i(0,0,readmap->height*SQUARE_SIZE);
    +		glTexCoord4f(1.0f,1.0f,(float)gs->mapx/gs->pwr2mapx,(float)gs->mapy/gs->pwr2mapy);
    +			glVertex3i(readmap->width*SQUARE_SIZE,0,readmap->height*SQUARE_SIZE);
    +		glTexCoord4f(1.0f,0.0f,(float)gs->mapx/gs->pwr2mapx,0.0f);
    +			glVertex3i(readmap->width*SQUARE_SIZE,0,0);
    +	glEnd();
    +
    +	glUseProgram(0);
    +
    +	if (refraction<2)
    +		glDepthMask(1);
    +}
    +
    +void CBumpWater::UpdateWater(CGame* game)
    +{
    +	if (readmap->minheight > 10 || mapInfo->map.voidWater)
    +		return;
    +
    +	if (refraction>1) DrawRefraction(game);
    +	if (reflection)   DrawReflection(game);
    +}
    +
    +void CBumpWater::DrawRefraction(CGame* game)
    +{
    +	// _RENDER_ REFRACTION TEXTURE
    +	drawRefraction=true;
    +	camera->Update(false);
    +	glViewport(0,0,refrSizeX,refrSizeY);
    +
    +	glClearColor(FogLand[0],FogLand[1],FogLand[2],1);
    +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    +
    +	float3 oldsun=unitDrawer->unitSunColor;
    +	float3 oldambient=unitDrawer->unitAmbientColor;
    +
    +	unitDrawer->unitSunColor*=float3(0.5f,0.7f,0.9f);
    +	unitDrawer->unitAmbientColor*=float3(0.6f,0.8f,1.0f);
    +
    +	game->SetDrawMode(CGame::refractionDraw);
    +
    +	glEnable(GL_CLIP_PLANE2);
    +	double plane[4]={0,-1,0,2};
    +	glClipPlane(GL_CLIP_PLANE2 ,plane);
    +	drawReflection=true;
    +
    +	readmap->GetGroundDrawer()->Draw();
    +	unitDrawer->Draw(false,true);
    +	featureHandler->Draw();
    +	drawReflection=false;
    +	ph->Draw(false,true);
    +	luaCallIns.DrawWorldRefraction();
    +	
    +	glDisable(GL_CLIP_PLANE2);
    +	game->SetDrawMode(CGame::normalDraw);
    +	drawRefraction=false;
    +
    +	glBindTexture(target, refractTexture);
    +	glEnable(target);
    +	glCopyTexSubImage2D(target,0,0,0,0,0,refrSizeX,refrSizeY);
    +	glDisable(target);
    +
    +	glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
    +	glClearColor(FogLand[0],FogLand[1],FogLand[2],1);
    +
    +	unitDrawer->unitSunColor=oldsun;
    +	unitDrawer->unitAmbientColor=oldambient;
    +}
    +
    +void CBumpWater::DrawReflection(CGame* game)
    +{
    +	// CREATE REFLECTION TEXTURE
    +	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
    +
    +	CCamera *realCam = camera;
    +	camera = new CCamera(*realCam);
    +	camera->up.x=0;
    +	camera->up.y=1;
    +	camera->up.z=0;
    +	camera->forward.y*=-1;
    +	camera->pos.y*=-1;
    +	camera->Update(false);
    +
    +	glViewport(0,0,reflTexSize,reflTexSize);
    +
    +	glClearColor(0.2f,0.4f,0.2f,1);
    +	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    +
    +	game->SetDrawMode(CGame::reflectionDraw);
    +
    +	sky->Draw();
    +
    +	glEnable(GL_CLIP_PLANE2);
    +	double plane[4]={0,1,0,0}; // make angle dependent?
    +	glClipPlane(GL_CLIP_PLANE2 ,plane);
    +	drawReflection=true;
    +
    +	readmap->GetGroundDrawer()->Draw(true);
    +	unitDrawer->Draw(true);
    +	featureHandler->Draw();
    +	ph->Draw(true);
    +	luaCallIns.DrawWorldReflection();
    +
    +	game->SetDrawMode(CGame::normalDraw);
    +	drawReflection=false;
    +	glDisable(GL_CLIP_PLANE2);
    +
    +	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
    +
    +	glViewport(gu->viewPosX,0,gu->viewSizeX,gu->viewSizeY);
    +	glClearColor(FogLand[0],FogLand[1],FogLand[2],1);
    +
    +	delete camera;
    +	camera = realCam;
    +	camera->Update(false);
    +}
    Index: rts/Rendering/Env/BumpWater.h
    ===================================================================
    --- rts/Rendering/Env/BumpWater.h	(revision 0)
    +++ rts/Rendering/Env/BumpWater.h	(revision 0)
    @@ -0,0 +1,68 @@
    +// BumpWater.h: interface for the CBumpWater class.
    +//
    +//////////////////////////////////////////////////////////////////////
    +
    +#ifndef __BUMP_WATER_H__
    +#define __BUMP_WATER_H__
    +
    +#include "Rendering/GL/myGL.h"
    +#include "BaseWater.h"
    +
    +class CBumpWater : public CBaseWater
    +{
    +public:
    +	void UpdateWater(CGame* game);
    +	void DrawReflection(CGame* game);
    +	void DrawRefraction(CGame* game);
    +	void Draw();
    +	CBumpWater();
    +	virtual ~CBumpWater();
    +	virtual int GetID() const { return 4; }
    +
    +	// user options
    +	bool reflection;
    +	char refraction; //0:=off, 1:=screencopy, 2:=own rendering cycle
    +	int  reflTexSize;
    +	bool waves;
    +
    +	// map options
    +	float3 surfaceColor;
    +	float3 specularColor;
    +
    +	int  refrSizeX;
    +	int  refrSizeY;
    +
    +	unsigned int target; // of the refract texture
    +	GLuint refractTexture;
    +	GLuint reflectTexture;
    +	GLuint rbo;
    +	GLuint fbo;
    +
    +	GLuint foamTexture;
    +	GLuint normalTexture;
    +	GLuint caustTextures[32];
    +	GLuint* heightTexture;
    +
    +	GLuint waterFP;
    +	GLuint waterVP;
    +	GLuint waterShader;
    +	
    +	GLuint midPosLoc;
    +	GLuint eyePosLoc;
    +	GLuint lightDirLoc;
    +	GLuint fresnelMinLoc;
    +	GLuint fresnelMaxLoc;
    +	GLuint fresnelPowerLoc;
    +	GLuint frameLoc;
    +	GLuint screenInverseLoc;
    +	GLuint viewPosLoc;
    +	GLuint normalmapLoc;
    +	GLuint heightmapLoc;
    +	GLuint causticLoc;
    +	GLuint foamLoc;
    +	GLuint reflectionLoc;
    +	GLuint refractionLoc;
    +};
    +
    +#endif // __BUMP_WATER_H__
    +
    
    patch file icon bumpwater.patch (23,466 bytes) 2008-05-10 16:30 +
  • zip file icon bumpwater.zip (252,411 bytes) 2008-05-10 16:42

-Relationships
+Relationships

-Notes

~0002253

jK (developer)

Forgot to mention that hwCursor are default off, cos I don't want to risk that someone got no cursor ingame. (to turn it on use "/hardwarecursor 1" (ui.patch))

~0002254

ILMTitan (reporter)

Last edited: 2008-05-10 17:41

I am starting by looking a hwCursor.patch and units.patch. If someone else wants to look over some of the others, that would be great.

Edit: and I guess ui.patch so I can see the hardware cursor

~0002255

jK (developer)

Last edited: 2008-05-10 18:55

ui.patch only adds the ingame /hardwarecursor command, you can also instead add HarwareCursor=1 to your .springrc/registry and start spring then.

~0002256

LordMatt (reporter)

I vote jK gets commit access if these are accepted. :)

~0002258

tvo (reporter)

Whoa, very good patches, don't see them like this every day.

(Just skimmed over the patches themselves; didn't apply/compile/test anything yet.)

Most major issues I found are still quite minor :-)

Here are they anyway (the ones I remember):

- CBumpWater has everything public, making private stuff private makes the code a little bit easier to understand (because you can then be sure no other code uses the private members)

- In CBFGroundTextures::LoadSquare, when stitching together the small tiles into big tiles, you copy 4 bytes at a time using GLfloat (instead of 1 byte at a time using char). However, IIRC this is DXT1 compressed texture data, so just using int would make more sense. (Since (unsigned) int is more commonly used for arbitrary streams of data then float :-))

- SpringApp.cpp seems to be a full-file diff in rendering.patch, maybe some line endings issue?

- When removing #includes, you may actually remove them, not just comment them out :) (for some reason everyone always comments #includes out instead of removing them, so you're not the only one ;-))

Especially in relation to the quality in general these are minor issues, so IMHO don't bother with them (yet) until at least these patches are committed.

If the SpringApp.cpp really proves to be a problem when applying the patch I'll inform you about it.

And funny we get yet another water renderer :-)

~0002259

ILMTitan (reporter)

First thoughts about hwCursor.patch. 1 annoying minor bug. When I start the game, the cursor is hidden, and acting like the cross cursor. Clicking the middle button changes it to the cross cursor. Clicking a second time returns the normal cursor. If it matters any, I'm on XP, and this occurs in both full screen and windowed mode.

One other minor stylistic thing. I can somewhat understand not wanting to write the curly braces around one-line if and for statement bodies, but why would you ever remove existing braces around said statements?

~0002260

jK (developer)

Last edited: 2008-05-11 08:17

@ILMTitan:
Oh sorry, I forgot that you need the ui.patch, cos it makes game.cpp to enables/show the mouse ingame, so that would solve the missing cursor (and hopefully the starting in middle mouse scrolling, too).

Edit: Oh and it is not that I am to lazy to make curly braces (they are easy to access on a us keyboard), I am one of those programmers who want to put as much information on the screen as possible, so I like to remove any redundant syntax and unnecessary linebreaks (IMO it is much easier to read then).
Yeah, I know most ppl don't like such a coding style :/

@tvo
thx :)
- yeah, CBumpWater.h was one of my first c++-files, so i simply copied it from DynWater what doesn't use privates, too (still a bad programming design by me).

- yeah, an int should be cleaner and faster for copying 4bytes.

- meh .. some editor of me changed the newline ending again. I had that already once and fixed it, but it happened again...

Oh, and I don't think the SpringApp.cpp is a problem to patch (it worked fine on my clean linux compile ebuild). But mapInfo.cpp,mapInfo.h and README.txt don't want to patch on my computer (linux), the strange is that when you seperate each one those files into an own patch, it works fine. (using a svn prog to patch it should work in all cases)

~0002262

ILMTitan (reporter)

hwCursor.patch and units.patch are all clear. ui.patch is mostly clear, except for /water 4 and the skybox wireframe sections, which require bumpwater.patch and rendering.patch respectively to test. Those are also the two I feel least qualified to approve.

~0002265

tvo (reporter)

* Applied hwCursor.patch and ui.patch from jK's patch set (mantis 0000928),
except the -finline-ffunctions -funroll-loops change from hwCursor.patch,
and the water and wireframe hunks from ui.patch (will all follow later).

~0002266

tvo (reporter)

Applied units.patch

Found that the GameOver LUA callin in LuaCallins.patch is wrong; the call is being made in the CGameServer thread/process currently, which will at least cause race conditions and worst case will not compile at all (because I don't think Auswaschbars dedicated server has a dependency on LUA.)

~0002268

tvo (reporter)

In LuaCallouts.patch, GetPlayerStats seems to be wrongly placed in LuaSyncedRead.cpp; looking at the rest of that file it seems it only returns synced stuff, while player stats are unsynced.

Is there a particular reason to put it there or can it go in LuaUnsyncedRead.cpp?

~0002269

tvo (reporter)

bumpwater.patch and rendering.patch committed, see commit msg for comments

~0002270

jK (developer)

"In LuaCallouts.patch, GetPlayerStats seems to be wrongly placed in LuaSyncedRead.cpp; looking at the rest of that file it seems it only returns synced stuff, while player stats are unsynced.

Is there a particular reason to put it there or can it go in LuaUnsyncedRead.cpp?"
 
PlayerStats are sended through server, and Spring.GetPlayerControlledUnit is also more unsynced than synced and it is placed in LuaSyncedRead, too. So it is part of both, but it contains informations that should be not accesible by all players (while the match is running), so imo it is more synced than unsynced.

@GameServer(IsGameOver)
And yeah, I already had a presentiment, that it won't work that way (it worked on a single pc game). Need to investigate GameServer/client differentiation then a bit more (not that easy ^^).

~0002271

tvo (reporter)

applied speedups.patch; only the Lua patches left.
+Notes

-Issue History
Date Modified Username Field Change
2008-05-10 16:27 jK New Issue
2008-05-10 16:27 jK File Added: hwCursor.patch
2008-05-10 16:28 jK File Added: units.patch
2008-05-10 16:28 jK File Added: LuaCallins.patch
2008-05-10 16:29 jK File Added: LuaCallouts.patch
2008-05-10 16:29 jK File Added: rendering.patch
2008-05-10 16:29 jK File Added: ui.patch
2008-05-10 16:29 jK File Added: speedups.patch
2008-05-10 16:30 jK File Added: bumpwater.patch
2008-05-10 16:42 jK File Added: bumpwater.zip
2008-05-10 17:39 jK Note Added: 0002253
2008-05-10 17:40 ILMTitan Note Added: 0002254
2008-05-10 17:41 ILMTitan Note Edited: 0002254
2008-05-10 18:54 jK Note Added: 0002255
2008-05-10 18:55 jK Note Edited: 0002255
2008-05-10 18:55 jK Note Edited: 0002255
2008-05-10 20:13 LordMatt Note Added: 0002256
2008-05-11 01:01 tvo Note Added: 0002258
2008-05-11 03:31 ILMTitan Note Added: 0002259
2008-05-11 08:04 jK Note Added: 0002260
2008-05-11 08:17 jK Note Edited: 0002260
2008-05-12 00:28 ILMTitan Note Added: 0002262
2008-05-12 15:02 tvo Note Added: 0002265
2008-05-12 15:14 tvo Note Added: 0002266
2008-05-12 15:30 tvo Note Added: 0002268
2008-05-12 17:07 tvo Note Added: 0002269
2008-05-12 18:21 jK Note Added: 0002270
2008-05-12 22:19 tvo Note Added: 0002271
2008-11-02 11:32 Auswaschbar Status new => resolved
2008-11-02 11:32 Auswaschbar Resolution open => fixed
2008-11-02 11:32 Auswaschbar Assigned To => Auswaschbar
+Issue History