Skip to content

Commit 403cdc3

Browse files
authored
Allow defining a custom path for data.pandora and pandora definitions dir (#225)
1 parent 48ec6e4 commit 403cdc3

File tree

7 files changed

+149
-46
lines changed

7 files changed

+149
-46
lines changed

addons/pandora/api.gd

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ var _backend_load_state: PandoraEntityBackend.LoadState = PandoraEntityBackend.L
2424

2525

2626
func _enter_tree() -> void:
27-
self._storage = PandoraJsonDataStorage.new("res://")
27+
var data_path := PandoraSettings.get_data_path()
28+
29+
self._storage = PandoraJsonDataStorage.new(data_path.get_base_dir())
2830
self._context_manager = PandoraContextManager.new()
2931
self._id_generator = PandoraIDGenerator.new()
3032
self._entity_backend = PandoraEntityBackend.new(_id_generator)
@@ -179,7 +181,7 @@ func calculate_import_data(path: String) -> int:
179181
else:
180182
(
181183
import_calculation_ended
182-
. emit(
184+
.emit(
183185
{
184186
"total_categories": imported_data["_entity_data"]["_categories"].size(),
185187
"total_entities": imported_data["_entity_data"]["_entities"].size(),

addons/pandora/plugin.gd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func _exit_tree() -> void:
5656
remove_autoload_singleton("Pandora")
5757

5858

59-
func _make_visible(visible:bool) -> void:
59+
func _make_visible(visible: bool) -> void:
6060
if Engine.is_editor_hint() and is_instance_valid(editor_view):
6161
editor_view.visible = visible
6262

@@ -75,12 +75,12 @@ func _get_plugin_icon() -> Texture2D:
7575
class PandoraExportPlugin extends EditorExportPlugin:
7676
# Override the _export_begin method to add the data.pandora file during export
7777
func _export_begin(features: PackedStringArray, is_debug: bool, path: String, flags: int):
78-
var pandora_path = "res://data.pandora"
78+
var pandora_path = PandoraSettings.get_data_path()
7979
var file = FileAccess.open(pandora_path, FileAccess.READ)
8080
if not file:
81-
printerr("Unable to export Pandora data: ", FileAccess.get_open_error())
81+
printerr("Unable to export Pandora data: ", FileAccess.get_open_error())
8282
return
83-
var data:PackedByteArray = file.get_buffer(file.get_length())
83+
var data: PackedByteArray = file.get_buffer(file.get_length())
8484
if not is_debug:
8585
var text = file.get_as_text()
8686
data = Compression.compress(text)

addons/pandora/settings/pandora_settings.gd

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ class_name PandoraSettings
33
extends RefCounted
44

55
enum IDType {
6-
SEQUENTIAL,
7-
NANOID,
6+
SEQUENTIAL,
7+
NANOID,
88
}
99

1010
const CATEGORY_MAIN: StringName = "pandora"
@@ -14,43 +14,85 @@ const SETTING_ID_TYPE: StringName = CATEGORY_CONFIG + "/id_type"
1414

1515
const DEFAULT_ID_TYPE: IDType = IDType.SEQUENTIAL
1616

17+
const SETTING_PANDORA_DATA_PATH: StringName = CATEGORY_CONFIG + "/data_path"
18+
const DEFAULT_PANDORA_DATA_PATH: StringName = "res://data.pandora"
19+
20+
const SETTINGS_PANDORA_DEFINITIONS_DIR: StringName = CATEGORY_CONFIG + "/definitions_dir"
21+
const DEFAULT_PANDORA_DEFINITIONS_DIR: StringName = "res://pandora/"
22+
1723

1824
static func initialize() -> void:
19-
init_setting(
20-
SETTING_ID_TYPE,
21-
IDType.keys()[DEFAULT_ID_TYPE],
22-
TYPE_STRING,
23-
PROPERTY_HINT_ENUM,
24-
"%s,%s" % IDType.keys()
25-
)
25+
init_setting(
26+
SETTING_ID_TYPE,
27+
IDType.keys()[DEFAULT_ID_TYPE],
28+
TYPE_STRING,
29+
PROPERTY_HINT_ENUM,
30+
"%s,%s" % IDType.keys()
31+
)
32+
33+
init_setting(
34+
SETTING_PANDORA_DATA_PATH,
35+
DEFAULT_PANDORA_DATA_PATH,
36+
TYPE_STRING,
37+
PROPERTY_HINT_FILE,
38+
)
39+
40+
init_setting(
41+
SETTINGS_PANDORA_DEFINITIONS_DIR,
42+
DEFAULT_PANDORA_DEFINITIONS_DIR,
43+
TYPE_STRING,
44+
PROPERTY_HINT_DIR
45+
)
2646

2747

2848
static func init_setting(
29-
name: String,
30-
default: Variant,
31-
type := typeof(default),
32-
hint := PROPERTY_HINT_NONE,
33-
hint_string := ""
49+
name: String,
50+
default: Variant,
51+
type := typeof(default),
52+
hint := PROPERTY_HINT_NONE,
53+
hint_string := ""
3454
) -> void:
35-
if not ProjectSettings.has_setting(name):
36-
ProjectSettings.set_setting(name, default)
55+
if not ProjectSettings.has_setting(name):
56+
ProjectSettings.set_setting(name, default)
3757

38-
ProjectSettings.set_initial_value(name, default)
58+
ProjectSettings.set_initial_value(name, default)
3959

40-
var info = {
41-
"name": name,
42-
"type": type,
43-
"hint": hint,
44-
"hint_string": hint_string,
45-
}
46-
ProjectSettings.add_property_info(info)
60+
var info = {
61+
"name": name,
62+
"type": type,
63+
"hint": hint,
64+
"hint_string": hint_string,
65+
}
66+
ProjectSettings.add_property_info(info)
4767

4868

4969
static func get_id_type() -> IDType:
50-
var default: StringName = IDType.keys()[DEFAULT_ID_TYPE]
51-
var key := ProjectSettings.get_setting(SETTING_ID_TYPE, default)
52-
return IDType[key]
70+
var default: StringName = IDType.keys()[DEFAULT_ID_TYPE]
71+
var key := ProjectSettings.get_setting(SETTING_ID_TYPE, default)
72+
return IDType[key]
5373

5474

5575
static func set_id_type(id_type: IDType) -> void:
56-
ProjectSettings.set_setting(SETTING_ID_TYPE, IDType.keys()[id_type])
76+
ProjectSettings.set_setting(SETTING_ID_TYPE, IDType.keys()[id_type])
77+
78+
79+
static func get_data_path() -> StringName:
80+
return ProjectSettings.get_setting(
81+
SETTING_PANDORA_DATA_PATH,
82+
DEFAULT_PANDORA_DATA_PATH
83+
)
84+
85+
86+
static func set_data_path(path: StringName) -> void:
87+
ProjectSettings.set_setting(SETTING_PANDORA_DATA_PATH, path)
88+
89+
90+
static func get_definitions_dir() -> StringName:
91+
return ProjectSettings.get_setting(
92+
SETTINGS_PANDORA_DEFINITIONS_DIR,
93+
DEFAULT_PANDORA_DEFINITIONS_DIR
94+
)
95+
96+
97+
static func set_definitions_dir(path: StringName) -> void:
98+
ProjectSettings.set_setting(SETTINGS_PANDORA_DEFINITIONS_DIR, path)

addons/pandora/storage/json/json_data_storage.gd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,13 @@ func _get_directory_path(context_id: String) -> String:
100100

101101

102102
func _get_file_path(context_id: String) -> String:
103-
return "%s/data.pandora" % [_get_directory_path(context_id)]
103+
# Allow to override the file name in the settings based
104+
# on whether the user has set a custom data path
105+
var file_name := "data.pandora"
106+
if PandoraSettings.get_data_path().get_file() != "data.pandora":
107+
file_name = PandoraSettings.get_data_path().get_file()
108+
109+
return "%s/%s" % [_get_directory_path(context_id), file_name]
104110

105111

106112
func _should_use_compression() -> bool:

addons/pandora/util/category_id_file_generator.gd

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,20 @@ static func _process_sub_category_tuples(
4747

4848
# Add current category to the local list if it's a leaf or has children
4949
if not subcategory_tuples.has(new_key) or subcategory_tuples[new_key].size() == 0:
50-
subcategory_tuples.erase(new_key) # Remove if empty
50+
subcategory_tuples.erase(new_key) # Remove if empty
5151
local_subcategories.append(category_tuple)
5252

5353
if local_subcategories.size() > 0:
5454
subcategory_tuples[parent_category] = local_subcategories
5555

5656

57-
5857
static func generate_category_id_file(
5958
root_category_tuples: Array[CategoryTuple], subcategory_tuples: Dictionary) -> void:
60-
var file_path = "res://pandora/categories.gd"
61-
if not DirAccess.dir_exists_absolute("res://pandora"):
62-
DirAccess.make_dir_absolute("res://pandora")
59+
var definitions_dir := PandoraSettings.get_definitions_dir()
60+
var file_path = "%s/categories.gd" % definitions_dir
61+
file_path.replace("//", "/") # Ensure correct path format
62+
if not DirAccess.dir_exists_absolute(definitions_dir):
63+
DirAccess.make_dir_absolute(definitions_dir)
6364

6465
var file_access = FileAccess.open(file_path, FileAccess.WRITE)
6566
file_access.store_line("# Do not modify! Auto-generated file.")

addons/pandora/util/entity_id_file_generator.gd

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ static func generate_class_to_entity_map(root_categories: Array[PandoraCategory]
2525
static func generate_entity_id_file(entity_class_name: String, entities: Array[PandoraEntity]) -> Array[String]:
2626
if entities.is_empty():
2727
return []
28-
var lines:Array[String] = ["# Do not modify! Auto-generated file.", "class_name " + entity_class_name + "\n\n"]
28+
var lines: Array[String] = ["# Do not modify! Auto-generated file.", "class_name " + entity_class_name + "\n\n"]
2929
var name_usages = {}
3030
for entity in entities:
3131
var entity_name = entity.get_entity_name()
@@ -40,7 +40,7 @@ static func generate_entity_id_file(entity_class_name: String, entities: Array[P
4040
static func _process_category_for_id_files(category: PandoraCategory, class_to_entity_map: Dictionary) -> void:
4141
var classname = category.get_id_generation_class()
4242
if not class_to_entity_map.has(classname):
43-
var empty:Array[PandoraEntity] = []
43+
var empty: Array[PandoraEntity] = []
4444
class_to_entity_map[classname] = empty
4545

4646
if category.is_generate_ids():
@@ -66,9 +66,13 @@ static func _entity_exists_in_map(entity_list: Array[PandoraEntity], entity: Pan
6666
return false
6767

6868
static func _write_to_file(entity_class_name: String, lines: Array[String]) -> void:
69-
var file_path = "res://pandora/" + entity_class_name.to_snake_case() + ".gd"
70-
if not DirAccess.dir_exists_absolute("res://pandora"):
71-
DirAccess.make_dir_absolute("res://pandora")
69+
var definitions_dir := PandoraSettings.get_definitions_dir()
70+
if not definitions_dir.ends_with("/"):
71+
definitions_dir += "/"
72+
73+
var file_path = definitions_dir + entity_class_name.to_snake_case() + ".gd"
74+
if not DirAccess.dir_exists_absolute(definitions_dir):
75+
DirAccess.make_dir_absolute(definitions_dir)
7276

7377
var file = FileAccess.open(file_path, FileAccess.WRITE)
7478
if FileAccess.get_open_error() == OK:

test/settings/pandora_settings_test.gd

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ extends GdUnitTestSuite
77

88
# TestSuite generated from
99
const __source = 'res://addons/pandora/settings/pandora_settings.gd'
10-
10+
const TEST_DIR = "testdata"
1111

1212
const IDType := PandoraSettings.IDType
1313

1414
const SETTING_ID_TYPE := PandoraSettings.SETTING_ID_TYPE
15+
const SETTING_PANDORA_DATA_PATH := PandoraSettings.SETTING_PANDORA_DATA_PATH
1516

1617

1718
func test_initialize() -> void:
@@ -48,3 +49,50 @@ func test_set_id_type() -> void:
4849
PROPERTY_HINT_ENUM, "%s,%s" % IDType.keys())
4950
PandoraSettings.set_id_type(IDType.NANOID)
5051
assert_int(PandoraSettings.get_id_type()).is_equal(IDType.NANOID)
52+
53+
54+
func test_get_data_path() -> void:
55+
ProjectSettings.clear(SETTING_PANDORA_DATA_PATH)
56+
PandoraSettings.init_setting(
57+
SETTING_PANDORA_DATA_PATH, "res://data.pandora",
58+
TYPE_STRING, PROPERTY_HINT_FILE, "*.pandora"
59+
)
60+
var expected: String = ProjectSettings.get_setting(SETTING_PANDORA_DATA_PATH)
61+
var actual := PandoraSettings.get_data_path()
62+
assert_str(actual).is_equal(expected)
63+
64+
65+
func test_set_data_path() -> void:
66+
ProjectSettings.clear(SETTING_PANDORA_DATA_PATH)
67+
PandoraSettings.init_setting(
68+
SETTING_PANDORA_DATA_PATH, "res://data.pandora",
69+
TYPE_STRING, PROPERTY_HINT_FILE, "*.pandora"
70+
)
71+
72+
Pandora.set_context_id("")
73+
var new_path: String = "res://" + TEST_DIR + "/" + "collection.pandora"
74+
PandoraSettings.set_data_path(new_path)
75+
assert_str(PandoraSettings.get_data_path()).is_equal(new_path)
76+
77+
# Reinitialize the data storage with the new path
78+
Pandora._storage = PandoraJsonDataStorage.new(new_path.get_base_dir())
79+
# Resave the data to ensure it uses the new path
80+
Pandora.save_data()
81+
# Unload and reload the data to ensure it reflects the new path
82+
Pandora._clear()
83+
Pandora.load_data()
84+
85+
assert_array(Pandora.get_all_entities()).is_not_empty()
86+
87+
assert_file(new_path).exists()
88+
89+
# Clean up
90+
DirAccess.remove_absolute(new_path)
91+
92+
PandoraSettings.set_data_path("res://data.pandora")
93+
assert_str(PandoraSettings.get_data_path()).is_equal("res://data.pandora")
94+
95+
Pandora._storage = PandoraJsonDataStorage.new(PandoraSettings.get_data_path().get_base_dir())
96+
97+
Pandora._clear()
98+
Pandora.load_data()

0 commit comments

Comments
 (0)