diff --git a/package-lock.json b/package-lock.json index 3b3cc1f..457f638 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "multi-render-blender", - "version": "1.2.0", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "multi-render-blender", - "version": "1.2.0", + "version": "1.3.0", "license": "MIT", "devDependencies": { "electron": "^34.0.0", diff --git a/release.sh b/release.sh index e61d03a..04b07c4 100755 --- a/release.sh +++ b/release.sh @@ -3,6 +3,18 @@ set -euo pipefail cd "$(dirname "$0")" +############################################ +# Options CLI +############################################ +BUMP_ARG="" + +while getopts "i:" opt; do + case "$opt" in + i) BUMP_ARG="$OPTARG" ;; + *) echo "Usage: $0 [-i patch|minor|major]"; exit 1 ;; + esac +done + ############################################ # Chargement du token ############################################ @@ -30,21 +42,30 @@ CURRENT_VERSION=$(node -p "require('./package.json').version") echo "Version actuelle: v$CURRENT_VERSION" echo "" -echo "Comment incrementer la version ?" -echo " 1) patch" -echo " 2) minor" -echo " 3) major" -echo " 4) garder ($CURRENT_VERSION)" -echo "" -read -p "Choix [1/2/3/4]: " BUMP_CHOICE +if [ -n "$BUMP_ARG" ]; then + case "$BUMP_ARG" in + patch) npm version patch --no-git-tag-version ;; + minor) npm version minor --no-git-tag-version ;; + major) npm version major --no-git-tag-version ;; + *) echo "Erreur: -i accepte patch, minor ou major"; exit 1 ;; + esac +else + echo "Comment incrementer la version ?" + echo " 1) patch" + echo " 2) minor" + echo " 3) major" + echo " 4) garder ($CURRENT_VERSION)" + echo "" + read -p "Choix [1/2/3/4]: " BUMP_CHOICE -case "$BUMP_CHOICE" in - 1) npm version patch --no-git-tag-version ;; - 2) npm version minor --no-git-tag-version ;; - 3) npm version major --no-git-tag-version ;; - 4) echo "Version inchangee." ;; - *) echo "Choix invalide"; exit 1 ;; -esac + case "$BUMP_CHOICE" in + 1) npm version patch --no-git-tag-version ;; + 2) npm version minor --no-git-tag-version ;; + 3) npm version major --no-git-tag-version ;; + 4) echo "Version inchangee." ;; + *) echo "Choix invalide"; exit 1 ;; + esac +fi VERSION=$(node -p "require('./package.json').version") TAG="v$VERSION" diff --git a/src/main/BlenderProcess.js b/src/main/BlenderProcess.js index ac864e7..5b99bc1 100644 --- a/src/main/BlenderProcess.js +++ b/src/main/BlenderProcess.js @@ -13,13 +13,56 @@ const BlenderProcess = { let str_safe_name = str_camera_name.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); - let str_python_expr = [ + let list_python_lines = [ "import bpy", "scene=bpy.context.scene", "scene.camera=bpy.data.objects['" + str_safe_name + "']", "scene.render.resolution_x=" + nb_resolution_x, "scene.render.resolution_y=" + nb_resolution_y, - ].join(";"); + ]; + + if (obj_params.obj_render_settings) { + let obj_rs = obj_params.obj_render_settings; + if (obj_rs.str_engine) { + list_python_lines.push("scene.render.engine='" + obj_rs.str_engine + "'"); + } + if (obj_rs.nb_resolution_percentage !== undefined) { + list_python_lines.push("scene.render.resolution_percentage=" + obj_rs.nb_resolution_percentage); + } + if (obj_rs.is_film_transparent !== undefined) { + list_python_lines.push("scene.render.film_transparent=" + (obj_rs.is_film_transparent ? "True" : "False")); + } + if (obj_rs.str_engine === "CYCLES") { + if (obj_rs.nb_samples !== undefined) { + list_python_lines.push("scene.cycles.samples=" + obj_rs.nb_samples); + } + if (obj_rs.str_device) { + list_python_lines.push("scene.cycles.device='" + obj_rs.str_device + "'"); + } + if (obj_rs.is_denoise !== undefined) { + list_python_lines.push("scene.cycles.use_denoising=" + (obj_rs.is_denoise ? "True" : "False")); + } + } else if (obj_rs.str_engine === "BLENDER_EEVEE" || obj_rs.str_engine === "BLENDER_EEVEE_NEXT") { + if (obj_rs.nb_samples !== undefined) { + list_python_lines.push("try:\n scene.eevee.taa_render_samples=" + obj_rs.nb_samples + "\nexcept:\n try:\n scene.eevee.samples=" + obj_rs.nb_samples + "\n except:pass"); + } + } + } + + let str_python_expr = list_python_lines.join(";"); + + if (obj_params.list_collections && obj_params.list_collections.length > 0) { + str_python_expr += "\ndef _slc(lc,n,v):" + + "\n for c in lc.children:" + + "\n if c.name==n:c.exclude=v;return" + + "\n _slc(c,n,v)\n"; + for (let obj_col of obj_params.list_collections) { + let str_col_safe = obj_col.str_name.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); + let str_val = obj_col.is_hide_render ? "True" : "False"; + str_python_expr += "bpy.data.collections['" + str_col_safe + "'].hide_render=" + str_val + + ";_slc(bpy.context.view_layer.layer_collection,'" + str_col_safe + "'," + str_val + ")\n"; + } + } let list_args = [ "-b", str_blend_path, diff --git a/src/main/CameraParser.js b/src/main/CameraParser.js index eafc4b9..d193b98 100644 --- a/src/main/CameraParser.js +++ b/src/main/CameraParser.js @@ -4,12 +4,25 @@ const PathResolver = require("./PathResolver.js"); const STR_SCENE_MARKER = "SCENE_JSON:"; const STR_PYTHON_EXPR = [ - "import bpy, json, sys;", - "s=bpy.context.scene;", - "cams=[o.name for o in bpy.data.objects if o.type=='CAMERA'];", - "info={'list_cameras':cams,'obj_scene':{'nb_resolution_x':s.render.resolution_x,'nb_resolution_y':s.render.resolution_y,'nb_frame_start':s.frame_start,'nb_frame_end':s.frame_end,'nb_frame_step':s.frame_step}};", - "sys.stdout.write('SCENE_JSON:' + json.dumps(info) + '\\n');", - "sys.stdout.flush()", + "import bpy, json, sys", + "\ns=bpy.context.scene", + "\ncams=[o.name for o in bpy.data.objects if o.type=='CAMERA']", + "\ncols=[]", + "\ndef _wlc(lc,d):", + "\n for c in lc.children:", + "\n cols.append({'str_name':c.name,'nb_depth':d,'is_hide_render':bpy.data.collections[c.name].hide_render,'is_exclude':c.exclude})", + "\n _wlc(c,d+1)", + "\n_wlc(bpy.context.view_layer.layer_collection,0)", + "\nrs={'str_engine':s.render.engine,'nb_resolution_percentage':s.render.resolution_percentage,'is_film_transparent':s.render.film_transparent}", + "\ntry:\n rs['nb_cycles_samples']=s.cycles.samples;rs['str_cycles_device']=s.cycles.device;rs['is_cycles_denoise']=s.cycles.use_denoising", + "\nexcept:pass", + "\ntry:\n rs['nb_eevee_samples']=s.eevee.taa_render_samples", + "\nexcept:", + "\n try:\n rs['nb_eevee_samples']=s.eevee.samples", + "\n except:pass", + "\ninfo={'list_cameras':cams,'obj_scene':{'nb_resolution_x':s.render.resolution_x,'nb_resolution_y':s.render.resolution_y,'nb_frame_start':s.frame_start,'nb_frame_end':s.frame_end,'nb_frame_step':s.frame_step},'obj_render_settings':rs,'list_collections':cols}", + "\nsys.stdout.write('SCENE_JSON:' + json.dumps(info) + '\\n')", + "\nsys.stdout.flush()", ].join(""); const CameraParser = { diff --git a/src/main/QueueManager.js b/src/main/QueueManager.js index 10e7849..ad30904 100644 --- a/src/main/QueueManager.js +++ b/src/main/QueueManager.js @@ -6,6 +6,8 @@ const { Notification } = require("electron"); const STR_STATUS_IDLE = "idle"; const STR_STATUS_RUNNING = "running"; const STR_STATUS_PAUSED = "paused"; +const STR_PLACEHOLDER_CONTENT = "RENDERING"; +const NB_PLACEHOLDER_MAX_SIZE = 64; class QueueManager { constructor(obj_window) { @@ -37,6 +39,8 @@ class QueueManager { this.nb_last_render_ms = 0; this.str_last_image_path = null; this.str_overwrite_mode = obj_config.str_overwrite_mode || "overwrite"; + this.list_collections = obj_config.list_collections || []; + this.obj_render_settings = obj_config.obj_render_settings || null; this._send_log("File de rendu construite : " + this.list_queue.length + " elements."); this._send_progress(); @@ -209,7 +213,6 @@ class QueueManager { break; } if (nb_size === 0) { - this._send_log("Placeholder vide detecte, re-rendu : " + obj_check.str_camera_name + " F" + obj_check.nb_frame); break; } obj_check.str_status = "skipped"; @@ -261,7 +264,7 @@ class QueueManager { if (!fs.existsSync(str_dir)) { fs.mkdirSync(str_dir, { recursive: true }); } - fs.writeFileSync(obj_item.str_expected_file, ""); + fs.writeFileSync(obj_item.str_expected_file, STR_PLACEHOLDER_CONTENT); } catch (obj_file_err) { this._send_log("ERREUR creation placeholder : " + obj_file_err.message); } @@ -280,6 +283,8 @@ class QueueManager { nb_resolution_y: obj_item.nb_resolution_y, str_format: obj_item.str_format, str_output_path: obj_item.str_output_path, + list_collections: this.list_collections, + obj_render_settings: this.obj_render_settings, fn_on_stdout: (str_data) => { this._send_log(str_data.trim()); }, @@ -316,7 +321,7 @@ class QueueManager { if (this.str_overwrite_mode === "skip" && fs.existsSync(obj_item.str_expected_file)) { try { let obj_stats = fs.statSync(obj_item.str_expected_file); - if (obj_stats.size === 0) { + if (obj_stats.size <= NB_PLACEHOLDER_MAX_SIZE) { fs.unlinkSync(obj_item.str_expected_file); } } catch (obj_cleanup_err) { diff --git a/src/renderer/index.html b/src/renderer/index.html index 783e322..4201522 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -33,8 +33,8 @@