Skip to content

Commit 8e051d9

Browse files
committed
Added @export_storage Export Type
1 parent 2f670db commit 8e051d9

File tree

7 files changed

+76
-13
lines changed

7 files changed

+76
-13
lines changed

godot-core/src/registry/property.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ pub mod export_info_functions {
462462
// right side are the corresponding property hint. Godot is not always consistent between the two, such
463463
// as `export_multiline` being `PROPERTY_HINT_MULTILINE_TEXT`.
464464
default_export_funcs!(
465+
export_storage => NONE,
465466
export_flags_2d_physics => LAYERS_2D_PHYSICS,
466467
export_flags_2d_render => LAYERS_2D_RENDER,
467468
export_flags_2d_navigation => LAYERS_2D_NAVIGATION,

godot-macros/src/class/data_models/field_export.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ impl FieldExport {
2727
pub fn to_export_hint(&self) -> Option<TokenStream> {
2828
self.export_type.to_export_hint()
2929
}
30+
31+
pub fn to_export_usage(&self) -> Option<Ident> {
32+
self.export_type.to_export_usage()
33+
}
3034
}
3135

3236
/// Store info from `#[export]` attribute.
@@ -40,6 +44,16 @@ pub enum ExportType {
4044
/// Can become other property hints, depends on context.
4145
Default,
4246

47+
/// ### GDScript annotations
48+
/// - `@export_storage`
49+
///
50+
/// ### Property hints
51+
/// - `NONE`
52+
///
53+
/// This is used to indicate that the property should be exported
54+
/// but should not be visible in the editor.
55+
Storage,
56+
4357
/// ### GDScript annotations
4458
/// - `@export_range`
4559
///
@@ -150,6 +164,10 @@ impl ExportType {
150164
/// becomes
151165
/// `#[export(flags/enum = (elem1, elem2 = key2, ...))]`
152166
pub(crate) fn new_from_kv(parser: &mut KvParser) -> ParseResult<Self> {
167+
if parser.handle_alone("storage")? {
168+
return Self::new_storage();
169+
}
170+
153171
if let Some(list_parser) = parser.handle_list("range")? {
154172
return Self::new_range_list(list_parser);
155173
}
@@ -273,6 +291,10 @@ impl ExportType {
273291
Ok(Self::Default)
274292
}
275293

294+
fn new_storage() -> ParseResult<Self> {
295+
Ok(Self::Storage)
296+
}
297+
276298
fn new_range_list(mut parser: ListParser) -> ParseResult<Self> {
277299
const FLAG_OPTIONS: [&str; 7] = [
278300
"or_greater",
@@ -396,6 +418,8 @@ impl ExportType {
396418
match self {
397419
Self::Default => None,
398420

421+
Self::Storage => quote_export_func! { export_storage() },
422+
399423
Self::Range {
400424
min,
401425
max,
@@ -513,6 +537,16 @@ impl ExportType {
513537
Self::ColorNoAlpha => quote_export_func! { export_color_no_alpha() },
514538
}
515539
}
540+
541+
pub fn to_export_usage(&self) -> Option<Ident> {
542+
match self {
543+
#[cfg(since_api = "4.3")]
544+
Self::Storage => Some(Ident::new("STORAGE", Span::call_site())),
545+
#[cfg(not(since_api = "4.3"))]
546+
Self::Storage => Some(Ident::new("DEFAULT", Span::call_site())),
547+
_ => None,
548+
}
549+
}
516550
}
517551

518552
/// The dimension of a `@export_flags_{dimension}_{layer}` annotation.

godot-macros/src/class/data_models/property.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,17 @@ pub fn make_property_impl(class_name: &Ident, fields: &Fields) -> TokenStream {
5353

5454
// Ensure we add a var if the user only provided a `#[export]`.
5555
let var = match (export, var) {
56-
(Some(_), None) => Some(FieldVar {
57-
usage_flags: UsageFlags::InferredExport,
58-
..Default::default()
59-
}),
56+
(Some(export), None) => {
57+
let usage_flags = if let Some(usage) = export.to_export_usage() {
58+
UsageFlags::Custom(vec![usage])
59+
} else {
60+
UsageFlags::InferredExport
61+
};
62+
Some(FieldVar {
63+
usage_flags,
64+
..Default::default()
65+
})
66+
}
6067

6168
(_, var) => var.clone(),
6269
};

godot-macros/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@ use crate::util::{bail, ident, KvParser};
243243
/// // @export
244244
/// #[export]
245245
/// float: f64,
246-
///
246+
///
247+
/// // @export_storage
248+
/// #[export(storage)]
249+
/// hidden_string: GString,
250+
///
247251
/// // @export_range(0.0, 10.0, or_greater)
248252
/// #[export(range = (0.0, 10.0, or_greater))]
249253
/// range_f64: f64,

itest/rust/build.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,11 @@ fn generate_property_template(inputs: &[Input]) -> PropertyTests {
471471
pub struct PropertyTestsRust {
472472
#(#rust,)*
473473

474+
#[export]
475+
export_string: GString,
476+
#[cfg(since_api = "4.3")]
477+
#[export(storage)]
478+
export_storage: GString,
474479
#[export(file)]
475480
export_file: GString,
476481
#[export(file = "*.txt")]
@@ -525,6 +530,8 @@ fn generate_property_template(inputs: &[Input]) -> PropertyTests {
525530
let gdscript = format!(
526531
r#"
527532
{}
533+
@export var export_string: String
534+
{}
528535
@export_file var export_file: String
529536
@export_file("*.txt") var export_file_wildcard_txt: String
530537
@export_global_file var export_global_file: String
@@ -550,7 +557,12 @@ fn generate_property_template(inputs: &[Input]) -> PropertyTests {
550557
@export_enum("Slow:30", "Average:60", "VeryFast:200") var export_enum_int_slow_30_average_60_very_fast_200: int
551558
@export_enum("Rebecca", "Mary", "Leah") var export_enum_string_rebecca_mary_leah: String
552559
"#,
553-
gdscript.join("\n")
560+
gdscript.join("\n"),
561+
if godot_bindings::since_api("4.3") {
562+
"@export_storage var export_storage: String"
563+
} else {
564+
""
565+
}
554566
);
555567

556568
PropertyTests { rust, gdscript }

itest/rust/src/object_tests/property_template_test.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,15 @@ fn property_template_test(ctx: &TestContext) {
6060

6161
let mut rust_usage = rust_prop.at("usage").to::<i64>();
6262

63-
// the GDSscript variables are script variables, and so have `PROPERTY_USAGE_SCRIPT_VARIABLE` set.
64-
if rust_usage == PropertyUsageFlags::STORAGE.ord() as i64 {
65-
// `PROPERTY_USAGE_SCRIPT_VARIABLE` does the same thing as `PROPERTY_USAGE_STORAGE` and so
66-
// GDScript doesn't set both if it doesn't need to.
67-
rust_usage = PropertyUsageFlags::SCRIPT_VARIABLE.ord() as i64
63+
// The GDSscript variables are script variables, and so have `PROPERTY_USAGE_SCRIPT_VARIABLE` set.
64+
// Before 4.3, `PROPERTY_USAGE_SCRIPT_VARIABLE` did the same thing as `PROPERTY_USAGE_STORAGE` and
65+
// so GDScript didn't set both if it didn't need to.
66+
if GdextBuild::before_api("4.3") {
67+
if rust_usage == PropertyUsageFlags::STORAGE.ord() as i64 {
68+
rust_usage = PropertyUsageFlags::SCRIPT_VARIABLE.ord() as i64
69+
} else {
70+
rust_usage |= PropertyUsageFlags::SCRIPT_VARIABLE.ord() as i64;
71+
}
6872
} else {
6973
rust_usage |= PropertyUsageFlags::SCRIPT_VARIABLE.ord() as i64;
7074
}
@@ -95,12 +99,12 @@ fn property_template_test(ctx: &TestContext) {
9599
}
96100
}
97101

102+
rust_properties.free();
103+
98104
assert!(
99105
properties.is_empty(),
100106
"not all properties were matched, missing: {properties:?}"
101107
);
102108

103109
assert!(errors.is_empty(), "{}", errors.join("\n"));
104-
105-
rust_properties.free();
106110
}

rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
hard_tabs = false

0 commit comments

Comments
 (0)