timmoc laitinI
This commit is contained in:
commit
a2600208cd
5 changed files with 424 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
zig-cache/
|
27
build.zig
Normal file
27
build.zig
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
const Builder = @import("std").build.Builder;
|
||||||
|
|
||||||
|
pub fn build(b: *Builder) void {
|
||||||
|
// Standard target options allows the person running `zig build` to choose
|
||||||
|
// what target to build for. Here we do not override the defaults, which
|
||||||
|
// means any target is allowed, and the default is native. Other options
|
||||||
|
// for restricting supported target set are available.
|
||||||
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
|
// Standard release options allow the person running `zig build` to select
|
||||||
|
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
|
||||||
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
|
const exe = b.addExecutable("zite", "src/main.zig");
|
||||||
|
exe.linkSystemLibrary("c");
|
||||||
|
exe.linkSystemLibrary("SDL2");
|
||||||
|
exe.linkSystemLibrary("SDL2_ttf");
|
||||||
|
exe.setTarget(target);
|
||||||
|
exe.setBuildMode(mode);
|
||||||
|
exe.install();
|
||||||
|
|
||||||
|
const run_cmd = exe.run();
|
||||||
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
|
const run_step = b.step("run", "Run the app");
|
||||||
|
run_step.dependOn(&run_cmd.step);
|
||||||
|
}
|
93
src/main.zig
Normal file
93
src/main.zig
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const sdl = @import("sdl.zig");
|
||||||
|
const ttf = @import("ttf.zig");
|
||||||
|
|
||||||
|
const Ui = struct {
|
||||||
|
window: sdl.Window,
|
||||||
|
renderer: sdl.Renderer,
|
||||||
|
|
||||||
|
uiFont: ttf.Font,
|
||||||
|
codeFont: ttf.Font,
|
||||||
|
|
||||||
|
treeWidget: TreeWidget,
|
||||||
|
|
||||||
|
pub fn init() !Ui {
|
||||||
|
try sdl.init();
|
||||||
|
var window = try sdl.Window.init("Zite", 1280, 720, sdl.Window.Shown);
|
||||||
|
var renderer = try window.createRenderer(null, 0);
|
||||||
|
|
||||||
|
try ttf.init();
|
||||||
|
var uiFont = try ttf.Font.init("/usr/share/fonts/ubuntu/Ubuntu-R.ttf", 16);
|
||||||
|
var codeFont = try ttf.Font.init("/usr/share/fonts/TTF/Cascadia.ttf", 16);
|
||||||
|
|
||||||
|
var treeWidget = TreeWidget.init();
|
||||||
|
|
||||||
|
return Ui{
|
||||||
|
.window = window,
|
||||||
|
.renderer = renderer,
|
||||||
|
|
||||||
|
.uiFont = uiFont,
|
||||||
|
.codeFont = codeFont,
|
||||||
|
|
||||||
|
.treeWidget = treeWidget,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Ui) void {
|
||||||
|
self.uiFont.deinit();
|
||||||
|
self.codeFont.deinit();
|
||||||
|
ttf.quit();
|
||||||
|
|
||||||
|
self.renderer.deinit();
|
||||||
|
self.window.deinit();
|
||||||
|
sdl.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(self: Ui) !void {
|
||||||
|
while (sdl.Event.poll()) |event| {
|
||||||
|
var type_ = event.type_();
|
||||||
|
// std.debug.warn("event: {}\n", .{@tagName(type_)});
|
||||||
|
|
||||||
|
switch (type_) {
|
||||||
|
.Quit => return error.Exiting,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(self: Ui) !void {
|
||||||
|
try self.renderer.setDrawColor(.{ .r = 30, .g = 30, .b = 30 });
|
||||||
|
try self.renderer.clear();
|
||||||
|
|
||||||
|
try self.treeWidget.render(self);
|
||||||
|
|
||||||
|
self.renderer.present();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const TreeWidget = struct {
|
||||||
|
pub fn init() TreeWidget {
|
||||||
|
return .{};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(self: TreeWidget, ui: Ui) !void {
|
||||||
|
var surface = try ui.uiFont.renderBlended("Hello world", .{ .r = 255, .g = 255, .b = 255 });
|
||||||
|
defer surface.deinit();
|
||||||
|
|
||||||
|
var texture = try ui.renderer.createTextureFromSurface(surface);
|
||||||
|
defer texture.deinit();
|
||||||
|
|
||||||
|
var dst = sdl.Rect{ .w = surface.width(), .h = surface.height() };
|
||||||
|
try ui.renderer.copy(texture, null, dst);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var ui = try Ui.init();
|
||||||
|
defer ui.deinit();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
try ui.update();
|
||||||
|
try ui.render();
|
||||||
|
}
|
||||||
|
}
|
255
src/sdl.zig
Normal file
255
src/sdl.zig
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
pub const c = @cImport(@cInclude("SDL2/SDL.h"));
|
||||||
|
|
||||||
|
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 Window = struct {
|
||||||
|
pub const Shown: i32 = c.SDL_WINDOW_SHOWN;
|
||||||
|
|
||||||
|
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 return error.SdlError;
|
||||||
|
return Window{ .window = window };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *Window) void {
|
||||||
|
c.SDL_DestroyWindow(self.window);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn surface(self: Window) !Surface {
|
||||||
|
return Surface{
|
||||||
|
.surface = c.SDL_GetWindowSurface(self.window) orelse return error.SdlError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn updateSurface(self: Window) !void {
|
||||||
|
if (c.SDL_UpdateWindowSurface(self.window) != 0) {
|
||||||
|
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 return error.SdlError;
|
||||||
|
return Renderer{ .renderer = renderer };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 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 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);
|
||||||
|
}
|
||||||
|
};
|
48
src/ttf.zig
Normal file
48
src/ttf.zig
Normal 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: [:0]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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue