|
@@ -1,6 +1,118 @@
|
|
|
/*
|
|
|
- * To change this template, choose Tools | Templates
|
|
|
- * and open the template in the editor.
|
|
|
+ Blender Options:
|
|
|
+ -b or --background <file> Load <file> in background (often used for UI-less rendering)
|
|
|
+ -a or --render-anim Render frames from start to end (inclusive)
|
|
|
+ -S or --scene <name> Set the active scene <name> for rendering
|
|
|
+ -f or --render-frame <frame> Render frame <frame> and save it. +<frame> start frame relative, -<frame> end frame relative.
|
|
|
+ -s or --frame-start <frame> Set start to frame <frame> (use before the -a argument)
|
|
|
+ -e or --frame-end <frame> Set end to frame <frame> (use before the -a argument)
|
|
|
+ -j or --frame-jump <frames> Set number of frames to step forward after each rendered frame
|
|
|
+ -o or --render-output <path> Set the render path and file name. Use // at the start of the path to
|
|
|
+ render relative to the blend file. The # characters are replaced by the frame number, and used to define zero padding.
|
|
|
+ ani_##_test.png becomes ani_01_test.png
|
|
|
+ test-######.png becomes test-000001.png
|
|
|
+ When the filename does not contain #, The suffix #### is added to the filename The frame number will be added at the end of the filename.
|
|
|
+ eg: blender -b foobar.blend -o //render_ -F PNG -x 1 -a
|
|
|
+ //render_ becomes //render_####, writing frames as //render_0001.png//
|
|
|
+ -E or --engine <engine> Specify the render engine use -E help to list available engines
|
|
|
+
|
|
|
+ Format Options:
|
|
|
+ -F or --render-format <format> Set the render format, Valid options are...
|
|
|
+ TGA IRIS JPEG MOVIE IRIZ RAWTGA
|
|
|
+ AVIRAW AVIJPEG PNG BMP FRAMESERVER (formats that can be compiled into blender, not available on all systems)
|
|
|
+ HDR TIFF EXR MULTILAYER MPEG AVICODEC QUICKTIME CINEON DPX DDS
|
|
|
+ -x or --use-extension <bool> Set option to add the file extension to the end of the file
|
|
|
+ -t or --threads <threads> Use amount of <threads> for rendering in background [1-64], 0 for systems processor count.
|
|
|
+
|
|
|
+ Animation Playback Options:
|
|
|
+ -a <options> <file(s)> Playback <file(s)>, only operates this way when not running in background.
|
|
|
+ -p <sx> <sy> Open with lower left corner at <sx>, <sy>
|
|
|
+ -m Read from disk (Don't buffer)
|
|
|
+ -f <fps> <fps-base> Specify FPS to start with
|
|
|
+ -j <frame> Set frame step to <frame>
|
|
|
+
|
|
|
+ Window Options:
|
|
|
+ -w or --window-border Force opening with borders (default)
|
|
|
+ -W or --window-borderless Force opening without borders
|
|
|
+ -p or --window-geometry <sx> <sy> <w> <h> Open with lower left corner at <sx>, <sy> and width and height as <w>, <h>
|
|
|
+ -con or --start-console Start with the console window open (ignored if -b is set)
|
|
|
+
|
|
|
+ Game Engine Specific Options:
|
|
|
+ -g Game Engine specific options
|
|
|
+ -g fixedtime Run on 50 hertz without dropping frames
|
|
|
+ -g vertexarrays Use Vertex Arrays for rendering (usually faster)
|
|
|
+ -g nomipmap No Texture Mipmapping
|
|
|
+ -g linearmipmap Linear Texture Mipmapping instead of Nearest (default)
|
|
|
+
|
|
|
+ Misc Options:
|
|
|
+ -d or --debug Turn debugging on
|
|
|
+ * Prints every operator call and their arguments
|
|
|
+ * Disables mouse grab (to interact with a debugger in some cases)
|
|
|
+ * Keeps python sys.stdin rather than setting it to None
|
|
|
+ --debug-fpe Enable floating point exceptions
|
|
|
+ --debug-ffmpeg Enable debug messages from FFmpeg library
|
|
|
+ --debug-libmv Enable debug messages from libmv library
|
|
|
+
|
|
|
+ --factory-startup Skip reading the "startup.blend" in the users home directory
|
|
|
+
|
|
|
+ --env-system-datafiles Set the BLENDER_SYSTEM_DATAFILES environment variable
|
|
|
+ --env-system-scripts Set the BLENDER_SYSTEM_SCRIPTS environment variable
|
|
|
+ --env-system-python Set the BLENDER_SYSTEM_PYTHON environment variable
|
|
|
+
|
|
|
+ -nojoystick Disable joystick support
|
|
|
+ -noglsl Disable GLSL shading
|
|
|
+ -noaudio Force sound system to None
|
|
|
+ -setaudio Force sound system to a specific device NULL SDL OPENAL JACK
|
|
|
+
|
|
|
+ -h or --help Print this help text and exit
|
|
|
+
|
|
|
+ -y or --enable-autoexec Enable automatic python script execution, (default)
|
|
|
+ -Y or --disable-autoexec Disable automatic python script execution (pydrivers & startup scripts)
|
|
|
+
|
|
|
+ -P or --python <filename> Run the given Python script (filename or Blender Text)
|
|
|
+ --python-console Run blender with an interactive console
|
|
|
+ --addons Comma separated list of addons (no spaces)
|
|
|
+ -v or --version Print Blender version and exit
|
|
|
+ -- Ends option processing, following arguments passed unchanged. Access via python's sys.argv
|
|
|
+ Other Options:
|
|
|
+ /? Print this help text and exit (windows only)
|
|
|
+ --debug-python Enable debug messages for python
|
|
|
+ --debug-events Enable debug messages for the event system
|
|
|
+ --debug-wm Enable debug messages for the window manager
|
|
|
+ --debug-all Enable all debug messages (excludes libmv)
|
|
|
+ --debug-value <value> Set debug value of <value> on startup
|
|
|
+
|
|
|
+ --debug-jobs Enable time profiling for background jobs.
|
|
|
+ --verbose <verbose> Set logging verbosity level.
|
|
|
+ -R Register .blend extension, then exit (Windows only)
|
|
|
+ -r Silently register .blend extension, then exit (Windows only)
|
|
|
+ Argument Parsing: arguments must be separated by white space. eg
|
|
|
+ "blender -ba test.blend"
|
|
|
+ ...will ignore the 'a'
|
|
|
+ "blender -b test.blend -f8"
|
|
|
+ ...will ignore 8 because there is no space between the -f and the frame value
|
|
|
+ Argument Order:
|
|
|
+ Arguments are executed in the order they are given. eg
|
|
|
+ "blender --background test.blend --render-frame 1 --render-output /tmp"
|
|
|
+ ...will not render to /tmp because '--render-frame 1' renders before the output path is set
|
|
|
+ "blender --background --render-output /tmp test.blend --render-frame 1"
|
|
|
+ ...will not render to /tmp because loading the blend file overwrites the render output that was set
|
|
|
+ "blender --background test.blend --render-output /tmp --render-frame 1" works as expected.
|
|
|
+
|
|
|
+ Environment Variables:
|
|
|
+ $BLENDER_USER_CONFIG Directory for user configuration files.
|
|
|
+ $BLENDER_USER_SCRIPTS Directory for user scripts.
|
|
|
+ $BLENDER_SYSTEM_SCRIPTS Directory for system wide scripts.
|
|
|
+ $Directory for user data files (icons, translations, ..).
|
|
|
+ $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.
|
|
|
+ $BLENDER_SYSTEM_PYTHON Directory for system python libraries.
|
|
|
+ $TMP or $TMPDIR Store temporary files here.
|
|
|
+ $SDL_AUDIODRIVER LibSDL audio driver - alsa, esd, dma.
|
|
|
+ $PYTHONHOME Path to the python directory, eg. /usr/lib/python.
|
|
|
+
|
|
|
+ blender/config
|
|
|
+ blender/scripts
|
|
|
+ blender/userscripts
|
|
|
*/
|
|
|
package com.jme3.gde.blender;
|
|
|
|
|
@@ -14,17 +126,24 @@ import java.util.logging.Logger;
|
|
|
import org.openide.DialogDisplayer;
|
|
|
import org.openide.NotifyDescriptor;
|
|
|
import org.openide.filesystems.FileObject;
|
|
|
+import org.openide.filesystems.FileUtil;
|
|
|
import org.openide.modules.InstalledFileLocator;
|
|
|
import org.openide.util.Exceptions;
|
|
|
import org.openide.util.Utilities;
|
|
|
import org.openide.windows.WindowManager;
|
|
|
-
|
|
|
+import java.awt.event.WindowEvent;
|
|
|
+import java.awt.event.WindowFocusListener;
|
|
|
/**
|
|
|
*
|
|
|
* @author normenhansen
|
|
|
*/
|
|
|
public class BlenderTool {
|
|
|
|
|
|
+ private static final String mainFolderName = "blender";
|
|
|
+ private static final String configFolderName = mainFolderName + "/config";
|
|
|
+ private static final String scriptsFolderName = mainFolderName + "/scripts";
|
|
|
+ private static final String userScriptsFolderName = mainFolderName + "/userscripts";
|
|
|
+ private static final String tempFolderName = mainFolderName + "/temp";
|
|
|
private static final Logger logger = Logger.getLogger(BlenderTool.class.getName());
|
|
|
private static boolean running = false;
|
|
|
private static Window blenderWindow = null;
|
|
@@ -37,58 +156,109 @@ public class BlenderTool {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static File getBlenderExecutable() {
|
|
|
- File blender = InstalledFileLocator.getDefault().locate("../blender/" + getBlenderExeName(), null, false);
|
|
|
- if (blender == null) {
|
|
|
- DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender executable at\n" + blender.getPath()));
|
|
|
- logger.log(Level.SEVERE, "Error finding Blender executable at {0}", blender.getPath());
|
|
|
+ private static String getBlenderOsPath() {
|
|
|
+ if (Utilities.isMac()) {
|
|
|
+ return "../blender/blender.app/Contents/MacOS";
|
|
|
+ } else {
|
|
|
+ return "../blender";
|
|
|
}
|
|
|
- return blender;
|
|
|
}
|
|
|
|
|
|
- public static File getBlenderSettingsFolder() {
|
|
|
- File blender = InstalledFileLocator.getDefault().locate("../blender/2.64", null, false);
|
|
|
+ private static boolean checkBlenderFolders() {
|
|
|
+ String jmpDir = System.getProperty("netbeans.user");
|
|
|
+ FileObject fileObject = FileUtil.toFileObject(new File(jmpDir));
|
|
|
+ if (fileObject != null) {
|
|
|
+ FileObject configFileObject = fileObject.getFileObject(configFolderName);
|
|
|
+ //TODO: using installed blender scripts folder, make more flexible by moving
|
|
|
+ //to updateable folder
|
|
|
+// FileObject scriptsFileObject = fileObject.getFileObject(scriptsFolderName);
|
|
|
+ FileObject userScriptsFileObject = fileObject.getFileObject(userScriptsFolderName);
|
|
|
+ if (configFileObject == null) {
|
|
|
+ try {
|
|
|
+ FileUtil.createFolder(fileObject, configFolderName);
|
|
|
+ } catch (IOException ex) {
|
|
|
+ Exceptions.printStackTrace(ex);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+// if (scriptsFileObject == null) {
|
|
|
+// try {
|
|
|
+// FileUtil.createFolder(fileObject, scriptsFolderName);
|
|
|
+// } catch (IOException ex) {
|
|
|
+// Exceptions.printStackTrace(ex);
|
|
|
+// return false;
|
|
|
+// }
|
|
|
+// }
|
|
|
+ if (userScriptsFileObject == null) {
|
|
|
+ try {
|
|
|
+ FileUtil.createFolder(fileObject, userScriptsFolderName);
|
|
|
+ } catch (IOException ex) {
|
|
|
+ Exceptions.printStackTrace(ex);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ logger.log(Level.SEVERE, "No global settings folder found!");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getConfigEnv() {
|
|
|
+ String ret = System.getProperty("netbeans.user") + "/" + configFolderName;
|
|
|
+ ret = ret.replace("/", File.separator);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getScriptsEnv() {
|
|
|
+ //TODO: using installed blender scripts folder
|
|
|
+ String ret = getBlenderSettingsFolder().getAbsolutePath();
|
|
|
+// String ret = System.getProperty("netbeans.user") + "/" + scriptsFolderName;
|
|
|
+ ret = ret.replace("/", File.separator);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static String getUserScriptsEnv() {
|
|
|
+ String ret = System.getProperty("netbeans.user") + "/" + userScriptsFolderName;
|
|
|
+ ret = ret.replace("/", File.separator);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static File getBlenderExecutable() {
|
|
|
+ File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath() + "/" + getBlenderExeName(), null, false);
|
|
|
if (blender == null) {
|
|
|
- DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender settings at\n" + blender.getPath()));
|
|
|
- logger.log(Level.SEVERE, "Error finding Blender settings at {0}", blender.getPath());
|
|
|
+ DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender executable"));
|
|
|
+ logger.log(Level.SEVERE, "Error finding Blender executable");
|
|
|
}
|
|
|
return blender;
|
|
|
}
|
|
|
|
|
|
- public static File getBlenderRootFolder() {
|
|
|
-// File appFolder = InstalledFileLocator.getDefault().locate("bin", null, false).getParentFile().getParentFile();
|
|
|
-// if (appFolder != null) {
|
|
|
-// DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message(appFolder.toString()));
|
|
|
-// }
|
|
|
- File blender = InstalledFileLocator.getDefault().locate("../blender", null, false);
|
|
|
+ private static File getBlenderSettingsFolder() {
|
|
|
+ File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath() + "/2.64", null, false);
|
|
|
if (blender == null) {
|
|
|
- DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender root folder at\n" + blender.getPath()));
|
|
|
- logger.log(Level.SEVERE, "Error finding Blender root folder at {0}", blender.getPath());
|
|
|
+ DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender settings"));
|
|
|
+ logger.log(Level.SEVERE, "Error finding Blender settings");
|
|
|
}
|
|
|
return blender;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- public static boolean openInBlender(FileObject file) {
|
|
|
- String path = file.getPath().replace("/", File.separator);
|
|
|
- return runBlender(path, true);
|
|
|
+ private static File getBlenderRootFolder() {
|
|
|
+ File blender = InstalledFileLocator.getDefault().locate(getBlenderOsPath(), null, false);
|
|
|
+ if (blender == null) {
|
|
|
+ DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message("Error finding Blender root folder"));
|
|
|
+ logger.log(Level.SEVERE, "Error finding Blender root folder");
|
|
|
+ }
|
|
|
+ return blender;
|
|
|
}
|
|
|
|
|
|
private static void setBlendWin(Window win) {
|
|
|
blenderWindow = win;
|
|
|
}
|
|
|
|
|
|
- public static boolean blenderToFront() {
|
|
|
- Window win = blenderWindow;
|
|
|
- if (win != null) {
|
|
|
- logger.log(Level.INFO, "Request focus of Blender window {0}", win);
|
|
|
- win.requestFocus();
|
|
|
- return true;
|
|
|
+ private static boolean runBlender(final String options, boolean async) {
|
|
|
+ if (!checkBlenderFolders()) {
|
|
|
+ logger.log(Level.SEVERE, "Could not create blender settings folders!");
|
|
|
}
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- public static boolean runBlender(final String options, boolean async) {
|
|
|
logger.log(Level.INFO, "Try running blender with options {0}", options);
|
|
|
if (running) {
|
|
|
logger.log(Level.INFO, "Blender seems to be running");
|
|
@@ -123,13 +293,13 @@ public class BlenderTool {
|
|
|
Runnable r = new Runnable() {
|
|
|
public void run() {
|
|
|
try {
|
|
|
- String command = null;
|
|
|
- if (options != null) {
|
|
|
- command = exe.getAbsolutePath() + " " + options;
|
|
|
- } else {
|
|
|
- command = exe.getAbsolutePath();
|
|
|
- }
|
|
|
- Process proc = Runtime.getRuntime().exec(command);
|
|
|
+ String command = exe.getAbsolutePath();
|
|
|
+ ProcessBuilder buildr = new ProcessBuilder(command, options);
|
|
|
+ buildr.directory(getBlenderRootFolder());
|
|
|
+ buildr.environment().put("BLENDER_USER_CONFIG", getConfigEnv());
|
|
|
+ buildr.environment().put("BLENDER_SYSTEM_SCRIPTS", getScriptsEnv());
|
|
|
+ buildr.environment().put("BLENDER_USER_SCRIPTS", getUserScriptsEnv());
|
|
|
+ Process proc = buildr.start();
|
|
|
OutputReader outReader = new OutputReader(proc.getInputStream());
|
|
|
OutputReader errReader = new OutputReader(proc.getErrorStream());
|
|
|
outReader.start();
|
|
@@ -174,6 +344,21 @@ public class BlenderTool {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ public static boolean openInBlender(FileObject file) {
|
|
|
+ String path = "'" + file.getPath().replace("/", File.separator) + "'";
|
|
|
+ return runBlender(path, true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static boolean blenderToFront() {
|
|
|
+ Window win = blenderWindow;
|
|
|
+ if (win != null) {
|
|
|
+ logger.log(Level.INFO, "Request focus of Blender window {0}", win);
|
|
|
+ win.requestFocus();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
public static void runBlender() {
|
|
|
if (!runBlender(null, true)) {
|
|
|
logger.log(Level.INFO, "Could not run blender, already running? Trying to focus window.");
|