v1
This commit is contained in:
293
CLAUDE.md
Normal file
293
CLAUDE.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# CLAUDE.md — Multi Render Blender
|
||||
|
||||
## Projet
|
||||
|
||||
Application **Electron** qui pilote **Blender en mode background** (`blender -b`) pour effectuer des rendus multi-cameras.
|
||||
Chaque camera possede ses propres parametres (resolution, frames, format, dossier de sortie).
|
||||
L'application construit une file de rendu (render queue) et execute les commandes Blender une par une,
|
||||
avec affichage de l'image rendue apres chaque etape.
|
||||
|
||||
---
|
||||
|
||||
## Stack technique
|
||||
|
||||
| Couche | Technologie |
|
||||
|--------------|--------------------------------------|
|
||||
| Application | **Electron** (main + renderer) |
|
||||
| Backend | **Node.js** (`child_process.spawn`) |
|
||||
| Frontend | **HTML / CSS / JS vanilla** |
|
||||
| CSS | **Bootstrap 5** via CDN |
|
||||
| Icones | **Material Design Icons (MDI)** CDN |
|
||||
| Scripts | **Python** (executes par Blender) |
|
||||
| Rendu | **Blender CLI** (`blender -b`) |
|
||||
|
||||
> Pas de React, pas de framework JS lourd. HTML/CSS/JS natif uniquement (conforme a la Norme).
|
||||
|
||||
---
|
||||
|
||||
## Architecture des fichiers
|
||||
|
||||
```
|
||||
multi_render_blender/
|
||||
|-- package.json
|
||||
|-- main.js # Process principal Electron
|
||||
|-- preload.js # Bridge IPC (contextBridge)
|
||||
|-- src/
|
||||
| |-- renderer/
|
||||
| | |-- index.html # Page principale
|
||||
| | |-- styles/
|
||||
| | | |-- Main.css
|
||||
| | |-- scripts/
|
||||
| | |-- App.js # Point d'entree renderer
|
||||
| | |-- CameraList.js # Gestion liste cameras
|
||||
| | |-- CameraConfig.js # Formulaires config par camera
|
||||
| | |-- RenderQueue.js # Affichage file de rendu
|
||||
| | |-- PreviewPanel.js # Affichage image rendue
|
||||
| | |-- ProgressBar.js # Barre de progression
|
||||
| | |-- ConsoleLog.js # Console logs UI
|
||||
| |-- main/
|
||||
| | |-- BlenderProcess.js # Spawn et gestion process Blender
|
||||
| | |-- QueueManager.js # File d'attente de rendu
|
||||
| | |-- CameraParser.js # Extraction cameras depuis .blend
|
||||
| | |-- ConfigManager.js # Sauvegarde/chargement config JSON
|
||||
| | |-- PathResolver.js # Gestion chemins dynamiques
|
||||
| |-- python/
|
||||
| |-- list_cameras.py # Script : lister les cameras
|
||||
| |-- setup_render.py # Script : configurer scene avant rendu
|
||||
|-- config/
|
||||
| |-- default_config.json # Config par defaut
|
||||
|-- CLAUDE.md
|
||||
|-- Norme.md
|
||||
```
|
||||
|
||||
### Conventions de nommage fichiers
|
||||
- **Fichiers JS** : `PascalCase.js` (ex: `QueueManager.js`)
|
||||
- **Fichiers Python** : `snake_case.py` (ex: `list_cameras.py`)
|
||||
- **Fichiers CSS** : `PascalCase.css` (ex: `Main.css`)
|
||||
- **Fichiers HTML** : `snake_case.html`
|
||||
|
||||
---
|
||||
|
||||
## Conventions de code (resume Norme.md)
|
||||
|
||||
### JavaScript / Node.js
|
||||
|
||||
| Regle | Detail |
|
||||
|------------------------------|--------------------------------------------------|
|
||||
| Variables | `snake_case` avec prefixes (`nb_`, `is_`, `list_`, `str_`, `obj_`, `has_`) |
|
||||
| Classes | `PascalCase`, un seul mot si possible |
|
||||
| Constantes globales | `MAJUSCULES` |
|
||||
| Indentation | 4 espaces |
|
||||
| Point-virgule | Obligatoire |
|
||||
| Fonctions | Flechees preferees (`() => {}`) |
|
||||
| `async/await` | **INTERDIT** — utiliser `.then()` / `.catch()` |
|
||||
| `forEach()` | **INTERDIT** — utiliser `for...of` |
|
||||
| Accolades | Meme ligne que l'instruction |
|
||||
| Variables | Declarees en debut de fonction |
|
||||
| Frameworks | Aucun (JS natif uniquement) |
|
||||
|
||||
### Python (scripts Blender)
|
||||
|
||||
| Regle | Detail |
|
||||
|------------------------------|--------------------------------------------------|
|
||||
| Variables | `snake_case` avec memes prefixes que JS |
|
||||
| Type hints | **Obligatoires** sur toutes les signatures |
|
||||
| Docstrings | **Obligatoires** en francais sur fonctions publiques |
|
||||
| `print()` | Interdit en production, utiliser `logging` |
|
||||
| Constantes globales | `MAJUSCULES` |
|
||||
| Imports | Standard > Tiers > Projet |
|
||||
| Erreurs | `try/except` doit loguer ET remonter |
|
||||
|
||||
### Gestion des erreurs
|
||||
|
||||
- Toute erreur doit etre **loguee** (console technique) ET **affichee a l'utilisateur** (UI).
|
||||
- Aucune erreur ne doit etre ignoree silencieusement.
|
||||
- En JS : toujours un `.catch()` sur chaque chaine de promesse.
|
||||
- En Python : tout `try/except` doit loguer l'erreur ET la remonter.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Electron (IPC)
|
||||
|
||||
```
|
||||
[Renderer Process] <--IPC--> [Main Process] <--spawn--> [Blender CLI]
|
||||
(UI) preload (Node.js) (blender -b)
|
||||
```
|
||||
|
||||
### Communication IPC
|
||||
|
||||
Le `preload.js` expose une API via `contextBridge` :
|
||||
|
||||
```js
|
||||
// preload.js — API exposee au renderer
|
||||
contextBridge.exposeInMainWorld("api", {
|
||||
select_blend_file: () => ipcRenderer.invoke("select-blend-file"),
|
||||
get_cameras: (str_path) => ipcRenderer.invoke("get-cameras", str_path),
|
||||
start_render: (obj_config) => ipcRenderer.invoke("start-render", obj_config),
|
||||
pause_render: () => ipcRenderer.invoke("pause-render"),
|
||||
stop_render: () => ipcRenderer.invoke("stop-render"),
|
||||
on_render_progress: (fn_callback) => ipcRenderer.on("render-progress", fn_callback),
|
||||
on_render_complete: (fn_callback) => ipcRenderer.on("render-complete", fn_callback),
|
||||
on_render_error: (fn_callback) => ipcRenderer.on("render-error", fn_callback),
|
||||
on_preview_update: (fn_callback) => ipcRenderer.on("preview-update", fn_callback),
|
||||
});
|
||||
```
|
||||
|
||||
> Toute communication entre renderer et main passe par IPC. Jamais d'acces direct a `child_process` ou `fs` depuis le renderer.
|
||||
|
||||
---
|
||||
|
||||
## Fonctionnalites principales
|
||||
|
||||
### 1. Chargement fichier .blend
|
||||
- Selection via dialog natif Electron (`dialog.showOpenDialog`)
|
||||
- Extraction des cameras via :
|
||||
```
|
||||
blender -b fichier.blend --python-expr "import bpy; print([o.name for o in bpy.data.objects if o.type=='CAMERA'])"
|
||||
```
|
||||
- Parsing du stdout pour recuperer la liste
|
||||
|
||||
### 2. Configuration par camera
|
||||
Chaque camera possede :
|
||||
- `is_enabled` : activer/desactiver
|
||||
- `nb_resolution_x` : resolution horizontale
|
||||
- `nb_resolution_y` : resolution verticale
|
||||
- `nb_frame_start` : premiere frame
|
||||
- `nb_frame_end` : derniere frame
|
||||
- `str_format` : format de sortie (PNG, JPEG, EXR)
|
||||
- `str_output_path` : dossier de sortie
|
||||
|
||||
### 3. Modes de rendu
|
||||
- **Mode 1 — Camera par camera** : toutes les frames d'une camera avant de passer a la suivante
|
||||
- **Mode 2 — Frame par frame** : toutes les cameras pour une frame avant de passer a la suivante
|
||||
|
||||
### 4. Commande Blender generee
|
||||
```bash
|
||||
blender -b fichier.blend \
|
||||
--python-expr "
|
||||
import bpy;
|
||||
scene=bpy.context.scene;
|
||||
scene.camera=bpy.data.objects['NomCamera'];
|
||||
scene.render.resolution_x=1920;
|
||||
scene.render.resolution_y=1080
|
||||
" \
|
||||
-o ./renders/NomCamera/frame_##### \
|
||||
-F PNG \
|
||||
-f 120
|
||||
```
|
||||
|
||||
### 5. File d'attente (Render Queue)
|
||||
- Construction d'une queue interne (tableau d'objets commande)
|
||||
- Execution sequentielle : attendre la fin du process avant le suivant
|
||||
- Controles : **Start** / **Pause** / **Stop**
|
||||
|
||||
### 6. Preview de l'image rendue
|
||||
Workflow apres chaque rendu :
|
||||
```
|
||||
Render termine -> Process exit -> Lire image -> Afficher preview -> Lancer suivant
|
||||
```
|
||||
- Detection du fichier genere via le chemin de sortie
|
||||
- Affichage dans un panneau preview (balise `<img>` avec rechargement)
|
||||
|
||||
### 7. Indicateurs UI
|
||||
- Camera en cours
|
||||
- Frame en cours
|
||||
- Progression (X / total)
|
||||
- Image preview
|
||||
- Console logs
|
||||
|
||||
---
|
||||
|
||||
## Modeles de donnees
|
||||
|
||||
### Configuration camera
|
||||
```js
|
||||
let obj_camera_config = {
|
||||
str_name: "Camera.001",
|
||||
is_enabled: true,
|
||||
nb_resolution_x: 1920,
|
||||
nb_resolution_y: 1080,
|
||||
nb_frame_start: 1,
|
||||
nb_frame_end: 250,
|
||||
str_format: "PNG",
|
||||
str_output_path: "./renders/Camera.001/"
|
||||
};
|
||||
```
|
||||
|
||||
### Element de la queue
|
||||
```js
|
||||
let obj_queue_item = {
|
||||
str_camera_name: "Camera.001",
|
||||
nb_frame: 120,
|
||||
nb_resolution_x: 1920,
|
||||
nb_resolution_y: 1080,
|
||||
str_format: "PNG",
|
||||
str_output_path: "./renders/Camera.001/frame_00120.png",
|
||||
str_status: "pending" // "pending" | "rendering" | "done" | "error" | "skipped"
|
||||
};
|
||||
```
|
||||
|
||||
### Configuration globale
|
||||
```js
|
||||
let obj_render_config = {
|
||||
str_blend_file: "/chemin/vers/fichier.blend",
|
||||
str_render_mode: "camera_by_camera", // "camera_by_camera" | "frame_by_frame"
|
||||
list_cameras: [ /* obj_camera_config */ ]
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Regles pour l'IA
|
||||
|
||||
1. **Respecter strictement la Norme.md** — c'est la reference absolue pour le style de code.
|
||||
2. **Jamais de `async/await`** — utiliser `.then()` / `.catch()` avec retour de promesse.
|
||||
3. **Jamais de `forEach()`** — utiliser `for...of`.
|
||||
4. **Nommage strict** — `snake_case` avec prefixes, `PascalCase` pour classes et fichiers JS.
|
||||
5. **Separation IPC** — le renderer ne touche jamais directement Node.js APIs.
|
||||
6. **Une fonction = une responsabilite** — extraire la logique repetee.
|
||||
7. **Gestion d'erreurs systematique** — `.catch()` sur chaque promesse, message utilisateur visible.
|
||||
8. **Pas de dependance externe inutile** — seulement Bootstrap 5 et MDI en CDN.
|
||||
9. **Python : type hints + docstrings** obligatoires sur les scripts Blender.
|
||||
10. **Pas de `print()` en Python** — utiliser `logging` (sauf stdout pour communication avec Node.js).
|
||||
11. **Tester chaque commande Blender** avant de la considerer fonctionnelle.
|
||||
12. **Commenter rarement** — le code doit etre autoportant via le nommage.
|
||||
13. **4 espaces d'indentation**, point-virgule obligatoire en JS.
|
||||
|
||||
---
|
||||
|
||||
## Bonus (a implementer progressivement)
|
||||
|
||||
- [ ] Skip si image deja existante
|
||||
- [ ] Resume apres crash
|
||||
- [ ] Sauvegarde / chargement config JSON
|
||||
- [ ] Drag & drop du fichier .blend
|
||||
- [ ] Multi-thread (plusieurs Blender en parallele)
|
||||
- [ ] Detection automatique du chemin Blender installe
|
||||
- [ ] Estimation du temps restant
|
||||
|
||||
---
|
||||
|
||||
## Commandes utiles
|
||||
|
||||
```bash
|
||||
# Lancer l'app en dev
|
||||
npm start
|
||||
|
||||
# Lister les cameras d'un .blend
|
||||
blender -b fichier.blend --python-expr "import bpy; print([o.name for o in bpy.data.objects if o.type=='CAMERA'])"
|
||||
|
||||
# Render une frame specifique
|
||||
blender -b fichier.blend --python-expr "import bpy; scene=bpy.context.scene; scene.camera=bpy.data.objects['Camera']" -o //output_##### -F PNG -f 1
|
||||
|
||||
# Packager l'app
|
||||
npx electron-builder
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Git
|
||||
|
||||
- Un commit = une fonctionnalite complete.
|
||||
- Aucun commit casse ou incomplet.
|
||||
- Messages de commit clairs et descriptifs.
|
||||
Reference in New Issue
Block a user