This repository has been archived on 2020-09-30. You can view files and clone it, but cannot push or open issues or pull requests.
odyssey-old/Scenes/MapEditor.gd

208 lines
5.8 KiB
GDScript

extends Control
onready var map_menu := ($menu/menubar/MapMenu as MenuButton).get_popup()
onready var map_node := $map
onready var cursor := $map/cursor
onready var cursor_sprite := $map/cursor/preview
const MAP_SCALE_MAX := 8.0
const MAP_SCALE_MIN := 0.25
const TileTabScene := preload("res://Scenes/Editor/TileTab.tscn")
func _ready():
add_tile_tab("Base", $map/tiles/base)
add_tile_tab("Floors", $map/tiles/floor)
add_tile_tab("Walls", $map/tiles/walls)
enum PlacingMode {
NONE,
TILEMAP,
OBJECT
}
# Prevent input handler from running when other dialogs/actions are focused
var input_lock := false
# Drag variables
var dragging := false
var view_origin := Vector2.ZERO
var mouse_origin := Vector2.ZERO
# Placing variables
var placing := false
var deleting := false
var placing_mode = PlacingMode.NONE
var placing_layer = null
var placing_tile_id := -1
var current_brush := "none"
# Cursor variables
var cursor_pos := Vector2.ZERO
var pressed_pos := Vector2.ZERO
const TILE_SIZE := 32
func _input(ev: InputEvent):
if input_lock:
return
if ev is InputEventMouseMotion:
if dragging:
map_node.global_position = view_origin - (mouse_origin - ev.global_position)
else:
# Map cursor location to grid
var tile_snap: Vector2 = map_node.scale * TILE_SIZE
var mouse_offset: Vector2 = (ev.global_position - map_node.global_position) / tile_snap
var new_cursor_pos := Vector2(floor(mouse_offset.x), floor(mouse_offset.y))
if new_cursor_pos != cursor_pos:
var old_pos = cursor_pos
cursor_pos = new_cursor_pos
if placing or deleting:
handle_held_cursor_move(old_pos, new_cursor_pos)
cursor.position = cursor_pos * TILE_SIZE
if ev is InputEventMouseButton:
var mouse := ev as InputEventMouseButton
if mouse.pressed:
match ev.button_index:
BUTTON_LEFT:
if current_brush == "freehand":
place_tiles([cursor_pos], placing_tile_id)
placing = true
pressed_pos = cursor_pos
BUTTON_RIGHT:
if current_brush == "freehand":
place_tiles([cursor_pos], -1)
deleting = true
BUTTON_WHEEL_UP:
# Zoom in
var old_scale = map_node.scale
if map_node.scale.x < MAP_SCALE_MAX:
if map_node.scale.x < 1:
map_node.scale *= 2
else:
map_node.scale += Vector2.ONE
map_node.position -= (map_node.position + mouse.position * map_node.scale)- (map_node.position + mouse.position * old_scale)
BUTTON_WHEEL_DOWN:
# Zoom out
var old_scale = map_node.scale
if map_node.scale.x > MAP_SCALE_MIN:
if map_node.scale.x <= 1:
map_node.scale /= 2
else:
map_node.scale -= Vector2.ONE
map_node.position -= (map_node.position + mouse.position * map_node.scale)- (map_node.position + mouse.position * old_scale)
BUTTON_MIDDLE:
view_origin = map_node.global_position
mouse_origin = ev.global_position
dragging = true
else:
match ev.button_index:
BUTTON_LEFT:
if current_brush == "rect":
place_rect(pressed_pos, cursor_pos, placing_tile_id)
placing = false
BUTTON_RIGHT:
deleting = false
BUTTON_MIDDLE:
dragging = false
map_node.global_position = view_origin - (mouse_origin - ev.global_position)
func handle_held_cursor_move(old_pos: Vector2, new_pos: Vector2):
match current_brush:
"freehand":
var id = placing_tile_id
# If deleting, null tile instead
if deleting:
id = -1
place_tiles([new_pos], id)
func place_rect(a: Vector2, b: Vector2, id: int):
if placing_layer == null:
return
var layer := placing_layer as TileMap
# Sort coordinates
var x_ord = Vector2(a.x, b.x)
var y_ord = Vector2(a.y, b.y)
if a.x > b.x:
x_ord = Vector2(b.x, a.x)
if a.y > b.y:
y_ord = Vector2(b.y, a.y)
var positions = []
for x in range(x_ord.x, x_ord.y+1):
layer.set_cellv(Vector2(x, a.y), id)
layer.set_cellv(Vector2(x, b.y), id)
for y in range(y_ord.x, y_ord.y+1):
layer.set_cellv(Vector2(a.x, y), id)
layer.set_cellv(Vector2(b.x, y), id)
layer.update_bitmask_region(a, b)
func place_tiles(positions: Array, id: int):
if placing_layer == null:
return
var layer := placing_layer as TileMap
for pos in positions:
# Place tile
layer.set_cellv(pos, id)
for pos in positions:
# Update bitmask
layer.update_bitmask_area(pos)
var group := ButtonGroup.new()
func add_tile_tab(name: String, tilemap: TileMap):
var tab := add_tab(name)
tab.connect("tile_selected", self, "_tile_selected", [name, tilemap])
var tileset := tilemap.tile_set
var ids := tileset.get_tiles_ids()
for id in ids:
var tile_name := tileset.tile_get_name(id)
var tile_icon := make_tile_texture(tileset, id)
tab.add_entry(id, group, tile_icon)
func add_tab(name: String) -> TileTab:
var tab := TileTabScene.instance() as TileTab
tab.name = name
$layers/tabs.add_child(tab)
return tab
func _toggle_tile_input(enable: bool):
input_lock = not enable
func _tile_selected(id: int, name: String, tilemap: TileMap):
cursor_sprite.texture = make_tile_texture(tilemap.tile_set, id)
placing_mode = PlacingMode.TILEMAP
placing_layer = tilemap
placing_tile_id = id
func make_tile_texture(tileset: TileSet, id: int) -> AtlasTexture:
var tile_mode := tileset.tile_get_tile_mode(id)
var tile_icon := AtlasTexture.new()
tile_icon.atlas = tileset.tile_get_texture(id)
match tile_mode:
TileSet.AUTO_TILE:
var tile_size := tileset.autotile_get_size(id)
tile_icon.region = Rect2(
tileset.autotile_get_icon_coordinate(id) * tile_size,
tile_size
)
TileSet.SINGLE_TILE:
tile_icon.region = tileset.tile_get_region(id)
return tile_icon
onready var layers_panel = $layers
onready var brush_panel = $tools/brushPanel
func _tool_selected(tool_type):
layers_panel.visible = false
brush_panel.visible = false
placing_mode = PlacingMode.NONE
match tool_type:
"tile":
layers_panel.visible = true
brush_panel.visible = true
placing_mode = PlacingMode.TILEMAP
func _set_brush(brush_type: String):
current_brush = brush_type