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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
//! <div align="center">
//! <h1>Cvars</h1>
//! <i>Configuration variables .rs</i>
//! <br />
//! A simple and ergonomic way to store and edit runtime configuration in your program
//! </div>
//! <br />
//!
//! **TL;DR:** Cvars allow you to access struct fields based on their name as a string.
//!
//! This is useful for app configuration, especially in games - gamedevs, modders and players access cvars dynamically using a TUI
//! while your gamecode accesses them statically as struct fields.
//!
//! The `cvars` crate contains proc macros to generate:
//! - setter and getter methods directly on your config struct
//! - an impl of `SetGet` for your config struct so it can use dynamic dispatch
//!
//! In-game consoles are in separate crates - pick one based on your game engine:
//! - [cvars-console-fyrox](https://crates.io/crates/cvars-console-fyrox) - [Fyrox](https://crates.io/crates/fyrox) console
//! - [cvars-console-macroquad](https://crates.io/crates/cvars-console-macroquad) - [Macroquad](https://crates.io/crates/macroquad) console
//!
//! # Example
//!
//! ```rust
//! use cvars::cvars;
//!
//! // This generates a Cvars struct containing all your config options
//! // and a corresponding Default impl.
//! cvars! {
//! g_rocket_launcher_ammo_max: i32 = 20,
//! g_rocket_launcher_damage: f32 = 100.0,
//! }
//!
//! // Store this in your game state.
//! let mut cvars = Cvars::default();
//!
//! // These normally come from the user
//! // (from stdin / your game's console / etc.)
//! let cvar_name = "g_rocket_launcher_damage";
//! let new_value = "150";
//!
//! // This looks up the right field and sets it to the new value.
//! cvars.set_str(cvar_name, new_value).unwrap();
//! ```
//!
//! A player/modder/gamedev wants rockets to do more damage.
//! He types `g_rocket_launcher_damage 150` into the game's console or stdin.
//! The code gets both the cvar name and new value as strings
//! so you can't write `cvars.g_rocket_launcher_damage = 150`.
//! You need to look up the correct field based on the string - this is what `cvars` does - it generates `set_str`
//! (and some other useful methods). You call `cvars.set_str("g_rocket_launcher_damage", "150");`
//! which looks up the right field, parses the value into its type and updates the field with it.
//! From then on, rockets do 150 damage.
//!
//! The important thing is that in the rest of your application,
//! you can still access your cvars as regular struct fields - e.g. `player.health -= cvars.g_rocket_launcher_damage;`.
//! This means you only need to use strings when the user
//! (player or developer when debugging or testing a different balance) is changing the values.
//! The rest of your **gamelogic is still statically typed** and using a cvar in gamecode
//! is just a field access without any overhead.
//!
//! A typical game will have hundreds or thousands of tunable parameters.
//! With cvars and a console you can keep them all configurable for advanced players,
//! modders and your-gamedev-self without having a build an elaborate settings menu.
//! You can keep everything configurable using a TUI
//! while also exposing common settings to normal players in your game's GUI.
//!
//! See [cvars/examples/stdin.rs](https://github.com/martin-t/cvars/blob/master/cvars/examples/stdin.rs)
//! for a small runnable example.
//!
//! For real-world examples, look at games using cvars:
//!
//! - [RecWars](https://github.com/martin-t/rec-wars/blob/master/src/cvars.rs) - uses the Macroquad console,
//! every aspect of the gameplay is configurable,
//! you can test it [in your browsser](https://martin-t.gitlab.io/gitlab-pages/rec-wars/macroquad.html)
//! - [RustCycles](https://github.com/rustcycles/rustcycles/blob/master/src/cvars.rs) - uses the Fyrox console
//!
//! # What it generates
//!
//! - A struct containing all your cvars
//! - A Default impl with the specified default values
//! - Methods to set and get cvars by name
//! - Some utility methods
//!
//! The most important methods have these signatures (same as on the `SetGet` trait):
//!
//! ```rust
//! # struct Cvars {}
//! impl Cvars {
//! /// Finds the cvar whose name matches `cvar_name` and returns its value as a `String`.
//! ///
//! /// Returns `Err` if the cvar doesn't exist.
//! pub fn get_string(&self, cvar_name: &str) -> Result<String, String>
//! # { unimplemented!() }
//!
//! /// Finds the cvar whose name matches `cvar_name`, tries to parse `str_value` to its type and sets it to the parsed value.
//! ///
//! /// Returns `Err` if the cvar doesn't exist or if `str_value` fails to parse to its type.
//! pub fn set_str(&mut self, cvar_name: &str, str_value: &str) -> Result<(), String>
//! # { unimplemented!() }
//! }
//! ```
//!
//! # Enums
//!
//! Cvar values can have any type which implements the `FromStr` and `Display` traits.
//! If you want to use enums, it's best to derive these traits automatically
//! via [strum](https://crates.io/crates/strum).
//!
//! ```rust
//! use strum_macros::{Display, EnumString};
//!
//! use cvars::cvars;
//!
//! cvars! {
//! cl_splitscreen: Splitscreen = Splitscreen::Vertical,
//! }
//!
//! #[derive(Debug, Clone, Copy, PartialEq, Eq, Display, EnumString)]
//! #[strum(ascii_case_insensitive)]
//! pub enum Splitscreen {
//! Vertical,
//! Horizontal,
//! }
//! ```
//!
//! Tip: use `#[strum(ascii_case_insensitive)]` so players don't need to pay attention to capilatization
//! when changing cvars - both `"Vertical"` and `"vertical"` will parse into `Splitscreen::Vertical`.
//!
//! # Attributes
//!
//! - **Skipping fields** - If a field is not meant to be configurable, mark it with `#[cvars(skip)]`.
//!
//! - **Checking cvars are sorted** - To make the macro panic if it detects that the cvars are not sorted,
//! use the `#[cvars(sorted)]` attribute on the struct.
//! Note if you're using the `cvars` macro instead of deriving `SetGet`,
//! you have to use it as an an inner attribute.
//!
//! # Related crates
//!
//! See the [README](https://github.com/martin-t/cvars) for more information about the cvars family of crates
//! and for comparison with alternatives such as [inline_tweak](https://crates.io/crates/inline_tweak).
pub use ;
/// A trait for writing generic code that can access cvars but doesn't know the concrete Cvars struct.
///
/// This is implemented automatically by both `#[derive(SetGet)]` and `cvars! {}`.
///
/// The methods provided here call those implemented directly on the concrete Cvars struct,
/// there is no difference between them.
///
/// Implementation note: This trait can't include the `get` and `set` methods
/// because it would no longer be object-safe.