Added footsteps, new tree, various other tweaks
This commit is contained in:
28
addons/proton_scatter/src/presets/preset_entry.gd
Normal file
28
addons/proton_scatter/src/presets/preset_entry.gd
Normal file
@@ -0,0 +1,28 @@
|
||||
@tool
|
||||
extends MarginContainer
|
||||
|
||||
signal load_full
|
||||
signal load_stack_only
|
||||
signal delete
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
$%LoadStackOnly.pressed.connect(func (): load_stack_only.emit())
|
||||
$%LoadFullPreset.pressed.connect(func (): load_full.emit())
|
||||
$%DeleteButton.pressed.connect(func (): delete.emit())
|
||||
|
||||
|
||||
func set_preset_name(preset_name: String) -> void:
|
||||
preset_name = preset_name.trim_suffix(".tres")
|
||||
$%Label.set_text(preset_name.capitalize())
|
||||
|
||||
|
||||
func show_save_controls() -> void:
|
||||
$%SaveButtons.visible = true
|
||||
$%LoadButtons.visible = false
|
||||
|
||||
|
||||
func show_load_controls() -> void:
|
||||
$%SaveButtons.visible = false
|
||||
$%LoadButtons.visible = true
|
||||
|
||||
92
addons/proton_scatter/src/presets/preset_entry.tscn
Normal file
92
addons/proton_scatter/src/presets/preset_entry.tscn
Normal file
@@ -0,0 +1,92 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://bosqtuvhckh3g"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://ddjrq1h4mkn6a" path="res://addons/proton_scatter/icons/load.svg" id="1_0auay"]
|
||||
[ext_resource type="Script" path="res://addons/proton_scatter/src/presets/preset_entry.gd" id="1_bqha3"]
|
||||
[ext_resource type="Texture2D" uid="uid://btb6rqhhi27mx" path="res://addons/proton_scatter/icons/remove.svg" id="2_p04k2"]
|
||||
|
||||
[sub_resource type="SystemFont" id="SystemFont_kgkwq"]
|
||||
|
||||
[sub_resource type="LabelSettings" id="LabelSettings_poli7"]
|
||||
font = SubResource("SystemFont_kgkwq")
|
||||
|
||||
[node name="PresetEntry" type="MarginContainer"]
|
||||
custom_minimum_size = Vector2(450, 0)
|
||||
anchors_preset = 14
|
||||
anchor_top = 0.5
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 0.5
|
||||
offset_top = -45.0
|
||||
offset_bottom = 45.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource("1_bqha3")
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Preset name"
|
||||
label_settings = SubResource("LabelSettings_poli7")
|
||||
|
||||
[node name="VSeparator" type="VSeparator" parent="MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LoadButtons" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="LoadStackOnly" type="Button" parent="MarginContainer/HBoxContainer/LoadButtons"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Load modifier stack"
|
||||
icon = ExtResource("1_0auay")
|
||||
alignment = 0
|
||||
|
||||
[node name="LoadFullPreset" type="Button" parent="MarginContainer/HBoxContainer/LoadButtons"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Load full preset"
|
||||
icon = ExtResource("1_0auay")
|
||||
alignment = 0
|
||||
|
||||
[node name="SaveButtons" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
size_flags_stretch_ratio = 2.0
|
||||
alignment = 1
|
||||
|
||||
[node name="OverrideButton" type="Button" parent="MarginContainer/HBoxContainer/SaveButtons"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Override preset"
|
||||
icon = ExtResource("1_0auay")
|
||||
alignment = 0
|
||||
|
||||
[node name="VSeparator2" type="VSeparator" parent="MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="DeleteButton" type="Button" parent="MarginContainer/HBoxContainer/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/icon_normal_color = Color(0.917647, 0.0784314, 0, 1)
|
||||
icon = ExtResource("2_p04k2")
|
||||
198
addons/proton_scatter/src/presets/presets.gd
Normal file
198
addons/proton_scatter/src/presets/presets.gd
Normal file
@@ -0,0 +1,198 @@
|
||||
@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
|
||||
90
addons/proton_scatter/src/presets/presets.tscn
Normal file
90
addons/proton_scatter/src/presets/presets.tscn
Normal file
@@ -0,0 +1,90 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://bcsosdvstytoq"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/proton_scatter/src/presets/presets.gd" id="1_ualle"]
|
||||
[ext_resource type="Texture2D" uid="uid://cun73k8jdmr4e" path="res://addons/proton_scatter/icons/add.svg" id="2_j26xt"]
|
||||
[ext_resource type="PackedScene" uid="uid://bosqtuvhckh3g" path="res://addons/proton_scatter/src/presets/preset_entry.tscn" id="2_orram"]
|
||||
|
||||
[node name="Presets" type="PopupPanel"]
|
||||
title = "Manage presets"
|
||||
initial_position = 2
|
||||
size = Vector2i(490, 200)
|
||||
unresizable = false
|
||||
borderless = false
|
||||
extend_to_title = true
|
||||
min_size = Vector2i(400, 150)
|
||||
script = ExtResource("1_ualle")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
offset_left = 4.0
|
||||
offset_top = 4.0
|
||||
offset_right = 486.0
|
||||
offset_bottom = 196.0
|
||||
theme_override_constants/margin_left = 12
|
||||
theme_override_constants/margin_top = 12
|
||||
theme_override_constants/margin_right = 12
|
||||
theme_override_constants/margin_bottom = 12
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
horizontal_scroll_mode = 0
|
||||
|
||||
[node name="PresetsRoot" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
alignment = 1
|
||||
|
||||
[node name="PresetEntry" parent="MarginContainer/VBoxContainer/ScrollContainer/PresetsRoot" instance=ExtResource("2_orram")]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="NewPresetButton" type="Button" parent="MarginContainer/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(200, 0)
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 4
|
||||
text = "Create new preset"
|
||||
icon = ExtResource("2_j26xt")
|
||||
|
||||
[node name="NewPresetDialog" type="ConfirmationDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
title = "Create new preset"
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="NewPresetDialog"]
|
||||
offset_left = 8.0
|
||||
offset_top = 8.0
|
||||
offset_right = 192.0
|
||||
offset_bottom = 51.0
|
||||
|
||||
[node name="NewPresetName" type="LineEdit" parent="NewPresetDialog/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 4
|
||||
placeholder_text = "New preset name"
|
||||
|
||||
[node name="DeleteDialog" type="ConfirmationDialog" parent="."]
|
||||
unique_name_in_owner = true
|
||||
title = "Delete preset"
|
||||
size = Vector2i(250, 184)
|
||||
ok_button_text = "Delete"
|
||||
dialog_autowrap = true
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="DeleteDialog"]
|
||||
offset_left = 8.0
|
||||
offset_top = 8.0
|
||||
offset_right = 242.0
|
||||
offset_bottom = 395.0
|
||||
|
||||
[node name="DeleteLabel" type="Label" parent="DeleteDialog/MarginContainer"]
|
||||
unique_name_in_owner = true
|
||||
custom_minimum_size = Vector2(250, 0)
|
||||
layout_mode = 2
|
||||
text = "Are you sure you want to delete preset [Preset]?
|
||||
|
||||
This operation cannot be undone."
|
||||
horizontal_alignment = 1
|
||||
autowrap_mode = 2
|
||||
Reference in New Issue
Block a user