Skip to main content

s3lightfixes/
light_args.rs

1use std::path::PathBuf;
2
3use clap::Parser;
4use clap_complete::Shell;
5
6use crate::default;
7
8#[derive(Parser, Debug)]
9#[command(
10    name = "s3lightfixes",
11    author,
12    version,
13    about = "A tool for modifying light values globally across an OpenMW installation.\nPlease note that arguments provided here, which also exist in lightConfig.toml, will override any values in lightConfig.toml when used.\nAdditionally, if the lightConfig.toml does not exist, the used values will be saved into the new lightConfig.toml."
14)]
15// CLI flags are naturally boolean. Turning these into enums would make the Rust type prettier
16// while making the command-line interface and clap mapping pointlessly dishonest.
17#[allow(clippy::struct_excessive_bools)]
18pub struct LightArgs {
19    /// Path to openmw.cfg
20    /// By default, uses the system paths defined by:
21    /// <https://openmw.readthedocs.io/en/latest/reference/modding/paths.html>
22    /// Can be the literal path to an openmw.cfg file (including not literally being called openmw.cfg)
23    /// Or the directory in which an openmw.cfg file lives.
24    #[arg(short = 'c', long = "openmw-cfg")]
25    pub openmw_cfg: Option<PathBuf>,
26
27    /// Enables classic mode using vtastek shaders.
28    /// ONLY for openmw 0.47. Relevant shaders can be found in the `OpenMW` discord:
29    /// <https://discord.com/channels/260439894298460160/718892786157617163/966468825321177148>
30    #[arg(short = '7', long = "classic")]
31    pub use_classic: bool,
32
33    /// Output directory.
34    /// The plugin may be saved to any location, but its name will always be `S3Lightfixes.omwaddon`.
35    /// Accepts relative and absolute terms.
36    #[arg(short = 'o', long = "output")]
37    pub output: Option<PathBuf>,
38
39    /// Whether to automatically enable the output plugin in openmw.cfg.
40    /// Disabled by default.
41    /// Typically lightfixes is ran under momw-configurator, making this param
42    /// unnecessary for many users.
43    #[arg(short = 'e', long = "auto-enable")]
44    pub auto_enable: bool,
45
46    /// If used, print to stdout instead of using native GUI dialogs.
47    /// Not available on android.
48    #[arg(short = 'n', long = "no-notifications")]
49    pub no_notifications: bool,
50
51    /// Output debugging information during lightfixes generation
52    /// Primarily displays output related to the openmw.cfg being used for generation
53    #[arg(short = 'd', long = "debug")]
54    pub debug: bool,
55
56    /// Validate config and source plugins, print planned changes, but do not write files.
57    #[arg(
58        long = "dry-run",
59        conflicts_with = "validate_config",
60        num_args = 0..=1,
61        default_missing_value = "true",
62        value_name = "BOOL"
63    )]
64    pub dry_run: Option<bool>,
65
66    /// Validate lightconfig.toml, CLI overrides, and regexes without generating a plugin.
67    #[arg(
68        long = "validate-config",
69        conflicts_with = "dry_run",
70        num_args = 0..=1,
71        default_missing_value = "true",
72        value_name = "BOOL"
73    )]
74    pub validate_config: Option<bool>,
75
76    /// Generate shell completion script to stdout
77    #[arg(long, value_name = "SHELL", conflicts_with = "generate_manpage")]
78    pub generate_completion: Option<Shell>,
79
80    /// Generate roff manpage to stdout
81    #[arg(long, conflicts_with = "generate_completion")]
82    pub generate_manpage: bool,
83
84    /// Whether to disable flickering lights during lightfixes generation
85    #[arg(short = 'f', long = "no-flicker")]
86    pub disable_flickering: Option<bool>,
87
88    /// Whether to disable pulsing lights during lightfixes generation
89    #[arg(short = 'p', long = "no-pulse")]
90    pub disable_pulse: Option<bool>,
91
92    /// Whether to null negative lights during lightfixes generation
93    #[arg(long = "disable-negative-lights")]
94    pub disable_negative_lights: Option<bool>,
95
96    #[arg(
97        long = "standard-hue",
98        help = &format!("For lights in the orange range, multiply their HSV hue by this value.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.\nThis argument has no short form due to a conflict with -h.", default::standard_hue())
99    )]
100    pub standard_hue: Option<f32>,
101
102    #[arg(
103        short = 's',
104        long = "standard-saturation",
105        help = &format!("For lights in the orange range, multiply their HSV saturation by this amount.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::standard_saturation())
106    )]
107    pub standard_saturation: Option<f32>,
108
109    #[arg(
110        short = 'v',
111        long = "standard-value",
112        help = &format!("For lights in the orange range, multiply their HSV value by this amount.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::standard_value())
113    )]
114    pub standard_value: Option<f32>,
115
116    #[arg(
117        short = 'r',
118        long = "standard-radius",
119        help = &format!("For lights in the orange range, multiply their radius by this value.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::standard_radius())
120    )]
121    pub standard_radius: Option<f32>,
122
123    #[arg(
124        short = 'H',
125        long = "colored-hue",
126        help = &format!("For lights that are red, purple, blue, green, or yellow, multiply their HSV hue by this value.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::colored_hue())
127    )]
128    pub colored_hue: Option<f32>,
129
130    #[arg(
131        short = 'S',
132        long = "colored-saturation",
133        help = &format!("For lights that are red, purple, blue, green, or yellow, multiply their HSV saturation by this amount.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::colored_saturation())
134    )]
135    pub colored_saturation: Option<f32>,
136
137    #[arg(
138        long = "colored-value",
139        help = &format!("For lights that are red, purple, blue, green, or yellow, multiply their HSV value by this amount.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::colored_value())
140    )]
141    pub colored_value: Option<f32>,
142
143    #[arg(
144        short = 'R',
145        long = "colored-radius",
146        help = &format!("For lights that are red, purple, blue, green, or yellow, multiply their radius by this value.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::colored_radius())
147    )]
148    pub colored_radius: Option<f32>,
149
150    #[arg(
151        short = 'M',
152        long = "duration-mult",
153        help = &format!("Multiplies the duration of all carryable lights.\nIf this argument is not used, the value will be derived from lightConfig.toml or use the default value of {}.", default::duration_mult())
154    )]
155    pub duration_mult: Option<f32>,
156
157    #[arg(
158        short = 'x',
159        long = "excluded-ids",
160        help = &format!("List of Regex patterns of light recordIds to exclude. This setting is *merged* onto values defined by lightconfig.toml.\nIf this argument is not used, the value will be derived from lightConfig.toml."),
161        value_delimiter = ',',
162    )]
163    pub excluded_ids: Vec<String>,
164
165    #[arg(
166        short = 'X',
167        long = "excluded-plugins",
168        help = &format!("List of Regex patterns of plugins to exclude. This setting is *merged* onto values defined by lightconfig.toml.\nIf this argument is not used, the value will be derived from lightConfig.toml."),
169        value_delimiter = ',',
170    )]
171    pub excluded_plugins: Vec<String>,
172
173    #[arg(
174        long = "light",
175        value_parser = crate::light_override::parse_light_override,
176        value_delimiter = ':',
177        help = &format!(
178     "Colon-separated list of regexes to light values.
179     May be specified multiple times instead of as a separated list.
180     Light color values may use fixed RGB fields (`red`, `green`, `blue`), HSV fixed fields (`hue`, `saturation`, `value`), HSV multipliers (`hue_mult`, `saturation_mult`, `value_mult`), and RGB multipliers (`red_mult`, `green_mult`, `blue_mult`).
181     EG:
182     --light \"Torch_001=radius=255,red=255,green=128,blue=64,hue=220,blue_mult=0.5,duration=1200,flag=FLICKERSLOW\" --light \"Torch_002=radius_mult=2.0,hue_mult=1.3,red_mult=1.1,duration_mult=5.0,flag=NONE\"
183     OR
184     --light \"Torch_001=radius=255,red=255,green=128,blue=64,hue=220,blue_mult=0.5,duration=1200,flag=FLICKERSLOW:Torch_002=radius_mult=2.0,hue_mult=1.3,red_mult=1.1,duration_mult=5.0,flag=NONE\"
185     RGB color components are 0-255, matching TES3/Construction Set values. Radius and duration are u32 (can be very big).
186     `flag` may be: NONE, FLICKER, FLICKERSLOW, PULSE, PULSESLOW
187     Color precedence: fixed RGB, when present, replaces the source RGB as the base color and disables global HSV fallback for missing HSV components; without fixed RGB, missing HSV components still use the standard/colored global HSV multipliers. HSV fixed fields/multipliers adjust the selected base color per component, fixed and multiplier forms for the same HSV component are mutually exclusive, and RGB multipliers are always applied last."),
188    )]
189    pub light_overrides: Vec<(String, crate::CustomLightData)>,
190
191    #[arg(
192        long = "ambient",
193        value_parser = crate::light_override::parse_ambient_override,
194        value_delimiter = ':',
195        help = &format!(
196            "
197            Colon-separated list of cell id regexes, to the corresponding ambient data.
198            `sunlight`, `ambient`, `fog`, and `fog_density` are available parameters.
199            Values are provided as fixed RGB values, no multipliers.
200            RGB color components are 0-255, matching TES3/Construction Set values.
201            Each field of cell ambient data is separated by a semicolon, as below:
202            --ambient \"caius cosades\' house=sunlight=red=255,green=255,blue=255;ambient=red=64,green=48,blue=32\"
203            "
204        )
205    )]
206    pub ambient_overrides: Vec<(String, crate::CustomCellAmbient)>,
207
208    #[arg(
209        short = 'U',
210        long,
211        help = &format!("Force-saves the light config on this run. Note that this parameter does not merge into lightConfig.toml like others, and must be manually set there.")
212    )]
213    pub update_light_config: bool,
214}