667 lines
30 KiB
C
Executable File
667 lines
30 KiB
C
Executable File
/// __ _____ _ __ ___ _ __ ___ ___ _ __
|
|
/// \ \/ / _ \| '_ ` _ \| '_ ` _ \ / _ \| '_ \
|
|
/// > < (_) | | | | | | | | | | | (_) | | | |
|
|
/// /_/\_\___/|_| |_| |_|_| |_| |_|\___/|_| |_|
|
|
///
|
|
/// Copyright (c) 1997 - Ognjen 'xolatile' Milan Robovic
|
|
///
|
|
/// xolatile@chud.cyou - xommon - Tiny and elegant XCB wrapper library so I don't have to deal with other people decisions.
|
|
///
|
|
/// This program is free software, free as in freedom and as in free beer, you can redistribute it and/or modify it under the terms of the GNU
|
|
/// General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version if you wish...
|
|
///
|
|
/// This program is distributed in the hope that it will be useful, but it is probably not, and without any warranty, without even the implied
|
|
/// warranty of merchantability or fitness for a particular purpose, because it is pointless. Please see the GNU (Geenoo) General Public License
|
|
/// for more details, if you dare, it is a lot of text that nobody wants to read...
|
|
|
|
#include <xcb/xcb.h>
|
|
#include <xcb/xcb_atom.h>
|
|
#include <xcb/xcb_image.h>
|
|
//~#include <xcb/composite.h>
|
|
|
|
#define common_font_width (8)
|
|
#define common_font_height (16)
|
|
#define common_font_tabulator (4)
|
|
|
|
#ifndef common_gameplay_framerate
|
|
#define common_gameplay_framerate (60)
|
|
#endif
|
|
|
|
#ifndef common_animation_framerate
|
|
#define common_animation_framerate (3)
|
|
#endif
|
|
|
|
typedef enum {
|
|
common_window_fullscreen = 0x1,
|
|
common_window_transparent = 0x2,
|
|
common_window_resizable = 0x4,
|
|
common_window_decorated = 0x8
|
|
} common_window_flag;
|
|
|
|
typedef struct {
|
|
xcb_connection_t * connection;
|
|
xcb_screen_t * screen;
|
|
xcb_image_t * image;
|
|
xcb_window_t window;
|
|
xcb_gcontext_t context;
|
|
xcb_pixmap_t pixmap;
|
|
|
|
boolean signal [signal_count];
|
|
boolean cursor [cursor_count];
|
|
|
|
boolean active;
|
|
natural window_width;
|
|
natural window_height;
|
|
natural framerate;
|
|
natural_64 frame_time;
|
|
natural_64 frame_begin;
|
|
natural_64 frame_end;
|
|
natural * framebuffer;
|
|
natural global_tick;
|
|
natural gameplay_tick;
|
|
natural animation_tick;
|
|
integer cursor_x;
|
|
integer cursor_y;
|
|
boolean freeze_cursor;
|
|
boolean freeze_signal;
|
|
natural sprite_count;
|
|
natural font_count;
|
|
natural dummy; /// TODO USE ME PLEASE
|
|
natural * * sprite_data;
|
|
natural * sprite_width;
|
|
natural * sprite_height;
|
|
natural * * font_index;
|
|
natural * * font_width;
|
|
natural * * font_height;
|
|
character * font_begin;
|
|
character * font_end;
|
|
} common_structure;
|
|
|
|
static natural common_center_x (common_structure * common, natural size) {
|
|
return ((common->window_width - size) / 2);
|
|
}
|
|
|
|
static natural common_center_y (common_structure * common, natural size) {
|
|
return ((common->window_height - size) / 2);
|
|
}
|
|
|
|
static boolean common_cursor_inside (common_structure * common, integer x, integer y, natural width, natural height) {
|
|
return ((common->cursor_x > x)
|
|
&& (common->cursor_y > y)
|
|
&& (common->cursor_x < x + (integer) width)
|
|
&& (common->cursor_y < y + (integer) height));
|
|
}
|
|
|
|
static boolean common_cursor_left_click (common_structure * common, integer x, integer y, natural width, natural height) {
|
|
if (common->cursor [cursor_left] == true) {
|
|
common->freeze_cursor = true;
|
|
|
|
return (common_cursor_inside (common, x, y, width, height) == true);
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
static boolean common_cursor_right_click (common_structure * common, integer x, integer y, natural width, natural height) {
|
|
if (common->cursor [cursor_right]) {
|
|
common->freeze_cursor = true;
|
|
|
|
return (common_cursor_inside (common, x, y, width, height));
|
|
}
|
|
|
|
return (false);
|
|
}
|
|
|
|
static natural common_sprite_raw_import (common_structure * common, natural * data, natural width, natural height) {
|
|
++common->sprite_count;
|
|
|
|
common->sprite_data = reallocate (common->sprite_data, common->sprite_count * sizeof (* common->sprite_data));
|
|
common->sprite_width = reallocate (common->sprite_width, common->sprite_count * sizeof (* common->sprite_width));
|
|
common->sprite_height = reallocate (common->sprite_height, common->sprite_count * sizeof (* common->sprite_height));
|
|
|
|
common->sprite_data [common->sprite_count - 1] = data;
|
|
common->sprite_width [common->sprite_count - 1] = width;
|
|
common->sprite_height [common->sprite_count - 1] = height;
|
|
|
|
return (common->sprite_count - 1);
|
|
}
|
|
|
|
static natural common_font_raw_import (common_structure * common, natural * data, natural image_width, character begin, character end, natural empty) {
|
|
natural pointer = 0;
|
|
natural width = 0;
|
|
natural height = 0;
|
|
natural * buffer = null;
|
|
|
|
++common->font_count;
|
|
|
|
common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
|
|
common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
|
|
common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
|
|
common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
|
|
common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
|
|
|
|
common->font_begin [common->font_count - 1] = begin;
|
|
common->font_end [common->font_count - 1] = end;
|
|
|
|
common->font_index [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_index));
|
|
common->font_width [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_width));
|
|
common->font_height [common->font_count - 1] = allocate ((caliber) (end - begin + 1) * sizeof (* * common->font_height));
|
|
|
|
for (character index = begin; index <= end; ++index) {
|
|
for ( ; data [pointer] == empty; ++pointer);
|
|
for (width = 0; data [pointer + width] != empty; ++width);
|
|
for (height = 0; data [pointer + height * image_width] != empty; ++height);
|
|
|
|
buffer = allocate (width * height * sizeof (* buffer));
|
|
|
|
for (natural y = 0; y < height; ++y) {
|
|
for (natural x = 0; x < width; ++x) {
|
|
buffer [y * width + x] = data [pointer + (y * image_width) + x];
|
|
}
|
|
}
|
|
|
|
common->font_index [common->font_count - 1] [index - begin] = common_sprite_raw_import (common, buffer, width, height);
|
|
common->font_width [common->font_count - 1] [index - begin] = width;
|
|
common->font_height [common->font_count - 1] [index - begin] = height;
|
|
|
|
pointer += width;
|
|
|
|
for (; data [pointer] == empty; ++pointer);
|
|
|
|
if (pointer % image_width == 2) {
|
|
pointer += height * image_width;
|
|
}
|
|
}
|
|
|
|
return (common->font_count - 1);
|
|
}
|
|
|
|
static natural common_sprite_import (common_structure * common, character * path) {
|
|
natural width = 0;
|
|
natural height = 0;
|
|
natural * data = null;
|
|
|
|
character buffer [256] = "";
|
|
|
|
#ifdef use_png_library
|
|
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
|
|
data = png_image_import (buffer, & width, & height);
|
|
}
|
|
#endif
|
|
|
|
#ifdef use_jxl_library
|
|
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
|
|
data = jxl_image_import (buffer, & width, & height);
|
|
}
|
|
#endif
|
|
|
|
fatal_failure (data == null, "opengl_sprite_import: Unsupported image format.");
|
|
|
|
return (common_sprite_raw_import (common, data, width, height));
|
|
}
|
|
|
|
static natural common_font_import (common_structure * common, character * path, character begin, character end, natural colour) {
|
|
natural width = 0;
|
|
natural height = 0;
|
|
natural result = 0;
|
|
natural * data = null;
|
|
|
|
character buffer [256] = "";
|
|
|
|
#ifdef use_png_library
|
|
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".png")) == true)) {
|
|
data = png_image_import (buffer, & width, & height);
|
|
}
|
|
#endif
|
|
|
|
#ifdef use_jxl_library
|
|
if ((data == null) && (file_exists (string_concatenate (string_copy (buffer, path), ".jxl")) == true)) {
|
|
data = jxl_image_import (buffer, & width, & height);
|
|
}
|
|
#endif
|
|
|
|
fatal_failure (data == null, "opengl_font_import: Unsupported image format.");
|
|
|
|
result = common_font_raw_import (common, data, width, begin, end, colour);
|
|
|
|
data = deallocate (data);
|
|
|
|
return (result);
|
|
}
|
|
|
|
static natural common_sprite_width (common_structure * common, natural sprite) {
|
|
return (common->sprite_width [sprite]);
|
|
}
|
|
|
|
static natural common_sprite_height (common_structure * common, natural sprite) {
|
|
return (common->sprite_height [sprite]);
|
|
}
|
|
|
|
static common_structure * common_initialize (none) {
|
|
common_structure * common = allocate (sizeof (* common));
|
|
|
|
return (common);
|
|
}
|
|
|
|
static common_structure * common_deinitialize (common_structure * common) {
|
|
for (natural index = 0; index < common->sprite_count; ++index) {
|
|
common->sprite_data [index] = deallocate (common->sprite_data [index]);
|
|
}
|
|
|
|
for (natural index = 0; index < common->font_count; ++index) {
|
|
common->font_index [index] = deallocate (common->font_index [index]);
|
|
common->font_width [index] = deallocate (common->font_width [index]);
|
|
common->font_height [index] = deallocate (common->font_height [index]);
|
|
}
|
|
|
|
common->font_index = deallocate (common->font_index);
|
|
common->font_width = deallocate (common->font_width);
|
|
common->font_height = deallocate (common->font_height);
|
|
common->font_begin = deallocate (common->font_begin);
|
|
common->font_end = deallocate (common->font_end);
|
|
|
|
common->sprite_data = deallocate (common->sprite_data);
|
|
common->sprite_width = deallocate (common->sprite_width);
|
|
common->sprite_height = deallocate (common->sprite_height);
|
|
|
|
common->framebuffer = deallocate (common->framebuffer);
|
|
|
|
xcb_free_gc (common->connection, common->context);
|
|
xcb_free_pixmap (common->connection, common->pixmap);
|
|
xcb_destroy_window (common->connection, common->window);
|
|
|
|
xcb_disconnect (common->connection);
|
|
|
|
return (deallocate (common));
|
|
}
|
|
|
|
static procedure common_configure (common_structure * common, natural width, natural height, character * title, natural window_flags) {
|
|
natural_64 font_bitmap [190] = {
|
|
0x0000000000000000, 0x0000000000000000, 0x0000101010101010, 0x1000101000000000, 0x0024242400000000, 0x0000000000000000,
|
|
0x00002424247e2424, 0x7e24242400000000, 0x0010107c9290907c, 0x1212927character0100000, 0x0000649468081010, 0x202c524c00000000,
|
|
0x000018242418304a, 0x4444443a00000000, 0x0010101000000000, 0x0000000000000000, 0x0000081020202020, 0x2020100800000000,
|
|
0x0000201008080808, 0x0808102000000000, 0x000000000024187e, 0x1824000000000000, 0x000000000010107c, 0x1010000000000000,
|
|
0x0000000000000000, 0x0000101020000000, 0x000000000000007e, 0x0000000000000000, 0x0000000000000000, 0x0000101000000000,
|
|
0x0000040408081010, 0x2020404000000000, 0x00003c4242464a52, 0x6242423c00000000, 0x0000081828080808, 0x0808083e00000000,
|
|
0x00003c4242020408, 0x1020407e00000000, 0x00003c4242021c02, 0x0242423c00000000, 0x000002060a122242, 0x7e02020200000000,
|
|
0x00007e4040407c02, 0x0202423c00000000, 0x00001c2040407c42, 0x4242423c00000000, 0x00007e0202040408, 0x0810101000000000,
|
|
0x00003c4242423c42, 0x4242423c00000000, 0x00003c424242423e, 0x0202043800000000, 0x0000000000101000, 0x0000101000000000,
|
|
0x0000000000101000, 0x0000101020000000, 0x0000000408102040, 0x2010080400000000, 0x00000000007e0000, 0x7e00000000000000,
|
|
0x0000004020100804, 0x0810204000000000, 0x00003c4242420408, 0x0800080800000000, 0x00007c829ea2a2a2, 0xa69a807e00000000,
|
|
0x00003c424242427e, 0x4242424200000000, 0x00007c4242427c42, 0x4242427c00000000, 0x00003c4242404040, 0x4042423c00000000,
|
|
0x0000784442424242, 0x4242447800000000, 0x00007e4040407840, 0x4040407e00000000, 0x00007e4040407840, 0x4040404000000000,
|
|
0x00003c424240404e, 0x4242423c00000000, 0x0000424242427e42, 0x4242424200000000, 0x0000381010101010, 0x1010103800000000,
|
|
0x00000e0404040404, 0x0444443800000000, 0x0000424448506060, 0x5048444200000000, 0x0000404040404040, 0x4040407e00000000,
|
|
0x000082c6aa929282, 0x8282828200000000, 0x000042424262524a, 0x4642424200000000, 0x00003c4242424242, 0x4242423c00000000,
|
|
0x00007c424242427c, 0x4040404000000000, 0x00003c4242424242, 0x42424a3c02000000, 0x00007c424242427c, 0x5048444200000000,
|
|
0x00003c4240403c02, 0x0242423c00000000, 0x0000fe1010101010, 0x1010101000000000, 0x0000424242424242, 0x4242423c00000000,
|
|
0x0000424242424224, 0x2424181800000000, 0x0000828282828292, 0x92aac68200000000, 0x0000424224241818, 0x2424424200000000,
|
|
0x0000828244442810, 0x1010101000000000, 0x00007e0202040810, 0x2040407e00000000, 0x0000382020202020, 0x2020203800000000,
|
|
0x0000404020201010, 0x0808040400000000, 0x0000380808080808, 0x0808083800000000, 0x0000102844000000, 0x0000000000000000,
|
|
0x0000000000000000, 0x0000007e00000000, 0x1008000000000000, 0x0000000000000000, 0x00000000003c023e, 0x4242423e00000000,
|
|
0x00004040407c4242, 0x4242427c00000000, 0x00000000003c4240, 0x4040423c00000000, 0x00000202023e4242, 0x4242423e00000000,
|
|
0x00000000003c4242, 0x7e40403c00000000, 0x00000e10107character010, 0x1010101000000000, 0x00000000003e4242, 0x4242423e02023c00,
|
|
0x00004040407c4242, 0x4242424200000000, 0x0000101000301010, 0x1010103800000000, 0x00000404000c0404, 0x0404040444443800,
|
|
0x0000404040424448, 0x7048444200000000, 0x0000301010101010, 0x1010103800000000, 0x0000000000fc9292, 0x9292929200000000,
|
|
0x00000000007c4242, 0x4242424200000000, 0x00000000003c4242, 0x4242423c00000000, 0x00000000007c4242, 0x4242427c40404000,
|
|
0x00000000003e4242, 0x4242423e02020200, 0x00000000005e6040, 0x4040404000000000, 0x00000000003e4040, 0x3c02027c00000000,
|
|
0x00001010107character010, 0x1010100e00000000, 0x0000000000424242, 0x4242423e00000000, 0x0000000000424242, 0x2424181800000000,
|
|
0x0000000000828292, 0x9292927c00000000, 0x0000000000424224, 0x1824424200000000, 0x0000000000424242, 0x4242423e02023c00,
|
|
0x00000000007e0408, 0x1020407e00000000, 0x00000character010102010, 0x1010100c00000000, 0x0000101010101010, 0x1010101000000000,
|
|
0x0000300808080408, 0x0808083000000000, 0x000000000062928c, 0x0000000000000000
|
|
};
|
|
|
|
natural event_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
|
|
|
|
natural mask_window_flags [2] = { 0 };
|
|
|
|
(none) window_flags;
|
|
|
|
natural * dumb_buffer = allocate (256 * sizeof (* dumb_buffer));
|
|
|
|
for (natural index = 0; index < 256; ++index) {
|
|
dumb_buffer [index] = 0xffffffff;
|
|
}
|
|
|
|
++common->font_count;
|
|
|
|
common->font_index = reallocate (common->font_index, common->font_count * sizeof (* common->font_index));
|
|
common->font_width = reallocate (common->font_width, common->font_count * sizeof (* common->font_width));
|
|
common->font_height = reallocate (common->font_height, common->font_count * sizeof (* common->font_height));
|
|
common->font_begin = reallocate (common->font_begin, common->font_count * sizeof (* common->font_begin));
|
|
common->font_end = reallocate (common->font_end, common->font_count * sizeof (* common->font_end));
|
|
|
|
common->font_begin [common->font_count - 1] = ' ';
|
|
common->font_end [common->font_count - 1] = '~';
|
|
|
|
common->font_index [common->font_count - 1] = allocate (95 * sizeof (* * common->font_index));
|
|
common->font_width [common->font_count - 1] = allocate (95 * sizeof (* * common->font_width));
|
|
common->font_height [common->font_count - 1] = allocate (95 * sizeof (* * common->font_height));
|
|
|
|
for (natural index = 0; index < 95; ++index) {
|
|
natural * buffer = allocate (common_font_width * common_font_height * sizeof (* buffer));
|
|
|
|
for (natural value = 0; value < 2; ++value) {
|
|
for (natural bit = 64; bit > 0; --bit) {
|
|
natural destination = ((value << 3) - ((bit - 1) >> 3) + 7) * common_font_width - ((bit - 1) & 7) + 7;
|
|
natural source = (font_bitmap [2 * index + value] >> (bit - 1)) & 1;
|
|
|
|
buffer [destination] = (source) ? 0xffffffff : 0x00000000;
|
|
}
|
|
}
|
|
|
|
common->font_index [common->font_count - 1] [index] = common_sprite_raw_import (common, buffer, common_font_width, common_font_height);
|
|
common->font_width [common->font_count - 1] [index] = common_font_width;
|
|
common->font_height [common->font_count - 1] [index] = common_font_height;
|
|
}
|
|
|
|
common_sprite_raw_import (common, dumb_buffer, 16, 16);
|
|
|
|
common->window_width = width;
|
|
common->window_height = height;
|
|
|
|
//~if (window_flags == ~ 0u) {
|
|
//~flags = common_window_decorated | common_window_resizable;
|
|
//~} else {
|
|
//~flags = window_flags;
|
|
//~}
|
|
|
|
common->connection = xcb_connect (null, null);
|
|
|
|
common->screen = xcb_setup_roots_iterator (xcb_get_setup (common->connection)).data;
|
|
|
|
common->window = xcb_generate_id (common->connection);
|
|
common->context = xcb_generate_id (common->connection);
|
|
common->pixmap = xcb_generate_id (common->connection);
|
|
|
|
mask_window_flags [0] = common->screen->black_pixel;
|
|
mask_window_flags [1] = XCB_EVENT_MASK_NO_EVENT |
|
|
XCB_EVENT_MASK_EXPOSURE |
|
|
XCB_EVENT_MASK_RESIZE_REDIRECT |
|
|
XCB_EVENT_MASK_KEY_RELEASE |
|
|
XCB_EVENT_MASK_KEY_PRESS |
|
|
XCB_EVENT_MASK_BUTTON_RELEASE |
|
|
XCB_EVENT_MASK_BUTTON_PRESS;
|
|
|
|
xcb_create_window (common->connection, common->screen->root_depth, common->window, common->screen->root, 0, 0, (natural_16) width,
|
|
(natural_16) height, 10, XCB_WINDOW_CLASS_INPUT_OUTPUT, common->screen->root_visual, event_mask, mask_window_flags);
|
|
|
|
xcb_map_window (common->connection, common->window);
|
|
|
|
//~xcb_composite_redirect_window (common->connection, common->window, XCB_COMPOSITE_REDIRECT_MANUAL);
|
|
|
|
xcb_change_property (common->connection, XCB_PROP_MODE_REPLACE, common->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
|
|
(natural) string_length (title), title);
|
|
|
|
xcb_create_pixmap (common->connection, common->screen->root_depth, common->pixmap, common->window, (natural_16) width, (natural_16 ) height);
|
|
|
|
xcb_create_gc (common->connection, common->context, common->pixmap, 0, null);
|
|
|
|
xcb_flush (common->connection);
|
|
|
|
common->framebuffer = allocate (width * height * sizeof (* common->framebuffer));
|
|
|
|
common->active = true;
|
|
|
|
common->frame_begin = nano_time ();
|
|
}
|
|
|
|
static procedure common_synchronize (common_structure * common, natural colour) {
|
|
natural signal_code [signal_count] = {
|
|
0,
|
|
38, 56, 54, 40, 26, 41, 42, 43, 31, 44, 45, 46, 58, 57, 32, 33,
|
|
24, 27, 39, 28, 30, 55, 25, 53, 29, 52, 19, 10, 11, 12, 13, 14,
|
|
15, 16, 17, 18, 9, 23, 36, 36, 61, 51, 47, 49, 65, 22, 60, 59,
|
|
48, 66, 20, 21, 34, 35, 37, 105, 50, 62, 64, 108, 67, 68, 69, 70,
|
|
71, 72, 73, 74, 75, 76, 95, 96, 111, 116, 113, 114, 77, 127, 118, 110,
|
|
112, 119, 115, 117, 86, 82, 63, 106, 104, 91, 90, 87, 88, 89, 83, 84,
|
|
85, 79, 80, 81
|
|
};
|
|
|
|
xcb_generic_event_t * generic_event = xcb_wait_for_event (common->connection);
|
|
//~xcb_generic_event_t * generic_event = null;
|
|
|
|
(none) colour;
|
|
|
|
//~for (; ; ) {
|
|
//~generic_event = xcb_poll_for_event (common->connection);
|
|
|
|
//~if (generic_event != null) {
|
|
//~if ((generic_event->response_type & 127) != 14) break;
|
|
//~}
|
|
//~}
|
|
|
|
xcb_flush (common->connection);
|
|
|
|
print ("%i\n", generic_event->response_type & 127);
|
|
//~XCB_NO_EXPOSURE = 14
|
|
//~if (generic_event != null) {
|
|
switch (generic_event->response_type & 127) {
|
|
//~case XCB_EXPOSE: {
|
|
//~xcb_flush (common->connection);
|
|
//~} break;
|
|
//~case XCB_MOTION_NOTIFY: {
|
|
//~;
|
|
//~} break;
|
|
case (XCB_BUTTON_PRESS): {
|
|
xcb_button_press_event_t * button_press = (xcb_button_press_event_t *) generic_event;
|
|
if (button_press->detail == 1) common->cursor [cursor_left] = true;
|
|
if (button_press->detail == 2) common->cursor [cursor_middle] = true;
|
|
if (button_press->detail == 3) common->cursor [cursor_right] = true;
|
|
common->cursor_x = button_press->event_x;
|
|
common->cursor_y = button_press->event_y;
|
|
} break;
|
|
case (XCB_BUTTON_RELEASE): {
|
|
xcb_button_release_event_t * button_release = (xcb_button_release_event_t *) generic_event;
|
|
if (button_release->detail == 1) common->cursor [cursor_left] = false;
|
|
if (button_release->detail == 2) common->cursor [cursor_middle] = false;
|
|
if (button_release->detail == 3) common->cursor [cursor_right] = false;
|
|
common->cursor_x = button_release->event_x;
|
|
common->cursor_y = button_release->event_y;
|
|
} break;
|
|
case (XCB_KEY_PRESS): {
|
|
xcb_key_press_event_t * key_press = (xcb_key_press_event_t *) generic_event;
|
|
for (natural index = 0; index < signal_count; ++index) {
|
|
if (key_press->detail == signal_code [index]) {
|
|
common->signal [index] = true;
|
|
}
|
|
}
|
|
} break;
|
|
case (XCB_KEY_RELEASE): {
|
|
xcb_key_release_event_t * key_release = (xcb_key_release_event_t *) generic_event;
|
|
for (natural index = 0; index < signal_count; ++index) {
|
|
if (key_release->detail == signal_code [index]) {
|
|
common->signal [index] = false;
|
|
}
|
|
}
|
|
} break;
|
|
default: {
|
|
} break;
|
|
}
|
|
|
|
generic_event = deallocate (generic_event);
|
|
//~}
|
|
|
|
for (natural pixel = 0; pixel < common->window_width * common->window_height; ++pixel) {
|
|
natural r = (common->framebuffer [pixel] & 0x00ff0000) >> 16;
|
|
natural b = (common->framebuffer [pixel] & 0x000000ff) << 16;
|
|
|
|
common->framebuffer [pixel] = (common->framebuffer [pixel] & 0xff00ff00) | b | r;
|
|
}
|
|
|
|
common->image = xcb_image_create_native (common->connection, (natural_16) common->window_width, (natural_16) common->window_height,
|
|
XCB_IMAGE_FORMAT_Z_PIXMAP, common->screen->root_depth, common->framebuffer,
|
|
(natural) (common->window_width * common->window_height * sizeof (* common->framebuffer)),
|
|
(natural_8 *) common->framebuffer);
|
|
|
|
xcb_image_put (common->connection, common->pixmap, common->context, common->image, 0, 0, 0);
|
|
|
|
xcb_image_destroy (common->image);
|
|
|
|
xcb_copy_area (common->connection, common->pixmap, common->window, common->context, 0, 0, 0, 0, (natural_16) common->window_width,
|
|
(natural_16) common->window_height);
|
|
|
|
common->framebuffer = allocate (common->window_width * common->window_height * sizeof (* common->framebuffer));
|
|
|
|
common->frame_end = nano_time ();
|
|
|
|
common->frame_time = common->frame_end - common->frame_begin;
|
|
|
|
if (common->frame_time < 1000000000ul / common_gameplay_framerate) {
|
|
nano_wait (1000000000ul / common_gameplay_framerate - common->frame_time);
|
|
}
|
|
|
|
if (common->global_tick % common_gameplay_framerate == 0) {
|
|
common->framerate = (natural) (1000000000ul / common->frame_time);
|
|
}
|
|
|
|
++common->global_tick;
|
|
|
|
common->global_tick = common->global_tick % (common_gameplay_framerate * common_animation_framerate);
|
|
common->gameplay_tick = common->global_tick % (common_gameplay_framerate);
|
|
common->animation_tick = common->global_tick / (common_gameplay_framerate / common_animation_framerate);
|
|
|
|
common->frame_begin = nano_time ();
|
|
}
|
|
|
|
static procedure common_render_base (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, real scale_x, real scale_y, integer flip_x,
|
|
integer flip_y, natural upper_left, natural upper_right, natural lower_left, natural lower_right) {
|
|
(none) scale_x;
|
|
(none) scale_y;
|
|
(none) flip_x;
|
|
(none) flip_y;
|
|
/// FIX TO INTERPOLATE ALL 4 COLOURS
|
|
//~(none) upper_left;
|
|
(none) upper_right;
|
|
(none) lower_left;
|
|
(none) lower_right;
|
|
|
|
/// COLOUR INTERPOLATION WITH RBGA-ABGR CONVERSION
|
|
natural interpolate_pixels (natural pixel, natural modifier) {
|
|
natural r = (((pixel & 0xff000000) >> 24) * ((modifier & 0x000000ff) >> 0)) / 0xff;
|
|
natural g = (((pixel & 0x00ff0000) >> 16) * ((modifier & 0x0000ff00) >> 8)) / 0xff;
|
|
natural b = (((pixel & 0x0000ff00) >> 8) * ((modifier & 0x00ff0000) >> 16)) / 0xff;
|
|
natural a = (((pixel & 0x000000ff) >> 0) * ((modifier & 0xff000000) >> 24)) / 0xff;
|
|
|
|
return ((r << 24) | (g << 16) | (b << 8) | a);
|
|
}
|
|
|
|
if ((x + (integer) width < 0) || (y + (integer) height < 0) || (x > (integer) common->window_width) || (y > (integer) common->window_height)) return;
|
|
|
|
for (natural vertical = 0; vertical < height; ++vertical) {
|
|
if (vertical + y >= common->window_height) break;
|
|
if (vertical + v >= common->sprite_height [sprite]) break;
|
|
|
|
for (natural horizontal = 0; horizontal < width; ++horizontal) {
|
|
if (horizontal + x >= common->window_width) break;
|
|
if (horizontal + u >= common->sprite_width [sprite]) break;
|
|
|
|
natural pixel = common->sprite_data [sprite] [(vertical + v) * common->sprite_width [sprite] + horizontal + u];
|
|
natural at = (y + vertical) * common->window_width + (x + horizontal);
|
|
|
|
common->framebuffer [at] = (((pixel & 0xff000000) >> 24) > 0x77) ? interpolate_pixels (pixel, upper_left) : common->framebuffer [at];
|
|
}
|
|
}
|
|
}
|
|
|
|
static procedure common_render_rectangle (common_structure * common, integer x, integer y, natural width, natural height, natural colour) {
|
|
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour, colour,
|
|
colour, colour);
|
|
}
|
|
|
|
static procedure common_render_rectangle_gradient_v (common_structure * common, integer x, integer y, natural width, natural height, natural colour_up, natural colour_down) {
|
|
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_up, colour_up,
|
|
colour_down, colour_down);
|
|
}
|
|
|
|
static procedure common_render_rectangle_gradient_h (common_structure * common, integer x, integer y, natural width, natural height, natural colour_left, natural colour_right) {
|
|
common_render_base (common, common->sprite_count - 1, x, y, 0, 0, 16, 16, (real) width / 16, (real) height / 16, 0, 0, colour_left,
|
|
colour_right, colour_left, colour_right);
|
|
}
|
|
|
|
static procedure common_render_sprite (common_structure * common, natural sprite, integer x, integer y) {
|
|
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu,
|
|
0xffffffffu);
|
|
}
|
|
|
|
static procedure common_render_sprite_crop (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height) {
|
|
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static procedure common_render_sprite_colour (common_structure * common, natural sprite, natural colour, integer x, integer y) {
|
|
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static procedure common_render_sprite_crop_colour (common_structure * common, natural sprite, natural colour, integer x, integer y, natural u, natural v, natural width, natural height) {
|
|
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, 0, 0, colour, colour, colour, colour);
|
|
}
|
|
|
|
static procedure common_render_sprite_flip (common_structure * common, natural sprite, integer x, integer y, integer flip_x, integer flip_y) {
|
|
common_render_base (common, sprite, x, y, 0, 0, common->sprite_width [sprite], common->sprite_height [sprite], 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static procedure common_render_sprite_animation (common_structure * common, natural sprite, integer x, integer y, natural frames, natural state, natural states) {
|
|
natural width = common->sprite_width [sprite] / states;
|
|
natural height = common->sprite_height [sprite] / frames;
|
|
natural u = width * (state % states);
|
|
natural v = height * (common->animation_tick % frames);
|
|
|
|
common_render_sprite_crop (common, sprite, x, y, u, v, width, height);
|
|
}
|
|
|
|
static procedure common_render_sprite_preview (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, real zoom) {
|
|
common_render_base (common, sprite, x, y, u, v, width, height, zoom, zoom, false, false, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static procedure common_render_sprite_control (common_structure * common, natural sprite, integer x, integer y, natural u, natural v, natural width, natural height, integer flip_x, integer flip_y) {
|
|
common_render_base (common, sprite, x, y, u, v, width, height, 1, 1, flip_x, flip_y, 0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu);
|
|
}
|
|
|
|
static natural common_render_string_width (common_structure * common, character * string, natural font, real scale) {
|
|
natural length = 0;
|
|
|
|
if (string == null) {
|
|
return (0);
|
|
}
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
natural character = common->font_index [font] [string [index] - common->font_begin [font]];
|
|
|
|
length += (natural) ((real) common->sprite_width [character] * scale);
|
|
}
|
|
|
|
return (length);
|
|
}
|
|
|
|
static procedure common_render_string (common_structure * common, character * string, natural font, integer x, integer y, real scale, natural colour) {
|
|
integer offset = x;
|
|
|
|
if (string == null) return;
|
|
|
|
if (font == 0xffffffffu) {
|
|
font = common->font_count - 1;
|
|
}
|
|
|
|
for (natural index = 0; string [index] != '\0'; ++index) {
|
|
natural character = 0;
|
|
|
|
if (string [index] == '\t') {
|
|
x += (integer) (scale * (real) common_font_tabulator * (real) common->sprite_width [common->font_index [font] [' ' - common->font_begin [font]]]);
|
|
continue;
|
|
} else if (string [index] == '\n') {
|
|
x = offset;
|
|
y += (integer) (scale * (real) common->sprite_height [common->font_index [font] [' ' - common->font_begin [font]]]);
|
|
continue;
|
|
} else if ((string [index] >= common->font_begin [font]) && (string [index] <= common->font_end [font])) {
|
|
character = common->font_index [font] [string [index] - common->font_begin [font]];
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
common_render_base (common, character, x, y, 0, 0, common->sprite_width [character], common->sprite_height [character],
|
|
scale, scale, 0, 0, colour, colour, colour, colour);
|
|
|
|
x += (integer) (scale * (real) common->sprite_width [character]);
|
|
}
|
|
}
|