diff options
-rw-r--r-- | Game/Code/Classes/UCovers.pas | 188 | ||||
-rw-r--r-- | Game/Code/Classes/UGraphic.pas | 4 | ||||
-rw-r--r-- | Game/Code/Classes/UTexture.pas | 141 |
3 files changed, 267 insertions, 66 deletions
diff --git a/Game/Code/Classes/UCovers.pas b/Game/Code/Classes/UCovers.pas index 3bd9e183..7a192e66 100644 --- a/Game/Code/Classes/UCovers.pas +++ b/Game/Code/Classes/UCovers.pas @@ -76,7 +76,7 @@ type TCC_FileIndexHeader = record Indicator: Array [1..4] of Char; //Contains INDE - HighestID: Cardinal; //Highest ID of a Cover + HighestID: Integer; //Highest ID of a Cover end; TCC_FileIndex = record @@ -108,10 +108,10 @@ type IndexNeedRewrite: Boolean; //Index in CacheFile is overwritten by other Data CacheReadOnly: Boolean; //Cache File is read only - Function WriteHeader:Boolean; + Function WriteHeader(const ReWriteCache: Boolean = false):Boolean; Function ReadHeader: Boolean; Function ReadIndex: Boolean; - Function WriteIndex: Boolean; + Function WriteIndex(const ReWriteCache: Boolean = false): Boolean; Function AddTexData(Data: PCC_TextureData): Cardinal; public W: word; @@ -124,11 +124,13 @@ type constructor Create(const Filename: String); procedure Load(const Filename: String); - Function AddCover(FileName: string): Integer; //Returns ID, Checks Cover for Change, Updates Cover if required - function CoverExists(FileName: string): Integer; //Returns ID by FilePath + Function AddCover(FileName: string): Integer; //Returns ID, Checks Cover for Change, Updates Cover if required + function CoverExists(FileName: string): Integer; //Returns ID by FilePath procedure PrepareData(FileName: string); Procedure LoadTextures; Function ReWriteCache: Boolean; //Deletes old cover.cache file and writes new one + + Function GetTexbyID(ID: Cardinal): Integer; end; var @@ -146,7 +148,7 @@ constructor TCovers.Create(const Filename: String); begin HighestID := -1; SetLength(Index, HighestID + 2); - Load(Filename); + //Load(Filename); end; //---------------------------------------------- @@ -189,7 +191,7 @@ end; //-------- // Writes Header(Resets File). Returns True if Writing succeed //-------- -Function TCovers.WriteHeader:Boolean; +Function TCovers.WriteHeader(const ReWriteCache: Boolean):Boolean; var F: File of TCC_FileHeader; begin @@ -198,7 +200,7 @@ begin //Read Header AssignFile(F, Filename); try - If (not FileExists(Filename)) then + If (not FileExists(Filename)) OR (ReWriteCache) then ReWrite(F) else Reset(F); @@ -222,16 +224,16 @@ var I: Integer; Procedure mReadLn(var S: String); - var J: Integer; + var + Len: Integer; begin S := ''; - J := 0; - Repeat - Inc(J); - SetLength(S, J); - Read(F, Byte(S[J])); - Until S[J] = #10 + BlockRead(F, Len, 4); //Read Len of Filename String + + //Read Filename String + SetLength(S, Len); + BlockRead(F, S[1], Len); end; begin try @@ -245,21 +247,22 @@ begin If (IndexHeader.Indicator = cCC_IndexIndicator) then begin - Result := False; - + Log.LogError('TCovers: loading Cover Index Header. HighestID: ' + InttoStr(IndexHeader.HighestID)); HighestID := IndexHeader.HighestID; SetLength(Index, HighestID + 2); Count := 0; Result := True; - If (HighestID > 0) then + If (HighestID >= 0) then begin //Read File Infos until (Eof or Footer) I := 0; - While (Not Eof(F)) AND ((I <= 0) OR (Index[I].FileIndex.DataStart <> High(Cardinal))) do - begin - If (I > HighestID) then + //While (Not Eof(F)) AND ((I <= 0) OR (Index[I-1].FileIndex.DataStart <> High(Cardinal))) do + Repeat + Log.LogError('TCovers: loading Cover Index. Position #' + InttoStr(I)); + If (I > HighestID + 1) then begin //Header IndexCOunt was wrong, running out of array + Log.LogError('TCovers: Wrong HighestID in Index Header. Running out of Array at Postion #' + InttoStr(I)); Inc(HighestID); IndexNeedReWrite := True; SetLength(Index, HighestID + 2); @@ -268,15 +271,24 @@ begin BlockRead(F, Index[I].FileIndex, SizeOf(TCC_FileIndex)); Index[I].TexID := -1; - If (Index[I].FileIndex.DataStart <> High(Cardinal)) AND (Not Eof(F)) then + If (Index[I].FileIndex.DataStart = High(Cardinal)) then + begin //Found Footer + Log.LogError('TCovers: Found footer at Position #' + InttoStr(I)); + Break; + end; + + If (Not Eof(F)) then begin //Read Filename mReadLn(Index[I].Filename); - Inc(Count); + + Log.LogError('TCovers: Cover loaded: ' + Index[I].Filename); + If (Index[I].FileIndex.DataStart <> 0) AND (Index[I].FileIndex.DataStart <> 1) then + Inc(Count); end; Inc(I); - end; + Until Eof(F); If (Index[HighestID + 1].FileIndex.DataStart = High(Cardinal)) then begin //No Footer found @@ -297,21 +309,24 @@ end; //-------- // Writes Index. Returns True if Writing succeed //-------- -Function TCovers.WriteIndex: Boolean; +Function TCovers.WriteIndex(const ReWriteCache: Boolean): Boolean; var F: File of Byte; IndexHeader: TCC_FileIndexHeader; I: Integer; Procedure mWriteLn(var S: String); - var N: Byte; + var Len: Integer; begin - BlockWrite(F, S, Length(S)); - N := Byte(#10); - Write(F, N); + //Write Length of String + Len := Length(S); + BlockWrite(F, Len, 4); + + //Write String + BlockWrite(F, S[1], Len); end; begin - Result := WriteHeader; + Result := WriteHeader(ReWriteCache); If (Result) then begin @@ -338,9 +353,12 @@ begin For I := 0 to HighestID+1 do begin BlockWrite(F, Index[I].FileIndex, SizeOf(TCC_FileIndex)); - mWriteLn(Index[I].Filename); + If (I <= HighestID) then + mWriteLn(Index[I].Filename); end; + IndexNeedRewrite := False; + finally CloseFile(F); end; @@ -363,7 +381,7 @@ begin Reset(F); Seek(F, Header.DataStart + Header.DataLength); - BlockWrite(F, Data, SizeOf(TCC_TextureData)); + BlockWrite(F, Data^, SizeOf(TCC_TextureData)); Result := Header.DataStart + Header.DataLength; Inc(Header.DataLength, SizeOf(TCC_TextureData)); @@ -382,6 +400,8 @@ procedure TCovers.Load(const Filename: String); var Succeed: Boolean; begin + Log.LogError('TCovers: Load cache from file: ''' + Filename + ''''); + Self.Filename := Filename; Succeed := False; If (FileExists(Filename)) then @@ -398,7 +418,10 @@ begin If not Succeed and not CacheReadOnly then If not (ReWriteCache) then + begin CacheReadOnly := True; + Log.LogError('TCovers: Cache readonly!'); + end; end; Function TCovers.AddCover(FileName: string): Integer; @@ -407,11 +430,13 @@ begin Result := CoverExists(Filename); If (Result = -1) then begin //Add Cover(Does not exist) + Log.LogError('TCovers: Adding cover: ''' + Filename + ''''); If (Count <= HighestID) then begin //There is an empty slot, Search It + Log.LogError('TCovers: Searching for Empty Slot'); For I := 0 to HighestID do If (Index[I].FileIndex.DataStart = 0) then - begin //Found the Slot + begin //Found that Slot Result := I; Break; end; @@ -419,6 +444,7 @@ begin If (Result = -1) then begin //Attach it to the End + Log.LogError('TCovers: Attach Cover to the end'); Inc(HighestID); SetLength(Index, HighestID + 2); Result := HighestID; @@ -427,6 +453,7 @@ begin Index[Result].Filename := Filename; Index[Result].TexID := -1; Index[Result].FileIndex.DataStart := 1; + Log.LogError('TCovers: Cover Added, ID: ' + InttoStr(Result)); end else begin //Check if File has Changed @@ -476,6 +503,8 @@ Function TCovers.ReWriteCache: Boolean; begin If not CacheReadOnly then begin + Log.LogError('TCovers: Rewriting Cache'); + Header.FileTyp := cCC_HeaderText; Header.Version := cCC_HeaderVersion; Header.Hash := MakeHash; @@ -485,7 +514,10 @@ begin Header.DataLength := 0; Header.IndexStart := Header.DataStart + Header.DataLength + 4; - Result := WriteIndex; + HighestID := -1; + SetLength(Index, HighestID + 2); + + Result := WriteIndex(True); end else Result := False; @@ -514,20 +546,100 @@ end; Procedure TCovers.LoadTextures; var I: Integer; - + TexData: PCC_TextureData; + CachedData: TCC_TextureData; + F: File of Byte; + Function LoadCover: Integer; begin + Result := -1; + + If (Index[I].FileIndex.DataStart = 1) then + begin //This Texture is new and has to be loaded + TexData := Texture.GetCoverThumbnail(Index[I].Filename); + If (TexData <> nil) then + begin + If not (CacheReadonly) then + begin //Save this Tex to Cache + Index[I].FileIndex.DataStart := AddTexData(TexData); + If (Index[I].FileIndex.DataStart = 0) then + begin + CacheReadOnly := True; //Failed to write Data + Log.LogError('Failed to Write TextureData to Cache'); + end; + end; + //Create Texture + glGenTextures(1, @Result); + + glBindTexture(GL_TEXTURE_2D, Result); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + //glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, Data); + glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, TexData); + end + else + Log.LogError('Couldn''t get Thumbnail Data'); + end + Else If (Index[I].FileIndex.DataStart > 1) then + begin //This texture is already in Cache, Load it from there + try + Log.LogError('TCovers: Loading Cover #' + InttoStr(I) + ' from Cache at Position: ' + InttoStr(Index[I].FileIndex.DataStart)); + Assign(F, Filename); + try + Reset(F); + Seek(F, Index[I].FileIndex.DataStart); + BlockRead(F, CachedData, SizeOf(TCC_TextureData)); + finally + CloseFile(F); + end; + + + //Create Texture + glGenTextures(1, @Result); + + if (Result > 0) then + begin + + glBindTexture(GL_TEXTURE_2D, Result); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + //glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, Data); + glTexImage2D(GL_TEXTURE_2D, 0, 3, cCC_CoverW, cCC_CoverH, 0, GL_RGB, GL_UNSIGNED_BYTE, @CachedData[0]); + end + else + Log.LogError('TCovers: Error Generating Texture'); + except + Log.LogError('TCovers: Error during loading'); + end; + end; end; begin - //Texture.SetCoverSize(cCC_CoverW, cCC_CoverH); + Texture.SetCoverSize(cCC_CoverW, cCC_CoverH); + Log.LogError('TCovers: LoadingTextures'); For I := 0 to HighestID do begin //Load all the Covers - {Index[I].TexID + If (Index[I].FileIndex.DataStart > 0) then + Index[I].TexID := LoadCover; //No empty SLot -> Load the Texture - Index[I].FileIndex.} + Log.LogError('TCovers: Texture for ID#' + InttoStr(I) + ': ' + InttoStr(Index[I].TexID)); end; + + If IndexNeedRewrite then + WriteIndex; +end; + +Function TCovers.GetTexbyID(ID: Cardinal): Integer; +begin + If (ID <= HighestID) then + Result := Index[ID].TexID + else + Result := -1; end; end. diff --git a/Game/Code/Classes/UGraphic.pas b/Game/Code/Classes/UGraphic.pas index afb986e1..90772ca8 100644 --- a/Game/Code/Classes/UGraphic.pas +++ b/Game/Code/Classes/UGraphic.pas @@ -253,6 +253,7 @@ uses UMain, UIni, UDisplay, UCommandLine, + UCovers, {$IFNDEF FPC} Graphics, {$ENDIF} @@ -538,7 +539,8 @@ begin // the mainthread have to know somehow what opengl function have to be called with which parameters like // texturetype, textureobjekt, textur-buffer-adress, ... - + //Load Covers from Cache and new added/ Updated Covers + Covers.LoadTextures; // wait for loading thread to finish // funktioniert so auch noch nicht - currently dos not work this way diff --git a/Game/Code/Classes/UTexture.pas b/Game/Code/Classes/UTexture.pas index 35757a8e..712c54bf 100644 --- a/Game/Code/Classes/UTexture.pas +++ b/Game/Code/Classes/UTexture.pas @@ -81,6 +81,11 @@ type TTextureUnit = class private + TnWidth, TnHeight: Cardinal; //Width and Height of the Cover Thumbnails + + TnBuffer: array of byte; + TnSurface: PSDL_Surface; + function LoadImage(const Identifier: string): PSDL_Surface; function pixfmt_eq(fmt1,fmt2: PSDL_Pixelformat): boolean; procedure AdjustPixelFormat(var TexSurface: PSDL_Surface; Typ: TTextureType); @@ -88,7 +93,6 @@ type procedure ScaleTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); procedure FitTexture(var TexSurface: PSDL_Surface; W,H: Cardinal); procedure ColorizeTexture(TexSurface: PSDL_Surface; Col: Cardinal); - public Limit: integer; CreateCacheMipmap: boolean; @@ -106,6 +110,9 @@ type procedure UnloadTexture(const Name: string; Typ: TTextureType; Col: Cardinal; FromCache: boolean); overload; //procedure FlushTextureDatabase(); + Function GetCoverThumbnail(const Name: string): Pointer; + Procedure SetCoverSize(W, H: Integer); + Constructor Create; Destructor Destroy; override; @@ -119,15 +126,10 @@ var Mipmapping: Boolean; - CacheMipmap: array[0..256*256*3-1] of byte; // 3KB - CacheMipmapSurface: PSDL_Surface; - - implementation uses ULog, DateUtils, - UCovers, UThemes, {$ifdef LINUX} fileutil, @@ -521,7 +523,7 @@ begin Log.LogStatus( 'ERROR Could not load texture' , Identifier +' '+ TextureTypeToStr(Typ) ); Exit; end; - + // convert pixel format as needed {$ifdef blindydebug} Log.LogStatus('',' AdjustPixelFormat'); @@ -536,7 +538,7 @@ begin if (newWidth > Limit) then newWidth := Limit; - + if (newHeight > Limit) then newHeight := Limit; @@ -560,36 +562,36 @@ begin // don't actually understand, if this is needed... // this should definately be changed... together with all this // cover cache stuff - if (CreateCacheMipmap) and (Typ = TEXTURE_TYPE_PLAIN) then + {if (CreateCacheMipmap) and (Typ = TEXTURE_TYPE_PLAIN) then begin - {$ifdef blindydebug} + {$ifdef blindydebug}{ Log.LogStatus('',' JB-1 : Minimap'); {$endif} - if (Covers.W <= 256) and (Covers.H <= 256) then + {if (TnWidth <= 256) and (TnHeight <= 256) then begin - {$ifdef blindydebug} + {$ifdef blindydebug}{ Log.LogStatus('',' GetScaledTexture('''+inttostr(Covers.W)+''','''+inttostr(Covers.H)+''') (for CacheMipmap)'); - {$endif} - MipmapSurface:=GetScaledTexture(TexSurface, Covers.W, Covers.H); + {$endif}{ + MipmapSurface:=GetScaledTexture(TexSurface, TnWidth, TnHeight); if assigned(MipmapSurface) then begin - {$ifdef blindydebug} + {$ifdef blindydebug}{ Log.LogStatus('',' ok'); Log.LogStatus('',' BlitSurface Stuff'); - {$endif} + {$endif}{ // creating and freeing the surface could be done once, if Cover.W and Cover.H don't change - CacheMipmapSurface:=SDL_CreateRGBSurfaceFrom(@CacheMipmap[0], Covers.W, Covers.H, 24, Covers.W*3, $000000ff, $0000ff00, $00ff0000, 0); - SDL_BlitSurface(MipMapSurface, nil, CacheMipmapSurface, nil); - SDL_FreeSurface(CacheMipmapSurface); - {$ifdef blindydebug} + TnSurface:=SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); + SDL_BlitSurface(TnSurface, nil, TnSurface, nil); + SDL_FreeSurface(TnSurface); + {$ifdef blindydebug}{ Log.LogStatus('',' ok'); Log.LogStatus('',' SDL_FreeSurface (CacheMipmap)'); - {$endif} - SDL_FreeSurface(MipmapSurface); - {$ifdef blindydebug} + {$endif}{ + SDL_FreeSurface(TnSurface); + {$ifdef blindydebug}{ Log.LogStatus('',' ok'); - {$endif} + {$endif}{ end else begin @@ -597,7 +599,7 @@ begin end; end; // should i create a cache texture, if Covers.W/H are larger? - end; + end; } {$ifdef blindydebug} Log.LogStatus('',' JB-2'); @@ -744,7 +746,7 @@ begin end; // use preloaded texture - if (not FromCache) or (FromCache and (Covers.CoverExists(Name) < 0)) then + if (not FromCache) or (FromCache{ and (Covers.CoverExists(Name) < 0)}) then begin // use full texture if TextureDatabase.Texture[T].Texture.TexNum = -1 then @@ -763,7 +765,7 @@ begin Result := TextureDatabase.Texture[T].Texture; end; - if FromCache and (Covers.CoverExists(Name) >= 0) then + {if FromCache and (Covers.CoverExists(Name) >= 0) then begin // use cache texture C := Covers.CoverExists(Name); @@ -777,6 +779,91 @@ begin // use texture Result := TextureDatabase.Texture[T].TextureCache; + end;} +end; + +//-------- +// Returns Pointer to an Array of Byte containing the Texture Data in the +// requested Size +//-------- +Function TTextureUnit.GetCoverThumbnail(const Name: string): Pointer; +var + TexSurface: PSDL_Surface; + newHeight, newWidth: Cardinal; +const + Typ = TEXTURE_TYPE_PLAIN; +begin + Result := nil; + If (FileExists(Name)) then + begin + {$ifdef blindydebug} + Log.LogStatus('',' ----------------------------------------------------'); + Log.LogStatus('',' GetCoverThumbnail('''+Name+''')'); + {$endif} + TexSurface := LoadImage(Name); + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + if assigned(TexSurface) then + begin + // convert pixel format as needed + {$ifdef blindydebug} + Log.LogStatus('',' AdjustPixelFormat'); + {$endif} + AdjustPixelFormat(TexSurface, Typ); + + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + + // Scale Texture to Covers Dimensions + {$ifdef blindydebug} + Log.LogStatus('',' ScaleTexture('''+inttostr(tnWidth)+''','''+inttostr(TnHeight)+''') (for CacheMipmap)'); + {$endif} + ScaleTexture(TexSurface, TnWidth, TnHeight); + + if assigned(TexSurface) AND assigned(TnSurface) then + begin + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + Log.LogStatus('',' BlitSurface Stuff'); + {$endif} + + SDL_BlitSurface(TexSurface, nil, TnSurface, nil); + + Result := @TnBuffer[0]; + + {$ifdef blindydebug} + Log.LogStatus('',' ok'); + {$endif} + end + else + Log.LogStatus(' Error creating Cover Thumbnail',' LoadTexture('''+Name+''')'); + end + else + Log.LogStatus( 'ERROR Could not load texture for Cover Thumbnail: ' , name+' '+ TextureTypeToStr(Typ) ); + + SDL_FreeSurface(TexSurface); + end; +end; + +//-------- +// Sets Textures Thumbnail Size Vars and Sets LEngth of DataBuffer and Create CoverSurface +//-------- +Procedure TTextureUnit.SetCoverSize(W, H: Integer); +begin + If (H > 0) AND (W > 0) then + begin + TnWidth := W; + TnHeight := H; + + SetLength(TnBuffer, TnWidth * TnHeight * 3); + + //Free if necesary and Create new Surface at Data + If (Assigned(TnSurface)) then + SDL_FreeSurface(TnSurface); + + TnSurface := SDL_CreateRGBSurfaceFrom(@TnBuffer[0], TnWidth, TnHeight, 24, TnWidth*3, $000000ff, $0000ff00, $00ff0000, 0); end; end; |