Skip to content

Commit

Permalink
Add batch import, and remember the last directory.
Browse files Browse the repository at this point in the history
Implements most of #36 - The ability to select additional packages in a batch.
The selected file types are remembered within a batch.
Folder view and current directory are persisted in memory.
  • Loading branch information
lyuma committed Dec 29, 2023
1 parent 3ca052d commit da39df0
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 11 deletions.
146 changes: 137 additions & 9 deletions package_import_dialog.gd
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var meta_worker = meta_worker_class.new()
var asset_adapter = asset_adapter_class.new()
var object_adapter = object_adapter_class.new()

var editor_plugin: EditorPlugin = null
var main_dialog: AcceptDialog = null
var file_dialog: EditorFileDialog = null
var main_dialog_tree: Tree = null
Expand Down Expand Up @@ -60,6 +61,7 @@ var checkbox_on_unicode: String = "\u2611"
var tmpdir: String = ""
var asset_database: asset_database_class = null

var current_selected_package: String
var tree_dialog_state: int = 0
var path_to_tree_item: Dictionary
var guid_to_dependency_guids: Dictionary
Expand All @@ -71,6 +73,8 @@ var _preprocessing_second_pass: Array = []
var retry_tex: bool = false
var _keep_open_on_import: bool = false
var paused: bool = false
var auto_import: bool = false
var _meta_work_count: int = 0

var auto_hide_checkbox: CheckBox
var dont_auto_select_dependencies_checkbox: CheckBox
Expand All @@ -83,6 +87,12 @@ var debug_disable_silhouette_fix_checkbox: CheckBox
var force_humanoid_checkbox: CheckBox
var enable_verbose_log_checkbox: CheckBox

var batch_import_list_widget: ItemList
var batch_import_add_button: Button

var batch_import_file_list: PackedStringArray
var batch_import_types: Dictionary

var progress_bar : ProgressBar
var status_bar : Label
var options_vbox : VBoxContainer
Expand Down Expand Up @@ -157,17 +167,23 @@ func _set_indeterminate_up_recursively(ti: TreeItem, is_checked: bool):
ti.set_indeterminate(0, false)
ti.set_checked(0, true)
_set_indeterminate_up_recursively(ti.get_parent(), is_checked)
if ti == select_by_type_items.get(ti.get_text(0)):
batch_import_types[ti.get_text(0)] = true
elif is_all_unchecked:
if ti.is_indeterminate(0) or ti.is_checked(0):
ti.set_indeterminate(0, false)
ti.set_checked(0, false)
_set_indeterminate_up_recursively(ti.get_parent(), is_checked)
if ti == select_by_type_items.get(ti.get_text(0)):
batch_import_types[ti.get_text(0)] = true
else:
if not ti.is_indeterminate(0):
ti.set_checked(0, false)
ti.set_indeterminate(0, true)
ti.set_checked(0, false)
_set_indeterminate_up_recursively(ti.get_parent(), is_checked)
if ti == select_by_type_items.get(ti.get_text(0)):
batch_import_types[ti.get_text(0)] = false


func _check_recursively(ti: TreeItem, is_checked: bool, process_dependencies: bool, visited_set: Dictionary={}, is_recursive_file: bool=false) -> void:
Expand All @@ -176,6 +192,8 @@ func _check_recursively(ti: TreeItem, is_checked: bool, process_dependencies: bo
if visited_set.has(ti):
return
visited_set[ti] = true
if ti == select_by_type_items.get(ti.get_text(0)):
batch_import_types[ti.get_text(0)] = is_checked
var other_item: TreeItem = ti.get_metadata(1) as TreeItem
if other_item != null:
_check_recursively(other_item, is_checked, false, visited_set, false)
Expand Down Expand Up @@ -459,6 +477,7 @@ func human_readable_fileid_heuristic(fileID: int) -> String:
return str(fileID)

func _meta_completed(tw: Object):
_meta_work_count -= 1
var pkgasset = tw.asset
var ti = tw.extra as TreeItem
var importer_type: String = ""
Expand All @@ -472,14 +491,17 @@ func _meta_completed(tw: Object):
importer_type = "[" + object_adapter.utype_to_classname[clsid] + "]"
var dep_guids: Dictionary = pkgasset.parsed_meta.meta_dependency_guids.duplicate()
if importer_type == "[LightingDataAsset]":
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if batch_import_types.get(".asset LightingDataAsset", false) == false:
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if importer_type == "[MonoScript]" or importer_type == "Mono" or importer_type == "":
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if batch_import_types.get(".cs Script", false) == false:
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if importer_type == "[Shader]" or importer_type == "Shader":
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if batch_import_types.get(".shader Shader", false) == false:
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
for guid in pkgasset.parsed_meta.dependency_guids:
dep_guids[guid] = pkgasset.parsed_meta.dependency_guids[guid]
var da := DirAccess.open("res://")
Expand Down Expand Up @@ -546,15 +568,29 @@ func _meta_completed(tw: Object):
var clsid: int = pkgasset.parsed_meta.main_object_id / 100000
if object_adapter.utype_to_classname.has(clsid):
obj_type = object_adapter.utype_to_classname[clsid]
if pkgasset.orig_pathname.to_lower().ends_with(".cs"):
obj_type = "Script"
if pkgasset.orig_pathname.to_lower().ends_with(".shader"):
obj_type = "Shader"
var select_by_type_item: TreeItem
var type_parent: TreeItem
var obj_type_desc = "." + pkgasset.orig_pathname.get_extension() + " " + obj_type
if auto_import:
if batch_import_types.get(obj_type_desc, true) == false:
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)
if pkgasset.orig_pathname.to_lower().ends_with(".dll") or pkgasset.orig_pathname.to_lower().ends_with(".dylib") or pkgasset.orig_pathname.to_lower().ends_with(".so"):
ignore_dependencies[pkgasset.guid] = true
_check_recursively(ti, false, false)

if select_by_type_items.has(obj_type_desc):
type_parent = select_by_type_items[obj_type_desc]
if type_parent.is_checked(0) and not ti.is_checked(0):
type_parent.set_indeterminate(0, true)
batch_import_types[obj_type_desc] = true
if not type_parent.is_checked(0) and ti.is_checked(0):
type_parent.set_indeterminate(0, true)
batch_import_types[obj_type_desc] = true
else:
var insert_idx: int = 0
for chld in select_by_type_tree_item.get_children():
Expand All @@ -570,6 +606,7 @@ func _meta_completed(tw: Object):
type_parent.set_collapsed_recursive(true)
type_parent.set_checked(0, ti.is_checked(0))
select_by_type_items[obj_type_desc] = type_parent
batch_import_types[obj_type_desc] = ti.is_checked(0)
select_by_type_item = type_parent.create_child()
select_by_type_item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK)
select_by_type_item.set_checked(0, ti.is_checked(0))
Expand All @@ -584,6 +621,10 @@ func _meta_completed(tw: Object):
select_by_type_item.set_metadata(1, ti)
ti.set_metadata(1, select_by_type_item)

if _meta_work_count <= 0:
if auto_import:
_asset_tree_window_confirmed()


func _prune_unselected_items(p_ti: TreeItem) -> bool:
# Directories might be unchecked but have children which are checked.
Expand Down Expand Up @@ -637,6 +678,13 @@ func _prune_unselected_items(p_ti: TreeItem) -> bool:


func _selected_package(p_path: String) -> void:
current_selected_package = p_path
main_dialog.title = "Select Assets to import from " + current_selected_package.get_file()
print(editor_plugin)
if editor_plugin != null:
editor_plugin.last_selected_dir = file_dialog.current_dir
editor_plugin.file_dialog_mode = file_dialog.display_mode
print("CURRENT DIR " + file_dialog.current_dir)
if p_path.to_lower().contains("technologies"):
OS.alert("Beware that this package may use a non-standard license.\nPlease take the time to double-check that you are\nin compliance with all licenses.")
_preprocessing_second_pass = [].duplicate()
Expand Down Expand Up @@ -688,6 +736,20 @@ func _selected_package(p_path: String) -> void:
enable_verbose_log_checkbox = _add_checkbox_option(options_vbox, "Enable verbose logs", true if asset_database.enable_verbose_logs else false)
enable_verbose_log_checkbox.toggled.connect(self._enable_verbose_log_changed)

batch_import_list_widget = ItemList.new()
batch_import_list_widget.item_activated.connect(self._batch_import_list_widget_activated)
options_vbox.add_child(batch_import_list_widget)
batch_import_add_button = Button.new()
batch_import_add_button.text = "Add extra packages to batch"
batch_import_add_button.pressed.connect(self._add_batch_import)
batch_import_add_button.tooltip_text = """
Batch import additional .unitypackage archives.
Double-click a package to remove it from the list.
The file type checkboxes to the right will determine which files are imported from the batch.
"""
options_vbox.add_child(batch_import_add_button)

meta_worker.start_threads(THREAD_COUNT) # Don't DISABLE_THREADING
main_dialog_tree.hide_root = true
main_dialog_tree.create_item()
Expand Down Expand Up @@ -748,6 +810,7 @@ func _selected_package(p_path: String) -> void:
ti.set_icon(0, icon)
if i == len(path_names) - 1:
meta_worker.push_asset(pkgasset, ti)
_meta_work_count += 1
ti.set_text(1, "")
else:
ti.set_text(1, "Directory")
Expand Down Expand Up @@ -797,23 +860,28 @@ func do_reimport_previous_files() -> void:
main_dialog.show()


func show_reimport() -> void:
func show_reimport(ep: EditorPlugin) -> void:
editor_plugin = ep
file_dialog = null
_show_importer_common()
self._selected_package("")


func show_importer() -> void:
func show_importer(ep: EditorPlugin) -> void:
file_dialog = EditorFileDialog.new()
file_dialog.add_filter("*.unitypackage, *.meta", "Asset packages or file")
file_dialog.show_hidden_files = true
editor_plugin = ep
file_dialog.file_mode = EditorFileDialog.FILE_MODE_OPEN_ANY
# FILE_MODE_OPEN_FILE = 0 – The dialog allows selecting one, and only one file.
file_dialog.access = EditorFileDialog.ACCESS_FILESYSTEM
file_dialog.set_title("Import .unitypackage archive, or Select Assets folder...")
file_dialog.file_selected.connect(self._selected_package)
file_dialog.dir_selected.connect(self._selected_package)
EditorPlugin.new().get_editor_interface().get_base_control().add_child(file_dialog, true)
ep.get_editor_interface().get_base_control().add_child(file_dialog, true)
if ep.get("last_selected_dir"):
file_dialog.current_dir = ep.last_selected_dir
file_dialog.display_mode = ep.file_dialog_mode
_show_importer_common()
check_fbx2gltf()

Expand Down Expand Up @@ -880,6 +948,48 @@ func _force_humanoid_changed(val: bool):
func _enable_verbose_log_changed(val: bool):
asset_database.enable_verbose_logs = val

func _add_batch_import():
if file_dialog:
file_dialog.queue_free()
file_dialog = null
file_dialog = EditorFileDialog.new()
file_dialog.add_filter("*.unitypackage", "Only asset packages supported")
file_dialog.show_hidden_files = true
file_dialog.file_mode = EditorFileDialog.FILE_MODE_OPEN_FILES
# FILE_MODE_OPEN_FILE = 0 – The dialog allows selecting one, and only one file.
file_dialog.access = EditorFileDialog.ACCESS_FILESYSTEM
file_dialog.set_title("Batch import additional .unitypackage archives...")
file_dialog.file_selected.connect(self._selected_batch_import_file)
file_dialog.files_selected.connect(self._selected_batch_import_files)
EditorPlugin.new().get_editor_interface().get_base_control().add_child(file_dialog, true)
if editor_plugin != null:
file_dialog.current_dir = editor_plugin.last_selected_dir
file_dialog.display_mode = editor_plugin.file_dialog_mode
if file_dialog != null:
file_dialog.popup_centered_ratio()

func _selected_batch_import_file(path: String):
_selected_batch_import_files(PackedStringArray([path]))

func _selected_batch_import_files(paths: PackedStringArray):
if editor_plugin != null:
editor_plugin.last_selected_dir = file_dialog.current_dir
editor_plugin.file_dialog_mode = file_dialog.display_mode
var cur_files: Dictionary
cur_files[current_selected_package] = true
for path in batch_import_file_list:
cur_files[path] = true
for path in paths:
batch_import_list_widget.custom_minimum_size = Vector2(100, 100)
if not cur_files.has(path):
batch_import_list_widget.add_item(path.get_file())
batch_import_list_widget.set_item_tooltip(batch_import_list_widget.item_count - 1, path)
batch_import_file_list.append(path)

func _batch_import_list_widget_activated(idx: int):
batch_import_list_widget.remove_item(idx)
batch_import_file_list.remove_at(idx)


func _pause_toggled(val: bool):
paused = val
Expand Down Expand Up @@ -1031,6 +1141,24 @@ func on_import_fully_completed():
main_dialog.hide()
ProjectSettings.set_setting("memory/limits/message_queue/max_size_mb", asset_database.orig_max_size_mb)

if not batch_import_file_list.is_empty():
var rc = RefCounted.new()
rc.set_script(get_script())
rc._show_importer_common()
rc.batch_import_file_list = batch_import_file_list.slice(1)
rc.batch_import_types = batch_import_types
rc.auto_import = true
rc._keep_open_on_import = _keep_open_on_import
rc._selected_package(batch_import_file_list[0])
rc.batch_import_file_list = batch_import_file_list.slice(1)
rc.batch_import_types = batch_import_types
rc.auto_import = true
rc._keep_open_on_import = _keep_open_on_import
if rc.batch_import_list_widget != null:
for f in rc.batch_import_file_list:
rc.batch_import_list_widget.add_item(f)
rc.main_dialog.title = "Batch importing " + batch_import_file_list[0] + "..."


func update_task_color(tw: RefCounted):
var ti: TreeItem = tw.extra
Expand Down
6 changes: 4 additions & 2 deletions plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const tarfile = preload("./tarfile.gd")
const package_import_dialog_class: GDScript = preload("./package_import_dialog.gd")

var package_import_dialog: RefCounted = null
var last_selected_dir: String = ""
var file_dialog_mode := EditorFileDialog.DISPLAY_LIST


func recursive_print(node: Node, indent: String = ""):
Expand All @@ -31,15 +33,15 @@ func show_reimport():
package_import_dialog.show_importer_logs()
return
package_import_dialog = package_import_dialog_class.new()
package_import_dialog.show_reimport()
package_import_dialog.show_reimport(self)


func show_importer():
if package_import_dialog != null and package_import_dialog.paused:
package_import_dialog.show_importer_logs()
return
package_import_dialog = package_import_dialog_class.new()
package_import_dialog.show_importer()
package_import_dialog.show_importer(self)

func show_importer_logs():
if package_import_dialog != null:
Expand Down

0 comments on commit da39df0

Please sign in to comment.