diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5d84152 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "files.associations": { + "stdio.h": "c", + "sdl_main.h": "c", + "neko.h": "c", + "sdl_image.h": "c", + "array": "c", + "string": "c", + "string_view": "c", + "shape.h": "c" + } +} \ No newline at end of file diff --git a/Readme.md b/Readme.md index 8eeb44c..9dd62a1 100644 --- a/Readme.md +++ b/Readme.md @@ -1,6 +1,10 @@ # Catz Attack + +## Dependency +- A compositor, it can be installed using `nix-shell -p xcompmgr`. But it might be better to embedd it directly because nix is slow as fuck + ## Todo list - [x] Create a X window transparent overlay -- [ ] Afficher images +- [x] Afficher images - [ ] Afficher vidéos - [ ] Jouer du son diff --git a/build.sh b/build.sh index db16ecc..c04770f 100755 --- a/build.sh +++ b/build.sh @@ -1,8 +1,8 @@ #!/bin/sh echo Building with ... -echo gcc src/main.c -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes) -gcc src/main.c -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes) +echo gcc src/main.c -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes sdl3-image) +gcc src/main.c src/neko.c -I src/ -o res/main $(pkg-config --cflags --libs sdl3 x11 xfixes sdl3-image) echo Running... -./res/main +DISPLAY=:1 ./res/main diff --git a/res/main b/res/main index 9f81a43..e77d361 100755 Binary files a/res/main and b/res/main differ diff --git a/res/sample.gif b/res/sample.gif new file mode 100644 index 0000000..a39bce5 Binary files /dev/null and b/res/sample.gif differ diff --git a/res/sample.gif.BAK b/res/sample.gif.BAK new file mode 100644 index 0000000..b36a6ee Binary files /dev/null and b/res/sample.gif.BAK differ diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..6b1c8b5 --- /dev/null +++ b/src/common.h @@ -0,0 +1,7 @@ +#ifndef COMMON_H +#define COMMON_H + +extern int WINDOW_WIDTH; +extern int WINDOW_HEIGHT; + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index 4bfcb3a..66e364c 100644 --- a/src/main.c +++ b/src/main.c @@ -12,20 +12,37 @@ #include #include #include +#include #include #include +#include + #include +#include "neko.h" +#include "common.h" + /* We will use this renderer to draw into this window every frame. */ static SDL_Window *window = NULL; static SDL_Renderer *renderer = NULL; -static SDL_Texture *texture = NULL; -static int texture_width = 0; -static int texture_height = 0; +static IMG_Animation *anim; +static SDL_Texture **anim_textures; +static int current_frame = 1; -static int WINDOW_WIDTH; -static int WINDOW_HEIGHT; +int WINDOW_WIDTH; +int WINDOW_HEIGHT; + +void set_override_redirect() { + Display *dpy = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); + Window xwin = (Window)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); + + XSetWindowAttributes attrs; + attrs.override_redirect = True; + + XChangeWindowAttributes(dpy, xwin, CWOverrideRedirect, &attrs); + XFlush(dpy); +} void make_window_clickthrough() { Display *dpy = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); @@ -40,11 +57,15 @@ void make_window_clickthrough() { XFlush(dpy); } +Uint32 increment_frame(void *userdata, SDL_TimerID timerID, Uint32 interval){ + current_frame = (current_frame+1) % anim->count; + return(interval); +} + /* This function runs once at startup. */ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) { - SDL_Surface *surface = NULL; - char *bmp_path = NULL; + char *gif_path = NULL; SDL_SetAppMetadata("systemd", "1.0", "org.kernel.systemd"); @@ -67,7 +88,6 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) WINDOW_WIDTH = DisplayMode->w; WINDOW_HEIGHT = DisplayMode->h; - if (!SDL_CreateWindowAndRenderer("systemd", WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_TRANSPARENT | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_BORDERLESS , &window, &renderer)) { @@ -76,32 +96,31 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) } make_window_clickthrough(); + set_override_redirect(); - /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D - engines refer to these as "sprites." We'll do a static texture (upload once, draw many - times) with data from a bitmap file. */ + neko_init(renderer); - /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. - Load a .bmp into a surface, move it to a texture from there. */ - SDL_asprintf(&bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ - surface = SDL_LoadBMP(bmp_path); - if (!surface) { - SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); + /* Open the image file */ + SDL_asprintf(&gif_path, "%ssample.gif", SDL_GetBasePath()); + anim = IMG_LoadAnimation(gif_path); + if (!anim) { + SDL_Log("Couldn't load %s: %s\n", gif_path, SDL_GetError()); return SDL_APP_FAILURE; } + SDL_free(gif_path); /* done with this, the file is loaded. */ + int aw = anim->w; + int ah = anim->h; - SDL_free(bmp_path); /* done with this, the file is loaded. */ - - texture_width = surface->w; - texture_height = surface->h; - - texture = SDL_CreateTextureFromSurface(renderer, surface); - if (!texture) { - SDL_Log("Couldn't create static texture: %s", SDL_GetError()); + anim_textures = (SDL_Texture **)SDL_calloc(anim->count, sizeof(*anim_textures)); + if (!anim_textures) { + SDL_Log("Couldn't allocate textures\n"); + IMG_FreeAnimation(anim); return SDL_APP_FAILURE; } - - SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ + for (int i = 0; i < anim->count; ++i) { + anim_textures[i] = SDL_CreateTextureFromSurface(renderer, anim->frames[i]); + } + SDL_AddTimer(anim->delays[0], increment_frame, NULL); return SDL_APP_CONTINUE; /* carry on with the program! */ } @@ -121,37 +140,18 @@ SDL_AppResult SDL_AppIterate(void *appstate) SDL_FRect dst_rect; const Uint64 now = SDL_GetTicks(); - /* we'll have some textures move around over a few seconds. */ - const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; - const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; - /* as you can see from this, rendering draws over whatever was drawn before it. */ SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_TRANSPARENT); /* black, full alpha */ SDL_RenderClear(renderer); /* start with a blank canvas. */ - /* Just draw the static texture a few times. You can think of it like a - stamp, there isn't a limit to the number of times you can draw with it. */ - - /* top left */ - dst_rect.x = (100.0f * scale); - dst_rect.y = 0.0f; - dst_rect.w = (float) texture_width; - dst_rect.h = (float) texture_height; - SDL_RenderTexture(renderer, texture, NULL, &dst_rect); - - /* center this one. */ - dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; - dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; - dst_rect.w = (float) texture_width; - dst_rect.h = (float) texture_height; - SDL_RenderTexture(renderer, texture, NULL, &dst_rect); - - /* bottom right. */ - dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale); - dst_rect.y = (float) (WINDOW_HEIGHT - texture_height); - dst_rect.w = (float) texture_width; - dst_rect.h = (float) texture_height; - SDL_RenderTexture(renderer, texture, NULL, &dst_rect); + neko_render(renderer, window); + /* + dst_rect.x = WINDOW_HEIGHT/2; + dst_rect.y = WINDOW_HEIGHT/2; + dst_rect.h = WINDOW_HEIGHT/10; + dst_rect.w = WINDOW_HEIGHT/10; + SDL_RenderTexture(renderer, anim_textures[current_frame], NULL, &dst_rect); + */ SDL_RenderPresent(renderer); /* put it all on the screen! */ @@ -161,6 +161,31 @@ SDL_AppResult SDL_AppIterate(void *appstate) /* This function runs once at shutdown. */ void SDL_AppQuit(void *appstate, SDL_AppResult result) { - SDL_DestroyTexture(texture); + neko_quit(); /* SDL will clean up the window/renderer for us. */ -} \ No newline at end of file +} + +/* BACKUP SDL_AppIterate + + const float direction = ((now % 2000) >= 1000) ? 1.0f : -1.0f; + const float scale = ((float) (((int) (now % 1000)) - 500) / 500.0f) * direction; + + dst_rect.x = (100.0f * scale); + dst_rect.y = 0.0f; + dst_rect.w = (float) texture_width; + dst_rect.h = (float) texture_height; + SDL_RenderTexture(renderer, texture, NULL, &dst_rect); + + + dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) / 2.0f; + dst_rect.y = ((float) (WINDOW_HEIGHT - texture_height)) / 2.0f; + dst_rect.w = (float) texture_width/2; + dst_rect.h = (float) texture_height/2; + SDL_RenderTexture(renderer, texture, NULL, &dst_rect); + + + dst_rect.x = ((float) (WINDOW_WIDTH - texture_width)) - (100.0f * scale); + dst_rect.y = (float) (WINDOW_HEIGHT - texture_height); + dst_rect.w = (float) texture_width; + dst_rect.h = (float) texture_height; +*/ \ No newline at end of file diff --git a/src/neko.c b/src/neko.c new file mode 100644 index 0000000..c403f6b --- /dev/null +++ b/src/neko.c @@ -0,0 +1,64 @@ +#include "neko.h" +#include "common.h" + +static SDL_Texture *texture = NULL; +static int texture_width = 0; +static int texture_height = 0; + +static float catx = 200; +static float caty = 200; + +int neko_init(SDL_Renderer *renderer){ + SDL_Surface *surface = NULL; + char *neko_bmp_path = NULL; + + /* Textures are pixel data that we upload to the video hardware for fast drawing. Lots of 2D + engines refer to these as "sprites." We'll do a static texture (upload once, draw many + times) with data from a bitmap file. */ + + /* SDL_Surface is pixel data the CPU can access. SDL_Texture is pixel data the GPU can access. + Load a .bmp into a surface, move it to a texture from there. */ + SDL_asprintf(&neko_bmp_path, "%ssample.bmp", SDL_GetBasePath()); /* allocate a string of the full file path */ + surface = SDL_LoadBMP(neko_bmp_path); + if (!surface) { + SDL_Log("Couldn't load bitmap: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + SDL_free(neko_bmp_path); /* done with this, the file is loaded. */ + + texture_width = surface->w; + texture_height = surface->h; + + texture = SDL_CreateTextureFromSurface(renderer, surface); + if (!texture) { + SDL_Log("Couldn't create static texture: %s", SDL_GetError()); + return SDL_APP_FAILURE; + } + + SDL_DestroySurface(surface); /* done with this, the texture has a copy of the pixels now. */ + +} + +void neko_render(SDL_Renderer *renderer, SDL_Window *window){ + float mousex, mousey; + int windowx, windowy; + float diffx, diffy; + SDL_FRect dst_rect; + + SDL_GetGlobalMouseState(&mousex, &mousey); + SDL_GetWindowPosition(window, &windowx, &windowy); + diffx = catx-(mousex-(float)windowx); + diffy = caty-(mousey-(float)windowy); + SDL_Log("(%f, %f)", diffx, diffy); + + dst_rect.x = catx+(diffx/diffy); + dst_rect.y = caty+(diffy/diffx); + dst_rect.h = WINDOW_HEIGHT/10; + dst_rect.w = WINDOW_HEIGHT/10; + SDL_RenderTexture(renderer, texture, NULL, &dst_rect); +} + +void neko_quit(){ + SDL_DestroyTexture(texture); +} \ No newline at end of file diff --git a/src/neko.h b/src/neko.h new file mode 100644 index 0000000..0a6e976 --- /dev/null +++ b/src/neko.h @@ -0,0 +1,14 @@ +#ifndef NEKO_H +#define NEKO_H + +#include +#include +#include + +#include + +int neko_init(SDL_Renderer *renderer); +void neko_render(SDL_Renderer *renderer, SDL_Window *window); +void neko_quit(); + +#endif \ No newline at end of file