Skip to content

File tree

4 files changed

+107
-1
lines changed

4 files changed

+107
-1
lines changed

gdnative-core/src/export/property.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,29 @@ impl PropertyUsage {
322322
}
323323
}
324324

325+
/// Marker for defining property groups.
326+
#[derive(Debug)]
327+
pub struct GroupMarker;
328+
329+
impl crate::core_types::ToVariant for GroupMarker {
330+
fn to_variant(&self) -> Variant {
331+
Variant::nil()
332+
}
333+
}
334+
335+
impl crate::core_types::FromVariant for GroupMarker {
336+
fn from_variant(variant: &Variant) -> Result<Self, FromVariantError> {
337+
if variant.is_nil() {
338+
Ok(Self)
339+
} else {
340+
Err(FromVariantError::InvalidVariantType {
341+
variant_type: variant.get_type(),
342+
expected: VariantType::Nil,
343+
})
344+
}
345+
}
346+
}
347+
325348
mod impl_export {
326349
use super::*;
327350

@@ -481,4 +504,13 @@ mod impl_export {
481504
hint.unwrap_or_default().export_info()
482505
}
483506
}
507+
508+
impl Export for GroupMarker {
509+
type Hint = hint::GroupHint;
510+
511+
#[inline]
512+
fn export_info(hint: Option<Self::Hint>) -> ExportInfo {
513+
hint.unwrap_or_default().export_info()
514+
}
515+
}
484516
}

gdnative-core/src/export/property/hint.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,3 +465,29 @@ impl ArrayHint {
465465
}
466466
}
467467
}
468+
469+
/// Provides a hint prefix for group members.
470+
#[derive(Clone, Debug, Default)]
471+
pub struct GroupHint {
472+
prefix: String,
473+
}
474+
475+
impl GroupHint {
476+
/// Returns a `GroupHint` with a specific prefix.
477+
#[inline]
478+
pub fn new<S: ToString>(prefix: S) -> Self {
479+
Self {
480+
prefix: prefix.to_string(),
481+
}
482+
}
483+
484+
#[inline]
485+
pub fn export_info(self) -> ExportInfo {
486+
ExportInfo {
487+
variant_type: VariantType::Nil,
488+
// hint_kind: sys::godot_property_hint_GODOT_PROPERTY_HINT_TYPE_STRING,
489+
hint_kind: sys::godot_property_hint_GODOT_PROPERTY_HINT_NONE,
490+
hint_string: GodotString::from_str(&self.prefix),
491+
}
492+
}
493+
}

gdnative-derive/src/native_script.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,32 @@ pub(crate) fn derive_native_class(derive_input: &DeriveInput) -> Result<TokenStr
6464
let properties = data.properties.into_iter().map(|(ident, config)| {
6565
let with_default = config
6666
.default
67+
.as_ref()
6768
.map(|default_value| quote!(.with_default(#default_value)));
68-
let with_hint = config.hint.map(|hint_fn| quote!(.with_hint(#hint_fn())));
69+
let with_hint = config
70+
.hint
71+
.as_ref()
72+
.map(|hint_fn| quote!(.with_hint(#hint_fn())))
73+
.or_else(|| {
74+
if let Some(Some(prefix)) = &config.group {
75+
Some(quote!(.with_hint(::gdnative::export::hint::GroupHint::new(#prefix))))
76+
} else {
77+
None
78+
}
79+
});
6980

7081
let with_usage = if config.no_editor {
7182
Some(quote!(.with_usage(::gdnative::export::PropertyUsage::NOEDITOR)))
83+
} else if config.group.is_some() {
84+
Some(quote!(.with_usage({
85+
::gdnative::export::PropertyUsage::DEFAULT
86+
| ::gdnative::export::PropertyUsage::GROUP
87+
})))
88+
} else if config.category {
89+
Some(quote!(.with_usage({
90+
::gdnative::export::PropertyUsage::DEFAULT
91+
| ::gdnative::export::PropertyUsage::CATEGORY
92+
})))
7293
} else {
7394
None
7495
};

gdnative-derive/src/native_script/property_args.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub struct PropertyAttrArgs {
99
pub before_set: Option<syn::Path>,
1010
pub after_set: Option<syn::Path>,
1111
pub no_editor: bool,
12+
pub group: Option<Option<String>>,
13+
pub category: bool,
1214
}
1315

1416
#[derive(Default)]
@@ -21,6 +23,8 @@ pub struct PropertyAttrArgsBuilder {
2123
before_set: Option<syn::Path>,
2224
after_set: Option<syn::Path>,
2325
no_editor: bool,
26+
group: Option<Option<String>>,
27+
category: bool,
2428
}
2529

2630
impl PropertyAttrArgsBuilder {
@@ -83,6 +87,23 @@ impl PropertyAttrArgsBuilder {
8387
));
8488
}
8589
}
90+
"group" => {
91+
let string = if let syn::Lit::Str(lit_str) = &pair.lit {
92+
lit_str.value()
93+
} else {
94+
return Err(syn::Error::new(
95+
pair.span(),
96+
"group hint is not a string literal".to_string(),
97+
));
98+
};
99+
100+
if let Some(old) = self.group.replace(Some(string)) {
101+
return Err(syn::Error::new(
102+
pair.span(),
103+
format!("there is already a group set: {:?}", old),
104+
));
105+
}
106+
}
86107
"before_get" => {
87108
let string = if let syn::Lit::Str(lit_str) = &pair.lit {
88109
lit_str.value()
@@ -173,6 +194,10 @@ impl PropertyAttrArgsBuilder {
173194
pub fn add_path(&mut self, path: &syn::Path) -> Result<(), syn::Error> {
174195
if path.is_ident("no_editor") {
175196
self.no_editor = true;
197+
} else if path.is_ident("group") {
198+
self.group = Some(None);
199+
} else if path.is_ident("category") {
200+
self.category = true;
176201
} else {
177202
return Err(syn::Error::new(
178203
path.span(),
@@ -195,6 +220,8 @@ impl PropertyAttrArgsBuilder {
195220
before_set: self.before_set,
196221
after_set: self.after_set,
197222
no_editor: self.no_editor,
223+
group: self.group,
224+
category: self.category,
198225
}
199226
}
200227
}

0 commit comments

Comments
 (0)