@@ -23,6 +23,46 @@ const StringNameTypeName = {
2323 StringNameType .METHOD_NAME : "MethodName" ,
2424 StringNameType .SIGNAL_NAME : "SignalName" ,
2525}
26+ const PASCAL_CASE_NAME_OVERRIDES = {
27+ "BitMap" : "Bitmap" ,
28+ "JSONRPC" : "JsonRpc" ,
29+ "Object" : "GodotObject" ,
30+ "OpenXRIPBinding" : "OpenXRIPBinding" ,
31+ "SkeletonModification2DCCDIK" : "SkeletonModification2DCcdik" ,
32+ "SkeletonModification2DFABRIK" : "SkeletonModification2DFabrik" ,
33+ "SkeletonModification3DCCDIK" : "SkeletonModification3DCcdik" ,
34+ "SkeletonModification3DFABRIK" : "SkeletonModification3DFabrik" ,
35+ "System" : "System_" ,
36+ "Thread" : "GodotThread" ,
37+ }
38+ const PASCAL_CASE_PART_OVERRIDES = {
39+ "AA" : "AA" , # Anti Aliasing
40+ "AO" : "AO" , # Ambient Occlusion
41+ "FILENAME" : "FileName" ,
42+ "FADEIN" : "FadeIn" ,
43+ "FADEOUT" : "FadeOut" ,
44+ "FX" : "FX" ,
45+ "GI" : "GI" , # Global Illumination
46+ "GZIP" : "GZip" ,
47+ "HBOX" : "HBox" , # Horizontal Box
48+ "ID" : "Id" ,
49+ "IO" : "IO" , # Input/Output
50+ "IP" : "IP" , # Internet Protocol
51+ "IV" : "IV" , # Initialization Vector
52+ "MACOS" : "MacOS" ,
53+ "NODEPATH" : "NodePath" ,
54+ "SPIRV" : "SpirV" ,
55+ "STDIN" : "StdIn" ,
56+ "STDOUT" : "StdOut" ,
57+ "USERNAME" : "UserName" ,
58+ "UV" : "UV" ,
59+ "UV2" : "UV2" ,
60+ "VBOX" : "VBox" , # Vertical Box
61+ "WHITESPACE" : "WhiteSpace" ,
62+ "WM" : "WM" ,
63+ "XR" : "XR" ,
64+ "XRAPI" : "XRApi" ,
65+ }
2666
2767
2868func _enter_tree ():
@@ -549,7 +589,7 @@ static func _get_property_type(cls_name: StringName, property: Dictionary) -> St
549589 return "Godot.Rid"
550590 TYPE_OBJECT :
551591 if property ["class_name" ] and property ["class_name" ] != "Object" :
552- return _get_class_from_class_name (property ["class_name" ])
592+ return _pascal_to_pascal_case ( _get_class_from_class_name (property ["class_name" ]) )
553593 else :
554594 return "GodotObject"
555595 TYPE_ARRAY :
@@ -730,3 +770,80 @@ static func _needs_enum_suffix(cls_name: StringName, enum_name: String) -> bool:
730770 if snake_case_enum_name == property ["name" ]:
731771 return true
732772 return false
773+
774+
775+ # Pascal case conversion used for class names.
776+ # Replicates the logic from `godot/modules/mono/utils/naming_utils.cpp`
777+ static func _is_ascii_upper_case (c : String ) -> bool :
778+ return c .to_upper () == c
779+
780+
781+ static func _is_ascii_lower_case (c : String ) -> bool :
782+ return c .to_lower () == c
783+
784+
785+ static func _is_digit (c : String ) -> bool :
786+ return c >= "0" and c <= "9"
787+
788+
789+ static func _split_pascal_case (p_identifier : String ) -> PackedStringArray :
790+ var parts := PackedStringArray ()
791+ var current_part_start := 0
792+ var prev_was_upper := _is_ascii_upper_case (p_identifier [0 ])
793+ for i in range (1 , p_identifier .length ()):
794+ if prev_was_upper :
795+ if _is_digit (p_identifier [i ]) or _is_ascii_lower_case (p_identifier [i ]):
796+ if not _is_digit (p_identifier [i ]):
797+ # These conditions only apply when the separator is not a digit.
798+ if i - current_part_start == 1 :
799+ # Upper character was only the beginning of a word.
800+ prev_was_upper = false
801+ continue
802+ if i != p_identifier .length ():
803+ # If this is not the last character, the last uppercase
804+ # character is the start of the next word.
805+ i -= 1
806+ if i - current_part_start > 0 :
807+ parts .append (p_identifier .substr (current_part_start , i - current_part_start ))
808+ current_part_start = i
809+ prev_was_upper = false
810+ else :
811+ if _is_digit (p_identifier [i ]) or _is_ascii_upper_case (p_identifier [i ]):
812+ parts .append (p_identifier .substr (current_part_start , i - current_part_start ))
813+ current_part_start = i
814+ prev_was_upper = true
815+
816+ # Add the rest of the identifier as the last part.
817+ if current_part_start != p_identifier .length ():
818+ parts .append (p_identifier .substr (current_part_start ))
819+ return parts
820+
821+
822+ static func _pascal_to_pascal_case (p_identifier : String ) -> String :
823+ if p_identifier .length () == 0 :
824+ return p_identifier
825+ if p_identifier .length () <= 2 :
826+ return p_identifier .to_upper ()
827+ if PASCAL_CASE_NAME_OVERRIDES .has (p_identifier ):
828+ return PASCAL_CASE_NAME_OVERRIDES [p_identifier ]
829+
830+ var parts := _split_pascal_case (p_identifier )
831+ var ret := ""
832+ for part in parts :
833+ if PASCAL_CASE_PART_OVERRIDES .has (part ):
834+ ret += PASCAL_CASE_PART_OVERRIDES [part ]
835+ continue
836+
837+ if part .length () <= 2 and _is_ascii_upper_case (part ):
838+ ret += part .to_upper ()
839+ continue
840+
841+ part [0 ] = part [0 ].to_upper ()
842+ for i in range (1 , part .length ()):
843+ if _is_digit (part [i - 1 ]):
844+ # Use uppercase after digits.
845+ part [i ] = part [i ].to_upper ()
846+ else :
847+ part [i ] = part [i ].to_lower ()
848+ ret += part
849+ return ret
0 commit comments