diff --git a/crates/server/src/backend.rs b/crates/server/src/backend.rs index 44dacef..85bd189 100644 --- a/crates/server/src/backend.rs +++ b/crates/server/src/backend.rs @@ -140,6 +140,7 @@ struct RuntimeSettings { allow_bare_percentages: bool, map_ordering_diagnostics: bool, debounce_ms: u64, + preview_enabled: bool, preview_image_width: u32, preview_zoom_percent: u32, } @@ -154,6 +155,7 @@ impl Default for RuntimeSettings { allow_bare_percentages: false, map_ordering_diagnostics: true, debounce_ms: DEFAULT_ANALYSIS_DEBOUNCE_MS, + preview_enabled: true, preview_image_width: DEFAULT_PREVIEW_IMAGE_WIDTH, preview_zoom_percent: DEFAULT_PREVIEW_ZOOM_PERCENT, } @@ -213,6 +215,10 @@ impl RuntimeSettings { .and_then(|value| value.as_bool()) .unwrap_or(true), debounce_ms, + preview_enabled: preview + .and_then(|preview| preview.get("enable")) + .and_then(|enabled| enabled.as_bool()) + .unwrap_or(true), preview_image_width: normalized_u32( preview.and_then(|preview| preview.get("imageWidth")), DEFAULT_PREVIEW_IMAGE_WIDTH, @@ -659,7 +665,8 @@ impl Backend { previous.model_member_strictness != settings.model_member_strictness; let map_ordering_changed = previous.map_ordering_diagnostics != settings.map_ordering_diagnostics; - let preview_changed = previous.preview_image_width != settings.preview_image_width + let preview_changed = previous.preview_enabled != settings.preview_enabled + || previous.preview_image_width != settings.preview_image_width || previous.preview_zoom_percent != settings.preview_zoom_percent; if preview_changed { @@ -1081,7 +1088,7 @@ impl LanguageServer for Backend { // Editor-facing settings arrive as `initializationOptions`. Shape: // `{ "format": {"enable": bool}, "schemaPath": "schema.json", - // "preview": {"imageWidth": 160, "zoomPercent": 100}, + // "preview": {"enable": true, "imageWidth": 160, "zoomPercent": 100}, // "analysis": {"modelMemberStrictness": "compatible", // "allowPercentagesWithoutSign": false, // "mapOrderingDiagnostics": true, "debounceMs": 250}, @@ -1461,11 +1468,25 @@ impl LanguageServer for Backend { let Some(source) = source else { return Ok(item); }; - let (image_width, zoom_percent) = self + let (preview_enabled, image_width, zoom_percent) = self .settings .lock() - .map(|settings| (settings.preview_image_width, settings.preview_zoom_percent)) - .unwrap_or((DEFAULT_PREVIEW_IMAGE_WIDTH, DEFAULT_PREVIEW_ZOOM_PERCENT)); + .map(|settings| { + ( + settings.preview_enabled, + settings.preview_image_width, + settings.preview_zoom_percent, + ) + }) + .unwrap_or(( + true, + DEFAULT_PREVIEW_IMAGE_WIDTH, + DEFAULT_PREVIEW_ZOOM_PERCENT, + )); + if !preview_enabled { + item.documentation = None; + return Ok(item); + } let cache_key = format!( "{}\0{}\0{image_width}\0{zoom_percent}", data.model.to_ascii_lowercase(), @@ -2215,12 +2236,14 @@ mod tests { #[test] fn preview_settings_default_and_clamp() { let defaults = RuntimeSettings::default(); + assert!(defaults.preview_enabled); assert_eq!(defaults.preview_image_width, 160); assert_eq!(defaults.preview_zoom_percent, 100); let settings = RuntimeSettings::from_value(Some(&serde_json::json!({ - "preview": {"imageWidth": 10_000, "zoomPercent": 0} + "preview": {"enable": false, "imageWidth": 10_000, "zoomPercent": 0} }))); + assert!(!settings.preview_enabled); assert_eq!(settings.preview_image_width, 640); assert_eq!(settings.preview_zoom_percent, 25); } @@ -2231,7 +2254,7 @@ mod tests { "format": {"enable": true}, "schemaPath": "schema.json", "baseIniRoots": ["base"], - "preview": {"imageWidth": 320, "zoomPercent": 150}, + "preview": {"enable": false, "imageWidth": 320, "zoomPercent": 150}, "analysis": {"modelMemberStrictness": "strict", "debounceMs": 9000} }))); let notification = RuntimeSettings::from_value(Some(&serde_json::json!({ @@ -2239,12 +2262,13 @@ mod tests { "format": {"enable": true}, "schema": {"path": "schema.json"}, "baseIniRoots": ["base"], - "preview": {"imageWidth": 320, "zoomPercent": 150}, + "preview": {"enable": false, "imageWidth": 320, "zoomPercent": 150}, "analysis": {"modelMemberStrictness": "strict", "debounceMs": 9000} } }))); assert_eq!(startup, notification); assert_eq!(startup.debounce_ms, 5000); + assert!(!startup.preview_enabled); assert_eq!(startup.preview_image_width, 320); assert_eq!(startup.preview_zoom_percent, 150); } diff --git a/crates/server/tests/e2e.py b/crates/server/tests/e2e.py index 7f926c4..2ba917f 100644 --- a/crates/server/tests/e2e.py +++ b/crates/server/tests/e2e.py @@ -170,7 +170,7 @@ def wait_for(pred, what, timeout=15.0): runtime_settings = { "format": {"enable": False}, - "preview": {"imageWidth": 240, "zoomPercent": 150}, + "preview": {"enable": True, "imageWidth": 240, "zoomPercent": 150}, "baseIniRoots": [], "schema": {"path": ""}, "analysis": { @@ -193,7 +193,7 @@ def configure(): }, "workspaceFolders": None, "rootUri": root_uri, "initializationOptions": { "format": {"enable": False}, - "preview": {"imageWidth": 240, "zoomPercent": 150}, + "preview": {"enable": True, "imageWidth": 240, "zoomPercent": 150}, "analysis": {"debounceMs": 50}, }}}) init = wait_for(lambda m: m.get("id") == 1 and "result" in m, "initialize result") @@ -626,6 +626,15 @@ def latest_burst_diag(message): assert resized_png != encoded_png, "zoom change reused the previous preview" print("OK: model preview size and zoom hot-reload") + runtime_settings["preview"]["enable"] = False + configure() + send({"jsonrpc": "2.0", "id": 103, "method": "completionItem/resolve", + "params": resolved["result"]}) + disabled = wait_for( + lambda m: m.get("id") == 103 and "result" in m, "disabled model preview") + assert "documentation" not in disabled["result"] + print("OK: model preview can be disabled without restarting") + runtime_settings["analysis"]["allowPercentagesWithoutSign"] = False configure() percent = wait_for( diff --git a/editors/vscode/README.md b/editors/vscode/README.md index 20398df..1c34b4f 100644 --- a/editors/vscode/README.md +++ b/editors/vscode/README.md @@ -37,7 +37,8 @@ While completing `Model =`, move the active selection with the keyboard or mouse to see a textured W3D thumbnail in VS Code's suggestion-details pane. The preview is loaded only for the selected entry. If the pane is collapsed, press `Ctrl+Space` again or use the suggestion widget's details control. -Use `zerosyntax.preview.imageWidth` to change the thumbnail/pane content width +Disable `zerosyntax.preview.enable` to avoid model rendering and cached images +on lower-end hardware. Use `zerosyntax.preview.imageWidth` to change the thumbnail/pane content width and `zerosyntax.preview.zoomPercent` to change the model framing. ## Settings @@ -50,6 +51,7 @@ and `zerosyntax.preview.zoomPercent` to change the model framing. | `zerosyntax.analysis.allowPercentagesWithoutSign` | `false` | Allows engine-compatible percentage values without a trailing `%`; applies immediately. | | `zerosyntax.analysis.mapOrderingDiagnostics` | `true` | Warns about source-proven forward-order problems in `map.ini` and `solo.ini`; applies immediately. | | `zerosyntax.analysis.debounceMs` | `250` | Delay before diagnostics/index refresh after typing; applies to future edits immediately. | +| `zerosyntax.preview.enable` | `true` | Enables rendered W3D model completion previews; disable on lower-end hardware. | | `zerosyntax.preview.imageWidth` | `160` | Displayed W3D thumbnail width in pixels; applies to newly resolved previews immediately. | | `zerosyntax.preview.zoomPercent` | `100` | Default W3D preview camera zoom; applies to newly resolved previews immediately. | | `zerosyntax.format.enable` | `false` | Enables indentation formatting immediately when the client supports dynamic registration. | diff --git a/editors/vscode/package.json b/editors/vscode/package.json index d0684a9..9903294 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -77,6 +77,11 @@ "default": false, "markdownDescription": "Enable document formatting (indentation normalization). When off — the default — `#editor.formatOnSave#` will not invoke it for Generals INI files." }, + "zerosyntax.preview.enable": { + "type": "boolean", + "default": true, + "markdownDescription": "Show rendered W3D model images in completion details. Disable this on lower-end hardware to avoid model rendering and cached preview images." + }, "zerosyntax.preview.imageWidth": { "type": "integer", "default": 160, diff --git a/editors/vscode/src/extension.ts b/editors/vscode/src/extension.ts index 54bedb2..ba07c24 100644 --- a/editors/vscode/src/extension.ts +++ b/editors/vscode/src/extension.ts @@ -43,6 +43,7 @@ export function activate(context: vscode.ExtensionContext) { enable: setting("format.enable", false), }, preview: { + enable: setting("preview.enable", true), imageWidth: setting("preview.imageWidth", 160), zoomPercent: setting("preview.zoomPercent", 100), },