forked from virt-mirrors/wayneko
let neko run around
This commit is contained in:
parent
c48484663c
commit
abba39daf9
1 changed files with 126 additions and 37 deletions
163
wayneko.c
163
wayneko.c
|
@ -22,12 +22,17 @@
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MIN(A, B) (A < B ? A : B)
|
||||||
|
|
||||||
#include "wlr-layer-shell-unstable-v1.h"
|
#include "wlr-layer-shell-unstable-v1.h"
|
||||||
|
|
||||||
|
pixman_color_t bg_colour;
|
||||||
|
pixman_color_t border_colour;
|
||||||
|
|
||||||
/* Note: Atlas width must be divisable by 4. */
|
/* Note: Atlas width must be divisable by 4. */
|
||||||
#include "neko-bitmap.xbm"
|
#include "neko-bitmap.xbm"
|
||||||
const int neko_bitmap_stride = neko_bitmap_width / 8;
|
const int neko_bitmap_stride = neko_bitmap_width / 8;
|
||||||
const int neko_size = 32;
|
const uint8_t neko_size = 32;
|
||||||
pixman_image_t *neko_atlas = NULL;
|
pixman_image_t *neko_atlas = NULL;
|
||||||
pixman_image_t *neko_atlas_bg_fill = NULL;
|
pixman_image_t *neko_atlas_bg_fill = NULL;
|
||||||
pixman_image_t *neko_atlas_border_fill = NULL;
|
pixman_image_t *neko_atlas_border_fill = NULL;
|
||||||
|
@ -70,14 +75,15 @@ struct Surface
|
||||||
{
|
{
|
||||||
struct wl_surface *wl_surface;
|
struct wl_surface *wl_surface;
|
||||||
struct zwlr_layer_surface_v1 *layer_surface;
|
struct zwlr_layer_surface_v1 *layer_surface;
|
||||||
|
uint32_t width, height;
|
||||||
|
uint16_t neko_x, prev_neko_x;
|
||||||
bool configured;
|
bool configured;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Surface surface = { 0 };
|
struct Surface surface = { 0 };
|
||||||
|
|
||||||
// TODO wide surface and let the neko run around.
|
const uint32_t desired_surface_height = neko_size;
|
||||||
const uint32_t surface_width = neko_size;
|
const uint8_t neko_x_advance = 15;
|
||||||
const uint32_t surface_height = neko_size;
|
|
||||||
|
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
bool loop = true;
|
bool loop = true;
|
||||||
|
@ -429,25 +435,6 @@ static void buffer_pool_destroy_all_buffers (void)
|
||||||
* Atlas *
|
* Atlas *
|
||||||
* *
|
* *
|
||||||
***********/
|
***********/
|
||||||
static bool colour_from_hex (pixman_color_t *colour, const char *hex)
|
|
||||||
{
|
|
||||||
uint16_t r = 0, g = 0, b = 0, a = 255;
|
|
||||||
|
|
||||||
if ( 4 != sscanf(hex, "0x%02hx%02hx%02hx%02hx", &r, &g, &b, &a)
|
|
||||||
&& 3 != sscanf(hex, "0x%02hx%02hx%02hx", &r, &g, &b) )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "ERROR: Invalid colour: %s\n", hex);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
colour->alpha = (uint16_t)(((double)a / 255.0) * 65535.0);
|
|
||||||
colour->red = (uint16_t)((((double)r / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
|
||||||
colour->green = (uint16_t)((((double)g / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
|
||||||
colour->blue = (uint16_t)((((double)b / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void atlas_deinit (void)
|
static void atlas_deinit (void)
|
||||||
{
|
{
|
||||||
if ( neko_atlas != NULL )
|
if ( neko_atlas != NULL )
|
||||||
|
@ -482,8 +469,6 @@ static bool atlas_init (void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_color_t bg_colour;
|
|
||||||
colour_from_hex(&bg_colour, "0xFFFFFF");
|
|
||||||
neko_atlas_bg_fill = pixman_image_create_solid_fill(&bg_colour);
|
neko_atlas_bg_fill = pixman_image_create_solid_fill(&bg_colour);
|
||||||
if ( neko_atlas_bg_fill == NULL )
|
if ( neko_atlas_bg_fill == NULL )
|
||||||
{
|
{
|
||||||
|
@ -492,8 +477,6 @@ static bool atlas_init (void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_color_t border_colour;
|
|
||||||
colour_from_hex(&border_colour, "0x000000");
|
|
||||||
neko_atlas_border_fill = pixman_image_create_solid_fill(&border_colour);
|
neko_atlas_border_fill = pixman_image_create_solid_fill(&border_colour);
|
||||||
if ( neko_atlas_border_fill == NULL )
|
if ( neko_atlas_border_fill == NULL )
|
||||||
{
|
{
|
||||||
|
@ -537,6 +520,16 @@ static void atlas_composite_neko (struct Buffer *buffer, enum Neko neko_type, ui
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool animation_can_run_left (void)
|
||||||
|
{
|
||||||
|
return surface.neko_x > neko_x_advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool animation_can_run_right (void)
|
||||||
|
{
|
||||||
|
return surface.neko_x < surface.width - neko_size;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns true if new frame is needed. */
|
/** Returns true if new frame is needed. */
|
||||||
static bool animation_next_state (void)
|
static bool animation_next_state (void)
|
||||||
{
|
{
|
||||||
|
@ -570,16 +563,78 @@ static bool animation_next_state (void)
|
||||||
animation_ticks_until_next_frame = 15;
|
animation_ticks_until_next_frame = 15;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (!animation_can_run_left())
|
||||||
|
return false;
|
||||||
|
current_neko = NEKO_RUN_LEFT_1;
|
||||||
|
surface.prev_neko_x = surface.neko_x;
|
||||||
|
surface.neko_x -= neko_x_advance;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (!animation_can_run_right())
|
||||||
|
return false;
|
||||||
|
current_neko = NEKO_RUN_RIGHT_1;
|
||||||
|
surface.prev_neko_x = surface.neko_x;
|
||||||
|
surface.neko_x += neko_x_advance;
|
||||||
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case NEKO_RUN_RIGHT_1:
|
||||||
|
case NEKO_RUN_RIGHT_2:
|
||||||
|
case NEKO_RUN_LEFT_1:
|
||||||
|
case NEKO_RUN_LEFT_2:
|
||||||
|
if ( current_neko == NEKO_RUN_LEFT_1 || current_neko == NEKO_RUN_LEFT_2 )
|
||||||
|
{
|
||||||
|
if (!animation_can_run_left())
|
||||||
|
{
|
||||||
|
current_neko = NEKO_STARE;
|
||||||
|
animation_ticks_until_next_frame = 10;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!animation_can_run_right())
|
||||||
|
{
|
||||||
|
current_neko = NEKO_STARE;
|
||||||
|
animation_ticks_until_next_frame = 10;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( rand() % 4 == 0 )
|
||||||
|
{
|
||||||
|
current_neko = NEKO_STARE;
|
||||||
|
animation_ticks_until_next_frame = 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (current_neko)
|
||||||
|
{
|
||||||
|
case NEKO_RUN_RIGHT_1: current_neko = NEKO_RUN_RIGHT_2; break;
|
||||||
|
case NEKO_RUN_RIGHT_2: current_neko = NEKO_RUN_RIGHT_1; break;
|
||||||
|
case NEKO_RUN_LEFT_1: current_neko = NEKO_RUN_LEFT_2; break;
|
||||||
|
case NEKO_RUN_LEFT_2: current_neko = NEKO_RUN_LEFT_1; break;
|
||||||
|
default: /* unreachable. */ break;
|
||||||
|
}
|
||||||
|
surface.prev_neko_x = surface.neko_x;
|
||||||
|
if ( current_neko == NEKO_RUN_LEFT_1 || current_neko == NEKO_RUN_LEFT_2 )
|
||||||
|
surface.neko_x -= neko_x_advance;
|
||||||
|
else
|
||||||
|
surface.neko_x += neko_x_advance;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
case NEKO_SLEEP_1:
|
case NEKO_SLEEP_1:
|
||||||
case NEKO_SLEEP_2:
|
case NEKO_SLEEP_2:
|
||||||
case NEKO_SCRATCH_1:
|
case NEKO_SCRATCH_1:
|
||||||
case NEKO_SCRATCH_2:
|
case NEKO_SCRATCH_2:
|
||||||
if ( rand() % 4 == 0)
|
if ( rand() % 4 == 0 )
|
||||||
{
|
{
|
||||||
if ( current_neko == NEKO_SLEEP_1 || current_neko == NEKO_SLEEP_2 )
|
if ( current_neko == NEKO_SLEEP_1 || current_neko == NEKO_SLEEP_2 )
|
||||||
{
|
{
|
||||||
|
@ -655,15 +710,21 @@ static void surface_next_frame (void)
|
||||||
{
|
{
|
||||||
if (!surface.configured)
|
if (!surface.configured)
|
||||||
return;
|
return;
|
||||||
struct Buffer *buffer = buffer_pool_next_buffer(surface_width, surface_height);
|
struct Buffer *buffer = buffer_pool_next_buffer(surface.width, surface.height);
|
||||||
if ( buffer == NULL )
|
if ( buffer == NULL )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
atlas_composite_neko(buffer, current_neko, 0, 0);
|
pixman_image_fill_rectangles(PIXMAN_OP_CLEAR, buffer->pixman_image, &bg_colour,
|
||||||
|
1, &(pixman_rectangle16_t){ (int16_t)surface.prev_neko_x, (int16_t)0, (uint16_t)neko_size, (uint16_t)neko_size, });
|
||||||
|
atlas_composite_neko(buffer, current_neko, surface.neko_x, 0);
|
||||||
|
|
||||||
wl_surface_set_buffer_scale(surface.wl_surface, 1);
|
wl_surface_set_buffer_scale(surface.wl_surface, 1);
|
||||||
wl_surface_attach(surface.wl_surface, buffer->wl_buffer, 0, 0);
|
wl_surface_attach(surface.wl_surface, buffer->wl_buffer, 0, 0);
|
||||||
wl_surface_damage_buffer(surface.wl_surface, 0, 0, INT32_MAX, INT32_MAX);
|
wl_surface_damage_buffer(
|
||||||
|
surface.wl_surface,
|
||||||
|
MIN(surface.neko_x, surface.prev_neko_x), 0,
|
||||||
|
neko_size + neko_x_advance, neko_size
|
||||||
|
);
|
||||||
buffer->busy = true;
|
buffer->busy = true;
|
||||||
wl_surface_commit(surface.wl_surface);
|
wl_surface_commit(surface.wl_surface);
|
||||||
}
|
}
|
||||||
|
@ -683,10 +744,17 @@ static void layer_surface_handle_configure (void *data, struct zwlr_layer_surfac
|
||||||
(void)layer_surface;
|
(void)layer_surface;
|
||||||
|
|
||||||
zwlr_layer_surface_v1_ack_configure(surface.layer_surface, serial);
|
zwlr_layer_surface_v1_ack_configure(surface.layer_surface, serial);
|
||||||
surface.configured = true;
|
surface.width = width;
|
||||||
|
surface.height = height;
|
||||||
|
|
||||||
if ( width != surface_width || height != surface_height )
|
/* Center neko on first configure. */
|
||||||
fprintf(stderr, "ERROR: Bad dimensions in configure: %d %d\n", width, height);
|
if (!surface.configured)
|
||||||
|
{
|
||||||
|
surface.neko_x = (uint16_t)((width / 2) - neko_size);
|
||||||
|
surface.prev_neko_x = surface.neko_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface.configured = true;
|
||||||
|
|
||||||
surface_next_frame();
|
surface_next_frame();
|
||||||
}
|
}
|
||||||
|
@ -723,12 +791,11 @@ static void surface_create (void)
|
||||||
);
|
);
|
||||||
zwlr_layer_surface_v1_set_size(
|
zwlr_layer_surface_v1_set_size(
|
||||||
surface.layer_surface,
|
surface.layer_surface,
|
||||||
surface_width,
|
0, desired_surface_height
|
||||||
surface_height
|
|
||||||
);
|
);
|
||||||
zwlr_layer_surface_v1_set_anchor(
|
zwlr_layer_surface_v1_set_anchor(
|
||||||
surface.layer_surface,
|
surface.layer_surface,
|
||||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
|
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT
|
||||||
);
|
);
|
||||||
|
|
||||||
/* Empty input region. */
|
/* Empty input region. */
|
||||||
|
@ -805,6 +872,25 @@ static void timespec_diff (struct timespec *a, struct timespec *b, struct timesp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool colour_from_hex (pixman_color_t *colour, const char *hex)
|
||||||
|
{
|
||||||
|
uint16_t r = 0, g = 0, b = 0, a = 255;
|
||||||
|
|
||||||
|
if ( 4 != sscanf(hex, "0x%02hx%02hx%02hx%02hx", &r, &g, &b, &a)
|
||||||
|
&& 3 != sscanf(hex, "0x%02hx%02hx%02hx", &r, &g, &b) )
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Invalid colour: %s\n", hex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
colour->alpha = (uint16_t)(((double)a / 255.0) * 65535.0);
|
||||||
|
colour->red = (uint16_t)((((double)r / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
||||||
|
colour->green = (uint16_t)((((double)g / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
||||||
|
colour->blue = (uint16_t)((((double)b / 255.0) * 65535.0) * colour->alpha / 0xffff);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
init_signals();
|
init_signals();
|
||||||
|
@ -812,6 +898,9 @@ int main (void)
|
||||||
wl_list_init(&buffer_pool);
|
wl_list_init(&buffer_pool);
|
||||||
srand((unsigned int)time(0));
|
srand((unsigned int)time(0));
|
||||||
|
|
||||||
|
colour_from_hex(&bg_colour, "0xFFFFFF");
|
||||||
|
colour_from_hex(&border_colour, "0x000000");
|
||||||
|
|
||||||
// TODO command line args
|
// TODO command line args
|
||||||
|
|
||||||
if (!atlas_init())
|
if (!atlas_init())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue