Implement CSV into TRES conversion

This commit is contained in:
don-tnowe 2022-10-22 17:39:38 +03:00
parent 744436e66d
commit 977932e017
7 changed files with 474 additions and 7 deletions

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=2]
[gd_scene load_steps=21 format=2]
[ext_resource path="res://addons/resources_speadsheet_view/editor_view.gd" type="Script" id=1]
[ext_resource path="res://addons/resources_speadsheet_view/typed_cells/cell_editor_string.gd" type="Script" id=2]
@ -17,6 +17,7 @@
[ext_resource path="res://addons/resources_speadsheet_view/typed_cells/cell_editor_enum_array.gd" type="Script" id=15]
[ext_resource path="res://addons/resources_speadsheet_view/typed_editors/dock_enum_array.tscn" type="PackedScene" id=16]
[ext_resource path="res://addons/resources_speadsheet_view/table_pages.gd" type="Script" id=17]
[ext_resource path="res://addons/resources_speadsheet_view/import_export/import_export_dialog.tscn" type="PackedScene" id=18]
[sub_resource type="Image" id=3]
data = {
@ -158,7 +159,7 @@ text = "Resource Folder:"
[node name="Path" type="LineEdit" parent="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer"]
unique_name_in_owner = true
margin_left = 107.0
margin_right = 553.0
margin_right = 525.0
margin_bottom = 24.0
size_flags_horizontal = 3
caret_blink = true
@ -168,8 +169,8 @@ __meta__ = {
}
[node name="SelectDir" type="Button" parent="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 553.0
margin_right = 581.0
margin_left = 525.0
margin_right = 553.0
margin_bottom = 24.0
hint_tooltip = "Open Folder"
icon = SubResource( 2 )
@ -179,6 +180,18 @@ __meta__ = {
}
icon_name = "Folder"
[node name="SelectFile" type="Button" parent="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 553.0
margin_right = 581.0
margin_bottom = 24.0
hint_tooltip = "Import/Export Text File"
icon = SubResource( 2 )
script = ExtResource( 4 )
__meta__ = {
"_edit_lock_": true
}
icon_name = "File"
[node name="Refresh" type="Button" parent="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer"]
margin_left = 581.0
margin_right = 609.0
@ -523,6 +536,32 @@ window_title = "Open a Folder"
mode_overrides_title = false
mode = 2
[node name="FileDialogText" type="FileDialog" parent="Control"]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -307.0
margin_top = -192.0
margin_right = 307.0
margin_bottom = 192.0
rect_min_size = Vector2( 150, 52.5 )
window_title = "Open a Folder"
mode_overrides_title = false
mode = 0
filters = PoolStringArray( "*.csv" )
[node name="ImportExport" parent="Control" instance=ExtResource( 18 )]
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
margin_left = -246.5
margin_top = -147.0
margin_right = 246.5
margin_bottom = 147.0
resizable = true
[node name="Info" type="AcceptDialog" parent="Control"]
anchor_left = 0.5
anchor_top = 0.5
@ -705,6 +744,7 @@ text = "Enable"
[connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer2/Info" to="Control/Info" method="popup_centered"]
[connection signal="text_entered" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer/Path" to="." method="_on_Path_text_entered"]
[connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer/SelectDir" to="Control/FileDialog" method="popup_centered"]
[connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer/SelectFile" to="Control/FileDialogText" method="popup_centered"]
[connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer/Refresh" to="." method="_on_Path_text_entered"]
[connection signal="pressed" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer/DeletePath" to="." method="remove_selected_path_from_recent"]
[connection signal="item_selected" from="HeaderContentSplit/VBoxContainer/HBoxContainer/HBoxContainer2/RecentPaths" to="." method="_on_RecentPaths_item_selected"]
@ -712,3 +752,4 @@ text = "Enable"
[connection signal="text_entered" from="HeaderContentSplit/MarginContainer/FooterContentSplit/Footer/Search/SearchCond" to="." method="_on_SearchCond_text_entered"]
[connection signal="text_entered" from="HeaderContentSplit/MarginContainer/FooterContentSplit/Footer/Search/ProcessExpr" to="." method="_on_ProcessExpr_text_entered"]
[connection signal="dir_selected" from="Control/FileDialog" to="." method="_on_FileDialog_dir_selected"]
[connection signal="file_selected" from="Control/FileDialogText" to="Control/ImportExport" method="_on_FileDialogText_file_selected"]

View File

@ -0,0 +1,275 @@
tool
extends WindowDialog
enum PropType {
BOOL,
INT,
REAL,
STRING,
VECTOR2,
RECT2,
VECTOR3,
COLOR,
ARRAY,
OBJECT,
ENUM,
MAX,
}
export var prop_list_item_scene : PackedScene
onready var editor_view := $"../.."
onready var node_filename_options := $"TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/OptionButton"
onready var node_classname_field := $"TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/LineEdit"
onready var node_filename_props := $"TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/OptionButton"
onready var prop_list := $"TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer"
var prop_types := []
var prop_names := []
var entries := []
var uniques := {}
var delimeter := ""
var path := "res://"
var property_used_as_filename := 0
var script_classname := ""
var remove_first_row := true
var new_script : GDScript
func _on_FileDialogText_file_selected(path : String):
self.path = path
_open_dialog()
popup_centered()
func _open_dialog():
node_classname_field.text = TextEditingUtils\
.string_snake_to_naming_case(path.get_file().get_basename())\
.replace(" ", "")
_load_entries()
_load_property_names()
_create_prop_editors()
func _load_entries():
var file = File.new()
file.open(path, File.READ)
delimeter = ";"
var text_lines := [file.get_line().split(delimeter)]
var line = text_lines[0]
if line.size() == 1:
delimeter = ","
text_lines[0] = text_lines[0][0].split(delimeter)
while !file.eof_reached():
line = file.get_csv_line(delimeter)
if line.size() == text_lines[0].size():
text_lines.append(line)
entries = []
entries.resize(text_lines.size())
for i in entries.size():
entries[i] = text_lines[i]
func _load_property_names():
prop_names = Array(entries[0])
prop_types.resize(prop_names.size())
prop_types.fill(4)
for i in prop_names.size():
prop_names[i] = entries[0][i].replace(" ", "_").to_lower()
if entries[1][i].is_valid_integer():
prop_types[i] = PropType.INT
elif entries[1][i].is_valid_float():
prop_types[i] = PropType.REAL
elif entries[1][i].begins_with("res://"):
prop_types[i] = PropType.OBJECT
else: prop_types[i] = PropType.STRING
node_filename_options.clear()
for i in prop_names.size():
node_filename_options.add_item(prop_names[i], i)
func _create_prop_editors():
for x in prop_list.get_children():
if !x is GridContainer: x.free()
for i in prop_names.size():
var new_node = prop_list_item_scene.instance()
prop_list.add_child(new_node)
new_node.display(prop_names[i], prop_types[i])
new_node.connect_all_signals(self, i)
func _generate_class():
new_script = GDScript.new()
if script_classname != "":
new_script.source_code = "class_name " + script_classname + " \nextends Resource\n\n"
else:
new_script.source_code = "extends Resource\n\n"
# Enums
uniques = {}
for i in prop_types.size():
if prop_types[i] == PropType.ENUM:
new_script.source_code += _create_enum_for_prop(i)
# Properties
for i in prop_names.size():
new_script.source_code += _create_property_line_for_prop(i)
ResourceSaver.save(path.get_basename() + ".gd", new_script)
new_script.reload()
new_script = load(path.get_basename() + ".gd") # Because when instanced, objects have a copy of the script
func _export_tres_folder():
var dir = Directory.new()
dir.make_dir_recursive(path.get_basename())
var prop_used_as_filename_str : String = prop_names[property_used_as_filename]
var new_res : Resource
for i in entries.size():
if remove_first_row && i == 0:
continue
new_res = new_script.new()
for j in prop_names.size():
new_res.set(prop_names[j], _string_to_property(entries[i][j], j))
new_res.resource_path = path.get_basename() + "/" + new_res.get(prop_used_as_filename_str) + ".tres"
ResourceSaver.save(new_res.resource_path, new_res)
func _create_property_line_for_prop(col_index : int):
var result = "export var " + prop_names[col_index] + " :"
match prop_types[col_index]:
PropType.STRING:
return result + "= \"\"\n"
PropType.BOOL:
return result + "= false\n"
PropType.REAL:
return result + "= 0.0\n"
PropType.INT:
return result + "= 0\n"
PropType.COLOR:
return result + "= Color.white\n"
PropType.OBJECT:
return result + " Resource\n"
PropType.ENUM:
return result.replace(
"export var",
"export("
+ TextEditingUtils.string_snake_to_naming_case(
prop_names[col_index]
).replace(" ", "")
+ ") var"
) + "= 0\n"
func _create_enum_for_prop(col_index):
# Find all uniques
var cur_value := ""
uniques[col_index] = {}
for i in entries.size():
if i == 0 && remove_first_row: continue
cur_value = entries[i][col_index].replace(" ", "_").to_upper()
if cur_value == "":
cur_value = "N_A"
if !uniques[col_index].has(cur_value):
uniques[col_index][cur_value] = uniques[col_index].size()
# Write to script
var result := (
"enum "
+ TextEditingUtils.string_snake_to_naming_case(prop_names[col_index]).replace(" ", "")
+ " {\n"
)
for k in uniques[col_index]:
result += (
"\t"
+ k # Enum Entry
+ " = "
+ str(uniques[col_index][k]) # Value
+ ",\n"
)
result += "\tMAX,\n}\n\n"
return result
func _string_to_property(string : String, col_index : int):
match prop_types[col_index]:
PropType.STRING:
return string
PropType.BOOL:
string = string.to_lower()
return !string in ["no", "disabled", "-", "false", "absent", "wrong", ""]
PropType.REAL:
return string.to_float()
PropType.INT:
return string.to_int()
PropType.COLOR:
return Color(string)
PropType.OBJECT:
return load(string)
PropType.ENUM:
if string == "":
return int(uniques[col_index]["N_A"])
else:
return int(uniques[col_index][string.to_upper().replace(" ", "_")])
func _on_Ok_pressed():
hide()
_generate_class()
_export_tres_folder()
yield(get_tree(), "idle_frame")
editor_view.display_folder(path.get_basename())
yield(get_tree(), "idle_frame")
editor_view.refresh()
# Input controls
func _on_classname_field_text_changed(new_text : String):
script_classname = new_text.replace(" ", "")
func _on_remove_first_row_toggled(button_pressed : bool):
remove_first_row = button_pressed
func _on_filename_options_item_selected(index):
property_used_as_filename = index
func _on_list_item_type_selected(type : int, index : int):
prop_types[index] = type
func _on_list_item_name_changed(name : String, index : int):
prop_names[index] = name.replace(" ", "")

View File

@ -0,0 +1,113 @@
[gd_scene load_steps=3 format=2]
[ext_resource path="res://addons/resources_speadsheet_view/import_export/import_export_dialog.gd" type="Script" id=1]
[ext_resource path="res://addons/resources_speadsheet_view/import_export/property_list_item.tscn" type="PackedScene" id=2]
[node name="Control" type="WindowDialog"]
pause_mode = 2
margin_right = 493.0
margin_bottom = 294.0
popup_exclusive = true
window_title = "Import/Export As Text"
script = ExtResource( 1 )
prop_list_item_scene = ExtResource( 2 )
[node name="TabContainer" type="TabContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
tab_align = 0
[node name="Import" type="VBoxContainer" parent="TabContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 4.0
margin_top = 32.0
margin_right = -4.0
margin_bottom = -4.0
[node name="MarginContainer" type="MarginContainer" parent="TabContainer/Import"]
margin_right = 485.0
margin_bottom = 234.0
size_flags_vertical = 3
custom_constants/margin_right = 4
custom_constants/margin_top = 4
custom_constants/margin_left = 4
custom_constants/margin_bottom = 0
[node name="ScrollContainer" type="ScrollContainer" parent="TabContainer/Import/MarginContainer"]
margin_left = 4.0
margin_top = 4.0
margin_right = 481.0
margin_bottom = 234.0
scroll_horizontal_enabled = false
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer"]
margin_right = 477.0
margin_bottom = 76.0
size_flags_horizontal = 3
[node name="GridContainer" type="GridContainer" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer"]
margin_right = 477.0
margin_bottom = 76.0
columns = 2
[node name="Label" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_top = 3.0
margin_right = 246.0
margin_bottom = 17.0
text = "Use as filename:"
[node name="OptionButton" type="OptionButton" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_left = 250.0
margin_right = 477.0
margin_bottom = 20.0
size_flags_horizontal = 3
[node name="Label2" type="Label" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_top = 29.0
margin_right = 246.0
margin_bottom = 43.0
text = "Class Name"
[node name="LineEdit" type="LineEdit" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_left = 250.0
margin_top = 24.0
margin_right = 477.0
margin_bottom = 48.0
[node name="CheckBox" type="CheckBox" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_top = 52.0
margin_right = 246.0
margin_bottom = 76.0
pressed = true
text = "First row contains property names"
[node name="Control" type="Control" parent="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer"]
margin_left = 250.0
margin_top = 52.0
margin_right = 477.0
margin_bottom = 76.0
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Import"]
margin_top = 238.0
margin_right = 485.0
margin_bottom = 258.0
alignment = 1
[node name="Ok" type="Button" parent="TabContainer/Import/HBoxContainer"]
margin_left = 182.0
margin_right = 244.0
margin_bottom = 20.0
text = "Confirm"
[node name="Cancel" type="Button" parent="TabContainer/Import/HBoxContainer"]
margin_left = 248.0
margin_right = 302.0
margin_bottom = 20.0
text = "Cancel"
[connection signal="item_selected" from="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/OptionButton" to="." method="_on_filename_options_item_selected"]
[connection signal="text_changed" from="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/LineEdit" to="." method="_on_classname_field_text_changed"]
[connection signal="toggled" from="TabContainer/Import/MarginContainer/ScrollContainer/VBoxContainer/GridContainer/CheckBox" to="." method="_on_remove_first_row_toggled"]
[connection signal="pressed" from="TabContainer/Import/HBoxContainer/Ok" to="." method="_on_Ok_pressed"]
[connection signal="pressed" from="TabContainer/Import/HBoxContainer/Cancel" to="." method="hide"]

View File

@ -0,0 +1,12 @@
tool
extends HBoxContainer
func display(name : String, type : int):
$"LineEdit".text = name
$"OptionButton".selected = type
func connect_all_signals(to : Object, index : int, prefix : String = "_on_list_item_"):
$"LineEdit".connect("text_changed", to, prefix + "name_changed", [index])
$"OptionButton".connect("item_selected", to, prefix + "type_selected", [index])

View File

@ -0,0 +1,26 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://addons/resources_speadsheet_view/import_export/property_list_item.gd" type="Script" id=1]
[node name="Entry" type="HBoxContainer"]
margin_right = 468.0
margin_bottom = 24.0
script = ExtResource( 1 )
[node name="LineEdit" type="LineEdit" parent="."]
margin_right = 309.0
margin_bottom = 24.0
size_flags_horizontal = 3
size_flags_stretch_ratio = 0.5
text = "1"
[node name="OptionButton" type="OptionButton" parent="."]
margin_left = 313.0
margin_right = 468.0
margin_bottom = 24.0
size_flags_horizontal = 3
size_flags_vertical = 5
size_flags_stretch_ratio = 0.25
text = "Bool"
items = [ "Bool", null, false, 1, null, "Integer Number", null, false, 2, null, "Floating Point Number", null, false, 3, null, "String/Other", null, false, 4, null, "Vector2", null, true, 5, null, "Rect2", null, true, 6, null, "Vector3", null, true, 7, null, "Color", null, false, 14, null, "Array", null, true, 19, null, "Resource Path", null, false, 17, null, "Enumeration", null, false, 101, null ]
selected = 0

View File

@ -5,5 +5,5 @@ description="Edit Many Resources from one Folder as a table.
Heavily inspired by Multi-Cursor-Editing in text editors, so after selecting multiple cells (in the same column!) using Ctrl+Click or Shift+Click, most Basic-to-Intermediate movements should be available."
author="Don Tnowe"
version="1.6"
version="1.7"
script="plugin.gd"

View File

@ -3,7 +3,7 @@
[ext_resource path="res://addons/resources_speadsheet_view/table_header.gd" type="Script" id=1]
[ext_resource path="res://addons/resources_speadsheet_view/editor_icon_button.gd" type="Script" id=2]
[sub_resource type="Image" id=3]
[sub_resource type="Image" id=1]
data = {
"data": PoolByteArray( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ),
"format": "LumAlpha8",
@ -15,7 +15,7 @@ data = {
[sub_resource type="ImageTexture" id=2]
flags = 4
flags = 4
image = SubResource( 3 )
image = SubResource( 1 )
size = Vector2( 16, 16 )
[node name="Header" type="HBoxContainer"]