Skip to content

Commit 2449468

Browse files
committed
Merge branch 'master' of https://github.com/godot-rust/gdextension into feature/godot-compat
2 parents 0576c11 + c3e7023 commit 2449468

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1067
-148
lines changed

.github/workflows/full-ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ on:
1515

1616
env:
1717
GDEXT_FEATURES: ''
18+
# GDEXT_FEATURES: '--features godot/serde'
1819
RETRY: ${{ github.workspace }}/.github/other/retry.sh
1920

2021
# LSan options: https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
@@ -217,7 +218,7 @@ jobs:
217218
os: ubuntu-20.04
218219
artifact-name: linux-nightly
219220
godot-binary: godot.linuxbsd.editor.dev.x86_64
220-
rust-extra-args: --features godot/custom-godot,godot/threads,godot/serde
221+
rust-extra-args: --features godot/custom-godot,godot/experimental-threads,godot/serde
221222

222223
# Linux compat
223224

.github/workflows/minimal-ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ jobs:
149149
os: ubuntu-20.04
150150
artifact-name: linux-nightly
151151
godot-binary: godot.linuxbsd.editor.dev.x86_64
152-
rust-extra-args: --features godot/custom-godot,godot/threads,godot/serde
152+
rust-extra-args: --features godot/custom-godot,godot/experimental-threads,godot/serde
153153

154154
# Linux compat
155155

godot-bindings/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ godot4-prebuilt = { optional = true, git = "https://github.com/godot-rust/godot4
2525
bindgen = { optional = true, version = "0.65", default-features = false, features = ["runtime"] }
2626
regex = { optional = true, version = "1.5.5", default-features = false, features = ["std", "unicode-gencat"] }
2727
which = { optional = true, version = "4" }
28+
29+
[dev-dependencies]
30+
# For tests, we need regex unconditionally. Keep this in sync with above dependency.
31+
regex = { version = "1.5.5", default-features = false, features = ["std", "unicode-gencat"] }

godot-bindings/src/godot_version.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn parse_godot_version(version_str: &str) -> Result<GodotVersion, Box<dyn Er
1616
// https://github.com/godot-rust/gdext/issues/118#issuecomment-1465748123
1717
// We assume that it's on a line of its own, but it may be surrounded by other lines.
1818
let regex = Regex::new(
19-
r#"(?xm)
19+
r"(?xm)
2020
# x: ignore whitespace and allow line comments (starting with `#`)
2121
# m: multi-line mode, ^ and $ match start and end of line
2222
^
@@ -32,15 +32,17 @@ pub fn parse_godot_version(version_str: &str) -> Result<GodotVersion, Box<dyn Er
3232
(\.[^.]+)+?
3333
# Git commit SHA1, currently truncated to 9 chars, but accept the full thing
3434
(?:\.(?P<custom_rev>[a-f0-9]{9,40}))?
35+
# Optional newline printed in some systems (e.g. Arch Linux, see #416)
36+
(?:\\n)?
3537
$
36-
"#,
38+
",
3739
)?;
3840

3941
let fail = || format!("Version substring cannot be parsed: `{version_str}`");
4042
let caps = regex.captures(version_str).ok_or_else(fail)?;
4143

4244
Ok(GodotVersion {
43-
full_string: caps.get(0).unwrap().as_str().to_string(),
45+
full_string: caps.get(0).unwrap().as_str().trim().to_string(),
4446
major: cap(&caps, "major")?.unwrap(),
4547
minor: cap(&caps, "minor")?.unwrap(),
4648
patch: cap(&caps, "patch")?.unwrap_or(0),
@@ -86,6 +88,7 @@ fn test_godot_versions() {
8688
("4.0.beta8.mono.custom_build.b28ddd918", 4, 0, 0, "beta8", s("b28ddd918")),
8789
("4.0.rc1.official.8843d9ad3", 4, 0, 0, "rc1", s("8843d9ad3")),
8890
("4.0.stable.arch_linux", 4, 0, 0, "stable", None),
91+
("4.1.1.stable.arch_linux\n", 4, 1, 1, "stable", None),
8992
// Output from 4.0.stable on MacOS in debug mode:
9093
// https://github.com/godotengine/godot/issues/74906
9194
("arguments
@@ -104,7 +107,7 @@ Current path: /Users/runner/work/gdext/gdext/godot-core
104107
for (full, major, minor, patch, status, custom_rev) in good_versions {
105108
let expected = GodotVersion {
106109
// Version line is last in every test at the moment.
107-
full_string: full.lines().last().unwrap().to_owned(),
110+
full_string: full.lines().last().unwrap().trim().to_owned(),
108111
major,
109112
minor,
110113
patch,

godot-bindings/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ pub struct GodotVersion {
4040
// ----------------------------------------------------------------------------------------------------------------------------------------------
4141
// Regenerate all files
4242

43+
// This file is explicitly included in unit tests. Needs regex dependency.
44+
#[cfg(test)]
45+
mod godot_version;
46+
4347
#[cfg(feature = "custom-godot")]
4448
#[path = ""]
4549
mod custom {

godot-codegen/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ codegen-fmt = []
1313
codegen-full = []
1414
double-precision = []
1515
custom-godot = ["godot-bindings/custom-godot"]
16+
experimental-godot-api = []
1617

1718
[dependencies]
1819
godot-bindings = { path = "../godot-bindings" }

godot-codegen/src/class_generator.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ fn make_class(class: &Class, class_name: &TyName, ctx: &mut Context) -> Generate
506506

507507
let constructor = make_constructor(class, ctx);
508508
let api_level = util::get_api_level(class);
509+
let init_level = api_level.to_init_level();
509510

510511
let FnDefinitions {
511512
functions: methods,
@@ -618,6 +619,7 @@ fn make_class(class: &Class, class_name: &TyName, ctx: &mut Context) -> Generate
618619
type Base = #base_ty;
619620
type Declarer = crate::obj::dom::EngineDomain;
620621
type Mem = crate::obj::mem::#memory;
622+
const INIT_LEVEL: Option<crate::init::InitLevel> = #init_level;
621623

622624
fn class_name() -> ClassName {
623625
ClassName::from_ascii_cstr(#class_name_cstr)

godot-codegen/src/codegen_special_cases.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ const SELECTED_CLASSES: &[&str] = &[
127127
"CollisionObject2D",
128128
"CollisionShape2D",
129129
"Control",
130+
"EditorPlugin",
130131
"Engine",
131132
"FileAccess",
132133
"HTTPRequest",

godot-codegen/src/special_cases.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,12 @@ pub(crate) fn is_deleted(class_name: &TyName, method: &ClassMethod, ctx: &mut Co
4444

4545
#[rustfmt::skip]
4646
pub(crate) fn is_class_deleted(class_name: &TyName) -> bool {
47-
let class_name = class_name.godot_ty.as_str();
48-
49-
// TODO feature-gate experimental classes.
50-
/*
47+
// Exclude experimental APIs unless opted-in.
5148
if !cfg!(feature = "experimental-godot-api") && is_class_experimental(class_name) {
5249
return true;
5350
}
54-
*/
51+
52+
let class_name = class_name.godot_ty.as_str();
5553

5654
// OpenXR has not been available for macOS before 4.2.
5755
// See e.g. https://github.com/GodotVR/godot-xr-tools/issues/479.
@@ -71,9 +69,15 @@ pub(crate) fn is_class_deleted(class_name: &TyName) -> bool {
7169

7270
match class_name {
7371
// Hardcoded cases that are not accessible.
74-
| "JavaClassWrapper" // only on Android.
75-
| "JavaScriptBridge" // only on WASM.
76-
| "ThemeDB" // lazily loaded; TODO enable this.
72+
// Only on Android.
73+
| "JavaClassWrapper"
74+
| "JNISingleton"
75+
| "JavaClass"
76+
// Only on WASM.
77+
| "JavaScriptBridge"
78+
| "JavaScriptObject"
79+
// lazily loaded; TODO enable this.
80+
| "ThemeDB"
7781

7882
// Thread APIs.
7983
| "Thread"
@@ -99,7 +103,6 @@ pub(crate) fn is_class_deleted(class_name: &TyName) -> bool {
99103
}
100104

101105
#[rustfmt::skip]
102-
#[allow(dead_code)] // remove once used.
103106
fn is_class_experimental(class_name: &TyName) -> bool {
104107
// These classes are currently hardcoded, but the information is available in Godot's doc/classes directory.
105108
// The XML file contains a property <class name="NavigationMesh" ... is_experimental="true">.
@@ -124,7 +127,6 @@ fn is_class_experimental(class_name: &TyName) -> bool {
124127
| "NavigationRegion3D"
125128
| "NavigationServer2D"
126129
| "NavigationServer3D"
127-
| "ProjectSettings"
128130
| "SkeletonModification2D"
129131
| "SkeletonModification2DCCDIK"
130132
| "SkeletonModification2DFABRIK"

godot-codegen/src/util.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ impl ClassCodegenLevel {
6666
Self::Lazy => unreachable!("lazy classes should be deleted at the moment"),
6767
}
6868
}
69+
70+
pub fn to_init_level(self) -> TokenStream {
71+
match self {
72+
Self::Servers => quote! { Some(crate::init::InitLevel::Servers) },
73+
Self::Scene => quote! { Some(crate::init::InitLevel::Scene) },
74+
Self::Editor => quote! { Some(crate::init::InitLevel::Editor) },
75+
Self::Lazy => quote! { None },
76+
}
77+
}
6978
}
7079

7180
// ----------------------------------------------------------------------------------------------------------------------------------------------
@@ -172,13 +181,20 @@ pub(crate) fn make_utility_function_ptr_name(function: &UtilityFunction) -> Iden
172181
safe_ident(&function.name)
173182
}
174183

175-
// TODO should eventually be removed, as all StringNames are cached
184+
#[cfg(since_api = "4.2")]
176185
pub fn make_string_name(identifier: &str) -> TokenStream {
186+
let lit = proc_macro2::Literal::byte_string(format!("{identifier}\0").as_bytes());
177187
quote! {
178-
StringName::from(#identifier)
188+
StringName::from_latin1_with_nul(#lit)
179189
}
180190
}
181191

192+
#[cfg(before_api = "4.2")]
193+
pub fn make_string_name(identifier: &str) -> TokenStream {
194+
quote! {
195+
StringName::from(#identifier)
196+
}
197+
}
182198
pub fn make_sname_ptr(identifier: &str) -> TokenStream {
183199
quote! {
184200
string_names.fetch(#identifier)

godot-core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ codegen-fmt = ["godot-ffi/codegen-fmt", "godot-codegen/codegen-fmt"]
1414
codegen-full = ["godot-codegen/codegen-full"]
1515
double-precision = ["godot-codegen/double-precision"]
1616
custom-godot = ["godot-ffi/custom-godot", "godot-codegen/custom-godot"]
17-
threads = []
17+
experimental-godot-api = ["godot-codegen/experimental-godot-api"]
18+
experimental-threads = []
1819

1920
[dependencies]
2021
godot-ffi = { path = "../godot-ffi" }

godot-core/src/builtin/array.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ impl<T: GodotType> Array<T> {
179179
interface_fn!(array_operator_index_const)(self.sys(), index)
180180
};
181181

182+
// Signature is wrong in GDExtension, semantically this is a const ptr
183+
let variant_ptr = sys::to_const_ptr(variant_ptr);
182184
Variant::ptr_from_sys(variant_ptr)
183185
}
184186

0 commit comments

Comments
 (0)