From b9592256c2d245df6910475fca532a65899560c7 Mon Sep 17 00:00:00 2001 From: Sijmen Schoon Date: Thu, 28 May 2020 00:28:20 +0200 Subject: [PATCH] Split up in smaller files --- src/sdl.zig | 212 ++++--------------------------------------- src/sdl/color.zig | 8 ++ src/sdl/renderer.zig | 103 +++++++++++++++++++++ src/sdl/surface.zig | 36 ++++++++ src/sdl/texture.zig | 15 +++ src/sdl/window.zig | 141 ++++++++++++++++++++++++++++ 6 files changed, 319 insertions(+), 196 deletions(-) create mode 100644 src/sdl/color.zig create mode 100644 src/sdl/renderer.zig create mode 100644 src/sdl/surface.zig create mode 100644 src/sdl/texture.zig create mode 100644 src/sdl/window.zig diff --git a/src/sdl.zig b/src/sdl.zig index c12fc15..38f99f6 100644 --- a/src/sdl.zig +++ b/src/sdl.zig @@ -1,6 +1,19 @@ const std = @import("std"); pub const c = @cImport(@cInclude("SDL2/SDL.h")); +pub const Color = @import("sdl/color.zig").Color; +pub const Texture = @import("sdl/texture.zig").Texture; +pub const Surface = @import("sdl/surface.zig").Surface; + +const window = @import("sdl/window.zig"); +pub const WindowPos = window.WindowPos; +pub const WindowFlags = window.WindowFlags; +pub const Window = window.Window; + +const renderer = @import("sdl/renderer.zig"); +pub const RendererFlags = renderer.RendererFlags; +pub const Renderer = renderer.Renderer; + pub fn getError() ?[*:0]const u8 { if (c.SDL_GetError()) |inner| { return @ptrCast([*:0]const u8, inner); @@ -8,187 +21,8 @@ pub fn getError() ?[*:0]const u8 { 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 fn glDrawableSize(self: Window) struct { w: i32, h: i32 } { - var width: c_int = 0; - var height: c_int = 0; - c.SDL_GL_GetDrawableSize(self.window, &width, &height); - return .{ .w = width, .h = height }; - } -}; - -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 { - std.debug.warn("Renderer.createTextureFromSurface: {}\n", .{getError()}); - 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; - } -}; +// TODO Convert to Zig enum. +pub const PixelFormatEnum = c.SDL_PixelFormatEnum; pub const PixelFormat = struct { pixelFormat: *c.SDL_PixelFormat, @@ -198,21 +32,7 @@ pub const PixelFormat = struct { } }; -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 const Rect = c.SDL_Rect; pub fn init() !void { // TODO Make this configurable diff --git a/src/sdl/color.zig b/src/sdl/color.zig new file mode 100644 index 0000000..0de1627 --- /dev/null +++ b/src/sdl/color.zig @@ -0,0 +1,8 @@ +pub const c = @cImport(@cInclude("SDL2/SDL.h")); + +pub const Color = struct { + r: u8, + g: u8, + b: u8, + a: u8 = c.SDL_ALPHA_OPAQUE, +}; diff --git a/src/sdl/renderer.zig b/src/sdl/renderer.zig new file mode 100644 index 0000000..3d55814 --- /dev/null +++ b/src/sdl/renderer.zig @@ -0,0 +1,103 @@ +const std = @import("std"); +const sdl = @import("../sdl.zig"); +const c = sdl.c; + +/// A structure of flags used when creating a rendering context. +pub const RendererFlags = struct { + /// The renderer is a software fallback. + pub const Software: u32 = c.SDL_RENDERER_SOFTWARE; + + /// The renderer uses hardware acceleration. + pub const Accelerated: u32 = c.SDL_RENDERER_ACCELERATED; + + /// Present is synchronized with the refresh rate. + pub const PresentVSync: u32 = c.SDL_RENDERER_PRESENTVSYNC; + + /// The renderer supports rendering to texture. + pub const TargetTexture: u32 = c.SDL_RENDERER_TARGETTEXTURE; +}; + +/// A structure that contains a rendering state. +pub const Renderer = struct { + renderer: *c.SDL_Renderer, + + /// Use this function to destroy the rendering context for a window and free associated + /// textures. + pub fn deinit(self: Renderer) void { + c.SDL_DestroyRenderer(self.renderer); + } + + /// Use this function to create a texture for a rendering context. + pub fn createTexture( + self: Renderer, + format: PixelFormatEnum, + access: TextureAccess, + w: i32, + h: i32, + ) !sdl.Texture { + var texture = c.SDL_CreateTextureFromSurface( + self.renderer, + @enumToInt(u32, format), + @enumToInt(i32, access), + w, + h, + ) orelse { + std.debug.warn("Renderer.createTexture: {}\n", .{sdl.getError()}); + return error.SdlError; + }; + + return sdl.Texture{ .texture = texture }; + } + + /// Use this function to create a texture from an existing surface. + pub fn createTextureFromSurface(self: Renderer, surface: sdl.Surface) !sdl.Texture { + var texture = c.SDL_CreateTextureFromSurface(self.renderer, surface.surface) orelse { + std.debug.warn("Renderer.createTextureFromSurface: {}\n", .{sdl.getError()}); + return error.SdlError; + }; + + return sdl.Texture{ .texture = texture }; + } + + /// Use this function to clear the current rendering target with the drawing color. + pub fn clear(self: Renderer) !void { + if (c.SDL_RenderClear(self.renderer) != 0) { + return error.SdlError; + } + } + + /// Use this function to copy a portion of the texture to the current rendering target. + pub fn copy( + self: Renderer, + texture: sdl.Texture, + srcrect: ?sdl.Rect, + dstrect: ?sdl.Rect, + ) !void { + var src = if (srcrect) |inner| &inner else null; + var dst = if (dstrect) |inner| &inner else null; + if (c.SDL_RenderCopy(self.renderer, texture.texture, src, dst) != 0) { + return error.SdlError; + } + } + + /// Use this function to update the screen with any rendering performed since the previous call. + pub fn present(self: Renderer) void { + c.SDL_RenderPresent(self.renderer); + } + + /// Use this function to set the color used for drawing operations (Rect, Line and Clear). + pub fn setDrawColor(self: Renderer, color: sdl.Color) !void { + if (c.SDL_SetRenderDrawColor(self.renderer, color.r, color.g, color.b, color.a) != 0) { + return error.SdlError; + } + } + + /// Use this function to fill a rectangle on the current rendering target with the drawing + /// color. + pub fn fillRect(self: Renderer, rect: ?sdl.Rect) !void { + var dst = if (rect) |inner| &inner else null; + if (c.SDL_RenderFillRect(self.renderer, dst) != 0) { + return error.SdlError; + } + } +}; diff --git a/src/sdl/surface.zig b/src/sdl/surface.zig new file mode 100644 index 0000000..e15bbe2 --- /dev/null +++ b/src/sdl/surface.zig @@ -0,0 +1,36 @@ +const sdl = @import("../sdl.zig"); +const c = sdl.c; + +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: ?sdl.Rect, color: u32) !void { + var dst = if (rect) |inner| &inner else null; + if (c.SDL_FillRect(self.surface, dst, 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; + } +}; diff --git a/src/sdl/texture.zig b/src/sdl/texture.zig new file mode 100644 index 0000000..ffec538 --- /dev/null +++ b/src/sdl/texture.zig @@ -0,0 +1,15 @@ +const sdl = @import("../sdl.zig"); +const c = sdl.c; + +/// A structure that contains an efficient, driver-specific representation of +/// pixel data. +/// +/// Can be created using sdl.Renderer.createTexture or +/// sdl.Renderer.createTextureFromSurface. +pub const Texture = struct { + texture: *c.SDL_Texture, + + pub fn deinit(self: Texture) void { + c.SDL_DestroyTexture(self.texture); + } +}; diff --git a/src/sdl/window.zig b/src/sdl/window.zig new file mode 100644 index 0000000..04d1625 --- /dev/null +++ b/src/sdl/window.zig @@ -0,0 +1,141 @@ +const std = @import("std"); +const sdl = @import("../sdl.zig"); + +pub const WindowPos = struct { + /// Used to indicate that you don't care what the window position is. + const Undefined: i32 = sdl.c.SDL_WINDOWPOS_UNDEFINED; + + /// Used to indicate that the window position should be centered. + const Centered: i32 = sdl.c.SDL_WINDOWPOS_CENTERED; +}; + +/// An enumeration of window states. +pub const WindowFlags = struct { + /// Fullscreen window. + pub const Fullscreen: i32 = sdl.sdl.c.SDL_WINDOW_FULLSCREEN; + + /// Window usable with OpenGL context. + pub const OpenGL: i32 = sdl.c.SDL_WINDOW_OPENGL; + + /// Window is visible. + pub const Shown: i32 = sdl.c.SDL_WINDOW_SHOWN; + + /// Window is not visible. + pub const Hidden: i32 = sdl.c.SDL_WINDOW_HIDDEN; + + /// No window decoration. + pub const Borderless: i32 = sdl.c.SDL_WINDOW_BORDERLESS; + + /// Window can be resized. + pub const Resizable: i32 = sdl.c.SDL_WINDOW_RESIZABLE; + + /// Window is minimized. + pub const Minimized: i32 = sdl.c.SDL_WINDOW_MINIMIZED; + + /// Window is maximized. + pub const Maximized: i32 = sdl.c.SDL_WINDOW_MAXIMIZED; + + /// Window has grabbed input focus. + pub const InputGrabbed: i32 = sdl.c.SDL_WINDOW_INPUT_GRABBED; + + /// Window has input focus. + pub const InputFocus: i32 = sdl.c.SDL_WINDOW_INPUT_FOCUS; + + /// Window has mouse focus. + pub const MouseFocus: i32 = sdl.c.SDL_WINDOW_MOUSE_FOCUS; + + /// Fullscreen window at the current desktop resolution. + pub const FullscreenDesktop: i32 = sdl.c.SDL_WINDOW_FULLSCREEN_DESKTOP; + + /// Window not created by SDL. + pub const Foreign: i32 = sdl.c.SDL_WINDOW_FOREIGN; + + /// Window should be created in high-DPI mode if supported. + /// On macOS NSHighResolutionCapable must be set true in the + /// application's Info.plist for this to have any effect. + pub const AllowHighDpi: i32 = sdl.c.SDL_WINDOW_ALLOW_HIGHDPI; + + /// Window has mouse captured (unrelated to INPUT_GRABBED). + pub const MouseCapture: i32 = sdl.c.SDL_WINDOW_MOUSE_CAPTURE; + + /// Window should always be above others (X11 only). + pub const AlwaysOnTop: i32 = sdl.c.SDL_WINDOW_ALWAYS_ON_TOP; + + /// Window should not be added to the taskbar (X11 only). + pub const SkipTaskbar: i32 = sdl.c.SDL_WINDOW_SKIP_TASKBAR; + + /// Window should be treated as a utility window (X11 only). + pub const Utility: i32 = sdl.c.SDL_WINDOW_UTILITY; + + /// Window should be treated as a tooltip (X11 only). + pub const Tooltip: i32 = sdl.c.SDL_WINDOW_TOOLTIP; + + /// Window should be treated as a popup menu (X11 only). + pub const PopupMenu: i32 = sdl.c.SDL_WINDOW_POPUP_MENU; + + /// Window usable for a Vulkan instance. + pub const Vulkan: i32 = sdl.c.SDL_WINDOW_VULKAN; + + /// Window usable for a Metal view. + pub const Metal: i32 = sdl.c.SDL_WINDOW_METAL; +}; + +/// The type used to identify a window +pub const Window = struct { + window: *sdl.c.SDL_Window, + + /// Use this function to create a window with the specified dimensions and flags. + pub fn init(title: []const u8, w: i32, h: i32, flags: u32) !Window { + return Window.initWithPos(title, WindowPos.Undefined, WindowPos.Undefined, w, h, flags); + } + + /// Use this function to create a window with the specified position, dimensions, and 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 = sdl.c.SDL_CreateWindow(title_, x, y, w, h, flags) orelse { + std.debug.warn("Window.initWithPos: {}\n", .{sdl.getError()}); + return error.SdlError; + }; + return Window{ .window = window }; + } + + /// Use this function to destroy a window. + pub fn deinit(self: *Window) void { + sdl.c.SDL_DestroyWindow(self.window); + } + + /// Use this function to get the SDL surface associated with the window. + pub fn surface(self: Window) !Surface { + var c = sdl.c.SDL_GetWindowSurface(self.window) orelse { + std.debug.warn("Window.surface: {}\n", .{sdl.getError()}); + return error.SdlError; + }; + return Surface{ .surface = c }; + } + + /// Use this function to copy the window surface to the screen. + pub fn updateSurface(self: Window) !void { + if (sdl.c.SDL_UpdateWindowSurface(self.window) != 0) { + std.debug.warn("Window.updateSurface: {}\n", .{sdl.getError()}); + return error.SdlError; + } + } + + /// Use this function to create a 2D rendering context for a window. + pub fn createRenderer(self: Window, index: ?i32, flags: u32) !sdl.Renderer { + var renderer = sdl.c.SDL_CreateRenderer(self.window, index orelse -1, flags) orelse { + std.debug.warn("Window.createRenderer: {}\n", .{sdl.getError()}); + return error.SdlError; + }; + return sdl.Renderer{ .renderer = renderer }; + } + + /// Use this function to get the size of a window's underlying drawable in + /// pixels (for use with glViewport). + pub fn glDrawableSize(self: Window) struct { w: i32, h: i32 } { + var width: c_int = 0; + var height: c_int = 0; + sdl.c.SDL_GL_GetDrawableSize(self.window, &width, &height); + return .{ .w = width, .h = height }; + } +};