diff options
-rw-r--r-- | engines/sci/engine/kgraphics.cpp | 18 | ||||
-rw-r--r-- | engines/sci/gfx/operations.cpp | 34 | ||||
-rw-r--r-- | engines/sci/gfx/operations.h | 10 |
3 files changed, 59 insertions, 3 deletions
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 89fed9d2d8..16818a9f4d 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -326,9 +326,23 @@ static reg_t kSetCursorSci11(EngineState *s, int funct_nr, int argc, reg_t *argv CursorMan.showMouse(argv[0].toSint16() != 0); break; case 2: - GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, - Common::Point(argv[0].toUint16(), argv[1].toUint16()))); + GFX_ASSERT(gfxop_set_pointer_position(s->gfx_state, + Common::Point(argv[0].toUint16() + s->port->_bounds.x, argv[1].toUint16() + s->port->_bounds.y))); break; + case 4: { + int16 top = argv[0].toSint16(); + int16 left = argv[1].toSint16(); + int16 bottom = argv[2].toSint16(); + int16 right = argv[3].toSint16(); + + if ((right >= left) && (bottom >= top)) { + Common::Rect rect = Common::Rect(left, top, right + 1, bottom + 1); + GFX_ASSERT(gfxop_set_pointer_zone(s->gfx_state, rect)); + } else { + warning("kSetCursor: Ignoring invalid mouse zone (%i, %i)-(%i, %i)", left, top, right, bottom); + } + break; + } case 5: case 9: hotspot = new Common::Point(argv[3].toSint16(), argv[4].toSint16()); diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp index b3a1be68d1..a23bae5350 100644 --- a/engines/sci/gfx/operations.cpp +++ b/engines/sci/gfx/operations.cpp @@ -258,9 +258,32 @@ static int _gfxop_draw_pixmap(GfxDriver *driver, gfx_pixmap_t *pxm, int priority } static void _gfxop_full_pointer_refresh(GfxState *state) { + bool clipped = false; Common::Point mousePoint = g_system->getEventManager()->getMousePos(); + state->pointer_pos.x = mousePoint.x / state->driver->getMode()->xfact; state->pointer_pos.y = mousePoint.y / state->driver->getMode()->yfact; + + if (state->pointer_pos.x < state->pointerZone.left) { + state->pointer_pos.x = state->pointerZone.left; + clipped = true; + } else if (state->pointer_pos.x >= state->pointerZone.right) { + state->pointer_pos.x = state->pointerZone.right - 1; + clipped = true; + } + + if (state->pointer_pos.y < state->pointerZone.top) { + state->pointer_pos.y = state->pointerZone.top; + clipped = true; + } else if (state->pointer_pos.y >= state->pointerZone.bottom) { + state->pointer_pos.y = state->pointerZone.bottom - 1; + clipped = true; + } + + // FIXME: Do this only when mouse is grabbed? + if (clipped) + g_system->warpMouse(state->pointer_pos.x * state->driver->getMode()->xfact, + state->pointer_pos.y * state->driver->getMode()->yfact); } static int _gfxop_buffer_propagate_box(GfxState *state, rect_t box, gfx_buffer_t buffer); @@ -427,6 +450,7 @@ int gfxop_init(int version, GfxState *state, state->gfxResMan = new GfxResManager(state->options, state->driver, resManager); gfxop_set_clip_zone(state, gfx_rect(0, 0, 320, 200)); + state->pointerZone = Common::Rect(0, 0, 320, 200); init_aux_pixmap(&(state->control_map)); init_aux_pixmap(&(state->priority_map)); @@ -1194,10 +1218,18 @@ int gfxop_set_pointer_position(GfxState *state, Common::Point pos) { g_system->warpMouse(pos.x * state->driver->getMode()->xfact, pos.y * state->driver->getMode()->yfact); - _gfxop_full_pointer_refresh(state); + // Trigger event reading to make sure the mouse coordinates will + // actually have changed the next time we read them. + gfxop_get_event(state, SCI_EVT_PEEK); + return 0; } +int gfxop_set_pointer_zone(GfxState *state, Common::Rect rect) { + state->pointerZone = rect; + return GFX_OK; +} + #define SCANCODE_ROWS_NR 3 struct scancode_row { diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h index ec0a810224..865b420681 100644 --- a/engines/sci/gfx/operations.h +++ b/engines/sci/gfx/operations.h @@ -94,6 +94,7 @@ struct GfxState { gfx_options_t *options; Common::Point pointer_pos; /**< Mouse pointer coordinates */ + Common::Rect pointerZone; /**< Rectangle in which the pointer can move */ rect_t clip_zone_unscaled; /**< The current UNSCALED clipping zone */ rect_t clip_zone; /**< The current SCALED clipping zone; a cached scaled version of clip_zone_unscaled */ @@ -424,6 +425,15 @@ int gfxop_set_pointer_view(GfxState *state, int nr, int loop, int cel, Common::P int gfxop_set_pointer_position(GfxState *state, Common::Point pos); /** + * Limits the mouse movement to a given rectangle. + * + * @param[in] state The affected state + * @param[in] rect The rectangle + * @return Any error code or GFX_OK + */ +int gfxop_set_pointer_zone(GfxState *state, Common::Rect rect); + +/** * Retrieves the next input event from the driver. * * @param[in] state The affected state |