modde_games/tools/
vkbasalt.rs1use smallvec::{SmallVec, smallvec};
8
9use super::{
10 GameTool, GeneratedConfig, ToolAvailability, ToolCategory, ToolConfig, tool_config_dir, which,
11};
12
13pub static VKBASALT: VkBasalt = VkBasalt;
14
15pub struct VkBasalt;
16
17impl GameTool for VkBasalt {
18 fn tool_id(&self) -> &'static str {
19 "vkbasalt"
20 }
21
22 fn display_name(&self) -> &'static str {
23 "vkBasalt"
24 }
25
26 fn category(&self) -> ToolCategory {
27 ToolCategory::PostProcess
28 }
29
30 fn description(&self) -> &'static str {
31 "Vulkan post-processing layer for CAS sharpening and shader effects."
32 }
33
34 fn settings_schema(&self) -> Vec<super::ToolSettingSpec> {
35 vec![
36 super::ToolSettingSpec::text("toggleKey", "Toggle key", "Key used to toggle vkBasalt.")
37 .section("Activation"),
38 super::ToolSettingSpec::bool(
39 "enableOnLaunch",
40 "Enable on launch",
41 "Start with vkBasalt effects enabled.",
42 )
43 .section("Activation"),
44 super::ToolSettingSpec::text(
45 "effects",
46 "Effects",
47 "Colon or comma separated effect list, such as cas or cas:fxaa.",
48 )
49 .section("Effects"),
50 super::ToolSettingSpec::number(
51 "casSharpness",
52 "CAS sharpness",
53 "Contrast Adaptive Sharpening amount.",
54 0.0,
55 1.0,
56 0.05,
57 )
58 .section("Effects"),
59 super::ToolSettingSpec::path(
60 "reshadeTexturePath",
61 "ReShade texture path",
62 "Optional ReShade texture directory for vkBasalt.",
63 )
64 .section("ReShade Paths"),
65 super::ToolSettingSpec::path(
66 "reshadeIncludePath",
67 "ReShade shader path",
68 "Optional ReShade shader include directory for vkBasalt.",
69 )
70 .section("ReShade Paths"),
71 ]
72 }
73
74 fn detect_available(&self) -> ToolAvailability {
75 #[cfg(not(target_os = "linux"))]
76 {
77 return ToolAvailability::NotInstalled {
78 install_hint: "vkBasalt is only available on Linux".into(),
79 };
80 }
81
82 #[cfg(target_os = "linux")]
85 {
86 let layer_paths = [
87 "/usr/share/vulkan/implicit_layer.d/vkBasalt.json",
88 "/etc/vulkan/implicit_layer.d/vkBasalt.json",
89 ];
90
91 if layer_paths.iter().any(|p| std::path::Path::new(p).exists())
92 || which("vkbasalt").is_some()
93 {
94 ToolAvailability::Available { version: None }
95 } else {
96 if let Ok(paths) = std::env::var("VK_LAYER_PATH") {
98 for dir in std::env::split_paths(&std::ffi::OsString::from(&paths)) {
99 if dir.join("vkBasalt.json").exists() {
100 return ToolAvailability::Available { version: None };
101 }
102 }
103 }
104
105 ToolAvailability::NotInstalled {
106 install_hint: "Install vkbasalt from your package manager".into(),
107 }
108 }
109 }
110 }
111
112 fn env_vars(&self, config: &ToolConfig) -> SmallVec<[(String, String); 4]> {
113 let mut vars = smallvec![("ENABLE_VKBASALT".into(), "1".into())];
114
115 if let Some(game_id) = config.get_str("_game_id") {
116 let conf_path = tool_config_dir(game_id).join("vkBasalt.conf");
117 vars.push((
118 "VKBASALT_CONFIG_FILE".into(),
119 conf_path.to_string_lossy().into(),
120 ));
121 }
122
123 vars
124 }
125
126 fn generate_config(&self, config: &ToolConfig) -> Option<GeneratedConfig> {
127 let game_id = config.get_str("_game_id")?;
128
129 let mut lines = Vec::new();
130 lines.push("# Generated by modde — do not edit manually".to_string());
131
132 let toggle_key = config.get_str("toggleKey").unwrap_or("Home");
134 lines.push(format!("toggleKey = {toggle_key}"));
135
136 let enable_on_launch = config.get_bool("enableOnLaunch");
138 lines.push(format!(
139 "enableOnLaunch = {}",
140 if enable_on_launch { "True" } else { "False" }
141 ));
142
143 if let Some(effects) = config.settings.get("effects").and_then(|v| v.as_array()) {
145 let effect_names: Vec<&str> = effects.iter().filter_map(|v| v.as_str()).collect();
146 if !effect_names.is_empty() {
147 lines.push(format!("effects = {}", effect_names.join(":")));
148 }
149 }
150
151 if let Some(sharpness) = config.settings.get("casSharpness") {
153 lines.push(format!("casSharpness = {sharpness}"));
154 }
155
156 if let Some(path) = config.get_str("reshadeTexturePath") {
158 lines.push(format!("reshadeTexturePath = {path}"));
159 }
160 if let Some(path) = config.get_str("reshadeIncludePath") {
161 lines.push(format!("reshadeIncludePath = {path}"));
162 }
163
164 let dir = tool_config_dir(game_id);
165 Some(GeneratedConfig {
166 path: dir.join("vkBasalt.conf"),
167 content: lines.join("\n") + "\n",
168 })
169 }
170
171 fn default_config(&self) -> ToolConfig {
172 let mut config = ToolConfig::new("vkbasalt");
173 config.set("toggleKey", serde_json::json!("Home"));
174 config.set("enableOnLaunch", serde_json::json!(true));
175 config.set("effects", serde_json::json!(["cas"]));
176 config.set("casSharpness", serde_json::json!(0.4));
177 config
178 }
179}