#![allow(clippy::match_like_matches_macro)]
use std::borrow::Cow;
use proc_macro2::Ident;
use crate::Context;
use crate::conv::to_enum_type_uncached;
use crate::models::domain::{
ClassCodegenLevel, Enum, EnumReplacements, RustTy, TyName, VirtualMethodPresence,
};
use crate::models::json::{JsonBuiltinMethod, JsonClassMethod, JsonSignal, JsonUtilityFunction};
use crate::special_cases::codegen_special_cases;
use crate::util::option_as_slice;
#[rustfmt::skip]
pub fn is_class_method_deleted(class_name: &TyName, method: &JsonClassMethod, ctx: &mut Context) -> bool {
if codegen_special_cases::is_class_method_excluded(method, ctx){
return true;
}
match (class_name.godot_ty.as_str(), method.name.as_str()) {
| ("Object", "get_instance_id")
| ("Node", "get_node")
| ("GDExtension", "open_library")
| ("GDExtension", "initialize_library")
| ("GDExtension", "close_library")
| ("OpenXRHand", "set_hand_skeleton")
| ("OpenXRHand", "get_hand_skeleton")
| ("SkeletonIK3D", "set_interpolation")
| ("SkeletonIK3D", "get_interpolation")
| ("VisualShaderNodeComment", "set_title")
| ("VisualShaderNodeComment", "get_title")
| ("VisualShaderNodeComment", "set_description")
| ("VisualShaderNodeComment", "get_description")
| ("VisualShader", "set_graph_offset")
| ("VisualShader", "get_graph_offset")
=> true,
#[cfg(not(feature = "experimental-threads"))]
| ("ResourceLoader", "load_threaded_get")
| ("ResourceLoader", "load_threaded_get_status")
| ("ResourceLoader", "load_threaded_request") => true,
_ => false
}
}
#[rustfmt::skip]
pub fn get_class_method_deprecation(class_name: &TyName, method: &JsonClassMethod) -> Option<&'static str> {
let deprecation_msg = match (class_name.godot_ty.as_str(), method.name.as_str()) {
| ("Node", "duplicate")
| ("Node", "duplicate_ex") => "Use `Gd::duplicate_node()` or `Gd::duplicate_node_ex()`.",
| ("Resource", "duplicate")
| ("Resource", "duplicate_ex")
| ("Resource", "duplicate_deep")
| ("Resource", "duplicate_deep_ex") => "Use `Gd::duplicate_resource()` or `Gd::duplicate_resource_ex()`.",
_ => return None,
};
Some(deprecation_msg)
}
pub fn is_class_deleted(class_name: &TyName) -> bool {
codegen_special_cases::is_class_excluded(&class_name.godot_ty)
|| is_godot_type_deleted(&class_name.godot_ty)
}
pub fn is_native_struct_excluded(ty: &str) -> bool {
codegen_special_cases::is_native_struct_excluded(ty)
}
#[rustfmt::skip]
pub fn get_native_struct_definition(struct_name: &str) -> Option<&'static str> {
match struct_name {
"Glyph" => Some(
"int start = -1;int end = -1;uint8_t count = 0;uint8_t repeat = 1;uint16_t flags = 0;float x_off = 0.f;float y_off = 0.f;\
float advance = 0.f;RID font_rid;int font_size = 0;int32_t index = 0;int span_index = -1"
),
_ => None,
}
}
#[rustfmt::skip]
pub fn is_godot_type_deleted(godot_ty: &str) -> bool {
if !cfg!(feature = "experimental-godot-api") && is_class_experimental(godot_ty) {
return true;
}
if godot_ty.starts_with("OpenXR") {
let target_os = std::env::var("CARGO_CFG_TARGET_OS");
match target_os.as_deref() {
Ok("ios") | Ok("emscripten") => return true,
_ => {}
}
}
match godot_ty {
| "JavaClass"
| "JavaClassWrapper"
| "JavaObject"
| "JNISingleton"
=> !cfg!(target_os = "android"),
| "JavaScriptBridge"
| "JavaScriptObject"
=> !cfg!(target_os = "emscripten"),
| "Thread"
| "Mutex"
| "Semaphore"
=> true,
| "UniformSetCacheRD"
=> cfg!(before_api = "4.3"),
_ => false
}
}
#[rustfmt::skip]
pub fn is_class_experimental(godot_class_name: &str) -> bool {
match godot_class_name {
| "AudioSample"
| "AudioSamplePlayback"
| "Compositor"
| "CompositorEffect"
| "GraphEdit"
| "GraphElement"
| "GraphFrame"
| "GraphNode"
| "NavigationAgent2D"
| "NavigationAgent3D"
| "NavigationLink2D"
| "NavigationLink3D"
| "NavigationMesh"
| "NavigationMeshSourceGeometryData2D"
| "NavigationMeshSourceGeometryData3D"
| "NavigationObstacle2D"
| "NavigationObstacle3D"
| "NavigationPathQueryParameters2D"
| "NavigationPathQueryParameters3D"
| "NavigationPathQueryResult2D"
| "NavigationPathQueryResult3D"
| "NavigationPolygon"
| "NavigationRegion2D"
| "NavigationRegion3D"
| "NavigationServer2D"
| "NavigationServer3D"
| "Parallax2D"
| "SkeletonModification2D"
| "SkeletonModification2DCCDIK"
| "SkeletonModification2DFABRIK"
| "SkeletonModification2DJiggle"
| "SkeletonModification2DLookAt"
| "SkeletonModification2DPhysicalBones"
| "SkeletonModification2DStackHolder"
| "SkeletonModification2DTwoBoneIK"
| "SkeletonModificationStack2D"
| "StreamPeerGZIP"
| "XRBodyModifier3D"
| "XRBodyTracker"
| "XRFaceModifier3D"
| "XRFaceTracker"
=> true, _ => false
}
}
pub fn is_class_instantiable(class_ty: &TyName) -> Option<bool> {
let class_name = class_ty.godot_ty.as_str();
if class_name == "Tween" || class_name.ends_with("Tweener") {
return Some(false);
}
None
}
#[rustfmt::skip]
pub fn is_class_abstract(class_ty: &TyName) -> bool {
match class_ty.godot_ty.as_str() {
| "AnimationMixer"
| "AudioEffectSpectrumAnalyzerInstance"
| "AudioStreamGeneratorPlayback"
| "AudioStreamPlaybackInteractive"
| "AudioStreamPlaybackPlaylist"
| "AudioStreamPlaybackPolyphonic"
| "AudioStreamPlaybackSynchronized"
| "BaseMaterial3D"
| "CanvasItem"
| "CollisionObject2D"
| "CollisionObject3D"
| "CompressedTextureLayered"
| "CSGPrimitive3D"
| "CSGShape3D"
| "DirAccess"
| "DisplayServer"
| "EditorDebuggerSession"
| "EditorExportPlatform"
| "EditorExportPlatformAppleEmbedded"
| "EditorExportPlatformPC"
| "EditorExportPreset"
| "EditorFileSystem"
| "EditorInterface"
| "EditorResourcePreview"
| "EditorToaster"
| "EditorUndoRedoManager"
| "ENetPacketPeer"
| "FileAccess"
| "FileSystemDock"
| "Font"
| "GDExtensionManager"
| "GPUParticlesAttractor3D"
| "GPUParticlesCollision3D"
| "ImageFormatLoader"
| "ImageTextureLayered"
| "Input"
| "InputEvent"
| "InputEventFromWindow"
| "InputEventGesture"
| "InputEventMouse"
| "InputEventWithModifiers"
| "InstancePlaceholder"
| "IP"
| "JavaScriptBridge"
| "JavaScriptObject"
| "Joint2D"
| "Joint3D"
| "Light2D"
| "Light3D"
| "Lightmapper"
| "MultiplayerAPI"
| "MultiplayerPeer"
| "NavigationServer2D"
| "NavigationServer3D"
| "Node3DGizmo"
| "Noise"
| "Occluder3D"
| "OpenXRBindingModifier"
| "OpenXRCompositionLayer"
| "OpenXRFutureResult"
| "OpenXRHapticBase"
| "OpenXRInteractionProfileEditorBase"
| "PackedDataContainerRef"
| "PacketPeer"
| "PhysicsBody2D"
| "PhysicsBody3D"
| "PhysicsDirectBodyState2D"
| "PhysicsDirectBodyState3D"
| "PhysicsDirectSpaceState2D"
| "PhysicsDirectSpaceState3D"
| "PhysicsServer2D"
| "PhysicsServer3D"
| "PlaceholderTextureLayered"
| "RenderData"
| "RenderingDevice"
| "RenderingServer"
| "RenderSceneBuffers"
| "RenderSceneData"
| "ResourceImporter"
| "ResourceUID"
| "SceneState"
| "SceneTreeTimer"
| "Script"
| "ScriptEditor"
| "ScriptEditorBase"
| "ScriptLanguage"
| "ScrollBar"
| "Separator"
| "Shader"
| "Shape2D"
| "Shape3D"
| "SkinReference"
| "Slider"
| "SpriteBase3D"
| "StreamPeer"
| "TextServer"
| "TextureLayeredRD"
| "TileSetSource"
| "TLSOptions"
| "TreeItem"
| "Tweener"
| "Viewport"
| "VisualShaderNode"
| "VisualShaderNodeConstant"
| "VisualShaderNodeGroupBase"
| "VisualShaderNodeOutput"
| "VisualShaderNodeParameter"
| "VisualShaderNodeParticleEmitter"
| "VisualShaderNodeResizableBase"
| "VisualShaderNodeSample3D"
| "VisualShaderNodeTextureParameter"
| "VisualShaderNodeVarying"
| "VisualShaderNodeVectorBase"
| "WebRTCDataChannel"
| "WebXRInterface"
| "WorkerThreadPool"
| "XRInterface"
| "XRTracker"
=> true, _ => false
}
}
#[rustfmt::skip]
pub fn is_named_accessor_in_table(class_or_builtin_ty: &TyName, godot_method_name: &str) -> bool {
match (class_or_builtin_ty.godot_ty.as_str(), godot_method_name) {
| ("OS", "has_feature")
=> return true, _ => {}
}
is_method_private(class_or_builtin_ty, godot_method_name)
}
#[rustfmt::skip]
pub fn is_method_private(class_or_builtin_ty: &TyName, godot_method_name: &str) -> bool {
if is_class_method_replaced_with_type_safe(class_or_builtin_ty, godot_method_name) {
return true;
}
match (class_or_builtin_ty.godot_ty.as_str(), godot_method_name) {
| ("Object", "to_string")
| ("Object", "notification")
| ("RefCounted", "init_ref")
| ("RefCounted", "reference")
| ("RefCounted", "unreference")
=> true, _ => false
}
}
#[rustfmt::skip]
fn is_class_method_replaced_with_type_safe(class_ty: &TyName, godot_method_name: &str) -> bool {
match (class_ty.godot_ty.as_str(), godot_method_name) {
| ("Object", "get_script")
| ("Object", "set_script")
| ("Object", "connect")
| ("Node", "get_tree")
| ("SceneTree", "call_group_flags")
| ("SceneTree", "notify_group")
| ("SceneTree", "notify_group_flags")
| ("SceneTree", "set_group_flags")
=> true, _ => false
}
}
pub fn get_class_method_param_enum_replacement(
class_ty: &TyName,
godot_method_name: &str,
) -> EnumReplacements {
let godot_class_name = class_ty.godot_ty.as_str();
match (godot_class_name, godot_method_name) {
("CharFXTransform", "get_glyph_flags") => &[("", "TextServer.GraphemeFlag", true)],
("CharFXTransform", "set_glyph_flags") => {
&[("glyph_flags", "TextServer.GraphemeFlag", true)]
}
("CodeEdit", "add_code_completion_option") => {
&[("location", "CodeEdit.CodeCompletionLocation", false)]
}
#[cfg(before_api = "4.6")] ("FileAccess", "create_temp") => &[("mode_flags", "FileAccess.ModeFlags", true)],
("GPUParticles2D", "emit_particle") => &[("flags", "GPUParticles2D.EmitFlags", true)],
("GPUParticles3D", "emit_particle") => &[("flags", "GPUParticles3D.EmitFlags", true)],
("Node", "duplicate") => &[("flags", "Node.DuplicateFlags", true)],
("ProgressBar", "get_fill_mode") => &[("", "ProgressBar.FillMode", false)],
("ProgressBar", "set_fill_mode") => &[("mode", "ProgressBar.FillMode", false)],
("TextEdit", "search") => &[("flags", "TextEdit.SearchFlags", true)],
("TextEdit", "set_search_flags") => &[("flags", "TextEdit.SearchFlags", true)],
("TextureProgressBar", "get_fill_mode") => &[("", "TextureProgressBar.FillMode", false)],
("TextureProgressBar", "set_fill_mode") => {
&[("mode", "TextureProgressBar.FillMode", false)]
}
("Tree", "get_drop_mode_flags") => &[("", "Tree.DropModeFlags", true)],
("Tree", "set_drop_mode_flags") => &[("flags", "Tree.DropModeFlags", true)],
_ => &[],
}
}
#[rustfmt::skip]
pub fn is_builtin_method_exposed(builtin_ty: &TyName, godot_method_name: &str) -> bool {
match (builtin_ty.godot_ty.as_str(), godot_method_name) {
| ("String" | "StringName", "begins_with")
| ("String" | "StringName", "bigrams")
| ("String" | "StringName", "bin_to_int")
| ("String" | "StringName", "c_escape")
| ("String" | "StringName", "c_unescape")
| ("String" | "StringName", "capitalize")
| ("String" | "StringName", "contains")
| ("String" | "StringName", "containsn")
| ("String" | "StringName", "dedent")
| ("String" | "StringName", "ends_with")
| ("String" | "StringName", "get_base_dir")
| ("String" | "StringName", "get_basename")
| ("String" | "StringName", "get_extension")
| ("String" | "StringName", "get_file")
| ("String" | "StringName", "hex_decode")
| ("String" | "StringName", "hex_to_int")
| ("String" | "StringName", "indent")
| ("String" | "StringName", "is_absolute_path")
| ("String" | "StringName", "is_empty")
| ("String" | "StringName", "is_relative_path")
| ("String" | "StringName", "is_subsequence_of")
| ("String" | "StringName", "is_subsequence_ofn")
| ("String" | "StringName", "is_valid_filename")
| ("String" | "StringName", "is_valid_float")
| ("String" | "StringName", "is_valid_hex_number")
| ("String" | "StringName", "is_valid_html_color")
| ("String" | "StringName", "is_valid_identifier")
| ("String" | "StringName", "is_valid_int")
| ("String" | "StringName", "is_valid_ip_address")
| ("String" | "StringName", "join")
| ("String" | "StringName", "json_escape")
| ("String" | "StringName", "left")
| ("String" | "StringName", "lstrip")
| ("String" | "StringName", "md5_buffer")
| ("String" | "StringName", "md5_text")
| ("String" | "StringName", "path_join")
| ("String" | "StringName", "repeat")
| ("String" | "StringName", "replace")
| ("String" | "StringName", "replacen")
| ("String" | "StringName", "reverse")
| ("String" | "StringName", "right")
| ("String" | "StringName", "rstrip")
| ("String" | "StringName", "sha1_buffer")
| ("String" | "StringName", "sha1_text")
| ("String" | "StringName", "sha256_buffer")
| ("String" | "StringName", "sha256_text")
| ("String" | "StringName", "similarity")
| ("String" | "StringName", "simplify_path")
| ("String" | "StringName", "split_floats")
| ("String" | "StringName", "strip_edges")
| ("String" | "StringName", "strip_escapes")
| ("String" | "StringName", "to_ascii_buffer")
| ("String" | "StringName", "to_camel_case")
| ("String" | "StringName", "to_float")
| ("String" | "StringName", "to_int")
| ("String" | "StringName", "to_lower")
| ("String" | "StringName", "to_pascal_case")
| ("String" | "StringName", "to_snake_case")
| ("String" | "StringName", "to_upper")
| ("String" | "StringName", "to_utf16_buffer")
| ("String" | "StringName", "to_utf32_buffer")
| ("String" | "StringName", "to_utf8_buffer")
| ("String" | "StringName", "to_wchar_buffer")
| ("String" | "StringName", "trim_prefix")
| ("String" | "StringName", "trim_suffix")
| ("String" | "StringName", "uri_decode")
| ("String" | "StringName", "uri_encode")
| ("String" | "StringName", "validate_filename")
| ("String" | "StringName", "validate_node_name")
| ("String" | "StringName", "xml_escape")
| ("String" | "StringName", "xml_unescape")
| ("String", "chr")
| ("String", "humanize_size")
| ("String", "num")
| ("String", "num_int64")
| ("String", "num_scientific")
| ("String", "num_uint64")
| ("NodePath", "is_absolute")
| ("NodePath", "is_empty")
| ("NodePath", "get_concatenated_names")
| ("NodePath", "get_concatenated_subnames")
| ("NodePath", "get_as_property_path")
| ("Callable", "call")
| ("Callable", "call_deferred")
| ("Callable", "bind")
| ("Callable", "get_bound_arguments")
| ("Callable", "rpc")
| ("Callable", "rpc_id")
| ("PackedByteArray", "get_string_from_ascii")
| ("PackedByteArray", "get_string_from_utf8")
| ("PackedByteArray", "get_string_from_utf16")
| ("PackedByteArray", "get_string_from_utf32")
| ("PackedByteArray", "get_string_from_wchar")
| ("PackedByteArray", "hex_encode")
| ("Basis", "looking_at")
| ("Transform3D", "looking_at")
=> true, _ => false
}
}
#[rustfmt::skip]
pub fn is_method_excluded_from_default_params(class_or_builtin_ty: Option<&TyName>, godot_method_name: &str) -> bool {
let class_name = class_or_builtin_ty.map_or("", |ty| ty.godot_ty.as_str());
if let Some(ty) = class_or_builtin_ty
&& is_method_private(ty, godot_method_name)
{
return true;
}
match (class_name, godot_method_name) {
| ("Object", "notification")
| ("String" | "StringName", "find")
| ("String" | "StringName", "findn")
| ("String" | "StringName", "rfind")
| ("String" | "StringName", "rfindn")
| ("String" | "StringName", "split")
| ("String" | "StringName", "rsplit")
| ("Array", "duplicate")
| ("Array", "duplicate_deep")
| ("Array", "slice")
| ("Array", "find")
| ("Array", "rfind")
| ("Array", "find_custom")
| ("Array", "rfind_custom")
| ("Array", "bsearch")
| ("Array", "bsearch_custom")
| ("Array", "reduce")
| ("Dictionary", "duplicate")
| ("PackedByteArray", "encode_var")
| ("PackedByteArray", "decode_var")
| ("PackedByteArray", "decode_var_size")
| ("PackedByteArray", "compress")
| ("PackedByteArray", "decompress")
| ("PackedByteArray", "decompress_dynamic")
=> true,
(builtin, "slice" | "find" | "rfind" | "bsearch")
if builtin.starts_with("Packed") && builtin.ends_with("Array")
=> true,
_ => false
}
}
#[rustfmt::skip]
pub fn is_class_method_const(class_name: &TyName, godot_method: &JsonClassMethod) -> Option<bool> {
match (class_name.godot_ty.as_str(), godot_method.name.as_str()) {
| ("Object", "to_string")
=> Some(true),
| ("EditorImportPlugin", "_import")
| ("StreamPeer", "get_8" | "get_16" | "get_32" | "get_64")
| ("StreamPeer", "get_u8" | "get_u16" | "get_u32" | "get_u64")
| ("StreamPeer", "get_half" | "get_float" | "get_double")
| ("StreamPeer", "get_string" | "get_utf8_string")
| ("StreamPeer", "get_data" | "get_partial_data")
| ("StreamPeer", "get_var")
| ("PacketPeer", "get_packet")
| ("PacketPeer", "get_var")
| ("FileAccess", "get_8" | "get_16" | "get_32" | "get_64")
| ("FileAccess", "get_half" | "get_float" | "get_double" | "get_real" )
| ("FileAccess", "get_var")
| ("FileAccess", "get_line")
| ("FileAccess", "get_csv_line")
| ("FileAccess", "get_buffer")
| ("FileAccess", "get_pascal_string")
| ("DirAccess", "get_next")
| ("NavigationAgent2D", "get_next_path_position")
| ("NavigationAgent3D", "get_next_path_position")
| ("GridMap", "get_bake_meshes")
| ("Node3D", "get_global_transform_interpolated")
=> Some(false),
_ if !godot_method.is_const && !godot_method.is_static && !godot_method.is_virtual
&& ["get_", "is_", "has_"].iter().any(|p| godot_method.name.starts_with(p))
=> Some(true),
_ => None,
}
}
#[rustfmt::skip]
pub fn is_class_method_param_required(
class_name: &TyName,
godot_method_name: &str,
param: &Ident, ) -> bool {
let param = param.to_string();
match (class_name.godot_ty.as_str(), godot_method_name, param.as_str()) {
| ("Node", "_input", "event")
| ("Node", "_shortcut_input", "event")
| ("Node", "_unhandled_input", "event")
| ("Node", "_unhandled_key_input", "event")
| ("Control", "_gui_input", "event")
| ("CollisionObject2D", "_input_event", "viewport" | "event")
| ("ScriptExtension", "_instance_create", "for_object")
| ("ScriptExtension", "_placeholder_instance_create", "for_object")
| ("ScriptExtension", "_inherits_script", "script")
| ("ScriptExtension", "_instance_has", "object")
| ("EditorExportPlugin", "_customize_resource", "resource")
| ("EditorExportPlugin", "_customize_scene", "scene")
| ("EditorPlugin", "_handles", "object")
=> true, _ => false,
}
}
pub fn is_builtin_method_deleted(_class_name: &TyName, method: &JsonBuiltinMethod) -> bool {
codegen_special_cases::is_builtin_method_excluded(method)
}
pub fn is_signal_deleted(_class_name: &TyName, signal: &JsonSignal) -> bool {
option_as_slice(&signal.arguments)
.iter()
.any(|arg| codegen_special_cases::is_class_excluded(&arg.type_))
}
pub fn is_builtin_type_deleted(class_name: &TyName) -> bool {
let name = class_name.godot_ty.as_str();
name == "Nil" || is_builtin_type_scalar(name)
}
pub fn is_builtin_type_scalar(name: &str) -> bool {
name.chars().next().unwrap().is_ascii_lowercase()
}
#[rustfmt::skip]
pub fn is_utility_function_deleted(function: &JsonUtilityFunction, ctx: &mut Context) -> bool {
let hardcoded = match function.name.as_str() {
| "instance_from_id"
=> true, _ => false
};
hardcoded || codegen_special_cases::is_utility_function_excluded(function, ctx)
}
#[rustfmt::skip]
pub fn is_utility_function_private(function: &JsonUtilityFunction) -> bool {
match function.name.as_str() {
| "is_instance_valid" | "is_instance_id_valid"
=> true, _ => false
}
}
pub fn maybe_rename_class_method<'m>(
class_name: &TyName,
godot_method_name: &'m str,
) -> Cow<'m, str> {
if is_class_method_replaced_with_type_safe(class_name, godot_method_name) {
let new_name = format!("raw_{godot_method_name}");
return Cow::Owned(new_name);
}
let hardcoded = match (class_name.godot_ty.as_str(), godot_method_name) {
(_, "new") => "instantiate",
_ => godot_method_name,
};
Cow::Borrowed(hardcoded)
}
pub fn maybe_rename_virtual_method<'m>(
class_name: &TyName,
godot_method_name: &'m str,
) -> Option<&'m str> {
let rust_name = match (class_name.godot_ty.as_str(), godot_method_name) {
(_, "_init") => "init_ext",
_ => return None,
};
Some(rust_name)
}
pub fn get_class_extra_docs(class_name: &TyName) -> Option<&'static str> {
match class_name.godot_ty.as_str() {
"FileAccess" => Some(
"The godot-rust library provides a higher-level abstraction, which should be preferred: [`GFile`][crate::tools::GFile].",
),
"ScriptExtension" => {
Some("Use this in combination with the [`obj::script` module][crate::obj::script].")
}
"ResourceFormatLoader" => Some(
"Enable the `experimental-threads` feature when using custom `ResourceFormatLoader`s. \
Otherwise the application will panic when the custom `ResourceFormatLoader` is used by Godot \
in a thread other than the main thread.",
),
_ => None,
}
}
pub fn get_interface_extra_docs(trait_name: &str) -> Option<&'static str> {
match trait_name {
"IScriptExtension" => {
Some("Use this in combination with the [`obj::script` module][crate::obj::script].")
}
_ => None,
}
}
#[cfg(before_api = "4.4")] #[cfg_attr(published_docs, doc(cfg(before_api = "4.4")))]
pub fn is_virtual_method_required(class_name: &TyName, godot_method_name: &str) -> bool {
match (class_name.godot_ty.as_str(), godot_method_name) {
("ScriptLanguageExtension", method) => method != "_get_doc_comment_delimiters",
("ScriptExtension", "_editor_can_reload_from_file")
| ("ScriptExtension", "_can_instantiate")
| ("ScriptExtension", "_get_base_script")
| ("ScriptExtension", "_get_global_name")
| ("ScriptExtension", "_inherits_script")
| ("ScriptExtension", "_get_instance_base_type")
| ("ScriptExtension", "_instance_create")
| ("ScriptExtension", "_placeholder_instance_create")
| ("ScriptExtension", "_instance_has")
| ("ScriptExtension", "_has_source_code")
| ("ScriptExtension", "_get_source_code")
| ("ScriptExtension", "_set_source_code")
| ("ScriptExtension", "_reload")
| ("ScriptExtension", "_get_documentation")
| ("ScriptExtension", "_has_method")
| ("ScriptExtension", "_has_static_method")
| ("ScriptExtension", "_get_method_info")
| ("ScriptExtension", "_is_tool")
| ("ScriptExtension", "_is_valid")
| ("ScriptExtension", "_get_language")
| ("ScriptExtension", "_has_script_signal")
| ("ScriptExtension", "_get_script_signal_list")
| ("ScriptExtension", "_has_property_default_value")
| ("ScriptExtension", "_get_property_default_value")
| ("ScriptExtension", "_update_exports")
| ("ScriptExtension", "_get_script_method_list")
| ("ScriptExtension", "_get_script_property_list")
| ("ScriptExtension", "_get_member_line")
| ("ScriptExtension", "_get_constants")
| ("ScriptExtension", "_get_members")
| ("ScriptExtension", "_is_placeholder_fallback_enabled")
| ("ScriptExtension", "_get_rpc_config")
| ("EditorExportPlugin", "_customize_resource")
| ("EditorExportPlugin", "_customize_scene")
| ("EditorExportPlugin", "_get_customization_configuration_hash")
| ("EditorExportPlugin", "_get_name")
| ("EditorVCSInterface", _)
| ("MovieWriter", _)
| ("TextServerExtension", "_has_feature")
| ("TextServerExtension", "_get_name")
| ("TextServerExtension", "_get_features")
| ("TextServerExtension", "_free_rid")
| ("TextServerExtension", "_has")
| ("TextServerExtension", "_create_font")
| ("TextServerExtension", "_font_set_fixed_size")
| ("TextServerExtension", "_font_get_fixed_size")
| ("TextServerExtension", "_font_set_fixed_size_scale_mode")
| ("TextServerExtension", "_font_get_fixed_size_scale_mode")
| ("TextServerExtension", "_font_get_size_cache_list")
| ("TextServerExtension", "_font_clear_size_cache")
| ("TextServerExtension", "_font_remove_size_cache")
| ("TextServerExtension", "_font_set_ascent")
| ("TextServerExtension", "_font_get_ascent")
| ("TextServerExtension", "_font_set_descent")
| ("TextServerExtension", "_font_get_descent")
| ("TextServerExtension", "_font_set_underline_position")
| ("TextServerExtension", "_font_get_underline_position")
| ("TextServerExtension", "_font_set_underline_thickness")
| ("TextServerExtension", "_font_get_underline_thickness")
| ("TextServerExtension", "_font_set_scale")
| ("TextServerExtension", "_font_get_scale")
| ("TextServerExtension", "_font_get_texture_count")
| ("TextServerExtension", "_font_clear_textures")
| ("TextServerExtension", "_font_remove_texture")
| ("TextServerExtension", "_font_set_texture_image")
| ("TextServerExtension", "_font_get_texture_image")
| ("TextServerExtension", "_font_get_glyph_list")
| ("TextServerExtension", "_font_clear_glyphs")
| ("TextServerExtension", "_font_remove_glyph")
| ("TextServerExtension", "_font_get_glyph_advance")
| ("TextServerExtension", "_font_set_glyph_advance")
| ("TextServerExtension", "_font_get_glyph_offset")
| ("TextServerExtension", "_font_set_glyph_offset")
| ("TextServerExtension", "_font_get_glyph_size")
| ("TextServerExtension", "_font_set_glyph_size")
| ("TextServerExtension", "_font_get_glyph_uv_rect")
| ("TextServerExtension", "_font_set_glyph_uv_rect")
| ("TextServerExtension", "_font_get_glyph_texture_idx")
| ("TextServerExtension", "_font_set_glyph_texture_idx")
| ("TextServerExtension", "_font_get_glyph_texture_rid")
| ("TextServerExtension", "_font_get_glyph_texture_size")
| ("TextServerExtension", "_font_get_glyph_index")
| ("TextServerExtension", "_font_get_char_from_glyph_index")
| ("TextServerExtension", "_font_has_char")
| ("TextServerExtension", "_font_get_supported_chars")
| ("TextServerExtension", "_font_draw_glyph")
| ("TextServerExtension", "_font_draw_glyph_outline")
| ("TextServerExtension", "_create_shaped_text")
| ("TextServerExtension", "_shaped_text_clear")
| ("TextServerExtension", "_shaped_text_add_string")
| ("TextServerExtension", "_shaped_text_add_object")
| ("TextServerExtension", "_shaped_text_resize_object")
| ("TextServerExtension", "_shaped_get_span_count")
| ("TextServerExtension", "_shaped_get_span_meta")
| ("TextServerExtension", "_shaped_set_span_update_font")
| ("TextServerExtension", "_shaped_text_substr")
| ("TextServerExtension", "_shaped_text_get_parent")
| ("TextServerExtension", "_shaped_text_shape")
| ("TextServerExtension", "_shaped_text_is_ready")
| ("TextServerExtension", "_shaped_text_get_glyphs")
| ("TextServerExtension", "_shaped_text_sort_logical")
| ("TextServerExtension", "_shaped_text_get_glyph_count")
| ("TextServerExtension", "_shaped_text_get_range")
| ("TextServerExtension", "_shaped_text_get_trim_pos")
| ("TextServerExtension", "_shaped_text_get_ellipsis_pos")
| ("TextServerExtension", "_shaped_text_get_ellipsis_glyphs")
| ("TextServerExtension", "_shaped_text_get_ellipsis_glyph_count")
| ("TextServerExtension", "_shaped_text_get_objects")
| ("TextServerExtension", "_shaped_text_get_object_rect")
| ("TextServerExtension", "_shaped_text_get_object_range")
| ("TextServerExtension", "_shaped_text_get_object_glyph")
| ("TextServerExtension", "_shaped_text_get_size")
| ("TextServerExtension", "_shaped_text_get_ascent")
| ("TextServerExtension", "_shaped_text_get_descent")
| ("TextServerExtension", "_shaped_text_get_width")
| ("TextServerExtension", "_shaped_text_get_underline_position")
| ("TextServerExtension", "_shaped_text_get_underline_thickness")
| ("AudioStreamPlayback", "_mix")
| ("AudioStreamPlaybackResampled", "_mix_resampled")
| ("AudioStreamPlaybackResampled", "_get_stream_sampling_rate")
| ("AudioEffectInstance", "_process")
| ("AudioEffect", "_instantiate")
| ("PhysicsDirectBodyState2DExtension", _)
| ("PhysicsDirectBodyState3DExtension", _)
| ("PhysicsDirectSpaceState2DExtension", _)
| ("PhysicsDirectSpaceState3DExtension", _)
| ("PhysicsServer3DExtension", _)
| ("PhysicsServer2DExtension", _)
| ("EditorScript", "_run")
| ("VideoStreamPlayback", "_update")
| ("EditorFileSystemImportFormatSupportQuery", _)
| ("Mesh", _)
| ("Texture2D", "_get_width")
| ("Texture2D", "_get_height")
| ("Texture3D", _)
| ("TextureLayered", _)
| ("StyleBox", "_draw")
| ("Material", "_get_shader_rid")
| ("Material", "_get_shader_mode")
| ("PacketPeerExtension", "_get_available_packet_count")
| ("PacketPeerExtension", "_get_max_packet_size")
| ("StreamPeerExtension", "_get_available_bytes")
| ("WebRTCDataChannelExtension", "_poll")
| ("WebRTCDataChannelExtension", "_close")
| ("WebRTCDataChannelExtension", "_set_write_mode")
| ("WebRTCDataChannelExtension", "_get_write_mode")
| ("WebRTCDataChannelExtension", "_was_string_packet")
| ("WebRTCDataChannelExtension", "_get_ready_state")
| ("WebRTCDataChannelExtension", "_get_label")
| ("WebRTCDataChannelExtension", "_is_ordered")
| ("WebRTCDataChannelExtension", "_get_id")
| ("WebRTCDataChannelExtension", "_get_max_packet_life_time")
| ("WebRTCDataChannelExtension", "_get_max_retransmits")
| ("WebRTCDataChannelExtension", "_get_protocol")
| ("WebRTCDataChannelExtension", "_is_negotiated")
| ("WebRTCDataChannelExtension", "_get_buffered_amount")
| ("WebRTCDataChannelExtension", "_get_available_packet_count")
| ("WebRTCDataChannelExtension", "_get_max_packet_size")
| ("WebRTCPeerConnectionExtension", _)
| ("MultiplayerPeerExtension", "_get_available_packet_count")
| ("MultiplayerPeerExtension", "_get_max_packet_size")
| ("MultiplayerPeerExtension", "_set_transfer_channel")
| ("MultiplayerPeerExtension", "_get_transfer_channel")
| ("MultiplayerPeerExtension", "_set_transfer_mode")
| ("MultiplayerPeerExtension", "_get_transfer_mode")
| ("MultiplayerPeerExtension", "_set_target_peer")
| ("MultiplayerPeerExtension", "_get_packet_peer")
| ("MultiplayerPeerExtension", "_get_packet_mode")
| ("MultiplayerPeerExtension", "_get_packet_channel")
| ("MultiplayerPeerExtension", "_is_server")
| ("MultiplayerPeerExtension", "_poll")
| ("MultiplayerPeerExtension", "_close")
| ("MultiplayerPeerExtension", "_disconnect_peer")
| ("MultiplayerPeerExtension", "_get_unique_id")
| ("MultiplayerPeerExtension", "_get_connection_status") => true,
_ => false,
}
}
#[rustfmt::skip]
pub fn get_derived_virtual_method_presence(class_name: &TyName, godot_method_name: &str) -> VirtualMethodPresence {
match (class_name.godot_ty.as_str(), godot_method_name) {
| ("AudioStreamPlaybackResampled", "_mix")
=> VirtualMethodPresence::Remove,
| ("PrimitiveMesh", "_get_surface_count")
| ("PrimitiveMesh", "_surface_get_array_len")
| ("PrimitiveMesh", "_surface_get_array_index_len")
| ("PrimitiveMesh", "_surface_get_arrays")
| ("PrimitiveMesh", "_surface_get_blend_shape_arrays")
| ("PrimitiveMesh", "_surface_get_lods")
| ("PrimitiveMesh", "_surface_get_format")
| ("PrimitiveMesh", "_surface_get_primitive_type")
| ("PrimitiveMesh", "_surface_set_material")
| ("PrimitiveMesh", "_surface_get_material")
| ("PrimitiveMesh", "_get_blend_shape_count")
| ("PrimitiveMesh", "_get_blend_shape_name")
| ("PrimitiveMesh", "_set_blend_shape_name")
| ("PrimitiveMesh", "_get_aabb")
=> VirtualMethodPresence::Override { is_required: false },
| ("EditorSyntaxHighlighter", "_create") => VirtualMethodPresence::Override { is_required: true },
_ => VirtualMethodPresence::Inherit,
}
}
#[rustfmt::skip]
pub fn classify_codegen_level(class_name: &str) -> Option<ClassCodegenLevel> {
let level = match class_name {
| "Object" | "RefCounted" | "Resource" | "MainLoop" | "GDExtension"
=> ClassCodegenLevel::Core,
| "ProjectSettings" | "Engine" | "OS" | "Time" | "ClassDB"
=> ClassCodegenLevel::Core,
| "OpenXRExtensionWrapper"
=> ClassCodegenLevel::Core,
| "OpenXRExtensionWrapperExtension"
=> ClassCodegenLevel::Servers,
| "PhysicsDirectBodyState2D" | "PhysicsDirectBodyState2DExtension"
| "PhysicsDirectSpaceState2D" | "PhysicsDirectSpaceState2DExtension"
| "PhysicsServer2D" | "PhysicsServer2DExtension"
| "PhysicsServer2DManager"
| "PhysicsDirectBodyState3D" | "PhysicsDirectBodyState3DExtension"
| "PhysicsDirectSpaceState3D" | "PhysicsDirectSpaceState3DExtension"
| "PhysicsServer3D" | "PhysicsServer3DExtension"
| "PhysicsServer3DManager"
| "PhysicsServer3DRenderingServerHandler"
| "RenderData" | "RenderDataExtension"
| "RenderSceneData" | "RenderSceneDataExtension"
=> ClassCodegenLevel::Servers,
| "AudioServer" | "CameraServer" | "NavigationServer2D" | "NavigationServer3D" | "RenderingServer" | "TranslationServer" | "XRServer" | "DisplayServer"
=> ClassCodegenLevel::Servers,
"OpenXRInteractionProfileEditorBase"
| "OpenXRInteractionProfileEditor"
| "OpenXRBindingModifierEditor" if cfg!(before_api = "4.5")
=> ClassCodegenLevel::Editor,
"ResourceImporterOggVorbis" | "ResourceImporterMP3" if cfg!(before_api = "4.3")
=> ClassCodegenLevel::Editor,
_ => return None,
};
Some(level)
}
#[rustfmt::skip]
pub fn is_enum_private(class_name: Option<&TyName>, enum_name: &str) -> bool {
match (class_name, enum_name) {
| (None, "Corner")
| (None, "EulerOrder")
| (None, "Side")
| (None, "Variant.Operator")
| (None, "Variant.Type")
| (None, "PropertyHint")
| (None, "PropertyUsageFlags")
| (None, "MethodFlags")
=> true, _ => false
}
}
#[rustfmt::skip]
pub fn is_enum_exhaustive(class_name: Option<&TyName>, enum_name: &str) -> bool {
match (class_name, enum_name) {
| (None, "ClockDirection")
| (None, "Corner")
| (None, "EulerOrder")
| (None, "Side")
| (None, "Orientation")
=> true, _ => false
}
}
#[rustfmt::skip]
pub fn is_enum_bitfield(class_name: Option<&TyName>, enum_name: &str) -> Option<bool> {
let class_name = class_name.map(|c| c.godot_ty.as_str());
match (class_name, enum_name) {
| (Some("FileAccess"), "ModeFlags")
| (Some("GPUParticles2D"), "EmitFlags")
| (Some("GPUParticles3D"), "EmitFlags")
| (Some("Node"), "DuplicateFlags")
| (Some("Object"), "ConnectFlags") | (Some("SceneTree"), "GroupCallFlags")
| (Some("TextEdit"), "SearchFlags")
=> Some(true),
_ => None
}
}
pub fn as_enum_bitmaskable(enum_: &Enum) -> Option<RustTy> {
if enum_.is_bitfield {
return None;
}
let class_name = enum_.surrounding_class.as_ref();
let class_name_str = class_name.map(|ty| ty.godot_ty.as_str());
let enum_name = enum_.godot_name.as_str();
let mapped = match (class_name_str, enum_name) {
(None, "Key") => "KeyModifierMask",
(None, "MouseButton") => "MouseButtonMask",
_ => return None,
};
assert!(
!is_enum_exhaustive(class_name, enum_name),
"Enum {enum_name} with bitmask mapping cannot be exhaustive"
);
let rust_ty = to_enum_type_uncached(mapped, true);
Some(rust_ty)
}