hadean-godot/Scripts/Grid.gd

193 lines
4.6 KiB
GDScript

@tool
class_name Grid
extends Node2D
@export var cells: int:
set(val):
cells = val
_calc_dims()
@export var cell_size: int:
set(val):
cell_size = val
_calc_dims()
var total_width: int
var total_height: int
var thickness: int
var off: Vector2
@onready var selection_manager: SelectionManager = Util.find(SelectionManager)
func _enter_tree():
_calc_dims()
func _ready():
_calc_dims()
Engine.is_editor_hint()
func _calc_dims():
total_width = cells * cell_size
total_height = cells * cell_size
thickness = 1
off = Vector2(total_width / -2, total_height / -2)
func _process(_delta):
queue_redraw()
func _draw():
var r = Rect2(off, Vector2(total_width, total_height))
draw_rect(r, Color("222222"), true)
var line_color = Color(1, 1, 1, 0.3)
for i in range(cells + 1):
draw_line(Vector2(i * cell_size, 0) + off, Vector2(i * cell_size, total_height) + off, line_color, thickness, false)
for i in range(cells + 1):
draw_line(Vector2(0, i * cell_size) + off, Vector2(total_width, i * cell_size) + off, line_color, thickness, false)
for x in range(cells):
for y in range(cells):
var world_pos = Vector2i(x, y)
var tile = _get_tile_at_tile_pos(world_pos)
if tile == null:
continue
var t = Rect2(
tile2world(world_pos),
Vector2.ONE * cell_size
)
draw_rect(t, Color("773322"))
func tile2world(tile: Vector2i) -> Vector2i:
return Vector2(tile) * cell_size + off
func tile2world_rect(tile: Rect2i) -> Rect2:
return Rect2(Vector2(tile.position) * cell_size + off, tile.size * cell_size)
func tile2world_size(tile_size: Vector2i) -> Vector2:
return Vector2(tile_size * cell_size)
func world2tile(world_pos: Vector2) -> Vector2i:
return Vector2i(((world_pos - off) / cell_size).floor())
func world2tile_f(world_pos: Vector2) -> Vector2:
return (world_pos - off) / cell_size
func world2tile_rect(rect: Rect2) -> Rect2i:
var start = world2tile(rect.position)
var end = world2tile(rect.end)
return Rect2i(start, end - start)
func quantize(world_position: Vector2, tile_size: Vector2i) -> Rect2:
var q_pos = tile2world(world2tile(world_position))
return Rect2(q_pos, tile_size * cell_size)
func quantize_on_objects(world_position: Vector2) -> Rect2:
var tile_pos = world2tile(world_position)
var size = Vector2i.ONE
for tile in things:
# we subtract ONE here, because the encloses thing is a >= test and goes OOB with integers
if Rect2(tile.tile_pos, tile.size - Vector2i.ONE).encloses(Rect2(tile_pos, Vector2.ZERO)):
size = tile.size
tile_pos = tile.tile_pos
break
return tile2world_rect(Rect2i(tile_pos, size))
func _get_tile_at_tile_pos(pos: Vector2i) -> Positional:
for tile in things:
if tile.get_tilebox().has_point(pos):
return tile
return null
func _get_tile_at_world_pos(pos: Vector2) -> Positional:
#var world_pos = world2tile_f(pos)
for tile in things:
if tile.worldbox.has_point(pos):
return tile
return null
func contains_world_pos(pos: Vector2) -> bool:
var tile = world2tile(pos)
if tile.x < 0 or tile.x > cells - 1:
return false
if tile.y < 0 or tile.y > cells - 1:
return false
return true
func _shift_rect_half(rect: Rect2) -> Rect2:
return Rect2(rect.position + rect.size / -2, rect.size)
var left_dragging = false
var left_mouse_down = false
var left_mouse_down_start_pos: Vector2 = Vector2.ZERO
func _is_mouse_pos_significant() -> bool:
return (get_local_mouse_position() - left_mouse_down_start_pos).length_squared() > 50
func _input(event: InputEvent):
if event is InputEventMouseMotion:
if left_mouse_down:
if not left_dragging and _is_mouse_pos_significant():
left_dragging = true
_begin_drag(get_local_mouse_position())
elif left_dragging:
_dragging(get_local_mouse_position())
elif event is InputEventMouseButton:
if event.button_index == 1:
left_mouse_down = event.pressed
if event.pressed:
left_mouse_down_start_pos = get_local_mouse_position()
else:
if left_dragging:
left_dragging = false
_end_drag(get_local_mouse_position())
else:
_click(get_local_mouse_position())
var things: Array[Positional] = []
var things_dict: Dictionary = {}
func register_tile(tile: Positional) -> void:
things.append(tile)
func remove_tile(tile: Positional) -> void:
things.erase(tile)
func _begin_drag(pos: Vector2):
print("drag from", pos)
func _dragging(pos: Vector2):
pass
func _end_drag(pos: Vector2):
print("to", pos)
func _click(pos: Vector2):
print("click at", pos)
var tile = _get_tile_at_world_pos(pos)
if tile == null:
selection_manager.clear()
return
selection_manager.select_array([tile])
func _double_click(pos: Vector2):
pass
func _right_click(pos: Vector2):
pass