199 lines
5.4 KiB
GDScript
199 lines
5.4 KiB
GDScript
@tool
|
|
extends Popup
|
|
|
|
|
|
const PRESETS_PATH = "res://addons/proton_scatter/presets"
|
|
const PresetEntry := preload("./preset_entry.tscn")
|
|
const ProtonScatterUtil := preload('../common/scatter_util.gd')
|
|
const ProtonScatterItem := preload('../scatter_item.gd')
|
|
const ProtonScatterShape := preload('../scatter_shape.gd')
|
|
|
|
var _scatter_node
|
|
var _ideal_popup_size: Vector2i
|
|
var _editor_file_system: EditorFileSystem
|
|
var _preset_path_to_delete: String
|
|
var _preset_control_to_delete: Control
|
|
|
|
@onready var _new_preset_button: Button = %NewPresetButton
|
|
@onready var _new_preset_dialog: ConfirmationDialog = %NewPresetDialog
|
|
@onready var _delete_preset_dialog: ConfirmationDialog = %DeleteDialog
|
|
@onready var _delete_warning_label: Label = %DeleteLabel
|
|
@onready var _presets_root: Control = %PresetsRoot
|
|
|
|
|
|
func _ready():
|
|
_new_preset_button.pressed.connect(_show_preset_dialog)
|
|
_new_preset_dialog.confirmed.connect(_on_new_preset_name_confirmed)
|
|
_delete_preset_dialog.confirmed.connect(_on_delete_preset_confirmed)
|
|
_new_preset_dialog.hide()
|
|
_delete_preset_dialog.hide()
|
|
hide()
|
|
|
|
|
|
func save_preset(scatter_node: Node3D) -> void:
|
|
if not scatter_node:
|
|
return
|
|
|
|
_populate()
|
|
_scatter_node = scatter_node
|
|
_new_preset_button.visible = true
|
|
|
|
for c in _presets_root.get_children():
|
|
c.show_save_controls()
|
|
|
|
popup_centered(_ideal_popup_size)
|
|
|
|
|
|
func load_preset(scatter_node: Node3D) -> void:
|
|
if not scatter_node:
|
|
return
|
|
|
|
_populate()
|
|
_scatter_node = scatter_node
|
|
_new_preset_button.visible = false
|
|
|
|
for c in _presets_root.get_children():
|
|
c.show_load_controls()
|
|
|
|
popup_centered(_ideal_popup_size)
|
|
|
|
|
|
func load_default(scatter_node: Node3D) -> void:
|
|
_scatter_node = scatter_node
|
|
_on_load_full_preset(PRESETS_PATH.path_join("scatter_default.tscn"))
|
|
|
|
|
|
func set_editor_plugin(editor_plugin: EditorPlugin) -> void:
|
|
if not editor_plugin:
|
|
return
|
|
|
|
_editor_file_system = editor_plugin.get_editor_interface().get_resource_filesystem()
|
|
|
|
|
|
func _clear():
|
|
for c in _presets_root.get_children():
|
|
c.queue_free()
|
|
|
|
|
|
func _populate() -> void:
|
|
_clear()
|
|
var dir = DirAccess.open(PRESETS_PATH)
|
|
if not dir:
|
|
print_debug("ProtonScatter error: Could not open folder ", PRESETS_PATH)
|
|
return
|
|
|
|
dir.include_hidden = false
|
|
dir.include_navigational = false
|
|
dir.list_dir_begin()
|
|
|
|
while true:
|
|
var file := dir.get_next()
|
|
if file == "":
|
|
break
|
|
|
|
if dir.current_is_dir():
|
|
continue
|
|
|
|
if not file.ends_with(".tscn") and not file.ends_with(".scn"):
|
|
continue
|
|
|
|
# Preset found, create an entry
|
|
var full_path = PRESETS_PATH.path_join(file)
|
|
var entry := PresetEntry.instantiate()
|
|
entry.set_preset_name(file.get_basename())
|
|
entry.load_full.connect(_on_load_full_preset.bind(full_path))
|
|
entry.load_stack_only.connect(_on_load_stack_only.bind(full_path))
|
|
entry.delete.connect(_on_delete_button_pressed.bind(full_path, entry))
|
|
|
|
_presets_root.add_child(entry)
|
|
|
|
dir.list_dir_end()
|
|
var full_height = _presets_root.get_child_count() * 120
|
|
_ideal_popup_size = Vector2i(450, clamp(full_height, 120, 500))
|
|
|
|
|
|
func _show_preset_dialog() -> void:
|
|
$%NewPresetName.set_text("")
|
|
_new_preset_dialog.popup_centered()
|
|
|
|
|
|
func _on_new_preset_name_confirmed() -> void:
|
|
var file_name: String = $%NewPresetName.text.to_lower().strip_edges() + ".tscn"
|
|
var full_path := PRESETS_PATH.path_join(file_name)
|
|
_on_save_preset(full_path)
|
|
hide()
|
|
|
|
|
|
func _on_save_preset(path) -> void:
|
|
var preset = _scatter_node.duplicate(7)
|
|
preset.clear_output()
|
|
ProtonScatterUtil.set_owner_recursive(preset, preset)
|
|
preset.global_transform.origin = Vector3.ZERO
|
|
|
|
var packed_scene = PackedScene.new()
|
|
if packed_scene.pack(preset) != OK:
|
|
print_debug("ProtonScatter error: Failed to save preset")
|
|
return
|
|
|
|
var err = ResourceSaver.save(packed_scene, path)
|
|
if err:
|
|
print_debug("ProtonScatter error: Failed to save preset. Code: ", err)
|
|
|
|
|
|
func _on_load_full_preset(path: String) -> void:
|
|
var preset_scene: PackedScene = load(path)
|
|
if not preset_scene:
|
|
print("Could not find preset ", path)
|
|
return
|
|
|
|
var preset = preset_scene.instantiate()
|
|
|
|
if preset:
|
|
_scatter_node.modifier_stack = preset.modifier_stack.get_copy()
|
|
preset.global_transform = _scatter_node.get_global_transform()
|
|
|
|
for c in _scatter_node.get_children():
|
|
if c is ProtonScatterItem or c is ProtonScatterShape:
|
|
_scatter_node.remove_child(c)
|
|
c.owner = null
|
|
c.queue_free()
|
|
|
|
for c in preset.get_children():
|
|
if c is Marker3D or c.name == "ScatterOutput":
|
|
continue
|
|
preset.remove_child(c)
|
|
c.owner = null
|
|
_scatter_node.add_child(c, true)
|
|
|
|
ProtonScatterUtil.set_owner_recursive(_scatter_node, get_tree().get_edited_scene_root())
|
|
preset.queue_free()
|
|
|
|
_scatter_node.rebuild.call_deferred()
|
|
hide()
|
|
|
|
|
|
func _on_load_stack_only(path: String) -> void:
|
|
var preset = load(path).instantiate()
|
|
if preset:
|
|
_scatter_node.modifier_stack = preset.modifier_stack.get_copy()
|
|
_scatter_node.rebuild.call_deferred()
|
|
preset.queue_free()
|
|
|
|
hide()
|
|
|
|
|
|
func _on_delete_button_pressed(path: String, entry: Control) -> void:
|
|
_preset_path_to_delete = path
|
|
_preset_control_to_delete = entry
|
|
_delete_warning_label.text = "Are you sure you want to delete the preset [" \
|
|
+ path.get_file().get_basename().capitalize() + "] ?\n\n" \
|
|
+ "This operation cannot be undone."
|
|
_delete_preset_dialog.popup_centered()
|
|
|
|
|
|
func _on_delete_preset_confirmed() -> void:
|
|
DirAccess.remove_absolute(_preset_path_to_delete)
|
|
_presets_root.remove_child(_preset_control_to_delete)
|
|
_preset_control_to_delete.queue_free()
|
|
_editor_file_system.scan() # Refresh the filesystem view
|