From 051eb3ea3155d70ba421ed8493ee58c9ff7e1ede Mon Sep 17 00:00:00 2001 From: Franklin Wei Date: Thu, 2 Jul 2020 01:03:20 -0400 Subject: puzzles: enhancements to mouse mode, zoom feature - zoom now remembers position between activations (but not when exiting the plugin) - key repeat enabled when panning - moving mouse out of frame while zoomed will pan - mouse can be moved diagonally Change-Id: I39380ef7f36238700b6baa54cac036832933df67 --- apps/plugins/puzzles/rockbox.c | 159 ++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 65 deletions(-) (limited to 'apps/plugins/puzzles') diff --git a/apps/plugins/puzzles/rockbox.c b/apps/plugins/puzzles/rockbox.c index 7fe7998c39..04d7e6d6e4 100644 --- a/apps/plugins/puzzles/rockbox.c +++ b/apps/plugins/puzzles/rockbox.c @@ -115,6 +115,7 @@ static inline void plot(fb_data *fb, int w, int h, unsigned x, unsigned y, unsigned long a, unsigned long r1, unsigned long g1, unsigned long b1, unsigned cl, unsigned cr, unsigned cu, unsigned cd); +static void zoom_clamp_panning(void); static midend *me = NULL; static unsigned *colors = NULL; @@ -137,7 +138,7 @@ static int mouse_x, mouse_y; extern bool audiobuf_available; /* defined in rbmalloc.c */ static fb_data *zoom_fb; /* dynamically allocated */ -static int zoom_x, zoom_y, zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; +static int zoom_x = -1, zoom_y = -1, zoom_w, zoom_h, zoom_clipu, zoom_clipd, zoom_clipl, zoom_clipr; static int cur_font = FONT_UI; static bool need_draw_update = false; @@ -1722,30 +1723,34 @@ static int process_input(int tmo, bool do_pausemenu) * following code is needed for mouse mode. */ if(mouse_mode) { - static int last_mousedir = 0, held_count = 0, v = 1; + static int held_count = 0, v = 2; + + int dx = 0, dy = 0; if(button & BTN_UP) - state = CURSOR_UP; - else if(button & BTN_DOWN) - state = CURSOR_DOWN; - else if(button & BTN_LEFT) - state = CURSOR_LEFT; - else if(button & BTN_RIGHT) - state = CURSOR_RIGHT; + dy -= 1; + if(button & BTN_DOWN) + dy += 1; + if(button & BTN_LEFT) + dx -= 1; + if(button & BTN_RIGHT) + dx += 1; unsigned released = ~button & last_keystate, - pressed = button & ~last_keystate; - - last_keystate = button; - - /* move */ - /* get the direction vector the cursor is moving in. */ - int new_x = mouse_x, new_y = mouse_y; - - /* in src/misc.c */ - move_cursor(state, &new_x, &new_y, LCD_WIDTH, LCD_HEIGHT, false); + pressed = button & ~last_keystate; - int dx = new_x - mouse_x, dy = new_y - mouse_y; + /* acceleration */ + if(button && button == last_keystate) + { + if(++held_count % 4 == 0 && v < 15) + v++; + } + else + { + LOGF("no buttons pressed, or state changed"); + v = 1; + held_count = 0; + } mouse_x += dx * v; mouse_y += dy * v; @@ -1753,15 +1758,25 @@ static int process_input(int tmo, bool do_pausemenu) /* clamp */ /* The % operator with negative operands is messy; this is much * simpler. */ + bool clamped_x = false, clamped_y = false; + if(mouse_x < 0) - mouse_x = 0; + mouse_x = 0, clamped_x = true; if(mouse_y < 0) - mouse_y = 0; + mouse_y = 0, clamped_y = true; if(mouse_x >= LCD_WIDTH) - mouse_x = LCD_WIDTH - 1; + mouse_x = LCD_WIDTH - 1, clamped_x = true; if(mouse_y >= LCD_HEIGHT) - mouse_y = LCD_HEIGHT - 1; + mouse_y = LCD_HEIGHT - 1, clamped_y = true; + + if((clamped_x || clamped_y) && zoom_enabled) { + if(clamped_x) + zoom_x += dx * v; + if(clamped_y) + zoom_y += dy * v; + zoom_clamp_panning(); + } /* clicking/dragging */ /* rclick on hold requires that we fire left-click on a @@ -1777,32 +1792,24 @@ static int process_input(int tmo, bool do_pausemenu) } else { - if(pressed & BTN_FIRE) + if(pressed & BTN_FIRE) { send_click(LEFT_BUTTON, false); + accept_input = false; + } else if(released & BTN_FIRE) send_click(LEFT_RELEASE, false); else if(button & BTN_FIRE) send_click(LEFT_DRAG, false); } - /* acceleration */ - if(state && state == last_mousedir) - { - if(++held_count % 5 == 0 && v < 15) - v++; - } - else + if(!button) { - if(!button) - { - LOGF("all keys released, accepting further input"); - accept_input = true; - } - last_mousedir = state; - v = 1; - held_count = 0; + LOGF("all keys released, accepting further input"); + accept_input = true; } + last_keystate = button; + /* no buttons are sent to the midend in mouse mode */ return 0; } @@ -1972,6 +1979,18 @@ static int process_input(int tmo, bool do_pausemenu) return state; } +static void zoom_clamp_panning(void) { + if(zoom_y < 0) + zoom_y = 0; + if(zoom_x < 0) + zoom_x = 0; + + if(zoom_y + LCD_HEIGHT >= zoom_h) + zoom_y = zoom_h - LCD_HEIGHT; + if(zoom_x + LCD_WIDTH >= zoom_w) + zoom_x = zoom_w - LCD_WIDTH; +} + /* This function handles zoom mode, where the user can either pan * around a zoomed-in image or play a zoomed-in version of the game. */ static void zoom(void) @@ -2001,13 +2020,21 @@ static void zoom(void) return; } + /* set position */ + + if(zoom_x < 0) { + /* first run */ + zoom_x = zoom_w / 2 - LCD_WIDTH / 2; + zoom_y = zoom_h / 2 - LCD_HEIGHT / 2; + } + + zoom_clamp_panning(); + zoom_enabled = true; /* draws go to the zoom framebuffer */ midend_force_redraw(me); - zoom_x = zoom_y = 0; - rb->lcd_bitmap_part(zoom_fb, zoom_x, zoom_y, STRIDE(SCREEN_MAIN, zoom_w, zoom_h), 0, 0, LCD_WIDTH, LCD_HEIGHT); @@ -2031,18 +2058,25 @@ static void zoom(void) if(view_mode) { int button = rb->button_get_w_tmo(timer_on ? TIMER_INTERVAL : -1); + + exit_on_usb(button); + switch(button) { case BTN_UP: + case BTN_UP | BUTTON_REPEAT: zoom_y -= PAN_Y; /* clamped later */ break; case BTN_DOWN: + case BTN_DOWN | BUTTON_REPEAT: zoom_y += PAN_Y; /* clamped later */ break; case BTN_LEFT: + case BTN_LEFT | BUTTON_REPEAT: zoom_x -= PAN_X; /* clamped later */ break; case BTN_RIGHT: + case BTN_RIGHT | BUTTON_REPEAT: zoom_x += PAN_X; /* clamped later */ break; case BTN_PAUSE: @@ -2050,22 +2084,15 @@ static void zoom(void) sfree(zoom_fb); fix_size(); return; - case BTN_FIRE: + case BTN_FIRE | BUTTON_REL: + /* state change to interaction mode */ view_mode = false; - continue; + break; default: break; } - if(zoom_y < 0) - zoom_y = 0; - if(zoom_x < 0) - zoom_x = 0; - - if(zoom_y + LCD_HEIGHT >= zoom_h) - zoom_y = zoom_h - LCD_HEIGHT; - if(zoom_x + LCD_WIDTH >= zoom_w) - zoom_x = zoom_w - LCD_WIDTH; + zoom_clamp_panning(); if(timer_on) timer_cb(); @@ -2081,9 +2108,23 @@ static void zoom(void) } else { + /* The cursor is always in screenspace coordinates; when + * zoomed, this means the mouse is always restricted to + * the bounds of the physical display, not the virtual + * zoom framebuffer. */ + if(mouse_mode) + draw_mouse(); + + rb->lcd_update(); + + if(mouse_mode) + clear_mouse(); + /* basically a copy-pasta'd main loop */ int button = process_input(timer_on ? TIMER_INTERVAL : -1, false); + exit_on_usb(button); + if(button < 0) { view_mode = true; @@ -2104,18 +2145,6 @@ static void zoom(void) draw_title(false); - /* The cursor is always in screenspace coordinates; when - * zoomed, this means the mouse is always restricted to - * the bounds of the physical display, not the virtual - * zoom framebuffer. */ - if(mouse_mode) - draw_mouse(); - - rb->lcd_update(); - - if(mouse_mode) - clear_mouse(); - rb->yield(); } } -- cgit v1.2.3