Skip to content

Commit 8639352

Browse files
committed
remove submodule
1 parent 8905ee3 commit 8639352

3 files changed

Lines changed: 244 additions & 2 deletions

File tree

addons/tbloader/src/godot-fgd

Lines changed: 0 additions & 1 deletion
This file was deleted.

addons/tbloader/src/plugin.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
extends EditorPlugin
33
class_name TBPlugin
44

5-
var godot_fgd = preload("res://addons/tbloader/src/godot-fgd/toFgd.gd").new()
5+
var godot_fgd = preload("res://addons/tbloader/src/toFgd.gd").new()
66
var map_control: Control = null
77
var fgd_control: Control = null
88
var editing_loader: WeakRef = weakref(null)

addons/tbloader/src/toFgd.gd

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,243 @@
1+
extends SceneTree
2+
3+
func get_files(entities_dir):
4+
# Define the root directory to search
5+
var root_dir = "res://%s" % entities_dir
6+
var dir = DirAccess.open(root_dir)
7+
var files = []
8+
var folders = []
9+
10+
# Get all files in the directory
11+
dir.list_dir_begin()
12+
while true:
13+
var file = dir.get_next()
14+
if file == "":
15+
break
16+
if dir.current_is_dir():
17+
folders.append(file)
18+
else:
19+
files.append("%s/%s" % [entities_dir, file])
20+
dir.list_dir_end()
21+
22+
for folder in folders:
23+
# Recursively get all files in the subdirectories
24+
files += get_files("%s/%s" % [entities_dir, folder])
25+
26+
return files
27+
28+
func remove_attached_scripts(files):
29+
var filtered_files = []
30+
var attached_scripts = []
31+
32+
# Find all attached scripts
33+
for file in files:
34+
if file.ends_with(".tscn"):
35+
var scene = load(file)
36+
var instance = scene.instantiate()
37+
var script = instance.get_script()
38+
if script: attached_scripts.append(script.get_path().replace("res://", ""))
39+
instance.queue_free()
40+
41+
# Remove attached scripts from the list
42+
for file in files:
43+
if file not in attached_scripts:
44+
filtered_files.append(file)
45+
46+
return filtered_files
47+
48+
func get_entity_properties(files = []):
49+
var properties = ["// Generated by Godot FGD Generator https://github.com/krazyjakee/godot-fgd\n\n"]
50+
51+
for file in files:
52+
if file.ends_with(".gd"):
53+
properties.append(create_entity(file, script_loader(file)))
54+
if file.ends_with(".tscn"):
55+
properties.append(create_entity(file, scene_loader(file)))
56+
else:
57+
continue
58+
59+
return properties
60+
61+
func scene_loader(path):
62+
var properties = []
63+
var scene = load(path)
64+
var instance = scene.instantiate()
65+
var script = instance.get_script()
66+
if script:
67+
properties = script_loader(script.get_path())
68+
var parsed_path = path_parser(path)
69+
properties = set_property_by_name("name", parsed_path[0], properties)
70+
instance.queue_free()
71+
return properties
72+
73+
func script_loader(path):
74+
var script = load(path)
75+
var properties = filter_properties(script.get_script_property_list())
76+
var instance = script.new()
77+
for property in properties:
78+
property.default_value = instance.get(property.name)
79+
instance.queue_free()
80+
return properties
81+
82+
func filter_properties(properties = []):
83+
# Filter out properties that are not exposed to the editor
84+
var filtered_properties = []
85+
for property in properties:
86+
if property.type > 0:
87+
filtered_properties.append(property)
88+
return filtered_properties
89+
90+
func type_converter(type: int):
91+
# Convert the type to a string
92+
var types = {
93+
1: "bool",
94+
2: "integer",
95+
3: "float",
96+
4: "string",
97+
20: "color",
98+
27: "flags",
99+
28: "choices"
100+
}
101+
return types[type] if type in types else "string"
102+
103+
func value_converter(type: int, value: Variant):
104+
# Convert the value to a string
105+
if type == 4:
106+
return "\"%s\"" % value
107+
elif type == 1:
108+
return "1" if value else "0"
109+
elif type == 20:
110+
return "\"%s %s %s\"" % [value.r, value.g, value.b]
111+
elif type == 27:
112+
var fgd_values = []
113+
var count = 1
114+
for key in value:
115+
var v = 1 if value[key] else 0
116+
fgd_values.append(" %s : \"%s\" : %s\n" % [count, key, v])
117+
if count > 1:
118+
count *= count
119+
else:
120+
count += 1
121+
122+
return "[\n%s ]" % "".join(PackedStringArray(fgd_values))
123+
elif type == 28: # Array (but only string array is supported)
124+
var fgd_values = []
125+
for i in value.size():
126+
var v = value[i]
127+
fgd_values.append(" %s : \"%s\"\n" % [i, v])
128+
129+
return "0 = [\n%s ]" % "".join(PackedStringArray(fgd_values))
130+
else:
131+
return value
132+
133+
func get_property_value_by_name(name, properties = [], default_value = null):
134+
# Get the properties by name
135+
for property in properties:
136+
if property.name == name:
137+
return property.default_value
138+
return default_value
139+
140+
func set_property_by_name(name, value, properties = []):
141+
# Set the properties by name
142+
for i in properties.size():
143+
if properties[i].name == name:
144+
properties[i][name] = value
145+
return properties
146+
147+
func path_parser(raw_path):
148+
var regex = RegEx.new()
149+
150+
# Parse the path to get the entity and group name
151+
var entity_name = raw_path.get_file().split(".")[0]
152+
var entity_location = raw_path.get_base_dir()
153+
154+
# Remove non-alphanumeric characters
155+
regex.compile("^entities")
156+
entity_location = regex.sub(entity_location, "")
157+
entity_location = entity_location.replace("/", "_")
158+
regex.compile("[\\-\\s]")
159+
entity_location = regex.sub(entity_location, "_", true)
160+
regex.compile("[\\W]")
161+
entity_location = regex.sub(entity_location, "", true)
162+
regex.compile("^_")
163+
entity_location = regex.sub(entity_location, "")
164+
if entity_location:
165+
entity_location += "_"
166+
167+
var entity_label = string_to_title_case(entity_location)
168+
169+
return ["%s%s" % [entity_location, entity_name], entity_label]
170+
171+
func string_to_title_case(string: String) -> String:
172+
var words = string.split("_")
173+
var result = ""
174+
for word in words:
175+
result += word.capitalize() + " "
176+
return result.strip_edges(true, true)
177+
178+
func create_entity(path, properties = []):
179+
if properties == null:
180+
return null
181+
# Header
182+
# Example: @PointClass size(-4 -4 -4, 4 4 4) color(255 255 0) model({ "path": ":progs/player.mdl" }) = light : "Light" [
183+
var fgd_size = get_property_value_by_name("fgd_size", properties, 4)
184+
var fgd_color = get_property_value_by_name("fgd_color", properties, "(0 255 0)")
185+
var fgd_model = get_property_value_by_name("fgd_model", properties, "")
186+
var fgd_block = get_property_value_by_name("fgd_block", properties, [])
187+
188+
var entity_name_properties = path_parser(path)
189+
var entity_name = entity_name_properties[0]
190+
var entity_label = entity_name_properties[1]
191+
fgd_model = " model(%s)" % JSON.stringify(fgd_model) if fgd_model else ""
192+
193+
var entity = "@PointClass size(-%s -%s -%s, %s %s %s) color%s%s = %s : \"%s\" [\n" % [
194+
fgd_size, fgd_size, fgd_size,
195+
fgd_size, fgd_size, fgd_size,
196+
fgd_color, fgd_model,
197+
entity_name, entity_label
198+
]
199+
200+
# Body
201+
# Example: energy(float) : "Energy" : 1 : "The light's strengh multiplier"
202+
for property in properties:
203+
if property.name.begins_with("fgd_") or property.name in fgd_block:
204+
continue
205+
206+
if property.type in [27]: # Flags
207+
entity += " %s(%s) = %s" % [
208+
property.name if property.name else "unnamed",
209+
type_converter(property.type) if property.type else 4,
210+
value_converter(property.type, property.default_value) if property.default_value else "",
211+
]
212+
else:
213+
entity += " %s(%s) : \"%s\" : %s" % [
214+
property.name if property.name else "unnamed",
215+
type_converter(property.type) if property.type else 4,
216+
string_to_title_case(property.name) if property.name else "",
217+
value_converter(property.type, property.default_value) if property.default_value else "",
218+
]
219+
220+
if property.type not in [28]: # Array
221+
entity += " : \"%s\"" % property.hint_string if property.hint_string else ""
222+
223+
entity += "\n"
224+
225+
# Footer
226+
entity += "]\n\n"
227+
228+
return entity
229+
230+
func build(entities_dir = "entities"):
231+
var all_files = get_files(entities_dir) # Get all .gd and .tscn files in the entity folder
232+
var files = remove_attached_scripts(all_files) # Remove attached scripts
233+
var properties = get_entity_properties(files) # Get the properties of each entity
234+
235+
var file = FileAccess.open("Game.fgd", FileAccess.WRITE)
236+
for property in properties:
237+
if property:
238+
file.store_string(property)
239+
240+
print("Game.fgd created successfully!")
241+
242+
func _init():
243+
build()

0 commit comments

Comments
 (0)