diff --git a/geo2d.nim b/geo2d.nim index 43c8a46..0771bbf 100644 --- a/geo2d.nim +++ b/geo2d.nim @@ -43,6 +43,11 @@ proc xlate*(x, y: float32) : X2d = result[2,0] = x result[2,1] = y +proc xlate*(p: P2d) : X2d = + result = identity[3,float32]() + result[2,0] = p.x + result[2,1] = p.y + proc scale*(center : P2d, x, y : float32) : X2d = xlate(-center.x, -center.y) * scale(x,y) * xlate(center.x, center.y) proc rot*(center : P2d, angle : float32) : X2d = xlate(-center.x, -center.y) * rot(angle) * xlate(center.x, center.y) diff --git a/grid.nim b/grid.nim index 038beb7..7b39804 100644 --- a/grid.nim +++ b/grid.nim @@ -1,57 +1,58 @@ import random from times import epochTime +from nwo/utils import nmod type Grid* = object - rows*, columns* : uint32 + rows*, columns* : int data : seq[uint32] -proc newGrid*(rows, columns : uint32) : Grid = +proc newGrid*(rows, columns : int) : Grid = Grid( rows: rows, columns: columns, data: newSeq[uint32]((rows * columns + 8 - 1) div 8) ) -proc get(grid : Grid, x, y : uint32) : bool = +proc get(grid : Grid, x, y : int) : bool = assert x < grid.columns assert y < grid.rows let index = y * grid.columns + x (grid.data[index div 8] and (1u32 shl (index mod 8))) != 0 -proc set(grid : var Grid, x, y : uint32, value : bool) : void = +proc set(grid : var Grid, x, y : int, value : bool) : void = assert x < grid.columns assert y < grid.rows let index = y * grid.columns + x - grid.data[(index div 8)] = + grid.data[index div 8] = if value: - grid.data[(index div 8)] or (1u32 shl (index mod 8)) + grid.data[index div 8] or (1u32 shl (index mod 8)) else: - grid.data[(index div 8)] and (not (1u32 shl (index mod 8))) + grid.data[index div 8] and (not (1u32 shl (index mod 8))) -template `[]`*(grid : Grid, x,y : uint32) : bool = +template `[]`*(grid : Grid, x,y : int) : bool = get(grid, x, y) -template `[]=`*(grid : Grid, x,y : uint32, value : bool) = +template `[]=`*(grid : Grid, x,y : int, value : bool) = set(grid, x, y, value) proc next_step*(old_grid, new_grid : var Grid) = for x in 0.. 1: + step -= 1 + of ']'.int: + if step < 10: + step += 1 else: discard of MouseButtonDown: let mouseButtonDownEvent = cast[MouseButtonEventPtr](addr(evt)) - if mouseButtonDownEvent.which == BUTTON_RIGHT: - pan_start = some(newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32)) + case mouseButtonDownEvent.button: + of BUTTON_RIGHT: + pan_start = some(newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32)) + of BUTTON_LEFT: + let inv = xform.invert() + let position = newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32) * inv / side.float32 + let row = position.x.int + let column = position.y.int + current_grid[][row, column] = not current_grid[][row, column] + else: + discard of MouseButtonUp: - let mouseButtonDownEvent = cast[MouseButtonEventPtr](addr(evt)) - if mouseButtonDownEvent.which == BUTTON_RIGHT and pan_start.isSome(): - let xlation = newP2d(mouseButtonDownEvent.x.float32, mouseButtonDownEvent.y.float32) - pan_start.get() - pan_start = none[P2d]() - uxform = uxform * xlate(xlation.x, xlation.y) + let mouseButtonUpEvent = cast[MouseButtonEventPtr](addr(evt)) + case mouseButtonUpEvent.button: + of BUTTON_RIGHT: + let xlation = newP2d(mouseButtonUpEvent.x.float32, mouseButtonUpEvent.y.float32) - pan_start.get() + pan_start = none[P2d]() + uxform = uxform * xlate(xlation.x, xlation.y) + else: + discard of MouseWheel: let mouseWheelEvent = cast[MouseWheelEventPtr](addr(evt)) + let zoomCenter = (block: + var x,y : cint + getMouseState(x,y) + newP2d(x.float32, y.float32) + ) if mouseWheelEvent.y > 0: - uxform = uxform * scale(newP2d(windowSize.width.float32 / 2f32, windowSize.height.float32 / 2f32), 1.1f32, 1.1f32) + uxform = uxform * scale(zoomCenter, 1.1f32, 1.1f32) else: - uxform = uxform * scale(newP2d(windowSize.width.float32 / 2f32, windowSize.height.float32 / 2f32), 0.9f32, 0.9f32) - of MouseMotion: - let mouseMotionEvent = cast[MouseMotionEventPtr](addr(evt)) - let position = newP2d(mouseMotionEvent.x.float32, mouseMotionEvent.y.float32) - + uxform = uxform * scale(zoomCenter, 0.9f32, 0.9f32) + # of MouseMotion: + # let mouseMotionEvent = cast[MouseMotionEventPtr](addr(evt)) + # if pan_start.isSome: + # pan = pan * xlate(newP2d(mouseMotionEvent.x.float32, mouseMotionEvent.y.float32) - pan_start.get()) + else: discard @@ -102,8 +131,20 @@ while not quit: render.setDrawColor 127,127,127,255 let f = min(windowSize.width / bb.width, windowSize.height / bb.height) - let xform = xlate(-bb.width / 2.0f32, -bb.height / 2.0f32) * scale(f, f) * - xlate(windowSize.width / 2.0f32, windowSize.height / 2.0f32) * uxform + # let pan_xform = block: + # if pan_start.isSome(): + # x + + let pan = block: + if pan_start.isSome: + var x, y : cint + getMouseState(x, y) + xlate(newP2d(x.float32, y.float32) - pan_start.get()) + else: + identity[3, float32]() + + xform = xlate(-bb.width / 2.0f32, -bb.height / 2.0f32) * scale(f, f) * + xlate(windowSize.width / 2.0f32, windowSize.height / 2.0f32) * uxform * pan while x <= bb.width: render.drawLine(newP2d(x, bb.top) * xform, newP2d(x, bb.height) * xform) @@ -124,9 +165,6 @@ while not quit: if not freeze and current_time_sec > elapsed_time_sec: elapsed_time_sec = current_time_sec next_step(current_grid[], next_grid[]) - let tmp = current_grid - current_grid = next_grid - next_grid = tmp destroy render destroy window \ No newline at end of file