hedgewars/uStore.pas
changeset 2017 7845c77c8d31
parent 1989 129e8c4fe554
child 2019 b3f1eda8865f
equal deleted inserted replaced
2016:73b0bcc4396d 2017:7845c77c8d31
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
    17  *)
    17  *)
    18 
    18 
    19 unit uStore;
    19 unit uStore;
    20 interface
    20 interface
    21 uses uConsts, uTeams, SDLh,
    21 uses sysutils, uConsts, uTeams, SDLh,
    22 {$IFDEF IPHONE}
    22 {$IFDEF IPHONE}
    23 	gles11,
    23 	gles11,
    24 {$ELSE}
    24 {$ELSE}
    25 	GL,
    25 	GL,
    26 {$ENDIF}
    26 {$ENDIF}
    43 procedure DrawCentered(X, Top: LongInt; Source: PTexture);
    43 procedure DrawCentered(X, Top: LongInt; Source: PTexture);
    44 procedure DrawFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
    44 procedure DrawFromRect(X, Y: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
    45 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    45 procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    46 procedure DrawFillRect(r: TSDL_Rect);
    46 procedure DrawFillRect(r: TSDL_Rect);
    47 function  RenderStringTex(s: string; Color: Longword; font: THWFont): PTexture;
    47 function  RenderStringTex(s: string; Color: Longword; font: THWFont): PTexture;
       
    48 function  RenderSpeechBubbleTex(s: string; SpeechType: Longword; font: THWFont): PTexture;
       
    49 procedure flipSurface(Surface: PSDL_Surface; Vertical: Boolean);
       
    50 //procedure rotateSurface(Surface: PSDL_Surface);
       
    51 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL
       
    52 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: Integer);
    48 procedure RenderHealth(var Hedgehog: THedgehog);
    53 procedure RenderHealth(var Hedgehog: THedgehog);
    49 procedure AddProgress;
    54 procedure AddProgress;
    50 procedure FinishProgress;
    55 procedure FinishProgress;
    51 function  LoadImage(const filename: string; hasAlpha, critical, setTransparent: boolean): PSDL_Surface;
    56 function  LoadImage(const filename: string; hasAlpha, critical, setTransparent: boolean): PSDL_Surface;
    52 procedure SetupOpenGL;
    57 procedure SetupOpenGL;
   670 RenderStringTex:= Surface2Tex(Result);
   675 RenderStringTex:= Surface2Tex(Result);
   671 
   676 
   672 SDL_FreeSurface(Result)
   677 SDL_FreeSurface(Result)
   673 end;
   678 end;
   674 
   679 
       
   680 function RenderSpeechBubbleTex(s: string; SpeechType: Longword; font: THWFont): PTexture;
       
   681 var textWidth, textHeight, x, y, w, h, i, pos, prevpos, line, numLines, edgeWidth, edgeHeight, cornerWidth, cornerHeight: LongInt;
       
   682     Result, tmpsurf, rotatedEdge: PSDL_Surface;
       
   683     rect: TSDL_Rect;
       
   684     chars: TSysCharSet = [#9,' ','.',';',':','?','!',','];
       
   685     substr: shortstring;
       
   686     edge, corner, tail: TSPrite;
       
   687 begin
       
   688 
       
   689 case SpeechType of
       
   690     1: begin; 
       
   691        edge:= sprSpeechEdge; 
       
   692        corner:= sprSpeechCorner;
       
   693        tail:= sprSpeechTail;
       
   694        end;
       
   695     2: begin; 
       
   696        edge:= sprThoughtEdge;
       
   697        corner:= sprThoughtCorner; 
       
   698        tail:= sprThoughtTail;
       
   699        end;
       
   700     3: begin; 
       
   701        edge:= sprShoutEdge;
       
   702        corner:= sprShoutCorner;
       
   703        tail:= sprShoutTail;
       
   704        end;
       
   705     end;
       
   706 edgeHeight:= SpritesData[edge].Height;
       
   707 edgeWidth:= SpritesData[edge].Width;
       
   708 cornerWidth:= SpritesData[corner].Width;
       
   709 cornerHeight:= SpritesData[corner].Height;
       
   710 // This one screws it up
       
   711 s:= 'This is the song that never ends.  ''cause it goes on and on my friends. Some people, started singing it not knowing what it was. And they''ll just go on singing it forever just because... This is the song that never ends...';
       
   712 // This one doesn't
       
   713 //s:= 'This is the song that never ends.  cause it goes on and on my friends. Some people, started singing it not knowing what it was. And theyll just go on singing it forever just because... This is the song that never ends... ';
       
   714 // Also screws up, but only action
       
   715 //s:= 'This is the song that never ends.  cause it goes on and on .';
       
   716 // ok in all
       
   717 // s:= 'This is the song that never ends.  cause it goes on .';
       
   718 numLines:= 1;
       
   719 
       
   720 if length(s) = 0 then s:= '...';
       
   721 
       
   722 TTF_SizeUTF8(Fontz[font].Handle, Str2PChar(s), w, h);
       
   723 textWidth:= w;
       
   724 textHeight:= h;
       
   725 if (length(s) > 20) then
       
   726     begin
       
   727     i:= round(Sqrt(length(s)) * 2);
       
   728     s:= WrapText(s, #1, chars, i);
       
   729     for pos:= 1 to length(s) do
       
   730         if (s[pos] = #1) or (pos = length(s)) then
       
   731             inc(numLines);
       
   732 
       
   733     // TODO - find out why this calc doesn't do what I expect
       
   734     if numLines = 2 then textWidth:= w div 2
       
   735     else if numlines > 2 then textWidth:= w div (numLines-1);
       
   736     end;
       
   737 
       
   738 textWidth:=((textWidth-(cornerWidth-edgeWidth)*2) div edgeWidth)*edgeWidth+edgeWidth;
       
   739 textHeight:=(((numlines * h)-((cornerHeight-edgeWidth)*2)) div edgeWidth)*edgeWidth+edgeWidth;
       
   740 addfilelog(inttostr(textHeight)+'=========== '+inttostr(numlines)+' x '+inttostr(h));
       
   741 //textWidth:=max(textWidth,SpritesData[tail].Width);
       
   742 rect.x:= 0;
       
   743 rect.y:= 0;
       
   744 rect.w:= textWidth + cornerWidth * 2;
       
   745 rect.h:= textHeight + cornerHeight * 2 - edgeHeight + SpritesData[tail].Height;
       
   746 //s:= inttostr(h) + ' ' + inttostr(numlines) + ' ' + inttostr(rect.x) + ' '+inttostr(rect.y) + ' ' + inttostr(rect.w) + ' ' + inttostr(rect.h) + ' ' + s;
       
   747 
       
   748 Result:= SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, 32, RMask, GMask, BMask, AMask);
       
   749 
       
   750 TryDo(Result <> nil, 'RenderString: fail to create surface', true);
       
   751 
       
   752 //////////////////////////////// CORNERS ///////////////////////////////
       
   753 copyToXY(SpritesData[corner].Surface, Result, 0, 0); /////////////////// NW
       
   754 
       
   755 flipSurface(SpritesData[corner].Surface, true); // store all 4 versions in memory to avoid repeated flips?
       
   756 x:= 0;
       
   757 y:= textHeight + cornerHeight -1;
       
   758 copyToXY(SpritesData[corner].Surface, Result, x, y); /////////////////// SW
       
   759 
       
   760 flipSurface(SpritesData[corner].Surface, false);
       
   761 x:= rect.w-cornerWidth-1;
       
   762 y:= textHeight + cornerHeight -1;
       
   763 copyToXY(SpritesData[corner].Surface, Result, x, y); /////////////////// SE
       
   764 
       
   765 flipSurface(SpritesData[corner].Surface, true);
       
   766 x:= rect.w-cornerWidth-1;
       
   767 y:= 0;
       
   768 copyToXY(SpritesData[corner].Surface, Result, x, y); /////////////////// NE
       
   769 flipSurface(SpritesData[corner].Surface, false); // restore original position
       
   770 //////////////////////////////// END CORNERS ///////////////////////////////
       
   771 
       
   772 //////////////////////////////// EDGES //////////////////////////////////////
       
   773 x:= cornerWidth;
       
   774 y:= 0;
       
   775 while x < rect.w-cornerWidth-1 do
       
   776     begin
       
   777     copyToXY(SpritesData[edge].Surface, Result, x, y); ///////////////// top edge
       
   778     inc(x,edgeWidth);
       
   779     end;
       
   780 flipSurface(SpritesData[edge].Surface, true);
       
   781 x:= cornerWidth;
       
   782 y:= textHeight + cornerHeight*2 - edgeHeight-1;
       
   783 while x < rect.w-cornerWidth-1 do
       
   784     begin
       
   785     copyToXY(SpritesData[edge].Surface, Result, x, y); ///////////////// bottom edge
       
   786     inc(x,edgeWidth);
       
   787     end;
       
   788 flipSurface(SpritesData[edge].Surface, true); // restore original position
       
   789 
       
   790 rotatedEdge:= SDL_CreateRGBSurface(SDL_SWSURFACE, edgeHeight, edgeWidth, 32, RMask, GMask, BMask, AMask);
       
   791 x:= rect.w - edgeHeight - 1;
       
   792 y:= cornerHeight;
       
   793 //// initially was going to rotate in place, but the SDL spec claims width/height are read only
       
   794 copyRotatedSurface(SpritesData[edge].Surface,rotatedEdge);
       
   795 while y < textHeight + cornerHeight do
       
   796     begin
       
   797     copyToXY(rotatedEdge, Result, x, y);
       
   798     inc(y,edgeWidth);
       
   799     end;
       
   800 flipSurface(rotatedEdge, false); // restore original position
       
   801 x:= 0;
       
   802 y:= cornerHeight;
       
   803 while y < textHeight + cornerHeight do
       
   804     begin
       
   805     copyToXY(rotatedEdge, Result, x, y);
       
   806     inc(y,edgeWidth);
       
   807     end;
       
   808 //////////////////////////////// END EDGES //////////////////////////////////////
       
   809 
       
   810 x:= cornerWidth;
       
   811 y:= textHeight + cornerHeight * 2 - edgeHeight - 1;
       
   812 copyToXY(SpritesData[tail].Surface, Result, x, y);
       
   813 
       
   814 rect.x:= edgeHeight;
       
   815 rect.y:= edgeHeight;
       
   816 rect.w:= rect.w - edgeHeight * 2;
       
   817 rect.h:= textHeight + cornerHeight * 2 - edgeHeight * 2;
       
   818 SDL_FillRect(Result, @rect, cWhiteColor);
       
   819 
       
   820 pos:= 1; prevpos:= 0; line:= 0;
       
   821 while pos <= length(s) do
       
   822     begin
       
   823     if (s[pos] = #1) or (pos = length(s)) then
       
   824         begin
       
   825         if s[pos] <> #1 then inc(pos);
       
   826         while s[prevpos+1] = ' 'do inc(prevpos);
       
   827         substr:= copy(s, prevpos+1, pos-prevpos-1);
       
   828         if Length(substr) <> 0 then
       
   829            begin
       
   830            tmpsurf:= TTF_RenderUTF8_Blended(Fontz[Font].Handle, Str2PChar(substr), cColorNearBlack);
       
   831            rect.x:= edgeHeight;
       
   832            rect.y:= edgeHeight + line * h;
       
   833            SDLTry(tmpsurf <> nil, true);
       
   834            SDL_UpperBlit(tmpsurf, nil, Result, @rect);
       
   835            SDL_FreeSurface(tmpsurf);
       
   836            inc(line);
       
   837            prevpos:= pos;
       
   838            end;
       
   839         end;
       
   840     inc(pos);
       
   841     end;
       
   842 
       
   843 //TryDo(SDL_SetColorKey(Result, SDL_SRCCOLORKEY, 0) = 0, errmsgTransparentSet, true);
       
   844 RenderSpeechBubbleTex:= Surface2Tex(Result);
       
   845 
       
   846 SDL_FreeSurface(rotatedEdge);
       
   847 SDL_FreeSurface(Result)
       
   848 end;
       
   849 
   675 procedure RenderHealth(var Hedgehog: THedgehog);
   850 procedure RenderHealth(var Hedgehog: THedgehog);
   676 var s: shortstring;
   851 var s: shortstring;
   677 begin
   852 begin
   678 str(Hedgehog.Gear^.Health, s);
   853 str(Hedgehog.Gear^.Health, s);
   679 if Hedgehog.HealthTagTex <> nil then FreeTexture(Hedgehog.HealthTagTex);
   854 if Hedgehog.HealthTagTex <> nil then FreeTexture(Hedgehog.HealthTagTex);
   753 begin
   928 begin
   754 WriteLnToConsole('Freeing progress surface... ');
   929 WriteLnToConsole('Freeing progress surface... ');
   755 FreeTexture(ProgrTex)
   930 FreeTexture(ProgrTex)
   756 end;
   931 end;
   757 
   932 
       
   933 procedure flipSurface(Surface: PSDL_Surface; Vertical: Boolean);
       
   934 var y, x, i, j: LongInt;
       
   935     tmpPixel: Longword;
       
   936     pixels: PLongWordArray;
       
   937 begin
       
   938 TryDo(Surface^.format^.BytesPerPixel = 4, 'flipSurface failed, expecting 32 bit surface', true);
       
   939 pixels:= Surface^.pixels;
       
   940 if Vertical then
       
   941    for y := 0 to (Surface^.h div 2) - 1 do
       
   942        for x := 0 to Surface^.w - 1 do
       
   943            begin
       
   944            i:= y * Surface^.w + x;
       
   945            j:= (Surface^.h - y - 1) * Surface^.w + x;
       
   946            tmpPixel:= pixels^[i];
       
   947            pixels^[i]:= pixels^[j];
       
   948            pixels^[j]:= tmpPixel;
       
   949            end
       
   950 else
       
   951    for x := 0 to (Surface^.w div 2) - 1 do
       
   952        for y := 0 to Surface^.h -1 do
       
   953            begin
       
   954            i:= y*Surface^.w + x;
       
   955            j:= y*Surface^.w + (Surface^.w - x - 1);
       
   956            tmpPixel:= pixels^[i];
       
   957            pixels^[i]:= pixels^[j];
       
   958            pixels^[j]:= tmpPixel;
       
   959            end;
       
   960 end;
       
   961 
       
   962 procedure copyToXY(src, dest: PSDL_Surface; destX, destY: Integer);
       
   963 var srcX, srcY, i, j, maxDest: LongInt;
       
   964     srcPixels, destPixels: PLongWordArray;
       
   965 begin
       
   966 addfilelog('copyToXY: src surf (w, h) = ('+inttostr(src^.w)+', '+inttostr(src^.h)+')');
       
   967 addfilelog('copyToXY: dest(X, Y) = ('+inttostr(destX)+', '+inttostr(destY)+')');
       
   968 maxDest:= (dest^.pitch div 4) * dest^.h;
       
   969 srcPixels:= src^.pixels;
       
   970 destPixels:= dest^.pixels;
       
   971 
       
   972 for srcX:= 0 to src^.w - 1 do
       
   973    for srcY:= 0 to src^.h - 1 do
       
   974       begin
       
   975       i:= (destY + srcY) * (dest^.pitch div 4) + destX + srcX;
       
   976       j:= srcY * (src^.pitch div 4) + srcX;
       
   977       // basic skip of transparent pixels - cleverness would be to do true alpha
       
   978       if (i < maxDest) and ($FF000000 and srcPixels^[j] <> 0) then destPixels^[i]:= srcPixels^[j];
       
   979       end;
       
   980 end;
       
   981 
       
   982 procedure copyRotatedSurface(src, dest: PSDL_Surface); // this is necessary since width/height are read only in SDL, apparently
       
   983 var y, x, i, j: LongInt;
       
   984     srcPixels, destPixels: PLongWordArray;
       
   985 begin
       
   986 TryDo(src^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true);
       
   987 TryDo(dest^.format^.BytesPerPixel = 4, 'rotateSurface failed, expecting 32 bit surface', true);
       
   988 
       
   989 srcPixels:= src^.pixels;
       
   990 destPixels:= dest^.pixels;
       
   991 
       
   992 j:= 0;
       
   993 for x := 0 to src^.w - 1 do
       
   994     for y := 0 to src^.h - 1 do
       
   995         begin
       
   996         i:= (src^.h - 1 - y) * (src^.pitch div 4) + x;
       
   997         destPixels^[j]:= srcPixels^[i];
       
   998         inc(j)
       
   999         end;
       
  1000 end;
       
  1001 
   758 end.
  1002 end.