X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fengine%2Fe_graphics.pas;h=1830c406172a53331dc69aba7d67c1f66c6a4460;hb=6fdaf7454535407de0331bdc6b96e538919525a6;hp=f08957c5c3233e313d20f8ea778dcdf348b89819;hpb=8558702f560e3faf9be93f96dfffbf4b6ba34c90;p=d2df-sdl.git diff --git a/src/engine/e_graphics.pas b/src/engine/e_graphics.pas index f08957c..1830c40 100644 --- a/src/engine/e_graphics.pas +++ b/src/engine/e_graphics.pas @@ -13,13 +13,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . *) -{$MODE DELPHI} +{$INCLUDE ../shared/a_modes.inc} unit e_graphics; interface uses - SysUtils, Classes, Math, e_log, e_textures, SDL2, GL, GLExt, MAPDEF, ImagingTypes, Imaging, ImagingUtility; + SysUtils, Classes, Math, e_log, e_texture, SDL2, GL, GLExt, MAPDEF, ImagingTypes, Imaging, ImagingUtility; type TMirrorType=(M_NONE, M_HORIZONTAL, M_VERTICAL); @@ -29,9 +29,6 @@ type X, Y: Integer; end; - TPoint = MAPDEF.TPoint; // TODO: create an utiltypes.pas or something - // for other types like rect as well - TPoint2f = record X, Y: Double; end; @@ -49,7 +46,7 @@ type R, G, B: Byte; end; - PPoint = ^TPoint; + PDFPoint = ^TDFPoint; PPoint2f = ^TPoint2f; PRect = ^TRect; PRectWH = ^TRectWH; @@ -65,18 +62,24 @@ procedure e_ResizeWindow(Width, Height: Integer); procedure e_Draw(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Mirror: TMirrorType = M_NONE); procedure e_DrawAdv(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; - Blending: Boolean; Angle: Single; RC: PPoint; Mirror: TMirrorType = M_NONE); + Blending: Boolean; Angle: Single; RC: PDFPoint; Mirror: TMirrorType = M_NONE); procedure e_DrawSize(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Width, Height: Word; Mirror: TMirrorType = M_NONE); procedure e_DrawSizeMirror(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; Blending: Boolean; Width, Height: Word; Mirror: TMirrorType = M_NONE); + procedure e_DrawFill(ID: DWORD; X, Y: Integer; XCount, YCount: Word; Alpha: Integer; AlphaChannel: Boolean; Blending: Boolean); + +procedure e_DrawFillX (id: DWORD; x, y, wdt, hgt: Integer; alpha: Integer; alphachannel: Boolean; blending: Boolean; scale: Single); + procedure e_DrawPoint(Size: Byte; X, Y: Integer; Red, Green, Blue: Byte); procedure e_DrawLine(Width: Byte; X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byte = 0); procedure e_DrawQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byte = 0); procedure e_DrawFillQuad(X1, Y1, X2, Y2: Integer; Red, Green, Blue, Alpha: Byte; Blending: TBlending = B_NONE); +procedure e_DarkenQuad (x0, y0, x1, y1: Integer; a: Integer); +procedure e_DarkenQuadWH (x, y, w, h: Integer; a: Integer); function e_CreateTextureImg (var img: TImageData; var ID: DWORD): Boolean; function e_CreateTexture(FileName: string; var ID: DWORD): Boolean; @@ -110,7 +113,7 @@ procedure e_TextureFontPrint(X, Y: GLint; Text: string; FontID: DWORD); procedure e_TextureFontPrintEx(X, Y: GLint; Text: string; FontID: DWORD; Red, Green, Blue: Byte; Scale: Single; Shadow: Boolean = False); procedure e_TextureFontPrintFmt(X, Y: GLint; Text: string; FontID: DWORD; Shadow: Boolean = False); -procedure e_TextureFontGetSize(ID: DWORD; var CharWidth, CharHeight: Byte); +procedure e_TextureFontGetSize(ID: DWORD; out CharWidth, CharHeight: Byte); procedure e_RemoveAllTextureFont(); function e_TextureFontCharWidth (ch: Char; FontID: DWORD): Integer; @@ -168,7 +171,7 @@ type end; Space: ShortInt; Height: ShortInt; - Live: Boolean; + alive: Boolean; end; TSavedTexture = record @@ -680,8 +683,151 @@ begin glDisable(GL_BLEND); end; + +//TODO: overflow checks +function intersectRect (var x0, y0, w0, h0: Integer; const x1, y1, w1, h1: Integer): Boolean; +var + ex0, ey0: Integer; +begin + result := false; + if (w0 < 1) or (h0 < 1) or (w1 < 1) or (h1 < 1) then exit; + // check for intersection + if (x0+w0 <= x1) or (y0+h0 <= y1) or (x1+w1 <= x0) or (y1+h1 <= y0) then exit; + if (x0 >= x1+w1) or (y0 >= y1+h1) or (x1 >= x0+h0) or (y1 >= y0+h0) then exit; + // ok, intersects + ex0 := x0+w0; + ey0 := y0+h0; + if (x0 < x1) then x0 := x1; + if (y0 < y1) then y0 := y1; + if (ex0 > x1+w1) then ex0 := x1+w1; + if (ey0 > y1+h1) then ey0 := y1+h1; + w0 := ex0-x0; + h0 := ey0-y0; + result := (w0 > 0) and (h0 > 0); +end; + + +procedure e_DrawFillX (id: DWORD; x, y, wdt, hgt: Integer; alpha: Integer; alphachannel: Boolean; blending: Boolean; scale: Single); +var + x2, y2: Integer; + { + wassc: Boolean; + scxywh: array[0..3] of GLint; + vpxywh: array[0..3] of GLint; + } + w, h, dw, cw, ch, yofs: Integer; + u, v, cu, cv: Single; + onlyOneY: Boolean; + + { + procedure setScissorGLInternal (x, y, w, h: Integer); + begin + //if not scallowed then exit; + x := trunc(x*scale); + y := trunc(y*scale); + w := trunc(w*scale); + h := trunc(h*scale); + y := vpxywh[3]-(y+h); + if not intersectRect(x, y, w, h, scxywh[0], scxywh[1], scxywh[2], scxywh[3]) then + begin + glScissor(0, 0, 0, 0); + end + else + begin + //writeln(' (', x, ',', y, ')-(', w, ',', h, ')'); + glScissor(x, y, w, h); + end; + end; + } + +begin + if e_NoGraphics then exit; + + if (wdt < 1) or (hgt < 1) then exit; + + if (wdt mod e_Textures[ID].tx.width = 0) and (hgt mod e_Textures[ID].tx.height = 0) then + begin + e_DrawFill(id, x, y, wdt div e_Textures[ID].tx.width, hgt div e_Textures[ID].tx.height, alpha, alphachannel, blending); + exit; + end; + + glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255); + + if (Alpha > 0) or AlphaChannel or Blending then + glEnable(GL_BLEND) + else + glDisable(GL_BLEND); + + if AlphaChannel or (Alpha > 0) then glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (Alpha > 0) then glColor4ub(e_Colors.R, e_Colors.G, e_Colors.B, 255-Alpha); + + if Blending then glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, e_Textures[ID].tx.id); + + x2 := x+wdt; + y2 := y+hgt; + + //k8: this SHOULD work... i hope + if {false and} (e_Textures[ID].tx.width = e_Textures[ID].tx.glwidth) and (e_Textures[ID].tx.height = e_Textures[ID].tx.glheight) then + begin + glBegin(GL_QUADS); + glTexCoord2f(0, hgt/e_Textures[ID].tx.height); glVertex2i(x, y); + glTexCoord2f(wdt/e_Textures[ID].tx.width, hgt/e_Textures[ID].tx.height); glVertex2i(x2, y); + glTexCoord2f(wdt/e_Textures[ID].tx.width, 0); glVertex2i(x2, y2); + glTexCoord2f(0, 0); glVertex2i(x, y2); + glEnd(); + end + else + begin + // hard day's night; setup scissor + { + glGetIntegerv(GL_VIEWPORT, @vpxywh[0]); + wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0); + if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]); + //writeln('(', scxywh[0], ',', scxywh[1], ')-(', scxywh[2], ',', scxywh[3], ')'); + //glEnable(GL_SCISSOR_TEST); + setScissorGLInternal(x, y, wdt, hgt); + } + // draw quads + u := e_Textures[ID].tx.u; + v := e_Textures[ID].tx.v; + w := e_Textures[ID].tx.width; + h := e_Textures[ID].tx.height; + x2 := x; + if (hgt > h) then begin y += hgt-h; onlyOneY := false; end else onlyOneY := true; + glBegin(GL_QUADS); + while (hgt > 0) do + begin + if (hgt >= h) then begin ch := h; cv := v; yofs := 0; end else begin ch := hgt; cv := v/(h/hgt); yofs := h-hgt; end; + if onlyOneY then yofs := 0; + Dec(hgt, h); + dw := wdt; + x := x2; + while (dw > 0) do + begin + if (dw >= w) then begin cw := w; cu := u; end else begin cw := dw; cu := u/(w/dw); end; + Dec(dw, w); + glTexCoord2f(0, cv); glVertex2i(X, Y+yofs); + glTexCoord2f(cu, cv); glVertex2i(X+cw, Y+yofs); + glTexCoord2f(cu, 0); glVertex2i(X+cw, Y+ch+yofs); + glTexCoord2f(0, 0); glVertex2i(X, Y+ch+yofs); + Inc(X, w); + end; + Dec(Y, h); + end; + glEnd(); + //if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST); + end; + + glDisable(GL_BLEND); +end; + + procedure e_DrawAdv(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean; - Blending: Boolean; Angle: Single; RC: PPoint; Mirror: TMirrorType = M_NONE); + Blending: Boolean; Angle: Single; RC: PDFPoint; Mirror: TMirrorType = M_NONE); begin if e_NoGraphics then Exit; @@ -861,6 +1007,34 @@ begin glDisable(GL_BLEND); end; + +// ////////////////////////////////////////////////////////////////////////// // +procedure e_DarkenQuad (x0, y0, x1, y1: Integer; a: Integer); +begin + if (a < 0) then a := 0; + if (a > 255) then a := 255; + glEnable(GL_BLEND); + glBlendFunc(GL_ZERO, GL_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + glColor4ub(0, 0, 0, Byte(255-a)); + glBegin(GL_QUADS); + glVertex2i(x0, y0); + glVertex2i(x1, y0); + glVertex2i(x1, y1); + glVertex2i(x0, y1); + glEnd(); + //glRect(x, y, x+w, y+h); + glColor4ub(1, 1, 1, 1); + glDisable(GL_BLEND); + //glBlendEquation(GL_FUNC_ADD); +end; + +procedure e_DarkenQuadWH (x, y, w, h: Integer; a: Integer); +begin + if (w > 0) and (h > 0) then e_DarkenQuad(x, y, x+w, y+h, a); +end; + + procedure e_DrawLine(Width: Byte; X1, Y1, X2, Y2: Integer; Red, Green, Blue: Byte; Alpha: Byte = 0); begin if e_NoGraphics then Exit; @@ -1024,7 +1198,7 @@ begin if e_CharFonts <> nil then for i := 0 to High(e_CharFonts) do - if not e_CharFonts[i].Live then + if not e_CharFonts[i].alive then begin id := i; Break; @@ -1046,7 +1220,7 @@ begin end; Space := sp; - Live := True; + alive := True; end; Result := id; @@ -1318,7 +1492,7 @@ begin for a := 0 to High(Chars) do if Chars[a].TextureID <> -1 then e_DeleteTexture(Chars[a].TextureID); - e_CharFonts[FontID].Live := False; + e_CharFonts[FontID].alive := False; end; procedure e_CharFont_RemoveAll(); @@ -1380,7 +1554,7 @@ begin glNewList(e_TextureFonts[id].Base+loop1, GL_COMPILE); glBegin(GL_QUADS); glTexCoord2f(cx, 1.0-cy-1/YCount); - glVertex2d(0, e_Textures[Tex].tx.Height div YCount); + glVertex2i(0, e_Textures[Tex].tx.Height div YCount); glTexCoord2f(cx+1/XCount, 1.0-cy-1/YCount); glVertex2i(e_Textures[Tex].tx.Width div XCount, e_Textures[Tex].tx.Height div YCount); @@ -1596,7 +1770,7 @@ begin glDisable(GL_BLEND); end; -procedure e_TextureFontGetSize(ID: DWORD; var CharWidth, CharHeight: Byte); +procedure e_TextureFontGetSize(ID: DWORD; out CharWidth, CharHeight: Byte); begin CharWidth := 16; CharHeight := 16; @@ -1739,7 +1913,7 @@ begin sign[2] := 68; sign[3] := 82; st.writeBuffer(sign, 4); - crc := crc32(0, @sign, 4); + crc := crc32(0, @sign[0], 4); hbuf[0] := 0; hbuf[1] := 0; hbuf[2] := (Width shr 8) and $ff; @@ -1753,7 +1927,7 @@ begin hbuf[10] := 0; // compression method hbuf[11] := 0; // filter method hbuf[12] := 0; // no interlace - crc := crc32(crc, @hbuf, 13); + crc := crc32(crc, @hbuf[0], 13); st.writeBuffer(hbuf, 13); writeIntBE(st, crc); //e_WriteLog('PNG: header written', MSG_NOTIFY); @@ -1765,7 +1939,7 @@ begin sign[2] := 65; sign[3] := 84; st.writeBuffer(sign, 4); - crc := crc32(0, @sign, 4); + crc := crc32(0, @sign[0], 4); crc := crc32(crc, obuf, dlen); st.writeBuffer(obuf^, dlen); writeIntBE(st, crc); @@ -1778,7 +1952,7 @@ begin sign[2] := 78; sign[3] := 68; st.writeBuffer(sign, 4); - crc := crc32(0, @sign, 4); + crc := crc32(0, @sign[0], 4); writeIntBE(st, crc); //e_WriteLog('PNG: end marker written', MSG_NOTIFY); finally