Initial commit

This commit is contained in:
Sijmen 2020-05-22 17:46:21 +02:00
commit 7f3dcce048
Signed by: vijfhoek
GPG Key ID: DAF7821E067D9C48
5 changed files with 463 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
zig-cache/

14
build.zig Normal file
View File

@ -0,0 +1,14 @@
const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const mode = b.standardReleaseOptions();
const lib = b.addStaticLibrary("zig-sdl", "src/main.zig");
lib.setBuildMode(mode);
lib.install();
var main_tests = b.addTest("src/main.zig");
main_tests.setBuildMode(mode);
const test_step = b.step("test", "Run library tests");
test_step.dependOn(&main_tests.step);
}

2
src/main.zig Normal file
View File

@ -0,0 +1,2 @@
pub const sdl = @import("sdl.zig");
pub const ttf = @import("ttf.zig");

398
src/sdl.zig Normal file
View File

@ -0,0 +1,398 @@
const std = @import("std");
pub const c = @cImport(@cInclude("SDL2/SDL.h"));
pub fn getError() ?[*:0]const u8 {
if (c.SDL_GetError()) |inner| {
return @ptrCast([*:0]const u8, inner);
}
return null;
}
pub const Color = struct {
r: u8,
g: u8,
b: u8,
a: u8 = c.SDL_ALPHA_OPAQUE,
};
pub const WindowPos = struct {
const Undefined: i32 = c.SDL_WINDOWPOS_UNDEFINED;
const Centered: i32 = c.SDL_WINDOWPOS_CENTERED;
};
pub const WindowFlags = struct {
pub const Fullscreen: i32 = c.SDL_WINDOW_FULLSCREEN;
pub const OpenGL: i32 = c.SDL_WINDOW_OPENGL;
pub const Shown: i32 = c.SDL_WINDOW_SHOWN;
pub const Hidden: i32 = c.SDL_WINDOW_HIDDEN;
pub const Borderless: i32 = c.SDL_WINDOW_BORDERLESS;
pub const Resizable: i32 = c.SDL_WINDOW_RESIZABLE;
pub const Minimized: i32 = c.SDL_WINDOW_MINIMIZED;
pub const InputGrabbed: i32 = c.SDL_WINDOW_INPUT_GRABBED;
pub const InputFocus: i32 = c.SDL_WINDOW_INPUT_FOCUS;
pub const MouseFocus: i32 = c.SDL_WINDOW_MOUSE_FOCUS;
pub const FullscreenDesktop: i32 = c.SDL_WINDOW_FULLSCREEN_DESKTOP;
pub const Foreign: i32 = c.SDL_WINDOW_FOREIGN;
pub const AllowHighDpi: i32 = c.SDL_WINDOW_ALLOW_HIGHDPI;
pub const MouseCapture: i32 = c.SDL_WINDOW_MOUSE_CAPTURE;
pub const AlwaysOnTop: i32 = c.SDL_WINDOW_ALWAYS_ON_TOP;
pub const SkipTaskbar: i32 = c.SDL_WINDOW_SKIP_TASKBAR;
pub const Utility: i32 = c.SDL_WINDOW_UTILITY;
pub const Tooltip: i32 = c.SDL_WINDOW_TOOLTIP;
pub const PopupMenu: i32 = c.SDL_WINDOW_POPUP_MENU;
pub const Vulkan: i32 = c.SDL_WINDOW_VULKAN;
pub const Metal: i32 = c.SDL_WINDOW_METAL;
};
pub const Window = struct {
window: *c.SDL_Window,
pub fn init(title: []const u8, w: i32, h: i32, flags: u32) !Window {
return Window.initWithPos(title, WindowPos.Undefined, WindowPos.Undefined, w, h, flags);
}
pub fn initWithPos(title: []const u8, x: i32, y: i32, w: i32, h: i32, flags: u32) !Window {
var title_ = @ptrCast([*c]const u8, title);
var window = c.SDL_CreateWindow(title_, x, y, w, h, flags) orelse {
std.debug.warn("Window.initWithPos: {}\n", .{getError()});
return error.SdlError;
};
return Window{ .window = window };
}
pub fn deinit(self: *Window) void {
c.SDL_DestroyWindow(self.window);
}
pub fn surface(self: Window) !Surface {
var c = c.SDL_GetWindowSurface(self.window) orelse {
std.debug.warn("Window.surface: {}\n", .{getError()});
return error.SdlError;
};
return Surface{ .surface = c };
}
pub fn updateSurface(self: Window) !void {
if (c.SDL_UpdateWindowSurface(self.window) != 0) {
std.debug.warn("Window.updateSurface: {}\n", .{getError()});
return error.SdlError;
}
}
pub fn createRenderer(self: Window, index: ?i32, flags: u32) !Renderer {
var renderer = c.SDL_CreateRenderer(self.window, index orelse -1, flags) orelse {
std.debug.warn("Window.createRenderer: {}\n", .{getError()});
return error.SdlError;
};
return Renderer{ .renderer = renderer };
}
};
pub const RendererFlags = struct {
pub const Software: u32 = c.SDL_RENDERER_SOFTWARE;
pub const Accelerated: u32 = c.SDL_RENDERER_ACCELERATED;
pub const PresentVSync: u32 = c.SDL_RENDERER_PRESENTVSYNC;
pub const TargetTexture: u32 = c.SDL_RENDERER_TARGETTEXTURE;
};
pub const Renderer = struct {
renderer: *c.SDL_Renderer,
pub fn deinit(self: Renderer) void {
c.SDL_DestroyRenderer(self.renderer);
}
pub fn createTextureFromSurface(self: Renderer, surface: Surface) !Texture {
var texture = c.SDL_CreateTextureFromSurface(self.renderer, surface.surface) orelse return error.SdlError;
return Texture{ .texture = texture };
}
pub fn clear(self: Renderer) !void {
if (c.SDL_RenderClear(self.renderer) != 0) {
return error.SdlError;
}
}
pub fn copy(self: Renderer, texture: Texture, srcrect: ?Rect, dstrect: ?Rect) !void {
var src = if (srcrect) |inner| &inner.c() else null;
var dst = if (dstrect) |inner| &inner.c() else null;
if (c.SDL_RenderCopy(self.renderer, texture.texture, src, dst) != 0) {
return error.SdlError;
}
}
pub fn present(self: Renderer) void {
c.SDL_RenderPresent(self.renderer);
}
pub fn setDrawColor(self: Renderer, color: Color) !void {
if (c.SDL_SetRenderDrawColor(self.renderer, color.r, color.g, color.b, color.a) != 0) {
return error.SdlError;
}
}
pub fn fillRect(self: Renderer, rect: ?Rect) !void {
var dst = if (rect) |inner| &inner.c() else null;
if (c.SDL_RenderFillRect(self.renderer, dst) != 0) {
return error.SdlError;
}
}
};
pub const Texture = struct {
texture: *c.SDL_Texture,
pub fn deinit(self: Texture) void {
c.SDL_DestroyTexture(self.texture);
}
};
pub const Surface = struct {
surface: *c.SDL_Surface,
pub fn initFromBmp(path: []const u8) !Surface {
var path_ = @ptrCast([*c]const u8, path);
var rw = c.SDL_RWFromFile(path_, "rb") orelse return error.SdlError;
var surface = c.SDL_LoadBMP_RW(rw, 1) orelse return error.SdlError;
return Surface{ .surface = surface };
}
pub fn deinit(self: Surface) void {
c.SDL_FreeSurface(self.surface);
}
pub fn fillRect(self: Surface, rect: [*c]const c.SDL_Rect, color: u32) !void {
if (c.SDL_FillRect(self.surface, rect, color) != 0) {
return error.SdlError;
}
}
pub fn format(self: Surface) PixelFormat {
return PixelFormat{ .pixelFormat = self.surface.*.format };
}
pub fn width(self: Surface) i32 {
return self.surface.w;
}
pub fn height(self: Surface) i32 {
return self.surface.h;
}
};
pub const PixelFormat = struct {
pixelFormat: *c.SDL_PixelFormat,
pub fn mapRgb(self: PixelFormat, r: u8, g: u8, b: u8) u32 {
return c.SDL_MapRGB(self.pixelFormat, r, g, b);
}
};
pub const Rect = struct {
x: i32 = 0,
y: i32 = 0,
w: i32 = 0,
h: i32 = 0,
fn c(self: Rect) c.SDL_Rect {
return .{
.x = self.x,
.y = self.y,
.w = self.w,
.h = self.h,
};
}
};
pub fn init() !void {
// TODO Make this configurable
if (c.SDL_Init(c.SDL_INIT_EVERYTHING) != 0) {
return error.SdlError;
}
}
pub fn quit() void {
c.SDL_Quit();
}
pub fn delay(ms: u32) void {
c.SDL_Delay(ms);
}
pub const EventType = enum(u32) {
FirstEvent = 0,
Quit = 0x100,
AppTerminating,
AppLowMemory,
AppWillEnterBackground,
AppDidEnterBackground,
AppWillEnterForeground,
AppDidEnterForeground,
LocaleChanged,
DisplayEvent = 0x150,
WindowEvent = 0x200,
SysWmEvent,
KeyDown = 0x300,
KeyUp,
TextEditing,
TextInput,
KeymapChanged,
MouseMotion = 0x400,
MouseButtonDown,
MouseButtonUp,
MouseWheel,
JoyAxisMotion = 0x600,
JoyBallMotion,
JoyHatMotion,
JoyButtonDown,
JoyButtonUp,
JoyDeviceAdded,
JoyDeviceRemoved,
ControllerAxisMotion = 0x650,
ControllerButtonDown,
ControllerButtonUp,
ControllerDeviceAdded,
ControllerDeviceRemoved,
ControllerDeviceRemapped,
FingerDown = 0x700,
FingerUp,
FingerMotion,
DollarGesture = 0x800,
DollarRecord,
MultiGesture,
ClipboardUpate = 0x900,
DropFile = 0x1000,
DropText,
DropBegin,
DropComplete,
AudioDeviceAdded = 0x1100,
AudioDeviceRemoved,
SensorUpdate = 0x1200,
RenderTargetsReset = 0x2000,
RenderDeviceReset,
UserEvent = 0x8000,
LastEvent = 0xFFFF,
_,
};
pub const MouseMotionEvent = struct {
timestamp: u32,
windowId: u32,
which: u32,
state: u32,
x: i32,
y: i32,
xrel: i32,
yrel: i32,
};
pub const Event = struct {
event: c.SDL_Event,
pub fn poll() ?Event {
var event = c.SDL_Event{ .type = 0 };
if (c.SDL_PollEvent(&event) == 0) {
return null;
}
return Event{ .event = event };
}
pub fn type_(self: Event) EventType {
return @intToEnum(EventType, self.event.type);
}
pub fn mouseMotion(self: Event) ?MouseMotionEvent {
if (self.type_() != .MouseMotion) {
return null;
}
var inner = self.event.motion;
return MouseMotionEvent{
.timestamp = inner.timestamp,
.windowId = inner.windowID,
.which = inner.which,
.state = inner.state,
.x = inner.x,
.y = inner.y,
.xrel = inner.xrel,
.yrel = inner.yrel,
};
}
};
pub const SystemCursor = extern enum {
Arrow = c.SDL_SYSTEM_CURSOR_ARROW,
IBeam = c.SDL_SYSTEM_CURSOR_IBEAM,
Wait = c.SDL_SYSTEM_CURSOR_WAIT,
Crosshair = c.SDL_SYSTEM_CURSOR_CROSSHAIR,
WaitArrow = c.SDL_SYSTEM_CURSOR_WAITARROW,
SizeNwSe = c.SDL_SYSTEM_CURSOR_SIZENWSE,
SizeNeSw = c.SDL_SYSTEM_CURSOR_SIZENESW,
SizeWE = c.SDL_SYSTEM_CURSOR_SIZEWE,
SizeNS = c.SDL_SYSTEM_CURSOR_SIZENS,
SizeAll = c.SDL_SYSTEM_CURSOR_SIZEALL,
No = c.SDL_SYSTEM_CURSOR_NO,
Hand = c.SDL_SYSTEM_CURSOR_HAND,
};
pub const Cursor = struct {
cursor: *c.SDL_Cursor,
pub fn initFromSystemCursor(id: SystemCursor) !Cursor {
var cursor = c.SDL_CreateSystemCursor(@intToEnum(c.SDL_SystemCursor, @enumToInt(id))) orelse {
std.debug.warn("Window.initWithPos: {}\n", .{getError()});
return error.SdlError;
};
return Cursor{ .cursor = cursor };
}
pub fn deinit(self: Cursor) void {
c.SDL_FreeCursor(self.cursor);
}
pub fn activate(self: Cursor) void {
c.SDL_SetCursor(self.cursor);
}
};
pub const PerformanceCounter = struct {
counter: u64,
pub fn init(counter: u64) PerformanceCounter {
return PerformanceCounter{ .counter = counter };
}
pub fn now() PerformanceCounter {
return PerformanceCounter{ .counter = c.SDL_GetPerformanceCounter() };
}
pub fn elapsed(self: PerformanceCounter) PerformanceCounter {
return PerformanceCounter{
.counter = c.SDL_GetPerformanceCounter() - self.counter,
};
}
pub fn frequency() u64 {
return c.SDL_GetPerformanceFrequency();
}
pub fn ms(self: PerformanceCounter) f64 {
return @intToFloat(f64, self.counter) * 1000 / @intToFloat(f64, PerformanceCounter.frequency());
}
};

48
src/ttf.zig Normal file
View File

@ -0,0 +1,48 @@
const std = @import("std");
const sdl = @import("sdl.zig");
pub const c = @cImport(@cInclude("SDL2/SDL_ttf.h"));
pub fn init() !void {
if (c.TTF_Init() == -1) {
return error.SdlTtfError;
}
}
pub fn quit() void {
c.TTF_Quit();
}
pub fn getError() ?[*:0]const u8 {
if (c.TTF_GetError()) |inner| {
return @ptrCast([*:0]const u8, inner);
}
return null;
}
pub const Font = struct {
font: *c.TTF_Font,
pub fn init(path: []const u8, size: i32) !Font {
var path_ = @ptrCast([*c]const u8, path);
if (c.TTF_OpenFont(path_, size)) |inner| {
return Font{ .font = inner };
} else {
std.debug.warn("Font.init: {}\n", .{getError()});
return error.SdlTtfError;
}
}
pub fn deinit(self: Font) void {
c.TTF_CloseFont(self.font);
}
pub fn renderBlended(self: Font, text: []const u8, color: sdl.Color) !sdl.Surface {
var cText = @ptrCast([*c]const u8, text);
if (c.TTF_RenderUTF8_Blended(self.font, cText, @bitCast(c.SDL_Color, color))) |surface| {
return sdl.Surface{ .surface = @ptrCast(*sdl.c.SDL_Surface, surface) };
} else {
std.debug.warn("Font.renderBlended: {}\n", .{getError()});
return error.SdlTtfError;
}
}
};