Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,23 @@ All notable changes to the **VS Code Aster** extension will be documented in thi
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.7.0] - 2026-04-16

New viewer toolbar with bounding box, wireframe, and screenshot tools.

### Added
- Top toolbar in the mesh viewer with three new tools:
- **Bounding box**: toggleable wireframe cube with colored axes (X red, Y green, Z blue), corner dots, a "0" origin marker, and dimension labels anchored in 3D
- **Wireframe mode**: toggle between solid surface and wireframe rendering to inspect mesh density
- **Screenshot**: left click saves the 3D view as PNG next to the source file and copies to clipboard; right click captures the full viewer including the sidebar
- Toolbar button tooltips using the same inline hover pattern as the rest of the UI
- Toolbar tab in the viewer help popup documenting the three new tools
- Updated README with diagnostics, terminal reuse, direct `.med` opening, and toolbar features

### Fixed
- Popup z-order: help and settings popups no longer render behind the sidebar
- Sidebar tooltip z-order: filter/clear tooltips no longer hidden behind the top toolbar

## [1.6.1] - 2026-04-15

Standalone mesh visualization: click any `.med` file to open the viewer directly, even without a `.comm`/`.export` pair.
Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cff-version: 1.6.1
cff-version: 1.7.0
title: VS Code Aster
message: >-
If you use this software, please cite it using the
Expand Down
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<p align="center"><img src="https://raw.githubusercontent.com/simvia-tech/vs-code-aster/main/media/images/simvia.png" alt="Simvia Logo" width="50%" /></p>

<p align="center">
<a href="/"><img src="https://img.shields.io/badge/version-1.6.1-blue" alt="Version" /></a>
<a href="/"><img src="https://img.shields.io/badge/version-1.7.0-blue" alt="Version" /></a>
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-GPL%203.0-green" alt="License" /></a>
</p>

Expand Down Expand Up @@ -135,7 +135,11 @@ There are two ways to open the form :
1. Open a `.export` file.
2. Click on the "play" icon `Run with code_aster` in the top-right corner of the file.

It will open a terminal and execute the following command : `cave run [file].export`.
It will open a terminal and execute the following command : `cave run [file].export`. Subsequent runs reuse the same terminal.

**Diagnostics**

Warnings (`<A>`), errors (`<E>`, `<F>`), Python tracebacks, and fatal errors from code_aster automatically appear in the VS Code **Problems panel** after a run — no `F mess` entry required in the `.export` file. Diagnostics are attached to the originating `.comm` line when possible and cleared between runs.

**Personnalize alias to run code-aster**

Expand Down Expand Up @@ -182,21 +186,24 @@ The visualizer is an integrated 3D viewer that lets you display and explore your

It’s powered by **VTK.js**, and supports both mesh visualization and node-based groups.

#### Opening the visualizer
![Mesh viewer screenshot](media/images/viewer-screenshot.png)

The visualizer is very easy to open :
#### Opening the visualizer

1. Open a `.comm` file.
2. Click on the "eye" icon `Open visualizer` in the top-right corner of the file.
There are two ways to open the visualizer :

The visualizer is now open !
- **From a `.comm` file** : click on the "eye" icon `Open visualizer` in the top-right corner of the file.
- **From a `.med` file** : click any `.med`, `.mmed`, or `.rmed` file in the explorer — it opens directly in the viewer, no `.comm` file needed. Files with non-standard MED extensions (e.g. `.71`) are auto-detected and can be registered in one click.

#### Features

- Load geometry files (`.med`) directly into the viewer
- Highlight face and node groups using the sidebar
- Highlight groups quickly by selecting their names from your command file (`.comm`)
- Control the camera with by rotating or panning it
- Control the camera by rotating or panning it
- **Bounding box** : toggle a wireframe cube with colored axes (X red, Y green, Z blue), corner dots, and dimension labels to quickly read the characteristic size of the structure
- **Wireframe mode** : switch between solid surface and wireframe rendering to inspect mesh density
- **Screenshot** : save the current 3D view as a PNG file next to your mesh and copy it to the clipboard

#### Usage tips

Expand All @@ -211,6 +218,9 @@ The visualizer is now open !
- Hold `Shift` + `Left click` and move your mouse to pan the camera
- Use the `Mouse wheel` to zoom in and out
- Click on the `X`, `Y`, and `Z` buttons at the bottom of the sidebar to quickly align the camera along an axis
- Toolbar :
- The top toolbar provides quick access to the bounding box, wireframe, and screenshot features
- Right-click the screenshot button to capture the full viewer including the sidebar
- File management :
- Mesh files (`.*med` files) are converted to `.obj` files, which are stored in a hidden folder called `.visu_data/` in your workspace

Expand Down
2 changes: 1 addition & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

The extension aims to reduce friction between modeling, validation, execution, and analysis by bringing **code_aster** native workflows into the editor.

## Current Capabilities (v1.6.1)
## Current Capabilities (v1.7.0)

- `.export` file generator
- 3D mesh viewer
Expand Down
Binary file added media/images/viewer-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 23 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vs-code-aster",
"displayName": "VS Code Aster",
"version": "1.6.1",
"version": "1.7.0",
"description": "VS Code extension for code_aster",
"publisher": "simvia",
"license": "GPL-3.0",
Expand Down Expand Up @@ -138,9 +138,15 @@
"viewType": "vs-code-aster.medViewer",
"displayName": "MED Mesh Viewer",
"selector": [
{ "filenamePattern": "*.med" },
{ "filenamePattern": "*.mmed" },
{ "filenamePattern": "*.rmed" }
{
"filenamePattern": "*.med"
},
{
"filenamePattern": "*.mmed"
},
{
"filenamePattern": "*.rmed"
}
],
"priority": "default"
}
Expand Down Expand Up @@ -274,6 +280,18 @@
"default": true,
"markdownDescription": "Show the orientation axes widget in the bottom-right corner of the viewer."
},
"vs-code-aster.viewer.showBoundingBox": {
"order": 17,
"type": "boolean",
"default": false,
"markdownDescription": "Show a bounding box with X/Y/Z tick marks and values around the loaded meshes in the viewer."
},
"vs-code-aster.viewer.showWireframe": {
"order": 18,
"type": "boolean",
"default": false,
"markdownDescription": "Render meshes in wireframe mode instead of solid surfaces."
},
"vs-code-aster.enableTelemetry": {
"order": 100,
"type": "boolean",
Expand Down Expand Up @@ -306,6 +324,7 @@
"@vscode/test-electron": "^2.5.2",
"esbuild": "^0.25.5",
"eslint": "^9.25.1",
"html-to-image": "^1.11.13",
"husky": "^9.1.7",
"npm-run-all": "^4.1.5",
"prettier": "^3.8.1",
Expand Down
1 change: 1 addition & 0 deletions src/MedEditorProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export class MedEditorProvider implements vscode.CustomReadonlyEditorProvider<vs
webviewPanel
);

visu.sourceDir = path.dirname(medPath);
this.activeViewers.set(medPath, visu);
webviewPanel.onDidDispose(() => {
this.activeViewers.delete(medPath);
Expand Down
1 change: 1 addition & 0 deletions src/VisuManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ export class VisuManager {
commName
);

visu.sourceDir = path.dirname(commUri.fsPath);
this.views.set(key, { commUri, objUris, visu });

// Send telemetry once per opening of this .comm (non-blocking).
Expand Down
14 changes: 14 additions & 0 deletions src/WebviewVisu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class WebviewVisu implements vscode.Disposable {

private readyReceived = false;
private deferredInit?: { fileContexts: string[]; objFilenames: string[] };
public sourceDir?: string;

public get webview(): vscode.Webview {
return this.panel.webview;
Expand Down Expand Up @@ -119,13 +120,24 @@ export class WebviewVisu implements vscode.Disposable {
'edgeMode',
'groupTransparency',
'showOrientationWidget',
'showBoundingBox',
'showWireframe',
];
for (const key of settingKeys) {
if (e.settings[key] !== undefined) {
cfg.update(`viewer.${key}`, e.settings[key], vscode.ConfigurationTarget.Global);
}
}
break;
case 'saveScreenshot': {
if (this.sourceDir) {
const base64 = (e.dataUrl as string).replace(/^data:image\/png;base64,/, '');
const buffer = Buffer.from(base64, 'base64');
const filePath = path.join(this.sourceDir, e.filename as string);
fs.writeFileSync(filePath, buffer);
}
break;
}
case 'debugPanel':
// Log debug messages from the webview
console.log('[WebviewVisu] Message received from webview:', e.text);
Expand Down Expand Up @@ -178,6 +190,8 @@ export class WebviewVisu implements vscode.Disposable {
edgeMode: config.get<string>('viewer.edgeMode', 'threshold'),
groupTransparency: config.get<number>('viewer.groupTransparency', 0.2),
showOrientationWidget: config.get<boolean>('viewer.showOrientationWidget', true),
showBoundingBox: config.get<boolean>('viewer.showBoundingBox', false),
showWireframe: config.get<boolean>('viewer.showWireframe', false),
};
this.panel.webview.postMessage({
type: 'init',
Expand Down
2 changes: 1 addition & 1 deletion webviews/viewer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<title>MeshViewer</title>
<script src="../js/vtk.js"></script>
</head>
<body class="h-screen w-screen flex" style="color: var(--ui-fg)">
<body class="h-screen w-screen flex overflow-hidden" style="color: var(--ui-fg)">
<div id="scene"></div>
<div id="app"></div>
<script type="module" src="./src/main.ts"></script>
Expand Down
6 changes: 6 additions & 0 deletions webviews/viewer/src/components/layout/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
import { groupHierarchy } from '../../lib/state';
import Sidebar from './Sidebar.svelte';
import TopActions from './TopActions.svelte';
import TopToolbar from './TopToolbar.svelte';
import ZoomWidget from '../viewer/ZoomWidget.svelte';
import BoundingBoxLabels from '../viewer/BoundingBoxLabels.svelte';
import Popup from '../popups/Popup.svelte';
import HelpPopup from '../popups/HelpPopup.svelte';
import SettingsPopup from '../popups/SettingsPopup.svelte';
Expand Down Expand Up @@ -35,7 +37,11 @@
}}
/>

<TopToolbar />

<ZoomWidget />

<BoundingBoxLabels />
{/if}

{#if openPopup}
Expand Down
2 changes: 1 addition & 1 deletion webviews/viewer/src/components/layout/Sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
});
</script>

<div id="controls" class="relative h-full flex flex-col z-10 p-2 bg-ui-muted">
<div id="controls" class="relative h-full flex flex-col z-20 p-2 bg-ui-muted">
<div id="sidebarGroups" class="flex flex-col items-center space-y-1 grow overflow-y-auto">
{#each Object.entries($groupHierarchy) as [key, data]}
<ObjectSection
Expand Down
16 changes: 16 additions & 0 deletions webviews/viewer/src/components/layout/TopToolbar.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script lang="ts">
import BoundingBoxButton from '../viewer/BoundingBoxButton.svelte';
import WireframeButton from '../viewer/WireframeButton.svelte';
import ScreenshotButton from '../viewer/ScreenshotButton.svelte';
</script>

<div
id="topToolbar"
class="absolute top-0 z-10 left-1/2 -translate-x-1/2 flex items-stretch rounded-b-sm border border-t-0 bg-ui-muted border-ui-border"
>
<BoundingBoxButton />
<div class="w-px bg-ui-border"></div>
<WireframeButton />
<div class="w-px bg-ui-border"></div>
<ScreenshotButton />
</div>
41 changes: 40 additions & 1 deletion webviews/viewer/src/components/popups/HelpPopup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
</script>

<script lang="ts">
import BoundingBoxIcon from '../../icons/BoundingBoxIcon.svelte';
import ClearIcon from '../../icons/ClearIcon.svelte';
import EyeIcon from '../../icons/EyeIcon.svelte';
import FaceIcon from '../../icons/FaceIcon.svelte';
Expand All @@ -11,11 +12,13 @@
import ObjectIcon from '../../icons/ObjectIcon.svelte';
import MouseScrollIcon from '../../icons/MouseScrollIcon.svelte';
import ResetIcon from '../../icons/ResetIcon.svelte';
import ScreenshotIcon from '../../icons/ScreenshotIcon.svelte';
import WireframeIcon from '../../icons/WireframeIcon.svelte';
import ZoomIcon from '../../icons/ZoomIcon.svelte';

let { onclose }: { onclose: () => void } = $props();

const mainTabs = ['Camera', 'Objects', 'Groups', 'Files'] as const;
const mainTabs = ['Camera', 'Toolbar', 'Objects', 'Groups', 'Files'] as const;
const tabs = [...mainTabs, 'About'] as const;
type Tab = (typeof tabs)[number];
let activeTab = $state<Tab>('Camera');
Expand Down Expand Up @@ -100,6 +103,42 @@
</span>
<span>Align camera along that axis — buttons at the bottom of the sidebar</span>
</div>
{:else if activeTab === 'Toolbar'}
<div class="grid grid-cols-[auto_1fr] gap-x-5 gap-y-3 items-center">
<span
class="inline-flex items-center justify-center size-6 rounded-sm bg-ui-muted border border-ui-border text-ui-text-secondary stroke-[1.75]"
>
<BoundingBoxIcon class="size-3.5" />
</span>
<span
>Toggle a <strong>bounding box</strong> with colored axes (<span
class="text-red-500 font-bold">X</span
>
<span class="text-green-500 font-bold">Y</span>
<span class="text-blue-500 font-bold">Z</span>), corner dots, and dimension labels to
quickly read the characteristic size of the structure</span
>

<span
class="inline-flex items-center justify-center size-6 rounded-sm bg-ui-muted border border-ui-border text-ui-text-secondary stroke-[1.75]"
>
<WireframeIcon class="size-3.5" />
</span>
<span
>Switch between <strong>solid surface</strong> and <strong>wireframe</strong> rendering to
inspect mesh density</span
>

<span
class="inline-flex items-center justify-center size-6 rounded-sm bg-ui-muted border border-ui-border text-ui-text-secondary stroke-[1.75]"
>
<ScreenshotIcon class="size-3.5" />
</span>
<span
><strong>Left click</strong> — save the 3D view as PNG next to your file &amp; copy to
clipboard. <strong>Right click</strong> — capture the full viewer including the sidebar.</span
>
</div>
{:else if activeTab === 'Objects'}
<div class="grid grid-cols-[auto_1fr] gap-x-5 gap-y-3 items-center">
<span
Expand Down
2 changes: 1 addition & 1 deletion webviews/viewer/src/components/popups/Popup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</script>

<div
class="fixed inset-0 z-10 bg-black/20 backdrop-blur-xs"
class="fixed inset-0 z-30 bg-black/20 backdrop-blur-xs"
role="dialog"
aria-modal="true"
tabindex="0"
Expand Down
Loading
Loading