Last active
February 4, 2024 12:23
-
-
Save Shilo/b2f1e7f58f476184e1960623690c3097 to your computer and use it in GitHub Desktop.
Simple runtime tilemap editor that will draw the a terrain from a tileset. (Left click = place, Right click = remove, Middle click = pan)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class_name TileMapEditor extends TileMap | |
enum InputState { | |
NONE, | |
PLACE, | |
REMOVE, | |
PAN | |
} | |
var input_state: InputState = InputState.NONE | |
var pan_start_position: Vector2 = Vector2.ZERO | |
var last_tile_position: Vector2 = Vector2.ZERO | |
func _unhandled_input(event: InputEvent): | |
if event is InputEventMouseButton: | |
on_mouse_button(event) | |
elif event is InputEventMouseMotion: | |
on_mouse_move() | |
func on_mouse_button(event: InputEventMouseButton): | |
if event.button_index == MOUSE_BUTTON_LEFT: | |
update_input_state(event, InputState.PLACE) | |
elif event.button_index == MOUSE_BUTTON_RIGHT: | |
update_input_state(event, InputState.REMOVE) | |
elif event.button_index == MOUSE_BUTTON_MIDDLE: | |
update_input_state(event, InputState.PAN) | |
func update_input_state(event: InputEventMouseButton, target_state: InputState): | |
var pressed := event.pressed | |
if pressed: | |
input_state = target_state | |
elif input_state == target_state: | |
input_state = InputState.NONE | |
update_input(pressed) | |
func on_mouse_move(): | |
if input_state == InputState.NONE: | |
return | |
update_input(false) | |
func update_input(start: bool = false): | |
if input_state == InputState.PLACE: | |
place_tile(start) | |
elif input_state == InputState.REMOVE: | |
remove_tile(start) | |
elif input_state == InputState.PAN: | |
pan_map(start) | |
func place_tile(start: bool = false): | |
var tile_position := cur_tile_position() | |
var path := [tile_position] if start else tile_path(last_tile_position, tile_position) | |
set_cells_terrain_connect(0, path, 0, 0) | |
#for tile in path: set_cell(0, tile, 0, Vector2i(0, 0)) | |
last_tile_position = tile_position | |
func remove_tile(start: bool = false): | |
var tile_position := cur_tile_position() | |
var path := [tile_position] if start else tile_path(last_tile_position, tile_position) | |
set_cells_terrain_connect(0, path, 0, -1) | |
#for tile in path: set_cell(0, tile) | |
last_tile_position = tile_position | |
func pan_map(start: bool): | |
if start: | |
pan_start_position = get_local_mouse_position() | |
return | |
position += get_local_mouse_position() - pan_start_position | |
func cur_tile_position() -> Vector2: | |
return Vector2i(get_local_mouse_position()) / tile_set.tile_size | |
func tile_path(start: Vector2, end: Vector2) -> Array: | |
var path := [] | |
var delta := end - start | |
var step := delta.normalized() | |
var distance := delta.length() | |
for i in range(0, int(distance) + 1): | |
path.append(start + step * i) | |
if distance < 1: | |
path.append(end) | |
return path |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Might be able to optimize it by not redrawing the current tile when moving mouse. But TileMap may optimize this anyhow.