1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/// Declare a unit struct with [`TagMask`] associated constants for a tag
/// hierarchy, plus a `register(&mut TagResolver)` method that registers every
/// tag name with the resolver.
///
/// # Syntax
///
/// ```ignore
/// define_tags! {
/// DamageTags,
/// damage_type {
/// elemental { fire, cold, lightning },
/// physical,
/// chaos,
/// },
/// weapon_type {
/// melee { sword, axe },
/// ranged { bow, wand },
/// },
/// }
/// ```
///
/// This generates:
///
/// ```ignore
/// pub struct DamageTags;
/// impl DamageTags {
/// pub const FIRE: TagMask = TagMask::bit(0);
/// // ...
/// pub const ELEMENTAL: TagMask = TagMask::new(Self::FIRE.0 | Self::COLD.0 | Self::LIGHTNING.0);
/// // ...
/// pub fn register(resolver: &mut TagResolver) { /* ... */ }
/// }
/// ```
///
/// [`TagMask`]: bevy_gauge::tags::TagMask
/// [`TagResolver`]: bevy_gauge::tags::TagResolver
/// Derive macro that generates [`AttributeDerived`] and/or [`WriteBack`]
/// implementations for a Bevy component, binding its fields to attributes.
///
/// Fields annotated with `#[read]` are read from attributes ([`AttributeDerived`]).
/// Fields annotated with `#[write]` are written back to attributes ([`WriteBack`]).
/// Fields without an annotation are plain struct fields.
///
/// The macro also emits `inventory::submit!` calls so that the component
/// is automatically registered with [`AttributesPlugin`] - no manual
/// `app.register_attribute_derived::<T>()` needed.
///
/// # Syntax
///
/// ```ignore
/// #[derive(Component, Default, AttributeComponent, Debug)]
/// pub struct Life {
/// #[read("Life")]
/// pub max: f32, // read from "Life" attribute
/// #[write]
/// pub current: f32, // write back to "Life.current" (auto-path)
/// pub label: String, // plain field, not attribute-bound
/// }
/// ```
///
/// ## Path resolution
///
/// - `#[read("path")]` / `#[write("path")]` - explicit attribute path string
/// - `#[read]` / `#[write]` (no argument) - auto-path: `"StructName.field_name"`
///
/// [`AttributeDerived`]: bevy_gauge::derived::AttributeDerived
/// [`WriteBack`]: bevy_gauge::derived::WriteBack
/// [`AttributesPlugin`]: bevy_gauge::plugin::AttributesPlugin
/// Derive macro that generates [`AttributeResolvable`] for structs and enums.
///
/// Fields are resolved from attributes using dot-separated paths based on
/// field names. Use `#[skip]` to exclude fields from resolution.
///
/// # Rules
///
/// - **Named struct fields**: each appends `.field_name` to the prefix
/// - **Single resolvable field**: transparent — prefix resolves directly to the value
/// - **Enums**: variant name is transparent, fields within each variant follow struct rules
/// - **Newtypes**: transparent — prefix resolves to the inner value
/// - **Unit variants/structs**: no-op
/// - **Terminal types** (f32, integers, bool): read directly via `attrs.value()`
/// - **Other types**: delegate to their `AttributeResolvable` impl
///
/// # Example
///
/// ```ignore
/// #[derive(AttributeResolvable)]
/// struct DirectionOffset {
/// #[skip]
/// direction: Dir3,
/// magnitude: f32, // single resolvable field → transparent
/// }
///
/// #[derive(AttributeResolvable)]
/// enum Gatherer {
/// Circle { radius: f32, count: u32 },
/// Sphere { radius: f32, count: u32 },
/// }
/// ```
///
/// [`AttributeResolvable`]: bevy_gauge::resolvable::AttributeResolvable