This is a work in progress / experiment to show feasibility.
Last active
September 5, 2021 02:03
-
-
Save jemc/b5744165ae4ff7d1adb49cd2854f43ce to your computer and use it in GitHub Desktop.
pony-sdl-wrapper
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.so | |
*.o | |
TAGS | |
pony-sdl-example |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "collections" | |
actor Main | |
new create(env: Env) => | |
let ui = UI("Pony SDL Example") | |
// Create a grid of squares in a gradient, with the upper-left being black, | |
// the lower-left being fully red, the upper-right being blue, and the | |
// lower-right being the mix of them (magenta). | |
// The colors of each square will do an independent random walk over time. | |
let size: USize = 40 | |
let window_width: USize = 640 | |
let window_height: USize = 480 | |
let x_count = window_width / size | |
let y_count = window_height / size | |
ui.access({(ui: UI ref) => | |
for x_index in Range(0, x_count) do | |
for y_index in Range(0, y_count) do | |
ui.renderables.push( | |
RenderableSquareWithRandomWalkingColor( | |
(x_index * size).i32(), | |
(y_index * size).i32(), | |
size.i32(), | |
RGBA( | |
((y_index * 0xff) / y_count).u8(), | |
0, | |
((x_index * 0xff) / x_count).u8(), | |
0xff | |
) | |
) | |
) | |
end | |
end | |
} val) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.PHONY: default | |
default: pony-sdl-example | |
./pony-sdl-example | |
pony-sdl-example: libsdlnative.so $(shell find . -name '*.pony') | |
ponyc -b pony-sdl-example | |
libsdlnative.so: sdl_native.o | |
CFLAGS="-O0 -ggdb3" gcc -shared -o libsdlnative.so sdl_native.o | |
sdl_native.o: | |
CFLAGS="-O0 -ggdb3" gcc -c -Wall -Werror -fpic -lSDL2 sdl_native.c | |
clean: | |
rm -f pony-sdl-example | |
rm -f libsdlnative.so | |
rm -f sdl_native.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "random" | |
trait Renderable | |
fun ref render_next(renderer: SDLRenderer) | |
class RenderableSeizureBackground is Renderable | |
var n: U32 = 0 | |
fun ref render_next(renderer: SDLRenderer) => | |
n = n + 1 | |
if (n % 2) == 0 then | |
renderer.set_draw_color(RGBA(255, 0, 0, 0)) | |
else | |
renderer.set_draw_color(RGBA(0, 0, 255, 0)) | |
end | |
renderer.fill_entire() | |
class RenderableSquareWithRandomWalkingColor is Renderable | |
let _rect: SDLRect | |
var _color: RGBA | |
let _rand: Rand | |
new iso create(x: I32, y: I32, diameter: I32, color: RGBA) => | |
_rect = SDLRect(x, y, diameter, diameter) | |
_color = color | |
_rand = Rand(color.r.u64(), color.b.u64()) | |
fun ref render_next(renderer: SDLRenderer) => | |
renderer.set_draw_color(_next_color()) | |
renderer.fill_rect(_rect) | |
fun ref _next_color(): RGBA => | |
var r = _color.r | |
var g = _color.g | |
var b = _color.b | |
if (r > 0x00) and (_rand.i8() > 0) then r = r - 1 end | |
if (r < 0xff) and (_rand.i8() > 0) then r = r + 1 end | |
if (g > 0x00) and (_rand.i8() > 0) then g = g - 1 end | |
if (g < 0xff) and (_rand.i8() > 0) then g = g + 1 end | |
if (b > 0x00) and (_rand.i8() > 0) then b = b - 1 end | |
if (b < 0xff) and (_rand.i8() > 0) then b = b + 1 end | |
_color = RGBA(r, g, b, _color.a) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "lib:SDL2" | |
use "path:./" | |
use "lib:sdlnative" | |
use @SDL_Init[I32](flags: U32) | |
use @SDL_CreateWindow[Pointer[_SDLWindow]](title: Pointer[U8] tag, x: I32, y: I32, w: I32, h: I32, flags: U32) | |
use @SDL_CreateRenderer[Pointer[_SDLRenderer]](window: Pointer[_SDLWindow], index: I32, flags: U32) | |
use @SDL_DestroyRenderer[None](renderer: Pointer[_SDLRenderer] tag) | |
use @SDL_DestroyWindow[None](window: Pointer[_SDLWindow] tag) | |
use @SDL_GL_GetCurrentContext[Pointer[_SDLGLContext]]() | |
use @SDL_GL_MakeCurrent[I32](window: Pointer[_SDLWindow], context: Pointer[_SDLGLContext]) | |
use @SDL_RenderClear[I32](renderer: Pointer[_SDLRenderer]) | |
use @SDL_RenderPresent[None](renderer: Pointer[_SDLRenderer]) | |
use @SDL_CreateRGBSurface[Pointer[_SDLSurface]](flags: U32, width: I32, height: I32, depth: I32, rmask: U32, gmask: U32, bmask: U32, amask: U32) | |
use @SDL_GetWindowSize[None](window: Pointer[_SDLWindow], width: Pointer[I32], height: Pointer[I32]) | |
use @SDL_FreeSurface[None](surface: Pointer[_SDLSurface]) | |
use @SDL_GetRendererOutputSize[None](renderer: Pointer[_SDLRenderer] , width: Pointer[I32], height: Pointer[I32]) | |
use @sdl_get_surface_info[None](info: NullablePointer[SDLSurfaceInfo], surface: Pointer[_SDLSurface]) | |
use @SDL_SetRenderDrawColor[None](renderer: Pointer[_SDLRenderer] , r: U8, g: U8, b: U8, a: U8) | |
use @SDL_CreateTextureFromSurface[Pointer[_SDLTexture]](renderer: Pointer[_SDLRenderer] , surface: Pointer[_SDLSurface]) | |
use @SDL_DestroyTexture[None](texture: Pointer[_SDLTexture]) | |
use @SDL_Quit[None]() | |
use @SDL_Delay[None](ms: U32) | |
// use @SDL_RenderCopy[None](renderer: Pointer[_SDLRenderer], texture: Pointer[_SDLTexture], a: NullablePointer[_SDLRect], b: NullablePointer[_SDLRect]) | |
use @sdl_poll_event_type[U32]() | |
use @sdl_poll_event[U32](e: Pointer[_SDLEvent]) | |
use @sdl_get_event_type[U32](e: Pointer[_SDLEvent] box) | |
use @new_sdl_event[Pointer[_SDLEvent]]() | |
use @free_sdl_event[None](e: Pointer[_SDLEvent] tag) | |
use @sdl_quit_event[U32]() | |
use @update_texture_from_surface[None](t: Pointer[_SDLTexture], s: Pointer[_SDLSurface]) | |
use @SDL_RenderFillRect[I32](renderer: Pointer[_SDLRenderer], rect: NullablePointer[SDLRect]) | |
primitive _SDLWindow | |
primitive _SDLRenderer | |
primitive _SDLGLContext | |
primitive _SDLSurface | |
primitive _SDLTexture | |
primitive _SDLEvent | |
struct val RGBA | |
var r: U8 = 0 | |
var g: U8 = 0 | |
var b: U8 = 0 | |
var a: U8 = 0 | |
new val create(r': U8, g': U8, b': U8, a': U8) => | |
r = r' | |
g = g' | |
b = b' | |
a = a' | |
struct val SDLRect | |
var x: I32 = 0 | |
var y: I32 = 0 | |
var w: I32 = 0 | |
var h: I32 = 0 | |
new val create(x': I32, y': I32, w': I32, h': I32) => | |
x = x' | |
y = y' | |
w = w' | |
h = h' | |
struct SDLSurfaceInfo | |
var w: I32 = 0 | |
var h: I32 = 0 | |
var pitch: I32 = 0 | |
new create() => None | |
class SDLWindow | |
let _ptr: Pointer[_SDLWindow] | |
let _gl: Pointer[_SDLGLContext] | |
fun ref _get_ptr(): Pointer[_SDLWindow] => _ptr | |
new iso create(title: String, x: I32, y: I32, w: I32, h: I32, flags: U32) => | |
_ptr = @SDL_CreateWindow(title.cstring(), x, y, w, h, flags) | |
_gl = @SDL_GL_GetCurrentContext() | |
fun _final() => | |
@SDL_DestroyWindow(_ptr) | |
fun ref begin_behavior() => | |
@SDL_GL_MakeCurrent(_ptr, _gl) | |
fun ref finish_behavior() => | |
@SDL_GL_MakeCurrent(_ptr.create(), _gl.create()) // these are NULL pointers | |
class SDLRenderer | |
let _window: SDLWindow | |
let _ptr: Pointer[_SDLRenderer] | |
fun ref _get_ptr(): Pointer[_SDLRenderer] => _ptr | |
new create(window': SDLWindow, index: I32, flags: U32) => | |
_window = window' | |
_ptr = @SDL_CreateRenderer(window'._get_ptr(), index, flags) | |
fun _final() => | |
None // TODO: SDL_DestroyRenderer but ensure window is not finalized first | |
fun ref begin_behavior() => _window.begin_behavior() | |
fun ref finish_behavior() => _window.finish_behavior() | |
fun ref clear() => @SDL_RenderClear(_ptr) | |
fun ref present() => @SDL_RenderPresent(_ptr) | |
fun ref set_draw_color(color: RGBA) => | |
@SDL_SetRenderDrawColor(_ptr, color.r, color.g, color.b, color.a) | |
fun ref fill_entire() => | |
@SDL_RenderFillRect(_ptr, NullablePointer[SDLRect].none()) | |
fun ref fill_rect(rect: SDLRect) => | |
var rect' = rect | |
@SDL_RenderFillRect(_ptr, NullablePointer[SDLRect](rect')) | |
class SDLEvent | |
let _ptr: Pointer[_SDLEvent] | |
fun ref _get_ptr(): Pointer[_SDLEvent] => _ptr | |
new create() => | |
_ptr = @new_sdl_event() | |
fun _final() => | |
@free_sdl_event(_ptr) | |
fun ref poll(): Bool => @sdl_poll_event(_ptr) != 0 | |
fun get_type(): U32 => @sdl_get_event_type(_ptr) | |
fun is_quit(): Bool => get_type() == 0x100 | |
primitive Sdl | |
fun init_video(): U32 => 0x00000020 | |
fun window_shown(): U32 => 0x00000004 | |
fun renderer_accelerated(): U32 => 0x00000002 | |
fun renderer_presentvsync(): U32 => 0x00000004 | |
fun windowpos_undefined(): I32 => | |
0x1FFF0000.op_or(0) | |
fun windowpos_centered(): U32 => | |
0x2FFF0000.op_or(0) | |
fun window_allow_highdpi(): U32 => 0x00002000 | |
fun init(flags: U32): I32 => | |
@SDL_Init(flags) | |
fun create_rgb_surface(flags: U32, width: I32, height: I32, depth: I32, rmask: U32, gmask: U32, bmask: U32, amask: U32): Pointer[_SDLSurface] => | |
@SDL_CreateRGBSurface(flags, width, height, depth, rmask, gmask, bmask, amask) | |
fun get_window_size(window: Pointer[_SDLWindow]): (I32, I32) => | |
var width: I32 = 0 | |
var height: I32 = 0 | |
@SDL_GetWindowSize(window, addressof width, addressof height) | |
(width, height) | |
fun free_surface(surface: Pointer[_SDLSurface]) => | |
@SDL_FreeSurface(surface) | |
fun get_renderer_output_size(renderer: Pointer[_SDLRenderer]): (I32, I32) => | |
var width: I32 = 0 | |
var height: I32 = 0 | |
@SDL_GetRendererOutputSize(renderer, addressof width, addressof height) | |
(width, height) | |
fun get_surface_info(surface: Pointer[_SDLSurface]): SDLSurfaceInfo => | |
let surface_info = SDLSurfaceInfo | |
@sdl_get_surface_info(NullablePointer[SDLSurfaceInfo](surface_info), surface) | |
surface_info | |
fun create_texture_from_surface(renderer: Pointer[_SDLRenderer], surface: Pointer[_SDLSurface]): Pointer[_SDLTexture] => | |
@SDL_CreateTextureFromSurface(renderer, surface) | |
fun destroy_texture(texture: Pointer[_SDLTexture]) => | |
@SDL_DestroyTexture(texture) | |
fun quit() => | |
@SDL_Quit() | |
fun delay(ms: U32) => | |
@SDL_Delay(ms) | |
// fun render_copy(renderer: Pointer[_SDLRenderer], texture: Pointer[_SDLTexture]) => | |
// @SDL_RenderCopy(renderer, texture, NullablePointer[_SDLRect].none(), NullablePointer[_SDLRect].none()) | |
fun poll_event_type(): U32 => | |
@sdl_poll_event_type() | |
fun poll_event(e: Pointer[_SDLEvent]): U32 => | |
@sdl_poll_event(e) | |
fun update_texture_from_surface(texture: Pointer[_SDLTexture], surface: Pointer[_SDLSurface]) => | |
@update_texture_from_surface(texture, surface) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL2/SDL.h> | |
Uint32 | |
sdl_poll_event_type(void) | |
{ | |
SDL_Event e; | |
SDL_PollEvent(&e); | |
return e.type; | |
} | |
Uint32 | |
sdl_poll_event(SDL_Event *e) | |
{ | |
return SDL_PollEvent(e); | |
} | |
Uint32 | |
sdl_get_event_type(SDL_Event *e) | |
{ | |
return e->type; | |
} | |
SDL_Event * | |
new_sdl_event(void) | |
{ | |
return (SDL_Event *)malloc(sizeof(SDL_Event)); | |
} | |
void | |
free_sdl_event(SDL_Event *e) | |
{ | |
free(e); | |
} | |
Uint32 | |
sdl_quit_event(void) | |
{ | |
return SDL_QUIT; | |
} | |
Uint32 | |
sdl_textureaccess_target(void) | |
{ | |
return SDL_TEXTUREACCESS_TARGET; | |
} | |
// Todo pass rect to define struct | |
void | |
update_texture_from_surface(SDL_Texture *texture, SDL_Surface *surface) | |
{ | |
SDL_UpdateTexture(texture, NULL, (unsigned char *)surface->pixels, surface->pitch); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use "time" | |
class UIFrameNotify is TimerNotify | |
let _ui: UI | |
new iso create(ui: UI) => _ui = ui | |
fun ref apply(timer: Timer, count: U64): Bool => | |
_ui.frame() | |
true | |
actor UI | |
let _renderer: SDLRenderer | |
let _event: SDLEvent | |
let _timers: Timers | |
let renderables: Array[Renderable] = Array[Renderable] | |
new create(window_title: String) => | |
Sdl.init(Sdl.init_video()) | |
let window = SDLWindow(window_title, Sdl.windowpos_undefined(), Sdl.windowpos_undefined(), 640, 480, Sdl.window_shown() or Sdl.window_allow_highdpi()) | |
_renderer = SDLRenderer(consume window, -1, Sdl.renderer_accelerated()) | |
_event = SDLEvent | |
_timers = Timers | |
_timers(Timer(UIFrameNotify(this), 5_000_000, 5_000_000)) | |
be dispose() => | |
_timers.dispose() | |
be access(fn: {(UI ref)} val) => | |
fn(this) | |
be frame() => | |
let quit = poll() | |
if quit then | |
dispose() | |
else | |
render() | |
end | |
fun ref poll(): Bool => | |
var quit: Bool = false | |
while _event.poll() do | |
if _event.is_quit() then | |
quit = true | |
end | |
end | |
quit | |
fun ref render() => | |
_renderer.begin_behavior() | |
_renderer.set_draw_color(RGBA(0, 0, 0, 0xff)) | |
_renderer.clear() | |
for r in renderables.values() do | |
r.render_next(_renderer) | |
end | |
_renderer.present() | |
_renderer.finish_behavior() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment