tins2023/allegro/allegro.zig

734 lines
20 KiB
Zig
Raw Normal View History

const std = @import("std");
pub const c = @import("c.zig").c;
pub const Bitmap = struct {
native: *c.ALLEGRO_BITMAP,
pub fn destroy(self: Bitmap) void {
destroyBitmap(self);
}
pub fn draw(self: Bitmap, x: f32, y: f32) void {
drawBitmap(self, x, y, DrawFlags{});
}
pub fn drawCentered(self: Bitmap, x: f32, y: f32) void {
self.draw(x - 0.5 * @intToFloat(f32, self.width()), y - 0.5 * @intToFloat(f32, self.height()), DrawFlags{});
}
pub fn drawCenteredScaledUniform(self: Bitmap, x: f32, y: f32, s: f32) void {
const w = s * @intToFloat(f32, self.width());
const h = s * @intToFloat(f32, self.height());
self.drawScaled(x - 0.5 * w, y - 0.5 * h, w, h);
}
pub fn drawScaled(self: Bitmap, x: f32, y: f32, w: f32, h: f32) void {
drawScaledBitmap(self, 0, 0, @intToFloat(f32, self.width()), @intToFloat(f32, self.height()), x, y, w, h, DrawFlags{});
}
pub fn drawScaledUniform(self: Bitmap, x: f32, y: f32, s: f32) void {
const sourceW = @intToFloat(f32, self.width());
const sourceH = @intToFloat(f32, self.height());
const scaledW = s * sourceW;
const scaledH = s * sourceH;
drawScaledBitmap(self, 0, 0, sourceW, sourceH, x, y, scaledW, scaledH, DrawFlags{});
}
pub fn drawTinted(self: Bitmap, tint: Color, x: f32, y: f32) void {
drawTintedBitmap(self, tint, x, y, DrawFlags{});
}
pub fn drawTintedCentered(self: Bitmap, tint: Color, x: f32, y: f32) void {
self.drawTinted(tint, x - 0.5 * @intToFloat(f32, self.width()), y - 0.5 * @intToFloat(f32, self.height()), DrawFlags{});
}
pub fn drawTintedCenteredScaled(self: Bitmap, tint: Color, x: f32, y: f32, s: f32) void {
const w = s * @intToFloat(f32, self.width());
const h = s * @intToFloat(f32, self.height());
self.drawTintedScaled(tint, x - 0.5 * w, y - 0.5 * h, w, h);
}
pub fn drawTintedScaled(self: Bitmap, tint: Color, x: f32, y: f32, w: f32, h: f32) void {
drawTintedScaledBitmap(self, tint, 0, 0, @intToFloat(f32, self.width()), @intToFloat(f32, self.height()), x, y, w, h, DrawFlags{});
}
pub fn drawTintedScaledUniform(self: Bitmap, tint: Color, x: f32, y: f32, s: f32) void {
const sourceW = @intToFloat(f32, self.width());
const sourceH = @intToFloat(f32, self.height());
const scaledW = s * sourceW;
const scaledH = s * sourceH;
drawTintedScaledBitmap(self, tint, 0, 0, sourceW, sourceH, x, y, scaledW, scaledH, DrawFlags{});
}
pub fn height(self: Bitmap) i32 {
return getBitmapHeight(self);
}
pub fn sub(self: Bitmap, x: i32, y: i32, w: i32, h: i32) !Bitmap {
return createSubBitmap(self, x, y, w, h);
}
pub fn width(self: Bitmap) i32 {
return getBitmapWidth(self);
}
};
pub const Color = struct {
native: c.ALLEGRO_COLOR,
fn hexToU4(hex: u8) u4 {
return switch (hex) {
'0'...'9' => @intCast(u4, hex - '0'),
'a'...'f' => @intCast(u4, hex - 'a') + 10,
'A'...'F' => @intCast(u4, hex - 'A') + 10,
else => unreachable,
};
}
pub fn initFromHex(hex: []const u8) Color {
if (hex.len == 0) unreachable;
const left: usize = if (hex[0] == '#') 1 else 0;
if (hex.len < left + 6) unreachable;
const r = (@intCast(u8, hexToU4(hex[left])) << 4) + @intCast(u8, hexToU4(hex[left + 1]));
const g = (@intCast(u8, hexToU4(hex[left + 2])) << 4) + @intCast(u8, hexToU4(hex[left + 3]));
const b = (@intCast(u8, hexToU4(hex[left + 4])) << 4) + @intCast(u8, hexToU4(hex[left + 5]));
if (hex.len < left + 8) {
return mapRgb(r, g, b);
}
const a = (@intCast(u8, hexToU4(hex[left + 6])) << 4) + @intCast(u8, hexToU4(hex[left + 7]));
return mapRgba(r, g, b, a);
}
};
pub const Display = struct {
native: *c.ALLEGRO_DISPLAY,
pub fn destroy(self: Display) void {
destroyDisplay(self);
}
pub fn eventSource(self: Display) EventSource {
return getDisplayEventSource(self);
}
pub fn height(self: Display) i32 {
return getDisplayHeight(self);
}
pub fn width(self: Display) i32 {
return getDisplayWidth(self);
}
};
pub const DrawFlags = packed struct(c_int) {
FLIP_HORIZONTAL: bool = false, // 0x00001
FLIP_VERTICAL: bool = false, // 0x00002
_NOT_USED: u30 = 0,
};
pub const DrawTextFlags = enum(c_int) {
NO_KERNING = -1,
ALIGN_LEFT = 0,
ALIGN_CENTER = 1,
ALIGN_RIGHT = 2,
ALIGN_LEFT_INTEGER = 4,
ALIGN_CENTER_INTEGER = 5,
ALIGN_RIGHT_INTEGER = 6,
};
pub const Event = c.ALLEGRO_EVENT;
pub const EventQueue = struct {
native: *c.ALLEGRO_EVENT_QUEUE,
pub fn destroy(self: EventQueue) void {
destroyEventQueue(self);
}
pub fn drop(self: EventQueue) void {
dropNextEvent(self);
}
pub fn flush(self: EventQueue) void {
flushEventQueue(self);
}
pub fn get(self: EventQueue, event: *Event) bool {
return getNextEvent(self, event);
}
pub fn isEmpty(self: EventQueue) bool {
return isEventQueueEmpty(self);
}
pub fn peek(self: EventQueue, event: *Event) void {
peekNextEvent(self, event);
}
pub fn register(self: EventQueue, source: EventSource) void {
registerEventSource(self, source);
}
pub fn registerDisplay(self: EventQueue, display: Display) void {
self.register(display.eventSource());
}
pub fn registerKeyboard(self: EventQueue) void {
self.register(getKeyboardEventSource());
}
pub fn registerMouse(self: EventQueue) void {
self.register(getMouseEventSource());
}
pub fn registerTimer(self: EventQueue, timer: Timer) void {
self.register(timer);
}
pub fn unregister(self: EventQueue, source: EventSource) void {
unregisterEventSource(self, source);
}
pub fn unregisterDisplay(self: EventQueue, display: Display) void {
self.unregister(display.eventSource());
}
pub fn wait(self: EventQueue, event: *Event) void {
waitForEvent(self, event);
}
};
pub const EventSource = struct {
native: *c.ALLEGRO_EVENT_SOURCE,
};
pub const File = struct {
native: *c.ALLEGRO_FILE,
pub fn close(file: File) void {
fclose(file);
}
};
pub const Font = struct {
native: *c.ALLEGRO_FONT,
pub fn destroy(self: Font) void {
destroyFont(self);
}
pub fn draw(self: Font, color: Color, x: f32, y: f32, flags: DrawTextFlags, text: [*:0]const u8) void {
drawText(self, color, x, y, flags, text);
}
pub fn textWidth(self: Font, text: [*:0]const u8) i32 {
return getTextWidth(self, text);
}
};
pub const LoadBitmapFlags = packed struct(c_int) {
_NOT_USED_1: bool = false,
KEEP_BITMAP_FORMAT: bool = false, // 0x0002 // was a bitmap flag in 5.0
_NOT_USED_2: u7 = 0,
NO_PREMULTIPLIED_ALPHA: bool = false, // 0x0200 // was a bitmap flag in 5.0
_NOT_USED_3: bool = false,
KEEP_INDEX: bool = false, // 0x0800
_NOT_USED_4: u20 = 0,
};
pub const LoadTtfFontFlags = packed struct(c_int) {
NO_KERNING: bool = false,
MONOCHROME: bool = false,
NO_AUTOHINT: bool = false,
_NOT_USED: u29 = 0,
};
pub const NewBitmapFlags = packed struct(c_int) {
MEMORY_BITMAP: bool = false, // 0x0001,
_KEEP_BITMAP_FORMAT: bool = false, // 0x0002,
FORCE_LOCKING: bool = false, // 0x0004,
NO_PRESERVE_TEXTURE: bool = false, // 0x0008,
_ALPHA_TEST: bool = false, // 0x0010,
_INTERNAL_OPENGL: bool = false, // 0x0020,
MIN_LINEAR: bool = false, // 0x0040,
MAG_LINEAR: bool = false, // 0x0080,
MIPMAP: bool = false, // 0x0100,
_NO_PREMULTIPLIED_ALPHA: bool = false, // 0x0200,
VIDEO_BITMAP: bool = false, // 0x0400,
_NOT_USED_1: bool = false, // 0x0800
CONVERT_BITMAP: bool = false, // 0x1000,
_NOT_USED_4: u19 = 0,
};
pub const NewDisplayFlags = packed struct(c_int) {
WINDOWED: bool = false,
FULLSCREEN: bool = false,
OPENGL: bool = false,
DIRECT3D_INTERNAL: bool = false,
RESIZABLE: bool = false,
FRAMELESS: bool = false,
GENERATE_EXPOSE_EVENTS: bool = false,
OPENGL_3_0: bool = false,
OPENGL_FORWARD_COMPATIBLE: bool = false,
FULLSCREEN_WINDOW: bool = false,
MINIMIZED: bool = false,
PROGRAMMABLE_PIPELINE: bool = false,
GTK_TOPLEVEL_INTERNAL: bool = false,
MAXIMIZED: bool = false,
OPENGL_ES_PROFILE: bool = false,
OPENGL_CORE_PROFILE: bool = false,
_NOT_USED: u16 = 0,
};
pub const NewDisplayOption = enum(c_int) {
RED_SIZE, // 0
GREEN_SIZE, // 1
BLUE_SIZE, // 2
ALPHA_SIZE, // 3
RED_SHIFT, // 4
GREEN_SHIFT, // 5
BLUE_SHIFT, // 6
ALPHA_SHIFT, // 7
ACC_RED_SIZE, // 8
ACC_GREEN_SIZE, // 9
ACC_BLUE_SIZE, // 10
ACC_ALPHA_SIZE, // 11
STEREO, // 12
AUX_BUFFERS, // 13
COLOR_SIZE, // 14
DEPTH_SIZE, // 15
STENCIL_SIZE, // 16
SAMPLE_BUFFERS, // 17
SAMPLES, // 18
RENDER_METHOD, // 19
FLOAT_COLOR, // 20
FLOAT_DEPTH, // 21
SINGLE_BUFFER, // 22
SWAP_METHOD, // 23
COMPATIBLE_DISPLAY, // 24
UPDATE_DISPLAY_REGION, // 25
VSYNC, // 26
MAX_BITMAP_SIZE, // 27
SUPPORT_NPOT_BITMAP, // 28
CAN_DRAW_INTO_BITMAP, // 29
SUPPORT_SEPARATE_ALPHA, // 30
AUTO_CONVERT_BITMAPS, // 31
SUPPORTED_ORIENTATIONS, // 32
OPENGL_MAJOR_VERSION, // 33
OPENGL_MINOR_VERSION, // 34
DEFAULT_SHADER_PLATFORM, // 35
};
pub const OptionImportance = enum(c_int) {
DONTCARE, // 0
REQUIRE, // 1
SUGGEST, // 2
};
pub const PixelFormat = enum(c_int) {
ANY, // 0
ANY_NO_ALPHA, // 1
ANY_WITH_ALPHA, // 2
ANY_15_NO_ALPHA, // 3
ANY_16_NO_ALPHA, // 4
ANY_16_WITH_ALPHA, // 5
ANY_24_NO_ALPHA, // 6
ANY_32_NO_ALPHA, // 7
ANY_32_WITH_ALPHA, // 8
ARGB_8888, // 9
RGBA_8888, // 10
ARGB_4444, // 11
RGB_888, // 12 // 24 bit format
RGB_565, // 13
RGB_555, // 14
RGBA_5551, // 15
ARGB_1555, // 16
ABGR_8888, // 17
XBGR_8888, // 18
BGR_888, // 19 // 24 bit format
BGR_565, // 20
BGR_555, // 21
RGBX_8888, // 22
XRGB_8888, // 23
ABGR_F32, // 24
ABGR_8888_LE, // 25
RGBA_4444, // 26
SINGLE_CHANNEL_8, // 27
COMPRESSED_RGBA_DXT1, // 28
COMPRESSED_RGBA_DXT3, // 29
COMPRESSED_RGBA_DXT5, // 30
ALLEGRO_NUM_PIXEL_FORMATS,
};
pub const Timer = struct {
native: *c.ALLEGRO_TIMER,
pub fn destroy(self: Timer) void {
destroyTimer(self);
}
pub fn eventSource(self: Timer) EventSource {
return getTimerEventSource(self);
}
pub fn start(self: Timer) void {
startTimer(self);
}
};
pub fn acknowledgeResize(display: Display) bool {
return c.al_acknowledge_resize(display.native);
}
pub fn clearToColor(color: Color) void {
c.al_clear_to_color(color.native);
}
pub fn convertMemoryBitmaps() void {
c.al_convert_memory_bitmaps();
}
pub fn createBitmap(width: i32, height: i32) !Bitmap {
const bitmap = c.al_create_bitmap(width, height);
if (bitmap) |native| {
return Bitmap{ .native = native };
}
return error.FailedToCreateBitmap;
}
pub fn createDisplay(width: i32, height: i32) !Display {
const display = c.al_create_display(width, height);
if (display) |native| {
return Display{ .native = native };
}
return error.FailedToCreateDisplay;
}
pub fn createEventQueue() !EventQueue {
const queue = c.al_create_event_queue();
if (queue) |native| {
return EventQueue{ .native = native };
}
return error.FailedToCreateEventQueue;
}
pub fn createSubBitmap(bitmap: Bitmap, x: i32, y: i32, width: i32, height: i32) !Bitmap {
const sub = c.al_create_sub_bitmap(bitmap.native, x, y, width, height);
if (sub) |native| {
return Bitmap{ .native = native };
}
return error.FailedToCreateSubBitmap;
}
pub fn createTimer(interval: f32) !Timer {
const timer = c.al_create_timer(interval);
if (timer) |native| {
return Timer{ .native = native };
}
return error.FailedToCreateTimer;
}
pub fn destroyBitmap(bitmap: Bitmap) void {
c.al_destroy_bitmap(bitmap.native);
}
pub fn destroyDisplay(display: Display) void {
c.al_destroy_display(display.native);
}
pub fn destroyEventQueue(queue: EventQueue) void {
c.al_destroy_event_queue(queue.native);
}
pub fn destroyFont(font: Font) void {
c.al_destroy_font(font.native);
}
pub fn destroyTimer(timer: Timer) void {
c.al_destroy_timer(timer.native);
}
pub fn drawBitmap(bitmap: Bitmap, dx: f32, dy: f32, flags: DrawFlags) void {
c.al_draw_bitmap(bitmap.native, dx, dy, @bitCast(c_int, flags));
}
pub fn drawScaledBitmap(bitmap: Bitmap, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32, flags: DrawFlags) void {
c.al_draw_scaled_bitmap(bitmap.native, sx, sy, sw, sh, dx, dy, dw, dh, @bitCast(c_int, flags));
}
pub fn drawText(font: Font, color: Color, x: f32, y: f32, flags: DrawTextFlags, text: [*:0]const u8) void {
c.al_draw_text(font.native, color.native, x, y, @enumToInt(flags), text);
}
pub fn drawTintedBitmap(bitmap: Bitmap, tint: Color, dx: f32, dy: f32, flags: DrawFlags) void {
c.al_draw_tinted_bitmap(bitmap.native, tint.native, dx, dy, @bitCast(c_int, flags));
}
pub fn drawTintedScaledBitmap(bitmap: Bitmap, tint: Color, sx: f32, sy: f32, sw: f32, sh: f32, dx: f32, dy: f32, dw: f32, dh: f32, flags: DrawFlags) void {
c.al_draw_tinted_scaled_bitmap(bitmap.native, tint.native, sx, sy, sw, sh, dx, dy, dw, dh, @bitCast(c_int, flags));
}
pub fn dropNextEvent(queue: EventQueue) bool {
return c.al_drop_next_event(queue.native);
}
pub fn fclose(file: File) bool {
return c.al_fclose(file.native);
}
pub fn flipDisplay() void {
c.al_flip_display();
}
pub fn flushEventQueue(queue: EventQueue) void {
c.al_flush_event_queue(queue.native);
}
pub fn isEventQueueEmpty(queue: EventQueue) bool {
return c.al_is_event_queue_empty(queue.native);
}
pub fn getBackbuffer(display: Display) !Bitmap {
const bitmap = c.al_get_backbuffer(display.native);
if (bitmap) |native| {
return Bitmap{ .native = native };
}
return error.FailedToGetBackBufferForDisplay;
}
pub fn getBitmapHeight(bitmap: Bitmap) c_int {
return c.al_get_bitmap_height(bitmap.native);
}
pub fn getBitmapWidth(bitmap: Bitmap) c_int {
return c.al_get_bitmap_width(bitmap.native);
}
pub fn getCurrentDisplay() !Display {
const display = c.al_get_current_display();
if (display) |native| {
return Display{ .native = native };
}
return error.NoCurrentDisplay;
}
pub fn getDisplayEventSource(display: Display) EventSource {
return EventSource{ .native = c.al_get_display_event_source(display.native) };
}
pub fn getDisplayFlags(display: Display) NewDisplayFlags {
return @bitCast(NewDisplayFlags, c.al_get_display_flags(display.native));
}
pub fn getDisplayHeight(display: Display) i32 {
return c.al_get_display_height(display.native);
}
pub fn getDisplayWidth(display: Display) i32 {
return c.al_get_display_width(display.native);
}
pub fn getFontAscent(font: Font) i32 {
return c.al_get_font_ascent(font.native);
}
pub fn getFontDescent(font: Font) i32 {
return c.al_get_font_descent(font.native);
}
pub fn getFontLineHeight(font: Font) i32 {
return c.al_get_font_line_height(font.native);
}
pub fn getKeyboardEventSource() EventSource {
return EventSource{ .native = c.al_get_keyboard_event_source() };
}
pub fn getNewBitmapFlags() NewBitmapFlags {
return c.al_set_new_bitmap_flags();
}
pub fn getNewDisplayOption(option: NewDisplayOption, importance: *OptionImportance) c_int {
return c.al_get_new_display_option(@enumToInt(option), @ptrCast(*c_int, importance));
}
pub fn getNewBitmapFormat() PixelFormat {
return c.al_set_new_bitmap_format();
}
pub fn getNewDisplayFlags() NewDisplayFlags {
return c.al_get_new_display_flags();
}
pub fn getNextEvent(queue: EventQueue, event: *Event) bool {
return c.al_get_next_event(queue.native, event);
}
pub fn getMouseEventSource() EventSource {
return EventSource{ .native = c.al_get_mouse_event_source() };
}
pub fn getTextWidth(font: Font, text: [*:0]const u8) void {
c.al_get_text_width(font.native, &text[0]);
}
pub fn getTime() f64 {
return c.al_get_time();
}
pub fn getTimerEventSource(timer: Timer) EventSource {
return EventSource{ .native = c.al_get_timer_event_source(timer.native) };
}
pub fn init() bool {
return c.al_init();
}
pub fn initFontAddon() bool {
return c.al_init_font_addon();
}
pub fn initImageAddon() bool {
return c.al_init_image_addon();
}
pub fn initTtfAddon() bool {
return c.al_init_ttf_addon();
}
pub fn installKeyboard() bool {
return c.al_install_keyboard();
}
pub fn installMouse() bool {
return c.al_install_mouse();
}
pub fn loadBitmap(path: [*:0]const u8) !Bitmap {
const bitmap = c.al_load_bitmap(path);
if (bitmap) |native| {
return Bitmap{ .native = native };
}
return error.FailedToLoadBitmap;
}
pub fn loadBitmapF(file: File, ident: []const u8) !Bitmap {
const bitmap = c.al_load_bitmap_f(file.native, &ident[0]);
if (bitmap) |native| {
return Bitmap{ .native = native };
}
return error.FailedToLoadBitmap;
}
pub fn loadBitmapFont(path: [*:0]const u8) !Font {
const font = c.al_load_bitmap_font(path);
if (font) |native| {
return Font{ .native = native };
}
return error.FailedToLoadFont;
}
pub fn loadFont(path: [*:0]const u8, size: i32, flags: c_int) !Font {
const font = c.al_load_font(path, size, flags);
if (font) |native| {
return Font{ .native = native };
}
return error.FailedToLoadFont;
}
pub fn loadTtfFont(path: [*:0]const u8, size: i32, flags: LoadTtfFontFlags) !Font {
const font = c.al_load_ttf_font(path, size, @bitCast(c_int, flags));
if (font) |native| {
return Font{ .native = native };
}
return error.FailedToLoadFont;
}
pub fn mapRgb(r: u8, g: u8, b: u8) Color {
return Color{ .native = c.al_map_rgb(r, g, b) };
}
pub fn mapRgba(r: u8, g: u8, b: u8, a: u8) Color {
return Color{ .native = c.al_map_rgba(r, g, b, a) };
}
pub fn mapRgbaF(r: f32, g: f32, b: f32, a: f32) Color {
return Color{ .native = c.al_map_rgba_f(r, g, b, a) };
}
pub fn mapRgbF(r: f32, g: f32, b: f32) Color {
return Color{ .native = c.al_map_rgb_f(r, g, b) };
}
pub fn openMemfile(data: []u8, mode: []const u8) !File {
const file = c.al_open_memfile(&data[0], @intCast(i64, data.len), &mode[0]);
if (file) |native| {
return File{ .native = native };
}
return error.FailedToOpenMemfile;
}
pub fn peekNextEvent(queue: EventQueue, event: *Event) bool {
return c.al_peek_next_event(queue.native, event);
}
pub fn registerEventSource(queue: EventQueue, source: EventSource) void {
c.al_register_event_source(queue.native, source.native);
}
pub fn saveBitmap(path: [*:0]const u8, bitmap: Bitmap) bool {
return c.al_save_bitmap(path, bitmap.native);
}
pub fn saveBitmapF(file: File, ident: []const u8, bitmap: Bitmap) bool {
return c.al_save_bitmap_f(file.native, &ident[0], bitmap.native);
}
pub fn setDisplayFlag(display: Display, flag: NewDisplayFlags, on: bool) bool {
return c.al_set_display_flag(display.native, @bitCast(c_int, flag), on);
}
pub fn setNewBitmapFlags(flags: NewBitmapFlags) void {
c.al_set_new_bitmap_flags(@bitCast(c_int, flags));
}
pub fn setNewBitmapFormat(format: PixelFormat) void {
c.al_set_new_bitmap_format(format);
}
pub fn setNewDisplayFlags(flags: NewDisplayFlags) void {
c.al_set_new_display_flags(@bitCast(c_int, flags));
}
pub fn setNewDisplayOption(option: NewDisplayOption, value: i32, importance: OptionImportance) void {
c.al_set_new_display_option(@enumToInt(option), value, @enumToInt(importance));
}
pub fn setTargetBitmap(bitmap: Bitmap) void {
c.al_set_target_bitmap(bitmap.native);
}
pub fn setTargetBackbuffer(display: Display) void {
c.al_set_target_bitmap(display.native);
}
pub fn startTimer(timer: Timer) void {
c.al_start_timer(timer.native);
}
pub fn unregisterEventSource(queue: EventQueue, source: EventSource) void {
c.al_unregister_event_source(queue.native, source.native);
}
pub fn waitForEvent(queue: EventQueue, event: *Event) void {
c.al_wait_for_event(queue.native, event);
}
pub fn waitForVsync() bool {
return c.al_wait_for_vsync();
}