Delegate storage of import data to separate class

This commit is contained in:
don-tnowe 2022-10-22 19:23:50 +03:00
parent 73b8d9cc41
commit 6ab9bcb96e
4 changed files with 205 additions and 163 deletions

View File

@ -1,21 +1,6 @@
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 := $"../.."
@ -24,30 +9,24 @@ onready var node_classname_field := $"TabContainer/Import/MarginContainer/Scroll
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
var import_data : SpreadsheetImport
var delimeter := ","
func _on_FileDialogText_file_selected(path : String):
self.path = path
import_data = SpreadsheetImport.new()
import_data.path = path
_open_dialog()
popup_centered()
func _open_dialog():
node_classname_field.text = TextEditingUtils\
.string_snake_to_naming_case(path.get_file().get_basename())\
.string_snake_to_naming_case(import_data.path.get_file().get_basename())\
.replace(" ", "")
_load_entries()
@ -57,7 +36,7 @@ func _open_dialog():
func _load_entries():
var file = File.new()
file.open(path, File.READ)
file.open(import_data.path, File.READ)
delimeter = ";"
var text_lines := [file.get_line().split(delimeter)]
@ -79,170 +58,86 @@ func _load_entries():
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()
import_data.prop_names = Array(entries[0])
import_data.prop_types.resize(import_data.prop_names.size())
import_data.prop_types.fill(4)
for i in import_data.prop_names.size():
import_data.prop_names[i] = entries[0][i].replace(" ", "_").to_lower()
if entries[1][i].is_valid_integer():
prop_types[i] = PropType.INT
import_data.prop_types[i] = SpreadsheetImport.PropType.INT
elif entries[1][i].is_valid_float():
prop_types[i] = PropType.REAL
import_data.prop_types[i] = SpreadsheetImport.PropType.REAL
elif entries[1][i].begins_with("res://"):
prop_types[i] = PropType.OBJECT
import_data.prop_types[i] = SpreadsheetImport.PropType.OBJECT
else: prop_types[i] = PropType.STRING
else: import_data.prop_types[i] = SpreadsheetImport.PropType.STRING
node_filename_options.clear()
for i in prop_names.size():
node_filename_options.add_item(prop_names[i], i)
for i in import_data.prop_names.size():
node_filename_options.add_item(import_data.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():
for i in import_data.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.display(import_data.prop_names[i], import_data.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"
var new_script = GDScript.new()
if import_data.script_classname != "":
new_script.source_code = "class_name " + import_data.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)
for i in import_data.prop_types.size():
if import_data.prop_types[i] == SpreadsheetImport.PropType.ENUM:
var cur_value := ""
uniques[i] = {}
for j in entries.size():
if j == 0 && import_data.remove_first_row: continue
cur_value = entries[j][i].replace(" ", "_").to_upper()
if cur_value == "":
cur_value = "N_A"
if !uniques[i].has(cur_value):
uniques[i][cur_value] = uniques[i].size()
new_script.source_code += import_data.create_enum_for_prop(i, uniques)
# Properties
for i in prop_names.size():
new_script.source_code += _create_property_line_for_prop(i)
for i in import_data.prop_names.size():
new_script.source_code += import_data.create_property_line_for_prop(i)
ResourceSaver.save(path.get_basename() + ".gd", new_script)
ResourceSaver.save(import_data.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
new_script = load(import_data.path.get_basename() + ".gd") # Because when instanced, objects have a copy of the script
import_data.new_script = new_script
func _export_tres_folder():
var dir = Directory.new()
dir.make_dir_recursive(path.get_basename())
dir.make_dir_recursive(import_data.path.get_basename())
var prop_used_as_filename_str : String = prop_names[property_used_as_filename]
import_data.prop_used_as_filename = import_data.prop_names[property_used_as_filename]
var new_res : Resource
for i in entries.size():
if remove_first_row && i == 0:
if import_data.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(" ", "_")])
new_res = import_data.strings_to_resource(entries[i], uniques)
ResourceSaver.save(new_res.resource_path, new_res)
func _on_Ok_pressed():
@ -250,17 +145,28 @@ func _on_Ok_pressed():
_generate_class()
_export_tres_folder()
yield(get_tree(), "idle_frame")
editor_view.display_folder(path.get_basename())
editor_view.display_folder(import_data.path.get_basename())
yield(get_tree(), "idle_frame")
editor_view.refresh()
func _on_OkSafe_pressed():
hide()
_generate_class()
import_data.save()
yield(get_tree(), "idle_frame")
editor_view.display_folder(import_data.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(" ", "")
import_data.script_classname = new_text.replace(" ", "")
func _on_remove_first_row_toggled(button_pressed : bool):
remove_first_row = button_pressed
import_data.remove_first_row = button_pressed
func _on_filename_options_item_selected(index):
@ -268,8 +174,8 @@ func _on_filename_options_item_selected(index):
func _on_list_item_type_selected(type : int, index : int):
prop_types[index] = type
import_data.prop_types[index] = type
func _on_list_item_name_changed(name : String, index : int):
prop_names[index] = name.replace(" ", "")
import_data.prop_names[index] = name.replace(" ", "")

View File

@ -94,20 +94,27 @@ 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
[node name="Ok2" type="Button" parent="TabContainer/Import/HBoxContainer"]
margin_left = 50.0
margin_right = 168.0
margin_bottom = 20.0
text = "Confirm"
text = "Confirm and edit"
[node name="Ok" type="Button" parent="TabContainer/Import/HBoxContainer"]
margin_left = 172.0
margin_right = 376.0
margin_bottom = 20.0
text = "Convert to Resources and edit"
[node name="Cancel" type="Button" parent="TabContainer/Import/HBoxContainer"]
margin_left = 248.0
margin_right = 302.0
margin_left = 380.0
margin_right = 434.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/Ok2" to="." method="_on_OkSafe_pressed"]
[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,120 @@
class_name SpreadsheetImport
extends Resource
enum PropType {
BOOL,
INT,
REAL,
STRING,
VECTOR2,
RECT2,
VECTOR3,
COLOR,
ARRAY,
OBJECT,
ENUM,
MAX,
}
var prop_types := []
var prop_names := []
var path := "res://"
var prop_used_as_filename := "name"
var script_classname := ""
var remove_first_row := true
var new_script : GDScript
func save():
resource_path = path.get_basename() + "_spreadsheet_import.tres"
ResourceSaver.save(resource_path, self)
func string_to_property(string : String, col_index : int, uniques : Dictionary):
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 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, uniques):
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 strings_to_resource(strings : Array, uniques : Dictionary):
var new_res = new_script.new()
for j in prop_names.size():
new_res.set(prop_names[j], string_to_property(strings[j], j, uniques))
new_res.resource_path = path.get_basename() + "/" + new_res.get(prop_used_as_filename) + ".tres"
return new_res

View File

@ -39,6 +39,12 @@ _global_script_classes=[ {
"language": "GDScript",
"path": "res://addons/resources_speadsheet_view/import_export/formats_edit/edit_tres.gd"
}, {
"base": "Resource",
"class": "SpreadsheetImport",
"language": "GDScript",
"path": "res://addons/resources_speadsheet_view/import_export/spreadsheet_import.gd"
}, {
"base": "Reference",
"class": "TextEditingUtils",
"language": "GDScript",
"path": "res://addons/resources_speadsheet_view/text_editing_utils.gd"
@ -58,6 +64,9 @@ _global_script_class_icons={
"CellEditorArray": "",
"SettingsGrid": "",
"SheetsDockEditor": "",
"SpreadsheetEditFormat": "",
"SpreadsheetEditFormatTres": "",
"SpreadsheetImport": "",
"TextEditingUtils": "",
"ThemeIconButton": "",
"ThemeStylebox": ""