From 0b7fdbf8e1e6231e3c6c12828243af46244cf40a Mon Sep 17 00:00:00 2001 From: Vinyl Darkscratch Date: Mon, 12 Dec 2016 22:59:07 -0800 Subject: [PATCH] Updates for a future Mac build --- .gitignore | 6 + CMakeLists.txt | 12 +- binding-mri/journal-binding.cpp | 54 +++++--- binding-mri/niko-binding.cpp | 9 +- journal/journal.pro | 47 +++++++ journal/mac/display.h | 17 +++ journal/mac/image.h | 113 +++++++++++++++ journal/mac/image/.gitignore | 1 + journal/mac/image/pixmapper.sh | 12 ++ journal/mac/journal.c | 235 ++++++++++++++++++++++++++++++++ journal/mac/main.c | 26 ++++ journal/mac/niko.c | 114 ++++++++++++++++ mkxp.pro | 18 +-- src/oneshot.cpp | 128 ++++++++++------- 14 files changed, 698 insertions(+), 94 deletions(-) create mode 100644 journal/mac/display.h create mode 100644 journal/mac/image.h create mode 100644 journal/mac/image/.gitignore create mode 100755 journal/mac/image/pixmapper.sh create mode 100644 journal/mac/journal.c create mode 100644 journal/mac/main.c create mode 100644 journal/mac/niko.c diff --git a/.gitignore b/.gitignore index b48c7ee..4ca6d29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ *.o *.pro.* +*.cmake *.bak *.xxd *.exe +*.app *.bmp Makefile* @@ -16,3 +18,7 @@ Makefile* object_script.* rpgscript.bat + +.qmake.stash +CMakeCache.txt +CMakeFiles/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d875826..aa749de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,8 +6,8 @@ Project(mkxp) option(SHARED_FLUID "Dynamically link fluidsynth at build time" OFF) option(WORKDIR_CURRENT "Keep current directory on startup" OFF) option(FORCE32 "Force 32bit compile on 64bit OS" OFF) -set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, MRUBY, NULL)") -set(EXTERNAL_LIB_PATH "" CACHE PATH "External precompiled lib prefix") +set(BINDING "MRI" CACHE STRING "The Binding Type (MRI, NULL)") +set(EXTERNAL_LIB_PATH "/usr/local/opt/ruby21" CACHE PATH "External precompiled lib prefix") ## Misc setup ## @@ -151,7 +151,7 @@ set(MAIN_HEADERS src/alstream.h src/audiostream.h src/rgssad.h - src/windowvx.h + src/window.h src/tilemapvx.h src/tileatlasvx.h src/sharedmidistate.h @@ -197,7 +197,7 @@ set(MAIN_SOURCE src/rgssad.cpp src/bundledfont.cpp src/vorbissource.cpp - src/windowvx.cpp + src/window.cpp src/tilemapvx.cpp src/tileatlasvx.cpp src/autotilesvx.cpp @@ -318,8 +318,8 @@ if (BINDING STREQUAL "MRI") binding-mri/audio-binding.cpp binding-mri/module_rpg.cpp binding-mri/filesystem-binding.cpp - binding-mri/windowvx-binding.cpp - binding-mri/tilemapvx-binding.cpp + binding-mri/window-binding.cpp + binding-mri/tilemap-binding.cpp ) elseif(BINDING STREQUAL "MRUBY") message(FATAL_ERROR "Mruby support in CMake needs to be finished") diff --git a/binding-mri/journal-binding.cpp b/binding-mri/journal-binding.cpp index 6954dcc..b922b1f 100644 --- a/binding-mri/journal-binding.cpp +++ b/binding-mri/journal-binding.cpp @@ -5,12 +5,26 @@ #include -#if defined __linux -#include -#include -#include -#include -#include +//OS-Specific code +#if defined _WIN32 + #define OS_W32 +#elif defined __APPLE__ || __linux__ + #define LINUX + #ifdef __APPLE__ + #define OS_OSX + #else + #define OS_LINUX + #endif + + #include + #include + #include + #ifdef OS_LINUX + #include + #endif + #include +#else + #error "Operating system not detected." #endif #define BUFFER_SIZE 256 @@ -20,20 +34,20 @@ static SDL_mutex *mutex = NULL; static volatile char message_buffer[BUFFER_SIZE]; static volatile bool active = false; -#if defined __linux -#define PIPE_PATH "/tmp/oneshot-pipe" -static volatile int message_len = 0; -static volatile int out_pipe = -1; -void cleanup_pipe() -{ - unlink(PIPE_PATH); -} +#ifdef LINUX + #define PIPE_PATH "/tmp/oneshot-pipe" + static volatile int message_len = 0; + static volatile int out_pipe = -1; + void cleanup_pipe() + { + unlink(PIPE_PATH); + } #endif int server_thread(void *data) { (void)data; -#if defined _WIN32 +#if defined OS_W32 HANDLE pipe = CreateNamedPipeW(L"\\\\.\\pipe\\oneshot-journal-to-game", PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE | PIPE_WAIT, @@ -53,7 +67,7 @@ int server_thread(void *data) DisconnectNamedPipe(pipe); } CloseHandle(pipe); -#elif defined __linux +#else out_pipe = open(PIPE_PATH, O_WRONLY); active = true; SDL_LockMutex(mutex); @@ -69,7 +83,7 @@ RB_METHOD(journalSet) RB_UNUSED_PARAM; const char *name; rb_get_args(argc, argv, "z", &name RB_ARG_END); -#if defined _WIN32 +#if defined OS_W32 SDL_LockMutex(mutex); strcpy((char*)message_buffer, name); SDL_UnlockMutex(mutex); @@ -90,7 +104,7 @@ RB_METHOD(journalSet) if (thread == NULL) { thread = SDL_CreateThread(server_thread, "journal", NULL); } -#elif defined __linux +#else // Clean up connection thread if (thread != NULL && out_pipe != -1) { SDL_WaitThread(thread, NULL); @@ -115,8 +129,6 @@ RB_METHOD(journalSet) // We don't have a pipe open, so spawn the connection thread thread = SDL_CreateThread(server_thread, "journal", NULL); } -#else -#error "not yet implemented" #endif return Qnil; } @@ -130,7 +142,7 @@ RB_METHOD(journalActive) void journalBindingInit() { mutex = SDL_CreateMutex(); -#if defined __linux +#ifdef LINUX mkfifo(PIPE_PATH, 0666); atexit(cleanup_pipe); #endif diff --git a/binding-mri/niko-binding.cpp b/binding-mri/niko-binding.cpp index 2d677b5..20c9d6c 100644 --- a/binding-mri/niko-binding.cpp +++ b/binding-mri/niko-binding.cpp @@ -6,6 +6,13 @@ #if defined _WIN32 #include +#elif defined __APPLE__ || __linux__ + #define LINUX + #ifdef __APPLE__ + #define OS_OSX + #else + #define OS_LINUX + #endif #endif #include @@ -43,7 +50,7 @@ RB_METHOD(nikoStart) si.cb = sizeof(si); PROCESS_INFORMATION pi; CreateProcessW(path, args, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); -#elif defined __linux +#elif defined LINUX // Calculate where to stick the window int x, y; // Top-left area of client (hopefully) SDL_GetWindowPosition(shState->rtData().window, &x, &y); diff --git a/journal/journal.pro b/journal/journal.pro index 44867c6..4e0106f 100644 --- a/journal/journal.pro +++ b/journal/journal.pro @@ -53,6 +53,53 @@ unix:!macx { # OS X macx { + # Directly copied from Linux, assuming this works but unsure + + SOURCES += \ + mac/main.c \ + mac/niko.c \ + mac/journal.c \ + mac/image/niko1.c \ + mac/image/niko2.c \ + mac/image/niko3.c \ + mac/image/default.c \ + mac/image/c1.c \ + mac/image/c2.c \ + mac/image/c3.c \ + mac/image/c4.c \ + mac/image/c5.c \ + mac/image/c6.c \ + mac/image/c7.c \ + mac/image/s1.c \ + mac/image/s2.c \ + mac/image/s3.c \ + mac/image/s4.c \ + mac/image/t1.c \ + mac/image/t2.c \ + mac/image/t3.c \ + mac/image/t4.c \ + mac/image/t5.c \ + mac/image/t6.c \ + mac/image/t7.c \ + mac/image/t8.c \ + mac/image/t9.c \ + mac/image/t10.c \ + mac/image/t11.c \ + mac/image/t12.c \ + mac/image/t13.c \ + mac/image/t14.c \ + mac/image/t15.c \ + mac/image/t16.c \ + mac/image/final.c \ + mac/image/save.c + + HEADERS += \ + mac/display.h \ + mac/image.h + + QMAKE_CFLAGS += -pthread + + LIBS += -pthread -lxcb -lxcb-util -lxcb-image -lxcb-shape -lxcb-icccm -lxcb-ewmh } # Windows diff --git a/journal/mac/display.h b/journal/mac/display.h new file mode 100644 index 0000000..8592baf --- /dev/null +++ b/journal/mac/display.h @@ -0,0 +1,17 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include +#include +#include + +struct Display { + xcb_connection_t *c; + xcb_screen_t *screen; +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define STRING(x) sizeof(x) - 1, (x) +#define ARRAY(x) sizeof(x), (x) + +#endif // DISPLAY_H diff --git a/journal/mac/image.h b/journal/mac/image.h new file mode 100644 index 0000000..f6f34f7 --- /dev/null +++ b/journal/mac/image.h @@ -0,0 +1,113 @@ +#ifndef EMBED_H +#define EMBED_H + +#include +#include +#include + +static inline xcb_pixmap_t create_mask(xcb_connection_t *c, + xcb_window_t win, + unsigned char *bits, + uint32_t width, + uint32_t height) +{ + return xcb_create_pixmap_from_bitmap_data(c, win, bits, width, height, 1, 0, 0, NULL); +} + +static inline xcb_pixmap_t create_image(xcb_connection_t *c, + xcb_window_t win, + unsigned char *bytes, + uint32_t width, + uint32_t height) +{ + xcb_image_t *image = xcb_image_create_native( + c, width, height, XCB_IMAGE_FORMAT_Z_PIXMAP, 24, NULL, width * height * 4, bytes); + xcb_pixmap_t pixmap = xcb_generate_id(c); + xcb_create_pixmap(c, 24, pixmap, win, width, height); + xcb_gcontext_t gc = xcb_generate_id(c); + xcb_create_gc(c, gc, pixmap, 0, NULL); + xcb_image_put(c, pixmap, gc, image, 0, 0, 0); + xcb_image_destroy(image); + xcb_free_gc(c, gc); + return pixmap; + +} + +static inline void set_shape(xcb_connection_t *c, xcb_window_t win, xcb_pixmap_t mask) +{ + xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, mask); +} + +#define NIKO_WIDTH 48 +#define NIKO_HEIGHT 64 +extern unsigned char niko1_mask[]; +extern unsigned char niko1_rgb[]; +extern unsigned char niko2_mask[]; +extern unsigned char niko2_rgb[]; +extern unsigned char niko3_mask[]; +extern unsigned char niko3_rgb[]; + +#define JOURNAL_WIDTH 800 +#define JOURNAL_HEIGHT 600 +extern unsigned char default_mask[]; +extern unsigned char default_rgb[]; +extern unsigned char c1_mask[]; +extern unsigned char c1_rgb[]; +extern unsigned char c2_mask[]; +extern unsigned char c2_rgb[]; +extern unsigned char c3_mask[]; +extern unsigned char c3_rgb[]; +extern unsigned char c4_mask[]; +extern unsigned char c4_rgb[]; +extern unsigned char c5_mask[]; +extern unsigned char c5_rgb[]; +extern unsigned char c6_mask[]; +extern unsigned char c6_rgb[]; +extern unsigned char c7_mask[]; +extern unsigned char c7_rgb[]; +extern unsigned char s1_mask[]; +extern unsigned char s1_rgb[]; +extern unsigned char s2_mask[]; +extern unsigned char s2_rgb[]; +extern unsigned char s3_mask[]; +extern unsigned char s3_rgb[]; +extern unsigned char s4_mask[]; +extern unsigned char s4_rgb[]; +extern unsigned char t1_mask[]; +extern unsigned char t1_rgb[]; +extern unsigned char t2_mask[]; +extern unsigned char t2_rgb[]; +extern unsigned char t3_mask[]; +extern unsigned char t3_rgb[]; +extern unsigned char t4_mask[]; +extern unsigned char t4_rgb[]; +extern unsigned char t5_mask[]; +extern unsigned char t5_rgb[]; +extern unsigned char t6_mask[]; +extern unsigned char t6_rgb[]; +extern unsigned char t7_mask[]; +extern unsigned char t7_rgb[]; +extern unsigned char t8_mask[]; +extern unsigned char t8_rgb[]; +extern unsigned char t9_mask[]; +extern unsigned char t9_rgb[]; +extern unsigned char t10_mask[]; +extern unsigned char t10_rgb[]; +extern unsigned char t11_mask[]; +extern unsigned char t11_rgb[]; +extern unsigned char t12_mask[]; +extern unsigned char t12_rgb[]; +extern unsigned char t13_mask[]; +extern unsigned char t13_rgb[]; +extern unsigned char t14_mask[]; +extern unsigned char t14_rgb[]; +extern unsigned char t15_mask[]; +extern unsigned char t15_rgb[]; +extern unsigned char t16_mask[]; +extern unsigned char t16_rgb[]; +extern unsigned char final_mask[]; +extern unsigned char final_rgb[]; +extern unsigned char save_mask[]; +extern unsigned char save_rgb[]; + +#endif // EMBED_H diff --git a/journal/mac/image/.gitignore b/journal/mac/image/.gitignore new file mode 100644 index 0000000..064a8d8 --- /dev/null +++ b/journal/mac/image/.gitignore @@ -0,0 +1 @@ +*.c diff --git a/journal/mac/image/pixmapper.sh b/journal/mac/image/pixmapper.sh new file mode 100755 index 0000000..546258d --- /dev/null +++ b/journal/mac/image/pixmapper.sh @@ -0,0 +1,12 @@ +#!/bin/bash +if [ $# -lt 1 ]; then + echo "usage: pixmapper.sh " + exit 1 +fi +basename="$(basename "$1" | tr '[:upper:]' '[:lower:]')" +name="${basename%.*}" +cfile="$name.c" +convert "$1" -alpha on -transparent '#00ff00' -alpha extract -negate xbm:- | sed "/^#define/d;s/-_bits/${name}_mask/g;s/^static char/unsigned char/" > "$cfile" +echo "unsigned char ${name}_rgb[] = {" >> "$cfile" +convert "$1" -alpha on -transparent '#00ff00' -depth 8 bgra:- | xxd -i >> "$cfile" +echo "};" >> "$cfile" diff --git a/journal/mac/journal.c b/journal/mac/journal.c new file mode 100644 index 0000000..f8cc299 --- /dev/null +++ b/journal/mac/journal.c @@ -0,0 +1,235 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "display.h" +#include "image.h" + +#define PIPE_DIR "/tmp" +#define PIPE_NAME "oneshot-pipe" +#define PIPE_PATH PIPE_DIR "/" PIPE_NAME +#define MESSAGE_BUF_SIZE 256 + +#define PAGES \ + PAGE(default) \ + PAGE(c1) \ + PAGE(c2) \ + PAGE(c3) \ + PAGE(c4) \ + PAGE(c5) \ + PAGE(c6) \ + PAGE(c7) \ + PAGE(s1) \ + PAGE(s2) \ + PAGE(s3) \ + PAGE(s4) \ + PAGE(t1) \ + PAGE(t2) \ + PAGE(t3) \ + PAGE(t4) \ + PAGE(t5) \ + PAGE(t6) \ + PAGE(t7) \ + PAGE(t8) \ + PAGE(t9) \ + PAGE(t10) \ + PAGE(t11) \ + PAGE(t12) \ + PAGE(t13) \ + PAGE(t14) \ + PAGE(t15) \ + PAGE(t16) \ + PAGE(final) \ + PAGE(save) + +struct ThreadData { + struct Display *dpy; + xcb_window_t window; + xcb_gcontext_t gc; + xcb_pixmap_t *masks; + xcb_pixmap_t *images; + volatile int page; +}; + +void set_page(struct ThreadData *threaddata, const char *name) +{ + int page = 0; +#define PAGE(x) if (strncmp(name, #x, MESSAGE_BUF_SIZE) == 0) { goto end; } else { ++page; } + PAGES +#undef PAGE + +end: + threaddata->page = page; + xcb_shape_mask(threaddata->dpy->c, ShapeSet, ShapeBounding, + threaddata->window, 0, 0, threaddata->masks[page]); + xcb_copy_area(threaddata->dpy->c, + threaddata->images[page], + threaddata->window, + threaddata->gc, + 0, 0, 0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT); + xcb_flush(threaddata->dpy->c); +} + +static void *ipc_thread(void *data) +{ + struct ThreadData *threaddata = (struct ThreadData*)data; + + for (;;) { + // Try to open pipe + int pipe = open(PIPE_PATH, O_RDONLY); + if (pipe == -1) { + // Use the default image for now + set_page(threaddata, "default"); + // Wait until the pipe appears to try again + int inotify = inotify_init(); + inotify_add_watch(inotify, PIPE_DIR, IN_CREATE); + char inotify_buf[sizeof(struct inotify_event) + NAME_MAX + 1]; + for (;;) { + ssize_t result = read(inotify, inotify_buf, sizeof(inotify_buf)); + if (result > 0) { + struct inotify_event *e = (struct inotify_event*)inotify_buf; + if (strcmp(e->name, PIPE_NAME) == 0) + break; + } else { + break; + } + } + close(inotify); + } else { + // Message loop + char message[MESSAGE_BUF_SIZE]; + for (;;) { + ssize_t len = read(pipe, message, sizeof(message)); + if (len > 0) { + set_page(threaddata, message); + } else if (len == 0) { + exit(0); // empty string + } else { + // End of the line + break; + } + } + close(pipe); + } + } + + return NULL; +} + +int do_journal(struct Display *dpy) +{ + // Connect EWMH + xcb_ewmh_connection_t ewmh; + xcb_ewmh_init_atoms_replies(&ewmh, xcb_ewmh_init_atoms(dpy->c, &ewmh), NULL); + + // Request some atoms + xcb_intern_atom_cookie_t WM_DELETE_WINDOW_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_DELETE_WINDOW")); + xcb_intern_atom_cookie_t _NET_WM_PING_cookie = xcb_intern_atom(dpy->c, false, STRING("_NET_WM_PING")); + xcb_intern_atom_cookie_t WM_PROTOCOLS_cookie = xcb_intern_atom(dpy->c, false, STRING("WM_PROTOCOLS")); + xcb_atom_t WM_DELETE_WINDOW = xcb_intern_atom_reply(dpy->c, WM_DELETE_WINDOW_cookie, NULL)->atom; + xcb_atom_t _NET_WM_PING = xcb_intern_atom_reply(dpy->c, _NET_WM_PING_cookie, NULL)->atom; + xcb_atom_t WM_PROTOCOLS = xcb_intern_atom_reply(dpy->c, WM_PROTOCOLS_cookie, NULL)->atom; + + // Create window + uint32_t values[] = { + XCB_EVENT_MASK_EXPOSURE, // event mask + }; + xcb_window_t window = xcb_generate_id(dpy->c); + xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root, + 0, 0, JOURNAL_WIDTH, JOURNAL_HEIGHT, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual, + XCB_CW_EVENT_MASK, &values); + + xcb_atom_t protocols[] = { + WM_DELETE_WINDOW, + _NET_WM_PING, + }; + xcb_icccm_set_wm_protocols(dpy->c, window, WM_PROTOCOLS, ARRAY(protocols)); + + xcb_icccm_set_wm_name(dpy->c, window, XCB_ATOM_STRING, 8, STRING("")); + xcb_icccm_set_wm_class(dpy->c, window, ARRAY("_______\0OneshotJournal")); + xcb_ewmh_set_wm_window_type(&ewmh, window, 1, &ewmh._NET_WM_WINDOW_TYPE_NORMAL); + + xcb_size_hints_t size_hints; + xcb_icccm_size_hints_set_min_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT); + xcb_icccm_size_hints_set_max_size(&size_hints, JOURNAL_WIDTH, JOURNAL_HEIGHT); + xcb_icccm_set_wm_size_hints(dpy->c, window, XCB_ATOM_WM_NORMAL_HINTS, &size_hints); + + // Create pixmaps + xcb_pixmap_t masks[] = { +#define PAGE(x) create_mask(dpy->c, window, x##_mask, JOURNAL_WIDTH, JOURNAL_HEIGHT), + PAGES +#undef PAGE + }; + xcb_pixmap_t images[] = { +#define PAGE(x) create_image(dpy->c, window, x##_rgb, JOURNAL_WIDTH, JOURNAL_HEIGHT), + PAGES +#undef PAGE + }; + + // Create graphics context + xcb_gcontext_t gc = xcb_generate_id(dpy->c); + xcb_create_gc(dpy->c, gc, window, 0, NULL); + + // Start IPC thread + struct ThreadData threaddata = { + dpy, + window, + gc, + masks, + images, + 0, + }; + pthread_t thread; + if (pthread_create(&thread, NULL, ipc_thread, &threaddata) != 0) + return 1; + + // Map! + xcb_map_window(dpy->c, window); + xcb_flush(dpy->c); + + // Handle events + xcb_generic_event_t *e; + while ((e = xcb_wait_for_event(dpy->c))) { + switch (e->response_type & ~0x80) { + case XCB_EXPOSE: { + xcb_expose_event_t *ee = (xcb_expose_event_t*)e; + xcb_copy_area(dpy->c, images[threaddata.page], + window, gc, + ee->x, ee->y, ee->x, ee->y, + ee->width, ee->height); + xcb_flush(dpy->c); + } break; + case XCB_CLIENT_MESSAGE: { + xcb_client_message_event_t *ce = (xcb_client_message_event_t*)e; + if (ce->type == WM_PROTOCOLS && ce->format == 32) { + xcb_atom_t atom = ce->data.data32[0]; + if (atom == WM_DELETE_WINDOW) { + goto end; + } else if (atom == _NET_WM_PING) { + ce->window = dpy->screen->root; + xcb_send_event(dpy->c, false, dpy->screen->root, + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, + (const char*)e); + } + } + } break; + } + free(e); + } + +end: + xcb_free_gc(dpy->c, gc); + for (size_t i = 0; i < ARRAY_SIZE(masks); ++i) { + xcb_free_pixmap(dpy->c, masks[i]); + xcb_free_pixmap(dpy->c, images[i]); + } + return 0; +} diff --git a/journal/mac/main.c b/journal/mac/main.c new file mode 100644 index 0000000..d68837d --- /dev/null +++ b/journal/mac/main.c @@ -0,0 +1,26 @@ +#include "display.h" + +extern int do_niko(struct Display *dpy, int x, int y); +extern int do_journal(struct Display *dpy); + +int main(int argc, char **argv) +{ + // Connect + struct Display dpy; + dpy.c = xcb_connect(NULL, NULL); + dpy.screen = xcb_setup_roots_iterator(xcb_get_setup(dpy.c)).data; + + int result; + if (argc == 3) { + // argc == 3, assume niko + int x = atoi(argv[1]); + int y = atoi(argv[2]); + result = do_niko(&dpy, x, y); + } else { + // argc == 3, assume journal + result = do_journal(&dpy); + } + + xcb_disconnect(dpy.c); + return result; +} diff --git a/journal/mac/niko.c b/journal/mac/niko.c new file mode 100644 index 0000000..eb99afb --- /dev/null +++ b/journal/mac/niko.c @@ -0,0 +1,114 @@ +#include + +#include "display.h" +#include "image.h" + +static uint64_t getticks() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (uint64_t)tv.tv_sec * 1000 + (uint64_t)tv.tv_usec / 1000; +} + +static void draw_niko(xcb_connection_t *c, + xcb_window_t win, + xcb_gcontext_t gc, + xcb_pixmap_t masks[3], + xcb_pixmap_t images[3], + int x, int y, int w, int h, + int offset) +{ + int frame; + if (offset % 32 >= 16) { + frame = 1; + } else { + if ((offset / 32) % 2) + frame = 0; + else + frame = 2; + } + xcb_shape_mask(c, ShapeSet, ShapeBounding, win, 0, 0, masks[frame]); + xcb_copy_area(c, images[frame], win, gc, x, y, x, y, w, h); + +} + +int do_niko(struct Display *dpy, int x, int y) +{ + // Create window + uint32_t values[] = { + true, // override_redirect + XCB_EVENT_MASK_EXPOSURE, // event mask + }; + xcb_window_t window = xcb_generate_id(dpy->c); + xcb_create_window(dpy->c, XCB_COPY_FROM_PARENT, window, dpy->screen->root, + x, y, NIKO_WIDTH, NIKO_HEIGHT, + 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, dpy->screen->root_visual, + XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK, &values); + + // Stick window on top + xcb_stack_mode_t stack = XCB_STACK_MODE_ABOVE; + xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_STACK_MODE, &stack); + + // Create pixmaps + xcb_pixmap_t niko_masks[] = { + create_mask(dpy->c, window, niko1_mask, NIKO_WIDTH, NIKO_HEIGHT), + create_mask(dpy->c, window, niko2_mask, NIKO_WIDTH, NIKO_HEIGHT), + create_mask(dpy->c, window, niko3_mask, NIKO_WIDTH, NIKO_HEIGHT), + }; + xcb_pixmap_t niko_images[] = { + create_image(dpy->c, window, niko1_rgb, NIKO_WIDTH, NIKO_HEIGHT), + create_image(dpy->c, window, niko2_rgb, NIKO_WIDTH, NIKO_HEIGHT), + create_image(dpy->c, window, niko3_rgb, NIKO_WIDTH, NIKO_HEIGHT), + }; + + // Create graphics context + xcb_gcontext_t gc = xcb_generate_id(dpy->c); + xcb_create_gc(dpy->c, gc, window, 0, NULL); + + // Map! + xcb_map_window(dpy->c, window); + xcb_flush(dpy->c); + + // Niko movement info + int niko_offset = 0; + + uint64_t ticks = getticks(); + for (;;) { + // Handle events + for (;;) { + xcb_generic_event_t *e = xcb_poll_for_event(dpy->c); + if (e) { + switch (e->response_type) { + case XCB_EXPOSE: { + xcb_expose_event_t *ee = (xcb_expose_event_t*)e; + draw_niko(dpy->c, window, gc, niko_masks, niko_images, + ee->x, ee->y, ee->width, ee->height, niko_offset); + xcb_flush(dpy->c); + } break; + } + free(e); + } else if (getticks() - ticks >= 1000 / 60) { + break; + } + } + + // Move niko + niko_offset += 2; + int new_y = y + niko_offset; + if (new_y > dpy->screen->height_in_pixels) + break; + xcb_configure_window(dpy->c, window, XCB_CONFIG_WINDOW_Y, &new_y); + draw_niko(dpy->c, window, gc, niko_masks, niko_images, 0, 0, NIKO_WIDTH, NIKO_HEIGHT, niko_offset); + xcb_flush(dpy->c); + ticks = getticks(); + } + + // Free up stuff + xcb_free_gc(dpy->c, gc); + for (int i = 0; i < 3; ++i) { + xcb_free_pixmap(dpy->c, niko_masks[i]); + xcb_free_pixmap(dpy->c, niko_images[i]); + } + + return 0; +} diff --git a/mkxp.pro b/mkxp.pro index cf06c11..e7267c9 100644 --- a/mkxp.pro +++ b/mkxp.pro @@ -24,15 +24,6 @@ contains(BINDING, MRI) { CONFIG += BINDING_MRI } -contains(BINDING, MRUBY) { - contains(_HAVE_BINDING, YES) { - error("Only one binding may be selected") - } - _HAVE_BINDING = YES - - CONFIG += BINDING_MRUBY -} - contains(BINDING, NULL) { contains(_HAVE_BINDING, YES) { error("Only one binding may be selected") @@ -45,12 +36,13 @@ contains(BINDING, NULL) { unix { CONFIG += c++11 PKGCONFIG += sigc++-2.0 pixman-1 vorbisfile \ - sdl2 SDL2_image SDL2_ttf SDL_sound physfs - LIBS += -ldl + sdl2 SDL2_image SDL2_ttf SDL_sound physfs + LIBS += -ldl macx: { - CONFIG -= app_bundle + #CONFIG -= app_bundle INCLUDEPATH += $$QMAKE_MAC_SDK_PATH/System/Library/Frameworks/OpenAL.framework/Versions/A/Headers LIBS += -framework OpenAL + QMAKE_LFLAGS += -L/usr/local/opt/ruby21/lib -L/usr/local/opt/openal-soft/lib } !macx: { PKGCONFIG += openal zlib @@ -252,7 +244,7 @@ BINDING_NULL { BINDING_MRI { isEmpty(MRIVERSION) { - MRIVERSION = 2.2 + MRIVERSION = 2.1 } PKGCONFIG += ruby-$$MRIVERSION diff --git a/src/oneshot.cpp b/src/oneshot.cpp index 2c3afe6..640a4b2 100644 --- a/src/oneshot.cpp +++ b/src/oneshot.cpp @@ -18,50 +18,54 @@ #include #include #include -#elif defined __APPLE__ - #define OS_OSX - #include -#elif defined __linux__ - #define OS_LINUX +#elif defined __APPLE__ || __linux__ + #ifdef __APPLE__ + #define OS_OSX + #else + #define OS_LINUX + #endif + #include #include #include #include - class GtkWidget; + #ifdef OS_LINUX + class GtkWidget; - typedef enum - { - GTK_MESSAGE_INFO, - GTK_MESSAGE_WARNING, - GTK_MESSAGE_QUESTION, - GTK_MESSAGE_ERROR - } GtkMessageType; + typedef enum + { + GTK_MESSAGE_INFO, + GTK_MESSAGE_WARNING, + GTK_MESSAGE_QUESTION, + GTK_MESSAGE_ERROR + } GtkMessageType; - typedef enum - { - GTK_BUTTONS_NONE, - GTK_BUTTONS_OK, - GTK_BUTTONS_CLOSE, - GTK_BUTTONS_CANCEL, - GTK_BUTTONS_YES_NO, - GTK_BUTTONS_OK_CANCEL - } GtkButtonsType; + typedef enum + { + GTK_BUTTONS_NONE, + GTK_BUTTONS_OK, + GTK_BUTTONS_CLOSE, + GTK_BUTTONS_CANCEL, + GTK_BUTTONS_YES_NO, + GTK_BUTTONS_OK_CANCEL + } GtkButtonsType; - typedef enum - { - GTK_RESPONSE_NONE = -1, - GTK_RESPONSE_REJECT = -2, - GTK_RESPONSE_ACCEPT = -3, - GTK_RESPONSE_DELETE_EVENT = -4, - GTK_RESPONSE_OK = -5, - GTK_RESPONSE_CANCEL = -6, - GTK_RESPONSE_CLOSE = -7, - GTK_RESPONSE_YES = -8, - GTK_RESPONSE_NO = -9, - GTK_RESPONSE_APPLY = -10, - GTK_RESPONSE_HELP = -11 - } GtkResponseType; + typedef enum + { + GTK_RESPONSE_NONE = -1, + GTK_RESPONSE_REJECT = -2, + GTK_RESPONSE_ACCEPT = -3, + GTK_RESPONSE_DELETE_EVENT = -4, + GTK_RESPONSE_OK = -5, + GTK_RESPONSE_CANCEL = -6, + GTK_RESPONSE_CLOSE = -7, + GTK_RESPONSE_YES = -8, + GTK_RESPONSE_NO = -9, + GTK_RESPONSE_APPLY = -10, + GTK_RESPONSE_HELP = -11 + } GtkResponseType; + #endif /** * xdg_user_dir_lookup_with_fallback: @@ -422,28 +426,46 @@ Oneshot::Oneshot(RGSSThreadData &threadData) : else p->lang = "en"; - //Get user's name - struct passwd *pwd = getpwuid(getuid()); - if (pwd) - { - if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',') - { - //Get the user's full name - int comma = 0; - for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {} - p->userName = std::string(pwd->pw_gecos, comma); - } - else - p->userName = pwd->pw_name; - } + #ifdef OS_OSX + + //Get user's name + struct passwd *pwd = getpwuid(geteuid()); + if (pwd) + { + if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',') + { + //Get the user's full name + int comma = 0; + for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {} + p->userName = std::string(pwd->pw_gecos, comma); + } + else + p->userName = pwd->pw_name; + } + + #elif defined OS_LINUX + + //Get user's name + struct passwd *pwd = getpwuid(getuid()); + if (pwd) + { + if (pwd->pw_gecos && pwd->pw_gecos[0] && pwd->pw_gecos[0] != ',') + { + //Get the user's full name + int comma = 0; + for (; pwd->pw_gecos[comma] && pwd->pw_gecos[comma] != ','; ++comma) {} + p->userName = std::string(pwd->pw_gecos, comma); + } + else + p->userName = pwd->pw_name; + } + + #endif -#ifdef OS_LINUX //Get documents path char *path = xdg_user_dir_lookup_with_fallback("DOCUMENTS", getenv("HOME")); p->docsPath = path; free(path); -#elif OS_OSX -#endif #endif /**********