diff --git a/.vscodeignore b/.vscodeignore
index c0171a1..18d3cc4 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -7,6 +7,11 @@ node_modules/**
src/**
.gitignore
.yarnrc
+.prettierignore
+.husky/**
+.mypy_cache/**
+.ruff_cache/**
+**/__pycache__/**
esbuild.js
vsc-extension-quickstart.md
**/tsconfig.json
@@ -14,10 +19,18 @@ vsc-extension-quickstart.md
**/*.map
**/*.ts
**/.vscode-test.*
+CITATION.cff
+ROADMAP.md
+pyproject.toml
+tailwind.config.js
.venv
noxfile.py
requirements.txt
python/data
+python/cmake/**
+python/bundled/.gitkeep
+python/requirements.txt
+python/datamodel/test/**
python/lsp/.venv
python/.venv
webviews/viewer/src/**
diff --git a/CHANGELOG.md b/CHANGELOG.md
index afe3605..51d2c36 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,21 @@ 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.5.2] - 2026-03-23
+
+Various fixes and improvements.
+
+### Added
+- Export form now auto-increments unit numbers to avoid duplicates when adding new files
+- Files named `export` (without extension) are now detected as export files
+
+### Fixed
+- Mesh viewer now correctly resolves .med file paths containing subdirectories (e.g. `Mesh/mesh.med`) relative to the .export file location ([#13](https://github.com/simvia-tech/vs-code-aster/issues/13))
+- Selecting text no longer resets manually hidden objects in the mesh viewer ([#14](https://github.com/simvia-tech/vs-code-aster/issues/14))
+- Fixed issues when two meshes share groups with the same name ([#15](https://github.com/simvia-tech/vs-code-aster/issues/15))
+- Fixed error in mesh viewer ([#16](https://github.com/simvia-tech/vs-code-aster/issues/16))
+- Reduced extension package size by excluding unnecessary files
+
## [1.5.1] - 2026-03-16
Various fixes and optimizations.
diff --git a/CITATION.cff b/CITATION.cff
index 76cf02a..a5034a0 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -1,4 +1,4 @@
-cff-version: 1.5.1
+cff-version: 1.5.2
title: VS Code Aster
message: >-
If you use this software, please cite it using the
diff --git a/README.md b/README.md
index 58fc2be..bbbfb6d 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@

-
+
diff --git a/ROADMAP.md b/ROADMAP.md
index 44f5abe..f7ad02f 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -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.5.1)
+## Current Capabilities (v1.5.2)
- `.export` file generator
- 3D mesh viewer
diff --git a/package-lock.json b/package-lock.json
index 618b7dd..3417108 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "vs-code-aster",
- "version": "1.5.1",
+ "version": "1.5.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "vs-code-aster",
- "version": "1.5.1",
+ "version": "1.5.2",
"license": "GPL-3.0",
"dependencies": {
"@tailwindcss/cli": "^4.1.17",
diff --git a/package.json b/package.json
index c998a2a..d4f1f75 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "vs-code-aster",
"displayName": "VS Code Aster",
- "version": "1.5.1",
+ "version": "1.5.2",
"description": "VS Code extension for code_aster",
"publisher": "simvia",
"license": "GPL-3.0",
diff --git a/src/VisuManager.ts b/src/VisuManager.ts
index f0dd0aa..94a0cba 100644
--- a/src/VisuManager.ts
+++ b/src/VisuManager.ts
@@ -208,7 +208,7 @@ export function findMedFiles(commFilePath: string): string[] {
try {
const dir = path.dirname(commFilePath);
const commFileName = path.basename(commFilePath);
- const exportFiles = fs.readdirSync(dir).filter((f) => f.endsWith('.export'));
+ const exportFiles = fs.readdirSync(dir).filter((f) => f === 'export' || f.endsWith('.export'));
if (exportFiles.length === 0) {
vscode.window.showErrorMessage(`No .export file found in directory: ${dir}`);
@@ -240,15 +240,15 @@ export function findMedFiles(commFilePath: string): string[] {
continue;
}
+ const medPath = path.isAbsolute(name) ? name : path.join(dir, name);
const medFileName = path.basename(name);
- const medPath = path.join(dir, medFileName);
if (fs.existsSync(medPath)) {
console.log(`[findMedFiles] found med file: ${medFileName}`);
foundMedFiles.push(medPath);
} else {
vscode.window.showErrorMessage(
- `The file "${medFileName}" mentioned in "${exportFile}" does not exist in the current directory (${path.basename(dir)}/).`
+ `The file "${name}" mentioned in "${exportFile}" does not exist.`
);
}
}
diff --git a/src/WebviewVisu.ts b/src/WebviewVisu.ts
index 46a32a0..4676bc8 100644
--- a/src/WebviewVisu.ts
+++ b/src/WebviewVisu.ts
@@ -189,6 +189,8 @@ export class WebviewVisu implements vscode.Disposable {
// Parse the text to find object names
// Object keys are like "all_mesh.obj"; match against the stem (no "all_" prefix, no extension)
+ // Only send showOnlyObjects when a mesh name is explicitly selected, to avoid
+ // resetting user-hidden meshes on every text selection change.
const selectedObjects =
this.objects?.filter((objectKey) => {
const withoutPrefix = objectKey.startsWith('all_') ? objectKey.slice(4) : objectKey;
@@ -196,10 +198,12 @@ export class WebviewVisu implements vscode.Disposable {
return this.makeWholeTokenRegex(shortName).test(text);
}) || [];
- this.panel.webview.postMessage({
- type: 'showOnlyObjects',
- body: { objects: selectedObjects },
- });
+ if (selectedObjects.length > 0) {
+ this.panel.webview.postMessage({
+ type: 'showOnlyObjects',
+ body: { objects: selectedObjects },
+ });
+ }
}
/**
diff --git a/webviews/export/export.js b/webviews/export/export.js
index 80a1953..c0c7e9f 100644
--- a/webviews/export/export.js
+++ b/webviews/export/export.js
@@ -30,6 +30,24 @@ const defaultUnits = {
libr: '16',
};
+function getNextAvailableUnit(defaultUnit) {
+ const usedUnits = new Set();
+ for (const f of formData.inputFiles) {
+ usedUnits.add(String(f.unit));
+ }
+ for (const f of formData.outputFiles) {
+ usedUnits.add(String(f.unit));
+ }
+ let unit = Number(defaultUnit);
+ if (unit === 0) {
+ return String(unit);
+ }
+ while (usedUnits.has(String(unit))) {
+ unit++;
+ }
+ return String(unit);
+}
+
const formData = {
name: '',
parameters: {
@@ -179,14 +197,15 @@ function addFileRow(container, targetArray, fileObj) {
inputName.value = fileObj.name;
inputUnit.value = fileObj.unit;
} else {
- fileObj = { type: 'nom', name: '', unit: '0' };
+ const unit = getNextAvailableUnit('0');
+ fileObj = { type: 'nom', name: '', unit: unit };
inputName.placeholder = 'File Name : ';
- inputUnit.value = '0';
+ inputUnit.value = unit;
}
select.addEventListener('input', () => {
fileObj.type = select.value.trim();
- const unit = defaultUnits[fileObj.type];
+ const unit = getNextAvailableUnit(defaultUnits[fileObj.type]);
inputUnit.value = unit;
fileObj.unit = unit;
});
diff --git a/webviews/viewer/src/lib/commands/VisibilityManager.ts b/webviews/viewer/src/lib/commands/VisibilityManager.ts
index 39c0cb9..08b64c2 100644
--- a/webviews/viewer/src/lib/commands/VisibilityManager.ts
+++ b/webviews/viewer/src/lib/commands/VisibilityManager.ts
@@ -63,6 +63,11 @@ export class VisibilityManager {
const wasHighlighted = this.highlightedGroupsSet.has(groupName);
const isHighlighted = typeof visible === 'boolean' ? visible : !wasHighlighted;
+ // Don't highlight groups on hidden objects
+ if (isHighlighted && this.hiddenObjects[object]) {
+ return;
+ }
+
if (isHighlighted) {
this.highlightedGroupsSet.add(groupName);
highlightedGroups.update((map) => {
diff --git a/webviews/viewer/src/lib/data/create/FaceActorCreator.ts b/webviews/viewer/src/lib/data/create/FaceActorCreator.ts
index a8bca45..5cfb2c1 100644
--- a/webviews/viewer/src/lib/data/create/FaceActorCreator.ts
+++ b/webviews/viewer/src/lib/data/create/FaceActorCreator.ts
@@ -26,6 +26,10 @@ export class FaceActorCreator {
const mapper = vtk.Rendering.Core.vtkMapper.newInstance();
mapper.setInputData(polyData);
+ if (!groupName.includes('all_')) {
+ mapper.setResolveCoincidentTopology(true);
+ mapper.setRelativeCoincidentTopologyPolygonOffsetParameters(-2, -2);
+ }
actor.setMapper(mapper);
const { colorIndex, isObjectActor } = this.setProperty(actor, groupName, cellCount);