diff --git a/packages/ludic.minimap/README.md b/packages/ludic.minimap/README.md index 5439cf5a..2dae73b3 100644 --- a/packages/ludic.minimap/README.md +++ b/packages/ludic.minimap/README.md @@ -60,7 +60,7 @@ export port MinimapWorld { # every member has a default | `minimap_pin_count()`, `minimap_pin_max()`, `minimap_pin_full()`, `minimap_pin(i) -> MinimapPin` | the marks | | `minimap_pin_set_label/icon/colour(i, v)`, `minimap_pin_last_icon()` | editing one | | `minimap_pin_open()`, `minimap_pin_select(i)`, `minimap_pin_followed()`, `minimap_pin_follow(i)`, `minimap_pin_follow_toggle()` | the open one and the followed one | -| `minimap_pins_near(x, z, n, within) -> []int` | the nearest marks, not the followed one (for a compass) | +| `minimap_pins_near(x, z, n, within) -> []int` | the nearest marks, not the followed one (for a compass), in a list the state keeps and refills: read it, do not keep it | | `minimap_config_view(span, zoom_min, zoom_max, focus)`, `minimap_window(x0, y0, size)` | the view's range, and where the window is this frame | | `minimap_px(x)`, `minimap_py(z)`, `minimap_wx(rx)`, `minimap_wz(ry)`, `minimap_span()`, `minimap_scale()`, `minimap_scale_metres()` | projection, and a scale bar's round distance | | `minimap_zoom()`, `minimap_zoom_set(z)`, `minimap_zoom_step(dir)`, `minimap_zoom_about(rx, ry, factor)` | zoom | diff --git a/packages/ludic.minimap/grid.ludic b/packages/ludic.minimap/grid.ludic index fb0689a0..0299249b 100644 --- a/packages/ludic.minimap/grid.ludic +++ b/packages/ludic.minimap/grid.ludic @@ -1,6 +1,7 @@ # grid.ludic - the explored grid: square cells round the origin, and the part of it "explored" is # measured over (a core, so a bigger grid does not change what a share of it means) export state MinimapState { + mm_near: []int = new []int # minimap_pins_near's answer, cleared and refilled: a compass asks every frame mm_land_n: int = 0 # land cells in the core, counted once per origin mm_land_ox: float = 0.0 mm_land_oz: float = 0.0 diff --git a/packages/ludic.minimap/pins.ludic b/packages/ludic.minimap/pins.ludic index c6994dea..7df34b15 100644 --- a/packages/ludic.minimap/pins.ludic +++ b/packages/ludic.minimap/pins.ludic @@ -71,8 +71,9 @@ export function minimap_pin(minimap_st: MinimapState, i: int) -> MinimapPin { } # the nearest n marks within `within` of (x, z), nearest first, leaving out the followed one -export function minimap_pins_near(minimap_st: MinimapState, x: float, z: float, n: int, within: float) -> []int { - let out = new []int +export function minimap_pins_near(minimap_st: mut MinimapState, x: float, z: float, n: int, within: float) -> []int { + let out = minimap_st.mm_near + List.clear(out) for k in 0 .. n { var best = -1 var bd = within * within diff --git a/packages/ludic.minimap/tests/minimap_test.ludic b/packages/ludic.minimap/tests/minimap_test.ludic index f270b55a..645b1f77 100644 --- a/packages/ludic.minimap/tests/minimap_test.ludic +++ b/packages/ludic.minimap/tests/minimap_test.ludic @@ -111,6 +111,20 @@ program MinimapTest { expect_eq(near[1], 1) } + test "asking for the nearest marks every frame allocates nothing" (minimap_st: mut MinimapState, minimap_test_st: mut MinimapTestState) { + fresh(minimap_st, minimap_test_st) + minimap_config_pins(minimap_st, 8, 8, 5) + minimap_pin_add(minimap_st, 110.0, 100.0, 0, "near") + minimap_pin_add(minimap_st, 130.0, 100.0, 0, "next") + minimap_pins_near(minimap_st, 100.0, 100.0, 2, 400.0) + let before = Os.heap_bytes() + for k in 0 .. 1000 { minimap_pins_near(minimap_st, 100.0 + float(k % 7), 100.0, 2, 400.0) } + let grew = Os.heap_bytes() - before + print(`minimap: 1000 asks, heap {grew} bytes`) + expect(grew == long(0)) + expect_eq(len(minimap_pins_near(minimap_st, 100.0, 100.0, 2, 400.0)), 2) + } + test "the view: the world on the window and back, zoom about a point, a pan, focus and the clamp" (minimap_st: mut MinimapState, minimap_test_st: mut MinimapTestState) { fresh(minimap_st, minimap_test_st) minimap_centre(minimap_st, 100.0, 100.0)