Skip to content

Instantly share code, notes, and snippets.

@nilium
Created May 30, 2010 12:35
Show Gist options
  • Save nilium/418994 to your computer and use it in GitHub Desktop.
Save nilium/418994 to your computer and use it in GitHub Desktop.
use nuit
use sdl
use sdl_image
use glew
import structs/Stack
import nuit/[GUI, Types, Image, Renderer, FramedWindow, Drawable, NinePatchDrawable]
import sdl
import sdl_image
import glew
/** IMAGE DATA **/
TestImageData: class extends NImageData {
_name: UInt
_size: NSize
size: func -> NSize {_size}
}
/*** TEST RENDERER ***/
TestRenderState: cover {
color: NColor
drawing_region: NRect
origin: NPoint
clipped := false
apply: func (rend: NRenderer) {
glColor4fv(color red&)
if (clipped) {
screen := rend screenSize()
glEnable(GL_SCISSOR_TEST)
glScissor(drawing_region x() as Int,
(screen height - drawing_region y() - drawing_region height()) as Int,
drawing_region width() as Int,
drawing_region height() as Int)
} else {
glDisable(GL_SCISSOR_TEST)
}
}
}
TestRenderer: class extends NRenderer {
/* TODO: anything missing */
states: Stack<TestRenderState>
current: TestRenderState
acquired: Int = 0
init: func {
states = Stack<TestRenderState> new()
current drawing_region size = screenSize()
current color = NColor white()
}
fillColor: func {current color}
setFillColor: func (color: NColor) {
current color = color
}
screenSize: func -> NSize {
info := sdlGetVideoInfo()
return NSize new(
info@ as StructSDLVideoInfo currentW as NFloat,
info@ as StructSDLVideoInfo currentH as NFloat)
}
loadImage: func (url: String) -> NImage {
img := NImage new(url)
_bufferImage(img)
img frameSize = img size()
img frameCount = 1
return img
}
// TODO
loadImageWithFrames: func (url: String, frameSize: NSize, frameCount: Int) -> NImage {null}
_bufferImage: func (image: NImage) {
if (image data != null && image data instanceOf(TestImageData))
return
data := TestImageData new()
glEnable(GL_TEXTURE_2D)
glGenTextures(1, data _name&)
glBindTexture(GL_TEXTURE_2D, data _name)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
surf := imgLoad(image url)
if (surf == null)
Exception new(This, "Couldn't load image at \""+image url+"\"") throw()
data _size set(surf@ as StructSDLSurface w as NFloat, surf@ as StructSDLSurface h as NFloat)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, surf@ as StructSDLSurface w, surf@ as StructSDLSurface h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf@ as StructSDLSurface pixels)
image data = data
sdlFreeSurface(surf)
}
saveState: func {
states push(current)
}
restoreState: func {
current = states pop()
if (0 < acquired) current apply(this)
}
acquire: func {
acquired += 1
if (1 < acquired)
return
glPushAttrib(GL_ENABLE_BIT|GL_SCISSOR_BIT|GL_TEXTURE_BIT|GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
sz := screenSize()
glOrtho(0.0 as Double, sz width as Double, 0.0 as Double, sz height as Double, -10.0 as Double, 10.0 as Double)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
glTranslatef(0.0, sz height, 0.0)
glScalef(1.0, -1.0, 1.0)
glDepthFunc(GL_ALWAYS)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
current apply(this)
}
release: func {
if (acquired == 0)
Exception new(This, "Attempt to release unacquired renderer") throw()
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glPopAttrib()
acquired -= 1
}
fillRect: func (rect: NRect) {
glDisable(GL_TEXTURE_2D)
rect origin add(current origin)
glBegin(GL_QUADS)
glVertex2f(rect left(), rect top())
glVertex2f(rect right(), rect top())
glVertex2f(rect right(), rect bottom())
glVertex2f(rect left(), rect bottom())
glEnd()
}
setDrawingOrigin: func (origin: NPoint) { current origin = origin }
drawingOrigin: func -> NPoint { current origin }
drawImage: func (image: NImage, frame: Int, inRect: NRect) {
/* this is not optimal, but what the hell */
_bufferImage(image)
glEnable(GL_TEXTURE_2D)
fsize := image frameSize()
isize := image size()
widthDiv := (isize width / fsize width) as Int
column := frame % widthDiv
row := (frame - column) / widthDiv
fsize width /= isize width
fsize height /= isize height
uv := NRect new(NPoint new(fsize width * column, fsize height * row), fsize)
inRect origin add(current origin)
inRect origin x += NFloat min(0.0, inRect size width)
inRect origin y += NFloat min(0.0, inRect size height)
inRect size width = inRect size width abs()
inRect size height = inRect size height abs()
glBindTexture(GL_TEXTURE_2D, image data as TestImageData _name)
// IMMEDIATE MODE == BAD
glBegin(GL_QUADS)
glTexCoord2f(uv left(), uv top())
glVertex2f(inRect left(), inRect top())
glTexCoord2f(uv right(), uv top())
glVertex2f(inRect right(), inRect top())
glTexCoord2f(uv right(), uv bottom())
glVertex2f(inRect right(), inRect bottom())
glTexCoord2f(uv left(), uv bottom())
glVertex2f(inRect left(), inRect bottom())
glEnd()
}
drawSubimage: func (image: NImage, frame: Int, subimage, inRect: NRect) {
_bufferImage(image)
glEnable(GL_TEXTURE_2D)
inRect origin add(current origin)
inRect origin x += NFloat min(0.0, inRect size width)
inRect origin y += NFloat min(0.0, inRect size height)
inRect size width = inRect size width abs()
inRect size height = inRect size height abs()
glBindTexture(GL_TEXTURE_2D, image data as TestImageData _name)
scale := image frameSize()
scale set(1.0 / scale width, 1.0 / scale height)
subimage origin x *= scale width
subimage origin y *= scale width
subimage size width *= scale width
subimage size height *= scale width
fsize := image frameSize()
isize := image size()
widthDiv := (isize width / fsize width) as Int
column := frame % widthDiv
row := (frame - column) / widthDiv
fsize width = fsize width / isize width
fsize height = fsize height / isize height
x := fsize width * column
y := fsize height * row
subimage origin x += x
subimage origin y += y
glBegin(GL_QUADS)
glTexCoord2f(subimage left(), subimage top())
glVertex2f(inRect left(), inRect top())
glTexCoord2f(subimage right(), subimage top())
glVertex2f(inRect right(), inRect top())
glTexCoord2f(subimage right(), subimage bottom())
glVertex2f(inRect right(), inRect bottom())
glTexCoord2f(subimage left(), subimage bottom())
glVertex2f(inRect left(), inRect bottom())
glEnd()
}
clippingRegion: func -> NRect {current drawing_region}
setClippingRegion: func (drawing_region: NRect) {
current drawing_region = drawing_region
if (0 < acquired) current apply(this)
}
enableClipping: func {
current clipped = true
if (0 < acquired) current apply(this)
}
disableClipping: func {
current clipped = false
if (0 < acquired) current apply(this)
}
}
/*** The Wooperton Plaza ***/
main: func(argc: Int, argv: String*) {
sdlInit(EnumSDLInitFlags initVideo)
mainSurface := sdlSetVideoMode(800, 600, 32, EnumSDLSurfaceFlags opengl as UInt32 | EnumSDLGlattr doublebuffer as UInt32)
event: SDLEvent
running := true
glewInit()
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
rd := TestRenderer new()
img := rd loadImage("window.png")
x := 0.0
y := 0.0
// img frameSize set(90.0, 128.0)
// img frameCount = 4
drw := NNinePatchDrawable new()
drw image = img
drw borderTopLeft set(5.0, 24.0)
drw borderBottomRight set(5.0, 5.0)
gui := NGUI new()
gui makeActive()
gui setRenderer(rd)
wnd: NFramedWindow = NFramedWindow new(NRect new(25.0, 64.0, 512.0, 256.0))
wnd _drawable = drw
gui _windows add(wnd)
wnd = NFramedWindow new(NRect new(25.0, 64.0, 512.0, 256.0))
wnd _drawable = drw
gui _windows add(wnd)
while (running) {
while (sdlPollEvent(event&)) {
match (event as UnionSDLEvent type) {
case EnumSDLEventType quit => running = false
case EnumSDLEventType mousebuttonup =>
x = event as UnionSDLEvent button as StructSDLMouseButtonEvent x as Float
y = event as UnionSDLEvent button as StructSDLMouseButtonEvent y as Float
button := event as UnionSDLEvent button as StructSDLMouseButtonEvent button as Int
gui pushMouseReleasedEvent(button, NPoint new(x, y))
case EnumSDLEventType mousebuttondown =>
x = event as UnionSDLEvent button as StructSDLMouseButtonEvent x as Float
y = event as UnionSDLEvent button as StructSDLMouseButtonEvent y as Float
button := event as UnionSDLEvent button as StructSDLMouseButtonEvent button as Int
gui pushMousePressedEvent(button, NPoint new(x, y))
case EnumSDLEventType mousemotion =>
x = event as UnionSDLEvent motion as StructSDLMouseMotionEvent x as Float
y = event as UnionSDLEvent motion as StructSDLMouseMotionEvent y as Float
gui pushMouseMoveEvent(NPoint new(x, y))
}
}
glClear(GL_COLOR_BUFFER_BIT)
gui draw()
sdlGlSwapBuffers()
}
sdlQuit()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment