Blender Command line importing files - blender

I will run the script on the Blender command line. All I want to do is run the same script for several files. I have completed the steps to run a background file (.blend) and run a script in Blender, but since I have just loaded one file, I can not run the script on another file.
I looked up the Blender manual, but I could not find the command to import the file.
I proceeded to creating a .blend file and running the script.
blender -b background.blend -P pythonfile.py
In addition, if possible, I would appreciate it if you could tell me how to script the camera and track axes to track to contraint (Ctrl + T -> Track to constraint).
really thank you for reading my ask.

Blender can only have one blend file open at a time, any open scripts are cleared out when a new file is opened. What you want is a loop that starts blender for each blend file using the same script file.
On *nix systems you can use a simple shell script
#!/bin/sh
for BF in $(ls *.blend)
do
blender -b ${BF} -P pythonfile.py
done
A more cross platform solution is to use python -
from glob import glob
from subprocess import call
for blendFile in glob('*.blend'):
call([ 'blender',
'-b', blendFile,
'--python', 'pythonfile.py' ])
To add a Track-to constraint to Camera pointing it at Cube -
camera = bpy.data.objects['Camera']
c = camera.constraints.new('TRACK_TO')
c.target = bpy.data.objects['Cube']
c.track_axis = 'TRACK_NEGATIVE_Z'
c.up_axis = 'UP_Y'
This is taken from my answer here which also animates the camera going around the object.

bpy.context.view_layer.objects.active = CameraObject
bpy.ops.object.constraint_add(type='TRACK_TO')
CameraObject.constraints["Track To"].target = bpy.data.objects['ObjectToTrack']

Related

Unison: sync only in one direction ...option selected in profile

I'm effectively asking this question:
Unison: sync only in one direction
but I'd like to apply the accepted answer to a profile script. Can I do that?
unison /src/dir /dest/dir -force /src/dir -nodeletion /dest/dir
Cheers!
Yes, of course you can write that command line to the profile script.
Locate the corresponding .prf unison preferences/profile file (usually under $HOME/.unison, but please double check, this may vary depending on your OS or Unison installation)
Edit the .prf file and add the following:
# Unison preferences
label = Sync in only one direction (mirror)
root = /src/dir
root = /dest/dir
force = /src/dir # force changes from this replica to the other
nodeletion = /dest/dir # prevent file deletions on this replica
noupdate = /src/dir # prevent file updates on this replica
You can also replace step #1 above by creating a new preferences profile using the Profile Editor in the GUI, or your text editor of choice. Please remember the name and location of this file (e.g. $HOME/.unison/sync-one-direction.prf). Then you can call unison from the command line like this:
unison $HOME/.unison/sync-one-direction.prf
or
unison -i
The latter will start an interactive profile selection.
HTH

Automatically run rule when file changes in Snakemake

When working on compiled documents (LaTeX, RMarkdown, etc), I usually set up a rule for make using inotifywait to watch the input files and automatically rebuild the output file whenever the input files change.
For example:
dependencies = main.tex
main.pdf: $(dependencies)
latexmk -lualatex --shell-escape $<
watch:
while true; do inotifywait --event modify $(dependencies); $(MAKE); done
I'm now trying to migrate from make to snakemake. How can I set up something similar with snakemake?
Using Snakemake you get the power of Python. For example, you can use inotify python module to wait for updates and run the snakemake.snakemake function each time you detect updates. But it would be much easier to reuse the bash script that you have already: while true; do inotifywait --event modify $(dependencies); snakemake; done.

Run blender from command line with custom startup .blend file

I know I can change the default startup file with File/Defaults/Save Startup File. I don't want to change the default startup file, but rather call blender from the command line with a custom .blend startup file, something like:
blender --startup-file my_file.blend
I don't want to do blender my_file.blend because then I can accidentally save the file and overwrite my_file.blend, which is supposed to be a template and not an editable file. I want to get the prompt to select the filename if I attempt to save. How can I accomplish that from the command line?
https://docs.blender.org/api/current/bpy.ops.wm.html#bpy.ops.wm.read_homefile
blender --python-expr "import bpy; bpy.ops.wm.read_homefile(filepath=r'my_file.blend')"
Or as a script:
import bpy
import subprocess
path = r"D:\Desktop\test.blend"
script = "\n".join([
"import bpy",
f"bpy.ops.wm.read_homefile(filepath=r\"{path}\")"
])
subprocess.Popen([bpy.app.binary_path, "--python-expr", script])
run
blender "my_file.blend" --python "my_script.py"
and put this in my_script.py
import bpy
bpy.ops.wm.save_as_mainfile(filepath="my_new_file.blend", compress=False)
https://docs.blender.org/manual/en/latest/advanced/command_line/arguments.html#python-options
https://docs.blender.org/api/current/bpy.ops.wm.html#bpy.ops.wm.save_as_mainfile

GIMP Script.Fu script to batch convert JPEG to PNG

Can someone give me the script I would need to run to batch convert many *.jpeg files to *.png in Script.Fu in GIMP?
Currently I am spending way too much time manually exporting every image and it's a waste of time.
I can't install anything right now so can't use alternative applications.
Alright, after a lot of trials and errors I finally figured out how to convert one file format to another using only GIMP.
This is the Script-Fu script for conversion to PNG:
(
let* ((filename "{{filename}}")
(output "{{output}}")
(image (car (gimp-file-load 1 filename filename)))
(drawable (car (gimp-image-get-active-layer image))))
(file-png-save-defaults 1 image drawable output output)
)
Where {{filename}} is input file that needs to be converted (a jpeg file, for example), {{output}} is the output file that you need (it can be simply the same file name but with PNG extension)
How to run it: it can probably be improved
gimp -i -n -f -d --batch "{{one-line script-fu}}"
More about command line options you can find in GIMP online documentation.
The place that needs to be changed is {{one-line script-fu}} and it has to be... one-line! You can probably do all of this in one file using cmd (in case if you use Windows), but for me it was easier to use Python, so here's the script for it:
import subprocess, os
def convert_to_png(file_dds):
#Loads the command to run gimp cli (second code block)
#Note: remove "{{one-line script-fu}}" and leave one space after the --batch
with open("gimp-convert.bat", "r") as f:
main_script = f.read()
#Prepares the Script-Fu script to be run, replacing necessary file names and makes it one-line (the firs code block)
with open("gimp-convert-png.fu", "r") as f:
script = f.read().replace("\n", " ").replace("{{filename}}", file_dds) \
.replace("{{output}}", file_dds[:-3]+"PNG").replace("\\", "\\\\").replace("\"", "\\\"")
subprocess.run(main_script + " \"" + script + "\" --batch \"(gimp-quit 1)\"",
cwd = os.getcwd(),
shell = True)
And you should get your file converted to PNG!
I needed this for my texture upscale project, all of the code below you can find here.
Tested with GIMP 2.10
The real solution is to use ImageMagicks convert, as simple as magick convert some.jpeg some.png. There must be a "portable" version somewhere that you can use off a USB key.
Otherwise with Gimp, a much less manual way that doesn't need for a new script, since it uses an existing script:
get/install ofn-export-layers
File>Open the first JPEG
File>Open as layers more Jpegs. You can select several/all jpegs in one call (actual number limited by available RAM mostly). Once this is done you have many Jpegs stacked in the same image
File>Export all layers, making sure the name pattern you use ends in .png (the doc that comes with the script explains how that works).

Persistent Python Command-Line History

I'd like to be able to "up-arrow" to commands that I input in a previous Python interpreter. I have found the readline module which offers functions like: read_history_file, write_history_file, and set_startup_hook. I'm not quite savvy enough to put this into practice though, so could someone please help? My thoughts on the solution are:
(1) Modify .login PYTHONSTARTUP to run a python script.
(2) In that python script file do something like:
def command_history_hook():
import readline
readline.read_history_file('.python_history')
command_history_hook()
(3) Whenever the interpreter exits, write the history to the file. I guess the best way to do this is to define a function in your startup script and exit using that function:
def ex():
import readline
readline.write_history_file('.python_history')
exit()
It's very annoying to have to exit using parentheses, though: ex(). Is there some python sugar that would allow ex (without the parens) to run the ex function?
Is there a better way to cause the history file to write each time? Thanks in advance for all solutions/suggestions.
Also, there are two architectural choices as I can see. One choice is to have a unified command history. The benefit is simplicity (the alternative that follows litters your home directory with a lot of files.) The disadvantage is that interpreters you run in separate terminals will be populated with each other's command histories, and they will overwrite one another's histories. (this is okay for me since I'm usually interested in closing an interpreter and reopening one immediately to reload modules, and in that case that interpreter's commands will have been written to the file.) One possible solution to maintain separate history files per terminal is to write an environment variable for each new terminal you create:
def random_key()
''.join([choice(string.uppercase + string.digits) for i in range(16)])
def command_history_hook():
import readline
key = get_env_variable('command_history_key')
if key:
readline.read_history_file('.python_history_{0}'.format(key))
else:
set_env_variable('command_history_key', random_key())
def ex():
import readline
key = get_env_variable('command_history_key')
if not key:
set_env_variable('command_history_key', random_key())
readline.write_history_file('.python_history_{0}'.format(key))
exit()
By decreasing the random key length from 16 to say 1 you could decrease the number of files littering your directories to 36 at the expense of possible (2.8% chance) of overlap.
I think the suggestions in the Python documentation pretty much cover what you want. Look at the example pystartup file toward the end of section 13.3:
http://docs.python.org/tutorial/interactive.html
or see this page:
http://rc98.net/pystartup
But, for an out of the box interactive shell that provides all this and more, take a look at using IPython:
http://ipython.scipy.org/moin/
Try using IPython as a python shell. It already has everything you ask for. They have packages for most popular distros, so install should be very easy.
Persistent history has been supported out of the box since Python 3.4. See this bug report.
Use PIP to install the pyreadline package:
pip install pyreadline
If all you want is to use interactive history substitution without all the file stuff, all you need to do is import readline:
import readline
And then you can use the up/down keys to navigate past commands. Same for 2 or 3.
This wasn't clear to me from the docs, but maybe I missed it.