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. |