84 lines
3.1 KiB
GDScript
84 lines
3.1 KiB
GDScript
tool
|
|
extends TileMap
|
|
|
|
# todo: Give care about descriptor swaps being loseless / non introducing artifacts.
|
|
# todo: Prevent user from deleting or editing tile_set property.
|
|
|
|
# todo: Update it when changed.
|
|
## Dictates whether tileset collision information should be exposed to game context.
|
|
export var expose_collisions: bool = true
|
|
|
|
# todo: Use Node identity instead of name.
|
|
var _descriptor_name_to_id: Dictionary # String to int
|
|
var _id_to_descriptor_name: Dictionary # int to String
|
|
|
|
func change_tile_texture(p_tile: String, p_texture: Texture) -> void:
|
|
if not p_tile in _descriptor_name_to_id:
|
|
push_error("Invalid tile name")
|
|
return
|
|
|
|
var id := _descriptor_name_to_id[p_tile] as int
|
|
tile_set.tile_set_texture(id, p_texture)
|
|
|
|
func is_path_traversible(p_game_object: Node2D, p_from: Vector2, p_to: Vector2) -> bool:
|
|
if p_from.distance_squared_to(p_to) == 1:
|
|
var id := get_cell(int(p_to.x), int(p_to.y))
|
|
if id == -1: return true
|
|
var descriptor = _id_to_descriptor_name[id] as String
|
|
return get_node(descriptor).is_traversible_for(p_game_object)
|
|
else:
|
|
print_debug("Unimplemented")
|
|
return false
|
|
|
|
func _enter_tree() -> void:
|
|
tile_set = TileSet.new()
|
|
|
|
var n_parent := get_parent()
|
|
if not n_parent is TK_Context:
|
|
return
|
|
|
|
n_parent.register_collider(self)
|
|
|
|
# It's okay to fail here for non-grid contexts.
|
|
if not n_parent.is_connected("cell_size_changed", self, "_update_cell_size") and \
|
|
n_parent.connect("cell_size_changed", self, "_update_cell_size") != OK:
|
|
assert(false)
|
|
|
|
_update_cell_size(n_parent.cell_size, n_parent.cell_size)
|
|
|
|
if not is_connected("child_entered_tree", self, "_on_child_entered_tree") and \
|
|
connect("child_entered_tree", self, "_on_child_entered_tree") != OK:
|
|
assert(false)
|
|
|
|
if not is_connected("child_exiting_tree", self, "_on_child_exiting_tree") and \
|
|
connect("child_exiting_tree", self, "_on_child_exiting_tree") != OK:
|
|
assert(false)
|
|
|
|
func _update_cell_size(_p_old_cell_size: Vector2, p_new_cell_size: Vector2) -> void:
|
|
# We're assuming that all tile textures are of same dimensions.
|
|
# todo: Diagnose mismatch by walking over all textures?
|
|
if tile_set.get_tiles_ids().size() == 0:
|
|
return
|
|
var tileset_texture_size := tile_set.tile_get_texture(0).get_size()
|
|
scale = p_new_cell_size / tileset_texture_size
|
|
cell_size = p_new_cell_size / scale
|
|
|
|
func _on_child_entered_tree(p_node: Node) -> void:
|
|
var id := tile_set.get_last_unused_tile_id()
|
|
_descriptor_name_to_id[p_node.name] = id
|
|
_id_to_descriptor_name[id] = p_node.name
|
|
tile_set.create_tile(id)
|
|
tile_set.tile_set_texture(id, p_node.texture)
|
|
if not p_node.id.empty():
|
|
tile_set.tile_set_name(id, p_node.id)
|
|
|
|
func _on_child_exiting_tree(p_node: Node) -> void:
|
|
var id := _descriptor_name_to_id[p_node.name] as int
|
|
for cell in get_used_cells_by_id(id):
|
|
set_cellv(cell, -1)
|
|
tile_set.remove_tile(id)
|
|
if not _descriptor_name_to_id.erase(p_node.name):
|
|
assert(false)
|
|
if not _id_to_descriptor_name.erase(id):
|
|
assert(false)
|