diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 81bc0d2..81de289 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,5 +21,8 @@ "ols.server.path": "ols" } } - } + }, + "securityOpt": [ + "seccomp=unconfined" + ] } diff --git a/.gitignore b/.gitignore index 19066f6..6e00695 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. .env +.kcov/ spinward diff --git a/Makefile b/Makefile index 7e55692..5fb527e 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ ifneq (,$(wildcard ./.env)) export endif -.PHONY: all build clean format lint run test +.PHONY: all build clean coverage format lint run test all: lint test build @@ -17,12 +17,16 @@ build: clean: git clean -fdxe ".env" +coverage: + odin build . -build-mode:test -debug + kcov --dump-summary --exclude-pattern=_test.odin --include-path=. .kcov spinward + format: odinfmt . -w lint: hadolint .devcontainer/Dockerfile - odin check . -vet + odin check . -strict-style -vet yamllint .github/workflows/linux.yml run: diff --git a/viewer/renderer.odin b/app.odin similarity index 72% rename from viewer/renderer.odin rename to app.odin index 93b0b5a..c5e1771 100644 --- a/viewer/renderer.odin +++ b/app.odin @@ -4,16 +4,20 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package viewer +package main import rl "vendor:raylib" -run :: proc() { +run :: proc() -> Error { rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE) defer rl.CloseWindow() + if !rl.IsWindowReady() { + return .Initialization_Failed + } + camera := new_camera() - sector := new_sector("Spinward Marches", {38, 6}) + sector := new_sector("Spinward Marches") for !rl.WindowShouldClose() { rl.BeginDrawing() @@ -21,13 +25,14 @@ run :: proc() { rl.ClearBackground(rl.BLACK) rl.DrawFPS(16, WINDOW_HEIGHT - 32) - pan_camera(&camera) - zoom_camera(&camera) + poll_camera(&camera) rl.BeginMode2D(camera) - draw_sector(sector) + draw_sector(sector, camera) rl.EndMode2D() rl.EndDrawing() } + + return nil } diff --git a/camera.odin b/camera.odin new file mode 100644 index 0000000..7ebf1a2 --- /dev/null +++ b/camera.odin @@ -0,0 +1,36 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:math" +import rl "vendor:raylib" + +new_camera :: proc() -> rl.Camera2D { + return {zoom = 1.0} +} + +poll_camera :: proc(camera: ^rl.Camera2D) { + if rl.IsMouseButtonDown(.RIGHT) { + pan_camera(camera, rl.GetMouseDelta()) + } + + if wheel := rl.GetMouseWheelMove(); wheel != 0.0 { + zoom_camera(camera, wheel, rl.GetMousePosition()) + } +} + +pan_camera :: proc(camera: ^rl.Camera2D, delta: rl.Vector2) { + camera.target += delta * -1.0 / camera.zoom +} + +zoom_camera :: proc(camera: ^rl.Camera2D, wheel: f32, position: rl.Vector2) { + camera^ = { + offset = position, + target = rl.GetScreenToWorld2D(position, camera^), + zoom = clamp(math.exp(math.log(camera.zoom, math.E) + 0.2 * wheel), 0.125, 64.0), + } +} diff --git a/camera_test.odin b/camera_test.odin new file mode 100644 index 0000000..6d25c69 --- /dev/null +++ b/camera_test.odin @@ -0,0 +1,35 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" +import rl "vendor:raylib" + +@(test) +test_new_camera :: proc(t: ^testing.T) { + testing.expect_value(t, new_camera(), rl.Camera2D{zoom = 1.0}) +} + +@(test) +test_pan_camera :: proc(t: ^testing.T) { + camera := new_camera() + + pan_camera(&camera, {1.0, 2.0}) + + testing.expect_value(t, camera.target, rl.Vector2{-1.0, -2.0}) +} + +@(test) +test_zoom_camera :: proc(t: ^testing.T) { + camera := new_camera() + + zoom_camera(&camera, 1.0, {1.0, 2.0}) + + testing.expect_value(t, camera.offset, rl.Vector2{1, 2}) + testing.expect_value(t, camera.target, rl.Vector2{1, 2}) + testing.expect_value(t, camera.zoom, 1.2214028) +} diff --git a/viewer/config.odin b/constants.odin similarity index 87% rename from viewer/config.odin rename to constants.odin index 180b351..4a4ff4b 100644 --- a/viewer/config.odin +++ b/constants.odin @@ -4,9 +4,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -package viewer +package main -HEX_SIZE :: 12 +HEX_SIZE :: 24 + +ODD_OFFSET :: -1 WINDOW_WIDTH :: 1920 WINDOW_HEIGHT :: 1080 diff --git a/hex.odin b/hex.odin new file mode 100644 index 0000000..394c1be --- /dev/null +++ b/hex.odin @@ -0,0 +1,57 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:fmt" +import "core:math" + +new_hex :: proc(q, r, s: f32) -> Hex { + assert(math.round(q + r + s) == 0) + + return {q, r, s} +} + +hex_index :: proc(hex: Hex) -> string { + offset := qoffset_from_cube(hex) + + return fmt.tprintf("%02d%02d", i32(offset.x + 1), i32(offset.y + 1)) +} + +hex_lerp :: proc(a, b: Hex, t: f32) -> Hex { + return math.lerp(a, b, t) +} + +hex_to_pixel :: proc(layout: Layout, hex: Hex) -> Point { + M := layout.orientation + size := layout.size + origin := layout.origin + + x := (M.f[0, 0] * hex.x + M.f[0, 1] * hex.y) * size.x + y := (M.f[1, 0] * hex.x + M.f[1, 1] * hex.y) * size.y + + return new_point(x + origin.x, y + origin.y) +} + +hex_round :: proc(hex: Hex) -> Hex { + q := math.round(hex.x) + r := math.round(hex.y) + s := math.round(hex.z) + + q_diff := math.abs(q - hex.x) + r_diff := math.abs(r - hex.y) + s_diff := math.abs(s - hex.z) + + if q_diff > r_diff && q_diff > s_diff { + q = -r - s + } else if r_diff > s_diff { + r = -q - s + } else { + s = -q - r + } + + return new_hex(q, r, s) +} diff --git a/hex_test.odin b/hex_test.odin new file mode 100644 index 0000000..273b9e4 --- /dev/null +++ b/hex_test.odin @@ -0,0 +1,48 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" + +@(test) +test_new_hex :: proc(t: ^testing.T) { + testing.expect_value(t, new_hex(1, 1, -2), Hex{1, 1, -2}) + testing.expect_value(t, new_hex(1.0, 1.0, -2.0), Hex{1.0, 1.0, -2.0}) +} + +@(test) +test_hex_index :: proc(t: ^testing.T) { + testing.expect_value(t, hex_index(new_hex(0, 0, 0)), "0101") + testing.expect_value(t, hex_index(new_hex(1, 0, -1)), "0201") + testing.expect_value(t, hex_index(new_hex(0, 1, -1)), "0102") + testing.expect_value(t, hex_index(new_hex(1, 1, -2)), "0202") +} + +@(test) +test_hex_round :: proc(t: ^testing.T) { + a := new_hex(0.0, 0.0, 0.0) + b := new_hex(1.0, -1.0, 0.0) + c := new_hex(0.0, -1.0, 1.0) + d := new_hex(10.0, -20.0, 10.0) + e := new_hex(5, -10, 5) + f := new_hex( + a.x * 0.4 + b.x * 0.3 + c.x * 0.3, + a.y * 0.4 + b.y * 0.3 + c.y * 0.3, + a.z * 0.4 + b.z * 0.3 + c.z * 0.3, + ) + g := new_hex( + a.x * 0.3 + b.x * 0.3 + c.x * 0.4, + a.y * 0.3 + b.y * 0.3 + c.y * 0.4, + a.z * 0.3 + b.z * 0.3 + c.z * 0.4, + ) + + testing.expect_value(t, hex_round(hex_lerp(a, d, 0.5)), e) + testing.expect_value(t, hex_round(a), hex_round(hex_lerp(a, b, 0.499))) + testing.expect_value(t, hex_round(b), hex_round(hex_lerp(a, b, 0.501))) + testing.expect_value(t, hex_round(a), hex_round(f)) + testing.expect_value(t, hex_round(c), hex_round(g)) +} diff --git a/layout.odin b/layout.odin new file mode 100644 index 0000000..0425a66 --- /dev/null +++ b/layout.odin @@ -0,0 +1,11 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +new_layout :: proc(orientation: Orientation, origin, size: Point) -> Layout { + return {orientation, origin, size} +} diff --git a/layout_test.odin b/layout_test.odin new file mode 100644 index 0000000..16a6705 --- /dev/null +++ b/layout_test.odin @@ -0,0 +1,17 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" + +@(test) +test_new_layout :: proc(t: ^testing.T) { + hex := new_hex(3, 4, -7) + flat := new_layout(flat_orientation(), new_point(10.0, 15.0), new_point(35.0, 71.0)) + + testing.expect_value(t, pixel_to_hex_rounded(flat, hex_to_pixel(flat, hex)), hex) +} diff --git a/main.odin b/main.odin index 14297dc..dbd4c47 100644 --- a/main.odin +++ b/main.odin @@ -6,8 +6,10 @@ package main -import "viewer" +import "core:os" main :: proc() { - viewer.run() + if err := run(); err != nil { + os.exit(1) + } } diff --git a/offset.odin b/offset.odin new file mode 100644 index 0000000..1755e91 --- /dev/null +++ b/offset.odin @@ -0,0 +1,26 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +new_offset :: proc(col, row: f32) -> Offset { + return {col, row} +} + +qoffset_from_cube :: proc(hex: Hex) -> Offset { + col := hex.x + row := hex.y + (hex.x + ODD_OFFSET * f32(i32(hex.x) & 1)) / 2 + + return new_offset(col, row) +} + +qoffset_to_cube :: proc(offset: Offset) -> Hex { + q := offset.x + r := offset.y - (offset.x + ODD_OFFSET * f32(i32(offset.x) & 1)) / 2 + s := -q - r + + return new_hex(q, r, s) +} diff --git a/offset_test.odin b/offset_test.odin new file mode 100644 index 0000000..5d2855d --- /dev/null +++ b/offset_test.odin @@ -0,0 +1,26 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" + +@(test) +test_new_offset :: proc(t: ^testing.T) { + testing.expect_value(t, new_offset(1, 2), Offset{1, 2}) +} + +@(test) +test_qoffset_from_cube :: proc(t: ^testing.T) { + testing.expect_value(t, qoffset_from_cube(new_hex(-2, 3, -1)), new_offset(-2, 2)) + testing.expect_value(t, qoffset_from_cube(new_hex(-1, -1, 2)), new_offset(-1, -2)) +} + +@(test) +test_qoffset_to_cube :: proc(t: ^testing.T) { + testing.expect_value(t, qoffset_to_cube(new_offset(-2, 2)), new_hex(-2, 3, -1)) + testing.expect_value(t, qoffset_to_cube(new_offset(-1, -2)), new_hex(-1, -1, 2)) +} diff --git a/ols.json b/ols.json new file mode 100644 index 0000000..58aa3ea --- /dev/null +++ b/ols.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://raw.githubusercontent.com/DanielGavin/ols/master/misc/ols.schema.json", + "enable_document_symbols": true, + "enable_hover": true, + "enable_snippets": true +} diff --git a/orientation.odin b/orientation.odin new file mode 100644 index 0000000..95314f5 --- /dev/null +++ b/orientation.odin @@ -0,0 +1,19 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:math" +import "core:math/linalg" + +flat_orientation :: proc() -> Orientation { + f := matrix[2, 2]f32{ + 3.0 / 2.0, 0.0, + math.SQRT_THREE / 2.0, math.SQRT_THREE, + } + + return {f, linalg.inverse(f), 0.0} +} diff --git a/orientation_test.odin b/orientation_test.odin new file mode 100644 index 0000000..f578cb7 --- /dev/null +++ b/orientation_test.odin @@ -0,0 +1,25 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:math" +import "core:testing" + +@(test) +test_flat_orientation :: proc(t: ^testing.T) { + f := matrix[2, 2]f32{ + 3.0 / 2.0, 0.0, + math.SQRT_THREE / 2.0, math.SQRT_THREE, + } + + b := matrix[2, 2]f32{ + 2.0 / 3.0, -0.0, + -1.0 / 3.0, math.SQRT_THREE / 3.0, + } + + testing.expect_value(t, flat_orientation(), Orientation{f, b, 0.0}) +} diff --git a/point.odin b/point.odin new file mode 100644 index 0000000..afac172 --- /dev/null +++ b/point.odin @@ -0,0 +1,28 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +new_point :: proc(x, y: f32) -> Point { + return {x, y} +} + +pixel_to_hex_fractional :: proc(layout: Layout, p: Point) -> Hex { + M := layout.orientation + origin := layout.origin + size := layout.size + + pt := new_point((p.x - origin.x) / size.x, (p.y - origin.y) / size.y) + + q := M.b[0, 0] * pt.x + M.b[0, 1] * pt.y + r := M.b[1, 0] * pt.x + M.b[1, 1] * pt.y + + return new_hex(q, r, -q - r) +} + +pixel_to_hex_rounded :: proc(layout: Layout, p: Point) -> Hex { + return hex_round(pixel_to_hex_fractional(layout, p)) +} diff --git a/point_test.odin b/point_test.odin new file mode 100644 index 0000000..b89d0b9 --- /dev/null +++ b/point_test.odin @@ -0,0 +1,14 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" + +@(test) +test_new_point :: proc(t: ^testing.T) { + testing.expect_value(t, new_point(1, 2), Point{1, 2}) +} diff --git a/sector.odin b/sector.odin new file mode 100644 index 0000000..ff010af --- /dev/null +++ b/sector.odin @@ -0,0 +1,66 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:math" +import "core:strings" +import rl "vendor:raylib" + +new_sector :: proc(name: string, origin: Point = {0, 0}) -> Sector { + hexes: map[string]Hex + + left := origin.x + right := origin.x + SECTOR_COLUMNS + top := origin.y + bottom := origin.y + SECTOR_ROWS - 1 + + for q := left; q < right; q += 1 { + q_offset := math.floor(q / 2.0) + for r := top - q_offset; r <= bottom - q_offset; r += 1 { + hex := new_hex(q, r, -q - r) + index := hex_index(hex) + hexes[index] = hex + } + } + + layout := new_layout(flat_orientation(), origin, {HEX_SIZE, HEX_SIZE}) + + return {name, hexes, layout} +} + +delete_sector :: proc(sector: Sector) { + delete(sector.hexes) +} + +contains_hex :: proc(hex: Hex) -> bool { + offset := qoffset_from_cube(hex) + + return offset.x >= 0 && offset.y >= 0 && offset.x < SECTOR_COLUMNS && offset.y < SECTOR_ROWS +} + +draw_sector :: proc(sector: Sector, camera: rl.Camera2D) { + for _, hex in sector.hexes { + draw_hex(sector.layout, hex, rl.DARKGRAY) + } + + position := rl.GetScreenToWorld2D(rl.GetMousePosition(), camera) + hovered := pixel_to_hex_rounded(sector.layout, position) + + if contains_hex(hovered) { + index := strings.clone_to_cstring(hex_index(hovered)) + + rl.DrawText(index, i32(position.x), i32(position.y - 8), 8, rl.WHITE) + + draw_hex(sector.layout, hovered, rl.RED) + } +} + +draw_hex :: proc(layout: Layout, hex: Hex, color: rl.Color) { + center := hex_to_pixel(layout, hex) + + rl.DrawPolyLines(center, 6, HEX_SIZE, 0, color) +} diff --git a/sector_test.odin b/sector_test.odin new file mode 100644 index 0000000..2a4c99b --- /dev/null +++ b/sector_test.odin @@ -0,0 +1,19 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import "core:testing" + +@(test) +test_new_sector :: proc(t: ^testing.T) { + sector := new_sector("Foo") + defer delete_sector(sector) + + testing.expect_value(t, sector.name, "Foo") + testing.expect_value(t, sector.layout.origin, Point{0, 0}) + testing.expect_value(t, sector.layout.size, Point{HEX_SIZE, HEX_SIZE}) +} diff --git a/types.odin b/types.odin new file mode 100644 index 0000000..5f87e13 --- /dev/null +++ b/types.odin @@ -0,0 +1,36 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +package main + +import rl "vendor:raylib" + +Error :: enum { + Initialization_Failed, +} + +Hex :: rl.Vector3 + +Layout :: struct { + orientation: Orientation, + origin, size: Point, +} + +Offset :: rl.Vector2 + +Orientation :: struct { + f: matrix[2, 2]f32, + b: matrix[2, 2]f32, + start_angle: f32, +} + +Point :: rl.Vector2 + +Sector :: struct { + name: string, + hexes: map[string]Hex, + layout: Layout, +} diff --git a/viewer/camera.odin b/viewer/camera.odin deleted file mode 100644 index 05e2220..0000000 --- a/viewer/camera.odin +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package viewer - -import "core:math" -import rl "vendor:raylib" - -new_camera :: proc() -> rl.Camera2D { - return {zoom = 1.0} -} - -pan_camera :: proc(camera: ^rl.Camera2D) { - if rl.IsMouseButtonDown(.RIGHT) { - delta := rl.GetMouseDelta() - delta *= -1.0 / camera.zoom - - camera.target += delta - } -} - -zoom_camera :: proc(camera: ^rl.Camera2D) { - if wheel := rl.GetMouseWheelMove(); wheel != 0.0 { - position := rl.GetMousePosition() - world := rl.GetScreenToWorld2D(position, camera^) - - camera.offset = position - camera.target = world - - scale := 0.2 * wheel - camera.zoom = clamp(math.exp(math.log(camera.zoom, math.E) + scale), 0.125, 64.0) - } -} diff --git a/viewer/coordinate.odin b/viewer/coordinate.odin deleted file mode 100644 index 93238f6..0000000 --- a/viewer/coordinate.odin +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package viewer - -import "core:math" -import rl "vendor:raylib" - -Coordinate :: struct { - col, row: i32, -} - -new_coordinate :: proc(col, row: i32) -> Coordinate { - return {col, row} -} - -oddq_to_axial :: proc(coord: Coordinate) -> Hex { - parity := coord.col & 1 - q := coord.col - r := coord.row - (coord.col - parity) / 2 - - return new_hex(q, r) -} - -oddq_offset_to_pixel :: proc(coord: Coordinate) -> rl.Vector2 { - x := 1.5 * f32(coord.col) - y := math.SQRT_THREE * (f32(coord.row) + 0.5 * f32(coord.col & 1)) - x *= HEX_SIZE - y *= HEX_SIZE - - return {x, y} -} diff --git a/viewer/hex.odin b/viewer/hex.odin deleted file mode 100644 index 1e91781..0000000 --- a/viewer/hex.odin +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package viewer - -import rl "vendor:raylib" - -Hex :: struct { - q, r: i32, -} - -new_hex :: proc(q, r: i32) -> Hex { - return {q, r} -} - -draw_hex :: proc(hex: Hex) { - center := oddq_offset_to_pixel(axial_to_oddq(hex)) - rl.DrawPolyLines(center, 6, HEX_SIZE, 0, rl.DARKGRAY) -} - -axial_to_oddq :: proc(hex: Hex) -> Coordinate { - parity := hex.q & 1 - col := hex.q - row := hex.r + (hex.q - parity) / 2 - - return new_coordinate(col, row) -} diff --git a/viewer/sector.odin b/viewer/sector.odin deleted file mode 100644 index 28bcc2e..0000000 --- a/viewer/sector.odin +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package viewer - -import rl "vendor:raylib" - -Sector :: struct { - name: cstring, - hexes: [SECTOR_ROWS][SECTOR_COLUMNS]Hex, - origin: Coordinate, -} - -new_sector :: proc(name: cstring, origin: Coordinate) -> Sector { - hexes: [SECTOR_ROWS][SECTOR_COLUMNS]Hex - - for &row, y in hexes { - for &hex, x in row { - hex = oddq_to_axial({origin.col + i32(x), origin.row + i32(y)}) - } - } - - return {name, hexes, origin} -} - -draw_sector :: proc(sector: Sector) { - for row in sector.hexes { - for hex in row { - draw_hex(hex) - } - } - - position := oddq_offset_to_pixel({sector.origin.col + 4, sector.origin.row + 18}) - - rl.DrawText(sector.name, i32(position.x - 8), i32(position.y - 8), 48, rl.WHITE) -}