Game stats that reset every frame, inspired by immediate mode GUI.
gamedev bevy stats
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #6 from AlephCubed/dev

Added system sets and helper plugins.

authored by

AlephCubed and committed by
GitHub
ec4ddfdd 80accda6

+280 -144
+137 -45
Cargo.lock
··· 31 31 dependencies = [ 32 32 "proc-macro2", 33 33 "quote", 34 - "syn 2.0.100", 34 + "syn 2.0.101", 35 35 ] 36 36 37 37 [[package]] 38 38 name = "async-executor" 39 - version = "1.13.1" 39 + version = "1.13.2" 40 40 source = "registry+https://github.com/rust-lang/crates.io-index" 41 - checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" 41 + checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" 42 42 dependencies = [ 43 43 "async-task", 44 44 "concurrent-queue", 45 45 "fastrand", 46 46 "futures-lite", 47 + "pin-project-lite", 47 48 "slab", 48 49 ] 49 50 ··· 64 65 dependencies = [ 65 66 "proc-macro2", 66 67 "quote", 67 - "syn 2.0.100", 68 + "syn 2.0.101", 68 69 ] 69 70 70 71 [[package]] ··· 93 94 94 95 [[package]] 95 96 name = "bevy-butler" 96 - version = "0.6.1-alpha.1" 97 + version = "0.6.1" 97 98 source = "registry+https://github.com/rust-lang/crates.io-index" 98 - checksum = "2b7d51c4ffc073548872bdcd60b16ea752cc56a21ad1d1697ac8994869906204" 99 + checksum = "3110fa6c59f9c5cbb3719b120f736f95fdf440d8034911a147f72efec691a85a" 99 100 dependencies = [ 100 101 "bevy-butler-proc-macro", 101 102 "bevy_app", ··· 107 108 108 109 [[package]] 109 110 name = "bevy-butler-proc-macro" 110 - version = "0.6.1-alpha.1" 111 + version = "0.6.1" 111 112 source = "registry+https://github.com/rust-lang/crates.io-index" 112 - checksum = "24b4cccdb3580d40b1c2fd4d32298478d995901d8ffb347f73e877c970737a3c" 113 + checksum = "8b9ee12e4ffa2725714bc68e942229724df006607e68b5fc244a9916814ff635" 113 114 dependencies = [ 115 + "deluxe", 116 + "deluxe-core", 114 117 "proc-macro2", 115 118 "quote", 116 119 "sha256", 117 - "syn 2.0.100", 120 + "syn 2.0.101", 118 121 ] 119 122 120 123 [[package]] ··· 148 151 dependencies = [ 149 152 "bevy_macro_utils", 150 153 "quote", 151 - "syn 2.0.100", 154 + "syn 2.0.101", 152 155 ] 153 156 154 157 [[package]] ··· 204 207 "bevy_macro_utils", 205 208 "proc-macro2", 206 209 "quote", 207 - "syn 2.0.100", 210 + "syn 2.0.101", 208 211 ] 209 212 210 213 [[package]] ··· 271 274 "parking_lot", 272 275 "proc-macro2", 273 276 "quote", 274 - "syn 2.0.100", 275 - "toml_edit", 277 + "syn 2.0.101", 278 + "toml_edit 0.22.26", 276 279 ] 277 280 278 281 [[package]] ··· 353 356 "bevy_macro_utils", 354 357 "proc-macro2", 355 358 "quote", 356 - "syn 2.0.100", 359 + "syn 2.0.101", 357 360 "uuid", 358 361 ] 359 362 ··· 433 436 "regex", 434 437 "rustc-hash", 435 438 "shlex", 436 - "syn 2.0.100", 439 + "syn 2.0.101", 437 440 ] 438 441 439 442 [[package]] ··· 462 465 463 466 [[package]] 464 467 name = "bytemuck" 465 - version = "1.22.0" 468 + version = "1.23.0" 466 469 source = "registry+https://github.com/rust-lang/crates.io-index" 467 - checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" 470 + checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c" 468 471 469 472 [[package]] 470 473 name = "byteorder" ··· 615 618 "ident_case", 616 619 "proc-macro2", 617 620 "quote", 618 - "strsim", 619 - "syn 2.0.100", 621 + "strsim 0.11.1", 622 + "syn 2.0.101", 620 623 ] 621 624 622 625 [[package]] ··· 627 630 dependencies = [ 628 631 "darling_core", 629 632 "quote", 630 - "syn 2.0.100", 633 + "syn 2.0.101", 634 + ] 635 + 636 + [[package]] 637 + name = "deluxe" 638 + version = "0.5.0" 639 + source = "registry+https://github.com/rust-lang/crates.io-index" 640 + checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" 641 + dependencies = [ 642 + "deluxe-core", 643 + "deluxe-macros", 644 + "once_cell", 645 + "proc-macro2", 646 + "syn 2.0.101", 647 + ] 648 + 649 + [[package]] 650 + name = "deluxe-core" 651 + version = "0.5.0" 652 + source = "registry+https://github.com/rust-lang/crates.io-index" 653 + checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" 654 + dependencies = [ 655 + "arrayvec", 656 + "proc-macro2", 657 + "quote", 658 + "strsim 0.10.0", 659 + "syn 2.0.101", 660 + ] 661 + 662 + [[package]] 663 + name = "deluxe-macros" 664 + version = "0.5.0" 665 + source = "registry+https://github.com/rust-lang/crates.io-index" 666 + checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" 667 + dependencies = [ 668 + "deluxe-core", 669 + "heck", 670 + "if_chain", 671 + "proc-macro-crate", 672 + "proc-macro2", 673 + "quote", 674 + "syn 2.0.101", 631 675 ] 632 676 633 677 [[package]] ··· 647 691 dependencies = [ 648 692 "proc-macro2", 649 693 "quote", 650 - "syn 2.0.100", 694 + "syn 2.0.101", 651 695 "unicode-xid", 652 696 ] 653 697 ··· 816 860 817 861 [[package]] 818 862 name = "hashbrown" 819 - version = "0.15.2" 863 + version = "0.15.3" 820 864 source = "registry+https://github.com/rust-lang/crates.io-index" 821 - checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 865 + checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" 822 866 dependencies = [ 823 867 "equivalent", 824 868 "serde", ··· 836 880 ] 837 881 838 882 [[package]] 883 + name = "heck" 884 + version = "0.4.1" 885 + source = "registry+https://github.com/rust-lang/crates.io-index" 886 + checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 887 + 888 + [[package]] 839 889 name = "hex" 840 890 version = "0.4.3" 841 891 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 848 898 checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 849 899 850 900 [[package]] 901 + name = "if_chain" 902 + version = "1.0.2" 903 + source = "registry+https://github.com/rust-lang/crates.io-index" 904 + checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" 905 + 906 + [[package]] 851 907 name = "immediate_stats" 852 908 version = "0.1.0" 853 909 dependencies = [ ··· 867 923 "proc-macro-error", 868 924 "proc-macro2", 869 925 "quote", 870 - "syn 2.0.100", 926 + "syn 2.0.101", 871 927 ] 872 928 873 929 [[package]] ··· 962 1018 dependencies = [ 963 1019 "proc-macro2", 964 1020 "quote", 965 - "syn 2.0.100", 1021 + "syn 2.0.101", 966 1022 ] 967 1023 968 1024 [[package]] ··· 1108 1164 dependencies = [ 1109 1165 "proc-macro2", 1110 1166 "quote", 1111 - "syn 2.0.100", 1167 + "syn 2.0.101", 1112 1168 ] 1113 1169 1114 1170 [[package]] ··· 1148 1204 checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" 1149 1205 dependencies = [ 1150 1206 "proc-macro2", 1151 - "syn 2.0.100", 1207 + "syn 2.0.101", 1208 + ] 1209 + 1210 + [[package]] 1211 + name = "proc-macro-crate" 1212 + version = "1.3.1" 1213 + source = "registry+https://github.com/rust-lang/crates.io-index" 1214 + checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 1215 + dependencies = [ 1216 + "once_cell", 1217 + "toml_edit 0.19.15", 1152 1218 ] 1153 1219 1154 1220 [[package]] ··· 1327 1393 dependencies = [ 1328 1394 "proc-macro2", 1329 1395 "quote", 1330 - "syn 2.0.100", 1396 + "syn 2.0.101", 1331 1397 ] 1332 1398 1333 1399 [[package]] 1334 1400 name = "sha2" 1335 - version = "0.10.8" 1401 + version = "0.10.9" 1336 1402 source = "registry+https://github.com/rust-lang/crates.io-index" 1337 - checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 1403 + checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" 1338 1404 dependencies = [ 1339 1405 "cfg-if", 1340 1406 "cpufeatures", ··· 1409 1475 1410 1476 [[package]] 1411 1477 name = "strsim" 1478 + version = "0.10.0" 1479 + source = "registry+https://github.com/rust-lang/crates.io-index" 1480 + checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1481 + 1482 + [[package]] 1483 + name = "strsim" 1412 1484 version = "0.11.1" 1413 1485 source = "registry+https://github.com/rust-lang/crates.io-index" 1414 1486 checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" ··· 1425 1497 1426 1498 [[package]] 1427 1499 name = "syn" 1428 - version = "2.0.100" 1500 + version = "2.0.101" 1429 1501 source = "registry+https://github.com/rust-lang/crates.io-index" 1430 - checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 1502 + checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 1431 1503 dependencies = [ 1432 1504 "proc-macro2", 1433 1505 "quote", ··· 1451 1523 dependencies = [ 1452 1524 "proc-macro2", 1453 1525 "quote", 1454 - "syn 2.0.100", 1526 + "syn 2.0.101", 1455 1527 ] 1456 1528 1457 1529 [[package]] ··· 1466 1538 1467 1539 [[package]] 1468 1540 name = "toml_datetime" 1469 - version = "0.6.8" 1541 + version = "0.6.9" 1542 + source = "registry+https://github.com/rust-lang/crates.io-index" 1543 + checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" 1544 + 1545 + [[package]] 1546 + name = "toml_edit" 1547 + version = "0.19.15" 1470 1548 source = "registry+https://github.com/rust-lang/crates.io-index" 1471 - checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 1549 + checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" 1550 + dependencies = [ 1551 + "indexmap", 1552 + "toml_datetime", 1553 + "winnow 0.5.40", 1554 + ] 1472 1555 1473 1556 [[package]] 1474 1557 name = "toml_edit" 1475 - version = "0.22.24" 1558 + version = "0.22.26" 1476 1559 source = "registry+https://github.com/rust-lang/crates.io-index" 1477 - checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" 1560 + checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" 1478 1561 dependencies = [ 1479 1562 "indexmap", 1480 1563 "toml_datetime", 1481 - "winnow", 1564 + "winnow 0.7.8", 1482 1565 ] 1483 1566 1484 1567 [[package]] ··· 1500 1583 dependencies = [ 1501 1584 "proc-macro2", 1502 1585 "quote", 1503 - "syn 2.0.100", 1586 + "syn 2.0.101", 1504 1587 ] 1505 1588 1506 1589 [[package]] ··· 1618 1701 dependencies = [ 1619 1702 "proc-macro2", 1620 1703 "quote", 1621 - "syn 2.0.100", 1704 + "syn 2.0.101", 1622 1705 ] 1623 1706 1624 1707 [[package]] ··· 1664 1747 "log", 1665 1748 "proc-macro2", 1666 1749 "quote", 1667 - "syn 2.0.100", 1750 + "syn 2.0.101", 1668 1751 "wasm-bindgen-shared", 1669 1752 ] 1670 1753 ··· 1699 1782 dependencies = [ 1700 1783 "proc-macro2", 1701 1784 "quote", 1702 - "syn 2.0.100", 1785 + "syn 2.0.101", 1703 1786 "wasm-bindgen-backend", 1704 1787 "wasm-bindgen-shared", 1705 1788 ] ··· 1843 1926 1844 1927 [[package]] 1845 1928 name = "winnow" 1846 - version = "0.7.7" 1929 + version = "0.5.40" 1847 1930 source = "registry+https://github.com/rust-lang/crates.io-index" 1848 - checksum = "6cb8234a863ea0e8cd7284fcdd4f145233eb00fee02bbdd9861aec44e6477bc5" 1931 + checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" 1932 + dependencies = [ 1933 + "memchr", 1934 + ] 1935 + 1936 + [[package]] 1937 + name = "winnow" 1938 + version = "0.7.8" 1939 + source = "registry+https://github.com/rust-lang/crates.io-index" 1940 + checksum = "9e27d6ad3dac991091e4d35de9ba2d2d00647c5d0fc26c5496dee55984ae111b" 1849 1941 dependencies = [ 1850 1942 "memchr", 1851 1943 ] ··· 1876 1968 dependencies = [ 1877 1969 "proc-macro2", 1878 1970 "quote", 1879 - "syn 2.0.100", 1971 + "syn 2.0.101", 1880 1972 ]
+7 -6
README.md
··· 35 35 36 36 fn main() { 37 37 App::new() 38 - .add_systems(PreUpdate, ( 39 - reset_component_modifiers::<Speed>, 40 - reset_resource_modifiers::<Speed>, 38 + .add_plugins(( 39 + ResetComponentPlugin::<Speed>::new(), 40 + ResetResourcePlugin::<Speed>::new(), 41 41 )) 42 42 .run(); 43 43 } ··· 46 46 ### Bevy Butler 47 47 48 48 If you use [Bevy Butler](https://github.com/TGRCdev/bevy-butler/), you can also use the `bevy_butler` feature flag. 49 - This automatically registers the required system(s) using the `add_component` attribute. 49 + This automatically registers the required system(s) using the `add_component` attribute 50 + or the existing `insert_resource` macro. 50 51 51 52 ```rust 52 53 #[butler_plugin] 53 54 struct MyPlugin; 54 55 55 56 // `StatContainer` derive adds the `add_component` attribute 56 - // and hooks into the existing `add_resource` macro. 57 + // and hooks into the existing `insert_resource` macro. 57 58 #[derive(StatContainer, Component, Resource)] 58 59 #[add_component(plugin = MyPlugin)] // Adds `reset_component_modifiers` system. 59 - #[add_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 60 + #[insert_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 60 61 struct Speed(Stat); 61 62 ``` 62 63
+1 -1
immediate_stats/Cargo.toml
··· 17 17 bevy_app = { version = "0.16.0", default-features = false, optional = true, features = [ 18 18 "bevy_reflect", 19 19 ] } 20 - bevy-butler = { version = "0.6.1-alpha", optional = true } 20 + bevy-butler = { version = "0.6.1", optional = true } 21 21 bevy_ecs = { version = "0.16.0", default-features = false, optional = true, features = [ 22 22 "bevy_reflect", 23 23 ] }
-63
immediate_stats/README.md
··· 1 - # Immediate Stats 2 - 3 - Game stats that reset every frame. Inspired by immediate mode rendering. 4 - Includes a derive macro which propagates stat resets to any stat fields. 5 - 6 - ```rust 7 - #[derive(StatContainer)] 8 - struct Speed(Stat); 9 - 10 - fn main() { 11 - loop { 12 - let mut speed = Speed(Stat::new(10)); // Set base speed to 10. 13 - 14 - speed.0 *= 2.0; // Applies a multiplier to the final result. 15 - speed.0 += 5; // Adds a bonus to the final result. 16 - // The order does not matter. Bonuses are always applied before multipliers. 17 - assert_eq!(speed.0.total(), 30); // (10 + 5) * 2 = 30 18 - 19 - speed.reset_modifiers(); // Reset bonus and multiplier, so speed is back to 10. 20 - } 21 - } 22 - ``` 23 - 24 - ## Bevy 25 - 26 - There is build-in integration with the [Bevy Engine](https://bevyengine.org) via the `bevy` feature flag. 27 - This adds systems for resetting `StatContainer` components and resources. 28 - 29 - ```rust 30 - #[derive(StatContainer, Component, Resource)] 31 - struct Speed(Stat); 32 - 33 - fn main() { 34 - App::new() 35 - .add_systems(PreUpdate, ( 36 - reset_component_modifiers::<Speed>, 37 - reset_resource_modifiers::<Speed>, 38 - )) 39 - .run(); 40 - } 41 - ``` 42 - 43 - ### Bevy Butler 44 - 45 - If you use [Bevy Butler](https://github.com/TGRCdev/bevy-butler/), you can also use the `bevy_butler` feature flag. 46 - This automatically registers the required system(s) using the `add_component` attribute 47 - or the existing `add_resource` macro. 48 - 49 - ```rust 50 - #[butler_plugin] 51 - struct MyPlugin; 52 - 53 - // `StatContainer` derive adds the `add_component` attribute and hooks into the existing `add_resource` macro. 54 - #[derive(StatContainer, Component, Resource, Default)] 55 - #[add_component(plugin = MyPlugin)] // Adds `reset_component_modifiers` system. 56 - #[add_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 57 - struct Speed(Stat); 58 - ``` 59 - 60 - ### Version Compatibility 61 - | bevy | immediate_stats | 62 - |--------|-----------------| 63 - | `0.16` | `0.1` |
+10 -4
immediate_stats/examples/simple_bevy.rs
··· 12 12 13 13 impl Plugin for SpeedPlugin { 14 14 fn build(&self, app: &mut App) { 15 - app.add_systems(Startup, init_speed) 16 - .add_systems(PreUpdate, reset_component_modifiers::<Speed>) 17 - // Modifiers must be applied before the speed can be read. 18 - .add_systems(Update, (apply_modifiers, read_speed).chain()); 15 + app.add_plugins((ImmediateStatsPlugin, ResetComponentPlugin::<Speed>::new())) 16 + .add_systems(Startup, init_speed) 17 + .add_systems( 18 + Update, 19 + ( 20 + // Modifiers must be applied before the speed can be read. 21 + apply_modifiers.in_set(StatSystems::Modify), 22 + read_speed.in_set(StatSystems::Read), 23 + ), 24 + ); 19 25 } 20 26 } 21 27
+5 -4
immediate_stats/examples/simple_bevy_butler.rs
··· 6 6 use immediate_stats::*; 7 7 8 8 fn main() { 9 - App::new().add_plugins((MinimalPlugins, SpeedPlugin)).run(); 9 + App::new() 10 + .add_plugins((MinimalPlugins, ImmediateStatsPlugin, SpeedPlugin)) 11 + .run(); 10 12 } 11 13 12 14 #[butler_plugin] ··· 21 23 commands.spawn(Speed(Stat::new(10))); // Set base speed to 10. 22 24 } 23 25 24 - #[add_system(plugin = SpeedPlugin, schedule = Update)] 26 + #[add_system(plugin = SpeedPlugin, schedule = Update, in_set = StatSystems::Modify)] 25 27 fn apply_modifiers(mut speeds: Query<&mut Speed>) { 26 28 for mut speed in &mut speeds { 27 29 speed.0 *= 2.0; // Applies a multiplier to the final result. ··· 30 32 } 31 33 } 32 34 33 - // Modifiers must be applied before the speed can be read. 34 - #[add_system(plugin = SpeedPlugin, schedule = Update, after = apply_modifiers)] 35 + #[add_system(plugin = SpeedPlugin, schedule = Update, in_set = StatSystems::Read)] 35 36 fn read_speed(speeds: Query<&Speed>) { 36 37 for speed in &speeds { 37 38 println!("The current speed is {}.", speed.0.total());
+90 -6
immediate_stats/src/bevy.rs
··· 4 4 use crate::StatContainer; 5 5 use crate::modifier::Modifier; 6 6 use crate::stat::Stat; 7 - use bevy_app::{App, Plugin}; 7 + use bevy_app::{App, Plugin, PreUpdate, Update}; 8 8 use bevy_ecs::component::Mutable; 9 - use bevy_ecs::prelude::ReflectComponent; 10 9 use bevy_ecs::prelude::{Component, Query, ResMut, Resource, Without}; 10 + use bevy_ecs::prelude::{IntoScheduleConfigs, ReflectComponent, SystemSet}; 11 11 use bevy_reflect::Reflect; 12 12 use bevy_reflect::prelude::ReflectDefault; 13 + use std::marker::PhantomData; 13 14 14 - /// Registers all types used by Immediate Stats with the Bevy type registry. 15 + /// Configures [system ordering](StatSystems) and registers types with the Bevy type registry. 16 + /// 17 + /// - [`StatSystems::Reset`] runs in `PreUpdate`. 18 + /// - [`StatSystems::Modify`] runs before [`StatSystems::Read`] in `Update`. 15 19 pub struct ImmediateStatsPlugin; 16 20 17 21 impl Plugin for ImmediateStatsPlugin { 18 22 fn build(&self, app: &mut App) { 19 23 app.register_type::<PauseStatReset>() 20 24 .register_type::<Stat>() 21 - .register_type::<Modifier>(); 25 + .register_type::<Modifier>() 26 + .configure_sets(Update, StatSystems::Modify.before(StatSystems::Read)) 27 + .configure_sets(PreUpdate, StatSystems::Reset); 22 28 } 23 29 } 24 30 31 + /// A [`SystemSet`] for ordering Immediate Stats operations. 32 + /// Recommend configuration can be added via the [`ImmediateStatsPlugin`]. 33 + #[derive(SystemSet, Debug, Clone, Eq, PartialEq, Hash)] 34 + pub enum StatSystems { 35 + /// Systems that reset [`StatContainers`](StatContainer). 36 + Reset, 37 + /// Systems that apply modifiers to stats. 38 + Modify, 39 + /// Systems that read the final value of stats. 40 + Read, 41 + } 42 + 25 43 /// Prevents any [`StatContainers`](StatContainer) on an entity from resetting. 26 44 #[derive(Component, Reflect, Eq, PartialEq, Debug, Default, Clone)] 27 45 #[component(storage = "SparseSet")] 28 46 #[reflect(Component, PartialEq, Debug, Default, Clone)] 29 47 pub struct PauseStatReset; 30 48 31 - /// Calls [`StatContainer::reset_modifiers`] on all `T` components. 49 + /// Calls [`reset_modifiers`](StatContainer::reset_modifiers) on all `T` components. 50 + /// 51 + /// Reset occurs in the [`Reset`](StatSystems::Reset) system set during [`PreUpdate`]. 52 + pub struct ResetComponentPlugin<T: Component<Mutability = Mutable> + StatContainer> { 53 + _phantom: PhantomData<T>, 54 + } 55 + 56 + impl<T: Component<Mutability = Mutable> + StatContainer> Plugin for ResetComponentPlugin<T> { 57 + fn build(&self, app: &mut App) { 58 + app.add_systems( 59 + PreUpdate, 60 + reset_component_modifiers::<T>.in_set(StatSystems::Reset), 61 + ); 62 + } 63 + } 64 + 65 + /// Calls [`reset_modifiers`](StatContainer::reset_modifiers) on all `T` components. 66 + /// 67 + /// Use the [`ResetResourcePlugin`] for recommended configuration. 32 68 pub fn reset_component_modifiers<T: Component<Mutability = Mutable> + StatContainer>( 33 69 mut query: Query<&mut T, Without<PauseStatReset>>, 34 70 ) { ··· 37 73 } 38 74 } 39 75 40 - /// Calls [`StatContainer::reset_modifiers`] on all the `T` resource, if it exists. 76 + impl<T: Component<Mutability = Mutable> + StatContainer> ResetComponentPlugin<T> { 77 + #[allow(missing_docs)] 78 + pub fn new() -> Self { 79 + Self::default() 80 + } 81 + } 82 + 83 + impl<T: Component<Mutability = Mutable> + StatContainer> Default for ResetComponentPlugin<T> { 84 + fn default() -> Self { 85 + Self { 86 + _phantom: PhantomData::default(), 87 + } 88 + } 89 + } 90 + 91 + /// Calls [`reset_modifiers`](StatContainer::reset_modifiers) on the `T` resource, if it exists. 92 + /// 93 + /// Reset occurs in the [`Reset`](StatSystems::Reset) system set during [`PreUpdate`]. 94 + pub struct ResetResourcePlugin<T: Resource + StatContainer> { 95 + _phantom: PhantomData<T>, 96 + } 97 + 98 + impl<T: Resource + StatContainer> Plugin for ResetResourcePlugin<T> { 99 + fn build(&self, app: &mut App) { 100 + app.add_systems( 101 + PreUpdate, 102 + reset_resource_modifiers::<T>.in_set(StatSystems::Reset), 103 + ); 104 + } 105 + } 106 + 107 + /// Calls [`reset_modifiers`](StatContainer::reset_modifiers) on the `T` resource, if it exists. 108 + /// 109 + /// Use the [`ResetResourcePlugin`] for recommended configuration. 41 110 pub fn reset_resource_modifiers<T: Resource + StatContainer>(res: Option<ResMut<T>>) { 42 111 if let Some(mut res) = res { 43 112 res.reset_modifiers(); 44 113 } 45 114 } 115 + 116 + impl<T: Resource + StatContainer> ResetResourcePlugin<T> { 117 + #[allow(missing_docs)] 118 + pub fn new() -> Self { 119 + Self::default() 120 + } 121 + } 122 + 123 + impl<T: Resource + StatContainer> Default for ResetResourcePlugin<T> { 124 + fn default() -> Self { 125 + Self { 126 + _phantom: PhantomData::default(), 127 + } 128 + } 129 + }
+10 -10
immediate_stats/src/lib.rs
··· 39 39 //! 40 40 //! fn main() { 41 41 //! App::new() 42 - //! .add_systems(PreUpdate, ( 43 - //! reset_component_modifiers::<Speed>, 44 - //! reset_resource_modifiers::<Speed>, 42 + //! .add_plugins(( 43 + //! ResetComponentPlugin::<Speed>::new(), 44 + //! ResetResourcePlugin::<Speed>::new(), 45 45 //! )) 46 46 //! .run(); 47 47 //! } ··· 52 52 //! If you use [Bevy Butler](https://github.com/TGRCdev/bevy-butler/), 53 53 //! you can also use the `bevy_butler` feature flag. 54 54 //! This automatically registers the required system(s) using the `add_component` attribute 55 - //! or the existing `add_resource` macro. 55 + //! or the existing `insert_resource` macro. 56 56 //! 57 57 #![cfg_attr(not(feature = "bevy_butler"), doc = "```rust ignore")] 58 58 #![cfg_attr(feature = "bevy_butler", doc = "```rust")] ··· 64 64 //! struct MyPlugin; 65 65 //! 66 66 //! // `StatContainer` derive adds the `add_component` attribute 67 - //! // and hooks into the existing `add_resource` macro. 67 + //! // and hooks into the existing `insert_resource` macro. 68 68 //! #[derive(StatContainer, Component, Resource, Default)] 69 69 //! #[add_component(plugin = MyPlugin)] // Adds `reset_component_modifiers` system. 70 - //! #[add_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 70 + //! #[insert_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 71 71 //! struct Speed(Stat); 72 72 //! ``` 73 73 //! ··· 138 138 /// ``` 139 139 /// # Bevy Butler 140 140 /// If the `bevy_butler` feature flag is enabled, you may also use the `add_component` attribute 141 - /// or the existing `add_resource` macro to register [`reset_component_modifiers`] 141 + /// or the existing `insert_resource` macro to register [`reset_component_modifiers`] 142 142 /// and/or [`reset_resource_modifiers`] automatically. 143 143 #[cfg_attr(not(feature = "bevy_butler"), doc = "```rust ignore")] 144 144 #[cfg_attr(feature = "bevy_butler", doc = "```rust")] ··· 149 149 /// struct MyPlugin; 150 150 /// 151 151 /// // `StatContainer` derive adds the `add_component` attribute 152 - /// // and hooks into the existing `add_resource` macro. 152 + /// // and hooks into the existing `insert_resource` macro. 153 153 /// #[derive(StatContainer, Component, Resource, Default)] 154 154 /// #[add_component(plugin = MyPlugin)] // Adds `reset_component_modifiers` system. 155 - /// #[add_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 155 + /// #[insert_resource(plugin = MyPlugin)] // Adds `reset_resource_modifiers` system. 156 156 /// struct Speed(Stat); 157 157 /// ``` 158 158 pub use immediate_stats_macros::StatContainer; ··· 165 165 // Used by derive macro. 166 166 #[cfg(feature = "bevy")] 167 167 #[doc(hidden)] 168 - pub use bevy_app::prelude::PreUpdate; 168 + pub use bevy_app::prelude::PreUpdate as __PreUpdate; 169 169 170 170 /// Types that contain stats that need to be reset. 171 171 ///
+3 -2
immediate_stats/tests/bevy_butler.rs
··· 1 1 //! Tests the `add_component` attribute for automatic system registration. 2 2 #![cfg(feature = "bevy_butler")] 3 3 4 + extern crate immediate_stats; 4 5 use crate::{Stat, StatContainer}; 5 6 use bevy_app::App; 6 7 use bevy_butler::*; ··· 12 13 13 14 #[derive(Resource, Component, StatContainer, Default, PartialEq, Debug)] 14 15 #[add_component(plugin = MyPlugin)] 15 - #[add_resource(plugin = MyPlugin)] 16 + #[insert_resource(plugin = MyPlugin)] 16 17 struct Health(Stat); 17 18 18 19 #[test] ··· 60 61 61 62 #[derive(Resource, Component, StatContainer, Default, PartialEq, Debug)] 62 63 #[add_component(plugin(MyPlugin))] 63 - #[add_resource(plugin(MyPlugin))] 64 + #[insert_resource(plugin(MyPlugin))] 64 65 struct AlternateSyntax(Stat); 65 66 66 67 #[test]
+17 -3
immediate_stats_macros/src/bevy_butler.rs
··· 14 14 if attr.path().is_ident("add_component") { 15 15 let plugin = PluginPath::from_meta(&attr.meta)?; 16 16 butler_attributes.component_plugin = Some(plugin); 17 - } else if attr.path().is_ident("add_resource") { 17 + } else if attr.path().is_ident("insert_resource") { 18 18 let plugin = PluginPath::from_meta(&attr.meta)?; 19 19 butler_attributes.resource_plugin = Some(plugin); 20 20 } ··· 46 46 let plugin = &plugin_path.0; 47 47 let use_as = format_ident!("__{ident}_component"); 48 48 49 + // Due to some strange import scoping issues, we cannot use the plugins. 50 + // Instead, we can just recreate the plugin's functionality. 49 51 tokens.extend(quote! { 50 - #[bevy_butler::add_system(generics = <#ident>, plugin = #plugin, schedule = immediate_stats::PreUpdate)] 52 + #[bevy_butler::add_system( 53 + generics = <#ident>, 54 + plugin = #plugin, 55 + schedule = immediate_stats::__PreUpdate, 56 + in_set = immediate_stats::StatSystems::Reset, 57 + )] 51 58 use immediate_stats::reset_component_modifiers as #use_as; 52 59 }); 53 60 } ··· 57 64 let plugin = &plugin_path.0; 58 65 let use_as = format_ident!("__{ident}_resource"); 59 66 67 + // Due to some strange import scoping issues, we cannot use the plugins. 68 + // Instead, we can just recreate the plugin's functionality. 60 69 tokens.extend(quote! { 61 - #[bevy_butler::add_system(generics = <#ident>, plugin = #plugin, schedule = immediate_stats::PreUpdate)] 70 + #[bevy_butler::add_system( 71 + generics = <#ident>, 72 + plugin = #plugin, 73 + schedule = immediate_stats::__PreUpdate, 74 + in_set = immediate_stats::StatSystems::Reset, 75 + )] 62 76 use immediate_stats::reset_resource_modifiers as #use_as; 63 77 }); 64 78 }