Skip to content

Commit 27bf125

Browse files
committed
Rename godot::engine -> godot::classes
Keep all symbols available as deprecated.
1 parent 1e9ea80 commit 27bf125

File tree

5 files changed

+167
-146
lines changed

5 files changed

+167
-146
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
//! Runtime checks and inspection of Godot classes.
9+
10+
use crate::builtin::meta::{CallContext, ClassName};
11+
use crate::builtin::GString;
12+
use crate::classes::{ClassDb, Object};
13+
use crate::obj::{bounds, Bounds, Gd, GodotClass, InstanceId};
14+
use crate::sys;
15+
16+
pub(crate) fn debug_string<T: GodotClass>(
17+
obj: &Gd<T>,
18+
f: &mut std::fmt::Formatter<'_>,
19+
ty: &str,
20+
) -> std::fmt::Result {
21+
if let Some(id) = obj.instance_id_or_none() {
22+
let class: GString = obj.raw.as_object().get_class();
23+
write!(f, "{ty} {{ id: {id}, class: {class} }}")
24+
} else {
25+
write!(f, "{ty} {{ freed obj }}")
26+
}
27+
}
28+
29+
pub(crate) fn display_string<T: GodotClass>(
30+
obj: &Gd<T>,
31+
f: &mut std::fmt::Formatter<'_>,
32+
) -> std::fmt::Result {
33+
let string: GString = obj.raw.as_object().to_string();
34+
<GString as std::fmt::Display>::fmt(&string, f)
35+
}
36+
37+
pub(crate) fn object_ptr_from_id(instance_id: InstanceId) -> sys::GDExtensionObjectPtr {
38+
// SAFETY: Godot looks up ID in ObjectDB and returns null if not found.
39+
unsafe { sys::interface_fn!(object_get_instance_from_id)(instance_id.to_u64()) }
40+
}
41+
42+
pub(crate) fn construct_engine_object<T>() -> Gd<T>
43+
where
44+
T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
45+
{
46+
// SAFETY: adhere to Godot API; valid class name and returned pointer is an object.
47+
unsafe {
48+
let object_ptr = sys::interface_fn!(classdb_construct_object)(T::class_name().string_sys());
49+
Gd::from_obj_sys(object_ptr)
50+
}
51+
}
52+
53+
pub(crate) fn ensure_object_alive(
54+
instance_id: InstanceId,
55+
old_object_ptr: sys::GDExtensionObjectPtr,
56+
call_ctx: &CallContext,
57+
) {
58+
let new_object_ptr = object_ptr_from_id(instance_id);
59+
60+
assert!(
61+
!new_object_ptr.is_null(),
62+
"{call_ctx}: access to instance with ID {instance_id} after it has been freed"
63+
);
64+
65+
// This should not happen, as reuse of instance IDs was fixed according to https://github.com/godotengine/godot/issues/32383,
66+
// namely in PR https://github.com/godotengine/godot/pull/36189. Double-check to make sure.
67+
assert_eq!(
68+
new_object_ptr, old_object_ptr,
69+
"{call_ctx}: instance ID {instance_id} points to a stale, reused object. Please report this to gdext maintainers."
70+
);
71+
}
72+
73+
#[cfg(debug_assertions)]
74+
pub(crate) fn ensure_object_inherits(
75+
derived: ClassName,
76+
base: ClassName,
77+
instance_id: InstanceId,
78+
) -> bool {
79+
if derived == base
80+
|| base == Object::class_name() // for Object base, anything inherits by definition
81+
|| is_derived_base_cached(derived, base)
82+
{
83+
return true;
84+
}
85+
86+
panic!(
87+
"Instance of ID {instance_id} has type {derived} but is incorrectly stored in a Gd<{base}>.\n\
88+
This may happen if you change an object's identity through DerefMut."
89+
)
90+
}
91+
92+
// ----------------------------------------------------------------------------------------------------------------------------------------------
93+
// Implementation of this file
94+
95+
/// Checks if `derived` inherits from `base`, using a cache for _successful_ queries.
96+
#[cfg(debug_assertions)]
97+
fn is_derived_base_cached(derived: ClassName, base: ClassName) -> bool {
98+
use std::collections::HashSet;
99+
use sys::Global;
100+
static CACHE: Global<HashSet<(ClassName, ClassName)>> = Global::default();
101+
102+
let mut cache = CACHE.lock();
103+
let key = (derived, base);
104+
if cache.contains(&key) {
105+
return true;
106+
}
107+
108+
// Query Godot API (takes linear time in depth of inheritance tree).
109+
let is_parent_class =
110+
ClassDb::singleton().is_parent_class(derived.to_string_name(), base.to_string_name());
111+
112+
// Insert only successful queries. Those that fail are on the error path already and don't need to be fast.
113+
if is_parent_class {
114+
cache.insert(key);
115+
}
116+
117+
is_parent_class
118+
}

godot-core/src/classes/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
//! Maps the Godot class API to Rust.
9+
//!
10+
//! This module contains the following symbols:
11+
//! * Classes: `CanvasItem`, etc.
12+
//! * Virtual traits: `ICanvasItem`, etc.
13+
//! * Enum/flag modules: `canvas_item`, etc.
14+
//!
15+
//! Noteworthy sub-modules are:
16+
//! * [`notify`][crate::engine::notify]: all notification enums, used when working with the virtual callback to handle lifecycle notifications.
17+
//! * [`native`][crate::engine::native]: definition of _native structure_ types.
18+
19+
mod class_runtime;
20+
mod manual_extensions;
21+
22+
// Re-exports all generated classes, interface traits and sidecar modules.
23+
pub use crate::gen::classes::*;
24+
25+
/// Support for Godot _native structures_.
26+
///
27+
/// Native structures are a niche API in Godot. These are low-level data types that are passed as pointers to/from the engine.
28+
/// In Rust, they are represented as `#[repr(C)]` structs.
29+
///
30+
/// There is unfortunately not much official documentation available; you may need to look at Godot source code.
31+
/// Most users will not need native structures, as they are very specialized.
32+
pub mod native {
33+
pub use crate::gen::native::*;
34+
}
35+
36+
// ----------------------------------------------------------------------------------------------------------------------------------------------
37+
// Crate-local utilities
38+
39+
pub(crate) use class_runtime::*;

godot-core/src/engine/mod.rs

Lines changed: 9 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -5,36 +5,12 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8-
//! Godot engine classes and methods.
8+
#![deprecated = "Module has been split into `godot::classes`, `godot::global` and `godot::extras`."]
99

10-
use crate::builtin::GString;
11-
use crate::obj::{bounds, Bounds, Gd, GodotClass, InstanceId};
10+
use crate::obj::{Bounds, GodotClass};
1211

13-
// Re-exports of generated symbols
14-
15-
pub use crate::gen::classes::*;
16-
17-
use crate::builtin::meta::CallContext;
18-
use crate::sys;
19-
20-
mod manual_extensions;
21-
22-
#[cfg(debug_assertions)]
23-
use crate::builtin::meta::ClassName;
24-
25-
/// Support for Godot _native structures_.
26-
///
27-
/// Native structures are a niche API in Godot. These are low-level data types that are passed as pointers to/from the engine.
28-
/// In Rust, they are represented as `#[repr(C)]` structs.
29-
///
30-
/// There is unfortunately not much official documentation available; you may need to look at Godot source code.
31-
/// Most users will not need native structures, as they are very specialized.
32-
pub mod native {
33-
pub use crate::gen::native::*;
34-
}
35-
36-
// ----------------------------------------------------------------------------------------------------------------------------------------------
37-
// Deprecations
12+
#[deprecated = "Classes have been moved to `godot::classes`."]
13+
pub use crate::classes::*;
3814

3915
#[deprecated = "Enums have been moved to `godot::global`."]
4016
pub mod global {
@@ -47,6 +23,11 @@ pub mod utilities {
4723
pub use crate::global::*;
4824
}
4925

26+
#[deprecated = "Native structures have been moved to `godot::classes::native`."]
27+
pub mod native {
28+
pub use crate::gen::native::*;
29+
}
30+
5031
#[deprecated = "`godot::engine::translate` has been moved to `godot::extras`."]
5132
pub mod translate {
5233
pub use crate::extras::{tr, tr_n};
@@ -78,110 +59,3 @@ pub use crate::global::load;
7859

7960
#[deprecated = "`try_load` has been moved to `godot::global`."]
8061
pub use crate::global::try_load;
81-
82-
// ----------------------------------------------------------------------------------------------------------------------------------------------
83-
// Utilities for crate
84-
85-
pub(crate) fn debug_string<T: GodotClass>(
86-
obj: &Gd<T>,
87-
f: &mut std::fmt::Formatter<'_>,
88-
ty: &str,
89-
) -> std::fmt::Result {
90-
if let Some(id) = obj.instance_id_or_none() {
91-
let class: GString = obj.raw.as_object().get_class();
92-
write!(f, "{ty} {{ id: {id}, class: {class} }}")
93-
} else {
94-
write!(f, "{ty} {{ freed obj }}")
95-
}
96-
}
97-
98-
pub(crate) fn display_string<T: GodotClass>(
99-
obj: &Gd<T>,
100-
f: &mut std::fmt::Formatter<'_>,
101-
) -> std::fmt::Result {
102-
let string: GString = obj.raw.as_object().to_string();
103-
<GString as std::fmt::Display>::fmt(&string, f)
104-
}
105-
106-
pub(crate) fn object_ptr_from_id(instance_id: InstanceId) -> sys::GDExtensionObjectPtr {
107-
// SAFETY: Godot looks up ID in ObjectDB and returns null if not found.
108-
unsafe { sys::interface_fn!(object_get_instance_from_id)(instance_id.to_u64()) }
109-
}
110-
111-
pub(crate) fn construct_engine_object<T>() -> Gd<T>
112-
where
113-
T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
114-
{
115-
// SAFETY: adhere to Godot API; valid class name and returned pointer is an object.
116-
unsafe {
117-
let object_ptr = sys::interface_fn!(classdb_construct_object)(T::class_name().string_sys());
118-
Gd::from_obj_sys(object_ptr)
119-
}
120-
}
121-
122-
pub(crate) fn ensure_object_alive(
123-
instance_id: InstanceId,
124-
old_object_ptr: sys::GDExtensionObjectPtr,
125-
call_ctx: &CallContext,
126-
) {
127-
let new_object_ptr = object_ptr_from_id(instance_id);
128-
129-
assert!(
130-
!new_object_ptr.is_null(),
131-
"{call_ctx}: access to instance with ID {instance_id} after it has been freed"
132-
);
133-
134-
// This should not happen, as reuse of instance IDs was fixed according to https://github.com/godotengine/godot/issues/32383,
135-
// namely in PR https://github.com/godotengine/godot/pull/36189. Double-check to make sure.
136-
assert_eq!(
137-
new_object_ptr, old_object_ptr,
138-
"{call_ctx}: instance ID {instance_id} points to a stale, reused object. Please report this to gdext maintainers."
139-
);
140-
}
141-
142-
#[cfg(debug_assertions)]
143-
pub(crate) fn ensure_object_inherits(
144-
derived: ClassName,
145-
base: ClassName,
146-
instance_id: InstanceId,
147-
) -> bool {
148-
if derived == base
149-
|| base == Object::class_name() // for Object base, anything inherits by definition
150-
|| is_derived_base_cached(derived, base)
151-
{
152-
return true;
153-
}
154-
155-
panic!(
156-
"Instance of ID {instance_id} has type {derived} but is incorrectly stored in a Gd<{base}>.\n\
157-
This may happen if you change an object's identity through DerefMut."
158-
)
159-
}
160-
161-
// ----------------------------------------------------------------------------------------------------------------------------------------------
162-
// Implementation of this file
163-
164-
/// Checks if `derived` inherits from `base`, using a cache for _successful_ queries.
165-
#[cfg(debug_assertions)]
166-
fn is_derived_base_cached(derived: ClassName, base: ClassName) -> bool {
167-
use std::collections::HashSet;
168-
use sys::Global;
169-
static CACHE: Global<HashSet<(ClassName, ClassName)>> = Global::default();
170-
171-
let mut cache = CACHE.lock();
172-
let key = (derived, base);
173-
if cache.contains(&key) {
174-
return true;
175-
}
176-
177-
// Query Godot API (takes linear time in depth of inheritance tree).
178-
let is_parent_class =
179-
ClassDb::singleton().is_parent_class(derived.to_string_name(), base.to_string_name());
180-
181-
// Insert only successful queries. Those that fail are on the error path already and don't need to be fast.
182-
if is_parent_class {
183-
cache.insert(key);
184-
}
185-
186-
is_parent_class
187-
}

godot-core/src/lib.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod storage;
1010

1111
pub mod builder;
1212
pub mod builtin;
13+
pub mod classes;
1314
pub mod global;
1415
pub mod init;
1516
pub mod obj;
@@ -31,17 +32,6 @@ pub use godot_ffi as sys;
3132
#[doc(hidden)]
3233
pub use godot_ffi::out;
3334
pub use registry::*;
34-
35-
/// Maps the Godot class API to Rust.
36-
///
37-
/// This module contains the following symbols:
38-
/// * Classes: `CanvasItem`, etc.
39-
/// * Virtual traits: `ICanvasItem`, etc.
40-
/// * Enum/flag modules: `canvas_item`, etc.
41-
///
42-
/// Noteworthy sub-modules are:
43-
/// * [`notify`][crate::engine::notify]: all notification enums, used when working with the virtual callback to handle lifecycle notifications.
44-
/// * [`native`][crate::engine::native]: definition of _native structure_ types.
4535
pub mod engine;
4636

4737
/// Higher-level additions to the Godot engine API.

0 commit comments

Comments
 (0)