From 0efd583006a2e9b3967cae067ec67526a4284443 Mon Sep 17 00:00:00 2001 From: Jason Reed Date: Sun, 10 Dec 2023 18:08:36 -0500 Subject: [PATCH] Zoom with +/- keys (fix #117) --- src/core/action.ts | 1 + src/core/reduce.ts | 37 +++++++++++++++++++++---------------- src/core/reduceKey.ts | 19 ++++++++++++++++++- src/ui/key.ts | 2 ++ 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/core/action.ts b/src/core/action.ts index aae21ff..51b268b 100644 --- a/src/core/action.ts +++ b/src/core/action.ts @@ -2,6 +2,7 @@ import { ViewData } from '../ui/ui-helpers'; import { Point } from '../util/types'; import { SceneState } from './state'; +// All of these p are p_in_canvas export type GameAction = | { t: 'none' } | { t: 'key', code: string } diff --git a/src/core/reduce.ts b/src/core/reduce.ts index 54b94ba..30d07a6 100644 --- a/src/core/reduce.ts +++ b/src/core/reduce.ts @@ -261,6 +261,26 @@ export function keyCaptured(keyCode: string): boolean { } } +export function reduceZoom(state: GameState, p_in_canvas: Point, delta: number): GameState { + const sf = delta < 0 ? 1.1 : 1 / 1.1; + const zoomed_canvas_of_unzoomed_canvas = composen( + translate(p_in_canvas), + scale({ x: sf, y: sf }), + translate(vscale(p_in_canvas, -1)), + ); + const canvas_from_world = compose(zoomed_canvas_of_unzoomed_canvas, state.coreState.canvas_from_world); + const MAX_ZOOM_OUT = 7.5; + const MAX_ZOOM_IN = 150; + if (canvas_from_world.scale.x < MAX_ZOOM_OUT || canvas_from_world.scale.y < MAX_ZOOM_OUT + || canvas_from_world.scale.x > MAX_ZOOM_IN || canvas_from_world.scale.y > MAX_ZOOM_IN) { + return state; + } + return produce(state, s => { + s.coreState.canvas_from_world = canvas_from_world; + }); + +} + function reduceGameAction(state: GameState, action: GameAction): effectful.Result { function gs(state: GameState): effectful.Result { return { state: { t: 'game', gameState: state, revision: 0 }, effects: [] }; @@ -271,22 +291,7 @@ function reduceGameAction(state: GameState, action: GameAction): effectful.Resul } case 'none': return gs(state); case 'wheel': { - const sf = action.delta < 0 ? 1.1 : 1 / 1.1; - const zoomed_canvas_of_unzoomed_canvas = composen( - translate(action.p), - scale({ x: sf, y: sf }), - translate(vscale(action.p, -1)), - ); - const canvas_from_world = compose(zoomed_canvas_of_unzoomed_canvas, state.coreState.canvas_from_world); - const MAX_ZOOM_OUT = 7.5; - const MAX_ZOOM_IN = 150; - if (canvas_from_world.scale.x < MAX_ZOOM_OUT || canvas_from_world.scale.y < MAX_ZOOM_OUT - || canvas_from_world.scale.x > MAX_ZOOM_IN || canvas_from_world.scale.y > MAX_ZOOM_IN) { - return gs(state); - } - return gs(produce(state, s => { - s.coreState.canvas_from_world = canvas_from_world; - })); + return gs(reduceZoom(state, action.p, action.delta)); } case 'mouseDown': { const wp = getWidgetPoint(state.coreState, action.p); diff --git a/src/core/reduceKey.ts b/src/core/reduceKey.ts index 152bc61..bb8fcab 100644 --- a/src/core/reduceKey.ts +++ b/src/core/reduceKey.ts @@ -1,7 +1,9 @@ -import { getWidgetPoint } from "../ui/widget-helpers"; +import { canvas_bds_in_canvas, getWidgetPoint } from "../ui/widget-helpers"; import { debugTiles } from "../util/debug"; import { produce } from "../util/produce"; +import { midpointOfRect } from "../util/util"; import { tryKillTileOfState } from "./kill-helpers"; +import { reduceZoom } from "./reduce"; import { getScore, incrementScore, setScore } from "./scoring"; import { GameState } from "./state"; import { addWorldTiles, checkValid, drawOfState, dropTopHandTile, withCoreState } from "./state-helpers"; @@ -10,6 +12,21 @@ import { dynamiteIntent, reduceToolSelect } from "./tools"; export function reduceKey(state: GameState, code: string): GameState { switch (code) { + case '=': // fallthrough intentional + case '+': + if (state.mouseState.t == 'up') { + return reduceZoom(state, state.mouseState.p_in_canvas, -1); + } + else + return reduceZoom(state, midpointOfRect(canvas_bds_in_canvas), -1); + break; + case '-': + if (state.mouseState.t == 'up') { + return reduceZoom(state, state.mouseState.p_in_canvas, 1); + } + else + return reduceZoom(state, midpointOfRect(canvas_bds_in_canvas), 1); + break; case '': { return withCoreState(state, cs => drawOfState(cs)); } diff --git a/src/ui/key.ts b/src/ui/key.ts index 8b2ca9c..b93ccd0 100644 --- a/src/ui/key.ts +++ b/src/ui/key.ts @@ -7,6 +7,8 @@ const table: { [k: number]: string } = { 219: '[', 220: '\\', 221: ']', + 173: '-', + 61: '=', 8: '', 9: '', 32: '',