Some minor fixes and additions to the graphics module.
This commit is contained in:
parent
ed887e67e9
commit
b10640cdad
1 changed files with 62 additions and 40 deletions
|
|
@ -9,7 +9,8 @@
|
||||||
|
|
||||||
## This module implements graphical output for Nimrod; the current
|
## This module implements graphical output for Nimrod; the current
|
||||||
## implementation uses SDL but the interface is meant to support multiple
|
## implementation uses SDL but the interface is meant to support multiple
|
||||||
## backends some day.
|
## backends some day. There is no need to init SDL as this module does that
|
||||||
|
## implicitly.
|
||||||
|
|
||||||
import colors, math
|
import colors, math
|
||||||
from sdl import PSurface # Bug
|
from sdl import PSurface # Bug
|
||||||
|
|
@ -20,9 +21,9 @@ type
|
||||||
TPoint* = tuple[x, y: int]
|
TPoint* = tuple[x, y: int]
|
||||||
|
|
||||||
PSurface* = ref TSurface ## a surface to draw onto
|
PSurface* = ref TSurface ## a surface to draw onto
|
||||||
TSurface {.pure, final.} = object
|
TSurface* {.pure, final.} = object
|
||||||
w, h: int
|
w*, h*: int
|
||||||
s: sdl.PSurface
|
s*: sdl.PSurface
|
||||||
|
|
||||||
EGraphics* = object of EIO
|
EGraphics* = object of EIO
|
||||||
|
|
||||||
|
|
@ -31,13 +32,25 @@ type
|
||||||
color: SDL.TColor
|
color: SDL.TColor
|
||||||
PFont* = ref TFont ## represents a font
|
PFont* = ref TFont ## represents a font
|
||||||
|
|
||||||
proc toSdlColor(c: TColor): Sdl.TColor =
|
proc toSdlColor*(c: TColor): Sdl.TColor =
|
||||||
# Convert colors.TColor to SDL.TColor
|
## Convert colors.TColor to SDL.TColor
|
||||||
var x = c.extractRGB
|
var x = c.extractRGB
|
||||||
result.r = toU8(x.r)
|
result.r = toU8(x.r)
|
||||||
result.g = toU8(x.g)
|
result.g = toU8(x.g)
|
||||||
result.b = toU8(x.b)
|
result.b = toU8(x.b)
|
||||||
|
|
||||||
|
proc createSdlColor*(sur: PSurface, c: TColor, alpha: int = 0): int32 =
|
||||||
|
## Creates a color using ``sdl.MapRGBA``.
|
||||||
|
var x = c.extractRGB
|
||||||
|
return sdl.MapRGBA(sur.s.format, toU8(x.r), toU8(x.g), toU8(x.b), toU8(alpha))
|
||||||
|
|
||||||
|
proc toSdlRect*(r: TRect): sdl.TRect =
|
||||||
|
## Convert ``graphics.TRect`` to ``sdl.TRect``.
|
||||||
|
result.x = int16(r.x)
|
||||||
|
result.y = int16(r.y)
|
||||||
|
result.w = int16(r.width)
|
||||||
|
result.h = int16(r.height)
|
||||||
|
|
||||||
proc raiseEGraphics =
|
proc raiseEGraphics =
|
||||||
raise newException(EGraphics, $SDL.GetError())
|
raise newException(EGraphics, $SDL.GetError())
|
||||||
|
|
||||||
|
|
@ -50,6 +63,8 @@ proc newSurface*(width, height: int): PSurface =
|
||||||
result.h = height
|
result.h = height
|
||||||
result.s = SDL.CreateRGBSurface(SDL.SWSURFACE, width, height,
|
result.s = SDL.CreateRGBSurface(SDL.SWSURFACE, width, height,
|
||||||
32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0)
|
32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0)
|
||||||
|
if result.s == nil:
|
||||||
|
raiseEGraphics()
|
||||||
|
|
||||||
assert(not sdl.MustLock(result.s))
|
assert(not sdl.MustLock(result.s))
|
||||||
|
|
||||||
|
|
@ -71,12 +86,14 @@ proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) =
|
||||||
## initializes the `defaultFont` var.
|
## initializes the `defaultFont` var.
|
||||||
defaultFont = newFont(name, size, color)
|
defaultFont = newFont(name, size, color)
|
||||||
|
|
||||||
proc newScreenSurface(width, height: int): PSurface =
|
proc newScreenSurface*(width, height: int): PSurface =
|
||||||
## Creates a new screen surface
|
## Creates a new screen surface
|
||||||
new(result, surfaceFinalizer)
|
new(result, surfaceFinalizer)
|
||||||
result.w = width
|
result.w = width
|
||||||
result.h = height
|
result.h = height
|
||||||
result.s = SDL.SetVideoMode(width, height, 0, 0)
|
result.s = SDL.SetVideoMode(width, height, 0, 0)
|
||||||
|
if result.s == nil:
|
||||||
|
raiseEGraphics()
|
||||||
|
|
||||||
proc writeToBMP*(sur: PSurface, filename: string) =
|
proc writeToBMP*(sur: PSurface, filename: string) =
|
||||||
## Saves the contents of the surface `sur` to the file `filename` as a
|
## Saves the contents of the surface `sur` to the file `filename` as a
|
||||||
|
|
@ -113,7 +130,7 @@ proc `[]`*(sur: PSurface, p: TPoint): TColor =
|
||||||
## get pixel at position `p`. No range checking is done!
|
## get pixel at position `p`. No range checking is done!
|
||||||
result = getPixel(sur, p.x, p.y)
|
result = getPixel(sur, p.x, p.y)
|
||||||
|
|
||||||
proc `[,]`*(sur: PSurface, x, y: int): TColor =
|
proc `[]`*(sur: PSurface, x, y: int): TColor =
|
||||||
## get pixel at position ``(x, y)``. No range checking is done!
|
## get pixel at position ``(x, y)``. No range checking is done!
|
||||||
result = getPixel(sur, x, y)
|
result = getPixel(sur, x, y)
|
||||||
|
|
||||||
|
|
@ -121,7 +138,7 @@ proc `[]=`*(sur: PSurface, p: TPoint, col: TColor) =
|
||||||
## set the pixel at position `p`. No range checking is done!
|
## set the pixel at position `p`. No range checking is done!
|
||||||
setPixel(sur, p.x, p.y, col)
|
setPixel(sur, p.x, p.y, col)
|
||||||
|
|
||||||
proc `[,]=`*(sur: PSurface, x, y: int, col: TColor) =
|
proc `[]=`*(sur: PSurface, x, y: int, col: TColor) =
|
||||||
## set the pixel at position ``(x, y)``. No range checking is done!
|
## set the pixel at position ``(x, y)``. No range checking is done!
|
||||||
setPixel(sur, x, y, col)
|
setPixel(sur, x, y, col)
|
||||||
|
|
||||||
|
|
@ -159,8 +176,6 @@ proc drawText*(sur: PSurface, p: TPoint, text: string, font = defaultFont) =
|
||||||
textSur.s = sdl_ttf.RenderTextBlended(font.f, text, font.color)
|
textSur.s = sdl_ttf.RenderTextBlended(font.f, text, font.color)
|
||||||
# Merge the text surface with sur
|
# Merge the text surface with sur
|
||||||
sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
|
sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
|
||||||
# Free the surface
|
|
||||||
SDL.FreeSurface(sur.s)
|
|
||||||
|
|
||||||
proc drawText*(sur: PSurface, p: TPoint, text: string,
|
proc drawText*(sur: PSurface, p: TPoint, text: string,
|
||||||
bg: TColor, font = defaultFont) =
|
bg: TColor, font = defaultFont) =
|
||||||
|
|
@ -171,8 +186,6 @@ proc drawText*(sur: PSurface, p: TPoint, text: string,
|
||||||
textSur.s = sdl_ttf.RenderTextShaded(font.f, text, font.color, toSdlColor(bg))
|
textSur.s = sdl_ttf.RenderTextShaded(font.f, text, font.color, toSdlColor(bg))
|
||||||
# Merge the text surface with sur
|
# Merge the text surface with sur
|
||||||
sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
|
sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
|
||||||
# Free the surface
|
|
||||||
SDL.FreeSurface(sur.s)
|
|
||||||
|
|
||||||
proc drawCircle*(sur: PSurface, p: TPoint, r: Natural, color: TColor) =
|
proc drawCircle*(sur: PSurface, p: TPoint, r: Natural, color: TColor) =
|
||||||
## draws a circle with center `p` and radius `r` with the given color
|
## draws a circle with center `p` and radius `r` with the given color
|
||||||
|
|
@ -323,14 +336,10 @@ proc drawRect*(sur: PSurface, r: TRect, color: TColor) =
|
||||||
setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side
|
setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side
|
||||||
|
|
||||||
proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
|
proc fillRect*(sur: PSurface, r: TRect, col: TColor) =
|
||||||
## draws and fills a rectangle.
|
## Fills a rectangle using sdl's ``FillRect`` function.
|
||||||
var video = cast[PPixels](sur.s.pixels)
|
var rect = toSdlRect(r)
|
||||||
assert video != nil
|
if sdl.FillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1:
|
||||||
var pitch = sur.s.pitch div ColSize
|
raiseEGraphics()
|
||||||
|
|
||||||
for i in r.y..min(sur.s.h, r.y+r.height-1)-1:
|
|
||||||
for j in r.x..min(sur.s.w, r.x+r.width-1)-1:
|
|
||||||
setPix(video, pitch, j, i, col)
|
|
||||||
|
|
||||||
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
|
proc Plot4EllipsePoints(sur: PSurface, CX, CY, X, Y: Natural, col: TColor) =
|
||||||
var video = cast[PPixels](sur.s.pixels)
|
var video = cast[PPixels](sur.s.pixels)
|
||||||
|
|
@ -450,7 +459,14 @@ proc drawLineAA*(sur: PSurface, p1, p2: TPoint, color: TColor) =
|
||||||
sur.plotAA(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
|
sur.plotAA(x.toFloat(), ipart(intery) + 1.0, fpart(intery), color)
|
||||||
intery = intery + gradient
|
intery = intery + gradient
|
||||||
|
|
||||||
template withEvents(surf: PSurface, event: expr, actions: stmt): stmt =
|
proc fillSurface*(sur: PSurface, color: TColor) =
|
||||||
|
## Fills the entire surface with ``color``.
|
||||||
|
if sdl.FillRect(sur.s, nil, sur.createSdlColor(color)) == -1:
|
||||||
|
raiseEGraphics()
|
||||||
|
|
||||||
|
template withEvents*(surf: PSurface, event: expr, actions: stmt): stmt =
|
||||||
|
## Simple template which creates an event loop. ``Event`` is the name of the
|
||||||
|
## variable containing the TEvent object.
|
||||||
while True:
|
while True:
|
||||||
var event: SDL.TEvent
|
var event: SDL.TEvent
|
||||||
if SDL.PollEvent(addr(event)) == 1:
|
if SDL.PollEvent(addr(event)) == 1:
|
||||||
|
|
@ -461,10 +477,9 @@ if sdl_ttf.Init() < 0: raiseEGraphics()
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
var surf = newScreenSurface(800, 600)
|
var surf = newScreenSurface(800, 600)
|
||||||
var r: TRect = (0, 0, 900, 900)
|
surf.fillSurface(colWhite)
|
||||||
|
|
||||||
# Draw the shapes
|
# Draw the shapes
|
||||||
surf.fillRect(r, colWhite)
|
|
||||||
surf.drawLineAA((100, 170), (400, 471), colTan)
|
surf.drawLineAA((100, 170), (400, 471), colTan)
|
||||||
surf.drawLine((100, 170), (400, 471), colRed)
|
surf.drawLine((100, 170), (400, 471), colRed)
|
||||||
|
|
||||||
|
|
@ -480,6 +495,8 @@ when isMainModule:
|
||||||
surf.drawVerLine(5, 60, 800, colRed)
|
surf.drawVerLine(5, 60, 800, colRed)
|
||||||
surf.drawCircle((600, 500), 60, colRed)
|
surf.drawCircle((600, 500), 60, colRed)
|
||||||
|
|
||||||
|
surf.fillRect((50, 50, 100, 100), colFuchsia)
|
||||||
|
|
||||||
#surf.drawText((300, 300), "TEST", colMidnightBlue)
|
#surf.drawText((300, 300), "TEST", colMidnightBlue)
|
||||||
#var textSize = textBounds("TEST")
|
#var textSize = textBounds("TEST")
|
||||||
#surf.drawText((300, 300 + textSize.height), $textSize.width & ", " &
|
#surf.drawText((300, 300 + textSize.height), $textSize.width & ", " &
|
||||||
|
|
@ -488,33 +505,38 @@ when isMainModule:
|
||||||
var mouseStartX = 0
|
var mouseStartX = 0
|
||||||
var mouseStartY = 0
|
var mouseStartY = 0
|
||||||
withEvents(surf, event):
|
withEvents(surf, event):
|
||||||
|
var eventp = addr(event)
|
||||||
case event.kind:
|
case event.kind:
|
||||||
of SDL.QUITEV:
|
of SDL.QUITEV:
|
||||||
break
|
break
|
||||||
of SDL.KEYDOWN:
|
of SDL.KEYDOWN:
|
||||||
if event.sym == SDL.K_LEFT:
|
var evk = sdl.EvKeyboard(eventp)
|
||||||
echo(event.sym)
|
if evk.keysym.sym == SDL.K_LEFT:
|
||||||
surf.drawHorLine(395, 300, 5, colPaleGoldenRod)
|
surf.drawHorLine(395, 300, 50, colBlack)
|
||||||
echo("Drawing")
|
echo("Drawing")
|
||||||
else:
|
else:
|
||||||
echo(event.sym)
|
echo(evk.keysym.sym)
|
||||||
of SDL.MOUSEBUTTONDOWN:
|
of SDL.MOUSEBUTTONDOWN:
|
||||||
# button.x/y is F* UP!
|
var mbd = sdl.EvMouseButton(eventp)
|
||||||
echo("MOUSEDOWN ", event.x)
|
mouseStartX = mbd.x
|
||||||
mouseStartX = event.x
|
mouseStartY = mbd.y
|
||||||
mouseStartY = event.y
|
|
||||||
|
|
||||||
of SDL.MOUSEBUTTONUP:
|
of SDL.MOUSEBUTTONUP:
|
||||||
echo("MOUSEUP ", mouseStartX)
|
var mbu = sdl.EvMouseButton(eventp)
|
||||||
if mouseStartX != 0 and mouseStartY != 0:
|
if mouseStartX != 0 and mouseStartY != 0:
|
||||||
echo(mouseStartX, "->", int(event.x))
|
echo(mouseStartX, "x->", mbu.x)
|
||||||
|
echo(mouseStartY, "y->", mbu.y)
|
||||||
surf.drawLineAA((mouseStartX, MouseStartY),
|
surf.drawLineAA((mouseStartX, MouseStartY),
|
||||||
(int(event.x), int(event.y)), colPaleGoldenRod)
|
(int(mbu.x), int(mbu.y)), colRed)
|
||||||
mouseStartX = 0
|
mouseStartX = 0
|
||||||
mouseStartY = 0
|
mouseStartY = 0
|
||||||
|
|
||||||
|
of SDL.MouseMotion:
|
||||||
|
var mm = sdl.EvMouseMotion(eventp)
|
||||||
|
echo(mm.x, " ", mm.y, " ", mm.yrel)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
#echo(event.theType)
|
#echo(event.kind)
|
||||||
|
|
||||||
SDL.UpdateRect(surf.s, int32(0), int32(0), int32(800), int32(600))
|
SDL.UpdateRect(surf.s, int32(0), int32(0), int32(800), int32(600))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue