--- a/hedgewars/hwengine.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/hwengine.pas Tue Jul 10 11:09:38 2012 +0200
@@ -31,7 +31,7 @@
uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler, uSound,
uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uRandom, uLandTexture, uCollisions,
- SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
+ SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted, uTextures
{$IFDEF SDL13}, uTouch{$ENDIF}{$IFDEF ANDROID}, GLUnit{$ENDIF};
{$IFDEF HWLIBRARY}
@@ -412,6 +412,7 @@
//uLandGraphics does not need initialization
//uLandObjects does not need initialization
//uLandTemplates does not need initialization
+ uTextures.initModule;
uLandTexture.initModule;
//uLocale does not need initialization
uRandom.initModule;
@@ -461,6 +462,7 @@
uIO.freeModule;
uLand.freeModule;
uLandPainted.freeModule;
+ uTextures.freeModule;
uCommandHandlers.freeModule;
uCommands.freeModule;
--- a/hedgewars/options.inc Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/options.inc Tue Jul 10 11:09:38 2012 +0200
@@ -30,6 +30,8 @@
{$DEFINE USE_LUA_SCRIPT}
+{$DEFINE GL2}
+
{$IFDEF ANDROID}
{$DEFINE MOBILE}
{$DEFINE USE_SDLTHREADS}
@@ -53,6 +55,10 @@
{$ENDIF}
+{$IFDEF GL2}
+ {$DEFINE S3D_DISABLED}
+{$ENDIF}
+
{$IFDEF WIN32}
{$DEFINE USE_CONTEXT_RESTORE}
{$ENDIF}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uAtlas.pas Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,764 @@
+{$INCLUDE "options.inc"}
+{$IF GLunit = GL}{$DEFINE GLunit:=GL,GLext}{$ENDIF}
+
+unit uAtlas;
+
+interface
+
+uses SDLh, uTypes;
+
+procedure initModule;
+
+function Surface2Tex_(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+procedure FreeTexture_(sprite: PTexture);
+procedure DebugAtlas;
+procedure DumpInfo(tex: PTexture);
+
+implementation
+
+uses GLunit, uBinPacker, uDebug, png, sysutils, uTextures;
+
+const
+ MaxAtlases = 4; // Maximum number of atlases (textures) to allocate
+ MaxTexSize = 1024; // Maximum atlas size in pixels
+ MinTexSize = 128; // Minimum atlas size in pixels
+ CompressionThreshold = 0.4; // Try to compact (half the size of) an atlas, when occupancy is less than this
+
+type
+ AtlasInfo = record
+ PackerInfo: Atlas; // Rectangle packer context
+ TextureInfo: TAtlas; // OpenGL texture information
+ Allocated: boolean; // indicates if this atlas is in use
+ DumpID: Integer;
+ end;
+
+var
+ Info: array[0..MaxAtlases-1] of AtlasInfo;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Debug routines
+
+procedure DumpInfo(tex: PTexture);
+var
+ frame: Integer;
+ i, atlasID: Integer;
+ aw, ah: Integer;
+begin
+ if tex = nil then
+ exit;
+
+ frame:= 0;
+ writeln(stdout, 'Texture: ' + IntToHex(Integer(tex), 8));
+
+ while tex <> nil do
+ begin
+ atlasID:= -1;
+ for i:= 0 to Pred(MaxAtlases) do
+ if tex^.atlas = @Info[i].TextureInfo then
+ atlasID:=i;
+
+ aw:= tex^.atlas^.w;
+ ah:= tex^.atlas^.h;
+
+ writeln(stdout, 'Frame : ' + IntToStr(frame));
+ writeln(stdout, 'Size : ' + IntToStr(tex^.w) + 'x' + IntToStr(tex^.h));
+ writeln(stdout, 'Atlas : ' + IntToStr(atlasID));
+ writeln(stdout, 'Location: ' + IntToStr(tex^.x) + 'x' + IntToStr(tex^.y));
+ writeln(stdout, 'TB : ' + '(' + FloatToStrF(tex^.tb[0].X, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[0].Y, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[1].X, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[1].Y, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[2].X, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[2].Y, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[3].X, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[3].Y, ffFixed, 15, 4) + ')');
+
+ writeln(stdout, 'TB.ABS : ' + '(' + FloatToStrF(tex^.tb[0].X * aw, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[0].Y * ah, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[1].X * aw, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[1].Y * ah, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[2].X * aw, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[2].Y * ah, ffFixed, 15, 4) + ') '
+ + '(' + FloatToStrF(tex^.tb[3].X * aw, ffFixed, 15, 4) + ',' + FloatToStrF(tex^.tb[3].Y * ah, ffFixed, 15, 4) + ')');
+
+ inc(frame);
+ tex:= tex^.nextFrame;
+ end;
+ halt(0);
+end;
+
+procedure AssertCount(tex: PTexture; count: Integer);
+var
+ i, j: Integer;
+ found: Integer;
+begin
+ found:= 0;
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].Allocated then
+ continue;
+ for j:=0 to pred(Info[i].PackerInfo.usedRectangles.count) do
+ begin
+ if Info[i].PackerInfo.usedRectangles.data[j].UserData = tex then
+ inc(found);
+ end;
+ end;
+ if found <> count then
+ begin
+ writeln('AssertCount(', IntToHex(Integer(tex), 8), ') failed, found ', found, ' times');
+
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].Allocated then
+ continue;
+ for j:=0 to pred(Info[i].PackerInfo.usedRectangles.count) do
+ begin
+ if Info[i].PackerInfo.usedRectangles.data[j].UserData = tex then
+ writeln(' found in atlas ', i, ' at slot ', j);
+ end;
+ end;
+ halt(-2);
+ end;
+end;
+
+var
+ DumpFile: File of byte;
+
+const
+ PNG_COLOR_TYPE_RGBA = 6;
+ PNG_COLOR_TYPE_RGB = 2;
+ PNG_INTERLACE_NONE = 0;
+ PNG_COMPRESSION_TYPE_DEFAULT = 0;
+ PNG_FILTER_TYPE_DEFAULT = 0;
+
+
+
+procedure writefunc(png: png_structp; buffer: png_bytep; size: QWord); cdecl;
+var
+ p: Pbyte;
+ i: Integer;
+begin
+ //TStream(png_get_io_ptr(png)).Write(buffer^, size);
+ BlockWrite(DumpFile, buffer^, size);
+{ p:= PByte(buffer^);
+ for i:=0 to pred(size) do
+ begin
+ Write(DumpFile, p^);
+ inc(p);
+ end;}
+end;
+
+function IntToStrPad(i: Integer): string;
+var
+ s: string;
+begin
+ s:= IntToStr(i);
+ if (i < 10) then s:='0' + s;
+ if (i < 100) then s:='0' + s;
+ if (i < 1000) then s:='0' + s;
+
+ IntToStrPad:=s;
+end;
+
+// GL1 ATLAS DEBUG ONLY CODE!
+procedure DebugAtlas;
+{$IFDEF DEBUG_ATLAS}
+var
+ vp: array[0..3] of GLint;
+ prog: GLint;
+ i: Integer;
+ x, y: Integer;
+const
+ SZ = 512;
+begin
+ x:= 0;
+ y:= 0;
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].allocated then
+ continue;
+ glGetIntegerv(GL_VIEWPORT, @vp);
+{$IFDEF GL2}
+ glGetIntegerv(GL_CURRENT_PROGRAM, @prog);
+ glUseProgram(0);
+{$ENDIF}
+ glPushMatrix;
+ glLoadIdentity;
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix;
+ glLoadIdentity;
+ glOrtho(0, vp[2], vp[3], 0, -1, 1);
+
+ glDisable(GL_CULL_FACE);
+
+ glBindTexture(GL_TEXTURE_2D, Info[i].TextureInfo.id);
+ glBegin(GL_QUADS);
+ glTexCoord2f(0.0, 0.0);
+ glVertex2i(x * SZ, y * SZ);
+ glTexCoord2f(1.0, 0.0);
+ glVertex2i((x + 1) * SZ, y * SZ);
+ glTexCoord2f(1.0, 1.0);
+ glVertex2i((x + 1) * SZ, (y + 1) * SZ);
+ glTexCoord2f(0.0, 1.0);
+ glVertex2i(x * SZ, (y + 1) * SZ);
+ glEnd();
+
+ glPopMatrix;
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix;
+
+ inc(x);
+ if (x = 2) then
+ begin
+ x:=0;
+ inc(y);
+ end;
+
+{$IFDEF GL2}
+ glUseProgram(prog);
+{$ENDIF}
+ end;
+end;
+{$ELSE}
+begin;
+end;
+{$ENDIF}
+
+procedure DumpAtlas(var dinfo: AtlasInfo);
+var
+ png: png_structp;
+ png_info: png_infop;
+ w, h, sz: Integer;
+ filename: string;
+ rows: array of png_bytep;
+ size: Integer;
+ i, j: Integer;
+ idx: Integer;
+ mem, p, pp: PByte;
+begin
+ idx:= -1;
+ for i:= 0 to Pred(MaxAtlases) do
+ if @dinfo = @Info[i] then
+ idx:=i;
+
+ filename:= '/home/wolfgangst/hedgewars/dump/atlas_' + IntToStr(idx) + '_' + IntToStrPad(dinfo.DumpID) + '.png';
+ Assign(DumpFile, filename);
+ inc(dinfo.DumpID);
+ Rewrite(DumpFile);
+
+ w:= dinfo.TextureInfo.w;
+ h:= dinfo.TextureInfo.h;
+ size:= w * h * 4;
+ SetLength(rows, h);
+ GetMem(mem, size);
+
+ glBindTexture(GL_TEXTURE_2D, dinfo.TextureInfo.id);
+
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, mem);
+
+ p:= mem;
+ for i:= 0 to pred(h) do
+ begin
+ rows[i]:= p;
+ pp:= p;
+ inc(pp, 3);
+ {for j:= 0 to pred(w) do
+ begin
+ pp^:=255;
+ inc(pp, 4);
+ end;}
+ inc(p, w * 4);
+ end;
+
+ png := png_create_write_struct(PNG_LIBPNG_VER_STRING, nil, nil, nil);
+ png_info := png_create_info_struct(png);
+
+ png_set_write_fn(png, nil, @writefunc, nil);
+ png_set_IHDR(png, png_info, w, h, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_write_info(png, png_info);
+ png_write_image(png, @rows[0]);
+ png_write_end(png, png_info);
+ png_destroy_write_struct(@png, @png_info);
+
+ FreeMem(mem);
+
+ SetLength(rows, 0);
+ Close(DumpFile);
+
+ //if (DumpID >= 30) then
+ // halt(0);
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+// Upload routines
+
+function createTexture(width, height: Integer): TAtlas;
+var
+ nullTex: Pointer;
+begin
+ createTexture.w:= width;
+ createTexture.h:= height;
+ createTexture.priority:= 0;
+ glGenTextures(1, @createTexture.id);
+ glBindTexture(GL_TEXTURE_2D, createTexture.id);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
+
+ GetMem(NullTex, width * height * 4);
+ FillChar(NullTex^, width * height * 4, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NullTex);
+ FreeMem(NullTex);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+end;
+
+function Min(x, y: Single): Single;
+begin
+ if x < y then
+ Min:=x
+ else Min:=y;
+end;
+
+function Max(x, y: Single): Single;
+begin
+ if x > y then
+ Max:=x
+ else Max:=y;
+end;
+
+
+procedure HSVToRGB(const H, S, V: Single; out R, G, B: Single);
+const
+ SectionSize = 60/360;
+var
+ Section: Single;
+ SectionIndex: Integer;
+ f: single;
+ p, q, t: Single;
+begin
+ if H < 0 then
+ begin
+ R:= V;
+ G:= R;
+ B:= R;
+ end
+ else
+ begin
+ Section:= H/SectionSize;
+ SectionIndex:= Trunc(Section);
+ f:= Section - SectionIndex;
+ p:= V * ( 1 - S );
+ q:= V * ( 1 - S * f );
+ t:= V * ( 1 - S * ( 1 - f ) );
+ case SectionIndex of
+ 0:
+ begin
+ R:= V;
+ G:= t;
+ B:= p;
+ end;
+ 1:
+ begin
+ R:= q;
+ G:= V;
+ B:= p;
+ end;
+ 2:
+ begin
+ R:= p;
+ G:= V;
+ B:= t;
+ end;
+ 3:
+ begin
+ R:= p;
+ G:= q;
+ B:= V;
+ end;
+ 4:
+ begin
+ R:= t;
+ G:= p;
+ B:= V;
+ end;
+ else
+ R:= V;
+ G:= p;
+ B:= q;
+ end;
+ end;
+end;
+
+procedure DebugColorize(surf: PSDL_Surface);
+var
+ sz: Integer;
+ p: PByte;
+ i: Integer;
+ r, g, b, a, inva: Integer;
+ randr, randg, randb: Single;
+ randh: Single;
+begin
+ sz:= surf^.w * surf^.h;
+ p:= surf^.pixels;
+ //randr:=Random;
+ //randg:=Random;
+ //randb:=1 - min(randr, randg);
+ randh:=Random;
+ HSVToRGB(randh, 1.0, 1.0, randr, randg, randb);
+ for i:=0 to pred(sz) do
+ begin
+ a:= p[3];
+ inva:= 255 - a;
+
+ r:=Trunc(inva*randr + p[0]*a/255);
+ g:=Trunc(inva*randg + p[1]*a/255);
+ b:=Trunc(inva*randb + p[2]*a/255);
+ if r > 255 then r:= 255;
+ if g > 255 then g:= 255;
+ if b > 255 then b:= 255;
+
+ p[0]:=r;
+ p[1]:=g;
+ p[2]:=b;
+ p[3]:=255;
+ inc(p, 4);
+ end;
+end;
+
+procedure Upload(var info: AtlasInfo; sprite: Rectangle; surf: PSDL_Surface);
+var
+ sp: PTexture;
+ i, j, stride: Integer;
+ scanline: PByte;
+ r: TSDL_Rect;
+begin
+ //writeln('Uploading sprite to ', sprite.x, ',', sprite.y, ',', sprite.width, ',', sprite.height);
+ sp:= PTexture(sprite.UserData);
+ sp^.x:= sprite.x;
+ sp^.y:= sprite.y;
+ sp^.isRotated:= sp^.w <> sprite.width;
+ sp^.atlas:= @info.TextureInfo;
+
+ if SDL_MustLock(surf) then
+ SDLTry(SDL_LockSurface(surf) >= 0, true);
+
+ //if GrayScale then
+ // Surface2GrayScale(surf);
+ //DebugColorize(surf);
+
+ glBindTexture(GL_TEXTURE_2D, info.TextureInfo.id);
+ if (sp^.isRotated) then
+ begin
+ scanline:= surf^.pixels;
+ for i:= 0 to pred(sprite.width) do
+ begin
+ glTexSubImage2D(GL_TEXTURE_2D, 0, sprite.x + i, sprite.y, 1, sprite.height, GL_RGBA, GL_UNSIGNED_BYTE, scanline);
+ inc(scanline, sprite.height * 4);
+ end;
+ end
+ else
+ glTexSubImage2D(GL_TEXTURE_2D, 0, sprite.x, sprite.y, sprite.width, sprite.height, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ if SDL_MustLock(surf) then
+ SDL_UnlockSurface(surf);
+
+ r.x:= 0;
+ r.y:= 0;
+ r.w:= sp^.w;
+ r.h:= sp^.h;
+ ComputeTexcoords(sp, @r, @sp^.tb);
+end;
+
+procedure Repack(var info: AtlasInfo; newAtlas: Atlas);
+var
+ base: PByte;
+ oldSize: Integer;
+ oldWidth: Integer;
+ offset: Integer;
+ i,j : Integer;
+ r: Rectangle;
+ sp: PTexture;
+ newIsRotated: boolean;
+ newSpriteRect: Rectangle;
+begin
+ writeln('Repacking atlas (', info.PackerInfo.width, 'x', info.PackerInfo.height, ')', ' -> (', newAtlas.width, 'x', newAtlas.height, ')');
+
+ // delete the old atlas
+ glDeleteTextures(1, @info.TextureInfo.id);
+
+ // create a new atlas with different size
+ info.TextureInfo:= createTexture(newAtlas.width, newAtlas.height);
+ glBindTexture(GL_TEXTURE_2D, info.TextureInfo.id);
+
+ atlasDelete(info.PackerInfo);
+ info.PackerInfo:= newAtlas;
+
+ // and process all sprites of the new atlas
+ for i:=0 to pred(newAtlas.usedRectangles.count) do
+ begin
+ r:= newAtlas.usedRectangles.data[i];
+ sp:= PTexture(r.UserData);
+ Upload(info, r, sp^.surface);
+ end;
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+end;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Utility functions
+
+function SizeForSprite(sprite: PTexture): Size;
+begin
+ SizeForSprite.width:= sprite^.w;
+ SizeForSprite.height:= sprite^.h;
+ SizeForSprite.UserData:= sprite;
+end;
+
+procedure EnlargeSize(var x: Integer; var y: Integer);
+begin
+ if (y < x) then
+ y:= y + y
+ else
+ x:= x + x;
+end;
+
+procedure CompactSize(var x: Integer; var y: Integer);
+begin
+ if (x > y) then
+ x:= x div 2
+ else
+ y:= y div 2;
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+// Sprite allocation logic
+
+function TryRepack(var info: AtlasInfo; w, h: Integer; hasNewSprite: boolean; newSprite: Size): boolean;
+var
+ sizes: SizeList;
+ repackedAtlas: Atlas;
+ sprite: PTexture;
+ i: Integer;
+ rects: RectangleList; // we wont really need this as we do a full repack using the atlas later on
+begin
+ TryRepack:= false;
+
+ // STEP 1: collect sizes of all existing sprites
+ sizeListInit(sizes);
+ for i:= 0 to pred(info.PackerInfo.usedRectangles.count) do
+ begin
+ sprite:= PTexture(info.PackerInfo.usedRectangles.data[i].UserData);
+ sizeListAdd(sizes, SizeForSprite(sprite));
+ end;
+
+ // STEP 2: add the new sprite to the list
+ if hasNewSprite then
+ sizeListAdd(sizes, newSprite);
+
+ // STEP 3: try to create a non adaptive re-packing using the whole list
+ repackedAtlas:= atlasNew(w, h);
+ rectangleListInit(rects);
+ if atlasInsertSet(repackedAtlas, sizes, rects) then
+ begin
+ TryRepack:= true;
+ Repack(info, repackedAtlas);
+ // repack assigns repackedAtlas to the current info and deletes the old one
+ // thus we wont do atlasDelete(repackedAtlas); here
+ rectangleListClear(rects);
+ sizeListClear(sizes);
+ //DumpAtlas(info);
+ exit;
+ end;
+
+ rectangleListClear(rects);
+ sizeListClear(sizes);
+ atlasDelete(repackedAtlas);
+end;
+
+function TryInsert(var info: AtlasInfo; newSprite: Size; surf: PSDL_Surface): boolean;
+var
+ rect: Rectangle;
+ sprite: PTexture;
+begin
+ TryInsert:= false;
+
+ if atlasInsertAdaptive(info.PackerInfo, newSprite, rect) then
+ begin
+ // we succeeded adaptivley allocating the sprite to the i'th atlas.
+ Upload(info, rect, surf);
+ //DumpAtlas(info);
+ TryInsert:= true;
+ end;
+end;
+
+function Surface2Tex_(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+var
+ sz: Size;
+ sprite: PTexture;
+ currentWidth, currentHeight: Integer;
+ i: Integer;
+begin
+ if (surf^.w > MaxTexSize) or (surf^.h > MaxTexSize) then
+ begin
+ // we could at best downscale the sprite, abort for now
+ writeln('Sprite size larger than maximum texture size');
+ halt(-1);
+ end;
+
+ // allocate the sprite
+ new(sprite);
+ Surface2Tex_:= sprite;
+
+ sprite^.w:= surf^.w;
+ sprite^.h:= surf^.h;
+ sprite^.x:= 0;
+ sprite^.y:= 0;
+ sprite^.isRotated:= false;
+ sprite^.surface:= surf;
+ sprite^.shared:= true;
+ sprite^.nextFrame:= nil;
+
+ sz:= SizeForSprite(sprite);
+
+ // STEP 1
+ // try to allocate the new sprite in one of the existing atlases
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].Allocated then
+ continue;
+ if TryInsert(Info[i], sz, surf) then
+ exit;
+ end;
+
+
+ // STEP 2
+ // none of the atlases has space left for the allocation, try a garbage collection
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].Allocated then
+ continue;
+
+ if TryRepack(Info[i], Info[i].PackerInfo.width, Info[i].PackerInfo.height, true, sz) then
+ exit;
+ end;
+
+ // STEP 3
+ // none of the atlases could be repacked in a way to fit the new sprite, try enlarging
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if not Info[i].Allocated then
+ continue;
+
+ currentWidth:= Info[i].PackerInfo.width;
+ currentHeight:= Info[i].PackerInfo.height;
+
+ EnlargeSize(currentWidth, currentHeight);
+ while (currentWidth <= MaxTexSize) and (currentHeight <= MaxTexSize) do
+ begin
+ if TryRepack(Info[i], currentWidth, currentHeight, true, sz) then
+ exit;
+ EnlargeSize(currentWidth, currentHeight);
+ end;
+ end;
+
+ // STEP 4
+ // none of the existing atlases could be resized, try to allocate a new atlas
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if Info[i].Allocated then
+ continue;
+
+ currentWidth:= MinTexSize;
+ currentHeight:= MinTexSize;
+ while (sz.width > currentWidth) do
+ currentWidth:= currentWidth + currentWidth;
+ while (sz.height > currentHeight) do
+ currentHeight:= currentHeight + currentHeight;
+
+ with Info[i] do
+ begin
+ PackerInfo:= atlasNew(currentWidth, currentHeight);
+ TextureInfo:= createTexture(currentWidth, currentHeight);
+ Allocated:= true;
+ end;
+
+ if TryInsert(Info[i], sz, surf) then
+ exit;
+
+ // this shouldnt have happened, the rectpacker should be able to fit the sprite
+ // into an unused rectangle that is the same size or larger than the requested sprite.
+ writeln('Internal error: atlas allocation failed');
+ halt(-1);
+ end;
+
+ // we reached the upperbound of resources we are willing to allocate
+ writeln('Exhausted maximum sprite allocation size');
+ halt(-1);
+end;
+
+////////////////////////////////////////////////////////////////////////////////
+// Sprite deallocation logic
+
+
+procedure FreeTexture_(sprite: PTexture);
+var
+ i, j, deleteAt: Integer;
+ usedArea: Integer;
+ totalArea: Integer;
+ r: Rectangle;
+ atlasW, atlasH: Integer;
+ unused: Size;
+begin
+ if sprite = nil then
+ exit;
+
+ deleteAt:= -1;
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ if sprite^.atlas <> @Info[i].TextureInfo then
+ continue;
+
+ usedArea:= 0;
+ for j:=0 to pred(Info[i].PackerInfo.usedRectangles.count) do
+ begin
+ r:= Info[i].PackerInfo.usedRectangles.data[j];
+ if r.UserData = sprite then
+ deleteAt:= j
+ else
+ inc(usedArea, r.width * r.height);
+ end;
+
+ rectangleListRemoveAt(Info[i].PackerInfo.usedRectangles, deleteAt);
+ dispose(sprite);
+
+ while true do
+ begin
+ atlasW:= Info[i].PackerInfo.width;
+ atlasH:= Info[i].PackerInfo.height;
+ totalArea:= atlasW * atlasH;
+ if usedArea >= totalArea * CompressionThreshold then
+ exit;
+
+ if (atlasW = MinTexSize) and (atlasH = MinTexSize) then
+ exit; // we could try to move everything from this to another atlas here
+
+ CompactSize(atlasW, atlasH);
+ unused:= unused;
+ TryRepack(Info[i], atlasW, atlasH, false, unused);
+ end;
+
+ exit;
+ end;
+end;
+
+procedure initModule;
+var
+ i: Integer;
+begin
+ for i:= 0 to pred(MaxAtlases) do
+ begin
+ Info[i].Allocated:= false;
+ Info[i].DumpID:=0;
+ end;
+end;
+
+end.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uBinPacker.pas Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,438 @@
+unit uBinPacker;
+
+interface
+
+// implements a maxrects packer with best short side fit heuristic
+
+type Rectangle = record
+ x, y, width, height: LongInt;
+ UserData: Pointer;
+end;
+
+type Size = record
+ width, height: LongInt;
+ UserData: Pointer;
+end;
+
+type PRectangle = ^Rectangle;
+type PSize = ^Size;
+
+type RectangleList = record
+ data: PRectangle;
+ count: LongInt;
+ size: LongInt;
+end;
+
+type SizeList = record
+ data: PSize;
+ count: LongInt;
+ size: LongInt;
+end;
+
+type Atlas = record
+ width, height: Longint;
+ freeRectangles: RectangleList;
+ usedRectangles: RectangleList;
+end;
+
+function atlasInsertAdaptive(var a: Atlas; sz: Size; var output: Rectangle): boolean;
+function atlasInsertSet(var a: Atlas; var input: SizeList; var outputs: RectangleList): boolean;
+function atlasNew(width, height: LongInt): Atlas;
+procedure atlasDelete(var a: Atlas);
+procedure atlasReset(var a: Atlas);
+
+procedure rectangleListInit(var list: RectangleList);
+procedure rectangleListRemoveAt(var list: RectangleList; index: LongInt);
+procedure rectangleListAdd(var list: RectangleList; r: Rectangle);
+procedure rectangleListClear(var list: RectangleList);
+procedure sizeListInit(var list: SizeList);
+procedure sizeListRemoveAt(var list: SizeList; index: LongInt);
+procedure sizeListAdd(var list: SizeList; s: Size); overload;
+procedure sizeListAdd(var list: SizeList; width, height: LongInt; UserData: Pointer); overload;
+procedure sizeListClear(var list: SizeList);
+
+implementation
+
+uses Math; // for min/max
+
+procedure rectangleListRemoveAt(var list: RectangleList; index: LongInt);
+var
+ i: Integer;
+begin
+ i:=index;
+ while (i + 1 < list.count) do
+ begin
+ list.data[i]:=list.data[i + 1];
+ inc(i);
+ end;
+ dec(list.count);
+end;
+
+procedure rectangleListAdd(var list: RectangleList; r: Rectangle);
+begin
+ if list.count >= list.size then
+ begin
+ inc(list.size, 512);
+ ReAllocMem(list.data, sizeof(Rectangle) * list.size);
+ end;
+ list.data[list.count]:=r;
+ inc(list.count);
+end;
+
+procedure rectangleListInit(var list: RectangleList);
+begin
+ list.data:= nil;
+ list.count:= 0;
+ list.size:= 0;
+end;
+
+procedure rectangleListClear(var list: RectangleList);
+begin
+ FreeMem(list.data);
+ list.count:= 0;
+ list.size:= 0;
+end;
+
+procedure sizeListRemoveAt(var list: SizeList; index: LongInt);
+begin
+ list.data[index]:= list.data[list.count - 1];
+ dec(list.count);
+end;
+
+procedure sizeListAdd(var list: SizeList; s: Size); overload;
+begin
+ if list.count >= list.size then
+ begin
+ inc(list.size, 512);
+ ReAllocMem(list.data, sizeof(Size) * list.size);
+ end;
+ list.data[list.count]:=s;
+ inc(list.count);
+end;
+
+procedure sizeListAdd(var list: SizeList; width, height: LongInt; UserData: Pointer); overload;
+var
+ sz: Size;
+begin
+ sz.width:= width;
+ sz.height:= height;
+ sz.UserData:= UserData;
+ sizeListAdd(list, sz);
+end;
+
+procedure sizeListInit(var list: SizeList);
+begin
+ list.data:= nil;
+ list.count:= 0;
+ list.size:= 0;
+end;
+
+procedure sizeListClear(var list: SizeList);
+begin
+ FreeMem(list.data);
+ list.count:= 0;
+ list.size:= 0;
+end;
+
+
+function isContainedIn(a, b: Rectangle): boolean;
+begin
+ isContainedIn:= (a.x >= b.x) and (a.y >= b.y)
+ and (a.x + a.width <= b.x + b.width)
+ and (a.y + a.height <= b.y + b.height);
+end;
+
+function findPositionForNewNodeBestShortSideFit(var list: RectangleList; width, height: LongInt;
+ var bestShortSideFit, bestLongSideFit: LongInt): Rectangle;
+var
+ bestNode: Rectangle;
+ i: Integer;
+ ri: Rectangle;
+ leftoverHoriz, leftoverVert, shortSideFit, longSideFit: Longint;
+begin
+ bestNode.x:= 0;
+ bestNode.y:= 0;
+ bestNode.width:= 0;
+ bestNode.height:= 0;
+ bestShortSideFit:= $7FFFFFFF;
+
+ for i:=0 to pred(list.count) do
+ begin
+ ri:= list.data[i];
+
+ // Try to place the rectangle in upright (non-flipped) orientation.
+ if (ri.width >= width) and (ri.height >= height) then
+ begin
+ leftoverHoriz:= Abs(ri.width - width);
+ leftoverVert:= Abs(ri.height - height);
+ shortSideFit:= Min(leftoverHoriz, leftoverVert);
+ longSideFit:= Max(leftoverHoriz, leftoverVert);
+
+ if (shortSideFit < bestShortSideFit) or
+ ((shortSideFit = bestShortSideFit) and (longSideFit < bestLongSideFit)) then
+ begin
+ bestNode.x:= ri.x;
+ bestNode.y:= ri.y;
+ bestNode.width:= width;
+ bestNode.height:= height;
+ bestShortSideFit:= shortSideFit;
+ bestLongSideFit:= longSideFit;
+ end;
+ end;
+
+ if (ri.width >= height) and (ri.height >= width) then
+ begin
+ leftoverHoriz:= Abs(ri.width - height);
+ leftoverVert:= Abs(ri.height - width);
+ shortSideFit:= Min(leftoverHoriz, leftoverVert);
+ longSideFit:= Max(leftoverHoriz, leftoverVert);
+
+ if (shortSideFit < bestShortSideFit) or
+ ((shortSideFit = bestShortSideFit) and (longSideFit < bestLongSideFit)) then
+ begin
+ bestNode.x:= ri.x;
+ bestNode.y:= ri.y;
+ bestNode.width:= height;
+ bestNode.height:= width;
+ bestShortSideFit:= shortSideFit;
+ bestLongSideFit:= longSideFit;
+ end;
+ end;
+ end;
+
+ findPositionForNewNodeBestShortSideFit:= bestNode;
+end;
+
+function scoreRect(var list: RectangleList; width, height: LongInt; var score1, score2: LongInt): Rectangle;
+var
+ newNode: Rectangle;
+begin
+ newNode:= findPositionForNewNodeBestShortSideFit(list, width, height, score1, score2);
+
+ // Cannot fit the current rectangle.
+ if newNode.height = 0 then
+ begin
+ score1:= $7FFFFFFF;
+ score2:= $7FFFFFFF;
+ end;
+
+ scoreRect:= newNode;
+end;
+
+function splitFreeNode(var freeRectangles: RectangleList; freeNode, usedNode: Rectangle): boolean;
+var
+ newNode: Rectangle;
+begin
+ // Test with SAT if the rectangles even intersect.
+ if (usedNode.x >= freeNode.x + freeNode.width) or (usedNode.x + usedNode.width <= freeNode.x) or
+ (usedNode.y >= freeNode.y + freeNode.height) or (usedNode.y + usedNode.height <= freeNode.y) then
+ begin
+ splitFreeNode:=false;
+ exit;
+ end;
+
+ if (usedNode.x < freeNode.x + freeNode.width) and (usedNode.x + usedNode.width > freeNode.x) then
+ begin
+ // New node at the top side of the used node.
+ if (usedNode.y > freeNode.y) and (usedNode.y < freeNode.y + freeNode.height) then
+ begin
+ newNode:= freeNode;
+ newNode.height:= usedNode.y - newNode.y;
+ rectangleListAdd(freeRectangles, newNode);
+ end;
+
+ // New node at the bottom side of the used node.
+ if (usedNode.y + usedNode.height < freeNode.y + freeNode.height) then
+ begin
+ newNode:= freeNode;
+ newNode.y:= usedNode.y + usedNode.height;
+ newNode.height:= freeNode.y + freeNode.height - (usedNode.y + usedNode.height);
+ rectangleListAdd(freeRectangles, newNode);
+ end;
+ end;
+
+ if (usedNode.y < freeNode.y + freeNode.height) and (usedNode.y + usedNode.height > freeNode.y) then
+ begin
+ // New node at the left side of the used node.
+ if (usedNode.x > freeNode.x) and (usedNode.y < freeNode.y + freeNode.width) then
+ begin
+ newNode:= freeNode;
+ newNode.width:= usedNode.x - newNode.x;
+ rectangleListAdd(freeRectangles, newNode);
+ end;
+
+ // New node at the right side of the used node.
+ if (usedNode.x + usedNode.width < freeNode.x + freeNode.width) then
+ begin
+ newNode:= freeNode;
+ newNode.x:= usedNode.x + usedNode.width;
+ newNode.width:= freeNode.x + freeNode.width - (usedNode.x + usedNode.width);
+ rectangleListAdd(freeRectangles, newNode);
+ end;
+ end;
+
+ splitFreeNode:= true;
+end;
+
+procedure pruneFreeList(var freeRectangles: RectangleList);
+var
+ i, j: LongInt;
+begin
+ // Go through each pair and remove any rectangle that is redundant.
+ i:= 0;
+ while i < freeRectangles.count do
+ begin
+ j:= i + 1;
+ while j < freeRectangles.count do
+ begin
+ if (isContainedIn(freeRectangles.data[i], freeRectangles.data[j])) then
+ begin
+ rectangleListRemoveAt(freeRectangles, i);
+ dec(i);
+ break;
+ end;
+
+ if (isContainedIn(freeRectangles.data[j], freeRectangles.data[i])) then
+ rectangleListRemoveAt(freeRectangles, j)
+ else
+ inc(j);
+ end;
+ inc(i);
+ end;
+end;
+
+function atlasInsertAdaptive(var a: Atlas; sz: Size; var output: Rectangle): boolean;
+var
+ newNode: Rectangle;
+ score1, score2: LongInt;
+ numRectanglesToProcess: LongInt;
+ i: LongInt;
+begin
+ newNode:= findPositionForNewNodeBestShortSideFit(a.freeRectangles, sz.width, sz.height, score1, score2);
+ if newNode.height = 0 then
+ begin
+ output:= newNode;
+ output.UserData:= nil;
+ atlasInsertAdaptive:= false;
+ exit;
+ end;
+
+ numRectanglesToProcess:= a.freeRectangles.count;
+
+ i:=0;
+ while i < numRectanglesToProcess do
+ begin
+ if splitFreeNode(a.freeRectangles, a.freeRectangles.data[i], newNode) then
+ begin
+ rectangleListRemoveAt(a.freeRectangles, i);
+ dec(numRectanglesToProcess);
+ end
+ else
+ inc(i);
+ end;
+
+ pruneFreeList(a.freeRectangles);
+ newNode.UserData:= sz.UserData;
+ rectangleListAdd(a.usedRectangles, newNode);
+ output:= newNode;
+ atlasInsertAdaptive:= true;
+end;
+
+procedure placeRect(var a: Atlas; node: Rectangle);
+var
+ numRectanglesToProcess: LongInt;
+ i: LongInt;
+begin
+ numRectanglesToProcess:= a.freeRectangles.Count;
+
+ i:= 0;
+ while i < numRectanglesToProcess do
+ begin
+ if not splitFreeNode(a.freeRectangles, a.freeRectangles.data[i], node) then
+ inc(i)
+ else
+ begin
+ rectangleListRemoveAt(a.freeRectangles, i);
+ dec(numRectanglesToProcess);
+ end;
+ end;
+
+ pruneFreeList(a.freeRectangles);
+ rectangleListAdd(a.usedRectangles, node);
+end;
+
+
+function atlasInsertSet(var a: Atlas; var input: SizeList; var outputs: RectangleList): boolean;
+var
+ bestScore1, bestScore2, bestRectIndex: LongInt;
+ score1, score2: LongInt;
+ bestNode, newNode: Rectangle;
+ i: LongInt;
+ sz: Size;
+begin
+ atlasInsertSet:= false;
+
+ while input.count > 0 do
+ begin
+ bestScore1:= $7FFFFFFF;
+ bestScore2:= $7FFFFFFF;
+ bestRectIndex:= -1;
+
+ for i:=0 to pred(input.count) do
+ begin
+ sz:= input.data[i];
+ newNode:= scoreRect(a.freeRectangles, sz.width, sz.height, score1, score2);
+
+ if (score1 >= bestScore1) and ((score1 <> bestScore1) or (score2 >= bestScore2)) then
+ continue;
+
+ bestScore1:= score1;
+ bestScore2:= score2;
+ bestNode:= newNode;
+ bestRectIndex:= i;
+ end;
+
+ if bestRectIndex = -1 then
+ exit;
+
+ bestNode.UserData:= input.data[bestRectIndex].UserData;
+ placeRect(a, bestNode);
+ rectangleListAdd(outputs, bestNode);
+ sizeListRemoveAt(input, bestRectIndex);
+ end;
+ atlasInsertSet:= true;
+end;
+
+function atlasNew(width, height: LongInt): Atlas;
+var
+ a: Atlas;
+ r: Rectangle;
+begin
+ rectangleListInit(a.freeRectangles);
+ rectangleListInit(a.usedRectangles);
+
+ a.width:= width;
+ a.height:= height;
+ r.x:= 0;
+ r.y:= 0;
+ r.width:= width;
+ r.height:= height;
+ rectangleListAdd(a.freeRectangles, r);
+
+ atlasNew:=a;
+end;
+
+procedure atlasDelete(var a: atlas);
+begin
+ rectangleListClear(a.freeRectangles);
+ rectangleListClear(a.usedRectangles);
+end;
+
+procedure atlasReset(var a: atlas);
+begin
+ atlasDelete(a);
+ a:=atlasNew(a.width, a.height);
+end;
+
+begin
+end.
--- a/hedgewars/uChat.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uChat.pas Tue Jul 10 11:09:38 2012 +0200
@@ -31,7 +31,7 @@
procedure KeyPressChat(Key: Longword);
implementation
-uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
+uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uStore, uIO;
const MaxStrIndex = 27;
@@ -96,9 +96,7 @@
SDL_FreeSurface(strSurface);
cl.Time:= RealTicks + 12500;
-cl.Tex:= Surface2Tex(resSurface, false);
-
-SDL_FreeSurface(resSurface)
+cl.Tex:= Surface2Atlas(resSurface, false);
end;
// For uStore texture recreation
--- a/hedgewars/uGearsRender.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uGearsRender.pas Tue Jul 10 11:09:38 2012 +0200
@@ -37,7 +37,7 @@
end;
implementation
-uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGears;
+uses uRender, uStore, uUtils, uVariables, uAmmos, Math, uVisualGears;
procedure DrawRopeLinesRQ(Gear: PGear);
begin
@@ -54,20 +54,18 @@
glDisable(GL_TEXTURE_2D);
//glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
-
- glTranslatef(WorldDx, WorldDy, 0);
+ ResetRotation;
+ SetOffset(WorldDx, WorldDy);
+ UpdateModelview;
glLineWidth(4.0);
Tint($C0, $C0, $C0, $FF);
- glVertexPointer(2, GL_FLOAT, 0, @RopePoints.rounded[0]);
+ SetVertexPointer(@RopePoints.rounded[0]);
glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2);
Tint($FF, $FF, $FF, $FF);
- glPopMatrix;
-
glEnable(GL_TEXTURE_2D);
//glDisable(GL_LINE_SMOOTH)
end
@@ -1036,7 +1034,7 @@
else
DrawSpriteRotatedF(sprExplosivesRoll, x, y + 4, 1, 0, Gear^.DirAngle);
end;
- gtDynamite: DrawSprite(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
+ gtDynamite: begin writeln(stdout, 'FIXME'); halt(-3); end; //DrawSprite(sprDynamite, x - 16, y - 25, Gear^.Tag and 1, Gear^.Tag shr 1);
gtClusterBomb: DrawSpriteRotated(sprClusterBomb, x, y, 0, Gear^.DirAngle);
gtCluster: DrawSprite(sprClusterParticle, x - 8, y - 8, 0);
gtFlame: if Gear^.Tag and 1 = 0 then
--- a/hedgewars/uLandTexture.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uLandTexture.pas Tue Jul 10 11:09:38 2012 +0200
@@ -99,7 +99,7 @@
with LandTextures[x, y] do
begin
tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y));
- glBindTexture(GL_TEXTURE_2D, tex^.id);
+ glBindTexture(GL_TEXTURE_2D, tex^.atlas^.id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, tpHigh);
end
else
@@ -156,7 +156,7 @@
if not isEmpty then
begin
if tex = nil then tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y));
- glBindTexture(GL_TEXTURE_2D, tex^.id);
+ glBindTexture(GL_TEXTURE_2D, tex^.atlas^.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y));
end
else if tex <> nil then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uMatrix.pas Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,123 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uMatrix;
+
+interface
+
+uses uTypes, gl;
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+
+implementation
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+begin
+ Result[0,0]:= 1.0; Result[1,0]:=0.0; Result[2,0]:=0.0; Result[3,0]:=0.0;
+ Result[0,1]:= 0.0; Result[1,1]:=1.0; Result[2,1]:=0.0; Result[3,1]:=0.0;
+ Result[0,2]:= 0.0; Result[1,2]:=0.0; Result[2,2]:=1.0; Result[3,2]:=0.0;
+ Result[0,3]:= 0.0; Result[1,3]:=0.0; Result[2,3]:=0.0; Result[3,3]:=1.0;
+end;
+
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+var
+ test: TMatrix4x4f;
+ i, j: Integer;
+ error: boolean;
+begin
+ Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+ Result[0,1]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+ Result[0,2]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+ Result[0,3]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+
+ Result[1,0]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+ Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+ Result[1,2]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+ Result[1,3]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+
+ Result[2,0]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+ Result[2,1]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+ Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+ Result[2,3]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+
+ Result[3,0]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+ Result[3,1]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+ Result[3,2]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+ Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+
+{
+ Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+ Result[0,1]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+ Result[0,2]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+ Result[0,3]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+
+ Result[1,0]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+ Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+ Result[1,2]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+ Result[1,3]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+
+ Result[2,0]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+ Result[2,1]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+ Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+ Result[2,3]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+
+ Result[3,0]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+ Result[3,1]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+ Result[3,2]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+ Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+}
+ glPushMatrix;
+ glLoadMatrixf(@lhs[0, 0]);
+ glMultMatrixf(@rhs[0, 0]);
+ glGetFloatv(GL_MODELVIEW_MATRIX, @test[0, 0]);
+ glPopMatrix;
+
+ error:=false;
+ for i:=0 to 3 do
+ for j:=0 to 3 do
+ if Abs(test[i, j] - Result[i, j]) > 0.000001 then
+ error:=true;
+
+ if error then
+ begin
+ writeln('shall:');
+ for i:=0 to 3 do
+ begin
+ for j:=0 to 3 do
+ write(test[i, j]);
+ writeln;
+ end;
+
+ writeln('is:');
+ for i:=0 to 3 do
+ begin
+ for j:=0 to 3 do
+ write(Result[i, j]);
+ writeln;
+ end;
+ halt(0);
+ end;
+
+
+end;
+
+
+end.
--- a/hedgewars/uRender.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uRender.pas Tue Jul 10 11:09:38 2012 +0200
@@ -22,10 +22,9 @@
interface
-uses SDLh, uTypes, GLunit, uConsts;
+uses SDLh, uTypes, GLunit, uConsts, uTextures, math;
procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt);
-procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
procedure DrawSpriteFromRect (Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
procedure DrawSpriteClipped (Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
procedure DrawSpriteRotated (Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -48,14 +47,78 @@
procedure DrawHedgehog (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
procedure DrawScreenWidget (widget: POnScreenWidget);
-procedure Tint (r, g, b, a: Byte); inline;
-procedure Tint (c: Longword); inline;
+// This is just temporary and becomes non public once everything changed to GL2
+procedure UpdateModelview;
+procedure ResetModelview;
+procedure SetOffset(X, Y: Longint);
+procedure ResetRotation;
implementation
-uses uVariables;
+uses uVariables, uStore;
+
+const DegToRad = 0.01745329252; // 2PI / 360
+
+procedure UpdateModelview;
+begin
+{$IFDEF GL2}
+ UpdateModelviewProjection;
+{$ELSE}
+ glLoadMatrixf(@mModelview[0,0]);
+{$ENDIF}
+end;
+
+procedure ResetModelview;
+begin
+ mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0; mModelview[3,0]:= 0;
+ mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0; mModelview[3,1]:= 0;
+ UpdateModelview;
+end;
+
+procedure SetOffset(X, Y: Longint);
+begin
+ mModelview[3,0]:= X;
+ mModelview[3,1]:= Y;
+end;
+
+procedure AddOffset(X, Y: GLfloat); // probably want to refactor this to use integers
+begin
+ mModelview[3,0]:=mModelview[3,0] + mModelview[0,0]*X + mModelview[1,0]*Y;
+ mModelview[3,1]:=mModelview[3,1] + mModelview[0,1]*X + mModelview[1,1]*Y;
+end;
-var LastTint: LongWord = 0;
+procedure SetScale(Scale: GLfloat);
+begin
+ mModelview[0,0]:= Scale;
+ mModelview[1,1]:= Scale;
+end;
+
+procedure AddScale(Scale: GLfloat);
+begin
+ mModelview[0,0]:= mModelview[0,0]*Scale; mModelview[1,0]:= mModelview[1,0]*Scale;
+ mModelview[0,1]:= mModelview[0,1]*Scale; mModelview[1,1]:= mModelview[1,1]*Scale;
+end;
+
+procedure AddScale(X, Y: GLfloat);
+begin
+ mModelview[0,0]:= mModelview[0,0]*X; mModelview[1,0]:= mModelview[1,0]*Y;
+ mModelview[0,1]:= mModelview[0,1]*X; mModelview[1,1]:= mModelview[1,1]*Y;
+end;
+
+
+procedure SetRotation(Angle, ZAxis: GLfloat);
+var s, c: Extended;
+begin
+ SinCos(Angle*DegToRad, s, c);
+ mModelview[0,0]:= c; mModelview[1,0]:=-s*ZAxis;
+ mModelview[0,1]:= s*ZAxis; mModelview[1,1]:= c;
+end;
+
+procedure ResetRotation;
+begin
+ mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0;
+ mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0;
+end;
procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
begin
@@ -70,52 +133,48 @@
end;
procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
-var rr: TSDL_Rect;
- _l, _r, _t, _b: real;
- VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
+var
+ rr: TSDL_Rect;
+ VertexBuffer, TextureBuffer: TVertexRect;
+ _l, _r, _t, _b: GLfloat;
begin
-if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
- exit;
+ if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
+ exit;
-// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
-if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
- exit;
-if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
- exit;
+ // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
+ if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
+ exit;
+ if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
+ exit;
-rr.x:= X;
-rr.y:= Y;
-rr.w:= W;
-rr.h:= H;
+ rr.x:= X;
+ rr.y:= Y;
+ rr.w:= W;
+ rr.h:= H;
-_l:= r^.x / SourceTexture^.w * SourceTexture^.rx;
-_r:= (r^.x + r^.w) / SourceTexture^.w * SourceTexture^.rx;
-_t:= r^.y / SourceTexture^.h * SourceTexture^.ry;
-_b:= (r^.y + r^.h) / SourceTexture^.h * SourceTexture^.ry;
+ glBindTexture(GL_TEXTURE_2D, SourceTexture^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
+ ComputeTexcoords(SourceTexture, r, @TextureBuffer);
-VertexBuffer[0].X:= X;
-VertexBuffer[0].Y:= Y;
-VertexBuffer[1].X:= rr.w + X;
-VertexBuffer[1].Y:= Y;
-VertexBuffer[2].X:= rr.w + X;
-VertexBuffer[2].Y:= rr.h + Y;
-VertexBuffer[3].X:= X;
-VertexBuffer[3].Y:= rr.h + Y;
+ _l:= X + SourceTexture^.cropInfo.l;
+ _r:= X + rr.w - SourceTexture^.cropInfo.l - SourceTexture^.cropInfo.r;
+ _t:= Y + SourceTexture^.cropInfo.t;
+ _b:= Y + rr.h - SourceTexture^.cropInfo.t - SourceTexture^.cropInfo.b;
+
-TextureBuffer[0].X:= _l;
-TextureBuffer[0].Y:= _t;
-TextureBuffer[1].X:= _r;
-TextureBuffer[1].Y:= _t;
-TextureBuffer[2].X:= _r;
-TextureBuffer[2].Y:= _b;
-TextureBuffer[3].X:= _l;
-TextureBuffer[3].Y:= _b;
+ VertexBuffer[0].X:= _l;
+ VertexBuffer[0].Y:= _t;
+ VertexBuffer[1].X:= _r;
+ VertexBuffer[1].Y:= _t;
+ VertexBuffer[2].X:= _r;
+ VertexBuffer[2].Y:= _b;
+ VertexBuffer[3].X:= _l;
+ VertexBuffer[3].Y:= _b;
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
-glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
+ SetVertexPointer(@VertexBuffer[0]);
+ //SetTexCoordPointer(@TextureBuffer[0]);
+ SetTexCoordPointer(@SourceTexture^.tb[0]);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
end;
procedure DrawTexture(X, Y: LongInt; Texture: PTexture); inline;
@@ -125,18 +184,17 @@
procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
begin
-
-glPushMatrix;
-glTranslatef(X, Y, 0);
-glScalef(Scale, Scale, 1);
+SetOffset(X, Y);
+ResetRotation;
+SetScale(Scale);
+UpdateModelview;
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
-glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb);
-glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
+SetVertexPointer(@Texture^.vb);
+SetTexCoordPointer(@Texture^.tb);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
-
-glPopMatrix
+ResetModelview;
end;
procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
@@ -145,63 +203,68 @@
end;
procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
-var ft, fb, fl, fr: GLfloat;
- hw, nx, ny: LongInt;
+var hw, nx, ny: LongInt;
+ r: TSDL_Rect;
VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
+ _l, _r, _t, _b: GLfloat;
begin
+
+ while (Frame > 0) and (Texture <> nil) do
+ begin
+ Texture:= Texture^.nextFrame;
+ dec(Frame);
+ end;
+
+ if Texture = nil then
+ exit;
+
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then
exit;
if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
exit;
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
if Dir = 0 then Dir:= 1;
-glRotatef(Angle, 0, 0, Dir);
-
-glTranslatef(Dir*OffsetX, OffsetY, 0);
-glScalef(Scale, Scale, 1);
+SetRotation(Angle, Dir);
+AddOffset(Dir*OffsetX, OffsetY);
+AddScale(Scale);
+UpdateModelview;
// Any reason for this call? And why only in t direction, not s?
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
hw:= w div (2 div Dir);
-nx:= round(Texture^.w / w); // number of horizontal frames
-ny:= round(Texture^.h / h); // number of vertical frames
+r.y:=0;
+r.x:=0;
+r.w:=w;
+r.h:=h;
+ComputeTexcoords(Texture, @r, @TextureBuffer);
-ft:= (Frame mod ny) * Texture^.ry / ny;
-fb:= ((Frame mod ny) + 1) * Texture^.ry / ny;
-fl:= (Frame div ny) * Texture^.rx / nx;
-fr:= ((Frame div ny) + 1) * Texture^.rx / nx;
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+_l:= -hw + Texture^.cropInfo.l;
+_t:= w/-2 + Texture^.cropInfo.t;
+_r:= hw - Texture^.cropInfo.l - Texture^.cropInfo.r;
+_b:= w/2 - Texture^.cropInfo.t - Texture^.cropInfo.b;
-VertexBuffer[0].X:= -hw;
-VertexBuffer[0].Y:= w / -2;
-VertexBuffer[1].X:= hw;
-VertexBuffer[1].Y:= w / -2;
-VertexBuffer[2].X:= hw;
-VertexBuffer[2].Y:= w / 2;
-VertexBuffer[3].X:= -hw;
-VertexBuffer[3].Y:= w / 2;
+VertexBuffer[0].X:= _l;
+VertexBuffer[0].Y:= _t;
+VertexBuffer[1].X:= _r;
+VertexBuffer[1].Y:= _t;
+VertexBuffer[2].X:= _r;
+VertexBuffer[2].Y:= _b;
+VertexBuffer[3].X:= _l;
+VertexBuffer[3].Y:= _b;
-TextureBuffer[0].X:= fl;
-TextureBuffer[0].Y:= ft;
-TextureBuffer[1].X:= fr;
-TextureBuffer[1].Y:= ft;
-TextureBuffer[2].X:= fr;
-TextureBuffer[2].Y:= fb;
-TextureBuffer[3].X:= fl;
-TextureBuffer[3].Y:= fb;
-
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+SetVertexPointer(@VertexBuffer[0]);
+//SetTexCoordPointer(@TextureBuffer[0]);
+SetTexCoordPointer(@Texture^.tb[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -214,23 +277,23 @@
procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
begin
-glPushMatrix;
-glTranslatef(X, Y, 0);
-
+SetOffset(X, Y);
if Dir < 0 then
- glRotatef(Angle, 0, 0, -1)
+ SetRotation(Angle, -1.0)
else
- glRotatef(Angle, 0, 0, 1);
+ SetRotation(Angle, 1.0);
if Dir < 0 then
- glScalef(-1.0, 1.0, 1.0);
+ AddScale(-1.0, 1.0);
+UpdateModelview;
DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
-glPopMatrix
+ResetModelview;
end;
procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
var VertexBuffer: array [0..3] of TVertex2f;
+ _l, _r, _t, _b: GLfloat;
begin
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then
@@ -238,55 +301,64 @@
if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
exit;
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
if Dir < 0 then
begin
hw:= - hw;
- glRotatef(Angle, 0, 0, -1);
+ SetRotation(Angle, -1.0);
end
else
- glRotatef(Angle, 0, 0, 1);
+ SetRotation(Angle, 1.0);
+UpdateModelview;
+
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
-
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+_l:= -hw + Texture^.cropInfo.l;
+_t:= -hh + Texture^.cropInfo.t;
+_r:= hw - Texture^.cropInfo.l - Texture^.cropInfo.r;
+_b:= hh - Texture^.cropInfo.t - Texture^.cropInfo.b;
-VertexBuffer[0].X:= -hw;
-VertexBuffer[0].Y:= -hh;
-VertexBuffer[1].X:= hw;
-VertexBuffer[1].Y:= -hh;
-VertexBuffer[2].X:= hw;
-VertexBuffer[2].Y:= hh;
-VertexBuffer[3].X:= -hw;
-VertexBuffer[3].Y:= hh;
+VertexBuffer[0].X:= _l;
+VertexBuffer[0].Y:= _t;
+VertexBuffer[1].X:= _r;
+VertexBuffer[1].Y:= _t;
+VertexBuffer[2].X:= _r;
+VertexBuffer[2].Y:= _b;
+VertexBuffer[3].X:= _l;
+VertexBuffer[3].Y:= _b;
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@Texture^.tb);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
-var row, col, numFramesFirstCol: LongInt;
+var
+ r: TSDL_Rect;
+ tex: PTexture;
begin
if SpritesData[Sprite].imageHeight = 0 then
exit;
- numFramesFirstCol:= SpritesData[Sprite].imageHeight div SpritesData[Sprite].Height;
- row:= Frame mod numFramesFirstCol;
- col:= Frame div numFramesFirstCol;
- DrawSprite(Sprite, X, Y, col, row);
-end;
+
+ tex:= SpritesData[Sprite].Texture;
+
+ while (Frame > 0) and (tex <> nil) do
+ begin
+ tex:= tex^.nextFrame;
+ dec(Frame);
+ end;
-procedure DrawSprite(Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
-var r: TSDL_Rect;
-begin
- r.x:= FrameX * SpritesData[Sprite].Width;
+ if (tex = nil) or (tex^.w = 0) or (tex^.h = 0) then
+ exit;
+
+ r.x:= 0;
r.w:= SpritesData[Sprite].Width;
- r.y:= FrameY * SpritesData[Sprite].Height;
+ r.y:= 0;
r.h:= SpritesData[Sprite].Height;
- DrawTextureFromRect(X, Y, @r, SpritesData[Sprite].Texture)
+ DrawTextureFromRect(X, Y, @r, tex)
end;
procedure DrawSpriteClipped(Sprite: TSprite; X, Y, TopY, RightX, BottomY, LeftX: LongInt);
@@ -329,8 +401,9 @@
glDisable(GL_TEXTURE_2D);
glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
- glTranslatef(WorldDx, WorldDy, 0);
+ ResetRotation;
+ SetOffset(WorldDx, WorldDy);
+ UpdateModelview;
glLineWidth(Width);
Tint(r, g, b, a);
@@ -339,11 +412,11 @@
VertexBuffer[1].X:= X1;
VertexBuffer[1].Y:= Y1;
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
- glPopMatrix;
+ ResetModelview;
glEnable(GL_TEXTURE_2D);
glDisable(GL_LINE_SMOOTH);
@@ -352,6 +425,10 @@
procedure DrawFillRect(r: TSDL_Rect);
var VertexBuffer: array [0..3] of TVertex2f;
begin
+SetOffset(0, 0);
+ResetRotation;
+UpdateModelview;
+
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
exit;
@@ -371,11 +448,13 @@
VertexBuffer[3].X:= r.x;
VertexBuffer[3].Y:= r.y + r.h;
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
-glEnable(GL_TEXTURE_2D)
+glEnable(GL_TEXTURE_2D);
+
+ResetModelview;
end;
procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
@@ -396,23 +475,29 @@
end;
glDisable(GL_TEXTURE_2D);
glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
+ SetOffset(0, 0);
+ ResetRotation;
+ UpdateModelview;
glLineWidth(Width);
- glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]);
+ SetVertexPointer(@CircleVertex[0]);
glDrawArrays(GL_LINE_LOOP, 0, 60);
- glPopMatrix;
glEnable(GL_TEXTURE_2D);
glDisable(GL_LINE_SMOOTH);
+ ResetModelview;
end;
procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
-const VertexBuffer: array [0..3] of TVertex2f = (
- (X: -16; Y: -16),
- (X: 16; Y: -16),
- (X: 16; Y: 16),
- (X: -16; Y: 16));
-var l, r, t, b: real;
+const VertexBuffers: array[0..1] of TVertexRect = (
+ ((x: -16; y: -16),
+ (x: 16; y: -16),
+ (x: 16; y: 16),
+ (x: -16; y: 16)),
+ ((x: 16; y: -16),
+ (x: -16; y: -16),
+ (x: -16; y: 16),
+ (x: 16; y: 16)));
+var r: TSDL_Rect;
TextureBuffer: array [0..3] of TVertex2f;
begin
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
@@ -421,41 +506,25 @@
if (abs(Y) > 32) and ((abs(Y - 0.5 * cScreenHeight) - 16) * cScaleFactor > cScreenHeight) then
exit;
- t:= Pos * 32 / HHTexture^.h;
- b:= (Pos + 1) * 32 / HHTexture^.h;
+ r.x:=Step * 32;
+ r.y:=Pos * 32;
+ r.w:=32;
+ r.h:=32;
+ ComputeTexcoords(HHTexture, @r, @TextureBuffer);
- if Dir = -1 then
- begin
- l:= (Step + 1) * 32 / HHTexture^.w;
- r:= Step * 32 / HHTexture^.w
- end
- else
- begin
- l:= Step * 32 / HHTexture^.w;
- r:= (Step + 1) * 32 / HHTexture^.w
- end;
-
+ SetOffset(X, Y);
+ SetRotation(Angle, 1.0);
+ UpdateModelview;
- glPushMatrix();
- glTranslatef(X, Y, 0);
- glRotatef(Angle, 0, 0, 1);
-
- glBindTexture(GL_TEXTURE_2D, HHTexture^.id);
+ glBindTexture(GL_TEXTURE_2D, HHTexture^.atlas^.id);
+ if Dir = -1 then
+ SetVertexPointer(@VertexBuffers[1][0])
+ else
+ SetVertexPointer(@VertexBuffers[0][0]);
+ SetTexCoordPointer(@TextureBuffer[0]);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- TextureBuffer[0].X:= l;
- TextureBuffer[0].Y:= t;
- TextureBuffer[1].X:= r;
- TextureBuffer[1].Y:= t;
- TextureBuffer[2].X:= r;
- TextureBuffer[2].Y:= b;
- TextureBuffer[3].X:= l;
- TextureBuffer[3].Y:= b;
-
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
- glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
- glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-
- glPopMatrix
+ ResetModelview;
end;
procedure DrawScreenWidget(widget: POnScreenWidget);
@@ -505,31 +574,4 @@
{$ENDIF}
end;
-procedure Tint(r, g, b, a: Byte); inline;
-var nc, tw: Longword;
-begin
- nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
-
- if nc = lastTint then
- exit;
-
- if GrayScale then
- begin
- tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
- if tw > 255 then
- tw:= 255;
- r:= tw;
- g:= tw;
- b:= tw
- end;
-
- glColor4ub(r, g, b, a);
- lastTint:= nc;
-end;
-
-procedure Tint(c: Longword); inline;
-begin
- Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
-end;
-
end.
--- a/hedgewars/uRenderUtils.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uRenderUtils.pas Tue Jul 10 11:09:38 2012 +0200
@@ -272,9 +272,7 @@
TryDo(SDL_SetColorKey(finalSurface, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
- RenderStringTexLim:= Surface2Tex(finalSurface, false);
-
- SDL_FreeSurface(finalSurface);
+ RenderStringTexLim:= Surface2Atlas(finalSurface, false);
end;
@@ -459,10 +457,9 @@
inc(pos);
end;
- RenderSpeechBubbleTex:= Surface2Tex(finalSurface, true);
+ RenderSpeechBubbleTex:= Surface2Atlas(finalSurface, true);
SDL_FreeSurface(rotatedEdge);
- SDL_FreeSurface(finalSurface);
end;
end.
--- a/hedgewars/uScript.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uScript.pas Tue Jul 10 11:09:38 2012 +0200
@@ -750,8 +750,7 @@
DrawRoundRect(@rr, clan^.Color, clan^.Color, texsurf, false);
FreeTexture(team^.HealthTex);
- team^.HealthTex:= Surface2Tex(texsurf, false);
- SDL_FreeSurface(texsurf);
+ team^.HealthTex:= Surface2Atlas(texsurf, false);
MakeCrossHairs
end
end;
--- a/hedgewars/uStore.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uStore.pas Tue Jul 10 11:09:38 2012 +0200
@@ -43,10 +43,23 @@
procedure WarpMouse(x, y: Word); inline;
procedure SwapBuffers; inline;
+procedure UpdateProjection;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+{$ENDIF}
+
+procedure Tint(r, g, b, a: Byte); inline;
+procedure Tint(c: Longword); inline;
+procedure SetTexCoordPointer(p: Pointer);
+procedure SetVertexPointer(p: Pointer);
+procedure SetColorPointer(p: Pointer);
+procedure BeginWater;
+procedure EndWater;
implementation
uses uMisc, uConsole, uMobile, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands,
- uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF};
+ uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}, uMatrix, uAtlas;
//type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
@@ -57,6 +70,27 @@
{$ELSE}
SDLPrimSurface: PSDL_Surface;
{$ENDIF}
+{$IFDEF GL2}
+ shaderMain: GLuint;
+ shaderWater: GLuint;
+
+ // attributes
+const
+ aVertex: GLint = 0;
+ aTexCoord: GLint = 1;
+ aColor: GLint = 2;
+
+var
+ uCurrentMVPLocation: GLint;
+
+ uMainMVPLocation: GLint;
+ uMainTintLocation: GLint;
+
+ uWaterMVPLocation: GLint;
+
+{$ENDIF}
+ LastTint: LongWord = 0;
+
function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
var w, h: LongInt;
@@ -121,8 +155,7 @@
SDL_UnlockSurface(texsurf);
FreeTexture(CrosshairTex);
- CrosshairTex:= Surface2Tex(texsurf, false);
- SDL_FreeSurface(texsurf)
+ CrosshairTex:= Surface2Atlas(texsurf, false);
end;
SDL_FreeSurface(tmpsurf)
@@ -155,8 +188,7 @@
rr:= r;
inc(rr.x, 2); dec(rr.w, 4); inc(rr.y, 2); dec(rr.h, 4);
DrawRoundRect(@rr, Clan^.Color, Clan^.Color, texsurf, false);
- HealthTex:= Surface2Tex(texsurf, false);
- SDL_FreeSurface(texsurf);
+ HealthTex:= Surface2Atlas(texsurf, false);
r.x:= 0;
r.y:= 0;
@@ -196,8 +228,7 @@
PLongwordArray(texsurf^.pixels)^[32 * 16 + 2]:= cNearBlackColor;
PLongwordArray(texsurf^.pixels)^[32 * 16 + 23]:= cNearBlackColor;
- FlagTex:= Surface2Tex(texsurf, false);
- SDL_FreeSurface(texsurf);
+ FlagTex:= Surface2Atlas(texsurf, false);
texsurf:= nil;
AIKillsTex := RenderStringTex(inttostr(stats.AIKills), Clan^.Color, fnt16);
@@ -229,8 +260,7 @@
r.w:= 28;
r.h:= 28;
DrawRoundRect(@r, cWhiteColor, cNearBlackColor, iconsurf, true);
- ropeIconTex:= Surface2Tex(iconsurf, false);
- SDL_FreeSurface(iconsurf);
+ ropeIconTex:= Surface2Atlas(iconsurf, false);
iconsurf:= nil;
end;
end;
@@ -265,8 +295,7 @@
texsurf:= LoadImage(UserPathz[ptGraves] + '/Statue', ifTransparent);
if texsurf = nil then
texsurf:= LoadImage(Pathz[ptGraves] + '/Statue', ifCritical or ifTransparent);
- GraveTex:= Surface2Tex(texsurf, false);
- SDL_FreeSurface(texsurf)
+ GraveTex:= SurfaceSheet2Atlas(texsurf, 32, 32);
end
end;
@@ -277,6 +306,7 @@
ai: TAmmoType;
tmpsurf: PSDL_Surface;
i: LongInt;
+ sw, sh: LongInt;
begin
AddFileLog('StoreLoad()');
@@ -363,12 +393,29 @@
end;
if (ii in [sprSky, sprSkyL, sprSkyR, sprHorizont, sprHorizontL, sprHorizontR]) then
begin
- Texture:= Surface2Tex(tmpsurf, true);
+ Texture:= Surface2Atlas(tmpsurf, true);
Texture^.Scale:= 2
end
else
begin
- Texture:= Surface2Tex(tmpsurf, false);
+ sw:=Trunc(Width*scale);
+ sh:=Trunc(Height*scale);
+ if (sw > imageWidth) or (sh > imageHeight) then
+ begin
+ if not (ii in [sprPHammer, sprBalls, sprSnow]) then
+ begin
+ writeln(stdout, 'Dimension error in ' + FileName + ' [' + IntToStr(Integer(ii)) + ']');
+ halt(-1);
+ end;
+ end;
+
+ if (imageWidth > sw) or (imageHeight > sh) then
+ begin
+ writeln(stdout, 'Animation sheet?: ' + FileName + ' : ' + IntToStr(Round(imageWidth/sw)) + 'x' + IntToStr(Round(imageHeight/sh)));
+ Texture:= SurfaceSheet2Atlas(tmpsurf, Width, Height);
+ end
+ else Texture:= Surface2Atlas(tmpsurf, false);
+
// HACK: We should include some sprite attribute to define the texture wrap directions
if ((ii = sprWater) or (ii = sprSDWater)) and ((cReducedQuality and (rq2DWater or rqClampLess)) = 0) then
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -382,8 +429,8 @@
{$ELSE}
if saveSurf then
Surface:= tmpsurf
- else
- SDL_FreeSurface(tmpsurf)
+ //else
+ // SDL_FreeSurface(tmpsurf) released by FreeTexture
{$ENDIF}
end
end
@@ -398,8 +445,7 @@
if tmpsurf = nil then
tmpsurf:= LoadImage(Pathz[ptGraphics] + '/' + cHHFileName, ifAlpha or ifCritical or ifTransparent);
-HHTexture:= Surface2Tex(tmpsurf, false);
-SDL_FreeSurface(tmpsurf);
+HHTexture:= SurfaceSheet2Atlas(tmpsurf, 32, 32);
InitHealth;
@@ -419,8 +465,7 @@
TryDo(tmpsurf <> nil,'Name-texture creation for ammo type #' + intToStr(ord(ai)) + ' failed!',true);
tmpsurf:= doSurfaceConversion(tmpsurf);
FreeTexture(NameTex);
- NameTex:= Surface2Tex(tmpsurf, false);
- SDL_FreeSurface(tmpsurf)
+ NameTex:= Surface2Atlas(tmpsurf, false);
end;
// number of weapons in ammo menu
@@ -429,8 +474,7 @@
tmpsurf:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(IntToStr(i) + 'x'), cWhiteColorChannels);
tmpsurf:= doSurfaceConversion(tmpsurf);
FreeTexture(CountTexz[i]);
- CountTexz[i]:= Surface2Tex(tmpsurf, false);
- SDL_FreeSurface(tmpsurf)
+ CountTexz[i]:= Surface2Atlas(tmpsurf, false);
end;
if not reload then
@@ -442,16 +486,14 @@
var ii: TSprite;
ai: TAmmoType;
i, t: LongInt;
+ nf: ^PTexture;
begin
for ii:= Low(TSprite) to High(TSprite) do
begin
+ nf:= @SpritesData[ii].Texture;
+ writeln(stdout, 'Releasing ' + IntToStr(Integer(ii)) + ' tex: ' + IntToHex(Integer(nf), 8));
FreeTexture(SpritesData[ii].Texture);
SpritesData[ii].Texture:= nil;
- if (SpritesData[ii].Surface <> nil) and (not reload) then
- begin
- SDL_FreeSurface(SpritesData[ii].Surface);
- SpritesData[ii].Surface:= nil
- end
end;
SDL_FreeSurface(MissionIcons);
@@ -582,10 +624,7 @@
FreeTexture(HHGear^.Hedgehog^.HatTex);
// assign new hat to hedgehog
- HHGear^.Hedgehog^.HatTex:= Surface2Tex(texsurf, true);
-
- // cleanup: free temporary surface mem
- SDL_FreeSurface(texsurf)
+ HHGear^.Hedgehog^.HatTex:= SurfaceSheet2Atlas(texsurf, 32, 32)
end;
end;
@@ -625,6 +664,112 @@
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // try to prefer hardware rendering
end;
+{$IFDEF GL2}
+function CompileShader(shaderFile: string; shaderType: GLenum): GLuint;
+var
+ shader: GLuint;
+ f: Textfile;
+ source, line: AnsiString;
+ sourceA: Pchar;
+ lengthA: GLint;
+ compileResult: GLint;
+ logLength: GLint;
+ log: PChar;
+begin
+ Assign(f, Pathz[ptShaders] + '/' + shaderFile);
+ filemode:= 0; // readonly
+ Reset(f);
+ if IOResult <> 0 then
+ begin
+ AddFileLog('Unable to load ' + shaderFile);
+ halt(-1);
+ end;
+
+ source:='';
+ while not eof(f) do
+ begin
+ ReadLn(f, line);
+ source:= source + line + #10;
+ end;
+
+ CloseFile(f);
+
+ WriteLnToConsole('Compiling shader: ' + Pathz[ptShaders] + '/' + shaderFile);
+
+ sourceA:=PChar(source);
+ lengthA:=Length(source);
+
+ shader:=glCreateShader(shaderType);
+ glShaderSource(shader, 1, @sourceA, @lengthA);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, @compileResult);
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, @logLength);
+
+ if logLength > 1 then
+ begin
+ GetMem(log, logLength);
+ glGetShaderInfoLog(shader, logLength, nil, log);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(log);
+ WriteLnToConsole('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if compileResult <> GL_TRUE then
+ begin
+ WriteLnToConsole('Shader compilation failed, halting');
+ halt(-1);
+ end;
+
+ CompileShader:= shader;
+end;
+
+function CompileProgram(shaderName: string): GLuint;
+var
+ program_: GLuint;
+ vs, fs: GLuint;
+ linkResult: GLint;
+ logLength: GLint;
+ log: PChar;
+begin
+ program_:= glCreateProgram();
+ vs:= CompileShader(shaderName + '.vs', GL_VERTEX_SHADER);
+ fs:= CompileShader(shaderName + '.fs', GL_FRAGMENT_SHADER);
+ glAttachShader(program_, vs);
+ glAttachShader(program_, fs);
+
+ glBindAttribLocation(program_, aVertex, 'vertex');
+ glBindAttribLocation(program_, aTexCoord, 'texcoord');
+ glBindAttribLocation(program_, aColor, 'color');
+
+ glLinkProgram(program_);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ glGetProgramiv(program_, GL_LINK_STATUS, @linkResult);
+ glGetProgramiv(program_, GL_INFO_LOG_LENGTH, @logLength);
+
+ if logLength > 1 then
+ begin
+ GetMem(log, logLength);
+ glGetProgramInfoLog(program_, logLength, nil, log);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(log);
+ WriteLnToConsole('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if linkResult <> GL_TRUE then
+ begin
+ WriteLnToConsole('Linking program failed, halting');
+ halt(-1);
+ end;
+
+ CompileProgram:= program_;
+end;
+
+{$ENDIF}
+
procedure SetupOpenGL;
//var vendor: shortstring = '';
var buf: array[byte] of char;
@@ -682,6 +827,26 @@
AddFileLog(' \----- Extensions: ' + shortstring(pchar(glGetString(GL_EXTENSIONS))));
//TODO: don't have the Extensions line trimmed but slipt it into multiple lines
+{$IFDEF GL2}
+ Load_GL_VERSION_2_0;
+
+ shaderWater:= CompileProgram('water');
+ glUseProgram(shaderWater);
+ glUniform1i(glGetUniformLocation(shaderWater, 'tex0'), 0);
+ uWaterMVPLocation:= glGetUniformLocation(shaderWater, 'mvp');
+
+ shaderMain:= CompileProgram('default');
+ glUseProgram(shaderMain);
+ glUniform1i(glGetUniformLocation(shaderMain, 'tex0'), 0);
+ uMainMVPLocation:= glGetUniformLocation(shaderMain, 'mvp');
+ uMainTintLocation:= glGetUniformLocation(shaderMain, 'tint');
+
+ uCurrentMVPLocation:= uMainMVPLocation;
+
+ Tint(255, 255, 255, 255);
+ UpdateModelviewProjection;
+{$ENDIF}
+
{$IFNDEF S3D_DISABLED}
if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
begin
@@ -729,9 +894,7 @@
glMatrixMode(GL_MODELVIEW);
// prepare default translation/scaling
- glLoadIdentity();
- glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
+ SetScale(2.0);
// enable alpha blending
glEnable(GL_BLEND);
@@ -742,27 +905,144 @@
glDisable(GL_DITHER);
// enable common states by default as they save a lot
glEnable(GL_TEXTURE_2D);
+
+{$IFDEF GL2}
+ glEnableVertexAttribArray(aVertex);
+ glEnableVertexAttribArray(aTexCoord);
+{$ELSE}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+{$ENDIF}
+end;
+
+
+procedure Tint(r, g, b, a: Byte); inline;
+var
+ nc, tw: Longword;
+const
+ scale = 1.0/255.0;
+begin
+ nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
+
+ if nc = lastTint then
+ exit;
+
+ if GrayScale then
+ begin
+ tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
+ if tw > 255 then
+ tw:= 255;
+ r:= tw;
+ g:= tw;
+ b:= tw
+ end;
+
+ {$IFDEF GL2}
+ glUniform4f(uMainTintLocation, r*scale, g*scale, b*scale, a*scale);
+ glColor4ub(r, g, b, a);
+ {$ELSE}
+ glColor4ub(r, g, b, a);
+ {$ENDIF}
+ lastTint:= nc;
+end;
+
+procedure Tint(c: Longword); inline;
+begin
+ Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
+end;
+
+procedure SetTexCoordPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 0, p);
+ {$ELSE}
+ glTexCoordPointer(2, GL_FLOAT, 0, p);
+ {$ENDIF}
+end;
+
+procedure SetVertexPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aVertex, 2, GL_FLOAT, GL_FALSE, 0, p);
+ {$ELSE}
+ glVertexPointer(2, GL_FLOAT, 0, p);
+ {$ENDIF}
+end;
+
+procedure SetColorPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, p);
+ {$ELSE}
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, p);
+ {$ENDIF}
+end;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+var
+ mvp: TMatrix4x4f;
+begin
+ MatrixMultiply(mvp, mProjection, mModelview);
+ glUniformMatrix4fv(uCurrentMVPLocation, 1, GL_FALSE, @mvp[0, 0]);
+end;
+{$ENDIF GL2}
+
+procedure UpdateProjection;
+var
+ s: GLfloat;
+begin
+ s:=cScaleFactor;
+ mProjection[0,0]:= s/cScreenWidth; mProjection[0,1]:= 0.0; mProjection[0,2]:=0.0; mProjection[0,3]:= 0.0;
+ mProjection[1,0]:= 0.0; mProjection[1,1]:= -s/cScreenHeight; mProjection[1,2]:=0.0; mProjection[1,3]:= 0.0;
+ mProjection[2,0]:= 0.0; mProjection[2,1]:= 0.0; mProjection[2,2]:=1.0; mProjection[2,3]:= 0.0;
+ mProjection[3,0]:= cStereoDepth; mProjection[3,1]:= s/2; mProjection[3,2]:=0.0; mProjection[3,3]:= 1.0;
+
+ {$IFDEF GL2}
+ UpdateModelviewProjection;
+ {$ELSE}
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(@mProjection[0, 0]);
+ glMatrixMode(GL_MODELVIEW);
+ {$ENDIF}
end;
procedure SetScale(f: GLfloat);
begin
-// leave immediately if scale factor did not change
- if f = cScaleFactor then
- exit;
+ // This lazy update conflicts with R7103 at the moment, missing the initial SetScale(2.0)
+ //if cScaleFactor <> f then
+ //begin
+ cScaleFactor:=f;
+ UpdateProjection;
+ //end;
+end;
- if f = cDefaultZoomLevel then
- glPopMatrix // "return" to default scaling
- else // other scaling
- begin
- glPushMatrix; // save default scaling
- glLoadIdentity;
- glScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
- end;
+procedure BeginWater;
+begin
+ {$IFDEF GL2}
+ glUseProgram(shaderWater);
+ uCurrentMVPLocation:=uWaterMVPLocation;
+ UpdateModelviewProjection;
+ glDisableVertexAttribArray(aTexCoord);
+ glEnableVertexAttribArray(aColor);
+ {$ELSE}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ {$ENDIF}
+end;
- cScaleFactor:= f;
+procedure EndWater;
+begin
+ {$IFDEF GL2}
+ glUseProgram(shaderMain);
+ uCurrentMVPLocation:=uMainMVPLocation;
+ UpdateModelviewProjection;
+ glDisableVertexAttribArray(aColor);
+ glEnableVertexAttribArray(aTexCoord);
+ {$ELSE}
+ glDisableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ {$ENDIF}
end;
////////////////////////////////////////////////////////////////////////////////
@@ -777,11 +1057,10 @@
if texsurf = nil then
texsurf:= LoadImage(Pathz[ptGraphics] + '/Progress', ifCritical or ifTransparent);
- ProgrTex:= Surface2Tex(texsurf, false);
-
squaresize:= texsurf^.w shr 1;
numsquares:= texsurf^.h div squaresize;
- SDL_FreeSurface(texsurf);
+
+ ProgrTex:= Surface2Atlas(texsurf, false);
uMobile.GameLoading();
end;
@@ -926,8 +1205,7 @@
SDL_FillRect(tmpsurf, @r, $ffffffff);
SDL_UpperBlit(iconsurf, iconrect, tmpsurf, @r);
-RenderHelpWindow:= Surface2Tex(tmpsurf, true);
-SDL_FreeSurface(tmpsurf)
+RenderHelpWindow:= Surface2Atlas(tmpsurf, true);
end;
procedure RenderWeaponTooltip(atype: TAmmoType);
@@ -1033,11 +1311,7 @@
// chFullScr is called when there is a rotation event and needs the SetScale and SetupOpenGL to set up the new resolution
// this 6 gl functions are the relevant ones and are hacked together here for optimisation
glMatrixMode(GL_MODELVIEW);
- glPopMatrix;
- glLoadIdentity();
- glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
- glViewport(0, 0, cScreenWidth, cScreenHeight);
+ SetScale(2.0);
exit;
{$ELSE}
SetScale(cDefaultZoomLevel);
@@ -1151,6 +1425,10 @@
procedure freeModule;
begin
+{$IFDEF GL2}
+ glDeleteProgram(shaderMain);
+ glDeleteProgram(shaderWater);
+{$ENDIF}
StoreRelease(false);
TTF_Quit();
{$IFDEF SDL13}
--- a/hedgewars/uTextures.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uTextures.pas Tue Jul 10 11:09:38 2012 +0200
@@ -24,17 +24,173 @@
function NewTexture(width, height: Longword; buf: Pointer): PTexture;
procedure Surface2GrayScale(surf: PSDL_Surface);
-function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+function SurfaceSheet2Atlas(surf: PSDL_Surface; spriteWidth: Integer; spriteHeight: Integer): PTexture;
+function Surface2Atlas(surf: PSDL_Surface; enableClamp: boolean): PTexture;
procedure FreeTexture(tex: PTexture);
+procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
procedure initModule;
procedure freeModule;
implementation
-uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole;
+uses GLunit, uUtils, uVariables, uConsts, uDebug, uConsole, uAtlas, SysUtils;
+
+var
+ logFile: TextFile;
+
+function CropSurface(source: PSDL_Surface; rect: PSDL_Rect): PSDL_Surface;
+var
+ fmt: PSDL_PixelFormat;
+ srcP, dstP: PByte;
+ copySize: Integer;
+ i: Integer;
+const
+ pixelSize = 4;
+begin
+ //writeln(stdout, 'Cropping from ' + IntToStr(source^.w) + 'x' + IntToStr(source^.h) + ' -> ' + IntToStr(rect^.w) + 'x' + IntToStr(rect^.h));
+
+ fmt:= source^.format;
+
+ CropSurface:= SDL_CreateRGBSurface(source^.flags, rect^.w, rect^.h,
+ fmt^.BitsPerPixel, fmt^.Rmask, fmt^.Gmask, fmt^.Bmask, fmt^.Amask);
+
+ if SDL_MustLock(source) then
+ SDLTry(SDL_LockSurface(source) >= 0, true);
+ if SDL_MustLock(CropSurface) then
+ SDLTry(SDL_LockSurface(CropSurface) >= 0, true);
+
+ srcP:= source^.pixels;
+ dstP:= CropSurface^.pixels;
+
+ inc(srcP, pixelSize * rect^.x);
+ inc(srcP, source^.pitch * rect^.y);
+ copySize:= rect^.w * pixelSize;
+ for i:= 0 to Pred(rect^.h) do
+ begin
+ Move(srcP^, dstP^, copySize);
+ inc(srcP, source^.pitch);
+ inc(dstP, CropSurface^.pitch);
+ end;
+
+ if SDL_MustLock(source) then
+ SDL_UnlockSurface(source);
+ if SDL_MustLock(CropSurface) then
+ SDL_UnlockSurface(CropSurface);
+end;
+
+function TransparentLine(p: PByte; stride: Integer; length: Integer): boolean;
+var
+ i: Integer;
+begin
+ TransparentLine:= false;
+ for i:=0 to pred(length) do
+ begin
+ if p^ <> 0 then
+ exit;
+ inc(p, stride);
+ end;
+ TransparentLine:= true;
+end;
+
+function AutoCrop(source: PSDL_Surface; var cropinfo: TCropInformation): PSDL_Surface;
+var
+ l,r,t,b, i: Integer;
+ pixels, p: PByte;
+ scanlineSize: Integer;
+ rect: TSDL_Rect;
+const
+ pixelSize = 4;
+begin
+ l:= source^.w;
+ r:= 0;
+ t:= source^.h;
+ b:= 0;
+
+ if SDL_MustLock(source) then
+ SDLTry(SDL_LockSurface(source) >= 0, true);
+
+ pixels:= source^.pixels;
+ scanlineSize:= source^.pitch;
-var TextureList: PTexture;
+ inc(pixels, 3); // advance to alpha value
+
+ // check top
+ p:= pixels;
+ for i:= 0 to Pred(source^.h) do
+ begin
+ if not TransparentLine(p, pixelSize, source^.w) then
+ begin
+ t:= i;
+ break;
+ end;
+ inc(p, scanlineSize);
+ end;
+
+
+ // check bottom
+ p:= pixels;
+ inc(p, scanlineSize * source^.h);
+ for i:= 0 to Pred(source^.h - t) do
+ begin
+ dec(p, scanlineSize);
+ if not TransparentLine(p, pixelSize, source^.w) then
+ begin
+ b:= i;
+ break;
+ end;
+ end;
+
+ // check left
+ p:= pixels;
+ for i:= 0 to Pred(source^.w) do
+ begin
+ if not TransparentLine(p, scanlineSize, source^.h) then
+ begin
+ l:= i;
+ break;
+ end;
+ inc(p, pixelSize);
+ end;
+ // check right
+ p:= pixels;
+ inc(p, scanlineSize);
+ for i:= 0 to Pred(source^.w - l) do
+ begin
+ dec(p, pixelSize);
+ if not TransparentLine(p, scanlineSize, source^.h) then
+ begin
+ r:= i;
+ break;
+ end;
+ end;
+
+ if SDL_MustLock(source) then
+ SDL_UnlockSurface(source);
+
+ rect.x:= l;
+ rect.y:= t;
+
+ rect.w:= source^.w - r - l;
+ rect.h:= source^.h - b - t;
+
+ cropInfo.l:= l;
+ cropInfo.r:= r;
+ cropInfo.t:= t;
+ cropInfo.b:= b;
+ cropInfo.x:= Trunc(source^.w / 2 - l + r);
+ cropInfo.y:= Trunc(source^.h / 2 - t + b);
+
+ if (l = source^.w) or (t = source^.h) then
+ begin
+ result:= nil;
+ exit;
+ end;
+
+ if (l <> 0) or (r <> 0) or (t <> 0) or (b <> 0) then
+ result:= CropSurface(source, @rect)
+ else result:= source;
+end;
procedure SetTextureParameters(enableClamp: Boolean);
begin
@@ -47,53 +203,107 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
end;
-procedure ResetVertexArrays(texture: PTexture);
+procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
+var
+ x0, y0, x1, y1, tmp: Real;
+ w, h, aw, ah: LongInt;
+ p: PChar;
+const
+ texelOffset = 0.0;
begin
-with texture^ do
+ aw:=texture^.atlas^.w;
+ ah:=texture^.atlas^.h;
+
+ if texture^.isRotated then
+ begin
+ w:=r^.h;
+ h:=r^.w;
+ end else
+ begin
+ w:=r^.w;
+ h:=r^.h;
+ end;
+
+ x0:= (texture^.x + {r^.x} + texelOffset)/aw;
+ x1:= (texture^.x + {r^.x} + w - texelOffset)/aw;
+ y0:= (texture^.y + {r^.y} + texelOffset)/ah;
+ y1:= (texture^.y + {r^.y} + h - texelOffset)/ah;
+
+ if (texture^.isRotated) then
begin
- vb[0].X:= 0;
- vb[0].Y:= 0;
- vb[1].X:= w;
- vb[1].Y:= 0;
- vb[2].X:= w;
- vb[2].Y:= h;
- vb[3].X:= 0;
- vb[3].Y:= h;
+ tb^[0].X:= x0;
+ tb^[0].Y:= y0;
+ tb^[3].X:= x1;
+ tb^[3].Y:= y0;
+ tb^[2].X:= x1;
+ tb^[2].Y:= y1;
+ tb^[1].X:= x0;
+ tb^[1].Y:= y1
+ end else
+ begin
+ tb^[0].X:= x0;
+ tb^[0].Y:= y0;
+ tb^[1].X:= x1;
+ tb^[1].Y:= y0;
+ tb^[2].X:= x1;
+ tb^[2].Y:= y1;
+ tb^[3].X:= x0;
+ tb^[3].Y:= y1;
+ end;
+end;
- tb[0].X:= 0;
- tb[0].Y:= 0;
- tb[1].X:= rx;
- tb[1].Y:= 0;
- tb[2].X:= rx;
- tb[2].Y:= ry;
- tb[3].X:= 0;
- tb[3].Y:= ry
+procedure ResetVertexArrays(texture: PTexture);
+var r: TSDL_Rect;
+begin
+ with texture^ do
+ begin
+ vb[0].X:= texture^.cropInfo.l;
+ vb[0].Y:= texture^.cropInfo.t;
+ vb[1].X:= texture^.cropInfo.l + w;
+ vb[1].Y:= texture^.cropInfo.t;
+ vb[2].X:= texture^.cropInfo.l + w;
+ vb[2].Y:= texture^.cropInfo.t + h;
+ vb[3].X:= texture^.cropInfo.l;
+ vb[3].Y:= texture^.cropInfo.t + h;
end;
+
+ r.x:= 0;
+ r.y:= 0;
+ r.w:= texture^.w;
+ r.h:= texture^.h;
+ ComputeTexcoords(texture, @r, @texture^.tb);
end;
function NewTexture(width, height: Longword; buf: Pointer): PTexture;
begin
new(NewTexture);
-NewTexture^.PrevTexture:= nil;
-NewTexture^.NextTexture:= nil;
NewTexture^.Scale:= 1;
-if TextureList <> nil then
- begin
- TextureList^.PrevTexture:= NewTexture;
- NewTexture^.NextTexture:= TextureList
- end;
-TextureList:= NewTexture;
-NewTexture^.w:= width;
-NewTexture^.h:= height;
-NewTexture^.rx:= 1.0;
-NewTexture^.ry:= 1.0;
+// Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
+new(NewTexture^.atlas);
+NewTexture^.atlas^.w:=width;
+NewTexture^.atlas^.h:=height;
+NewTexture^.x:=0;
+NewTexture^.y:=0;
+NewTexture^.w:=width;
+NewTexture^.h:=height;
+NewTexture^.isRotated:=false;
+NewTexture^.shared:=false;
+NewTexture^.surface:=nil;
+NewTexture^.nextFrame:=nil;
+NewTexture^.cropInfo.l:= 0;
+NewTexture^.cropInfo.r:= 0;
+NewTexture^.cropInfo.t:= 0;
+NewTexture^.cropInfo.b:= 0;
+NewTexture^.cropInfo.x:= width div 2;
+NewTexture^.cropInfo.y:= height div 2;
+
ResetVertexArrays(NewTexture);
-glGenTextures(1, @NewTexture^.id);
+glGenTextures(1, @NewTexture^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, NewTexture^.id);
+glBindTexture(GL_TEXTURE_2D, NewTexture^.atlas^.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
SetTextureParameters(true);
@@ -121,35 +331,112 @@
end;
-function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+function SurfaceSheet2Atlas(surf: PSDL_Surface; spriteWidth: Integer; spriteHeight: Integer): PTexture;
+var
+ subSurface: PSDL_Surface;
+ framesX, framesY: Integer;
+ last, current: PTexture;
+ r: TSDL_Rect;
+ x, y: Integer;
+begin
+ SurfaceSheet2Atlas:= nil;
+ r.x:= 0;
+ r.y:= 0;
+ r.w:= spriteWidth;
+ r.h:= spriteHeight;
+ last:= nil;
+
+ framesX:= surf^.w div spriteWidth;
+ framesY:= surf^.h div spriteHeight;
+
+ for x:=0 to Pred(framesX) do
+ begin
+ r.y:= 0;
+ for y:=0 to Pred(framesY) do
+ begin
+ subSurface:= CropSurface(surf, @r);
+ current:= Surface2Atlas(subSurface, false);
+
+ if last = nil then
+ begin
+ SurfaceSheet2Atlas:= current;
+ last:= current;
+ end else
+ begin
+ last^.nextFrame:= current;
+ last:= current;
+ end;
+ inc(r.y, spriteHeight);
+ end;
+ inc(r.x, spriteWidth);
+ end;
+
+ SDL_FreeSurface(surf);
+end;
+
+function Surface2Atlas(surf: PSDL_Surface; enableClamp: boolean): PTexture;
var tw, th, x, y: Longword;
tmpp: pointer;
+ cropped: PSDL_Surface;
fromP4, toP4: PLongWordArray;
+ cropInfo: TCropInformation;
begin
-new(Surface2Tex);
-Surface2Tex^.PrevTexture:= nil;
-Surface2Tex^.NextTexture:= nil;
-if TextureList <> nil then
+ cropped:= AutoCrop(surf, cropInfo);
+ if cropped <> surf then
+ begin
+ SDL_FreeSurface(surf);
+ surf:= cropped;
+ end;
+
+ if surf = nil then
begin
- TextureList^.PrevTexture:= Surface2Tex;
- Surface2Tex^.NextTexture:= TextureList
+ new(Surface2Atlas);
+ Surface2Atlas^.w:= 0;
+ Surface2Atlas^.h:= 0;
+ Surface2Atlas^.x:=0 ;
+ Surface2Atlas^.y:=0 ;
+ Surface2Atlas^.isRotated:= false;
+ Surface2Atlas^.surface:= nil;
+ Surface2Atlas^.shared:= false;
+ Surface2Atlas^.nextFrame:= nil;
+ Surface2Atlas^.cropInfo:= cropInfo;
+ exit;
end;
-TextureList:= Surface2Tex;
+
+ if (surf^.w <= 512) and (surf^.h <= 512) then
+ begin
+ Surface2Atlas:= Surface2Tex_(surf, enableClamp); // run the atlas side by side for debugging
+ Surface2Atlas^.cropInfo:= cropInfo;
+ ResetVertexArrays(Surface2Atlas);
+ exit;
+ end;
+new(Surface2Atlas);
-Surface2Tex^.w:= surf^.w;
-Surface2Tex^.h:= surf^.h;
+// Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
+new(Surface2Atlas^.atlas);
+
+Surface2Atlas^.w:= surf^.w;
+Surface2Atlas^.h:= surf^.h;
+Surface2Atlas^.x:=0;
+Surface2Atlas^.y:=0;
+Surface2Atlas^.isRotated:=false;
+Surface2Atlas^.surface:= surf;
+Surface2Atlas^.shared:= false;
+Surface2Atlas^.nextFrame:= nil;
+Surface2Atlas^.cropInfo:= cropInfo;
+
if (surf^.format^.BytesPerPixel <> 4) then
begin
TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
- Surface2Tex^.id:= 0;
- exit
+ Surface2Atlas^.atlas^.id:= 0;
+ exit;
end;
-glGenTextures(1, @Surface2Tex^.id);
+glGenTextures(1, @Surface2Atlas^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
+glBindTexture(GL_TEXTURE_2D, Surface2Atlas^.atlas^.id);
if SDL_MustLock(surf) then
SDLTry(SDL_LockSurface(surf) >= 0, true);
@@ -164,8 +451,8 @@
tw:= toPowerOf2(Surf^.w);
th:= toPowerOf2(Surf^.h);
- Surface2Tex^.rx:= Surf^.w / tw;
- Surface2Tex^.ry:= Surf^.h / th;
+ Surface2Atlas^.atlas^.w:=tw;
+ Surface2Atlas^.atlas^.h:=th;
tmpp:= GetMem(tw * th * surf^.format^.BytesPerPixel);
@@ -195,12 +482,12 @@
end
else
begin
- Surface2Tex^.rx:= 1.0;
- Surface2Tex^.ry:= 1.0;
+ Surface2Atlas^.atlas^.w:=Surf^.w;
+ Surface2Atlas^.atlas^.h:=Surf^.h;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
end;
-ResetVertexArrays(Surface2Tex);
+ResetVertexArrays(Surface2Atlas);
if SDL_MustLock(surf) then
SDL_UnlockSurface(surf);
@@ -212,33 +499,43 @@
// if nil is passed nothing is done
procedure FreeTexture(tex: PTexture);
begin
-if tex <> nil then
+ if tex <> nil then
begin
- if tex^.NextTexture <> nil then
- tex^.NextTexture^.PrevTexture:= tex^.PrevTexture;
- if tex^.PrevTexture <> nil then
- tex^.PrevTexture^.NextTexture:= tex^.NextTexture
- else
- TextureList:= tex^.NextTexture;
- glDeleteTextures(1, @tex^.id);
+ FreeTexture(tex^.nextFrame); // free all frames linked to this animation
+
+ if tex^.surface = nil then
+ begin
+ Dispose(tex);
+ exit;
+ end;
+
+ if tex^.shared then
+ begin
+ SDL_FreeSurface(tex^.surface);
+ FreeTexture_(tex); // run atlas side by side for debugging
+ exit;
+ end;
+
+ // Atlas cleanup happens here later on. For now we just free as each sprite has one atlas
+ glDeleteTextures(1, @tex^.atlas^.id);
+ Dispose(tex^.atlas);
+
+ if (tex^.surface <> nil) then
+ SDL_FreeSurface(tex^.surface);
Dispose(tex);
end
end;
procedure initModule;
begin
-TextureList:= nil;
+assign(logFile, 'out.log');
+rewrite(logFile);
+uAtlas.initModule;
end;
procedure freeModule;
begin
-if TextureList <> nil then
- WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem');
- while TextureList <> nil do
- begin
- AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000)));
- FreeTexture(TextureList);
- end
+close(logFile);
end;
end.
--- a/hedgewars/uTypes.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uTypes.pas Tue Jul 10 11:09:38 2012 +0200
@@ -44,7 +44,8 @@
// Different files are stored in different folders, this enumeration is used to tell which folder to use
TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts,
- ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, ptSuddenDeath, ptButtons);
+ ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, ptSuddenDeath, ptButtons,
+ ptShaders);
// Available sprites for displaying stuff
TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
@@ -199,14 +200,42 @@
X, Y: GLint;
end;
+ TMatrix4x4f = array[0..3, 0..3] of GLfloat;
+
+ PAtlas = ^TAtlas;
PTexture = ^TTexture;
+
+ TAtlas = record
+ id: GLuint;
+ w, h: LongInt;
+ priority: GLfloat;
+ end;
+
+ PVertexRect = ^TVertexRect;
+ TVertexRect = array[0..3] of TVertex2f;
+
+ TCropInformation = record
+ l, r, t, b: Integer; // cropped pixels for each side
+ x, y: Integer; // pivot (center) of the sprite in the cropped image
+ end;
+
TTexture = record
- id: GLuint;
+ atlas: PAtlas;
w, h, scale: LongInt;
- rx, ry: GLfloat;
- priority: GLfloat;
- vb, tb: array [0..3] of TVertex2f;
- PrevTexture, NextTexture: PTexture;
+
+ x, y: LongInt; // Offset in the texture atlas
+ cropInfo: TCropInformation;
+
+ isRotated: boolean; // if true sprite is flipped in the atlas taking w pixels along the y and h pixels along the x axis
+
+ shared: boolean; // true if in an atlas, false if atlas points to a dedicated texture for this sprite
+
+ surface: PSDL_Surface; // retained in memory surface
+
+ // Cached values for texel coordinates and vertex coordinates
+ vb, tb: TVertexRect;
+
+ nextFrame: PTexture;
end;
THogEffect = (heInvulnerable, heResurrectable, hePoisoned, heResurrected, heFrozen);
--- a/hedgewars/uVariables.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uVariables.pas Tue Jul 10 11:09:38 2012 +0200
@@ -21,7 +21,7 @@
unit uVariables;
interface
-uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile;
+uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile, uMatrix;
var
/////// init flags ///////
@@ -225,8 +225,9 @@
'Graphics/Hats', // ptHats
'Graphics/Flags', // ptFlags
'Missions/Maps', // ptMissionMaps
- 'Graphics/SuddenDeath', // ptSuddenDeath
- 'Graphics/Buttons' // ptButton
+ 'Graphics/SuddenDeath', // ptSuddenDeath
+ 'Graphics/Buttons', // ptButton
+ 'Shaders' // ptShaders
);
Fontz: array[THWFont] of THHFont = (
@@ -265,383 +266,384 @@
Texture: PTexture;
Surface: PSDL_Surface;
Width, Height, imageWidth, imageHeight: LongInt;
- saveSurf: boolean;
+ scale: Integer;
+ saveSurf : boolean;
priority: GLfloat;
getDimensions, getImageDimensions: boolean;
end = (
(FileName: 'BlueWater'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprWater
(FileName: 'Clouds'; Path: ptCurrTheme;AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloud
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCloud
(FileName: 'Bomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBomb
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBomb
(FileName: 'BigDigits'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigit
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigDigit
(FileName: 'Frame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 4; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFrame
+ Width: 4; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFrame
(FileName: 'Lag'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 65; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLag
+ Width: 65; Height: 65; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLag
(FileName: 'Arrow'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCursor
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCursor
(FileName:'BazookaShell'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBazookaShell
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBazookaShell
(FileName: 'Targetp'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetP
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetP
(FileName: 'Bee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBee
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBee
(FileName: 'SmokeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeTrace
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeTrace
(FileName: 'RopeHook'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprRopeHook
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprRopeHook
(FileName: 'Expl50'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosion50
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosion50
(FileName: 'MineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOff
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOff
(FileName: 'MineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOn
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineOn
(FileName: 'MineDead'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineDead
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMineDead
(FileName: 'Case'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCase
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprCase
(FileName: 'FirstAid'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprFAid
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprFAid
(FileName: 'dynamite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDynamite
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDynamite
(FileName: 'Power'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprPower
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprPower
(FileName: 'ClBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterBomb
(FileName: 'ClParticle'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterParticle
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprClusterParticle
(FileName: 'Flame'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlame
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlame
(FileName: 'horizont'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
(FileName: 'horizontL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
(FileName: 'horizontR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprHorizont
(FileName: 'Sky'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
(FileName: 'SkyL'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
(FileName: 'SkyR'; Path: ptCurrTheme;AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: true; getImageDimensions: true),// sprSky
(FileName: 'Slot'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlot
(FileName: 'Ammos'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMAmmos
(FileName: 'Ammos_bw'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprAMAmmosBW
(FileName: 'SlotKeys'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMSlotKeys
(FileName: 'Corners'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 2; Height: 2; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMCorners
+ Width: 2; Height: 2; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAMCorners
(FileName: 'Finger'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFinger
+ Width: 32; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprFinger
(FileName: 'AirBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirBomb
(FileName: 'Airplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirplane
+ Width: 256; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAirplane
(FileName: 'amAirplane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmAirplane
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmAirplane
(FileName: 'amGirder'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 160; Height:160; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmGirder
+ Width: 160; Height:160; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmGirder
(FileName: 'hhMask'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHHTelepMask
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHHTelepMask
(FileName: 'Switch'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSwitch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSwitch
(FileName: 'Parachute'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprParachute
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprParachute
(FileName: 'Target'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTarget
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTarget
(FileName: 'RopeNode'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 6; Height: 6; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprRopeNode
+ Width: 6; Height: 6; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprRopeNode
(FileName: 'thinking'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprQuestion
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprQuestion
(FileName: 'PowerBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPowerBar
+ Width: 256; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPowerBar
(FileName: 'WindBar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 151; Height: 17; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindBar
+ Width: 151; Height: 17; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindBar
(FileName: 'WindL'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindL
+ Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindL
(FileName: 'WindR'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindR
+ Width: 80; Height: 13; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWindR
{$IFDEF USE_TOUCH_INTERFACE}
(FileName: 'firebutton'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprFireButton
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprFireButton
(FileName: 'arrowUp'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowUp
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowUp
(FileName: 'arrowDown'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowDown
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowDown
(FileName: 'arrowLeft'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowLeft
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowLeft
(FileName: 'arrowRight'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowRight
+ Width: 100; Height: 100; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprArrowRight
(FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprAMWidget
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprAMWidget
(FileName: 'backjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprJumpWidget
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprJumpWidget
(FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton
+ Width: 120; Height: 100; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprPauseButton
(FileName: 'pause'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image
- Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton
+ Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTimerButton
(FileName: 'forwardjump'; Path: ptButtons; AltPath: ptNone; Texture: nil; Surface: nil;//TODO correct image
- Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton
+ Width: 120; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true), // sprTargetButton
{$ENDIF}
(FileName: 'Flake'; Path:ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFlake
(FileName: 'amRope'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandRope
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandRope
(FileName: 'amBazooka'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBazooka
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBazooka
(FileName: 'amShotgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandShotgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandShotgun
(FileName: 'amDEagle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDEagle
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDEagle
(FileName:'amAirAttack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandAirAttack
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandAirAttack
(FileName: 'amBaseball'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBaseball
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBaseball
(FileName: 'Hammer'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPHammer
+ Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPHammer
(FileName: 'amBTorch_i'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBlowTorch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBlowTorch
(FileName: 'amBTorch_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBlowTorch
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBlowTorch
(FileName: 'Teleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTeleport
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTeleport
(FileName: 'HHDeath'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHHDeath
+ Width: 32; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHHDeath
(FileName:'amShotgun_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprShotgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprShotgun
(FileName: 'amDEagle_w'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDEagle
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDEagle
(FileName: 'Idle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHHIdle
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHHIdle
(FileName: 'Mortar'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMortar
(FileName: 'TurnsLeft'; Path: ptAmmoMenu; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTurnsLeft
(FileName: 'amKamikaze'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprKamikaze
(FileName: 'amWhip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWhip
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWhip
(FileName: 'Kowtow'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprKowtow
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprKowtow
(FileName: 'Sad'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSad
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSad
(FileName: 'Wave'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprWave
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprWave
(FileName: 'Hurrah'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHurrah
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprHurrah
(FileName:'ILoveLemonade';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLemonade
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprLemonade
(FileName: 'Shrug'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShrug
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShrug
(FileName: 'Juggle'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprJuggle
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprJuggle
(FileName: 'ExplPart'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart
(FileName: 'ExplPart2'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart2
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplPart2
(FileName: 'Cake_walk'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeWalk
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeWalk
(FileName: 'Cake_down'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeDown
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCakeDown
(FileName: 'Watermelon'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWatermelon
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprWatermelon
(FileName: 'EvilTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprEvilTrace
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprEvilTrace
(FileName:'HellishBomb'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHellishBomb
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHellishBomb
(FileName: 'Seduction'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSeduction
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSeduction
(FileName: 'HHDress'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprDress
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprDress
(FileName: 'Censored'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprCensored
+ Width: 64; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprCensored
(FileName: 'Drill'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDrill
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprDrill
(FileName: 'amDrill'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDrill
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDrill
(FileName: 'amBallgun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBallgun
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBallgun
(FileName: 'Balls'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBalls
+ Width: 32; Height: 20; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBalls
(FileName: 'RCPlane'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPlane
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPlane
(FileName: 'amRCPlane'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandPlane
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandPlane
(FileName: 'Utility'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprUtility
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprUtility
(FileName:'Invulnerable';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprInvulnerable
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprInvulnerable
(FileName: 'Vampiric'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprVampiric
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprVampiric
(FileName: 'amGirder'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 512; Height:512; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprGirder
+ Width: 512; Height:512; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprGirder
(FileName:'SpeechCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 12; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechCorner
+ Width: 12; Height: 9; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechCorner
(FileName: 'SpeechEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 9; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechEdge
+ Width: 25; Height: 9; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechEdge
(FileName: 'SpeechTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 25; Height: 26; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechTail
+ Width: 25; Height: 26; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprSpeechTail
(FileName:'ThoughtCorner';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 49; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtCorner
+ Width: 49; Height: 37; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtCorner
(FileName:'ThoughtEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 23; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtEdge
+ Width: 23; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtEdge
(FileName:'ThoughtTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 45; Height: 65; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtTail
+ Width: 45; Height: 65; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprThoughtTail
(FileName:'ShoutCorner'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 34; Height: 23; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutCorner
+ Width: 34; Height: 23; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutCorner
(FileName: 'ShoutEdge'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 20; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutEdge
+ Width: 30; Height: 20; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutEdge
(FileName: 'ShoutTail'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 30; Height: 37; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutTail
+ Width: 30; Height: 37; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpLowest; getDimensions: false; getImageDimensions: true),// sprShoutTail
(FileName:'amSniperRifle';Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSniperRifle
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSniperRifle
(FileName: 'Bubbles'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBubbles
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprBubbles
(FileName: 'amJetpack'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprJetpack
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprJetpack
(FileName: 'Health'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHealth
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprHealth
(FileName: 'amMolotov'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),//sprHandMolotov
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),//sprHandMolotov
(FileName: 'Molotov'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMolotov
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprMolotov
(FileName: 'Smoke'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmoke
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmoke
(FileName: 'SmokeWhite'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeWhite
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSmokeWhite
(FileName: 'Shells'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprShell
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: true),// sprShell
(FileName: 'Dust'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDust
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDust
(FileName: 'SnowDust'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSnowDust
+ Width: 22; Height: 22; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSnowDust
(FileName: 'Explosives'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosives
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosives
(FileName: 'ExplosivesRoll'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosivesRoll
+ Width: 48; Height: 48; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprExplosivesRoll
(FileName: 'amTeleport'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmTeleport
+ Width: 64; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprAmTeleport
(FileName: 'Splash'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSplash
+ Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSplash
(FileName: 'Droplet'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDroplet
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprDroplet
(FileName: 'Birdy'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 75; Height: 75; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBirdy
+ Width: 75; Height: 75; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBirdy
(FileName: 'amCake'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCake
(FileName: 'amConstruction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandConstruction
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandConstruction
(FileName: 'amGrenade'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandGrenade
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandGrenade
(FileName: 'amMelon'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMelon
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMelon
(FileName: 'amMortar'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMortar
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMortar
(FileName: 'amSkip'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSkip
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSkip
(FileName: 'amCluster'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCluster
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCluster
(FileName: 'amDynamite'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDynamite
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandDynamite
(FileName: 'amHellish'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandHellish
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandHellish
(FileName: 'amMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMine
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandMine
(FileName: 'amSeduction'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSeduction
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSeduction
(FileName: 'amVamp'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandVamp
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandVamp
(FileName: 'BigExplosion'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 385; Height: 385; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigExplosion
+ Width: 385; Height: 385; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprBigExplosion
(FileName: 'SmokeRing'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 200; Height: 200; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSmokeRing
+ Width: 200; Height: 200; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSmokeRing
(FileName: 'BeeTrace'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprBeeTrace
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprBeeTrace
(FileName: 'Egg'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprEgg
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprEgg
(FileName: 'TargetBee'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetBee
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprTargetBee
(FileName: 'amBee'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBee
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandBee
(FileName: 'Feather'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 15; Height: 25; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFeather
+ Width: 15; Height: 25; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprFeather
(FileName: 'Piano'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPiano
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPiano
(FileName: 'amSineGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSineGun
+ Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSineGun
(FileName: 'amPortalGun'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortalGun
+ Width: 128; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortalGun
(FileName: 'Portal'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortal
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprPortal
(FileName: 'cheese'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCheese
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprCheese
(FileName: 'amCheese'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandCheese
(FileName: 'amFlamethrower'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
+ Width: 128; Height: 128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandFlamethrower
(FileName: 'Chunk'; Path: ptCurrTheme; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprChunk
(FileName: 'Note'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
+ Width: 32; Height: 32; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprNote
(FileName: 'SMineOff'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOff
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOff
(FileName: 'SMineOn'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOn
+ Width: 8; Height: 8; imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSMineOn
(FileName: 'amSMine'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSMine
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSMine
(FileName: 'amHammer'; Path: ptHedgehog; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprHammer
+ Width: 128; Height: 64; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true), // sprHammer
(FileName: 'amResurrector'; Path: ptHedgehog; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
//sprHandResurrector
(FileName: 'Cross'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 108; Height: 138;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
//sprCross
(FileName: 'AirDrill'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprAirDrill
(FileName: 'NapalmBomb'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 16; Height: 16;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; scale: 4; saveSurf: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprNapalmBomb
(FileName: 'BulletHit'; Path: ptGraphics; AltPath: ptNone;
Texture: nil; Surface: nil; Width: 32; Height: 32;
- imageWidth: 0; imageHeight: 0; saveSurf: false; priority:
+ imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority:
tpMedium; getDimensions: false; getImageDimensions: true),
// sprNapalmBomb
(FileName: 'Snowball'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnowball
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnowball
(FileName: 'amSnowball'; Path: ptCurrTheme; AltPath: ptHedgehog; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSnowball
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprHandSnowball
(FileName: 'Snow'; Path: ptCurrTheme; AltPath: ptGraphics; Texture: nil; Surface: nil;
- Width: 4; Height: 4; imageWidth: 0; imageHeight: 0; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnow
+ Width: 4; Height: 4; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: true; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSnow
(FileName: 'SDFlake'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDFlake
+ Width: 64; Height: 64; imageWidth: 0; imageHeight: 0; scale: 2; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDFlake
(FileName: 'SDWater'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprSDWater
+ Width: 0; Height: 0; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: true; getImageDimensions: true),// sprSDWater
(FileName: 'SDClouds'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 256; Height:128; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloud
+ Width: 256; Height:128; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHigh; getDimensions: false; getImageDimensions: true),// sprSDCloud
(FileName: 'SDSplash'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSDSplash
+ Width: 80; Height: 50; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpMedium; getDimensions: false; getImageDimensions: true),// sprSDSplash
(FileName: 'SDDroplet'; Path: ptCurrTheme; AltPath: ptSuddenDeath; Texture: nil; Surface: nil;
- Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDDroplet
+ Width: 16; Height: 16; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprSDDroplet
(FileName: 'TARDIS'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 48; Height: 79; imageWidth: 0; imageHeight: 0; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis
+ Width: 48; Height: 79; imageWidth: 0; imageHeight: 0; scale: 1; saveSurf: false; priority: tpHighest; getDimensions: false; getImageDimensions: true),// sprTardis
(FileName: 'slider'; Path: ptGraphics; AltPath: ptNone; Texture: nil; Surface: nil;
- Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider
+ Width: 3; Height: 17; imageWidth: 3; imageHeight: 17; scale: 1; saveSurf: false; priority: tpLow; getDimensions: false; getImageDimensions: false) // sprSlider
);
const
@@ -2427,6 +2429,7 @@
SyncTexture,
ConfirmTexture: PTexture;
cScaleFactor: GLfloat;
+ cStereoDepth: GLfloat;
SupportNPOTT: Boolean;
Step: LongInt;
squaresize : LongInt;
@@ -2465,6 +2468,9 @@
lastTurnChecksum : Longword;
+ mModelview: TMatrix4x4f;
+ mProjection: TMatrix4x4f;
+
var trammo: array[TAmmoStrId] of ansistring; // name of the weapon
trammoc: array[TAmmoStrId] of ansistring; // caption of the weapon
trammod: array[TAmmoStrId] of ansistring; // description of the weapon
@@ -2613,6 +2619,9 @@
SDWaterOpacity:= $80;
LuaGoals:= '';
+
+ MatrixLoadIdentity(mModelview);
+ MatrixLoadIdentity(mProjection);
end;
procedure freeModule;
--- a/hedgewars/uWorld.pas Mon Jul 09 23:28:02 2012 -0400
+++ b/hedgewars/uWorld.pas Tue Jul 10 11:09:38 2012 +0200
@@ -60,7 +60,8 @@
uCaptions,
uCursor,
uCommands,
- uMobile
+ uMobile,
+ uAtlas
;
var cWaveWidth, cWaveHeight: LongInt;
@@ -77,7 +78,6 @@
amSel: TAmmoType = amNothing;
missionTex: PTexture;
missionTimer: LongInt;
- stereoDepth: GLfloat;
isFirstFrame: boolean;
AMAnimType: LongInt;
@@ -495,8 +495,7 @@
DrawLine2Surf(amSurface, AMRect.w+BORDERSIZE+i, BORDERSIZE, AMRect.w + BORDERSIZE+i, AMRect.h + BORDERSIZE, 160,160,160);//right
end;
-GetAmmoMenuTexture:= Surface2Tex(amSurface, false);
-if amSurface <> nil then SDL_FreeSurface(amSurface);
+GetAmmoMenuTexture:= Surface2Atlas(amSurface, false);
end;
procedure ShowAmmoMenu;
@@ -795,29 +794,30 @@
VertexBuffer[3].X:= -lw;
VertexBuffer[3].Y:= lh;
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
+ BeginWater;
if SuddenDeathDmg then
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, @SDWaterColorArray[0])
+ SetColorPointer(@SDWaterColorArray[0])
else
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WaterColorArray[0]);
+ SetColorPointer(@WaterColorArray[0]);
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
- glDisableClientState(GL_COLOR_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ EndWater;
+ {$IFNDEF GL2}
glColor4ub($FF, $FF, $FF, $FF); // must not be Tint() as color array seems to stay active and color reset is required
+ {$ENDIF}
glEnable(GL_TEXTURE_2D);
end;
end;
procedure DrawWaves(Dir, dX, dY: LongInt; tnt: Byte);
var VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
- lw, waves, shift: GLfloat;
+ lw, waves: GLfloat;
sprite: TSprite;
-begin
+ r: TSDL_Rect;
+begin{
if SuddenDeathDmg then
sprite:= sprSDWater
else
@@ -826,7 +826,6 @@
cWaveWidth:= SpritesData[sprite].Width;
lw:= cScreenWidth / cScaleFactor;
-waves:= lw * 2 / cWaveWidth;
if SuddenDeathDmg then
Tint(LongInt(tnt) * SDWaterColorArray[2].r div 255 + 255 - tnt,
@@ -841,7 +840,7 @@
255
);
-glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
+glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.atlas^.id);
VertexBuffer[0].X:= -lw;
VertexBuffer[0].Y:= cWaterLine + WorldDy + dY;
@@ -852,19 +851,16 @@
VertexBuffer[3].X:= -lw;
VertexBuffer[3].Y:= VertexBuffer[2].Y;
-shift:= - lw / cWaveWidth;
-TextureBuffer[0].X:= shift + (( - WorldDx + LongInt(RealTicks shr 6) * Dir + dX) mod cWaveWidth) / (cWaveWidth - 1);
-TextureBuffer[0].Y:= 0;
-TextureBuffer[1].X:= TextureBuffer[0].X + waves;
-TextureBuffer[1].Y:= TextureBuffer[0].Y;
-TextureBuffer[2].X:= TextureBuffer[1].X;
-TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
-TextureBuffer[3].X:= TextureBuffer[0].X;
-TextureBuffer[3].Y:= TextureBuffer[2].Y;
+// this uses texture repeat mode, when using an atlas rect we need to split to several quads here!
+r.x := -Trunc(lw) + (( - WorldDx + LongInt(RealTicks shr 6) * Dir + dX) mod cWaveWidth);
+r.y:= 0;
+r.w:= Trunc(lw + lw);
+r.h:= SpritesData[sprite].Texture^.h;
+ComputeTexcoords(SpritesData[sprite].Texture, @r, @TextureBuffer);
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
@@ -873,7 +869,7 @@
DrawSprite(sprWater,
i * cWaveWidth + ((WorldDx + (RealTicks shr 6) * Dir + dX) mod cWaveWidth) - (cScreenWidth div 2),
cWaterLine + WorldDy + dY,
- 0)}
+ 0)}}
end;
procedure DrawRepeated(spr, sprL, sprR: TSprite; Shift, OffsetY: LongInt);
@@ -1069,41 +1065,26 @@
else
glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
DrawWorldStereo(Lag, rmRightEye);
- end
+ end;
+{$ELSE}
+ ;
{$ENDIF}
+ DebugAtlas;
end;
procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
begin
-{$IFDEF S3D_DISABLED}
- rm:= rm; d:= d; // avoid hint
- exit;
-{$ELSE}
d:= d / 5;
- if rm = rmDefault then
- exit
- else if rm = rmLeftEye then
+ if rm = rmLeftEye then
d:= -d;
- stereoDepth:= stereoDepth + d;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(d, 0, 0);
- glMatrixMode(GL_MODELVIEW);
-{$ENDIF}
+ cStereoDepth:= cStereoDepth + d;
+ UpdateProjection;
end;
procedure ResetDepth(rm: TRenderMode);
begin
-{$IFDEF S3D_DISABLED}
- rm:= rm; // avoid hint
- exit;
-{$ELSE}
- if rm = rmDefault then
- exit;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(-stereoDepth, 0, 0);
- glMatrixMode(GL_MODELVIEW);
- stereoDepth:= 0;
-{$ENDIF}
+ cStereoDepth:= 0;
+ UpdateProjection;
end;
procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
@@ -1496,8 +1477,7 @@
tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
tmpSurface:= doSurfaceConversion(tmpSurface);
FreeTexture(timeTexture);
- timeTexture:= Surface2Tex(tmpSurface, false);
- SDL_FreeSurface(tmpSurface)
+ timeTexture:= Surface2Atlas(tmpSurface, false);
end;
if timeTexture <> nil then
@@ -1514,8 +1494,7 @@
tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
tmpSurface:= doSurfaceConversion(tmpSurface);
FreeTexture(fpsTexture);
- fpsTexture:= Surface2Tex(tmpSurface, false);
- SDL_FreeSurface(tmpSurface)
+ fpsTexture:= Surface2Atlas(tmpSurface, false);
end;
if fpsTexture <> nil then
DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture);
@@ -1569,7 +1548,7 @@
glDisable(GL_TEXTURE_2D);
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
glEnable(GL_TEXTURE_2D);
@@ -1838,14 +1817,13 @@
missionTimer:= 0;
missionTex:= nil;
cOffsetY:= 0;
- stereoDepth:= 0;
+ cStereoDepth:= 0;
AMState:= AMHidden;
isFirstFrame:= true;
end;
procedure freeModule;
begin
- stereoDepth:= stereoDepth; // avoid hint
FreeTexture(fpsTexture);
fpsTexture:= nil;
FreeTexture(timeTexture);
--- a/share/hedgewars/Data/CMakeLists.txt Mon Jul 09 23:28:02 2012 -0400
+++ b/share/hedgewars/Data/CMakeLists.txt Tue Jul 10 11:09:38 2012 +0200
@@ -1,3 +1,3 @@
-foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts")
+foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts" "Shaders")
add_subdirectory(${dir})
endforeach(dir)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/CMakeLists.txt Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,5 @@
+file(GLOB BaseShaders *.vs *.fs)
+
+install(FILES
+ ${BaseShaders}
+ DESTINATION ${SHAREPATH}Data/Shaders)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/default.fs Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,13 @@
+#version 130
+
+uniform sampler2D tex0;
+uniform vec4 tint;
+
+in vec2 tex;
+
+out vec4 color;
+
+void main()
+{
+ color = texture(tex0, tex) * tint;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/default.vs Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,16 @@
+#version 130
+
+in vec2 vertex;
+in vec2 texcoord;
+in vec4 colors;
+
+out vec2 tex;
+
+uniform mat4 mvp;
+
+void main()
+{
+ vec4 p = mvp * vec4(vertex, 0.0f, 1.0f);
+ gl_Position = p;
+ tex = texcoord;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/water.fs Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,9 @@
+#version 130
+
+in vec4 vcolor;
+out vec4 color;
+
+void main()
+{
+ color = vcolor;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/water.vs Tue Jul 10 11:09:38 2012 +0200
@@ -0,0 +1,14 @@
+#version 130
+
+in vec2 vertex;
+in vec4 color;
+out vec4 vcolor;
+
+uniform mat4 mvp;
+
+void main()
+{
+ vec4 p = mvp * vec4(vertex, 0.0f, 1.0f);
+ gl_Position = p;
+ vcolor = color;
+}