关卡重构
@ -1,53 +0,0 @@
|
||||
@tool
|
||||
extends "res://addons/MetroidvaniaSystem/Database/CellPaintEditor.gd"
|
||||
|
||||
func _editor_init() -> void:
|
||||
use_cursor = false
|
||||
super()
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
var cell_data := get_cell_at_cursor()
|
||||
|
||||
if event is InputEventMouseMotion:
|
||||
if cell_data:
|
||||
var rel := editor.map_overlay.get_local_mouse_position().posmodv(MetSys.CELL_SIZE)
|
||||
var border := get_square_border_idx(cell_data.borders, rel)
|
||||
|
||||
var new_border := -1
|
||||
var borders: Array[int] = cell_data.borders
|
||||
|
||||
for i in 4:
|
||||
if border == i and borders[i] > -1:
|
||||
new_border = border
|
||||
break
|
||||
|
||||
if new_border != highlighted_border:
|
||||
highlighted_border = new_border
|
||||
editor.map_overlay.queue_redraw()
|
||||
else:
|
||||
highlighted_border = -1
|
||||
|
||||
super(event)
|
||||
|
||||
func update_hovered_room():
|
||||
if highlighted_border == -1:
|
||||
highlighted_room.clear()
|
||||
return
|
||||
|
||||
super()
|
||||
|
||||
func modify_cell(cell_data: MetroidvaniaSystem.MapData.CellData, mode: int) -> bool:
|
||||
if highlighted_border == -1:
|
||||
return false
|
||||
|
||||
var modified: bool
|
||||
if whole_room:
|
||||
for i in 4:
|
||||
modified = modify_border(cell_data, i, mode) or modified
|
||||
else:
|
||||
modified = modify_border(cell_data, highlighted_border, mode)
|
||||
|
||||
return modified
|
||||
|
||||
func modify_border(cell_data: MetroidvaniaSystem.MapData.CellData, border: int, mode: int) -> bool:
|
||||
return false
|
||||
@ -1,82 +0,0 @@
|
||||
@tool
|
||||
extends "res://addons/MetroidvaniaSystem/Database/SubEditor.gd"
|
||||
|
||||
enum { MODE_DRAW, MODE_ERASE, MODE_PICK }
|
||||
|
||||
var can_pick: bool
|
||||
var super_use_cursor: bool
|
||||
var whole_room: bool
|
||||
|
||||
func _editor_init() -> void:
|
||||
super_use_cursor = use_cursor
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Shortcuts.show()
|
||||
%ShortcutPick.visible = can_pick
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Shortcuts.hide()
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
if event.pressed:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if can_pick and not whole_room and event.is_command_or_control_pressed():
|
||||
paint(MODE_PICK)
|
||||
else:
|
||||
paint(MODE_DRAW)
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
paint(MODE_ERASE)
|
||||
|
||||
elif event is InputEventMouseMotion:
|
||||
if whole_room:
|
||||
update_hovered_room()
|
||||
|
||||
if event.button_mask & (MOUSE_BUTTON_MASK_LEFT | MOUSE_BUTTON_MASK_RIGHT):
|
||||
var erase := bool(event.button_mask & MOUSE_BUTTON_MASK_RIGHT)
|
||||
paint(MODE_ERASE if erase else MODE_DRAW)
|
||||
|
||||
elif event is InputEventKey:
|
||||
if not event.echo and event.keycode == KEY_SHIFT:
|
||||
whole_room = event.pressed
|
||||
use_cursor = super_use_cursor and not whole_room
|
||||
if whole_room:
|
||||
update_hovered_room()
|
||||
else:
|
||||
highlighted_room.clear()
|
||||
|
||||
editor.map_overlay.queue_redraw()
|
||||
|
||||
func update_hovered_room():
|
||||
var hr := highlighted_room
|
||||
highlighted_room = MetSys.map_data.get_whole_room(get_coords(get_cursor_pos()))
|
||||
if highlighted_room != hr:
|
||||
editor.map_overlay.queue_redraw()
|
||||
|
||||
func paint(mode: int):
|
||||
var coords_to_modify: Array[Vector3i]
|
||||
if whole_room:
|
||||
coords_to_modify = highlighted_room
|
||||
else:
|
||||
coords_to_modify.assign([get_coords(get_cursor_pos())])
|
||||
|
||||
var modified: bool
|
||||
for coords in coords_to_modify:
|
||||
var cell_data := MetSys.map_data.get_cell_at(coords)
|
||||
if not cell_data:
|
||||
continue
|
||||
|
||||
if modify_cell(cell_data, mode) or modify_coords(coords, mode):
|
||||
modified = true
|
||||
|
||||
if modified:
|
||||
mark_modified()
|
||||
editor.map.queue_redraw()
|
||||
|
||||
func modify_cell(cell_data: MetroidvaniaSystem.MapData.CellData, mode: int) -> bool:
|
||||
return false
|
||||
|
||||
func modify_coords(coords: Vector3i, mode: int) -> bool:
|
||||
return false
|
||||
@ -1,19 +0,0 @@
|
||||
[gd_resource type="Theme" format=3 uid="uid://dfyoc5jqnnpf5"]
|
||||
|
||||
[resource]
|
||||
MetSys/colors/active_custom_element = Color(0.1, 0.1, 1, 0.8)
|
||||
MetSys/colors/assigned_scene = Color(0.235294, 0.701961, 0.443137, 0.8)
|
||||
MetSys/colors/border_highlight = Color(0, 1, 0, 0.5)
|
||||
MetSys/colors/current_scene_room = Color(1, 0, 0, 0.5)
|
||||
MetSys/colors/cursor_color = Color(0, 1, 0, 1)
|
||||
MetSys/colors/cursor_color_erase = Color(1, 0, 0, 1)
|
||||
MetSys/colors/custom_element_marker = Color(1, 1, 0, 1)
|
||||
MetSys/colors/foreign_marked_collectible_room = Color(1, 0, 0, 0.25)
|
||||
MetSys/colors/group_color = Color(0.576471, 0.439216, 0.858824, 0.8)
|
||||
MetSys/colors/highlighted_room = Color(0, 1, 0, 0.25)
|
||||
MetSys/colors/inactive_custom_element = Color(0, 0, 1, 0.4)
|
||||
MetSys/colors/marked_collectible_room = Color(0.541176, 0.168627, 0.886275, 0.75)
|
||||
MetSys/colors/room_assigned = Color(1, 1, 1, 1)
|
||||
MetSys/colors/room_not_assigned = Color(1, 0, 0, 1)
|
||||
MetSys/colors/scene_cell_border = Color(1, 1, 1, 0.33)
|
||||
MetSys/colors/scene_room_exit = Color(1, 0, 1, 0.67)
|
||||
@ -1,57 +0,0 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://crxgu2q73va5y"]
|
||||
|
||||
[ext_resource type="Theme" uid="uid://dfyoc5jqnnpf5" path="res://addons/MetroidvaniaSystem/Database/DatabaseTheme.tres" id="1_hfop4"]
|
||||
[ext_resource type="PackedScene" uid="uid://dfbykrvyqnqr5" path="res://addons/MetroidvaniaSystem/Database/MapEditor.tscn" id="1_lpqq2"]
|
||||
[ext_resource type="PackedScene" uid="uid://df5fuj4vjr11p" path="res://addons/MetroidvaniaSystem/Database/MapViewer.tscn" id="2_0tuq7"]
|
||||
[ext_resource type="PackedScene" uid="uid://he12yvtcmf87" path="res://addons/MetroidvaniaSystem/Database/Manage.tscn" id="2_1dme8"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_ov8k3"]
|
||||
script/source = "@tool
|
||||
extends VBoxContainer
|
||||
|
||||
@onready var tabs = $TabContainer
|
||||
|
||||
var plugin: EditorPlugin
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0ndnc"]
|
||||
bg_color = Color(0, 0, 0, 0.501961)
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_u4ywv"]
|
||||
|
||||
[node name="Main" type="VBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme = ExtResource("1_hfop4")
|
||||
script = SubResource("GDScript_ov8k3")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
theme_type_variation = &"HeaderSmall"
|
||||
text = "Metroidvania System Database"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_0ndnc")
|
||||
tab_alignment = 1
|
||||
|
||||
[node name="Map Editor" parent="TabContainer" instance=ExtResource("1_lpqq2")]
|
||||
layout_mode = 2
|
||||
mode_group = SubResource("ButtonGroup_u4ywv")
|
||||
|
||||
[node name="Map Viewer" parent="TabContainer" instance=ExtResource("2_0tuq7")]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Manage" parent="TabContainer" instance=ExtResource("2_1dme8")]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
@ -1,463 +0,0 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://he12yvtcmf87"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_kxd0b"]
|
||||
script/source = "@tool
|
||||
extends Control
|
||||
|
||||
var plugin: EditorPlugin
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if owner:
|
||||
plugin = owner.plugin
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
%ValidationPanel.add_theme_stylebox_override(&\"panel\", get_theme_stylebox(&\"panel\", &\"Tree\"))
|
||||
|
||||
func edit_settings_pressed():
|
||||
plugin.get_editor_interface().edit_resource(MetSys.settings)
|
||||
|
||||
func force_reload() -> void:
|
||||
MetSys.map_data = MetSys.MapData.new()
|
||||
MetSys.map_data.load_data()
|
||||
|
||||
for group in MetSys.map_data.cell_groups.values():
|
||||
var i: int
|
||||
while i < group.size():
|
||||
if MetSys.map_data.get_cell_at(group[i]):
|
||||
i += 1
|
||||
else:
|
||||
group.remove_at(i)
|
||||
|
||||
func edit_database_theme() -> void:
|
||||
plugin.get_editor_interface().edit_resource(owner.theme)
|
||||
|
||||
func reset_theme() -> void:
|
||||
%AllowReset.button_pressed = false
|
||||
|
||||
var th: Theme = owner.theme
|
||||
th.set_color(&\"group_color\", &\"MetSys\", Color(Color.MEDIUM_PURPLE, 0.8))
|
||||
th.set_color(&\"highlighted_room\", &\"MetSys\", Color(Color.GREEN, 0.25))
|
||||
th.set_color(&\"assigned_scene\", &\"MetSys\", Color(Color.MEDIUM_SEA_GREEN, 0.8))
|
||||
th.set_color(&\"border_highlight\", &\"MetSys\", Color(Color.GREEN, 0.5))
|
||||
th.set_color(&\"cursor_color\", &\"MetSys\", Color.GREEN)
|
||||
th.set_color(&\"cursor_color_erase\", &\"MetSys\", Color.RED)
|
||||
th.set_color(&\"marked_collectible_room\", &\"MetSys\", Color(Color.BLUE_VIOLET, 0.75))
|
||||
th.set_color(&\"foreign_marked_collectible_room\", &\"MetSys\", Color(Color.RED, 0.25))
|
||||
th.set_color(&\"current_scene_room\", &\"MetSys\", Color(Color.RED, 0.5))
|
||||
th.set_color(&\"room_not_assigned\", &\"MetSys\", Color.RED)
|
||||
th.set_color(&\"room_assigned\", &\"MetSys\", Color.WHITE)
|
||||
th.set_color(&\"active_custom_element\", &\"MetSys\", Color(0.1, 0.1, 1, 0.8))
|
||||
th.set_color(&\"inactive_custom_element\", &\"MetSys\", Color(0, 0, 1, 0.4))
|
||||
th.set_color(&\"custom_element_marker\", &\"MetSys\", Color.YELLOW)
|
||||
ResourceSaver.save(th)
|
||||
|
||||
func toggle_allow_reset(button_pressed: bool) -> void:
|
||||
%ResetButton.disabled = not button_pressed
|
||||
|
||||
func refresh_custom_elements() -> void:
|
||||
var custom_script := MetSys.settings.custom_element_script
|
||||
MetSys.settings.custom_element_script = null
|
||||
MetSys.settings.custom_element_script = custom_script
|
||||
MetSys.settings.custom_elements_changed.emit()
|
||||
|
||||
func export_json() -> void:
|
||||
$FileDialog.popup_centered_ratio(0.6)
|
||||
|
||||
func json_file_selected(path: String) -> void:
|
||||
var map_data: Dictionary
|
||||
|
||||
var cells: Dictionary
|
||||
map_data[\"cells\"] = cells
|
||||
|
||||
for cell in MetSys.map_data.cells:
|
||||
var cell_to_save: Dictionary
|
||||
cells[\"%s,%s,%s\" % [cell.x, cell.y, cell.z]] = cell_to_save
|
||||
|
||||
var cell_data := MetSys.map_data.get_cell_at(cell)
|
||||
cell_to_save[\"borders\"] = cell_data.borders
|
||||
if cell_data.symbol > -1:
|
||||
cell_to_save[\"symbol\"] = cell_data.symbol
|
||||
if cell_data.color.a > 0:
|
||||
cell_to_save[\"color\"] = cell_data.color.to_html(false)
|
||||
if cell_data.border_colors.any(func(color: Color) -> bool: return color.a > 0):
|
||||
cell_to_save[\"border_colors\"] = cell_data.border_colors.map(func(color: Color) -> String:
|
||||
return \"000000\" if color.a == 0 else color.to_html(false))
|
||||
if not cell_data.assigned_scene.is_empty():
|
||||
cell_to_save[\"assigned_scene\"] = cell_data.assigned_scene
|
||||
|
||||
var groups: Dictionary
|
||||
|
||||
for group in MetSys.map_data.cell_groups:
|
||||
var group_cells: Array[Vector3i]
|
||||
group_cells.assign(MetSys.map_data.cell_groups[group])
|
||||
|
||||
if group_cells.is_empty():
|
||||
continue
|
||||
|
||||
var group_to_save: Array
|
||||
groups[group] = group_to_save
|
||||
|
||||
for cell in group_cells:
|
||||
group_to_save.append(\"%s,%s,%s\" % [cell.x, cell.y, cell.z])
|
||||
|
||||
if not groups.is_empty():
|
||||
map_data[\"groups\"] = groups
|
||||
|
||||
var elements: Dictionary
|
||||
|
||||
for element in MetSys.map_data.custom_elements:
|
||||
var element_to_save: Dictionary
|
||||
elements[\"%s,%s,%s\" % [element.x, element.y, element.z]] = element_to_save
|
||||
|
||||
var element_data: Dictionary = MetSys.map_data.custom_elements[element]
|
||||
element_to_save[\"name\"] = element_data[\"name\"]
|
||||
element_to_save[\"size\"] = \"%s,%s\" % [element_data[\"size\"].x, element_data[\"size\"].y]
|
||||
if not element_data[\"data\"].is_empty():
|
||||
element_to_save[\"data\"] = element_data[\"data\"]
|
||||
|
||||
if not elements.is_empty():
|
||||
map_data[\"custom_elements\"] = elements
|
||||
|
||||
var file := FileAccess.open(path, FileAccess.WRITE)
|
||||
file.store_string(JSON.stringify(map_data, \"\\t\"))
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_6lvlf"]
|
||||
content_margin_left = 4.0
|
||||
content_margin_top = 4.0
|
||||
content_margin_right = 4.0
|
||||
content_margin_bottom = 5.0
|
||||
bg_color = Color(0.1, 0.1, 0.1, 0.6)
|
||||
corner_radius_top_left = 3
|
||||
corner_radius_top_right = 3
|
||||
corner_radius_bottom_right = 3
|
||||
corner_radius_bottom_left = 3
|
||||
corner_detail = 5
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_x20sf"]
|
||||
resource_name = "ValidationPlanel"
|
||||
script/source = "@tool
|
||||
extends PanelContainer
|
||||
|
||||
enum { SUCCESS, WARNING, ERROR, INFO }
|
||||
|
||||
var plugin: EditorPlugin
|
||||
|
||||
var warning_color: Color
|
||||
var error_color: Color
|
||||
var success_color: Color
|
||||
|
||||
var has_error: bool
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if owner:
|
||||
plugin = owner.plugin
|
||||
|
||||
func _ready() -> void:
|
||||
if plugin:
|
||||
hide()
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
warning_color = get_theme_color(&\"warning_color\", &\"Editor\")
|
||||
error_color = get_theme_color(&\"error_color\", &\"Editor\")
|
||||
success_color = get_theme_color(&\"success_color\", &\"Editor\")
|
||||
|
||||
func validate_map_data() -> void:
|
||||
dismiss()
|
||||
has_error = false
|
||||
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
|
||||
var unused_symbols: Array[int]
|
||||
unused_symbols.assign(range(map_theme.symbols.size()))
|
||||
unused_symbols.erase(map_theme.uncollected_item_symbol)
|
||||
unused_symbols.erase(map_theme.collected_item_symbol)
|
||||
|
||||
for coords in MetSys.map_data.cells:
|
||||
var cell_data: MetroidvaniaSystem.MapData.CellData = MetSys.map_data.cells[coords]
|
||||
|
||||
if not MetSys.map_data.get_assigned_scene_at(coords):
|
||||
add_label(\"No assigned map at: %s\" % coords, WARNING)
|
||||
|
||||
var symbol := cell_data.get_symbol()
|
||||
if symbol >= map_theme.symbols.size():
|
||||
add_label(\"Invalid symbol (%d) at: %s\" % [symbol, coords], ERROR)
|
||||
else:
|
||||
unused_symbols.erase(symbol)
|
||||
|
||||
for i in 4:
|
||||
var border := cell_data.get_border(i)
|
||||
if map_theme.rectangle and border >= map_theme.vertical_borders.size() + 2:
|
||||
add_label(\"Invalid border (%d) at: %s\" % [border, coords], ERROR)
|
||||
elif not map_theme.rectangle and border >= map_theme.borders.size() + 2:
|
||||
add_label(\"Invalid border (%d) at: %s\" % [border, coords], ERROR)
|
||||
elif cell_data.get_border(i) != 0:
|
||||
var next: Vector3i = coords + Vector3i(MetroidvaniaSystem.MapData.FWD[i].x, MetroidvaniaSystem.MapData.FWD[i].y, 0)
|
||||
if not MetSys.map_data.get_cell_at(next):
|
||||
add_label(\"Passage to nowhere at: %s\" % coords, WARNING)
|
||||
|
||||
for symbol in unused_symbols:
|
||||
add_label(\"Potentially unused symbol: %d\" % symbol, WARNING)
|
||||
|
||||
if not has_error:
|
||||
add_label(\"Map data is valid.\", SUCCESS)
|
||||
|
||||
func validate_map_theme() -> void:
|
||||
dismiss()
|
||||
has_error = false
|
||||
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
|
||||
if map_theme.center_texture:
|
||||
add_label(\"Cell Shape: %s\" % (\"Rectangle\" if map_theme.rectangle else \"Square\"), INFO)
|
||||
add_label(\"Base Cell Size: %s\" % map_theme.center_texture.get_size(), INFO)
|
||||
else:
|
||||
add_label(\"Theme is missing center texture. Map can't be drawn.\", ERROR)
|
||||
return
|
||||
|
||||
if map_theme.is_unicorner():
|
||||
add_label(\"Uses unified corners.\", INFO)
|
||||
|
||||
if map_theme.empty_space_texture and map_theme.empty_space_texture.get_size() != map_theme.center_texture.get_size():
|
||||
add_label(\"Size mismatch between empty texture (%s) and center texture.\" % map_theme.empty_space_texture.get_size(), ERROR)
|
||||
|
||||
if map_theme.rectangle:
|
||||
if map_theme.vertical_borders.size() != map_theme.horizontal_borders.size():
|
||||
add_label(\"Number of horizontal and vertical borders do not match.\", ERROR)
|
||||
|
||||
check_vertical_border_texture(map_theme.vertical_wall, \"Vertical wall texture\")
|
||||
check_vertical_border_texture(map_theme.vertical_passage, \"Vertical passage texture\")
|
||||
|
||||
for i in map_theme.vertical_borders.size():
|
||||
var texture: Texture2D = map_theme.vertical_borders[i]
|
||||
check_vertical_border_texture(texture, \"Vertical border texture at index %d\" % i)
|
||||
|
||||
check_horizontal_border_texture(map_theme.horizontal_wall, \"Horizontal wall texture\")
|
||||
check_horizontal_border_texture(map_theme.horizontal_passage, \"Horizontal passage texture\")
|
||||
|
||||
for i in map_theme.horizontal_borders.size():
|
||||
var texture: Texture2D = map_theme.horizontal_borders[i]
|
||||
check_horizontal_border_texture(texture, \"Horizontal border texture at index %d\" % i)
|
||||
else:
|
||||
check_vertical_border_texture(map_theme.wall, \"Wall texture\")
|
||||
check_vertical_border_texture(map_theme.passage, \"Passage texture\")
|
||||
|
||||
for i in map_theme.borders.size():
|
||||
var texture: Texture2D = map_theme.borders[i]
|
||||
check_vertical_border_texture(texture, \"Border texture at index %d\" % i)
|
||||
|
||||
if map_theme.uncollected_item_symbol >= map_theme.symbols.size():
|
||||
add_label(\"Uncollected item symbol index is greater than number of available symbols.\", ERROR)
|
||||
|
||||
if map_theme.collected_item_symbol >= map_theme.symbols.size():
|
||||
add_label(\"Collected item symbol index is greater than number of available symbols.\", ERROR)
|
||||
|
||||
for i in map_theme.symbols.size():
|
||||
check_symbol_texture(map_theme.symbols[i], \"Symbol %d texture\" % i)
|
||||
if map_theme.use_shared_borders:
|
||||
check_corner_texture(map_theme.u_corner, \"U corner texture\")
|
||||
check_corner_texture(map_theme.l_corner, \"L corner texture\")
|
||||
check_corner_texture(map_theme.t_corner, \"T corner texture\")
|
||||
check_corner_texture(map_theme.cross_corner, \"Cross corner texture\")
|
||||
else:
|
||||
check_corner_texture(map_theme.inner_corner, \"Inner corner texture\")
|
||||
check_corner_texture(map_theme.outer_corner, \"Outer corner texture\")
|
||||
|
||||
if map_theme.player_location_scene:
|
||||
var test := map_theme.player_location_scene.instantiate()
|
||||
test.queue_free()
|
||||
if not test is Node2D:
|
||||
add_label(\"Player location scene is not a Node2D.\", ERROR)
|
||||
else:
|
||||
add_label(\"Missing player location scene. Player location can't be displayed using built-in methods.\", WARNING)
|
||||
|
||||
if not has_error:
|
||||
add_label(\"Theme is valid.\", SUCCESS)
|
||||
|
||||
func check_vertical_border_texture(texture: Texture2D, texture_name: String):
|
||||
if texture:
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
if texture.get_height() != map_theme.center_texture.get_height():
|
||||
add_label(\"%s has invalid height (%d). It should be vertical, oriented towards the right side and match the height of the center texture.\" % [texture_name, texture.get_height()], ERROR)
|
||||
elif texture.get_width() > map_theme.center_texture.get_width() / 2:
|
||||
add_label(\"%s is wider than half of the center texture. It may cause overlaps.\" % texture_name, WARNING)
|
||||
else:
|
||||
add_label(\"%s is empty.\" % texture_name, ERROR)
|
||||
|
||||
func check_horizontal_border_texture(texture: Texture2D, texture_name: String):
|
||||
if texture:
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
if texture.get_height() != map_theme.center_texture.get_width():
|
||||
add_label(\"%s has invalid height (%d). It should be vertical, oriented towards the right side and height should match the width of the center texture.\" % [texture_name, texture.get_height()], ERROR)
|
||||
elif texture.get_width() > map_theme.center_texture.get_height() / 2:
|
||||
add_label(\"%s is wider than half of the height of the center texture. It may cause overlaps.\" % texture_name, WARNING)
|
||||
else:
|
||||
add_label(\"%s is empty.\" % texture_name, ERROR)
|
||||
|
||||
func check_symbol_texture(texture: Texture2D, texture_name: String):
|
||||
if texture:
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
if texture.get_width() > map_theme.center_texture.get_width() or texture.get_height() > map_theme.center_texture.get_height():
|
||||
add_label(\"%s is bigger than center texture. It will stick out of cells.\" % texture_name, WARNING)
|
||||
else:
|
||||
add_label(\"%s is empty.\" % texture_name, ERROR)
|
||||
|
||||
func check_corner_texture(texture: Texture2D, texture_name: String):
|
||||
if texture:
|
||||
var map_theme: MapTheme = MetSys.settings.theme
|
||||
if texture.get_width() > map_theme.center_texture.get_width() / 2 or texture.get_height() > map_theme.center_texture.get_height() / 2:
|
||||
add_label(\"%s is bigger than half of the center texture. It may cause overlaps.\" % texture_name, WARNING)
|
||||
else:
|
||||
add_label(\"%s is empty.\" % texture_name, ERROR)
|
||||
|
||||
func add_label(text: String, type: int):
|
||||
show()
|
||||
|
||||
var label := Label.new()
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD
|
||||
label.text = \"• \" + text
|
||||
|
||||
match type:
|
||||
SUCCESS:
|
||||
label.modulate = success_color
|
||||
WARNING:
|
||||
label.modulate = warning_color
|
||||
ERROR:
|
||||
label.modulate = error_color
|
||||
has_error = true
|
||||
|
||||
%Output.add_child(label)
|
||||
|
||||
func dismiss() -> void:
|
||||
if not visible:
|
||||
return
|
||||
|
||||
for node in %Output.get_children():
|
||||
node.queue_free()
|
||||
hide()
|
||||
"
|
||||
|
||||
[node name="Manage" type="MarginContainer"]
|
||||
anchors_preset = 13
|
||||
anchor_left = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 1.0
|
||||
offset_left = -200.0
|
||||
offset_right = 200.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/margin_top = 32
|
||||
script = SubResource("GDScript_kxd0b")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
custom_minimum_size = Vector2(400, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "一般设置"
|
||||
|
||||
[node name="Button6" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "刷新默认元素"
|
||||
|
||||
[node name="Button2" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "重新加载并清理地图数据"
|
||||
|
||||
[node name="HSeparator3" type="HSeparator" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button4" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "校验地图数据"
|
||||
|
||||
[node name="Button5" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "校验地图主题"
|
||||
|
||||
[node name="Button7" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "导出地图数据为JSON"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Button3" type="Button" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "编辑数据库主题"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AllowReset" type="CheckBox" parent="VBoxContainer/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ResetButton" type="Button" parent="VBoxContainer/VBoxContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
disabled = true
|
||||
text = "重置数据库主题"
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="VBoxContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ValidationPanel" type="PanelContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_6lvlf")
|
||||
script = SubResource("GDScript_x20sf")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/ValidationPanel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/ValidationPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "校验结果"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer/ValidationPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Output" type="VBoxContainer" parent="VBoxContainer/ValidationPanel/VBoxContainer/ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer/ValidationPanel/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "关闭"
|
||||
|
||||
[node name="FileDialog" type="FileDialog" parent="."]
|
||||
size = Vector2i(483, 162)
|
||||
access = 2
|
||||
filters = PackedStringArray("*.json")
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button" to="." method="edit_settings_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button6" to="." method="refresh_custom_elements"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button2" to="." method="force_reload"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button4" to="VBoxContainer/ValidationPanel" method="validate_map_data"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button5" to="VBoxContainer/ValidationPanel" method="validate_map_theme"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button7" to="." method="export_json"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/Button3" to="." method="edit_database_theme"]
|
||||
[connection signal="toggled" from="VBoxContainer/VBoxContainer/HBoxContainer/AllowReset" to="." method="toggle_allow_reset"]
|
||||
[connection signal="pressed" from="VBoxContainer/VBoxContainer/HBoxContainer/ResetButton" to="." method="reset_theme"]
|
||||
[connection signal="pressed" from="VBoxContainer/ValidationPanel/VBoxContainer/Button" to="VBoxContainer/ValidationPanel" method="dismiss"]
|
||||
[connection signal="file_selected" from="FileDialog" to="." method="json_file_selected"]
|
||||
@ -1,91 +0,0 @@
|
||||
@tool
|
||||
extends "res://addons/MetroidvaniaSystem/Scripts/MapView.gd"
|
||||
|
||||
@onready var ghost_map: Control = %GhostMap
|
||||
@onready var grid: Control = %Grid
|
||||
|
||||
@export var mode_group: ButtonGroup
|
||||
|
||||
var mode: int
|
||||
var preview_layer := -1
|
||||
var modified: bool
|
||||
|
||||
func _ready() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
plugin.dirty_toggled.connect(update_name)
|
||||
await super()
|
||||
|
||||
mode_group.pressed.connect(mode_pressed)
|
||||
get_current_sub_editor()._editor_enter()
|
||||
MetSys.settings.theme_changed.connect(grid.queue_redraw)
|
||||
map_overlay.mouse_entered.connect(map_overlay.grab_focus)
|
||||
|
||||
func mode_pressed(button: BaseButton):
|
||||
get_current_sub_editor()._editor_exit()
|
||||
mode = button.get_index() - 1
|
||||
get_current_sub_editor()._editor_enter()
|
||||
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
func on_layer_changed(l: int):
|
||||
super(l)
|
||||
ghost_map.queue_redraw()
|
||||
|
||||
func preview_layer_changed(value: float) -> void:
|
||||
preview_layer = value
|
||||
ghost_map.queue_redraw()
|
||||
|
||||
func get_current_sub_editor() -> Control:
|
||||
return mode_group.get_buttons()[mode]
|
||||
|
||||
func _on_overlay_input(event: InputEvent) -> void:
|
||||
super(event)
|
||||
get_current_sub_editor()._editor_input(event)
|
||||
|
||||
func _on_drag():
|
||||
ghost_map.queue_redraw()
|
||||
|
||||
func _on_overlay_draw() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
super()
|
||||
map_overlay.draw_set_transform(Vector2(map_offset) * MetSys.CELL_SIZE)
|
||||
|
||||
var sub := get_current_sub_editor()
|
||||
sub.top_draw = Callable()
|
||||
sub._editor_draw(map_overlay)
|
||||
|
||||
if sub.top_draw.is_valid():
|
||||
sub.top_draw.call(map_overlay)
|
||||
|
||||
func _on_ghost_map_draw() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
if preview_layer == -1 or preview_layer == current_layer:
|
||||
return
|
||||
|
||||
for x in range(-100, 100):
|
||||
for y in range(-100, 100):
|
||||
MetSys.draw_cell(ghost_map, Vector2i(x, y) + map_offset, Vector3i(x, y, preview_layer))
|
||||
|
||||
func _on_grid_draw() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
var empty_texture: Texture2D = MetSys.settings.theme.empty_space_texture
|
||||
for x in ceili(grid.size.x / MetSys.CELL_SIZE.x):
|
||||
for y in ceili(grid.size.y / MetSys.CELL_SIZE.y):
|
||||
if empty_texture:
|
||||
grid.draw_texture(empty_texture, Vector2(x, y) * MetSys.CELL_SIZE)
|
||||
else:
|
||||
grid.draw_rect(Rect2(Vector2(x, y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), Color(Color.WHITE, 0.1), false)
|
||||
|
||||
func update_name(dirty: bool):
|
||||
if dirty:
|
||||
name = "Map Editor (*)"
|
||||
else:
|
||||
name = "Map Editor"
|
||||
@ -1,868 +0,0 @@
|
||||
[gd_scene load_steps=13 format=3 uid="uid://dfbykrvyqnqr5"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Database/MapEditor.gd" id="1_i7yda"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Database/MapOverlay.gd" id="2_w1wnt"]
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_pv7fp"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_dsps8"]
|
||||
resource_name = "RoomLayout"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/SubEditor.gd\"
|
||||
|
||||
var erase_mode: bool
|
||||
|
||||
func _editor_init() -> void:
|
||||
room_only_cursor = false
|
||||
|
||||
func _update_theme():
|
||||
theme_cache.cursor_color = get_theme_color(&\"cursor_color\", &\"MetSys\")
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
drag_from = get_cursor_pos()
|
||||
else:
|
||||
var rect := get_rect_between(drag_from, get_cursor_pos())
|
||||
update_rooms(rect)
|
||||
drag_from = EDITOR_SCRIPT.NULL_VECTOR2I
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
if event.pressed:
|
||||
drag_from = get_cursor_pos()
|
||||
erase_mode = true
|
||||
theme_cache.cursor_color = get_theme_color(&\"cursor_color_erase\", &\"MetSys\")
|
||||
queue_redraw()
|
||||
else:
|
||||
var rect := get_rect_between(drag_from, get_cursor_pos())
|
||||
erase_rooms(rect)
|
||||
erase_mode = false
|
||||
theme_cache.cursor_color = get_theme_color(&\"cursor_color\", &\"MetSys\")
|
||||
drag_from = EDITOR_SCRIPT.NULL_VECTOR2I
|
||||
|
||||
func update_rooms(rect: Rect2i):
|
||||
var map_data: MetroidvaniaSystem.MapData = MetSys.map_data
|
||||
|
||||
for x in range(rect.position.x, rect.end.x):
|
||||
for y in range(rect.position.y, rect.end.y):
|
||||
var coords := Vector3i(x, y, editor.current_layer)
|
||||
|
||||
var cell = map_data.get_cell_at(coords)
|
||||
if cell:
|
||||
remove_assign(coords)
|
||||
|
||||
if x != rect.end.x - 1:
|
||||
cell.borders[0] = -1
|
||||
if y != rect.end.y - 1:
|
||||
cell.borders[1] = -1
|
||||
if x != rect.position.x:
|
||||
cell.borders[2] = -1
|
||||
if y != rect.position.y:
|
||||
cell.borders[3] = -1
|
||||
else:
|
||||
cell = map_data.create_cell_at(coords)
|
||||
if x == rect.end.x - 1:
|
||||
cell.borders[0] = 0
|
||||
if y == rect.end.y - 1:
|
||||
cell.borders[1] = 0
|
||||
if x == rect.position.x:
|
||||
cell.borders[2] = 0
|
||||
if y == rect.position.y:
|
||||
cell.borders[3] = 0
|
||||
|
||||
mark_modified()
|
||||
editor.map.queue_redraw()
|
||||
|
||||
func erase_rooms(rect: Rect2i):
|
||||
var map_data: MetroidvaniaSystem.MapData = MetSys.map_data
|
||||
|
||||
for x in range(rect.position.x, rect.end.x):
|
||||
for y in range(rect.position.y, rect.end.y):
|
||||
var coords := Vector3i(x, y, editor.current_layer)
|
||||
var cell_data := map_data.get_cell_at(coords)
|
||||
|
||||
if not cell_data:
|
||||
continue
|
||||
|
||||
if x == rect.end.x - 1:
|
||||
close_border(Vector2i(x + 1, y), 2)
|
||||
if y == rect.end.y - 1:
|
||||
close_border(Vector2i(x, y + 1), 3)
|
||||
if x == rect.position.x:
|
||||
close_border(Vector2i(x - 1, y), 0)
|
||||
if y == rect.position.y:
|
||||
close_border(Vector2i(x, y - 1), 1)
|
||||
|
||||
map_data.erase_cell(coords)
|
||||
|
||||
mark_modified()
|
||||
editor.map.queue_redraw()
|
||||
|
||||
func remove_assign(coords: Vector3i):
|
||||
var assigned_scene: String = MetSys.map_data.cells[coords].assigned_scene
|
||||
MetSys.map_data.assigned_scenes.erase(assigned_scene)
|
||||
|
||||
func close_border(pos: Vector2i, border: int):
|
||||
var cell: MetroidvaniaSystem.MapData.CellData = MetSys.map_data.get_cell_at(get_coords(pos))
|
||||
|
||||
if cell:
|
||||
cell.borders[border] = 0
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_tlx5u"]
|
||||
resource_name = "CellColor"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/CellPaintEditor.gd\"
|
||||
|
||||
func _editor_init() -> void:
|
||||
super()
|
||||
can_pick = true
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Colors.show()
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Colors.hide()
|
||||
|
||||
func modify_cell(cell_data: MetroidvaniaSystem.MapData.CellData, mode: int) -> bool:
|
||||
if mode == MODE_PICK:
|
||||
if cell_data.color.a > 0:
|
||||
%CurrentColor.color = cell_data.color
|
||||
else:
|
||||
var target_color := Color.TRANSPARENT
|
||||
if mode == MODE_DRAW:
|
||||
target_color = %CurrentColor.color
|
||||
|
||||
if cell_data.color != target_color:
|
||||
cell_data.color = target_color
|
||||
return true
|
||||
|
||||
return false
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_ujwfx"]
|
||||
resource_name = "CellSymbol"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/CellPaintEditor.gd\"
|
||||
|
||||
var symbol_group: ButtonGroup
|
||||
|
||||
func _editor_init() -> void:
|
||||
can_pick = true
|
||||
super()
|
||||
|
||||
symbol_group = ButtonGroup.new()
|
||||
reload_symbols()
|
||||
MetSys.settings.theme_changed.connect(reload_symbols)
|
||||
MetSys.theme_modified.connect(func(changes: Array[String]):
|
||||
if \"symbols\" in changes:
|
||||
reload_symbols())
|
||||
|
||||
func reload_symbols():
|
||||
for symbol in %SymbolContainer.get_children():
|
||||
symbol.free()
|
||||
|
||||
for symbol in MetSys.settings.theme.symbols:
|
||||
add_symbol(symbol)
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Symbols.show()
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Symbols.hide()
|
||||
|
||||
func modify_cell(cell_data: MetroidvaniaSystem.MapData.CellData, mode: int) -> bool:
|
||||
if mode == MODE_PICK:
|
||||
if cell_data.symbol > -1:
|
||||
symbol_group.get_buttons()[cell_data.symbol].button_pressed = true
|
||||
return false
|
||||
|
||||
var target_symbol := -1
|
||||
if mode == MODE_DRAW:
|
||||
target_symbol = symbol_group.get_pressed_button().get_index()
|
||||
|
||||
if cell_data.symbol != target_symbol:
|
||||
cell_data.symbol = target_symbol
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func add_symbol(texture: Texture2D):
|
||||
var button := Button.new()
|
||||
button.icon = texture
|
||||
button.toggle_mode = true
|
||||
button.button_group = symbol_group
|
||||
|
||||
if not symbol_group.get_pressed_button():
|
||||
button.button_pressed = true
|
||||
|
||||
%SymbolContainer.add_child(button)
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_a80ln"]
|
||||
resource_name = "CellGroup"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/CellPaintEditor.gd\"
|
||||
|
||||
var cell_groups: Dictionary
|
||||
var drawing: int
|
||||
|
||||
func _editor_init() -> void:
|
||||
super()
|
||||
room_only_cursor = true
|
||||
cell_groups = MetSys.map_data.cell_groups
|
||||
|
||||
func _update_theme():
|
||||
theme_cache.group_color = get_theme_color(&\"group_color\", &\"MetSys\")
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Groups.show()
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Groups.hide()
|
||||
|
||||
func _editor_draw(map_overlay: CanvasItem):
|
||||
super(map_overlay)
|
||||
|
||||
for p in cell_groups.get(%CurrentGroup.value as int, []):
|
||||
map_overlay.draw_rect(Rect2(Vector2(p.x, p.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.group_color)
|
||||
|
||||
func modify_coords(coords: Vector3i, mode: int) -> bool:
|
||||
var current_group: int = %CurrentGroup.value
|
||||
|
||||
if mode == MODE_DRAW:
|
||||
if not current_group in cell_groups:
|
||||
cell_groups[current_group] = []
|
||||
|
||||
if not coords in cell_groups[current_group]:
|
||||
cell_groups[current_group].append(coords)
|
||||
return true
|
||||
else:
|
||||
if coords in cell_groups[current_group]:
|
||||
cell_groups[current_group].erase(coords)
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func draw_group():
|
||||
if drawing == 0:
|
||||
return
|
||||
|
||||
var coords := get_coords(get_cursor_pos())
|
||||
var current_group: int = %CurrentGroup.value
|
||||
|
||||
if drawing & MOUSE_BUTTON_MASK_LEFT != 0:
|
||||
var cell_data: MetroidvaniaSystem.MapData.CellData = MetSys.map_data.get_cell_at(coords)
|
||||
if not cell_data:
|
||||
return
|
||||
|
||||
if not current_group in cell_groups:
|
||||
cell_groups[current_group] = []
|
||||
|
||||
if not coords in cell_groups[current_group]:
|
||||
cell_groups[current_group].append(coords)
|
||||
|
||||
mark_modified()
|
||||
editor.map_overlay.queue_redraw()
|
||||
elif drawing & MOUSE_BUTTON_MASK_RIGHT != 0:
|
||||
if not current_group in cell_groups:
|
||||
return
|
||||
|
||||
var cell_data: MetroidvaniaSystem.MapData.CellData = MetSys.map_data.get_cell_at(coords)
|
||||
if not cell_data:
|
||||
return
|
||||
|
||||
cell_groups[current_group].erase(coords)
|
||||
mark_modified()
|
||||
editor.map_overlay.queue_redraw()
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_ilxbw"]
|
||||
resource_name = "BorderType"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/BorderPaintEditor.gd\"
|
||||
|
||||
var border_group: ButtonGroup
|
||||
|
||||
func _editor_init() -> void:
|
||||
use_cursor = false
|
||||
can_pick = true
|
||||
super()
|
||||
border_group = ButtonGroup.new()
|
||||
|
||||
reload_borders()
|
||||
MetSys.settings.theme_changed.connect(reload_borders)
|
||||
MetSys.theme_modified.connect(func(changes: Array[String]):
|
||||
if \"borders\" in changes or \"vertical_borders\" or \"vertical_borders\" in changes:
|
||||
reload_borders())
|
||||
|
||||
func reload_borders():
|
||||
for symbol in %BorderContainer.get_children():
|
||||
symbol.free()
|
||||
|
||||
if MetSys.settings.theme.rectangle:
|
||||
add_border(MetSys.settings.theme.vertical_wall)
|
||||
add_border(MetSys.settings.theme.vertical_passage)
|
||||
|
||||
for border in MetSys.settings.theme.vertical_borders:
|
||||
add_border(border)
|
||||
else:
|
||||
add_border(MetSys.settings.theme.wall)
|
||||
add_border(MetSys.settings.theme.passage)
|
||||
|
||||
for border in MetSys.settings.theme.borders:
|
||||
add_border(border)
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Borders.show()
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Borders.hide()
|
||||
|
||||
func modify_border(cell_data: MetroidvaniaSystem.MapData.CellData, border: int, mode: int) -> bool:
|
||||
if cell_data.borders[border] == -1:
|
||||
return false
|
||||
|
||||
if mode == MODE_PICK:
|
||||
border_group.get_buttons()[cell_data.borders[border]].button_pressed = true
|
||||
else:
|
||||
var target_border := 0
|
||||
if mode == MODE_DRAW:
|
||||
target_border = border_group.get_pressed_button().get_index()
|
||||
|
||||
if cell_data.borders[border] != target_border:
|
||||
cell_data.borders[border] = target_border
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
func add_border(texture: Texture2D):
|
||||
var button := Button.new()
|
||||
button.icon = texture
|
||||
button.toggle_mode = true
|
||||
button.button_group = border_group
|
||||
button.custom_minimum_size.x = MetSys.CELL_SIZE.x
|
||||
button.icon_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
|
||||
if not border_group.get_pressed_button():
|
||||
button.button_pressed = true
|
||||
|
||||
%BorderContainer.add_child(button)
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_a3fsx"]
|
||||
resource_name = "BorderColor"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/BorderPaintEditor.gd\"
|
||||
|
||||
func _editor_init():
|
||||
can_pick = true
|
||||
super()
|
||||
|
||||
func _editor_enter():
|
||||
super()
|
||||
%Colors.show()
|
||||
|
||||
func _editor_exit():
|
||||
super()
|
||||
%Colors.hide()
|
||||
|
||||
func modify_border(cell_data: MetroidvaniaSystem.MapData.CellData, border: int, mode: int) -> bool:
|
||||
if cell_data.borders[border] == -1:
|
||||
return false
|
||||
|
||||
if mode == MODE_PICK:
|
||||
if cell_data.border_colors[border].a > 0:
|
||||
%CurrentColor.color = cell_data.border_colors[border]
|
||||
else:
|
||||
var target_color := Color.TRANSPARENT
|
||||
if mode == MODE_DRAW:
|
||||
target_color = %CurrentColor.color
|
||||
|
||||
if cell_data.border_colors[border] != target_color:
|
||||
cell_data.border_colors[border] = target_color
|
||||
return true
|
||||
|
||||
return false
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_p75ne"]
|
||||
resource_name = "SceneAssign"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/SubEditor.gd\"
|
||||
|
||||
func _editor_init() -> void:
|
||||
use_cursor = false
|
||||
|
||||
func _update_theme():
|
||||
theme_cache.assigned_scene = get_theme_color(&\"assigned_scene\", &\"MetSys\")
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
if event is InputEventMouseMotion:
|
||||
var hr := highlighted_room
|
||||
highlighted_room = MetSys.map_data.get_whole_room(get_coords(get_cursor_pos()))
|
||||
if highlighted_room != hr:
|
||||
editor.map_overlay.queue_redraw()
|
||||
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
if not highlighted_room.is_empty():
|
||||
if %FileDialog.root_subfolder.is_empty():
|
||||
%FileDialog.root_subfolder = MetSys.settings.map_root_folder.trim_prefix(\"res://\")
|
||||
%FileDialog.popup_centered_ratio(0.6)
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
var first := true
|
||||
for p in highlighted_room:
|
||||
if first:
|
||||
var assigned_scene: String = MetSys.map_data.get_cell_at(p).assigned_scene
|
||||
MetSys.map_data.assigned_scenes.erase(assigned_scene)
|
||||
first = false
|
||||
|
||||
MetSys.map_data.get_cell_at(p).assigned_scene = \"\"
|
||||
MetSys.room_assign_updated.emit()
|
||||
|
||||
mark_modified()
|
||||
editor.map_overlay.queue_redraw()
|
||||
|
||||
func _editor_draw(map_overlay: CanvasItem):
|
||||
super(map_overlay)
|
||||
|
||||
for coords in MetSys.map_data.assigned_scenes.values():
|
||||
if coords[0].z != editor.current_layer:
|
||||
continue
|
||||
|
||||
for p in coords:
|
||||
map_overlay.draw_rect(Rect2(Vector2(p.x, p.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.assigned_scene)
|
||||
|
||||
if not highlighted_room.is_empty():
|
||||
map_overlay.draw_set_transform_matrix(Transform2D())
|
||||
map_overlay.draw_string(get_theme_font(&\"font\", &\"Label\"), Vector2(0, 40),
|
||||
MetSys.map_data.get_cell_at(highlighted_room.front()).assigned_scene)
|
||||
|
||||
func on_map_selected(path: String) -> void:
|
||||
path = path.trim_prefix(MetSys.settings.map_root_folder)
|
||||
|
||||
MetSys.map_data.assigned_scenes[path] = []
|
||||
for coords in highlighted_room:
|
||||
MetSys.map_data.get_cell_at(coords).assigned_scene = path
|
||||
MetSys.map_data.assigned_scenes[path].append(coords)
|
||||
MetSys.room_assign_updated.emit()
|
||||
|
||||
mark_modified()
|
||||
editor.map_overlay.queue_redraw()
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_gb3rf"]
|
||||
resource_name = "CustomElements"
|
||||
script/source = "@tool
|
||||
extends \"res://addons/MetroidvaniaSystem/Database/SubEditor.gd\"
|
||||
|
||||
var current_element: String
|
||||
var custom_elements: Dictionary
|
||||
|
||||
func _editor_init() -> void:
|
||||
room_only_cursor = false
|
||||
custom_elements = MetSys.map_data.custom_elements
|
||||
MetSys.settings.custom_elements_changed.connect(reload_custom_elements)
|
||||
|
||||
reload_custom_elements()
|
||||
|
||||
func _update_theme():
|
||||
theme_cache.active_custom_element = get_theme_color(&\"active_custom_element\", &\"MetSys\")
|
||||
theme_cache.inactive_custom_element = get_theme_color(&\"inactive_custom_element\", &\"MetSys\")
|
||||
theme_cache.custom_element_marker = get_theme_color(&\"custom_element_marker\", &\"MetSys\")
|
||||
|
||||
func reload_custom_elements():
|
||||
for element in %CustomElementContainer.get_children():
|
||||
element.queue_free()
|
||||
current_element = \"\"
|
||||
|
||||
if not MetSys.settings.custom_elements or MetSys.settings.custom_elements.custom_elements.is_empty():
|
||||
%NoElements.show()
|
||||
return
|
||||
else:
|
||||
%NoElements.hide()
|
||||
|
||||
var element_group := ButtonGroup.new()
|
||||
|
||||
for element in MetSys.settings.custom_elements.custom_elements:
|
||||
var button := CheckBox.new()
|
||||
button.text = str(element).capitalize()
|
||||
button.button_group = element_group
|
||||
button.pressed.connect(set_current_element.bind(element))
|
||||
%CustomElementContainer.add_child(button)
|
||||
|
||||
if not element_group.get_pressed_button():
|
||||
button.button_pressed = true
|
||||
set_current_element(element)
|
||||
|
||||
func _editor_enter():
|
||||
%CustomElements.show()
|
||||
|
||||
func _editor_exit():
|
||||
%CustomElements.hide()
|
||||
|
||||
func set_current_element(element: String):
|
||||
current_element = element
|
||||
editor.map_overlay.queue_redraw()
|
||||
|
||||
func _editor_draw(map_overlay: CanvasItem):
|
||||
super(map_overlay)
|
||||
|
||||
for coords in custom_elements:
|
||||
if coords.z != editor.current_layer:
|
||||
continue
|
||||
|
||||
var element_color: Color
|
||||
var element: Dictionary = custom_elements[coords]
|
||||
if element.name == current_element:
|
||||
element_color = theme_cache.active_custom_element
|
||||
else:
|
||||
element_color = theme_cache.inactive_custom_element
|
||||
|
||||
map_overlay.draw_rect(Rect2(Vector2(coords.x, coords.y) * MetSys.CELL_SIZE, Vector2(element.size) * MetSys.CELL_SIZE), element_color)
|
||||
|
||||
var square := minf(MetSys.CELL_SIZE.x, MetSys.CELL_SIZE.y)
|
||||
map_overlay.draw_rect(Rect2((Vector2(coords.x, coords.y) + Vector2(0.5, 0.5)) * MetSys.CELL_SIZE - Vector2.ONE * square * 0.5, Vector2.ONE * square).grow(-square * 0.2), theme_cache.custom_element_marker)
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed:
|
||||
drag_from = get_cursor_pos()
|
||||
else:
|
||||
var rect := get_rect_between(drag_from, get_cursor_pos())
|
||||
add_element(rect)
|
||||
mark_modified()
|
||||
drag_from = EDITOR_SCRIPT.NULL_VECTOR2I
|
||||
elif event.button_index == MOUSE_BUTTON_RIGHT:
|
||||
if event.pressed:
|
||||
var coords := Vector3i(get_cursor_pos().x, get_cursor_pos().y, editor.current_layer)
|
||||
if coords in MetSys.map_data.custom_elements:
|
||||
MetSys.map_data.custom_elements.erase(coords)
|
||||
mark_modified()
|
||||
editor.map.queue_redraw()
|
||||
|
||||
func add_element(rect: Rect2i):
|
||||
var element: Dictionary
|
||||
element.name = current_element
|
||||
element.size = rect.size
|
||||
element.data = %CustomData.text
|
||||
|
||||
var coords := Vector3i(rect.position.x, rect.position.y, editor.current_layer)
|
||||
MetSys.map_data.custom_elements[coords] = element
|
||||
editor.map.queue_redraw()
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_xiyo8"]
|
||||
content_margin_left = 4.0
|
||||
content_margin_right = 4.0
|
||||
bg_color = Color(0, 0, 0, 0.501961)
|
||||
|
||||
[node name="MapEditor" type="HBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_i7yda")
|
||||
mode_group = SubResource("ButtonGroup_pv7fp")
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="PanelContainer" type="PanelContainer" parent="."]
|
||||
custom_minimum_size = Vector2(200, 0)
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="PanelContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Layer" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/Layer"]
|
||||
layout_mode = 2
|
||||
text = "当前层"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="CurrentLayer" type="SpinBox" parent="PanelContainer/ScrollContainer/VBoxContainer/Layer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="Label2" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/Layer"]
|
||||
layout_mode = 2
|
||||
text = "预览层"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="SpinBox2" type="SpinBox" parent="PanelContainer/ScrollContainer/VBoxContainer/Layer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
min_value = -1.0
|
||||
value = -1.0
|
||||
|
||||
[node name="RecenterButton" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Layer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "重置相机"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="PanelContainer/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Modes" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
text = "模式"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="RoomLayout" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "房间布局"
|
||||
script = SubResource("GDScript_dsps8")
|
||||
|
||||
[node name="CellColor" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "地块颜色"
|
||||
script = SubResource("GDScript_tlx5u")
|
||||
|
||||
[node name="CellSymbol" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "地块符号"
|
||||
script = SubResource("GDScript_ujwfx")
|
||||
|
||||
[node name="CellGroup" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "地块组"
|
||||
script = SubResource("GDScript_a80ln")
|
||||
|
||||
[node name="BorderType" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "边缘类型"
|
||||
script = SubResource("GDScript_ilxbw")
|
||||
|
||||
[node name="BorderColor" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "边缘颜色"
|
||||
script = SubResource("GDScript_a3fsx")
|
||||
|
||||
[node name="SceneAssign" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "场景分配"
|
||||
script = SubResource("GDScript_p75ne")
|
||||
|
||||
[node name="CustomElements" type="Button" parent="PanelContainer/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_pv7fp")
|
||||
text = "自定义元素"
|
||||
script = SubResource("GDScript_gb3rf")
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="PanelContainer/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="EditControls" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 0
|
||||
mouse_filter = 2
|
||||
alignment = 2
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="Symbols" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="SymbolContainer" type="HFlowContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Symbols"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Borders" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="BorderContainer" type="HFlowContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Borders"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Groups" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Groups"]
|
||||
layout_mode = 2
|
||||
text = "Group ID"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="CurrentGroup" type="SpinBox" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Groups"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Colors" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="CurrentColor" type="ColorPickerButton" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Colors"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(0, 30)
|
||||
layout_mode = 2
|
||||
edit_alpha = false
|
||||
|
||||
[node name="CustomElements" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/CustomElements"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/CustomElements/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Data"
|
||||
|
||||
[node name="CustomData" type="LineEdit" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/CustomElements/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="NoElements" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/CustomElements"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "No Custom Elements Registered"
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="CustomElementContainer" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/CustomElements"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Shortcuts" type="VBoxContainer" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ShortcutPick" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Shortcuts"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Ctrl+Click: 从地图拾取"
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="Label2" type="Label" parent="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Shortcuts"]
|
||||
layout_mode = 2
|
||||
text = "Shift+Click: 为整个房间设置"
|
||||
autowrap_mode = 2
|
||||
|
||||
[node name="MapOverlay" type="Control" parent="."]
|
||||
texture_filter = 1
|
||||
clip_contents = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
focus_mode = 2
|
||||
script = ExtResource("2_w1wnt")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="MapOverlay"]
|
||||
modulate = Color(0, 0, 0, 0.12549)
|
||||
show_behind_parent = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Grid" type="Control" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
show_behind_parent = true
|
||||
clip_contents = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Map" type="Control" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
show_behind_parent = true
|
||||
clip_contents = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="GhostMap" type="Control" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
modulate = Color(1, 1, 1, 0.12549)
|
||||
show_behind_parent = true
|
||||
clip_contents = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_right = 1.0
|
||||
offset_bottom = 23.0
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_xiyo8")
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="FileDialog" type="FileDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
title = "Open a File"
|
||||
size = Vector2i(345, 162)
|
||||
ok_button_text = "打开"
|
||||
file_mode = 0
|
||||
filters = PackedStringArray("*.tscn")
|
||||
|
||||
[connection signal="value_changed" from="PanelContainer/ScrollContainer/VBoxContainer/Layer/SpinBox2" to="." method="preview_layer_changed"]
|
||||
[connection signal="value_changed" from="PanelContainer/ScrollContainer/VBoxContainer/EditControls/Groups/CurrentGroup" to="MapOverlay" method="queue_redraw" unbinds=1]
|
||||
[connection signal="draw" from="MapOverlay/Grid" to="." method="_on_grid_draw"]
|
||||
[connection signal="draw" from="MapOverlay/GhostMap" to="." method="_on_ghost_map_draw"]
|
||||
[connection signal="file_selected" from="FileDialog" to="PanelContainer/ScrollContainer/VBoxContainer/Modes/SceneAssign" method="on_map_selected"]
|
||||
@ -1,12 +0,0 @@
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
var cursor_inside: bool
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_MOUSE_ENTER:
|
||||
cursor_inside = true
|
||||
queue_redraw()
|
||||
elif what == NOTIFICATION_MOUSE_EXIT:
|
||||
cursor_inside = false
|
||||
queue_redraw()
|
||||
@ -1,101 +0,0 @@
|
||||
@tool
|
||||
extends "res://addons/MetroidvaniaSystem/Scripts/MapView.gd"
|
||||
|
||||
enum {MODE_LAYOUT = 1, MODE_ROOM_SYMBOL, MODE_ROOM_COLOR, MODE_ROOM_GROUP, MODE_BORDER_TYPE, MODE_BORDER_COLOR, MODE_MAP}
|
||||
|
||||
@export var mode_group: ButtonGroup
|
||||
|
||||
var theme_cache: Dictionary
|
||||
|
||||
var room_under_cursor: MetroidvaniaSystem.MapData.CellData
|
||||
var current_hovered_item: Control
|
||||
var extra_draw: Callable
|
||||
|
||||
func _ready() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
super()
|
||||
|
||||
plugin.scene_changed.connect(map_overlay.queue_redraw.unbind(1))
|
||||
MetSys.map_updated.connect(map.queue_redraw)
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
theme_cache.marked_collectible_room = get_theme_color(&"marked_collectible_room", &"MetSys")
|
||||
theme_cache.foreign_marked_collectible_room = get_theme_color(&"foreign_marked_collectible_room", &"MetSys")
|
||||
theme_cache.current_scene_room = get_theme_color(&"current_scene_room", &"MetSys")
|
||||
theme_cache.cursor_color = get_theme_color(&"cursor_color", &"MetSys")
|
||||
theme_cache.room_not_assigned = get_theme_color(&"room_not_assigned", &"MetSys")
|
||||
theme_cache.room_assigned = get_theme_color(&"room_assigned", &"MetSys")
|
||||
|
||||
func _on_item_hover(item: Control):
|
||||
item.mouse_exited.connect(_on_item_unhover.bind(item))
|
||||
current_hovered_item = item
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
func _on_item_unhover(item: Control):
|
||||
item.mouse_exited.disconnect(_on_item_unhover)
|
||||
if item == current_hovered_item:
|
||||
current_hovered_item = null
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
func _update_status_label():
|
||||
status_label.show()
|
||||
status_label.modulate = Color.WHITE
|
||||
if room_under_cursor and not room_under_cursor.assigned_scene.is_empty():
|
||||
status_label.text = str(get_cursor_pos(), " ", room_under_cursor.assigned_scene)
|
||||
else:
|
||||
if room_under_cursor:
|
||||
status_label.modulate = Color.RED
|
||||
status_label.text = str(get_cursor_pos())
|
||||
|
||||
func _on_overlay_input(event: InputEvent) -> void:
|
||||
super(event)
|
||||
|
||||
if event is InputEventMouseMotion:
|
||||
var cursor := get_cursor_pos()
|
||||
room_under_cursor = MetSys.map_data.get_cell_at(Vector3i(cursor.x, cursor.y, current_layer))
|
||||
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_LEFT:
|
||||
if event.pressed and room_under_cursor and not room_under_cursor.assigned_scene.is_empty():
|
||||
plugin.get_editor_interface().open_scene_from_path(MetSys.settings.map_root_folder.path_join(room_under_cursor.assigned_scene))
|
||||
|
||||
func _on_overlay_draw() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
super()
|
||||
var mouse := get_cursor_pos()
|
||||
|
||||
if map_overlay.cursor_inside:
|
||||
map_overlay.draw_rect(Rect2(Vector2(mouse + map_offset) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.cursor_color, false, 2)
|
||||
|
||||
if get_tree().edited_scene_root and get_tree().edited_scene_root.scene_file_path.begins_with(MetSys.settings.map_root_folder):
|
||||
var current_scene := get_tree().edited_scene_root.scene_file_path.trim_prefix(MetSys.settings.map_root_folder)
|
||||
|
||||
for coords in MetSys.map_data.get_cells_assigned_to(current_scene):
|
||||
if coords.z != current_layer:
|
||||
break
|
||||
|
||||
map_overlay.draw_rect(Rect2(Vector2(coords.x + map_offset.x, coords.y + map_offset.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.current_scene_room)
|
||||
|
||||
if current_hovered_item:
|
||||
var data: Dictionary = current_hovered_item.get_meta(&"data")
|
||||
if "coords" in data:
|
||||
var coords: Vector3i = data.coords
|
||||
map_overlay.draw_rect(Rect2(Vector2(coords.x + map_offset.x, coords.y + map_offset.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.marked_collectible_room if coords.z == current_layer else theme_cache.foreign_marked_collectible_room)
|
||||
else:
|
||||
for coords in MetSys.map_data.get_cells_assigned_to(data.map):
|
||||
if coords.z != current_layer:
|
||||
break
|
||||
|
||||
map_overlay.draw_rect(Rect2(Vector2(coords.x + map_offset.x, coords.y + map_offset.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.marked_collectible_room)
|
||||
break
|
||||
|
||||
if extra_draw.is_valid():
|
||||
extra_draw.call(map_overlay)
|
||||
|
||||
func toggle_mapped(toggled_on: bool) -> void:
|
||||
force_mapped = toggled_on
|
||||
map.queue_redraw()
|
||||
@ -1,417 +0,0 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://df5fuj4vjr11p"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Database/MapViewer.gd" id="1_s16ok"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Database/MapOverlay.gd" id="2_pgyha"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/EditorIconButton.gd" id="2_tjngl"]
|
||||
|
||||
[sub_resource type="ButtonGroup" id="ButtonGroup_lmh17"]
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_fjyy3"]
|
||||
resource_name = "Settings"
|
||||
script/source = "@tool
|
||||
extends Button
|
||||
|
||||
var plugin: EditorPlugin
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if owner:
|
||||
plugin = owner.plugin
|
||||
|
||||
func _ready() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
_pressed()
|
||||
|
||||
await get_tree().process_frame
|
||||
for data in MetSys.settings.collectible_list:
|
||||
var collectible := add_collectible()
|
||||
collectible.set_data(data)
|
||||
|
||||
func _pressed() -> void:
|
||||
for button in button_group.get_buttons():
|
||||
button.exit()
|
||||
|
||||
%Settings.show()
|
||||
|
||||
func exit():
|
||||
%Settings.hide()
|
||||
|
||||
func add_collectible() -> Control:
|
||||
var collectible := preload(\"res://addons/MetroidvaniaSystem/Nodes/CollectibleElement.tscn\").instantiate()
|
||||
%CollectibleList.add_child(collectible)
|
||||
collectible.save_request.connect(save_collectible_list)
|
||||
return collectible
|
||||
|
||||
func save_collectible_list():
|
||||
var list: Array[Dictionary]
|
||||
for collectible in %CollectibleList.get_children():
|
||||
if not collectible.is_queued_for_deletion():
|
||||
list.append(collectible.get_data())
|
||||
MetSys.settings.collectible_list = list
|
||||
ResourceSaver.save(MetSys.settings)
|
||||
"
|
||||
|
||||
[sub_resource type="GDScript" id="GDScript_dicqo"]
|
||||
resource_name = "Finder"
|
||||
script/source = "@tool
|
||||
extends Button
|
||||
|
||||
@onready var scan_progress: ProgressBar = %ScanProgress
|
||||
@onready var show_on_map: CheckButton = %ShowOnMap
|
||||
@onready var summary: VBoxContainer = %Summary
|
||||
|
||||
var thread: Thread
|
||||
var found_elements: Array[Dictionary]
|
||||
|
||||
func _ready() -> void:
|
||||
scan_progress.hide()
|
||||
show_on_map.hide()
|
||||
exit()
|
||||
|
||||
func _pressed() -> void:
|
||||
for button in button_group.get_buttons():
|
||||
button.exit()
|
||||
|
||||
%Finder.show()
|
||||
|
||||
func exit():
|
||||
%Finder.hide()
|
||||
|
||||
func start_scan() -> void:
|
||||
summary.hide()
|
||||
%ScanButton.disabled = true
|
||||
|
||||
var collectible_list: Array[Dictionary]
|
||||
for item in %CollectibleList.get_children():
|
||||
collectible_list.append(item.get_data2())
|
||||
|
||||
found_elements.clear()
|
||||
for item in summary.get_children():
|
||||
item.free()
|
||||
|
||||
thread = Thread.new()
|
||||
thread.start(scan_maps.bind(collectible_list))
|
||||
set_process(true)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not thread:
|
||||
set_process(false)
|
||||
return
|
||||
|
||||
if thread.is_alive():
|
||||
return
|
||||
|
||||
thread.wait_to_finish()
|
||||
thread = null
|
||||
|
||||
scan_progress.hide()
|
||||
show_on_map.show()
|
||||
summary.show()
|
||||
%ScanButton.disabled = false
|
||||
|
||||
for item in %CollectibleList.get_children():
|
||||
var data: Dictionary = item.get_data2()
|
||||
var count := 0
|
||||
var count_label := setup_header(data)
|
||||
|
||||
for found in found_elements:
|
||||
if found.element != data.element:
|
||||
continue
|
||||
|
||||
count += 1
|
||||
setup_found(found)
|
||||
|
||||
count_label.text = str(count)
|
||||
summary.add_child(HSeparator.new())
|
||||
|
||||
func scan_maps(element_list: Array[Dictionary]):
|
||||
Thread.set_thread_safety_checks_enabled(false)
|
||||
|
||||
var maps: Array[String]
|
||||
var folders: Array[String]
|
||||
folders.append(MetSys.settings.map_root_folder)
|
||||
|
||||
while not folders.is_empty():
|
||||
var folder := folders.pop_back()
|
||||
folders.append_array(Array(DirAccess.get_directories_at(folder)).map(func(subfolder: String) -> String: return folder.path_join(subfolder)))
|
||||
maps.append_array(Array(DirAccess.get_files_at(folder)).map(func(file: String) -> String: return folder.path_join(file)))
|
||||
|
||||
scan_progress.max_value = maps.size()
|
||||
scan_progress.value = 0
|
||||
scan_progress.show()
|
||||
show_on_map.hide()
|
||||
|
||||
for map in maps:
|
||||
var lines := FileAccess.open(map, FileAccess.READ).get_as_text().split(\"\\n\")
|
||||
|
||||
var current_element: Dictionary
|
||||
for line in lines:
|
||||
if not current_element.is_empty():
|
||||
if line.begins_with(\"[\"):
|
||||
found_elements.append(current_element)
|
||||
current_element = {}
|
||||
elif line.begins_with(\"position =\"):
|
||||
current_element.position = str_to_var(line.get_slice(\"=\", 1))
|
||||
else:
|
||||
continue
|
||||
|
||||
for element in element_list:
|
||||
if line.begins_with(\"[node name=\\\"%s\" % element.element):
|
||||
current_element = element.duplicate()
|
||||
current_element.map = map
|
||||
break
|
||||
|
||||
if not current_element.is_empty():
|
||||
found_elements.append(current_element)
|
||||
|
||||
scan_progress.value += 1
|
||||
|
||||
func complete_element(element: Dictionary):
|
||||
var found := preload(\"res://addons/MetroidvaniaSystem/Nodes/CollectibleFoundItem.tscn\").instantiate()
|
||||
found.set_element(element)
|
||||
found.hovered.connect(owner._on_item_hover.bind(found))
|
||||
summary.add_child.call_deferred(found)
|
||||
|
||||
func setup_header(data: Dictionary) -> Label:
|
||||
var hbox := HBoxContainer.new()
|
||||
summary.add_child(hbox)
|
||||
|
||||
var tex := TextureRect.new()
|
||||
hbox.add_child(tex)
|
||||
tex.texture = data.get(\"icon\")
|
||||
|
||||
var label := Label.new()
|
||||
hbox.add_child(label)
|
||||
label.text = data.element
|
||||
|
||||
label = Label.new()
|
||||
hbox.add_child(label)
|
||||
|
||||
return label
|
||||
|
||||
func setup_found(data: Dictionary):
|
||||
var label := Label.new()
|
||||
summary.add_child(label)
|
||||
label.mouse_filter = Control.MOUSE_FILTER_PASS
|
||||
label.set_meta(&\"data\", data)
|
||||
|
||||
data.map = data.map.trim_prefix(MetSys.settings.map_root_folder)
|
||||
|
||||
var room := MetSys.map_data.get_cells_assigned_to(data.map)
|
||||
if \"position\" in data and not room.is_empty():
|
||||
var top_left := Vector2i.MAX
|
||||
for coords in room:
|
||||
top_left.x = mini(coords.x, top_left.x)
|
||||
top_left.y = mini(coords.y, top_left.y)
|
||||
|
||||
var pos := top_left + Vector2i(data.position / MetSys.settings.in_game_cell_size)
|
||||
data.coords = Vector3i(pos.x, pos.y, room[0].z)
|
||||
label.text = \"%s %s\" % [data.map, data.coords]
|
||||
else:
|
||||
label.text = \"%s\" % data.map
|
||||
|
||||
label.mouse_entered.connect(owner._on_item_hover.bind(label))
|
||||
|
||||
func toggle_display_on_map(toggled_on: bool) -> void:
|
||||
if toggled_on:
|
||||
owner.extra_draw = draw_collectibles_on_map
|
||||
else:
|
||||
owner.extra_draw = Callable()
|
||||
owner.map_overlay.queue_redraw()
|
||||
|
||||
func draw_collectibles_on_map(canvas_item: CanvasItem):
|
||||
for element in found_elements:
|
||||
var icon: Texture2D = element.icon
|
||||
var target_size := icon.get_size() * (minf(MetSys.CELL_SIZE.x, MetSys.CELL_SIZE.y) / minf(icon.get_width(), icon.get_height()) * 0.9)
|
||||
|
||||
if \"coords\" in element:
|
||||
var coords: Vector3i = element.coords
|
||||
if coords.z != owner.current_layer:
|
||||
continue
|
||||
|
||||
var pos := Vector2(coords.x + owner.map_offset.x, coords.y + owner.map_offset.y) * MetSys.CELL_SIZE
|
||||
canvas_item.draw_texture_rect(icon, Rect2(pos + MetSys.CELL_SIZE * 0.5 - target_size * 0.5, target_size), false)
|
||||
else:
|
||||
for coords in MetSys.map_data.get_cells_assigned_to(element.map):
|
||||
if coords.z != owner.current_layer:
|
||||
break
|
||||
|
||||
var pos := Vector2(coords.x + owner.map_offset.x, coords.y + owner.map_offset.y) * MetSys.CELL_SIZE
|
||||
canvas_item.draw_texture_rect(icon, Rect2(pos + MetSys.CELL_SIZE * 0.5 - target_size * 0.5, target_size), false)
|
||||
break
|
||||
|
||||
"
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qbvjg"]
|
||||
content_margin_left = 4.0
|
||||
content_margin_right = 4.0
|
||||
bg_color = Color(0, 0, 0, 0.501961)
|
||||
|
||||
[node name="MapViewer" type="HBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("1_s16ok")
|
||||
metadata/_edit_lock_ = true
|
||||
|
||||
[node name="Panel" type="PanelContainer" parent="."]
|
||||
custom_minimum_size = Vector2(200, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="Panel"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Layer" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Label" type="Label" parent="Panel/ScrollContainer/VBoxContainer/Layer"]
|
||||
layout_mode = 2
|
||||
text = "当前层"
|
||||
horizontal_alignment = 1
|
||||
|
||||
[node name="CurrentLayer" type="SpinBox" parent="Panel/ScrollContainer/VBoxContainer/Layer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
|
||||
[node name="RecenterButton" type="Button" parent="Panel/ScrollContainer/VBoxContainer/Layer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "重置视角"
|
||||
|
||||
[node name="CheckButton" type="CheckButton" parent="Panel/ScrollContainer/VBoxContainer/Layer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "预览映射"
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="Panel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Modes" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Settings" type="Button" parent="Panel/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
button_group = SubResource("ButtonGroup_lmh17")
|
||||
text = "收集品设置"
|
||||
script = SubResource("GDScript_fjyy3")
|
||||
|
||||
[node name="Finder" type="Button" parent="Panel/ScrollContainer/VBoxContainer/Modes"]
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_group = SubResource("ButtonGroup_lmh17")
|
||||
text = "收集品查找"
|
||||
script = SubResource("GDScript_dicqo")
|
||||
|
||||
[node name="HSeparator2" type="HSeparator" parent="Panel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="EditControls" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Settings" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Settings"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
vertical_scroll_mode = 2
|
||||
|
||||
[node name="CollectibleList" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Settings/ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="Button" type="Button" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Settings"]
|
||||
layout_mode = 2
|
||||
icon_alignment = 1
|
||||
script = ExtResource("2_tjngl")
|
||||
icon_name = "Add"
|
||||
|
||||
[node name="Finder" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScanButton" type="Button" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Finder"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Scan Maps"
|
||||
|
||||
[node name="ScanProgress" type="ProgressBar" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Finder"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ShowOnMap" type="CheckButton" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Finder"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "Display on Map"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Finder"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
horizontal_scroll_mode = 3
|
||||
vertical_scroll_mode = 2
|
||||
|
||||
[node name="Summary" type="VBoxContainer" parent="Panel/ScrollContainer/VBoxContainer/EditControls/Finder/ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 0
|
||||
|
||||
[node name="MapOverlay" type="Control" parent="."]
|
||||
clip_contents = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource("2_pgyha")
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="MapOverlay"]
|
||||
modulate = Color(0, 0, 0, 0.12549)
|
||||
show_behind_parent = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Map" type="Control" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
show_behind_parent = true
|
||||
anchors_preset = 0
|
||||
size_flags_horizontal = 3
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="StatusLabel" type="Label" parent="MapOverlay"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
offset_right = 1.0
|
||||
offset_bottom = 23.0
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_qbvjg")
|
||||
vertical_alignment = 1
|
||||
|
||||
[connection signal="toggled" from="Panel/ScrollContainer/VBoxContainer/Layer/CheckButton" to="." method="toggle_mapped"]
|
||||
[connection signal="pressed" from="Panel/ScrollContainer/VBoxContainer/EditControls/Settings/Button" to="Panel/ScrollContainer/VBoxContainer/Modes/Settings" method="add_collectible"]
|
||||
[connection signal="pressed" from="Panel/ScrollContainer/VBoxContainer/EditControls/Finder/ScanButton" to="Panel/ScrollContainer/VBoxContainer/Modes/Finder" method="start_scan"]
|
||||
[connection signal="toggled" from="Panel/ScrollContainer/VBoxContainer/EditControls/Finder/ShowOnMap" to="Panel/ScrollContainer/VBoxContainer/Modes/Finder" method="toggle_display_on_map"]
|
||||
@ -1,119 +0,0 @@
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
const EDITOR_SCRIPT = preload("res://addons/MetroidvaniaSystem/Database/MapEditor.gd")
|
||||
var editor: EDITOR_SCRIPT
|
||||
var theme_cache: Dictionary
|
||||
|
||||
var use_cursor := true
|
||||
var room_only_cursor := true
|
||||
|
||||
var drag_from: Vector2i = EDITOR_SCRIPT.NULL_VECTOR2I
|
||||
var highlighted_room: Array[Vector3i]
|
||||
var highlighted_border := -1
|
||||
|
||||
var top_draw: Callable
|
||||
|
||||
func _ready() -> void:
|
||||
if not owner.plugin:
|
||||
return
|
||||
|
||||
editor = owner
|
||||
_editor_init.call_deferred()
|
||||
|
||||
func _editor_init():
|
||||
pass
|
||||
|
||||
func _update_theme():
|
||||
pass
|
||||
|
||||
func _editor_enter():
|
||||
pass
|
||||
|
||||
func _editor_exit():
|
||||
pass
|
||||
|
||||
func _editor_input(event: InputEvent):
|
||||
pass
|
||||
|
||||
func _editor_draw(map_overlay: CanvasItem):
|
||||
if highlighted_border == -1:
|
||||
for p in highlighted_room:
|
||||
map_overlay.draw_rect(Rect2(Vector2(p.x, p.y) * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.highlighted_room)
|
||||
|
||||
if drag_from == EDITOR_SCRIPT.NULL_VECTOR2I:
|
||||
if use_cursor and map_overlay.cursor_inside and (not room_only_cursor or get_cell_at_cursor()):
|
||||
map_overlay.draw_rect(Rect2(get_cursor_pos() as Vector2 * MetSys.CELL_SIZE, MetSys.CELL_SIZE), theme_cache.cursor_color, false, 2)
|
||||
else:
|
||||
var rect := get_rect_between(drag_from, get_cursor_pos())
|
||||
top_draw = func(map_overlay: CanvasItem): map_overlay.draw_string(get_theme_font(&"font", &"Label"), Vector2(get_cursor_pos()) * MetSys.CELL_SIZE + MetSys.CELL_SIZE * Vector2.UP * 0.5, "%d x %d" % [rect.size.x, rect.size.y])
|
||||
|
||||
rect.position *= MetSys.CELL_SIZE
|
||||
rect.size *= MetSys.CELL_SIZE
|
||||
map_overlay.draw_rect(rect, theme_cache.cursor_color, false, 2)
|
||||
|
||||
if highlighted_border > -1:
|
||||
if highlighted_room.is_empty():
|
||||
draw_border_highlight(map_overlay, get_cursor_pos(), highlighted_border)
|
||||
else:
|
||||
for p in highlighted_room:
|
||||
var cell_data := MetSys.map_data.get_cell_at(p)
|
||||
for i in 4:
|
||||
if cell_data.borders[i] > -1:
|
||||
draw_border_highlight(map_overlay, Vector2(p.x, p.y), i)
|
||||
|
||||
func draw_border_highlight(map_overlay: CanvasItem, pos: Vector2, border: int):
|
||||
match border:
|
||||
MetSys.R:
|
||||
map_overlay.draw_rect(Rect2(pos * MetSys.CELL_SIZE + Vector2(MetSys.CELL_SIZE.x * 0.667, 0), MetSys.CELL_SIZE * Vector2(0.333, 1)), theme_cache.border_highlight)
|
||||
MetSys.D:
|
||||
map_overlay.draw_rect(Rect2(pos * MetSys.CELL_SIZE + Vector2(0, MetSys.CELL_SIZE.y * 0.667), MetSys.CELL_SIZE * Vector2(1, 0.333)), theme_cache.border_highlight)
|
||||
MetSys.L:
|
||||
map_overlay.draw_rect(Rect2(pos * MetSys.CELL_SIZE, MetSys.CELL_SIZE * Vector2(0.333, 1)), theme_cache.border_highlight)
|
||||
MetSys.U:
|
||||
map_overlay.draw_rect(Rect2(pos * MetSys.CELL_SIZE, MetSys.CELL_SIZE * Vector2(1, 0.333)), theme_cache.border_highlight)
|
||||
|
||||
func get_cursor_pos() -> Vector2i:
|
||||
return editor.get_cursor_pos()
|
||||
|
||||
func get_coords(p: Vector2i, layer := editor.current_layer) -> Vector3i:
|
||||
return Vector3i(p.x, p.y, layer)
|
||||
|
||||
func get_rect_between(point1: Vector2, point2: Vector2) -> Rect2:
|
||||
var start: Vector2
|
||||
start.x = minf(point1.x, point2.x)
|
||||
start.y = minf(point1.y, point2.y)
|
||||
|
||||
var end: Vector2
|
||||
end.x = maxf(point1.x, point2.x)
|
||||
end.y = maxf(point1.y, point2.y)
|
||||
|
||||
return Rect2(start, Vector2.ONE).expand(end + Vector2.ONE)
|
||||
|
||||
func get_square_border_idx(borders: Array[int], rel: Vector2) -> int:
|
||||
if borders[MetSys.L] > -1 and rel.x < MetSys.CELL_SIZE.x / 3:
|
||||
return MetSys.L
|
||||
|
||||
if borders[MetSys.R] > -1 and rel.x > MetSys.CELL_SIZE.x - MetSys.CELL_SIZE.x / 3:
|
||||
return MetSys.R
|
||||
|
||||
if borders[MetSys.U] > -1 and rel.y < MetSys.CELL_SIZE.y / 3:
|
||||
return MetSys.U
|
||||
|
||||
if borders[MetSys.D] > -1 and rel.y > MetSys.CELL_SIZE.y - MetSys.CELL_SIZE.y / 3:
|
||||
return MetSys.D
|
||||
|
||||
return -1
|
||||
|
||||
func get_cell_at_cursor() -> MetroidvaniaSystem.MapData.CellData:
|
||||
return MetSys.map_data.get_cell_at(get_coords(get_cursor_pos()))
|
||||
|
||||
func mark_modified():
|
||||
editor.plugin.modified = true
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
theme_cache.highlighted_room = get_theme_color(&"highlighted_room", &"MetSys")
|
||||
theme_cache.border_highlight = get_theme_color(&"border_highlight", &"MetSys")
|
||||
theme_cache.cursor_color = get_theme_color(&"cursor_color", &"MetSys")
|
||||
_update_theme()
|
||||
|
Before Width: | Height: | Size: 452 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://chxprk5rw4ldq"
|
||||
path="res://.godot/imported/Icon.png-ee9c40684788f1a27b35051aa11d9b76.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Icon.png"
|
||||
dest_files=["res://.godot/imported/Icon.png-ee9c40684788f1a27b35051aa11d9b76.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,76 +0,0 @@
|
||||
@tool
|
||||
extends EditorPlugin
|
||||
|
||||
enum { TAB_EDITOR, TAB_OVERVIEW, TAB_MANAGE }
|
||||
|
||||
var main: Control
|
||||
var modified: bool:
|
||||
set(m):
|
||||
if m == modified:
|
||||
return
|
||||
|
||||
modified = m
|
||||
dirty_toggled.emit(modified)
|
||||
|
||||
var theme_scanner: Timer
|
||||
var prev_theme_state: Array
|
||||
|
||||
signal dirty_toggled
|
||||
|
||||
func _has_main_screen() -> bool:
|
||||
return true
|
||||
|
||||
func _get_plugin_name() -> String:
|
||||
return "MetSys"
|
||||
|
||||
func _get_plugin_icon() -> Texture2D:
|
||||
return preload("res://addons/MetroidvaniaSystem/Icon.png")
|
||||
|
||||
func _enter_tree() -> void:
|
||||
theme_scanner = Timer.new()
|
||||
theme_scanner.wait_time = 0.6
|
||||
add_child(theme_scanner)
|
||||
theme_scanner.timeout.connect(check_theme)
|
||||
|
||||
await get_tree().process_frame
|
||||
if not get_singleton():
|
||||
add_autoload_singleton("MetSys", "res://addons/MetroidvaniaSystem/Nodes/Singleton.tscn")
|
||||
ProjectSettings.save()
|
||||
OS.set_restart_on_exit(true, ["-e"])
|
||||
get_tree().quit()
|
||||
return
|
||||
|
||||
main = preload("res://addons/MetroidvaniaSystem/Database/Main.tscn").instantiate()
|
||||
main.plugin = self
|
||||
get_editor_interface().get_editor_main_screen().add_child(main)
|
||||
main.hide()
|
||||
|
||||
get_singleton().settings.theme_changed.connect(func(): prev_theme_state.clear())
|
||||
|
||||
func _exit_tree() -> void:
|
||||
main.queue_free()
|
||||
|
||||
func _make_visible(visible: bool) -> void:
|
||||
main.visible = visible
|
||||
if visible:
|
||||
theme_scanner.start()
|
||||
else:
|
||||
theme_scanner.stop()
|
||||
|
||||
func _save_external_data() -> void:
|
||||
get_singleton().map_data.save_data()
|
||||
modified = false
|
||||
|
||||
func _get_unsaved_status(for_scene: String) -> String:
|
||||
if modified and for_scene.is_empty():
|
||||
return "MetSys map has been modified."
|
||||
return ""
|
||||
|
||||
func get_singleton() -> MetroidvaniaSystem:
|
||||
return get_tree().root.get_node_or_null(^"MetSys")
|
||||
|
||||
func check_theme():
|
||||
var theme := get_singleton().settings.theme
|
||||
var changed := theme.check_for_changes(prev_theme_state)
|
||||
if not changed.is_empty():
|
||||
get_singleton().theme_modified.emit(changed)
|
||||
@ -1,42 +0,0 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://w48b71tv2d4v"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/CollectibleElement.gd" id="1_1bebr"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/EditorIconButton.gd" id="2_3d05g"]
|
||||
|
||||
[node name="Collectible" type="PanelContainer"]
|
||||
script = ExtResource("1_1bebr")
|
||||
metadata/is_collectible = true
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="VBoxContainer/HBoxContainer2"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
placeholder_text = "Node Name"
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer/HBoxContainer2"]
|
||||
layout_mode = 2
|
||||
script = ExtResource("2_3d05g")
|
||||
icon_name = "Remove"
|
||||
|
||||
[node name="IconContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/IconContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
text = "Icon"
|
||||
|
||||
[node name="SaveTimer" type="Timer" parent="."]
|
||||
wait_time = 0.5
|
||||
one_shot = true
|
||||
|
||||
[connection signal="text_changed" from="VBoxContainer/HBoxContainer2/LineEdit" to="SaveTimer" method="start" unbinds=1]
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer2/Button" to="." method="delete"]
|
||||
[connection signal="timeout" from="SaveTimer" to="." method="emit_signal" binds= [&"save_request"]]
|
||||
@ -1,30 +0,0 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cwdt1r5mp5gpj"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/CollectibleFoundItem.gd" id="1_t85ni"]
|
||||
|
||||
[node name="Collectible" type="PanelContainer"]
|
||||
script = ExtResource("1_t85ni")
|
||||
metadata/is_collectible = true
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Icon" type="TextureRect" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
expand_mode = 3
|
||||
stretch_mode = 5
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Name"
|
||||
|
||||
[node name="Button" type="Button" parent="."]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
flat = true
|
||||
|
||||
[connection signal="mouse_entered" from="Button" to="." method="on_hover"]
|
||||
[connection signal="mouse_exited" from="Button" to="." method="on_unhover"]
|
||||
@ -1,6 +0,0 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://c01ibpvrp2wsd"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/MetroidvaniaSystem.gd" id="1_y1fyl"]
|
||||
|
||||
[node name="MetroidvaniaSettings" type="Node"]
|
||||
script = ExtResource("1_y1fyl")
|
||||
@ -1,37 +0,0 @@
|
||||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
var resource_picker: EditorResourcePicker
|
||||
|
||||
signal save_request
|
||||
|
||||
func _ready() -> void:
|
||||
if get_tree().edited_scene_root and get_tree().edited_scene_root.is_ancestor_of(self):
|
||||
return
|
||||
|
||||
resource_picker = EditorResourcePicker.new()
|
||||
%IconContainer.add_child(resource_picker)
|
||||
resource_picker.base_type = "Texture2D"
|
||||
resource_picker.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
resource_picker.resource_changed.connect(func(a): save_request.emit())
|
||||
|
||||
func get_data() -> Dictionary:
|
||||
var data := {element = %LineEdit.text}
|
||||
if resource_picker.edited_resource:
|
||||
data.icon = resource_picker.edited_resource.resource_path
|
||||
return data
|
||||
|
||||
func get_data2() -> Dictionary:
|
||||
var data := get_data()
|
||||
if "icon" in data:
|
||||
data.icon = load(data.icon)
|
||||
return data
|
||||
|
||||
func set_data(data: Dictionary):
|
||||
%LineEdit.text = data.element
|
||||
if "icon" in data:
|
||||
resource_picker.edited_resource = load(data.icon)
|
||||
|
||||
func delete() -> void:
|
||||
queue_free()
|
||||
save_request.emit()
|
||||
@ -1,32 +0,0 @@
|
||||
@tool
|
||||
extends PanelContainer
|
||||
|
||||
signal hovered
|
||||
signal unhovered
|
||||
|
||||
var data: Dictionary
|
||||
|
||||
func set_element(element: Dictionary):
|
||||
data = element
|
||||
%Label.text = data.element
|
||||
%Icon.texture = data.get("icon")
|
||||
data.map = data.map.trim_prefix(MetSys.settings.map_root_folder)
|
||||
|
||||
var room := MetSys.map_data.get_cells_assigned_to(data.map)
|
||||
if "position" in data and not room.is_empty():
|
||||
var top_left := Vector2i.MAX
|
||||
for coords in room:
|
||||
top_left.x = mini(coords.x, top_left.x)
|
||||
top_left.y = mini(coords.y, top_left.y)
|
||||
|
||||
var pos := top_left + Vector2i(data.position / MetSys.settings.in_game_cell_size)
|
||||
data.coords = Vector3i(pos.x, pos.y, room[0].z)
|
||||
%Button.tooltip_text = "%s\nat: %s %s" % [data.element, data.map, data.coords]
|
||||
else:
|
||||
%Button.tooltip_text = "%s\nat: %s" % [data.element, data.map]
|
||||
|
||||
func on_hover() -> void:
|
||||
hovered.emit()
|
||||
|
||||
func on_unhover() -> void:
|
||||
unhovered.emit()
|
||||
@ -1,25 +0,0 @@
|
||||
@tool
|
||||
## A class that registers and draws custom elements.
|
||||
##
|
||||
## Custom elements are map elements that are too complex to be handled as regular cells. Example elements include location name labels, Metroid-like elevator shafts or room contents inside cell. Internally they are represented as rectangles with an origin point and a [String] extra data.
|
||||
## [br][br]To use custom elements, create a new script that inherits this one and assign it to [code]custom_element_script[/code] property in MetSys Settings. Register your elements by calling [method register_elements] inside [method Object._init] then press Refresh Custom Elements button in the Manage tab of MetSys Database. This will create an instance of your script and the elements will be available in Custom Elements edit mode of the editor. You need to call [method MetroidvaniaSystem.draw_custom_elements] to draw the elements on your map.
|
||||
extends RefCounted
|
||||
|
||||
var custom_elements: Dictionary
|
||||
|
||||
## Registers a new element. The [param name] will appear in the editor (capitalized) and [param draw_callback] will be used to draw your element. The callback is called automatically when the element needs to be drawn.
|
||||
## [br][br]The callback signature is [code]method(canvas_item: CanvasItem, coords: Vector3i, pos: Vector2, size: Vector2, data: String)[/code]. [code]canvas_item[/code] is the [CanvasItem] that you should use to draw the elements, [code]coords[/code] are the coordinates of the origin point of the element, [code]pos[/code] is the position of the element's origin in pixels, [code]size[/code] is the size of the element's rectangle in pixels, [code]data[/code] is the data [String] that was assigned to the element.
|
||||
## [br][br]Example draw callback that draws a label if the cell was discovered:
|
||||
## [codeblock]
|
||||
## func draw_label(canvas_item: CanvasItem, coords: Vector3i, pos: Vector2, size: Vector2, data: String):
|
||||
## if not MetSys.is_cell_discovered(coords):
|
||||
## return
|
||||
##
|
||||
## canvas_item.draw_string(ThemeDB.get_default_theme().default_font,
|
||||
## pos + Vector2(-1, -0.5) * MetSys.CELL_SIZE, data, HORIZONTAL_ALIGNMENT_CENTER, MetSys.CELL_SIZE.x * 3)
|
||||
func register_element(name: String, draw_callback: Callable):
|
||||
custom_elements[name.replace("/", "_")] = draw_callback
|
||||
|
||||
func draw_element(canvas_item: CanvasItem, coords: Vector3i, name: String, pos: Vector2, size: Vector2, data: String):
|
||||
var callback: Callable = custom_elements[name]
|
||||
callback.call(canvas_item, coords, pos, size, data)
|
||||
@ -1,11 +0,0 @@
|
||||
@tool
|
||||
extends Button
|
||||
|
||||
@export var icon_name: String
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
if get_tree().edited_scene_root and get_tree().edited_scene_root.is_ancestor_of(self):
|
||||
return
|
||||
|
||||
icon = get_theme_icon(icon_name, &"EditorIcons")
|
||||
@ -1,19 +0,0 @@
|
||||
## A class for creating custom cells at runtime.
|
||||
##
|
||||
## MapBuilder is obtained with [method MetroidvaniaSystem.get_map_builder] and can be used for procedural map generation or other use-cases where cells that weren't created in the editor need to be used.
|
||||
## [br][br]A cell can be created with [method create_cell] (the position can't already have another cell). The method will return a CellOverride that you can use to customize the cell's appearance. Once you finished creating your cells, use [method update_map].
|
||||
## [br][br]Note that, while cells created with this class are part of [method MetroidvaniaSystem.get_save_data]'s dump, you can't differentiate them from regular cell overrides. You need to keep this information yourself.
|
||||
extends RefCounted
|
||||
|
||||
## The cells created with this MapBuilder.
|
||||
var cells: Array[MetroidvaniaSystem.MapData.CellOverride]
|
||||
|
||||
## Creates a new cell on the world map and returns a CellOverride that can be used to customize the cell. You can destroy created cells using their [code]destroy()[/code] method.
|
||||
func create_cell(at: Vector3i) -> MetroidvaniaSystem.MapData.CellOverride:
|
||||
var cell: MetroidvaniaSystem.MapData.CellOverride = MetSys.map_data.create_custom_cell(at)
|
||||
cells.append(cell)
|
||||
return cell
|
||||
|
||||
## Requests the world map update. This simply emits [signal MetroidvaniaSystem.map_updated]. The signal is not emitted automatically when customizing the cells, unlike regular overrides. Updating the map in batches is more efficient.
|
||||
func update_map():
|
||||
MetSys.map_updated.emit()
|
||||
@ -1,424 +0,0 @@
|
||||
const FWD = { MetroidvaniaSystem.R: Vector2i.RIGHT, MetroidvaniaSystem.D: Vector2i.DOWN, MetroidvaniaSystem.L: Vector2i.LEFT, MetroidvaniaSystem.U: Vector2i.UP }
|
||||
|
||||
class CellData:
|
||||
enum { DATA_EXITS, DATA_COLORS, DATA_SYMBOL, DATA_MAP, OVERRIDE_COORDS, OVERRIDE_CUSTOM }
|
||||
|
||||
var color: Color = Color.TRANSPARENT
|
||||
var borders: Array[int] = [-1, -1, -1, -1]
|
||||
var border_colors: Array[Color] = [Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT, Color.TRANSPARENT]
|
||||
var symbol := -1
|
||||
var assigned_scene: String
|
||||
var override_map: String
|
||||
|
||||
var loading
|
||||
|
||||
func _init(line: String) -> void:
|
||||
if line.is_empty():
|
||||
return
|
||||
loading = [line, -1]
|
||||
|
||||
var chunk := load_next_chunk()
|
||||
for i in 4:
|
||||
borders[i] = chunk.get_slice(",", i).to_int()
|
||||
|
||||
chunk = load_next_chunk()
|
||||
if not chunk.is_empty():
|
||||
var color_slice := chunk.get_slice(",", 0)
|
||||
if not color_slice.is_empty():
|
||||
color = Color(color_slice)
|
||||
|
||||
for i in 4:
|
||||
color_slice = chunk.get_slice(",", i + 1)
|
||||
if not color_slice.is_empty():
|
||||
border_colors[i] = Color(color_slice)
|
||||
|
||||
chunk = load_next_chunk()
|
||||
if not chunk.is_empty():
|
||||
symbol = chunk.to_int()
|
||||
|
||||
assigned_scene = load_next_chunk()
|
||||
loading = null
|
||||
|
||||
func get_string() -> String:
|
||||
var data: PackedStringArray
|
||||
data.append("%s,%s,%s,%s" % borders)
|
||||
|
||||
var colors: Array[Color]
|
||||
colors.assign([color] + Array(border_colors))
|
||||
if colors.any(func(col: Color): return col.a > 0):
|
||||
data.append("%s,%s,%s,%s,%s" % colors.map(func(col: Color): return col.to_html(false) if col.a > 0 else ""))
|
||||
else:
|
||||
data.append("")
|
||||
|
||||
if symbol > -1:
|
||||
data.append(str(symbol))
|
||||
else:
|
||||
data.append("")
|
||||
data.append(assigned_scene.trim_prefix(MetSys.settings.map_root_folder + "/"))
|
||||
return "|".join(data)
|
||||
|
||||
func load_next_chunk() -> String:
|
||||
loading[1] += 1
|
||||
return loading[0].get_slice("|", loading[1])
|
||||
|
||||
func get_color() -> Color:
|
||||
var c: Color
|
||||
var override := get_override()
|
||||
if override and override.color.a > 0:
|
||||
c = override.color
|
||||
else:
|
||||
c = color
|
||||
|
||||
if c.a > 0:
|
||||
return c
|
||||
return MetSys.settings.theme.default_center_color
|
||||
|
||||
func get_border(idx: int) -> int:
|
||||
var override := get_override()
|
||||
if override and override.borders[idx] != -2:
|
||||
return override.borders[idx]
|
||||
return borders[idx]
|
||||
|
||||
func get_border_color(idx: int) -> Color:
|
||||
var c: Color
|
||||
var override := get_override()
|
||||
if override and override.border_colors[idx].a > 0:
|
||||
c = override.border_colors[idx]
|
||||
else:
|
||||
c = border_colors[idx]
|
||||
|
||||
if c.a > 0:
|
||||
return c
|
||||
return MetSys.settings.theme.default_border_color
|
||||
|
||||
func get_symbol() -> int:
|
||||
var override := get_override()
|
||||
if override and override.symbol != -2:
|
||||
return override.symbol
|
||||
return symbol
|
||||
|
||||
func get_assigned_scene() -> String:
|
||||
var override := get_override()
|
||||
if override and override.assigned_scene != "/":
|
||||
return override.assigned_scene
|
||||
if not override_map.is_empty():
|
||||
return override_map
|
||||
return assigned_scene
|
||||
|
||||
func get_override() -> CellOverride:
|
||||
if not MetSys.save_data:
|
||||
return null
|
||||
return MetSys.save_data.cell_overrides.get(self)
|
||||
|
||||
func get_coords() -> Vector3i:
|
||||
return MetSys.map_data.cells.find_key(self)
|
||||
|
||||
## A runtime override for the cell's properties that allows to modify it's default appearance designed in the editor.
|
||||
##
|
||||
## CellOverride can be obtained from [method MetroidvaniaSystem.get_cell_override] or using the MapBuilder. It comes with a set of methods that allows customizing the cells. [signal MetroidvaniaSystem.map_updated] signal is automatically emitted after modifications, unless the cell comes from MapBuilder.
|
||||
class CellOverride extends CellData:
|
||||
var original_room: CellData
|
||||
var custom_cell_coords := Vector3i.MAX
|
||||
var commit_queued: bool
|
||||
|
||||
func _init(from: CellData) -> void:
|
||||
original_room = from
|
||||
borders = [-2, -2, -2, -2]
|
||||
symbol = -2
|
||||
assigned_scene = "/"
|
||||
|
||||
static func load_from_line(line: String) -> CellOverride:
|
||||
var cell: CellData
|
||||
var coords_string := line.get_slice("|", CellData.OVERRIDE_COORDS)
|
||||
var coords := Vector3i(coords_string.get_slice(",", 0).to_int(), coords_string.get_slice(",", 1).to_int(), coords_string.get_slice(",", 2).to_int())
|
||||
|
||||
var is_custom := line.get_slice("|", CellData.OVERRIDE_CUSTOM) == "true"
|
||||
if is_custom:
|
||||
cell = MetSys.map_data.create_cell_at(coords)
|
||||
else:
|
||||
cell = MetSys.map_data.get_cell_at(coords)
|
||||
|
||||
var override := CellOverride.new(cell)
|
||||
if is_custom:
|
||||
override.custom_cell_coords = coords
|
||||
|
||||
var fake_cell := CellData.new(line)
|
||||
override.borders = fake_cell.borders
|
||||
override.border_colors = fake_cell.border_colors
|
||||
override.color = fake_cell.color
|
||||
override.symbol = fake_cell.symbol
|
||||
override.set_assigned_scene(fake_cell.assigned_scene)
|
||||
|
||||
return override
|
||||
|
||||
## Sets a border of the cell. [param idx] is the direction index of the cell. Use [constant MetroidvaniaSystem.R], [constant MetroidvaniaSystem.D], [constant MetroidvaniaSystem.L], [constant MetroidvaniaSystem.U] constants here. The [param value] must be within the [member MapTheme.borders] array bounds + 2 (0 and 1 are the default wall and passage). Use the default to reset to the border assigned in the editor. Value of [code]-1[/code] will remove the border, but it's not recommended.
|
||||
func set_border(idx: int, value := -2):
|
||||
assert(idx >= 0 and idx < 4)
|
||||
borders[idx] = value
|
||||
_queue_commit()
|
||||
|
||||
## Sets the color of a cell's border. [param idx] is the direction index of the cell (see [method set_border]). If the default [param value] is used (or any color with [code]0[/code] alpha), the border will be reset to the default color.
|
||||
func set_border_color(idx: int, value := Color.TRANSPARENT):
|
||||
assert(idx >= 0 and idx < 4)
|
||||
border_colors[idx] = value
|
||||
_queue_commit()
|
||||
|
||||
## Sets the color of the cell's center texture.
|
||||
func set_color(value := Color.TRANSPARENT):
|
||||
color = value
|
||||
_queue_commit()
|
||||
|
||||
## Sets the cell's assigned symbol. Value of [code]-1[/code] will remove the symbol. The markers assigned from [method MetroidvaniaSystem.set_custom_marker] still have a priority.
|
||||
func set_symbol(value := -2):
|
||||
assert(value >= -2 and value < MetSys.settings.theme.symbols.size())
|
||||
symbol = value
|
||||
_queue_commit()
|
||||
|
||||
## Changes the scene assigned to the cell. Unlike other methods, this has effect on the whole room that contains this cell. Using the default value will reset it to the scene assigned in the editor.
|
||||
func set_assigned_scene(value := "/"):
|
||||
if value == "/":
|
||||
_cleanup_assigned_scene()
|
||||
else:
|
||||
if custom_cell_coords != Vector3i.MAX:
|
||||
if not value in MetSys.map_data.assigned_scenes:
|
||||
MetSys.map_data.assigned_scenes[value] = []
|
||||
MetSys.map_data.assigned_scenes[value].append(custom_cell_coords)
|
||||
else:
|
||||
MetSys.map_data.scene_overrides[value] = original_room.assigned_scene
|
||||
|
||||
for coords in MetSys.map_data.get_whole_room(original_room.get_coords()):
|
||||
var cell: CellData = MetSys.map_data.cells[coords]
|
||||
if not cell.override_map.is_empty():
|
||||
push_warning("Assigned map already overriden at: %s" % coords)
|
||||
cell.override_map = value
|
||||
|
||||
assigned_scene = value
|
||||
MetSys.room_assign_updated.emit()
|
||||
_queue_commit()
|
||||
|
||||
## Applies the values from this CellOverride to all cells that belong to the specified [param group_id]. You need to apply your customization [i]before[/i] calling this method.
|
||||
func apply_to_group(group_id: int):
|
||||
assert(group_id in MetSys.map_data.cell_groups)
|
||||
|
||||
for coords in MetSys.map_data.cell_groups[group_id]:
|
||||
var override: CellOverride = MetSys.get_cell_override(coords)
|
||||
if override == self:
|
||||
continue
|
||||
|
||||
override.borders = borders.duplicate()
|
||||
override.color = color
|
||||
override.border_colors = border_colors.duplicate()
|
||||
override.symbol = symbol
|
||||
|
||||
_queue_commit()
|
||||
|
||||
## Destroys the cell. This method can only be used on the overrides from the MapBuilder.
|
||||
func destroy() -> void:
|
||||
if custom_cell_coords == Vector3i.MAX:
|
||||
push_error("Only custom cell can be destroyed.")
|
||||
return
|
||||
|
||||
var cell_coords := custom_cell_coords
|
||||
custom_cell_coords = Vector3i.MAX
|
||||
|
||||
MetSys.remove_cell_override(cell_coords)
|
||||
MetSys.map_data.erase_cell(cell_coords)
|
||||
MetSys.map_data.cell_overrides.erase(cell_coords)
|
||||
MetSys.map_data.custom_cells.erase(self)
|
||||
|
||||
if assigned_scene != "/":
|
||||
MetSys.map_data.assigned_scenes[assigned_scene].erase(cell_coords)
|
||||
|
||||
if MetSys.save_data:
|
||||
MetSys.save_data.discovered_cells.erase(cell_coords)
|
||||
|
||||
func _cleanup_assigned_scene() -> void:
|
||||
if assigned_scene == "/":
|
||||
return
|
||||
|
||||
MetSys.map_data.scene_overrides.erase(assigned_scene)
|
||||
for coords in MetSys.map_data.get_whole_room(original_room.get_coords()):
|
||||
MetSys.map_data.cells[coords].override_map = ""
|
||||
|
||||
func _get_override_string(coords: Vector3i) -> String:
|
||||
return str(get_string(), "|", coords.x, ",", coords.y, ",", coords.z, "|", custom_cell_coords != Vector3i.MAX)
|
||||
|
||||
func _queue_commit():
|
||||
if commit_queued or custom_cell_coords != Vector3i.MAX:
|
||||
return
|
||||
commit_queued = true
|
||||
_commit.call_deferred()
|
||||
|
||||
func _commit() -> void:
|
||||
commit_queued = false
|
||||
MetSys.map_updated.emit()
|
||||
|
||||
var cells: Dictionary#[Vector3i, CellData]
|
||||
var custom_cells: Dictionary#[Vector3i, CellData]
|
||||
var assigned_scenes: Dictionary#[String, Array[Vector3i]]
|
||||
var cell_groups: Dictionary#[int, Array[Vector3i]]
|
||||
var custom_elements: Dictionary#[Vector3i, Struct]
|
||||
|
||||
var cell_overrides: Dictionary#[Vector3i, CellOverride]
|
||||
var scene_overrides: Dictionary#[String, String]
|
||||
|
||||
func load_data():
|
||||
var file := FileAccess.open(MetSys.settings.map_setting_folder.path_join("MapData.txt"), FileAccess.READ)
|
||||
if not file:
|
||||
push_warning("Map data file does not exist.")
|
||||
return
|
||||
|
||||
var data := file.get_as_text().split("\n")
|
||||
var i: int
|
||||
|
||||
var current_section := 0 # groups, custom_elements, cells
|
||||
while i < data.size():
|
||||
var line := data[i]
|
||||
if line.begins_with("["):
|
||||
current_section = 2
|
||||
line = line.trim_prefix("[").trim_suffix("]")
|
||||
|
||||
var coords: Vector3i
|
||||
coords.x = line.get_slice(",", 0).to_int()
|
||||
coords.y = line.get_slice(",", 1).to_int()
|
||||
coords.z = line.get_slice(",", 2).to_int()
|
||||
|
||||
i += 1
|
||||
line = data[i]
|
||||
|
||||
var cell_data := CellData.new(line)
|
||||
if not cell_data.assigned_scene.is_empty():
|
||||
assigned_scenes[cell_data.assigned_scene] = [coords]
|
||||
|
||||
cells[coords] = cell_data
|
||||
elif current_section == 1 or current_section == 0 and line.contains("/"):
|
||||
current_section = 1
|
||||
var element_data := line.split("/")
|
||||
var element: Dictionary
|
||||
element.name = element_data[1]
|
||||
element.size = Vector2i(element_data[2].get_slice("x", 0).to_int(), element_data[2].get_slice("x", 1).to_int())
|
||||
if element_data.size() == 4:
|
||||
element.data = element_data[3]
|
||||
else:
|
||||
element.data = ""
|
||||
|
||||
var coords: Vector3i
|
||||
coords.x = element_data[0].get_slice(",", 0).to_int()
|
||||
coords.y = element_data[0].get_slice(",", 1).to_int()
|
||||
coords.z = element_data[0].get_slice(",", 2).to_int()
|
||||
custom_elements[coords] = element
|
||||
elif current_section == 0:
|
||||
var group_data := line.split(":")
|
||||
var group_id := group_data[0].to_int()
|
||||
var rooms_in_group: Array
|
||||
for j in range(1, group_data.size()):
|
||||
var coords: Vector3i
|
||||
coords.x = group_data[j].get_slice(",", 0).to_int()
|
||||
coords.y = group_data[j].get_slice(",", 1).to_int()
|
||||
coords.z = group_data[j].get_slice(",", 2).to_int()
|
||||
rooms_in_group.append(coords)
|
||||
|
||||
cell_groups[group_id] = rooms_in_group
|
||||
|
||||
i += 1
|
||||
|
||||
for map in assigned_scenes.keys():
|
||||
var assigned_cells: Array[Vector3i]
|
||||
assigned_cells.assign(assigned_scenes[map])
|
||||
assigned_scenes[map] = get_whole_room(assigned_cells[0])
|
||||
|
||||
func save_data():
|
||||
var file := FileAccess.open(MetSys.settings.map_setting_folder.path_join("MapData.txt"), FileAccess.WRITE)
|
||||
if not file:
|
||||
push_error("Could not open file '%s' for writing." % MetSys.settings.map_setting_folder.path_join("MapData.txt"))
|
||||
return
|
||||
|
||||
for group in cell_groups:
|
||||
if cell_groups[group].is_empty():
|
||||
continue
|
||||
|
||||
var line: PackedStringArray
|
||||
line.append(str(group))
|
||||
for coords in cell_groups[group]:
|
||||
line.append("%s,%s,%s" % [coords.x, coords.y, coords.z])
|
||||
|
||||
file.store_line(":".join(line))
|
||||
|
||||
for coords in custom_elements:
|
||||
var line: PackedStringArray
|
||||
line.append("%s,%s,%s" % [coords.x, coords.y, coords.z])
|
||||
|
||||
var element: Dictionary = custom_elements[coords]
|
||||
line.append(element.name)
|
||||
line.append("%sx%s" % [element.size.x, element.size.y])
|
||||
if not element.data.is_empty():
|
||||
line.append(element.data)
|
||||
|
||||
file.store_line("/".join(line))
|
||||
|
||||
for coords in cells:
|
||||
file.store_line("[%s,%s,%s]" % [coords.x, coords.y, coords.z])
|
||||
|
||||
var cell_data := get_cell_at(coords)
|
||||
file.store_line(cell_data.get_string())
|
||||
|
||||
func get_cell_at(coords: Vector3i) -> CellData:
|
||||
return cells.get(coords)
|
||||
|
||||
func create_cell_at(coords: Vector3i) -> CellData:
|
||||
cells[coords] = CellData.new("")
|
||||
return cells[coords]
|
||||
|
||||
func create_custom_cell(coords: Vector3i) -> CellOverride:
|
||||
assert(not coords in cells, "A cell already exists at this position")
|
||||
var cell := create_cell_at(coords)
|
||||
custom_cells[coords] = cell
|
||||
|
||||
var override: CellOverride = MetSys.save_data.add_cell_override(cell)
|
||||
override.custom_cell_coords = coords
|
||||
return override
|
||||
|
||||
func get_whole_room(at: Vector3i) -> Array[Vector3i]:
|
||||
var room: Array[Vector3i]
|
||||
|
||||
var to_check: Array[Vector2i] = [Vector2i(at.x, at.y)]
|
||||
var checked: Array[Vector2i]
|
||||
|
||||
while not to_check.is_empty():
|
||||
var p: Vector2i = to_check.pop_back()
|
||||
checked.append(p)
|
||||
|
||||
var coords := Vector3i(p.x, p.y, at.z)
|
||||
if coords in cells:
|
||||
room.append(coords)
|
||||
for i in 4:
|
||||
if cells[coords].borders[i] == -1:
|
||||
var p2: Vector2i = p + FWD[i]
|
||||
if not p2 in to_check and not p2 in checked:
|
||||
to_check.append(p2)
|
||||
|
||||
return room
|
||||
|
||||
func get_cells_assigned_to(map: String) -> Array[Vector3i]:
|
||||
if map in scene_overrides:
|
||||
map = scene_overrides[map]
|
||||
|
||||
var ret: Array[Vector3i]
|
||||
ret.assign(assigned_scenes.get(map, []))
|
||||
return ret
|
||||
|
||||
func get_assigned_scene_at(coords: Vector3i) -> String:
|
||||
var cell := get_cell_at(coords)
|
||||
if cell:
|
||||
return cell.get_assigned_scene()
|
||||
else:
|
||||
return ""
|
||||
|
||||
func erase_cell(coords: Vector3i):
|
||||
var assigned_scene: String = cells[coords].assigned_scene
|
||||
assigned_scenes.erase(assigned_scene)
|
||||
|
||||
cells.erase(coords)
|
||||
|
||||
for group in cell_groups.values():
|
||||
group.erase(coords)
|
||||
@ -1,146 +0,0 @@
|
||||
@tool
|
||||
## Resource that defines the cell appearance.
|
||||
##
|
||||
## MapTheme is assigned in MetSys Settings and defines the cell appearance when using [method MetroidvaniaSystem.draw_cell]. It has a few subtypes: shape can be either square or rectangular and borders can be either shared or not. Some properties are only available for certain theme subtypes. Check the Map Theme section in README for some more detailed information.
|
||||
extends Resource
|
||||
class_name MapTheme
|
||||
|
||||
const SQUARE_BORDERS = ["wall", "passage", "separator", "borders"]
|
||||
const RECTANGLE_BORDERS = ["vertical_wall", "horizontal_wall", "vertical_passage", "horizontal_passage", "vertical_separator", "horizontal_separator", "vertical_borders", "horizontal_borders"]
|
||||
const DEFAULT_CORNERS = ["inner_corner", "outer_corner"]
|
||||
const SHARED_CORNERS = ["u_corner", "l_corner", "t_corner", "cross_corner"]
|
||||
|
||||
## The cell's center texture. The size of all other textures depends on this one. It can be square or rectangular and the shape affects some properties. The texture should be grayscale (preferrably white).
|
||||
@export var center_texture: Texture2D:
|
||||
set(ct):
|
||||
center_texture = ct
|
||||
var new_rectangle := center_texture.get_width() != center_texture.get_height()
|
||||
if new_rectangle != rectangle:
|
||||
rectangle = new_rectangle
|
||||
notify_property_list_changed()
|
||||
|
||||
## The texture drawn in empty space. Optional.
|
||||
@export var empty_space_texture: Texture2D
|
||||
|
||||
## The scene that appears at player location after using [method MetroidvaniaSystem.add_player_location]. Must have a [Node2D] root. Optional, but [method MetroidvaniaSystem.add_player_location] can't be used if the scene is not provided.
|
||||
@export var player_location_scene: PackedScene
|
||||
## If [code]true[/code], the player location is displayed accurately inside the cell. If [code]false[/code], the location marker always appears at the center of the cell.
|
||||
@export var show_exact_player_location: bool
|
||||
## Determines how mapped (unexplored) cells are displayed. Use Preview Mapped option in Map Viewer to preview this style.
|
||||
@export_flags("Center", "Outline", "Borders", "Symbol") var mapped_display := 3
|
||||
|
||||
## If [code]true[/code], cell borders are drawn between the cells instead of inside them. This setting has a major effect on the theme.
|
||||
@export var use_shared_borders: bool:
|
||||
set(usb):
|
||||
if usb != use_shared_borders:
|
||||
use_shared_borders = usb
|
||||
notify_property_list_changed()
|
||||
|
||||
@export_group("Colors")
|
||||
## Default modulation of the center texture.
|
||||
@export var default_center_color: Color
|
||||
## Modulation of the center texture when the cell is only mapped. Usually this color is gray.
|
||||
@export var mapped_center_color: Color
|
||||
## Default modulation of the cell's border textures.
|
||||
@export var default_border_color: Color
|
||||
## Modulation of the cell's border textures when the cell is only mapped.
|
||||
@export var mapped_border_color: Color
|
||||
|
||||
@export_group("Symbols")
|
||||
## The list of symbols that can be assigned to cells, either from editor, using [method MetroidvaniaSystem.add_custom_marker] or from storable objects.
|
||||
@export var symbols: Array[Texture2D]
|
||||
## The symbol for discovered, but not collected item (or any other object). See [method MetroidvaniaSystem.add_storable_object_with_marker]. Must be within [member symbols] indicies. [code]-1[/code] means no symbol will be assigned automatically.
|
||||
@export var uncollected_item_symbol := -1
|
||||
## The symbol for collected item (or any other object). See [method MetroidvaniaSystem.store_object]. Must be within [member symbols] indicies. [code]-1[/code] means no symbol will be assigned automatically.
|
||||
@export var collected_item_symbol := -1
|
||||
|
||||
@export_group("Border Textures")
|
||||
## The texture used for wall borders. Must be oriented vertically facing towards east. Height should match [member center_texture].
|
||||
@export var wall: Texture2D
|
||||
## The texture used for passage borders. Same rules as [member wall].
|
||||
@export var passage: Texture2D
|
||||
## The texture used for separator, i.e. fake border that draws between cells with no border. Same rules as [member wall]. Optional.
|
||||
@export var separator: Texture2D
|
||||
## A set of alternative borders that can be assigned to the cell (either walls or passages). Same rules as [member wall].
|
||||
@export var borders: Array[Texture2D]
|
||||
|
||||
## Same as [member wall], but only available when the [member center_texture] is a rectangle.
|
||||
@export var vertical_wall: Texture2D
|
||||
## Same as [member wall], but only available when the [member center_texture] is a rectangle. It should still be oriented horizontally and height should match center texture's width.
|
||||
@export var horizontal_wall: Texture2D
|
||||
## Same as [member passage], but only available when the [member center_texture] is a rectangle.
|
||||
@export var vertical_passage: Texture2D
|
||||
## Same as [member passage], but only available when the [member center_texture] is a rectangle. It should still be oriented horizontally and height should match center texture's width.
|
||||
@export var horizontal_passage: Texture2D
|
||||
## Same as [member separator], but only available when the [member center_texture] is a rectangle.
|
||||
@export var vertical_separator: Texture2D
|
||||
## Same as [member separator], but only available when the [member center_texture] is a rectangle. It should still be oriented horizontally and height should match center texture's width.
|
||||
@export var horizontal_separator: Texture2D
|
||||
## Same as [member borders], but only available when the [member center_texture] is a rectangle.
|
||||
@export var vertical_borders: Array[Texture2D]
|
||||
## Same as [member borders], but only available when the [member center_texture] is a rectangle. It should still be oriented horizontally and height should match center texture's width.
|
||||
@export var horizontal_borders: Array[Texture2D]
|
||||
|
||||
@export_group("Corner Textures")
|
||||
## The texture that draws at room's outer corners. It draws above borders.
|
||||
@export var outer_corner: Texture2D
|
||||
## The texture that draws at room's inner corners. Only appears in concave rooms. It draws above borders.
|
||||
@export var inner_corner: Texture2D
|
||||
|
||||
## Only available when [member use_shared_borders] is enabled. Corner of a single border that divides U-shaped room.
|
||||
@export var u_corner: Texture2D
|
||||
## Only available when [member use_shared_borders] is enabled. Corner of 2 perpendicular borders.
|
||||
@export var l_corner: Texture2D
|
||||
## Only available when [member use_shared_borders] is enabled. Corner of 3 borders connecting at one point.
|
||||
@export var t_corner: Texture2D
|
||||
## Only available when [member use_shared_borders] is enabled. Corner of 4 borders.
|
||||
@export var cross_corner: Texture2D
|
||||
|
||||
var rectangle: bool
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if rectangle:
|
||||
if property.name in SQUARE_BORDERS:
|
||||
property.usage = 0
|
||||
return
|
||||
else:
|
||||
if property.name in RECTANGLE_BORDERS:
|
||||
property.usage = 0
|
||||
return
|
||||
|
||||
if use_shared_borders:
|
||||
if property.name in DEFAULT_CORNERS:
|
||||
property.usage = 0
|
||||
return
|
||||
else:
|
||||
if property.name in SHARED_CORNERS:
|
||||
property.usage = 0
|
||||
return
|
||||
|
||||
func is_unicorner() -> bool:
|
||||
if use_shared_borders:
|
||||
return l_corner == u_corner and t_corner == u_corner and cross_corner == u_corner
|
||||
else:
|
||||
return inner_corner == outer_corner
|
||||
|
||||
func check_for_changes(prev_state: Array) -> Array[String]:
|
||||
var new_state: Array
|
||||
var changed: Array[String]
|
||||
|
||||
var properties := get_property_list()
|
||||
for property in properties:
|
||||
new_state.append(get(property.name))
|
||||
if changed:
|
||||
continue
|
||||
|
||||
var idx := new_state.size() - 1
|
||||
if idx >= prev_state.size():
|
||||
continue
|
||||
|
||||
if new_state[idx] != prev_state[idx]:
|
||||
changed.append(property.name)
|
||||
|
||||
if not changed.is_empty() or prev_state.size() != new_state.size():
|
||||
prev_state.assign(new_state)
|
||||
|
||||
return changed
|
||||
@ -1,135 +0,0 @@
|
||||
extends Control
|
||||
|
||||
@onready var map_overlay: Control = $MapOverlay
|
||||
@onready var map: Control = %Map
|
||||
@onready var current_layer_spinbox: SpinBox = %CurrentLayer
|
||||
@onready var status_label: Label = %StatusLabel
|
||||
|
||||
const NULL_VECTOR2I = Vector2i(-9999999, -9999999)
|
||||
var plugin: EditorPlugin
|
||||
|
||||
var drag_from: Vector2i = NULL_VECTOR2I
|
||||
var view_drag: Vector4
|
||||
var map_offset := Vector2i(10, 10)
|
||||
|
||||
var current_layer: int
|
||||
var force_mapped: bool
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if owner:
|
||||
plugin = owner.plugin
|
||||
|
||||
func _ready() -> void:
|
||||
map.draw.connect(_on_map_draw)
|
||||
map_overlay.mouse_exited.connect(status_label.hide)
|
||||
map_overlay.gui_input.connect(_on_overlay_input)
|
||||
map_overlay.draw.connect(_on_overlay_draw)
|
||||
|
||||
current_layer_spinbox.value_changed.connect(on_layer_changed)
|
||||
%RecenterButton.pressed.connect(on_recenter_view)
|
||||
|
||||
status_label.hide()
|
||||
await get_tree().process_frame
|
||||
update_map_position()
|
||||
map.size = MetSys.CELL_SIZE * 200
|
||||
|
||||
var refresh := func():
|
||||
update_map_position()
|
||||
on_layer_changed(current_layer)
|
||||
|
||||
MetSys.settings.theme_changed.connect(refresh)
|
||||
MetSys.theme_modified.connect(refresh.unbind(1))
|
||||
|
||||
func get_cursor_pos() -> Vector2i:
|
||||
var pos := (map_overlay.get_local_mouse_position() - MetSys.CELL_SIZE / 2).snapped(MetSys.CELL_SIZE) / MetSys.CELL_SIZE as Vector2i - map_offset
|
||||
return pos
|
||||
|
||||
func on_layer_changed(l: int):
|
||||
current_layer = l
|
||||
map.queue_redraw()
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
func on_recenter_view() -> void:
|
||||
map_offset = Vector2i(10, 10)
|
||||
map_overlay.queue_redraw()
|
||||
update_map_position()
|
||||
|
||||
func _on_overlay_input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
if view_drag != Vector4():
|
||||
if event.position.x >= map_overlay.size.x:
|
||||
map_overlay.warp_mouse(Vector2(event.position.x - map_overlay.size.x, event.position.y))
|
||||
view_drag.x -= map_overlay.size.x
|
||||
elif event.position.x < 0:
|
||||
map_overlay.warp_mouse(Vector2(map_overlay.size.x + event.position.x, event.position.y))
|
||||
view_drag.x += map_overlay.size.x
|
||||
|
||||
if event.position.y >= map_overlay.size.y:
|
||||
map_overlay.warp_mouse(Vector2(event.position.x, event.position.y - map_overlay.size.y))
|
||||
view_drag.y -= map_overlay.size.y
|
||||
elif event.position.y < 0:
|
||||
map_overlay.warp_mouse(Vector2(event.position.x, map_overlay.size.y + event.position.y))
|
||||
view_drag.y += map_overlay.size.y
|
||||
|
||||
map_offset = Vector2(view_drag.z, view_drag.w) + (map_overlay.get_local_mouse_position() - Vector2(view_drag.x, view_drag.y)) / MetSys.CELL_SIZE
|
||||
update_map_position()
|
||||
map_overlay.queue_redraw()
|
||||
_on_drag()
|
||||
else:
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
_update_status_label()
|
||||
|
||||
if event is InputEventMouseButton:
|
||||
if event.button_index == MOUSE_BUTTON_MIDDLE:
|
||||
if event.pressed:
|
||||
view_drag.x = map_overlay.get_local_mouse_position().x
|
||||
view_drag.y = map_overlay.get_local_mouse_position().y
|
||||
view_drag.z = map_offset.x
|
||||
view_drag.w = map_offset.y
|
||||
else:
|
||||
view_drag = Vector4()
|
||||
|
||||
func _on_drag():
|
||||
pass
|
||||
|
||||
func _update_status_label():
|
||||
status_label.show()
|
||||
status_label.text = str(get_cursor_pos())
|
||||
|
||||
func _unhandled_key_input(event: InputEvent) -> void:
|
||||
if not visible:
|
||||
return
|
||||
|
||||
if event is InputEventKey and event.pressed:
|
||||
if event.physical_keycode == KEY_Q:
|
||||
current_layer_spinbox.value -= 1
|
||||
accept_event()
|
||||
elif event.physical_keycode == KEY_E:
|
||||
current_layer_spinbox.value += 1
|
||||
accept_event()
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_THEME_CHANGED:
|
||||
if map_overlay:
|
||||
map_overlay.queue_redraw()
|
||||
|
||||
func _on_map_draw() -> void:
|
||||
if not plugin:
|
||||
return
|
||||
|
||||
MetroidvaniaSystem.RoomDrawer.force_mapped = force_mapped
|
||||
for x in range(-100, 100):
|
||||
for y in range(-100, 100):
|
||||
MetSys.draw_cell(map, Vector2i(x, y) + Vector2i(100, 100), Vector3i(x, y, current_layer), true, false)
|
||||
|
||||
if MetSys.settings.theme.use_shared_borders:
|
||||
MetSys.draw_shared_borders()
|
||||
|
||||
MetroidvaniaSystem.RoomDrawer.force_mapped = false
|
||||
|
||||
func _on_overlay_draw() -> void:
|
||||
MetSys.draw_custom_elements(map_overlay, Rect2i(-map_offset, map_overlay.size / MetSys.CELL_SIZE + Vector2.ONE), Vector2(), current_layer)
|
||||
|
||||
func update_map_position():
|
||||
map.position = Vector2(map_offset - Vector2i(100, 100)) * MetSys.CELL_SIZE
|
||||
@ -1,356 +0,0 @@
|
||||
@tool
|
||||
## The class behind the MetSys singleton. It provides almost all of the public API of the addon.
|
||||
##
|
||||
## MetroidvaniaSystem class has various methods for interacting with various MetSys sub-systems at runtime. All methods and members with a description are "public", while anything that doesn't have a description is supposed to be used only internally. There are a couple of sub-classes that you can use; you can access their documentation from the methods that return them.
|
||||
class_name MetroidvaniaSystem extends Node
|
||||
|
||||
const DEFAULT_SYMBOL = -99
|
||||
enum { DISPLAY_CENTER = 1, DISPLAY_OUTLINE = 2, DISPLAY_BORDERS = 4, DISPLAY_SYMBOLS = 8 }
|
||||
|
||||
const Settings = preload("res://addons/MetroidvaniaSystem/Scripts/Settings.gd")
|
||||
const SaveData = preload("res://addons/MetroidvaniaSystem/Scripts/SaveData.gd")
|
||||
const MapData = preload("res://addons/MetroidvaniaSystem/Scripts/MapData.gd")
|
||||
const MapBuilder = preload("res://addons/MetroidvaniaSystem/Scripts/MapBuilder.gd")
|
||||
const RoomInstance = preload("res://addons/MetroidvaniaSystem/Scripts/RoomInstance.gd")
|
||||
const RoomDrawer = preload("res://addons/MetroidvaniaSystem/Scripts/RoomDrawer.gd")
|
||||
const CustomElementManager = preload("res://addons/MetroidvaniaSystem/Scripts/CustomElementManager.gd")
|
||||
|
||||
enum { R, ## Right border.
|
||||
D, ## Bottom border.
|
||||
L, ## Left border.
|
||||
U, ## Top border.
|
||||
}
|
||||
|
||||
var settings: Settings
|
||||
## The size of a map cell. Automatically set to the size of [member MapTheme.center_texture]. Read only.
|
||||
var CELL_SIZE: Vector2
|
||||
|
||||
var map_data: MapData
|
||||
var save_data: SaveData
|
||||
|
||||
var last_player_position := Vector3i.MAX
|
||||
var exact_player_position: Vector2
|
||||
var current_room: RoomInstance
|
||||
|
||||
## The current layer, for the purpose of visiting with [method set_player_position] among other things. MetSys does not modify it automatically in any way. Changing it emits [signal cell_changed] signal.
|
||||
var current_layer: int:
|
||||
set(layer):
|
||||
if layer == current_layer:
|
||||
return
|
||||
|
||||
current_layer = layer
|
||||
cell_changed.emit(Vector3i(last_player_position.x, last_player_position.y, current_layer))
|
||||
|
||||
var _meta_list: Array[StringName]
|
||||
|
||||
## Emitted when the player crosses a cell boundary and visits another cell as a result of [method set_player_position]. The new cell coordinates are provided as an argument.
|
||||
signal cell_changed(new_cell: Vector3i)
|
||||
## Emitted when the player enters a new room, i.e. using [method set_player_position] results in a cell that has a different assigned scene. The new scene is provided as an argument, you can use it to easily make room transitions.
|
||||
signal room_changed(new_room: String)
|
||||
|
||||
## Emitted when a map cell was added, deleted or modified. This includes cell overrides and MapBuilder updates.
|
||||
signal map_updated
|
||||
signal room_assign_updated
|
||||
signal theme_modified(changes: Array[String])
|
||||
|
||||
func _enter_tree() -> void:
|
||||
var settings_path := "res://setting/MetSysSettings.tres"
|
||||
if ProjectSettings.has_setting("metroidvania_system/settings_file"):
|
||||
settings_path = ProjectSettings.get_setting("metroidvania_system/settings_file")
|
||||
else:
|
||||
ProjectSettings.set_setting("metroidvania_system/settings_file", settings_path)
|
||||
|
||||
if ResourceLoader.exists(settings_path):
|
||||
settings = load(settings_path)
|
||||
else:
|
||||
settings = Settings.new()
|
||||
settings.theme = load("res://addons/MetroidvaniaSystem/Themes/Exquisite/Theme.tres")
|
||||
ResourceSaver.save(settings, settings_path)
|
||||
|
||||
settings.theme_changed.connect(_update_theme)
|
||||
_update_theme()
|
||||
|
||||
map_data = MapData.new()
|
||||
map_data.load_data()
|
||||
|
||||
func _update_theme():
|
||||
CELL_SIZE = settings.theme.center_texture.get_size()
|
||||
map_updated.emit()
|
||||
|
||||
func _ready() -> void:
|
||||
set_physics_process(false)
|
||||
|
||||
## Returns a [Dictionary] containing the MetSys' runtime data, like discovered cells or stored objects. You need to serialize it yourself, e.g. using [method FileAccess.store_var].
|
||||
func get_save_data() -> Dictionary:
|
||||
return save_data.get_data()
|
||||
|
||||
## Pass it the data from [method get_save_data] to restore the saved state of MetSys. Calling this method with the default parameter will clear the data, allowing to start new game session.
|
||||
func set_save_data(data := {}):
|
||||
save_data = SaveData.new()
|
||||
save_data.set_data(data)
|
||||
|
||||
func visit_cell(coords: Vector3i):
|
||||
save_data.explore_cell(coords)
|
||||
|
||||
var previous_map := map_data.get_assigned_scene_at(Vector3i(last_player_position.x, last_player_position.y, current_layer))
|
||||
var new_map := map_data.get_assigned_scene_at(coords)
|
||||
if not new_map.is_empty() and not previous_map.is_empty() and new_map != previous_map:
|
||||
room_changed.emit(new_map)
|
||||
|
||||
## Returns [code]true[/code] if the call was discovered, either mapped (if [param include_mapped] is [code]true[/code]) or explored.
|
||||
func is_cell_discovered(coords: Vector3i, include_mapped := true) -> bool:
|
||||
if RoomDrawer.force_mapped:
|
||||
return include_mapped
|
||||
|
||||
if not save_data:
|
||||
return true
|
||||
|
||||
var discovered := save_data.is_cell_discovered(coords)
|
||||
return discovered == 2 or include_mapped and discovered == 1
|
||||
|
||||
## Returns the ratio of explored cells vs all cells. Cells created with MapBuilder are also included.
|
||||
func get_explored_ratio(layer := -1):
|
||||
var all: float
|
||||
var discovered: float
|
||||
|
||||
for coords in map_data.cells:
|
||||
if layer != -1 and coords.z != layer:
|
||||
continue
|
||||
|
||||
all += 1
|
||||
discovered += int(is_cell_discovered(coords, false))
|
||||
|
||||
return discovered / all
|
||||
|
||||
## Sets the position of the player to be tracked by MetSys. Automatically explores cells when crossing cell boundary and emits [signal cell_changed] and [signal room_changed] signals.
|
||||
## [br][br][param position] should be position in the room's coordinates, i.e. with [code](0, 0)[/code] being the top-left corner of the scene assigned to the room (which in most cases simply equals to global position of the player).
|
||||
func set_player_position(position: Vector2):
|
||||
exact_player_position = position
|
||||
var player_pos := Vector2i((position / settings.in_game_cell_size).floor()) + current_room.min_cell
|
||||
var player_pos_3d := Vector3i(player_pos.x, player_pos.y, current_layer)
|
||||
if player_pos_3d != last_player_position:
|
||||
visit_cell(Vector3i(player_pos.x, player_pos.y, current_layer))
|
||||
last_player_position = player_pos_3d
|
||||
cell_changed.emit(player_pos_3d)
|
||||
|
||||
## Discovers (maps) the cell at the given [param coords]. Fails if the cell does not exist.
|
||||
func discover_cell(coords: Vector3i):
|
||||
assert(coords in map_data.cells)
|
||||
|
||||
save_data.discover_cell(coords)
|
||||
map_updated.emit()
|
||||
|
||||
## Discovers (maps) all cells that belong to the specified group. The group ID must exist (i.e. have at least a single cell with it assigned).
|
||||
func discover_cell_group(group_id: int):
|
||||
assert(group_id in map_data.cell_groups)
|
||||
|
||||
for coords in map_data.cell_groups[group_id]:
|
||||
save_data.discover_cell(coords)
|
||||
|
||||
map_updated.emit()
|
||||
|
||||
## Assigns a custom symbol to the given cell that will override the symbol set in the editor. You can assign any number of symbols and the one with the highest ID will be displayed. [param symbol_id] must be within the symbols defined in [member MapTheme.symbols].
|
||||
func add_custom_marker(coords: Vector3i, symbol_id: int):
|
||||
assert(symbol_id >= 0 and symbol_id < mini(MetSys.settings.theme.symbols.size(), 63))
|
||||
save_data.add_custom_marker(coords, symbol_id)
|
||||
|
||||
## Removes a custom symbol assigned in [method add_custom_marker]. Does nothing if the given [param symbol_id] was not assigned to the cell.
|
||||
func remove_custom_marker(coords: Vector3i, symbol_id: int):
|
||||
save_data.remove_custom_marker(coords, symbol_id)
|
||||
|
||||
## Registers a storable object, i.e. object whose state is supposed to be saved, and automatically leaves a marker on the map. Useful for collectibles.
|
||||
## [br][br][param object] is the object that needs storing, [param stored_callback] is the callback that will be automatically called by this method when the object was already stored (defaults to [method Node.queue_free] for nodes). [param map_marker] is the ID of the symbol that will be added to the cell. If no symbol is provided, [member MapTheme.uncollected_item_symbol] will be used.
|
||||
## [br][br][b]Note:[/b] [method get_object_id] is used to determine object's ID. You can make the same object appear in multiple places if you assign them custom ID (e.g. to make a collectible that changes its location after an event). [method get_object_coords] is used to determine where the marker should appear.
|
||||
func register_storable_object_with_marker(object: Object, stored_callback := Callable(), map_marker := DEFAULT_SYMBOL) -> bool:
|
||||
if stored_callback.is_null():
|
||||
if object is Node:
|
||||
stored_callback = Callable(object, &"queue_free")
|
||||
elif not object is RefCounted:
|
||||
stored_callback = Callable(object, &"free")
|
||||
|
||||
if save_data.is_object_stored(object):
|
||||
stored_callback.call()
|
||||
return true
|
||||
|
||||
if map_marker == DEFAULT_SYMBOL:
|
||||
map_marker = settings.theme.uncollected_item_symbol
|
||||
object.set_meta(&"map_marker", map_marker)
|
||||
elif map_marker > -1:
|
||||
object.set_meta(&"map_marker", map_marker)
|
||||
|
||||
if save_data.register_storable_object(object) and map_marker > -1:
|
||||
save_data.add_custom_marker(get_object_coords(object), map_marker)
|
||||
|
||||
return false
|
||||
|
||||
## Same as [method register_storable_object_with_marker], but doesn't assign any marker. Useful for things like buttons, breakable walls etc.
|
||||
func register_storable_object(object: Object, stored_callback := Callable()) -> bool:
|
||||
return register_storable_object_with_marker(object, stored_callback, -1)
|
||||
|
||||
## Stores the given object. Using [method register_storable_object] aftewards will call its callback. Note that this method simply registers the object as stored, it does not free it nor anything. [param map_marker] is the ID of the symbol that will be added to the cell. If no symbol is provided, [member MapTheme.collected_item_symbol] will be used.
|
||||
## [br][br][b]Note:[/b] The marker will be ignored if the object was not registered with a marker.
|
||||
func store_object(object: Object, map_marker := DEFAULT_SYMBOL):
|
||||
save_data.store_object(object)
|
||||
if object.has_meta(&"map_marker"):
|
||||
save_data.remove_custom_marker(get_object_coords(object), object.get_meta(&"map_marker"))
|
||||
else:
|
||||
map_marker = -1
|
||||
|
||||
if map_marker == DEFAULT_SYMBOL:
|
||||
map_marker = settings.theme.collected_item_symbol
|
||||
|
||||
if map_marker > -1:
|
||||
save_data.add_custom_marker(get_object_coords(object), map_marker)
|
||||
|
||||
## Returns the game-unique ID of an object. It's used to identify instances of objects in the game's world. It can be used manually when storable objects are insufficient for whatever reason.
|
||||
## [br][br]The ID is first determined from [code]object_id[/code] metadata (see [method Object.set_meta]), then using [code]_get_object_id()[/code] method and finally using a heuristic based on the current scene and node's path in scene. If the [param object] is not a [Node] and no custom ID is provided, this method returns empty string.
|
||||
func get_object_id(object: Object) -> String:
|
||||
if object.has_meta(&"object_id"):
|
||||
return object.get_meta(&"object_id")
|
||||
elif object.has_method(&"_get_object_id"):
|
||||
var id: String = object._get_object_id()
|
||||
object.set_meta(&"object_id", id)
|
||||
return id
|
||||
elif object is Node:
|
||||
var id := str(object.owner.scene_file_path.get_file().get_basename(), "/", object.get_parent().name if object.get_parent() != object.owner else ".", "/", object.name)
|
||||
object.set_meta(&"object_id", id)
|
||||
return id
|
||||
return ""
|
||||
|
||||
## Returns the map coordinates of an object on the scene. It can be used e.g. to place custom markers for non-storable objects.
|
||||
## [br][br]Similar to [method get_object_id], the method will first use [code]object_coords[/code] metadata and [code]_get_object_coords()[/code] method. If the [param object] is a [Node], the top-left coordinate of the current scene's location on map will be used. If the object is a [CanvasItem], it will return a precise coordinate based on the object's position on the scene.
|
||||
func get_object_coords(object: Object) -> Vector3i:
|
||||
if object.has_meta(&"object_coords"):
|
||||
return object.get_meta(&"object_coords")
|
||||
elif object.has_method(&"_get_object_coords"):
|
||||
var coords: Vector3i = object._get_object_coords()
|
||||
object.set_meta(&"object_coords", coords)
|
||||
return coords
|
||||
elif object is Node:
|
||||
var room_name: String = object.owner.scene_file_path.trim_prefix(settings.map_root_folder)
|
||||
room_name = MetSys.map_data.scene_overrides.get(room_name, room_name)
|
||||
assert(room_name in map_data.assigned_scenes)
|
||||
|
||||
var coords: Vector3i = map_data.assigned_scenes[room_name].front()
|
||||
for vec in map_data.assigned_scenes[room_name]:
|
||||
coords.x = mini(coords.x, vec.x)
|
||||
coords.y = mini(coords.y, vec.y)
|
||||
|
||||
if object is CanvasItem:
|
||||
var position: Vector2 = object.position / settings.in_game_cell_size
|
||||
coords.x += int(position.x)
|
||||
coords.y += int(position.y)
|
||||
|
||||
object.set_meta(&"object_coords", coords)
|
||||
return coords
|
||||
return Vector3i()
|
||||
|
||||
## Translates map coordinates to 2D pixel coordinates. Can be used for custom drawing on the map.
|
||||
## [br][br][param relative] allows to specify precise position inside the cell, with [code](0.5, 0.5)[/code] being the cell's center. [param base_offset] is an additional offset in pixels.
|
||||
func get_cell_position(coords: Vector2i, relative := Vector2(0.5, 0.5), base_offset := Vector2()) -> Vector2:
|
||||
return base_offset + (Vector2(coords) + relative) * MetSys.CELL_SIZE
|
||||
|
||||
## Returns a cell override at position [param coords]. If it doesn't exist, it will be created (unless [param auto_create] is [code]false[/code]). A cell must exist at the given [param coords].
|
||||
## [br][br]Cell overrides allow to modify any cell's data at runtime. They are included with the data returned in [method get_save_data]. Creating an override and doing any modifications with emit [signal map_updated]. The signal emitted with modifications is deferred, i.e. multiple modifications will do only a single emission, at the end of the current frame.
|
||||
## [br][br]Click this method's return value for more info.
|
||||
func get_cell_override(coords: Vector3i, auto_create := true) -> MapData.CellOverride:
|
||||
var cell := map_data.get_cell_at(coords)
|
||||
assert(cell, "Can't override non-existent cell")
|
||||
|
||||
var existing := cell.get_override()
|
||||
if existing:
|
||||
return existing
|
||||
elif auto_create:
|
||||
return save_data.add_cell_override(cell)
|
||||
else:
|
||||
push_error("No override found at %s" % coords)
|
||||
return null
|
||||
|
||||
## Returns an override for the first cell assigned to the given [param group_id]. The group ID must exist (i.e. have at least a single cell with it assigned).
|
||||
## [br][br]Useful for applying override to a group.
|
||||
func get_cell_override_from_group(group_id: int, auto_create := true) -> MapData.CellOverride:
|
||||
assert(group_id in map_data.cell_groups)
|
||||
return get_cell_override(map_data.cell_groups[group_id].front(), auto_create)
|
||||
|
||||
## Removes an override created with [method get_cell_override], reverting the cell to its original appearance, and emits [signal map_updated] signal. Does nothing if the override didn't exist.
|
||||
## [br][br][b]Note:[/b] If the override was created with MapBuilder, use the [code]destroy()[/code] method instead.
|
||||
func remove_cell_override(coords: Vector3i):
|
||||
var cell = MetSys.map_data.get_cell_at(coords)
|
||||
assert(cell, "Can't remove override of non-existent cell")
|
||||
if save_data.remove_cell_override(cell):
|
||||
map_updated.emit()
|
||||
|
||||
## Returns a MapBuilder object. It can be used to create custom cells at runtime (for procedural maps etc.). The created cells can be customized with overrides, which are created automatically.
|
||||
## [br][br]Click this method's return value for more info.
|
||||
func get_map_builder() -> MapBuilder:
|
||||
return MapBuilder.new()
|
||||
|
||||
## Draws a single map cell. [param canvas_item] is the [CanvasItem] responsible for drawing, [param offset] is the drawing offset in map coordinates. [param coords] is the coordinate of the map cell that's going to be drawn (does not need to exist). If [param skip_empty] is [code]false[/code], [member MapTheme.empty_space_texture] will be drawn in place of empty cells, if available. If [param use_save_data] is [code]true[/code], the discovered rooms data will be used for drawing the map.
|
||||
## [br][br]Example of drawing a 3x3 minimap where center is at [code]current_cell[/code]:
|
||||
## [codeblock]
|
||||
## for x in range(-1, 2):
|
||||
## for y in range(-1, 2):
|
||||
## MetSys.draw_cell(self, Vector2i(x + 1, y + 1), Vector3i(current_cell.x + x, current_cell.y + y, MetSys.current_layer))
|
||||
## [/codeblock]
|
||||
## [b]Note:[/b] Drawing a cell is an expensive operation, so avoid performing it too often. You can use the [signal map_updated] signal to only redraw when necessary.
|
||||
func draw_cell(canvas_item: CanvasItem, offset: Vector2, coords: Vector3i, skip_empty := false, use_save_data := true):
|
||||
RoomDrawer.draw(canvas_item, offset, coords, skip_empty, map_data, save_data if use_save_data else null)
|
||||
|
||||
## Performs a second drawing pass after all cells were drawn, for drawing the shared borders. Only required if [member MapTheme.use_shared_borders] is enabled.
|
||||
func draw_shared_borders():
|
||||
RoomDrawer.draw_shared_borders()
|
||||
|
||||
## Performs another drawing pass after all cells were draw, for drawing the custom elements. Only required if [code]custom_element_script[/code] is assigned in MetSyS Settings.
|
||||
## [br][br][param canvas_item] is the [CanvasItem] responsible for drawing. [param rect] is the portion of the world map that's going to be drawn. All elements whose rects intersect with this rectangle will be drawn. [param drawing_offset] is an offset in pixels, in case your map has a margin etc. You can draw elements from another layer or leave default [param layer] to use the current one.
|
||||
func draw_custom_elements(canvas_item: CanvasItem, rect: Rect2i, drawing_offset := Vector2(), layer := current_layer):
|
||||
if not settings.custom_elements or map_data.custom_elements.is_empty():
|
||||
return
|
||||
RoomDrawer.draw_custom_elements(canvas_item, map_data.custom_elements, drawing_offset, rect, layer)
|
||||
|
||||
## Creates an instance of [member MapTheme.player_location_scene] and adds it as a child of the specified [param canvas_item]. The location scene will be moved to the player's location, respecting [member MapTheme.show_exact_player_location]. [param offset] is the offset in pixels for drawing the location. Use it if your map doesn't use [code](0, 0)[/code] as origin point.
|
||||
## [br][br][b]Note:[/b] The scene automatically disables processing if it's not visible, so you don't need to worry about having animations and such. They will not run in the background.
|
||||
func add_player_location(canvas_item: CanvasItem, offset := Vector2()) -> Node2D:
|
||||
var location_instance: Node2D = settings.theme.player_location_scene.instantiate()
|
||||
location_instance.set_script(load("res://addons/MetroidvaniaSystem/Scripts/PlayerLocationInstance.gd"))
|
||||
location_instance.offset = offset
|
||||
canvas_item.add_child(location_instance)
|
||||
return location_instance
|
||||
|
||||
## Returns the current cell coordinates of the player, as determined from [method set_player_position].
|
||||
func get_current_coords() -> Vector3i:
|
||||
return Vector3i(last_player_position.x, last_player_position.y, current_layer)
|
||||
|
||||
## Same as [method get_current_coords], but does not include layer.
|
||||
func get_current_flat_coords() -> Vector2i:
|
||||
return Vector2i(last_player_position.x, last_player_position.y)
|
||||
|
||||
## Returns the currently active RoomInstance object.
|
||||
## [br][br]Click this method's return value for more info.
|
||||
func get_current_room_instance() -> RoomInstance:
|
||||
if is_instance_valid(current_room):
|
||||
return current_room
|
||||
return null
|
||||
|
||||
## Returns the name of the current room, or empty string if there is no active RoomInstance. Use together with [method get_full_room_path] to get the full path.
|
||||
func get_current_room_name() -> String:
|
||||
if current_room:
|
||||
return current_room.room_name
|
||||
else:
|
||||
return ""
|
||||
|
||||
## Returns the full path to the provided [param room_name] scene. This method assumes that the scene is inside the base map folder.
|
||||
func get_full_room_path(room_name: String) -> String:
|
||||
return settings.map_root_folder.path_join(room_name)
|
||||
|
||||
func _add_meta(meta: StringName, value: Variant):
|
||||
set_meta(meta, value)
|
||||
|
||||
if _meta_list.is_empty():
|
||||
_cleanup_meta.call_deferred()
|
||||
|
||||
_meta_list.append(meta)
|
||||
|
||||
func _cleanup_meta():
|
||||
for meta in _meta_list:
|
||||
remove_meta(meta)
|
||||
_meta_list.clear()
|
||||
@ -1,22 +0,0 @@
|
||||
extends Node2D
|
||||
|
||||
var offset: Vector2
|
||||
var exact: bool
|
||||
|
||||
func _ready() -> void:
|
||||
exact = MetSys.settings.theme.show_exact_player_location
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_VISIBILITY_CHANGED:
|
||||
if is_visible_in_tree():
|
||||
process_mode = Node.PROCESS_MODE_INHERIT
|
||||
else:
|
||||
process_mode = Node.PROCESS_MODE_DISABLED
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
var last_player_position_2d := Vector2(MetSys.last_player_position.x, MetSys.last_player_position.y)
|
||||
var player_position := last_player_position_2d * MetSys.CELL_SIZE + MetSys.CELL_SIZE / 2
|
||||
if exact:
|
||||
player_position += (MetSys.exact_player_position / MetSys.settings.in_game_cell_size).posmod(1) * MetSys.CELL_SIZE - MetSys.CELL_SIZE * 0.5
|
||||
|
||||
position = player_position + offset
|
||||
@ -1,446 +0,0 @@
|
||||
extends RefCounted
|
||||
|
||||
static var force_mapped: bool
|
||||
|
||||
static func draw(canvas_item: CanvasItem, offset: Vector2, coords: Vector3i, skip_empty: bool, map_data: MetroidvaniaSystem.MapData, save_data: MetroidvaniaSystem.SaveData):
|
||||
if MetSys.settings.custom_elements and not map_data.custom_elements.is_empty():
|
||||
setup_custom_elements(canvas_item, offset, coords)
|
||||
|
||||
var cell_data := map_data.get_cell_at(coords)
|
||||
if not cell_data:
|
||||
if not skip_empty:
|
||||
draw_empty(canvas_item, offset)
|
||||
return
|
||||
|
||||
var discovered := 2
|
||||
if save_data:
|
||||
discovered = save_data.is_cell_discovered(coords)
|
||||
elif force_mapped:
|
||||
discovered = 1
|
||||
|
||||
if discovered == 0:
|
||||
if not skip_empty:
|
||||
draw_empty(canvas_item, offset)
|
||||
return
|
||||
|
||||
var theme: MapTheme = MetSys.settings.theme
|
||||
|
||||
var ci := canvas_item.get_canvas_item()
|
||||
var display_flags: int = (int(discovered == 2) * 255) | theme.mapped_display
|
||||
|
||||
# center
|
||||
if bool(display_flags & MetroidvaniaSystem.DISPLAY_CENTER):
|
||||
var room_color := cell_data.get_color()
|
||||
theme.center_texture.draw(ci, offset * MetSys.CELL_SIZE, room_color if discovered == 2 else theme.mapped_center_color)
|
||||
|
||||
# corners
|
||||
if theme.use_shared_borders:
|
||||
if not MetSys.has_meta(&"shared_borders_to_draw"):
|
||||
MetSys._add_meta(&"shared_borders_to_draw", {})#[Vector3i, Vector2]
|
||||
MetSys._add_meta(&"shared_borders_data", {"canvas_item": canvas_item, "display_flags": display_flags})
|
||||
|
||||
var shared_borders_to_draw: Dictionary = MetSys.get_meta(&"shared_borders_to_draw")
|
||||
shared_borders_to_draw[coords] = offset
|
||||
else:
|
||||
draw_regular_borders(canvas_item, offset, coords, map_data, cell_data, display_flags, discovered)
|
||||
|
||||
canvas_item.draw_set_transform_matrix(Transform2D())
|
||||
|
||||
if bool(display_flags & MetroidvaniaSystem.DISPLAY_SYMBOLS):
|
||||
var symbol: int = -1
|
||||
|
||||
if save_data and coords in save_data.custom_markers:
|
||||
var custom: int = save_data.custom_markers[coords]
|
||||
for i in range(63, -1, -1):
|
||||
if custom & 1 << i:
|
||||
symbol = i
|
||||
break
|
||||
|
||||
if symbol == -1:
|
||||
symbol = cell_data.get_symbol()
|
||||
|
||||
if symbol > - 1:
|
||||
if symbol >= theme.symbols.size():
|
||||
push_error("Bad symbol '%s' at '%s'" % [symbol, coords])
|
||||
else:
|
||||
canvas_item.draw_texture(theme.symbols[symbol], offset * MetSys.CELL_SIZE + MetSys.CELL_SIZE * 0.5 - theme.symbols[symbol].get_size() / 2)
|
||||
|
||||
static func draw_regular_borders(canvas_item: CanvasItem, offset: Vector2, coords: Vector3i, map_data: MetroidvaniaSystem.MapData, cell_data: MetroidvaniaSystem.MapData.CellData, display_flags: int, discovered: int):
|
||||
var theme: MapTheme = MetSys.settings.theme
|
||||
var ci := canvas_item.get_canvas_item()
|
||||
|
||||
# borders
|
||||
var borders: Array[int] = [-1, -1, -1, -1]
|
||||
|
||||
var display_outlines := bool(display_flags & MetroidvaniaSystem.DISPLAY_OUTLINE)
|
||||
for i in 4:
|
||||
var border: int = cell_data.get_border(i)
|
||||
if not display_outlines and border == 0:
|
||||
borders[i] = -1
|
||||
elif not bool(display_flags & MetroidvaniaSystem.DISPLAY_BORDERS):
|
||||
borders[i] = mini(border, 0 if display_outlines else -1)
|
||||
else:
|
||||
borders[i] = border
|
||||
|
||||
for i in 4:
|
||||
var texture: Texture2D
|
||||
var color: Color
|
||||
|
||||
var rotation := PI * 0.5 * i
|
||||
if borders[i] == -1:
|
||||
if display_outlines:
|
||||
texture = get_border_texture(theme, -1, i)
|
||||
color = Color.WHITE
|
||||
else:
|
||||
var border: int = borders[i]
|
||||
|
||||
if not bool(display_flags & MetroidvaniaSystem.DISPLAY_BORDERS):
|
||||
border = 0
|
||||
|
||||
texture = get_border_texture(theme, border, i)
|
||||
if discovered == 2:
|
||||
color = cell_data.get_border_color(i)
|
||||
else:
|
||||
color = theme.mapped_border_color
|
||||
|
||||
if not texture:
|
||||
continue
|
||||
|
||||
canvas_item.draw_set_transform(offset * MetSys.CELL_SIZE + MetSys.CELL_SIZE * 0.5, rotation, Vector2.ONE)
|
||||
match i:
|
||||
MetroidvaniaSystem.R, MetroidvaniaSystem.L:
|
||||
texture.draw(ci, -texture.get_size() / 2 + Vector2.RIGHT * (MetSys.CELL_SIZE.x * 0.5 - texture.get_width() / 2), color)
|
||||
MetroidvaniaSystem.D, MetroidvaniaSystem.U:
|
||||
texture.draw(ci, -texture.get_size() / 2 + Vector2.RIGHT * (MetSys.CELL_SIZE.y * 0.5 - texture.get_width() / 2), color)
|
||||
|
||||
if not display_outlines:
|
||||
return
|
||||
|
||||
# outer corner
|
||||
for i in 4:
|
||||
var j := rotate(i)
|
||||
if borders[i] == -1 or borders[j] == -1:
|
||||
continue
|
||||
|
||||
var texture: Texture2D = theme.outer_corner
|
||||
var corner_color: Color
|
||||
if discovered == 2:
|
||||
corner_color = get_shared_color(cell_data.get_border_color(i), cell_data.get_border_color(j), theme.default_border_color)
|
||||
else:
|
||||
corner_color = theme.mapped_border_color
|
||||
|
||||
canvas_item.draw_set_transform(offset * MetSys.CELL_SIZE + MetSys.CELL_SIZE * 0.5, PI * 0.5 * i, Vector2.ONE)
|
||||
|
||||
var corner_offset := -texture.get_size()
|
||||
if theme.use_shared_borders:
|
||||
corner_offset /= 2
|
||||
|
||||
match i:
|
||||
MetroidvaniaSystem.R, MetroidvaniaSystem.L:
|
||||
texture.draw(ci, MetSys.CELL_SIZE * 0.5 + corner_offset, corner_color)
|
||||
MetroidvaniaSystem.D, MetroidvaniaSystem.U:
|
||||
texture.draw(ci, Vector2(MetSys.CELL_SIZE.y, MetSys.CELL_SIZE.x) * 0.5 + corner_offset, corner_color)
|
||||
|
||||
# inner corner
|
||||
for i in 4:
|
||||
var j := rotate(i)
|
||||
if borders[i] != -1 or borders[j] != -1:
|
||||
continue
|
||||
|
||||
var neighbor_room := get_neighbor(map_data, coords, map_data.FWD[i] + map_data.FWD[j])
|
||||
if neighbor_room:
|
||||
if neighbor_room.borders[opposite(i)] == -1 and neighbor_room.borders[opposite(j)] == -1:
|
||||
continue
|
||||
|
||||
var texture: Texture2D = theme.inner_corner
|
||||
var color1 := get_neighbor(map_data, coords, map_data.FWD[i]).get_border_color(rotate(i))
|
||||
var color2 := get_neighbor(map_data, coords, map_data.FWD[j]).get_border_color(rotate(j, -1))
|
||||
|
||||
var corner_color := get_shared_color(color1, color2, theme.default_border_color)
|
||||
|
||||
canvas_item.draw_set_transform(offset * MetSys.CELL_SIZE + MetSys.CELL_SIZE * 0.5, PI * 0.5 * i, Vector2.ONE)
|
||||
|
||||
var corner_offset := -texture.get_size()
|
||||
if theme.use_shared_borders:
|
||||
corner_offset /= 2
|
||||
|
||||
match i:
|
||||
MetroidvaniaSystem.R, MetroidvaniaSystem.L:
|
||||
theme.inner_corner.draw(ci, MetSys.CELL_SIZE * 0.5 + corner_offset, corner_color)
|
||||
MetroidvaniaSystem.D, MetroidvaniaSystem.U:
|
||||
theme.inner_corner.draw(ci, Vector2(MetSys.CELL_SIZE.y, MetSys.CELL_SIZE.x) * 0.5 + corner_offset, corner_color)
|
||||
|
||||
static func draw_shared_borders():
|
||||
assert(MetSys.settings.theme.use_shared_borders, "This function requires shared borders to be enabled.")
|
||||
if not MetSys.has_meta(&"shared_borders_to_draw"):
|
||||
return
|
||||
|
||||
var theme: MapTheme = MetSys.settings.theme
|
||||
|
||||
var shared_borders_to_draw: Dictionary = MetSys.get_meta(&"shared_borders_to_draw")
|
||||
var shared_borders_data: Dictionary = MetSys.get_meta(&"shared_borders_data")
|
||||
|
||||
var shared_borders_colors: Dictionary#[Vector3i, Color]
|
||||
var shared_corners_data: Dictionary#[Vector3i, int]
|
||||
var shared_corners_colors: Dictionary#[Vector3i, Color]
|
||||
|
||||
var display_flags: int = shared_borders_data["display_flags"]
|
||||
var canvas_item: CanvasItem = shared_borders_data["canvas_item"]
|
||||
var ci := canvas_item.get_canvas_item()
|
||||
|
||||
var additional_corners: Dictionary#[Vector3i, Vector2]
|
||||
for coords in shared_borders_to_draw:
|
||||
for x in range (-1, 1):
|
||||
for y in range(-1, 1):
|
||||
var coords2: Vector3i = coords + Vector3i(x, y, 0)
|
||||
if not coords2 in shared_borders_to_draw:
|
||||
additional_corners[coords2] = shared_borders_to_draw[coords] + Vector2(x, y)
|
||||
|
||||
shared_borders_to_draw.merge(additional_corners)
|
||||
for coords in shared_borders_to_draw:
|
||||
var corner_data := 0
|
||||
corner_data |= (1 << 0) * (get_corner_bit(coords, MetroidvaniaSystem.R) | get_corner_bit(coords + Vector3i(1, 0, 0), MetroidvaniaSystem.L))
|
||||
corner_data |= (1 << 1) * (get_corner_bit(coords, MetroidvaniaSystem.D) | get_corner_bit(coords + Vector3i(0, 1, 0), MetroidvaniaSystem.U))
|
||||
corner_data |= (1 << 2) * (get_corner_bit(coords + Vector3i(0, 1, 0), MetroidvaniaSystem.R) | get_corner_bit(coords + Vector3i(1, 1, 0), MetroidvaniaSystem.L))
|
||||
corner_data |= (1 << 3) * (get_corner_bit(coords + Vector3i(1, 0, 0), MetroidvaniaSystem.D) | get_corner_bit(coords + Vector3i(1, 1, 0), MetroidvaniaSystem.U))
|
||||
|
||||
if theme.is_unicorner():
|
||||
corner_data = signi(corner_data) * 15
|
||||
|
||||
var use_default: bool
|
||||
var color_blend: Array[Color]
|
||||
for i in 4:
|
||||
var color: Color
|
||||
if i < 2:
|
||||
color = get_shared_border_color(coords, i)
|
||||
else:
|
||||
color = get_shared_border_color(coords + Vector3i(1, 1, 0), i)
|
||||
|
||||
if color == theme.default_border_color:
|
||||
use_default = true
|
||||
elif color.a > 0:
|
||||
color_blend.append(color)
|
||||
|
||||
shared_corners_data[coords] = corner_data
|
||||
if not color_blend.is_empty():
|
||||
var ratio: float = 1.0 / color_blend.size()
|
||||
shared_corners_colors[coords] = color_blend.reduce(func(final: Color, current: Color) -> Color: return final.lerp(current, ratio))
|
||||
elif use_default:
|
||||
shared_corners_colors[coords] = theme.default_border_color
|
||||
|
||||
var border_data: Array[int] = [-1, -1]
|
||||
var border_colors: Array[Color] = [Color(), Color()]
|
||||
for i in 2:
|
||||
var fwd := Vector3i(MetroidvaniaSystem.MapData.FWD[i].x, MetroidvaniaSystem.MapData.FWD[i].y, 0)
|
||||
border_data[i] = maxi(get_border_at(coords, i), get_border_at(coords + fwd, opposite(i)))
|
||||
border_colors[i] = get_shared_border_color(coords, i)
|
||||
|
||||
shared_borders_data[coords] = border_data
|
||||
shared_borders_colors[coords] = border_colors
|
||||
|
||||
# borders
|
||||
for coords in shared_borders_to_draw:
|
||||
var borders: Array[int] = shared_borders_data[coords]
|
||||
for i in 2:
|
||||
var texture: Texture2D
|
||||
var color: Color
|
||||
|
||||
var rotation := PI * 0.5 * i
|
||||
if borders[i] == -1:
|
||||
texture = get_border_texture(theme, -1, i)
|
||||
color = Color.WHITE
|
||||
else:
|
||||
var border: int = borders[i]
|
||||
|
||||
if not bool(display_flags & MetroidvaniaSystem.DISPLAY_BORDERS):
|
||||
border = 0
|
||||
|
||||
texture = get_border_texture(theme, border, i)
|
||||
color = shared_borders_colors[coords][i]
|
||||
|
||||
if not texture:
|
||||
continue
|
||||
|
||||
canvas_item.draw_set_transform(shared_borders_to_draw[coords] * MetSys.CELL_SIZE + MetSys.CELL_SIZE * 0.5, rotation, Vector2.ONE)
|
||||
match i:
|
||||
MetroidvaniaSystem.R, MetroidvaniaSystem.L:
|
||||
texture.draw(ci, -texture.get_size() / 2 + Vector2.RIGHT * (MetSys.CELL_SIZE.x * 0.5), color)
|
||||
MetroidvaniaSystem.D, MetroidvaniaSystem.U:
|
||||
texture.draw(ci, -texture.get_size() / 2 + Vector2.RIGHT * (MetSys.CELL_SIZE.y * 0.5), color)
|
||||
|
||||
# corners
|
||||
for coords in shared_borders_to_draw:
|
||||
var offset: Vector2 = shared_borders_to_draw[coords]
|
||||
var corner_data: int = shared_corners_data[coords]
|
||||
var corner_type = signi(corner_data & 1) + signi(corner_data & 2) + signi(corner_data & 4) + signi(corner_data & 8)
|
||||
|
||||
var corner_texture: Texture2D
|
||||
var corner_rotation := -1
|
||||
match corner_type:
|
||||
1:
|
||||
corner_texture = theme.u_corner
|
||||
match corner_data:
|
||||
1:
|
||||
corner_rotation = 0
|
||||
2:
|
||||
corner_rotation = 3
|
||||
4:
|
||||
corner_rotation = 2
|
||||
8:
|
||||
corner_rotation = 1
|
||||
2:
|
||||
corner_texture = theme.l_corner
|
||||
match corner_data:
|
||||
3:
|
||||
corner_rotation = 3
|
||||
6:
|
||||
corner_rotation = 2
|
||||
9:
|
||||
corner_rotation = 0
|
||||
12:
|
||||
corner_rotation = 1
|
||||
3:
|
||||
corner_texture = theme.t_corner
|
||||
match corner_data:
|
||||
7:
|
||||
corner_rotation = 1
|
||||
11:
|
||||
corner_rotation = 2
|
||||
13:
|
||||
corner_rotation = 3
|
||||
14:
|
||||
corner_rotation = 0
|
||||
4:
|
||||
corner_texture = theme.cross_corner
|
||||
corner_rotation = 0
|
||||
|
||||
if corner_rotation == -1 or not corner_texture:
|
||||
continue
|
||||
|
||||
canvas_item.draw_set_transform(offset * MetSys.CELL_SIZE + MetSys.CELL_SIZE, PI * 0.5 * corner_rotation, Vector2.ONE)
|
||||
corner_texture.draw(canvas_item.get_canvas_item(), -corner_texture.get_size() / 2, shared_corners_colors[coords])
|
||||
|
||||
MetSys.remove_meta(&"shared_borders_to_draw")
|
||||
MetSys.remove_meta(&"shared_borders_data")
|
||||
canvas_item.draw_set_transform_matrix(Transform2D())
|
||||
|
||||
static func setup_custom_elements(canvas_item: CanvasItem, offset: Vector2, coords: Vector3i):
|
||||
var custom_element_data: Dictionary
|
||||
if not MetSys.has_meta(&"custom_elements_data"):
|
||||
custom_element_data["canvas_item"] = canvas_item
|
||||
MetSys._add_meta(&"custom_elements_data", custom_element_data)
|
||||
|
||||
static func draw_custom_elements(canvas_item: CanvasItem, elements: Dictionary, base_offset: Vector2, rect: Rect2i, layer: int):
|
||||
var element_manager: MetroidvaniaSystem.CustomElementManager = MetSys.settings.custom_elements
|
||||
var already_drawn: Array[Dictionary]
|
||||
|
||||
for y in rect.size.y:
|
||||
for x in rect.size.y:
|
||||
var pos := rect.position + Vector2i(x, y)
|
||||
for coords in elements:
|
||||
if coords.z != layer:
|
||||
continue
|
||||
|
||||
var element: Dictionary = elements[coords]
|
||||
if element in already_drawn:
|
||||
continue
|
||||
|
||||
var elerect := Rect2i(coords.x, coords.y, element["size"].x, element["size"].y)
|
||||
if elerect.has_point(pos):
|
||||
element_manager.draw_element(canvas_item, coords, element.name, (base_offset + Vector2(coords.x, coords.y) - Vector2(pos) + Vector2(x, y)) * MetSys.CELL_SIZE, Vector2(element.size) * MetSys.CELL_SIZE, element.data)
|
||||
already_drawn.append(element)
|
||||
|
||||
static func get_border_at(coords: Vector3i, idx: int) -> int:
|
||||
var cell_data = get_discovered_cell_at(coords)
|
||||
if not cell_data:
|
||||
return -1
|
||||
return cell_data.get_border(idx)
|
||||
|
||||
static func get_corner_bit(coords: Vector3i, idx: int) -> int:
|
||||
return int(get_border_at(coords, idx) > -1)
|
||||
|
||||
static func get_shared_border_color(coords: Vector3i, idx: int) -> Color:
|
||||
var fwd := Vector3i(MetroidvaniaSystem.MapData.FWD[idx].x, MetroidvaniaSystem.MapData.FWD[idx].y, 0)
|
||||
var color := Color.TRANSPARENT
|
||||
|
||||
var cell_data = get_discovered_cell_at(coords)
|
||||
if cell_data:
|
||||
color = cell_data.get_border_color(idx)
|
||||
|
||||
cell_data = get_discovered_cell_at(coords + fwd)
|
||||
if cell_data:
|
||||
if color.a > 0:
|
||||
color = get_shared_color(color, cell_data.get_border_color(opposite(idx)), MetSys.settings.theme.default_border_color)
|
||||
else:
|
||||
color = cell_data.get_border_color(opposite(idx))
|
||||
|
||||
return color
|
||||
|
||||
static func get_discovered_cell_at(coords: Vector3i) -> MetroidvaniaSystem.MapData.CellData:
|
||||
var cell_data = MetSys.map_data.get_cell_at(coords)
|
||||
if cell_data and MetSys.is_cell_discovered(coords):
|
||||
return cell_data
|
||||
return null
|
||||
|
||||
static func get_shared_color(color1: Color, color2: Color, default: Color) -> Color:
|
||||
if color1 == default:
|
||||
return color2
|
||||
elif color2 == default:
|
||||
return color1
|
||||
return color1.lerp(color2, 0.5)
|
||||
|
||||
static func get_border_texture(theme: MapTheme, idx: int, direction: int) -> Texture2D:
|
||||
var texture_name: StringName
|
||||
|
||||
if theme.rectangle:
|
||||
if direction == MetroidvaniaSystem.R or direction == MetroidvaniaSystem.L:
|
||||
match idx:
|
||||
-1:
|
||||
texture_name = &"vertical_separator"
|
||||
0:
|
||||
texture_name = &"vertical_wall"
|
||||
1:
|
||||
texture_name = &"vertical_passage"
|
||||
2:
|
||||
texture_name = &"vertical_borders"
|
||||
else:
|
||||
match idx:
|
||||
-1:
|
||||
texture_name = &"horizontal_separator"
|
||||
0:
|
||||
texture_name = &"horizontal_wall"
|
||||
1:
|
||||
texture_name = &"horizontal_passage"
|
||||
_:
|
||||
texture_name = &"vertical_borders"
|
||||
else:
|
||||
match idx:
|
||||
-1:
|
||||
texture_name = &"separator"
|
||||
0:
|
||||
texture_name = &"wall"
|
||||
1:
|
||||
texture_name = &"passage"
|
||||
_:
|
||||
texture_name = &"borders"
|
||||
|
||||
if idx >= 2:
|
||||
return theme.get(texture_name)[idx - 2]
|
||||
else:
|
||||
return theme.get(texture_name)
|
||||
|
||||
static func draw_empty(canvas_item: CanvasItem, offset: Vector2):
|
||||
var theme: MapTheme = MetSys.settings.theme
|
||||
if theme.empty_space_texture:
|
||||
var ci := canvas_item.get_canvas_item()
|
||||
theme.empty_space_texture.draw(ci, offset * MetSys.CELL_SIZE, Color.WHITE)
|
||||
|
||||
static func get_neighbor(map_data: MetroidvaniaSystem.MapData, coords: Vector3i, offset: Vector2i) -> MetroidvaniaSystem.MapData.CellData:
|
||||
var neighbor: Vector2i = Vector2i(coords.x, coords.y) + offset
|
||||
return map_data.get_cell_at(Vector3i(neighbor.x, neighbor.y, coords.z))
|
||||
|
||||
static func rotate(i: int, amount := 1) -> int:
|
||||
return (i + amount) % 4
|
||||
|
||||
static func opposite(i: int) -> int:
|
||||
return (i + 2) % 4
|
||||
@ -1,73 +0,0 @@
|
||||
@tool
|
||||
## A node representing MetSys room.
|
||||
##
|
||||
## RoomInstance is a node that allows for integration between scenes and MetSys database. In editor it will provide drawing for room bounds and in game it provides some helper methods for interacting with the map data. [code]RoomInstance.tscn[/code] scene is provided for convenience. You should add it to every scene used as MetSys room. It's recommended to put the node at [code](0, 0)[/code] global coordinates.
|
||||
extends Node3D
|
||||
|
||||
var GRID_COLOR: Color
|
||||
var GRID_PASSAGE_COLOR: Color
|
||||
|
||||
var cells: Array[Vector3i]
|
||||
var initialized: bool
|
||||
var room_name: String
|
||||
|
||||
var min_cell := Vector2i(999999, 999999)
|
||||
var max_cell := Vector2i(-999999, -999999)
|
||||
var layer: int
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if not Engine.is_editor_hint():
|
||||
MetSys.current_room = self
|
||||
|
||||
if initialized:
|
||||
return
|
||||
initialized = true
|
||||
|
||||
if Engine.is_editor_hint():
|
||||
MetSys.room_assign_updated.connect(_update_assigned_scene)
|
||||
var theme: Theme = load("res://addons/MetroidvaniaSystem/Database/DatabaseTheme.tres")
|
||||
GRID_COLOR = theme.get_color(&"scene_cell_border", &"MetSys")
|
||||
GRID_PASSAGE_COLOR = theme.get_color(&"scene_room_exit", &"MetSys")
|
||||
|
||||
_update_assigned_scene()
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if MetSys.current_room == self:
|
||||
MetSys.current_room = null
|
||||
|
||||
func _update_assigned_scene():
|
||||
var owner_node := owner if owner != null else self
|
||||
room_name = owner_node.scene_file_path.trim_prefix(MetSys.settings.map_root_folder)
|
||||
cells = MetSys.map_data.get_cells_assigned_to(room_name)
|
||||
if cells.is_empty():
|
||||
return
|
||||
|
||||
layer = cells[0].z
|
||||
for p in cells:
|
||||
min_cell.x = mini(min_cell.x, p.x)
|
||||
min_cell.y = mini(min_cell.y, p.y)
|
||||
max_cell.x = maxi(max_cell.x, p.x)
|
||||
max_cell.y = maxi(max_cell.y, p.y)
|
||||
|
||||
## Returns the full size of this room, based on the cells and [code]in_game_cell_size[/code] defined in MetSys Settings.
|
||||
func get_size() -> Vector2:
|
||||
return Vector2(max_cell - min_cell + Vector2i.ONE) * MetSys.settings.in_game_cell_size
|
||||
|
||||
## Returns this rooms cells in local coordinates, i.e. with [code](0, 0)[/code] being the top-left cell.
|
||||
func get_local_cells() -> Array[Vector2i]:
|
||||
var ret: Array[Vector2i]
|
||||
ret.assign(cells.map(func(coords: Vector3i) -> Vector2i:
|
||||
return Vector2i(coords.x - min_cell.x, coords.y - min_cell.y)))
|
||||
return ret
|
||||
|
||||
## Returns the top-left cell's flat coordinates within the room's rectangle.
|
||||
func get_base_coords() -> Vector2i:
|
||||
return min_cell
|
||||
|
||||
## Returns the bottom-right cell's flat coordinates within the room's rectangle.
|
||||
func get_end_coords() -> Vector2i:
|
||||
return max_cell
|
||||
|
||||
## Returns the room's layer.
|
||||
func get_layer() -> int:
|
||||
return layer
|
||||
@ -1,95 +0,0 @@
|
||||
extends RefCounted
|
||||
|
||||
const SIMPLE_STORABLE_PROPERTIES: Array[StringName] = [&"discovered_cells", &"registered_objects", &"stored_objects", &"custom_markers"]
|
||||
|
||||
var discovered_cells: Dictionary#[Vector3i, int]
|
||||
var registered_objects: Dictionary#[String, bool]
|
||||
var stored_objects: Dictionary#[String, bool]
|
||||
|
||||
var custom_markers: Dictionary#[Vector3i, int]
|
||||
var cell_overrides: Dictionary#[CellData, CellOverride]
|
||||
|
||||
func discover_cell(coords: Vector3i):
|
||||
if discovered_cells.get(coords, 0) < 1:
|
||||
discovered_cells[coords] = 1
|
||||
|
||||
func explore_cell(coords: Vector3i):
|
||||
if discovered_cells.get(coords, 0) < 2:
|
||||
discovered_cells[coords] = 2
|
||||
MetSys.map_updated.emit()
|
||||
|
||||
func is_cell_discovered(coords: Vector3i) -> int:
|
||||
return discovered_cells.get(coords, 0)
|
||||
|
||||
func register_storable_object(object: Object) -> bool:
|
||||
var id: String = MetSys.get_object_id(object)
|
||||
if not id in registered_objects:
|
||||
registered_objects[id] = true
|
||||
return true
|
||||
return false
|
||||
|
||||
func store_object(object: Object):
|
||||
var id: String = MetSys.get_object_id(object)
|
||||
assert(id in registered_objects)
|
||||
assert(not id in stored_objects)
|
||||
registered_objects.erase(id)
|
||||
stored_objects[id] = true
|
||||
|
||||
func is_object_stored(object: Object) -> bool:
|
||||
var id: String = MetSys.get_object_id(object)
|
||||
return id in stored_objects
|
||||
|
||||
func add_cell_override(room: MetroidvaniaSystem.MapData.CellData) -> MetroidvaniaSystem.MapData.CellOverride:
|
||||
if not room in cell_overrides:
|
||||
cell_overrides[room] = MetroidvaniaSystem.MapData.CellOverride.new(room)
|
||||
return cell_overrides[room]
|
||||
|
||||
func remove_cell_override(room: MetroidvaniaSystem.MapData.CellData) -> bool:
|
||||
var override := cell_overrides.get(room)
|
||||
if override:
|
||||
if override.custom_cell_coords != Vector3i.MAX:
|
||||
push_error("Can't delete override of a custom cell. Use destroy() instead.")
|
||||
return false
|
||||
override._cleanup_assigned_scene()
|
||||
|
||||
cell_overrides.erase(room)
|
||||
return override != null
|
||||
|
||||
func add_custom_marker(coords: Vector3i, symbol: int):
|
||||
if not coords in custom_markers:
|
||||
custom_markers[coords] = 0
|
||||
|
||||
custom_markers[coords] |= 1 << symbol
|
||||
MetSys.map_updated.emit()
|
||||
|
||||
func remove_custom_marker(coords: Vector3i, symbol: int):
|
||||
if not coords in custom_markers:
|
||||
return
|
||||
|
||||
custom_markers[coords] &= ~(1 << symbol)
|
||||
if custom_markers[coords] == 0:
|
||||
custom_markers.erase(coords)
|
||||
MetSys.map_updated.emit()
|
||||
|
||||
func get_data() -> Dictionary:
|
||||
var data: Dictionary
|
||||
|
||||
for property in SIMPLE_STORABLE_PROPERTIES:
|
||||
data[property] = get(property)
|
||||
|
||||
data[&"cell_overrides"] = cell_overrides.keys().map(func(room):
|
||||
var coords: Vector3i = MetSys.map_data.cells.find_key(room)
|
||||
return cell_overrides[room]._get_override_string(coords))
|
||||
|
||||
return data
|
||||
|
||||
func set_data(data: Dictionary):
|
||||
if data.is_empty():
|
||||
return
|
||||
|
||||
for property in SIMPLE_STORABLE_PROPERTIES:
|
||||
set(property, data[property])
|
||||
|
||||
for override_string in data.cell_overrides:
|
||||
var override: MetroidvaniaSystem.MapData.CellOverride = MetroidvaniaSystem.MapData.CellOverride.load_from_line(override_string)
|
||||
cell_overrides[override.original_room] = override
|
||||
@ -1,40 +0,0 @@
|
||||
@tool
|
||||
extends Resource
|
||||
|
||||
## The theme used for drawing map cells.
|
||||
@export var theme: MapTheme:
|
||||
set(t):
|
||||
if t == theme:
|
||||
return
|
||||
|
||||
theme = t
|
||||
theme_changed.emit()
|
||||
|
||||
## The root directory where room scenes are located. All scenes used for MetSys editor should be within this folder or its subfolders.
|
||||
@export_dir var map_root_folder: String = "res://"
|
||||
@export_dir var map_setting_folder: String = "res://"
|
||||
## The size of a map cell within an in-game room, i.e. this is the real game size of your map cells. Usually equal to the screen size.
|
||||
@export var in_game_cell_size := Vector2(1152, 648)
|
||||
@export var collectible_list: Array[Dictionary]
|
||||
## The script that determines the custom elements available in the Custom Elements map editor mode. It should inherit [code]CustomElementManager.gd[/code], refer to that class' documentation on how to use it.
|
||||
@export var custom_element_script: Script:
|
||||
set(elements):
|
||||
if elements == custom_element_script:
|
||||
return
|
||||
|
||||
custom_element_script = elements
|
||||
if elements:
|
||||
custom_elements = elements.new()
|
||||
else:
|
||||
custom_elements = null
|
||||
|
||||
custom_elements_changed.emit()
|
||||
|
||||
var custom_elements: MetroidvaniaSystem.CustomElementManager
|
||||
|
||||
signal theme_changed
|
||||
signal custom_elements_changed
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if property.name == "collectible_list":
|
||||
property.usage &= ~PROPERTY_USAGE_EDITOR
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://q4al3ip12dm1"
|
||||
path="res://.godot/imported/BorderPassage.png-633225ee718470c51dbf8f1eadaceebc.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/AoS/BorderPassage.png"
|
||||
dest_files=["res://.godot/imported/BorderPassage.png-633225ee718470c51dbf8f1eadaceebc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 767 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://citg7br0tcbix"
|
||||
path="res://.godot/imported/BorderWall.png-b3eebcdcaea75a2afb38071c89ec8187.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/AoS/BorderWall.png"
|
||||
dest_files=["res://.godot/imported/BorderWall.png-b3eebcdcaea75a2afb38071c89ec8187.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 780 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://gumwhy8sgmcu"
|
||||
path="res://.godot/imported/Corner.png-10c3b8f9b1a8940081842cbc25b22edb.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/AoS/Corner.png"
|
||||
dest_files=["res://.godot/imported/Corner.png-10c3b8f9b1a8940081842cbc25b22edb.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cg88cixacoi6n"
|
||||
path="res://.godot/imported/PlayerLocation.png-5bb116814673a6a1b60e3356eb77b54c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/AoS/PlayerLocation.png"
|
||||
dest_files=["res://.godot/imported/PlayerLocation.png-5bb116814673a6a1b60e3356eb77b54c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,74 +0,0 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://b1hnpnqaqqcds"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://cg88cixacoi6n" path="res://addons/MetroidvaniaSystem/Themes/AoS/PlayerLocation.png" id="1_6xqmr"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_a76ue"]
|
||||
resource_name = "Animate"
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:modulate")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 0.0627451), Color(1, 1, 1, 1)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath(".:scale")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(1, 1), Vector2(1e-05, 1e-05)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_4lnw3"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:modulate")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Color(1, 1, 1, 0.0627451)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath(".:scale")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector2(1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_qhx6n"]
|
||||
_data = {
|
||||
"Animate": SubResource("Animation_a76ue"),
|
||||
"RESET": SubResource("Animation_4lnw3")
|
||||
}
|
||||
|
||||
[node name="PlayerLocation" type="Sprite2D"]
|
||||
modulate = Color(1, 1, 1, 0.0627451)
|
||||
texture = ExtResource("1_6xqmr")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
autoplay = "Animate"
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_qhx6n")
|
||||
}
|
||||
|
Before Width: | Height: | Size: 796 B |
@ -1,30 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="MapTheme" load_steps=7 format=3 uid="uid://bnbbd2mcri1tv"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://gumwhy8sgmcu" path="res://addons/MetroidvaniaSystem/Themes/AoS/Corner.png" id="1_1n1yf"]
|
||||
[ext_resource type="PackedScene" uid="uid://b1hnpnqaqqcds" path="res://addons/MetroidvaniaSystem/Themes/AoS/PlayerLocation.tscn" id="3_bjiwt"]
|
||||
[ext_resource type="Texture2D" uid="uid://da3bit4f5alc4" path="res://addons/MetroidvaniaSystem/Themes/AoS/RoomFill.png" id="4_0del7"]
|
||||
[ext_resource type="Texture2D" uid="uid://q4al3ip12dm1" path="res://addons/MetroidvaniaSystem/Themes/AoS/BorderPassage.png" id="5_n3yba"]
|
||||
[ext_resource type="Texture2D" uid="uid://citg7br0tcbix" path="res://addons/MetroidvaniaSystem/Themes/AoS/BorderWall.png" id="6_dpo7t"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/MapTheme.gd" id="7_hynsb"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("7_hynsb")
|
||||
center_texture = ExtResource("4_0del7")
|
||||
player_location_scene = ExtResource("3_bjiwt")
|
||||
show_exact_player_location = false
|
||||
mapped_display = 7
|
||||
use_shared_borders = true
|
||||
default_center_color = Color(0, 0, 0.878431, 1)
|
||||
mapped_center_color = Color(0.25098, 0.25098, 0.25098, 1)
|
||||
default_border_color = Color(1, 1, 1, 1)
|
||||
mapped_border_color = Color(0.533333, 0.533333, 0.533333, 1)
|
||||
symbols = Array[Texture2D]([])
|
||||
uncollected_item_symbol = -1
|
||||
collected_item_symbol = -1
|
||||
wall = ExtResource("6_dpo7t")
|
||||
passage = ExtResource("5_n3yba")
|
||||
borders = Array[Texture2D]([])
|
||||
u_corner = ExtResource("1_1n1yf")
|
||||
l_corner = ExtResource("1_1n1yf")
|
||||
t_corner = ExtResource("1_1n1yf")
|
||||
cross_corner = ExtResource("1_1n1yf")
|
||||
|
Before Width: | Height: | Size: 911 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dlhoaflaw78ms"
|
||||
path="res://.godot/imported/BorderPassage.png-9267f5e7854f25956faac66e32244104.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/BorderPassage.png"
|
||||
dest_files=["res://.godot/imported/BorderPassage.png-9267f5e7854f25956faac66e32244104.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 776 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bfhk3kvl3cx6t"
|
||||
path="res://.godot/imported/BorderPassageHorizontal.png-c5365caa5938f8ef2ff19b0f85764346.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/BorderPassageHorizontal.png"
|
||||
dest_files=["res://.godot/imported/BorderPassageHorizontal.png-c5365caa5938f8ef2ff19b0f85764346.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 767 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cp12io0ko3ari"
|
||||
path="res://.godot/imported/BorderWall.png-26fbbf8b28dea53d162e4509b0078129.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/BorderWall.png"
|
||||
dest_files=["res://.godot/imported/BorderWall.png-26fbbf8b28dea53d162e4509b0078129.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 768 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bixscdbqbbnqm"
|
||||
path="res://.godot/imported/BorderWallHorizontal.png-8a03585c3fec3e27ec36d9209e60ddb0.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/BorderWallHorizontal.png"
|
||||
dest_files=["res://.godot/imported/BorderWallHorizontal.png-8a03585c3fec3e27ec36d9209e60ddb0.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 780 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dp67rmhfarvuw"
|
||||
path="res://.godot/imported/Corner.png-3b270bb0bc68b65f38a41512dcd55729.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/Corner.png"
|
||||
dest_files=["res://.godot/imported/Corner.png-3b270bb0bc68b65f38a41512dcd55729.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://rwf0o6emuvco"
|
||||
path="res://.godot/imported/PlayerLocation.png-23939cf1e6de1a78232f9845375f45f9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/PlayerLocation.png"
|
||||
dest_files=["res://.godot/imported/PlayerLocation.png-23939cf1e6de1a78232f9845375f45f9.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,6 +0,0 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://cq5af3a4hpkmc"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://rwf0o6emuvco" path="res://addons/MetroidvaniaSystem/Themes/BS/PlayerLocation.png" id="1_ky7bq"]
|
||||
|
||||
[node name="PlayerLocation" type="Sprite2D"]
|
||||
texture = ExtResource("1_ky7bq")
|
||||
|
Before Width: | Height: | Size: 825 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://danai55i8ghuq"
|
||||
path="res://.godot/imported/RoomFill.png-24f0edf089b5b86a6e70f860d60f551c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/BS/RoomFill.png"
|
||||
dest_files=["res://.godot/imported/RoomFill.png-24f0edf089b5b86a6e70f860d60f551c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,35 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="MapTheme" load_steps=9 format=3 uid="uid://dtpk6t0nnpjb"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://bfhk3kvl3cx6t" path="res://addons/MetroidvaniaSystem/Themes/BS/BorderPassageHorizontal.png" id="1_fsnn7"]
|
||||
[ext_resource type="Texture2D" uid="uid://bixscdbqbbnqm" path="res://addons/MetroidvaniaSystem/Themes/BS/BorderWallHorizontal.png" id="2_gohjd"]
|
||||
[ext_resource type="Texture2D" uid="uid://dp67rmhfarvuw" path="res://addons/MetroidvaniaSystem/Themes/BS/Corner.png" id="3_junke"]
|
||||
[ext_resource type="PackedScene" uid="uid://cq5af3a4hpkmc" path="res://addons/MetroidvaniaSystem/Themes/BS/PlayerLocation.tscn" id="3_y5832"]
|
||||
[ext_resource type="Texture2D" uid="uid://danai55i8ghuq" path="res://addons/MetroidvaniaSystem/Themes/BS/RoomFill.png" id="4_4g5i5"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/MapTheme.gd" id="7_2ip2q"]
|
||||
[ext_resource type="Texture2D" uid="uid://dlhoaflaw78ms" path="res://addons/MetroidvaniaSystem/Themes/BS/BorderPassage.png" id="8_fo8f6"]
|
||||
[ext_resource type="Texture2D" uid="uid://cp12io0ko3ari" path="res://addons/MetroidvaniaSystem/Themes/BS/BorderWall.png" id="9_c2e7j"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("7_2ip2q")
|
||||
center_texture = ExtResource("4_4g5i5")
|
||||
player_location_scene = ExtResource("3_y5832")
|
||||
show_exact_player_location = true
|
||||
mapped_display = 7
|
||||
use_shared_borders = true
|
||||
default_center_color = Color(0, 0.368627, 0.996078, 1)
|
||||
mapped_center_color = Color(0.25098, 0.25098, 0.25098, 1)
|
||||
default_border_color = Color(1, 1, 1, 1)
|
||||
mapped_border_color = Color(1, 1, 1, 1)
|
||||
symbols = Array[Texture2D]([])
|
||||
uncollected_item_symbol = -1
|
||||
collected_item_symbol = -1
|
||||
vertical_wall = ExtResource("9_c2e7j")
|
||||
horizontal_wall = ExtResource("2_gohjd")
|
||||
vertical_passage = ExtResource("8_fo8f6")
|
||||
horizontal_passage = ExtResource("1_fsnn7")
|
||||
vertical_borders = Array[Texture2D]([])
|
||||
horizontal_borders = Array[Texture2D]([])
|
||||
u_corner = ExtResource("3_junke")
|
||||
l_corner = ExtResource("3_junke")
|
||||
t_corner = ExtResource("3_junke")
|
||||
cross_corner = ExtResource("3_junke")
|
||||
|
Before Width: | Height: | Size: 924 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b8ccoibsf323o"
|
||||
path="res://.godot/imported/BorderPassage.png-0014d135952d67eb8309d6d7ed57443f.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderPassage.png"
|
||||
dest_files=["res://.godot/imported/BorderPassage.png-0014d135952d67eb8309d6d7ed57443f.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://6lyqjfj3vsy7"
|
||||
path="res://.godot/imported/BorderPassageHorizontal.png-f9924ee9207cc35f2ff1a8237bef6b88.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderPassageHorizontal.png"
|
||||
dest_files=["res://.godot/imported/BorderPassageHorizontal.png-f9924ee9207cc35f2ff1a8237bef6b88.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 767 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://xn6gipdberdc"
|
||||
path="res://.godot/imported/BorderWall.png-62cc1a22fdc4f3da3329cb0764e89558.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderWall.png"
|
||||
dest_files=["res://.godot/imported/BorderWall.png-62cc1a22fdc4f3da3329cb0764e89558.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 832 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c5wg3is8k5pux"
|
||||
path="res://.godot/imported/BorderWallHorizontal.png-a151ba4bbdf139b3a508f2d33464c8be.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderWallHorizontal.png"
|
||||
dest_files=["res://.godot/imported/BorderWallHorizontal.png-a151ba4bbdf139b3a508f2d33464c8be.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 2.6 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://rgchhbw4jh7f"
|
||||
path="res://.godot/imported/CornerInner.png-c52d89f0e905827e58f95c8e77d169fc.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/CornerInner.png"
|
||||
dest_files=["res://.godot/imported/CornerInner.png-c52d89f0e905827e58f95c8e77d169fc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 956 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dihccrjj2ehi4"
|
||||
path="res://.godot/imported/CornerOuter.png-aadab3438335cc00d2d7825b4169097e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/CornerOuter.png"
|
||||
dest_files=["res://.godot/imported/CornerOuter.png-aadab3438335cc00d2d7825b4169097e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 8.8 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://208uoowofggq"
|
||||
path="res://.godot/imported/Empty.png-5c5b7398b3c73e9dac69098338edeff8.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/Empty.png"
|
||||
dest_files=["res://.godot/imported/Empty.png-5c5b7398b3c73e9dac69098338edeff8.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://u3h7efr7bfkv"
|
||||
path="res://.godot/imported/PlayerLocation.png-db89c3dd938814d3cdaf16f8d83e4f4c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/PlayerLocation.png"
|
||||
dest_files=["res://.godot/imported/PlayerLocation.png-db89c3dd938814d3cdaf16f8d83e4f4c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,53 +0,0 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://brmrbsa4ongaw"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://u3h7efr7bfkv" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/PlayerLocation.png" id="1_8k1h2"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_ff42g"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:rotation")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [0.0]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_2cmdj"]
|
||||
resource_name = "Spin"
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:rotation")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 1),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [0.0, 6.28319]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_dyruj"]
|
||||
_data = {
|
||||
"RESET": SubResource("Animation_ff42g"),
|
||||
"Spin": SubResource("Animation_2cmdj")
|
||||
}
|
||||
|
||||
[node name="PlayerLocation" type="Sprite2D"]
|
||||
texture_filter = 1
|
||||
texture = ExtResource("1_8k1h2")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
autoplay = "Spin"
|
||||
playback_speed = 0.5
|
||||
libraries = {
|
||||
"": SubResource("AnimationLibrary_dyruj")
|
||||
}
|
||||
|
||||
[node name="VisibleOnScreenEnabler2D" type="VisibleOnScreenEnabler2D" parent="."]
|
||||
|
Before Width: | Height: | Size: 2.1 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxs8cn6khov7j"
|
||||
path="res://.godot/imported/RoomFill.png-a2c5cfa768a806eaffa0be05b808df2d.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/RoomFill.png"
|
||||
dest_files=["res://.godot/imported/RoomFill.png-a2c5cfa768a806eaffa0be05b808df2d.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://b1hy1w1k1asap"
|
||||
path="res://.godot/imported/RoomSeparator.png-fba7149bc653105012a4b989a09fd2c7.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/RoomSeparator.png"
|
||||
dest_files=["res://.godot/imported/RoomSeparator.png-fba7149bc653105012a4b989a09fd2c7.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 4.2 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ljjnp6f81hm"
|
||||
path="res://.godot/imported/Collected.png-70d99c06085090377e196418cee66c19.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Collected.png"
|
||||
dest_files=["res://.godot/imported/Collected.png-70d99c06085090377e196418cee66c19.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 8.3 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bcuwpuvv6bpsf"
|
||||
path="res://.godot/imported/Collectible.png-9af2468e6f0024e693f1577ca821a870.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Collectible.png"
|
||||
dest_files=["res://.godot/imported/Collectible.png-9af2468e6f0024e693f1577ca821a870.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 11 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dvp5dov6wsh2m"
|
||||
path="res://.godot/imported/Portal.png-bff52835ac3177f5a3115b1a5554c998.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Portal.png"
|
||||
dest_files=["res://.godot/imported/Portal.png-bff52835ac3177f5a3115b1a5554c998.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 5.9 KiB |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bc0o6ot1koste"
|
||||
path="res://.godot/imported/Ring.png-531ccf1f93cfc7df1edda7c73e3f0897.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Ring.png"
|
||||
dest_files=["res://.godot/imported/Ring.png-531ccf1f93cfc7df1edda7c73e3f0897.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
@ -1,43 +0,0 @@
|
||||
[gd_resource type="Resource" script_class="MapTheme" load_steps=16 format=3 uid="uid://bt6s3nd8xo6b"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://6lyqjfj3vsy7" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderPassageHorizontal.png" id="1_hth3y"]
|
||||
[ext_resource type="Texture2D" uid="uid://c5wg3is8k5pux" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderWallHorizontal.png" id="2_tawyw"]
|
||||
[ext_resource type="Texture2D" uid="uid://208uoowofggq" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/Empty.png" id="2_tsiva"]
|
||||
[ext_resource type="Texture2D" uid="uid://rgchhbw4jh7f" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/CornerInner.png" id="3_4qbbp"]
|
||||
[ext_resource type="PackedScene" uid="uid://brmrbsa4ongaw" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/PlayerLocation.tscn" id="3_mk7eh"]
|
||||
[ext_resource type="Texture2D" uid="uid://bxs8cn6khov7j" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/RoomFill.png" id="4_2clky"]
|
||||
[ext_resource type="Texture2D" uid="uid://dihccrjj2ehi4" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/CornerOuter.png" id="4_xtd8s"]
|
||||
[ext_resource type="Texture2D" uid="uid://b8ccoibsf323o" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderPassage.png" id="5_sn1if"]
|
||||
[ext_resource type="Texture2D" uid="uid://b1hy1w1k1asap" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/RoomSeparator.png" id="6_f6pnw"]
|
||||
[ext_resource type="Texture2D" uid="uid://xn6gipdberdc" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/BorderWall.png" id="7_eifkn"]
|
||||
[ext_resource type="Script" path="res://addons/MetroidvaniaSystem/Scripts/MapTheme.gd" id="8_gh637"]
|
||||
[ext_resource type="Texture2D" uid="uid://dvp5dov6wsh2m" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Portal.png" id="9_3gfe5"]
|
||||
[ext_resource type="Texture2D" uid="uid://bc0o6ot1koste" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Ring.png" id="9_c11cy"]
|
||||
[ext_resource type="Texture2D" uid="uid://bcuwpuvv6bpsf" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Collectible.png" id="11_o6efd"]
|
||||
[ext_resource type="Texture2D" uid="uid://ljjnp6f81hm" path="res://addons/MetroidvaniaSystem/Themes/Exquisite/Symbols/Collected.png" id="13_hjnmv"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("8_gh637")
|
||||
center_texture = ExtResource("4_2clky")
|
||||
empty_space_texture = ExtResource("2_tsiva")
|
||||
player_location_scene = ExtResource("3_mk7eh")
|
||||
show_exact_player_location = true
|
||||
mapped_display = 11
|
||||
use_shared_borders = false
|
||||
default_center_color = Color(0.5, 0.25, 0.25, 1)
|
||||
mapped_center_color = Color(0.745098, 0.745098, 0.745098, 1)
|
||||
default_border_color = Color(1, 0.741176, 0.580392, 1)
|
||||
mapped_border_color = Color(1, 1, 1, 1)
|
||||
symbols = Array[Texture2D]([ExtResource("9_c11cy"), ExtResource("9_3gfe5"), ExtResource("11_o6efd"), ExtResource("13_hjnmv")])
|
||||
uncollected_item_symbol = 2
|
||||
collected_item_symbol = 3
|
||||
vertical_wall = ExtResource("7_eifkn")
|
||||
horizontal_wall = ExtResource("2_tawyw")
|
||||
vertical_passage = ExtResource("5_sn1if")
|
||||
horizontal_passage = ExtResource("1_hth3y")
|
||||
vertical_separator = ExtResource("6_f6pnw")
|
||||
horizontal_separator = ExtResource("6_f6pnw")
|
||||
vertical_borders = Array[Texture2D]([])
|
||||
horizontal_borders = Array[Texture2D]([])
|
||||
outer_corner = ExtResource("4_xtd8s")
|
||||
inner_corner = ExtResource("3_4qbbp")
|
||||
|
Before Width: | Height: | Size: 778 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bdj2f008uewl8"
|
||||
path="res://.godot/imported/BorderPassage.png-3717726a9e8f42f33cda81f114d70776.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/MF/BorderPassage.png"
|
||||
dest_files=["res://.godot/imported/BorderPassage.png-3717726a9e8f42f33cda81f114d70776.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 765 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://q0b38erpbso0"
|
||||
path="res://.godot/imported/BorderWall.png-72c47be69f4a48ebfeda5788ec64219e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/MF/BorderWall.png"
|
||||
dest_files=["res://.godot/imported/BorderWall.png-72c47be69f4a48ebfeda5788ec64219e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 868 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bhu6ahuyeibux"
|
||||
path="res://.godot/imported/Door1.png-e528b647953d6dfe7941c40924408ce6.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/MF/Borders/Door1.png"
|
||||
dest_files=["res://.godot/imported/Door1.png-e528b647953d6dfe7941c40924408ce6.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 873 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ca1c415uaj78m"
|
||||
path="res://.godot/imported/Door2.png-f4a3bf33e9c7d664e2e850bfa8d97b14.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/MF/Borders/Door2.png"
|
||||
dest_files=["res://.godot/imported/Door2.png-f4a3bf33e9c7d664e2e850bfa8d97b14.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 867 B |
@ -1,34 +0,0 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://cebl0efe2kt0t"
|
||||
path="res://.godot/imported/Door3.png-924d56b4d9b2633e731ac99de58ac625.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/MetroidvaniaSystem/Themes/MF/Borders/Door3.png"
|
||||
dest_files=["res://.godot/imported/Door3.png-924d56b4d9b2633e731ac99de58ac625.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
|
Before Width: | Height: | Size: 870 B |