5b760c29274b77e5fe6fe2e397b045a4d54b3f20
6 SysUtils
, Math
, e_log
, e_textures
, SDL2
, GL
, GLExt
, MAPDEF
;
9 TMirrorType
=(M_NONE
, M_HORIZONTAL
, M_VERTICAL
);
10 TBlending
=(B_NONE
, B_BLEND
, B_FILTER
, B_INVERT
);
16 TPoint
= MAPDEF
.TPoint
; // TODO: create an utiltypes.pas or something
17 // for other types like rect as well
24 Left
, Top
, Right
, Bottom
: Integer;
42 //------------------------------------------------------------------
44 //------------------------------------------------------------------
46 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
47 procedure e_ResizeWindow(Width
, Height
: Integer);
49 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
50 Blending
: Boolean; Mirror
: TMirrorType
= M_NONE
);
51 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
52 Blending
: Boolean; Angle
: Single; RC
: PPoint
; Mirror
: TMirrorType
= M_NONE
);
53 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
54 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
55 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
56 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
57 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
58 AlphaChannel
: Boolean; Blending
: Boolean);
59 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
60 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
61 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
62 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
63 Blending
: TBlending
= B_NONE
);
65 function e_CreateTexture(FileName
: string; var ID
: DWORD
): Boolean;
66 function e_CreateTextureEx(FileName
: string; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
67 function e_CreateTextureMem(pData
: Pointer; var ID
: DWORD
): Boolean;
68 function e_CreateTextureMemEx(pData
: Pointer; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
69 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
70 function e_GetTextureSize2(ID
: DWORD
): TRectWH
;
71 procedure e_DeleteTexture(ID
: DWORD
);
72 procedure e_RemoveAllTextures();
75 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
76 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
77 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
78 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
79 Color
: TRGB
; Scale
: Single = 1.0);
80 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
81 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
82 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
83 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
84 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
85 procedure e_CharFont_Remove(FontID
: DWORD
);
86 procedure e_CharFont_RemoveAll();
89 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
91 procedure e_TextureFontKill(FontID
: DWORD
);
92 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
93 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
94 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
95 procedure e_TextureFontPrintFmt(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Shadow
: Boolean = False);
96 procedure e_TextureFontGetSize(ID
: DWORD
; var CharWidth
, CharHeight
: Byte);
97 procedure e_RemoveAllTextureFont();
99 procedure e_ReleaseEngine();
100 procedure e_BeginRender();
101 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
102 procedure e_Clear(); overload
;
103 procedure e_EndRender();
105 function e_GetGamma(win
: PSDL_Window
): Byte;
106 procedure e_SetGamma(win
: PSDL_Window
;Gamma
: Byte);
108 procedure e_MakeScreenshot(FileName
: string; Width
, Height
: Word);
110 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
111 function _Point(X
, Y
: Integer): TPoint2i
;
112 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
113 function _TRect(L
, T
, R
, B
: LongInt): TRect
;
118 e_NoGraphics
: Boolean = False;
131 TTextureFont
= record
141 Chars
: array[0..255] of
151 TSavedTexture
= record
158 e_Textures
: array of TTexture
= nil;
159 e_TextureFonts
: array of TTextureFont
= nil;
160 e_CharFonts
: array of TCharFont
;
161 //e_SavedTextures: array of TSavedTexture;
163 //------------------------------------------------------------------
164 // Èíèöèàëèçèðóåò OpenGL
165 //------------------------------------------------------------------
166 procedure e_InitGL();
170 e_DummyTextures
:= True;
176 glDisable(GL_DEPTH_TEST
);
177 glEnable(GL_SCISSOR_TEST
);
178 glClearColor(0, 0, 0, 0);
181 procedure e_SetViewPort(X
, Y
, Width
, Height
: Word);
183 mat
: Array [0..15] of GLDouble
;
186 if e_NoGraphics
then Exit
;
188 glScissor(X
, Y
, Width
, Height
);
189 glViewport(X
, Y
, Width
, Height
);
190 //gluOrtho2D(0, Width, Height, 0);
192 glMatrixMode(GL_PROJECTION
);
194 mat
[ 0] := 2.0 / Width
;
200 mat
[ 5] := -2.0 / Height
;
214 glLoadMatrixd(@mat
[0]);
216 glMatrixMode(GL_MODELVIEW
);
220 //------------------------------------------------------------------
221 // Èùåò ñâîáîäíûé ýëåìåíò â ìàññèâå òåêñòóð
222 //------------------------------------------------------------------
223 function FindTexture(): DWORD
;
227 if e_Textures
<> nil then
228 for i
:= 0 to High(e_Textures
) do
229 if e_Textures
[i
].Width
= 0 then
235 if e_Textures
= nil then
237 SetLength(e_Textures
, 32);
242 Result
:= High(e_Textures
) + 1;
243 SetLength(e_Textures
, Length(e_Textures
) + 32);
247 //------------------------------------------------------------------
249 //------------------------------------------------------------------
250 function e_CreateTexture(FileName
: String; var ID
: DWORD
): Boolean;
257 e_WriteLog('Loading texture from '+FileName
, MSG_NOTIFY
);
259 find_id
:= FindTexture();
261 if not LoadTexture(FileName
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].Width
,
262 e_Textures
[find_id
].Height
, @fmt
) then Exit
;
265 e_Textures
[ID
].Fmt
:= fmt
;
270 function e_CreateTextureEx(FileName
: String; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
277 find_id
:= FindTexture();
279 if not LoadTextureEx(FileName
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
281 e_Textures
[find_id
].Width
:= fWidth
;
282 e_Textures
[find_id
].Height
:= fHeight
;
283 e_Textures
[find_id
].Fmt
:= fmt
;
290 function e_CreateTextureMem(pData
: Pointer; var ID
: DWORD
): Boolean;
297 find_id
:= FindTexture
;
299 if not LoadTextureMem(pData
, e_Textures
[find_id
].tx
, e_Textures
[find_id
].Width
,
300 e_Textures
[find_id
].Height
, @fmt
) then exit
;
303 e_Textures
[id
].Fmt
:= fmt
;
308 function e_CreateTextureMemEx(pData
: Pointer; var ID
: DWORD
; fX
, fY
, fWidth
, fHeight
: Word): Boolean;
315 find_id
:= FindTexture();
317 if not LoadTextureMemEx(pData
, e_Textures
[find_id
].tx
, fX
, fY
, fWidth
, fHeight
, @fmt
) then exit
;
319 e_Textures
[find_id
].Width
:= fWidth
;
320 e_Textures
[find_id
].Height
:= fHeight
;
321 e_Textures
[find_id
].Fmt
:= fmt
;
328 procedure e_GetTextureSize(ID
: DWORD
; Width
, Height
: PWord);
330 if Width
<> nil then Width
^ := e_Textures
[ID
].Width
;
331 if Height
<> nil then Height
^ := e_Textures
[ID
].Height
;
334 function e_GetTextureSize2(ID
: DWORD
): TRectWH
;
342 w
:= e_Textures
[ID
].Width
;
343 h
:= e_Textures
[ID
].Height
;
350 if e_NoGraphics
then Exit
;
352 data
:= GetMemory(w
*h
*4);
353 glEnable(GL_TEXTURE_2D
);
354 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
355 glGetTexImage(GL_TEXTURE_2D
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, data
);
357 for y
:= h
-1 downto 0 do
364 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
370 Result
.Y
:= h
-lastline
;
382 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
388 Result
.Height
:= h
-lastline
-Result
.Y
;
400 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
406 Result
.X
:= lastline
+1;
411 for x
:= w
-1 downto 0 do
418 a
:= Byte((data
+y
*w
*4+x
*4+3)^) <> 0;
424 Result
.Width
:= lastline
-Result
.X
+1;
432 procedure e_ResizeWindow(Width
, Height
: Integer);
436 e_SetViewPort(0, 0, Width
, Height
);
439 procedure e_Draw(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
440 Blending
: Boolean; Mirror
: TMirrorType
= M_NONE
);
444 if e_NoGraphics
then Exit
;
445 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
447 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
452 if (AlphaChannel
) or (Alpha
> 0) then
453 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
456 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
459 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
461 glEnable(GL_TEXTURE_2D
);
462 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
465 u
:= e_Textures
[ID
].tx
.u
;
466 v
:= e_Textures
[ID
].tx
.v
;
468 if Mirror
= M_NONE
then
470 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
471 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
472 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
473 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
476 if Mirror
= M_HORIZONTAL
then
478 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
479 glTexCoord2f(0, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
480 glTexCoord2f(0, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
481 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
484 if Mirror
= M_VERTICAL
then
486 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
487 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
488 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
489 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
497 procedure e_DrawSize(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
498 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
502 if e_NoGraphics
then Exit
;
503 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
505 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
510 if (AlphaChannel
) or (Alpha
> 0) then
511 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
514 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
517 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
519 glEnable(GL_TEXTURE_2D
);
520 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
522 u
:= e_Textures
[ID
].tx
.u
;
523 v
:= e_Textures
[ID
].tx
.v
;
526 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
527 glTexCoord2f(u
, v
); glVertex2i(X
+ Width
, Y
);
528 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
529 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
535 procedure e_DrawSizeMirror(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
536 Blending
: Boolean; Width
, Height
: Word; Mirror
: TMirrorType
= M_NONE
);
540 if e_NoGraphics
then Exit
;
541 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
543 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
548 if (AlphaChannel
) or (Alpha
> 0) then
549 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
552 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
555 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
557 glEnable(GL_TEXTURE_2D
);
558 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
561 u
:= e_Textures
[ID
].tx
.u
;
562 v
:= e_Textures
[ID
].tx
.v
;
564 if Mirror
= M_NONE
then
566 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
);
567 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
568 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ Height
);
569 glTexCoord2f(u
, -v
); glVertex2i(X
+ Width
, Y
+ Height
);
572 if Mirror
= M_HORIZONTAL
then
574 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
575 glTexCoord2f(0, 0); glVertex2i(X
+ Width
, Y
);
576 glTexCoord2f(0, -v
); glVertex2i(X
+ Width
, Y
+ Height
);
577 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ Height
);
580 if Mirror
= M_VERTICAL
then
582 glTexCoord2f(u
, -v
); glVertex2i(X
+ Width
, Y
);
583 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
584 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ Height
);
585 glTexCoord2f(u
, 0); glVertex2i(X
+ Width
, Y
+ Height
);
593 procedure e_DrawFill(ID
: DWORD
; X
, Y
: Integer; XCount
, YCount
: Word; Alpha
: Integer;
594 AlphaChannel
: Boolean; Blending
: Boolean);
596 X2
, Y2
, dx
, w
, h
: Integer;
599 if e_NoGraphics
then Exit
;
600 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
602 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
607 if (AlphaChannel
) or (Alpha
> 0) then
608 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
611 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
614 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
622 glEnable(GL_TEXTURE_2D
);
623 glBindTexture(GL_TEXTURE_2D
, e_Textures
[ID
].tx
.id
);
625 X2
:= X
+ e_Textures
[ID
].Width
* XCount
;
626 Y2
:= Y
+ e_Textures
[ID
].Height
* YCount
;
628 //k8: this SHOULD work... i hope
629 if (e_Textures
[ID
].tx
.width
= e_Textures
[ID
].tx
.glwidth
) and (e_Textures
[ID
].tx
.height
= e_Textures
[ID
].tx
.glheight
) then
632 glTexCoord2i(0, YCount
); glVertex2i(X
, Y
);
633 glTexCoord2i(XCount
, YCount
); glVertex2i(X2
, Y
);
634 glTexCoord2i(XCount
, 0); glVertex2i(X2
, Y2
);
635 glTexCoord2i(0, 0); glVertex2i(X
, Y2
);
642 u
:= e_Textures
[ID
].tx
.u
;
643 v
:= e_Textures
[ID
].tx
.v
;
644 w
:= e_Textures
[ID
].tx
.width
;
645 h
:= e_Textures
[ID
].tx
.height
;
652 glTexCoord2f(0, v
); glVertex2i(X
, Y
);
653 glTexCoord2f(u
, v
); glVertex2i(X
+w
, Y
);
654 glTexCoord2f(u
, 0); glVertex2i(X
+w
, Y
+h
);
655 glTexCoord2f(0, 0); glVertex2i(X
, Y
+h
);
669 procedure e_DrawAdv(ID
: DWORD
; X
, Y
: Integer; Alpha
: Byte; AlphaChannel
: Boolean;
670 Blending
: Boolean; Angle
: Single; RC
: PPoint
; Mirror
: TMirrorType
= M_NONE
);
674 if e_NoGraphics
then Exit
;
675 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
677 if (Alpha
> 0) or (AlphaChannel
) or (Blending
) then
682 if (AlphaChannel
) or (Alpha
> 0) then
683 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
686 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255-Alpha
);
689 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
);
691 if (Angle
<> 0) and (RC
<> nil) then
694 glTranslatef(X
+RC
.X
, Y
+RC
.Y
, 0);
695 glRotatef(Angle
, 0, 0, 1);
696 glTranslatef(-(X
+RC
.X
), -(Y
+RC
.Y
), 0);
699 glEnable(GL_TEXTURE_2D
);
700 glBindTexture(GL_TEXTURE_2D
, e_Textures
[id
].tx
.id
);
701 glBegin(GL_QUADS
); //0-1 1-1
704 u
:= e_Textures
[ID
].tx
.u
;
705 v
:= e_Textures
[ID
].tx
.v
;
707 if Mirror
= M_NONE
then
709 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
710 glTexCoord2f(0, 0); glVertex2i(X
, Y
);
711 glTexCoord2f(0, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
712 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
715 if Mirror
= M_HORIZONTAL
then
717 glTexCoord2f(u
, 0); glVertex2i(X
, Y
);
718 glTexCoord2f(0, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
719 glTexCoord2f(0, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
720 glTexCoord2f(u
, -v
); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
723 if Mirror
= M_VERTICAL
then
725 glTexCoord2f(u
, -v
); glVertex2i(X
+ e_Textures
[id
].Width
, Y
);
726 glTexCoord2f(0, -v
); glVertex2i(X
, Y
);
727 glTexCoord2f(0, 0); glVertex2i(X
, Y
+ e_Textures
[id
].Height
);
728 glTexCoord2f(u
, 0); glVertex2i(X
+ e_Textures
[id
].Width
, Y
+ e_Textures
[id
].Height
);
739 procedure e_DrawPoint(Size
: Byte; X
, Y
: Integer; Red
, Green
, Blue
: Byte);
741 if e_NoGraphics
then Exit
;
742 glDisable(GL_TEXTURE_2D
);
743 glColor3ub(Red
, Green
, Blue
);
746 if (Size
= 2) or (Size
= 4) then
750 glVertex2f(X
+0.3, Y
+1.0);
753 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
756 procedure e_LineCorrection(var X1
, Y1
, X2
, Y2
: Integer);
758 // Make lines only top-left/bottom-right and top-right/bottom-left
770 // Pixel-perfect hack
778 procedure e_DrawQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
780 nX1
, nY1
, nX2
, nY2
: Integer;
782 if e_NoGraphics
then Exit
;
783 // Only top-left/bottom-right quad
800 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
804 glDisable(GL_TEXTURE_2D
);
805 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
809 nX1
:= X1
; nY1
:= Y1
;
810 nX2
:= X2
; nY2
:= Y1
;
811 e_LineCorrection(nX1
, nY1
, nX2
, nY2
); // Pixel-perfect lines
812 glVertex2i(nX1
, nY1
);
813 glVertex2i(nX2
, nY2
);
815 nX1
:= X2
; nY1
:= Y1
;
816 nX2
:= X2
; nY2
:= Y2
;
817 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
818 glVertex2i(nX1
, nY1
);
819 glVertex2i(nX2
, nY2
);
821 nX1
:= X2
; nY1
:= Y2
;
822 nX2
:= X1
; nY2
:= Y2
;
823 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
824 glVertex2i(nX1
, nY1
);
825 glVertex2i(nX2
, nY2
);
827 nX1
:= X1
; nY1
:= Y2
;
828 nX2
:= X1
; nY2
:= Y1
;
829 e_LineCorrection(nX1
, nY1
, nX2
, nY2
);
830 glVertex2i(nX1
, nY1
);
831 glVertex2i(nX2
, nY2
);
834 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
839 procedure e_DrawFillQuad(X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
, Alpha
: Byte;
840 Blending
: TBlending
= B_NONE
);
842 if e_NoGraphics
then Exit
;
843 if (Alpha
> 0) or (Blending
<> B_NONE
) then
848 if Blending
= B_BLEND
then
849 glBlendFunc(GL_SRC_ALPHA
, GL_ONE
)
851 if Blending
= B_FILTER
then
852 glBlendFunc(GL_DST_COLOR
, GL_SRC_COLOR
)
854 if Blending
= B_INVERT
then
855 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
)
858 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
860 glDisable(GL_TEXTURE_2D
);
861 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
873 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
878 procedure e_DrawLine(Width
: Byte; X1
, Y1
, X2
, Y2
: Integer; Red
, Green
, Blue
: Byte; Alpha
: Byte = 0);
880 if e_NoGraphics
then Exit
;
881 // Pixel-perfect lines
883 e_LineCorrection(X1
, Y1
, X2
, Y2
);
888 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
892 glDisable(GL_TEXTURE_2D
);
893 glColor4ub(Red
, Green
, Blue
, 255-Alpha
);
901 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
906 //------------------------------------------------------------------
907 // Óäàëÿåò òåêñòóðó èç ìàññèâà
908 //------------------------------------------------------------------
909 procedure e_DeleteTexture(ID
: DWORD
);
911 if not e_NoGraphics
then
912 glDeleteTextures(1, @e_Textures
[ID
].tx
.id
);
913 e_Textures
[ID
].tx
.id
:= 0;
914 e_Textures
[ID
].Width
:= 0;
915 e_Textures
[ID
].Height
:= 0;
918 //------------------------------------------------------------------
919 // Óäàëÿåò âñå òåêñòóðû
920 //------------------------------------------------------------------
921 procedure e_RemoveAllTextures();
925 if e_Textures
= nil then Exit
;
927 for i
:= 0 to High(e_Textures
) do
928 if e_Textures
[i
].Width
<> 0 then e_DeleteTexture(i
);
932 //------------------------------------------------------------------
934 //------------------------------------------------------------------
935 procedure e_ReleaseEngine();
938 e_RemoveAllTextureFont
;
941 procedure e_BeginRender();
943 if e_NoGraphics
then Exit
;
944 glEnable(GL_ALPHA_TEST
);
945 glAlphaFunc(GL_GREATER
, 0.0);
948 procedure e_Clear(Mask
: TGLbitfield
; Red
, Green
, Blue
: Single); overload
;
950 if e_NoGraphics
then Exit
;
951 glClearColor(Red
, Green
, Blue
, 0);
955 procedure e_Clear(); overload
;
957 if e_NoGraphics
then Exit
;
958 glClearColor(0, 0, 0, 0);
959 glClear(GL_COLOR_BUFFER_BIT
);
962 procedure e_EndRender();
964 if e_NoGraphics
then Exit
;
968 procedure e_MakeScreenshot(FileName
: String; Width
, Height
: Word);
970 if e_NoGraphics
then Exit
;
974 aRGB = Array [0..1] of TRGB;
977 TByteArray = Array [0..1] of Byte;
978 PByteArray = ^TByteArray;
981 FILEHEADER: BITMAPFILEHEADER;
982 INFOHEADER: BITMAPINFOHEADER;
989 if (Width mod 4) > 0 then
990 Width := Width + 4 - (Width mod 4);
992 GetMem(pixels, Width*Height*3);
993 glReadPixels(0, 0, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
995 for i := 0 to Width * Height - 1 do
996 with PaRGB(pixels)[i] do
1005 bfType := $4D42; // "BM"
1006 bfSize := Width*Height*3 + SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER);
1009 bfOffBits := SizeOf(BITMAPFILEHEADER) + SizeOf(BITMAPINFOHEADER);
1014 biSize := SizeOf(BITMAPINFOHEADER);
1020 biSizeImage := Width*Height*3;
1021 biXPelsPerMeter := 0;
1022 biYPelsPerMeter := 0;
1024 biClrImportant := 0;
1027 AssignFile(F, FileName);
1030 BlockWrite(F, FILEHEADER, SizeOf(FILEHEADER));
1031 BlockWrite(F, INFOHEADER, SizeOf(INFOHEADER));
1032 BlockWrite(F, pixels[0], Width*Height*3);
1039 function e_GetGamma(win
: PSDL_Window
): Byte;
1041 ramp
: array [0..256*3-1] of Word;
1042 rgb
: array [0..2] of Double;
1051 if e_NoGraphics
then Exit
;
1056 SDL_GetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1065 for j
:= min
to max
- 1 do
1068 B
:= (j
mod 256)/256;
1070 sum
:= sum
+ ln(A
)/ln(B
);
1073 rgb
[i
] := sum
/ count
;
1076 Result
:= 100 - Trunc(((rgb
[0] + rgb
[1] + rgb
[2])/3 - 0.23) * 100/(2.7 - 0.23));
1079 procedure e_SetGamma(win
: PSDL_Window
; Gamma
: Byte);
1081 ramp
: array [0..256*3-1] of Word;
1086 if e_NoGraphics
then Exit
;
1087 g
:= (100 - Gamma
)*(2.7 - 0.23)/100 + 0.23;
1089 for i
:= 0 to 255 do
1091 r
:= Exp(g
* ln(i
/256))*65536;
1092 if r
< 0 then r
:= 0
1093 else if r
> 65535 then r
:= 65535;
1094 ramp
[i
] := trunc(r
);
1095 ramp
[i
+ 256] := trunc(r
);
1096 ramp
[i
+ 512] := trunc(r
);
1099 SDL_SetWindowGammaRamp(win
, @ramp
[0], @ramp
[256], @ramp
[512]);
1102 function e_CharFont_Create(sp
: ShortInt=0): DWORD
;
1106 e_WriteLog('Creating CharFont...', MSG_NOTIFY
);
1110 if e_CharFonts
<> nil then
1111 for i
:= 0 to High(e_CharFonts
) do
1112 if not e_CharFonts
[i
].Live
then
1118 if id
= DWORD(-1) then
1120 SetLength(e_CharFonts
, Length(e_CharFonts
) + 1);
1121 id
:= High(e_CharFonts
);
1124 with e_CharFonts
[id
] do
1126 for i
:= 0 to High(Chars
) do
1140 procedure e_CharFont_AddChar(FontID
: DWORD
; Texture
: Integer; c
: Char; w
: Byte);
1142 with e_CharFonts
[FontID
].Chars
[Ord(c
)] do
1144 TextureID
:= Texture
;
1149 procedure e_CharFont_Print(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1153 if e_NoGraphics
then Exit
;
1154 if Text = '' then Exit
;
1155 if e_CharFonts
= nil then Exit
;
1156 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1158 with e_CharFonts
[FontID
] do
1160 for a
:= 1 to Length(Text) do
1161 with Chars
[Ord(Text[a
])] do
1162 if TextureID
<> -1 then
1164 e_Draw(TextureID
, X
, Y
, 0, True, False);
1165 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1170 procedure e_CharFont_PrintEx(FontID
: DWORD
; X
, Y
: Integer; Text: string;
1171 Color
: TRGB
; Scale
: Single = 1.0);
1176 if e_NoGraphics
then Exit
;
1177 if Text = '' then Exit
;
1178 if e_CharFonts
= nil then Exit
;
1179 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1181 with e_CharFonts
[FontID
] do
1183 for a
:= 1 to Length(Text) do
1184 with Chars
[Ord(Text[a
])] do
1185 if TextureID
<> -1 then
1187 if Scale
<> 1.0 then
1190 glScalef(Scale
, Scale
, 0);
1195 e_Draw(TextureID
, X
, Y
, 0, True, False);
1198 if Scale
<> 1.0 then glPopMatrix
;
1200 X
:= X
+Width
+IfThen(a
= Length(Text), 0, Space
);
1205 procedure e_CharFont_PrintFmt(FontID
: DWORD
; X
, Y
: Integer; Text: string);
1207 a
, TX
, TY
, len
: Integer;
1211 if e_NoGraphics
then Exit
;
1212 if Text = '' then Exit
;
1213 if e_CharFonts
= nil then Exit
;
1214 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1222 len
:= Length(Text);
1224 e_CharFont_GetSize(FontID
, 'A', w
, h
);
1226 with e_CharFonts
[FontID
] do
1228 for a
:= 1 to len
do
1239 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1244 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1249 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1254 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1259 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1264 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1269 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1274 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1279 with Chars
[Ord(Text[a
])] do
1280 if TextureID
<> -1 then
1284 e_Draw(TextureID
, TX
, TY
, 0, True, False);
1287 TX
:= TX
+Width
+IfThen(a
= Length(Text), 0, Space
);
1293 procedure e_CharFont_GetSize(FontID
: DWORD
; Text: string; var w
, h
: Word);
1301 if Text = '' then Exit
;
1302 if e_CharFonts
= nil then Exit
;
1303 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1305 with e_CharFonts
[FontID
] do
1307 for a
:= 1 to Length(Text) do
1308 with Chars
[Ord(Text[a
])] do
1309 if TextureID
<> -1 then
1311 w
:= w
+Width
+IfThen(a
= Length(Text), 0, Space
);
1312 e_GetTextureSize(TextureID
, nil, @h2
);
1313 if h2
> h
then h
:= h2
;
1318 procedure e_CharFont_GetSizeFmt(FontID
: DWORD
; Text: string; var w
, h
: Word);
1320 a
, lines
, len
: Integer;
1327 if Text = '' then Exit
;
1328 if e_CharFonts
= nil then Exit
;
1329 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1332 len
:= Length(Text);
1334 with e_CharFonts
[FontID
] do
1336 for a
:= 1 to len
do
1338 if Text[a
] = #10 then
1348 else if Text[a
] in [#1, #2, #3, #4, #18, #19, #20, #21] then
1351 with Chars
[Ord(Text[a
])] do
1352 if TextureID
<> -1 then
1354 w2
:= w2
+ Width
+ IfThen(a
= len
, 0, Space
);
1355 e_GetTextureSize(TextureID
, nil, @h2
);
1356 if h2
> h
then h
:= h2
;
1366 function e_CharFont_GetMaxWidth(FontID
: DWORD
): Word;
1372 if e_CharFonts
= nil then Exit
;
1373 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1375 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1376 Result
:= Max(Result
, e_CharFonts
[FontID
].Chars
[a
].Width
);
1379 function e_CharFont_GetMaxHeight(FontID
: DWORD
): Word;
1386 if e_CharFonts
= nil then Exit
;
1387 if Integer(FontID
) > High(e_CharFonts
) then Exit
;
1389 for a
:= 0 to High(e_CharFonts
[FontID
].Chars
) do
1391 if e_CharFonts
[FontID
].Chars
[a
].TextureID
<> -1 then
1392 e_GetTextureSize(e_CharFonts
[FontID
].Chars
[a
].TextureID
, nil, @h2
)
1394 if h2
> Result
then Result
:= h2
;
1398 procedure e_CharFont_Remove(FontID
: DWORD
);
1402 with e_CharFonts
[FontID
] do
1403 for a
:= 0 to High(Chars
) do
1404 if Chars
[a
].TextureID
<> -1 then e_DeleteTexture(Chars
[a
].TextureID
);
1406 e_CharFonts
[FontID
].Live
:= False;
1409 procedure e_CharFont_RemoveAll();
1413 if e_CharFonts
= nil then Exit
;
1415 for a
:= 0 to High(e_CharFonts
) do
1416 e_CharFont_Remove(a
);
1421 procedure e_TextureFontBuild(Tex
: DWORD
; var FontID
: DWORD
; XCount
, YCount
: Word;
1428 if e_NoGraphics
then Exit
;
1429 e_WriteLog('Creating texture font...', MSG_NOTIFY
);
1433 if e_TextureFonts
<> nil then
1434 for i
:= 0 to High(e_TextureFonts
) do
1435 if e_TextureFonts
[i
].Base
= 0 then
1441 if id
= DWORD(-1) then
1443 SetLength(e_TextureFonts
, Length(e_TextureFonts
) + 1);
1444 id
:= High(e_TextureFonts
);
1447 with e_TextureFonts
[id
] do
1449 Base
:= glGenLists(XCount
*YCount
);
1450 TextureID
:= e_Textures
[Tex
].tx
.id
;
1451 CharWidth
:= (e_Textures
[Tex
].Width
div XCount
)+Space
;
1452 CharHeight
:= e_Textures
[Tex
].Height
div YCount
;
1459 glBindTexture(GL_TEXTURE_2D
, e_Textures
[Tex
].tx
.id
);
1460 for loop1
:= 0 to XCount
*YCount
-1 do
1462 cx
:= (loop1
mod XCount
)/XCount
;
1463 cy
:= (loop1
div YCount
)/YCount
;
1465 glNewList(e_TextureFonts
[id
].Base
+loop1
, GL_COMPILE
);
1467 glTexCoord2f(cx
, 1.0-cy
-1/YCount
);
1468 glVertex2d(0, e_Textures
[Tex
].Height
div YCount
);
1470 glTexCoord2f(cx
+1/XCount
, 1.0-cy
-1/YCount
);
1471 glVertex2i(e_Textures
[Tex
].Width
div XCount
, e_Textures
[Tex
].Height
div YCount
);
1473 glTexCoord2f(cx
+1/XCount
, 1.0-cy
);
1474 glVertex2i(e_Textures
[Tex
].Width
div XCount
, 0);
1476 glTexCoord2f(cx
, 1.0-cy
);
1479 glTranslated((e_Textures
[Tex
].Width
div XCount
)+Space
, 0, 0);
1486 procedure e_TextureFontKill(FontID
: DWORD
);
1488 if e_NoGraphics
then Exit
;
1489 glDeleteLists(e_TextureFonts
[FontID
].Base
, 256);
1490 e_TextureFonts
[FontID
].Base
:= 0;
1493 procedure e_TextureFontPrint(X
, Y
: GLint
; Text: string; FontID
: DWORD
);
1495 if e_NoGraphics
then Exit
;
1496 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1497 if Text = '' then Exit
;
1499 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1502 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1505 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1506 glEnable(GL_TEXTURE_2D
);
1507 glTranslated(x
, y
, 0);
1508 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1509 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1510 glDisable(GL_TEXTURE_2D
);
1513 glDisable(GL_BLEND
);
1516 // god forgive me for this, but i cannot figure out how to do it without lists
1517 procedure e_TextureFontPrintChar(X
, Y
: Integer; Ch
: Char; FontID
: DWORD
; Shadow
: Boolean = False);
1519 if e_NoGraphics
then Exit
;
1524 glColor4ub(0, 0, 0, 128);
1525 glTranslated(X
+1, Y
+1, 0);
1526 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1531 glColor4ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
, 255);
1532 glTranslated(X
, Y
, 0);
1533 glCallLists(1, GL_UNSIGNED_BYTE
, @Ch
);
1538 procedure e_TextureFontPrintFmt(X
, Y
: Integer; Text: string; FontID
: DWORD
; Shadow
: Boolean = False);
1540 a
, TX
, TY
, len
: Integer;
1544 if e_NoGraphics
then Exit
;
1545 if Text = '' then Exit
;
1546 if e_TextureFonts
= nil then Exit
;
1547 if Integer(FontID
) > High(e_TextureFonts
) then Exit
;
1555 len
:= Length(Text);
1557 w
:= e_TextureFonts
[FontID
].CharWidth
;
1559 with e_TextureFonts
[FontID
] do
1561 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1562 glEnable(GL_TEXTURE_2D
);
1563 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1565 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1568 for a
:= 1 to len
do
1579 c
.R
:= 0; c
.G
:= 0; c
.B
:= 0;
1584 c
.R
:= 255; c
.G
:= 255; c
.B
:= 255;
1589 c
.R
:= c
.R
div 2; c
.G
:= c
.G
div 2; c
.B
:= c
.B
div 2;
1594 c
.R
:= Min(c
.R
* 2, 255); c
.G
:= Min(c
.G
* 2, 255); c
.B
:= Min(c
.B
* 2, 255);
1599 c
.R
:= 255; c
.G
:= 0; c
.B
:= 0;
1604 c
.R
:= 0; c
.G
:= 255; c
.B
:= 0;
1609 c
.R
:= 0; c
.G
:= 0; c
.B
:= 255;
1614 c
.R
:= 255; c
.G
:= 255; c
.B
:= 0;
1621 e_TextureFontPrintChar(TX
, TY
, Text[a
], FontID
, Shadow
);
1626 glDisable(GL_TEXTURE_2D
);
1627 glDisable(GL_BLEND
);
1631 procedure e_TextureFontPrintEx(X
, Y
: GLint
; Text: string; FontID
: DWORD
; Red
, Green
,
1632 Blue
: Byte; Scale
: Single; Shadow
: Boolean = False);
1634 if e_NoGraphics
then Exit
;
1635 if Text = '' then Exit
;
1638 glBindTexture(GL_TEXTURE_2D
, e_TextureFonts
[FontID
].TextureID
);
1639 glEnable(GL_TEXTURE_2D
);
1640 glListBase(DWORD(Integer(e_TextureFonts
[FontID
].Base
)-32));
1642 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
1647 glColor4ub(0, 0, 0, 128);
1648 glTranslated(x
+1, y
+1, 0);
1649 glScalef(Scale
, Scale
, 0);
1650 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1655 glColor4ub(Red
, Green
, Blue
, 255);
1656 glTranslated(x
, y
, 0);
1657 glScalef(Scale
, Scale
, 0);
1658 glCallLists(Length(Text), GL_UNSIGNED_BYTE
, PChar(Text));
1660 glDisable(GL_TEXTURE_2D
);
1662 glColor3ub(e_Colors
.R
, e_Colors
.G
, e_Colors
.B
);
1663 glDisable(GL_BLEND
);
1666 procedure e_TextureFontGetSize(ID
: DWORD
; var CharWidth
, CharHeight
: Byte);
1670 if e_NoGraphics
then Exit
;
1671 if Integer(ID
) > High(e_TextureFonts
) then
1673 CharWidth
:= e_TextureFonts
[ID
].CharWidth
;
1674 CharHeight
:= e_TextureFonts
[ID
].CharHeight
;
1677 procedure e_RemoveAllTextureFont();
1681 if e_NoGraphics
then Exit
;
1682 if e_TextureFonts
= nil then Exit
;
1684 for i
:= 0 to High(e_TextureFonts
) do
1685 if e_TextureFonts
[i
].Base
<> 0 then
1687 glDeleteLists(e_TextureFonts
[i
].Base
, 256);
1688 e_TextureFonts
[i
].Base
:= 0;
1691 e_TextureFonts
:= nil;
1694 function _RGB(Red
, Green
, Blue
: Byte): TRGB
;
1701 function _Point(X
, Y
: Integer): TPoint2i
;
1707 function _Rect(X
, Y
: Integer; Width
, Height
: Word): TRectWH
;
1711 Result
.Width
:= Width
;
1712 Result
.Height
:= Height
;
1715 function _TRect(L
, T
, R
, B
: LongInt): TRect
;