Skip to content

Commit

Permalink
support Blender 2.93 LTS and Blender 3.3 LTS; demo scripts moved to u…
Browse files Browse the repository at this point in the history
…tils
  • Loading branch information
StefLab Ubuntu 20.04 committed Nov 1, 2022
1 parent 6f8368f commit e8923ad
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 23 deletions.
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@ Blender 2.8x add-on that allows streaming of data (from another computer) into B
**without** freezing the interface (publisher-subscriber pattern).

## Update
- v1.1 (2020-02-10) - **Blender 2.81+ pip support**: In Blender 2.81 pip is enabled by default.
- v1.2 (2022-11-01) - Now supports **Blender version 2.93 LTS and 3.3 LTS**! Changes:
- No Blender restart required anymore
- Python binary has to be accessed from `sys.executable` from v2.93 (rather than `bpy.app.binary_path_python`)
- Slightly refracted code in `PIPZMQ_OT_pip_pyzmq`
- Blender < 2.93 functioning unchanged
- Test scripts moved under `utils/`
- v1.1 (2020-02-10)
- **Blender 2.81+ pip support**: In Blender 2.81 pip is enabled by default.
This update takes that behavior into account. If the `Enable pip & install pyzmq` button fails, it still executes
`ensurepip.bootstrap()`. Restart Blender and try again, it will work this time
(on Windows make sure you run with admin rights).
Expand Down Expand Up @@ -32,14 +39,14 @@ You can take this add-on as an example on how to connect your own programs with


## Prerequisite
- Python (tested with 3.7, probably 2.7, 3.5+ works too) on your system with `pyzmq`
- Python (tested with 3.10, probably 2.7, 3.5+ works too) on your system with `pyzmq`
for programs outside Blender.
- Anaconda (recommended to manage Python environments)
1. Anaconda 3.7+: https://www.anaconda.com/distribution/
2. `conda create --name bzmq python=3.7` # create environment with Python 3.7
1. Anaconda 3.10+: https://www.anaconda.com/distribution/
2. `conda create --name bzmq python=3.10` # create environment with Python 3.7
3. `conda activate bzmq` # activate newly created environment
4. `conda install -c anaconda pyzmq` # install pyzmq in this environment
- System Python: `pip install pyzmq`
4. `conda install -c anaconda pyzmq=24.0` # install pyzmq in this environment
- System Python: `pip install pyzmq=24.0.*`

## How to use
1. Download this repository as a .zip by:
Expand All @@ -59,7 +66,7 @@ for programs outside Blender.
1. Get script by:
* Unziping the .zip downloaded in step 1
* In terminal: `git clone https://github.com/NumesSanguis/Blender-ZMQ-add-on`
2. Open a terminal and navigate to `cd *path*/Blender-ZMQ-add-on`
2. Open a terminal and navigate to `cd *path*/Blender-ZMQ-add-on/utils`
3. Make sure conda / virtual env is active (e.g. `conda activate bzmq`) with `pyzmq`
4. Execute: `python zmq_pub_number_gen.py` (Change ip or port by adding `--ip 192.168.x.x` and/or `--port 8080`)
1. See objects moving!
Expand Down
16 changes: 13 additions & 3 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
bl_info = {
"name": "blendzmq",
"author": "Stef van der Struijk",
"version": (1, 0),
"blender": (2, 80, 0), # also tested with 2.81
"version": (1, 2),
"blender": (3, 3, 0), # also tested with 2.81
"location": "View3D > Sidebar > Create Tab",
"description": "Connects Blender with outside programs through ZeroMQ without freezing the interface",
"warning": "",
Expand Down Expand Up @@ -57,6 +57,7 @@
from . blendzmq_props import PIPZMQProperties, ZMQSocketProperties
from . blendzmq_panel import BLENDZMQ_PT_zmqConnector
from . blendzmq_ops import SOCKET_OT_connect_subscriber, PIPZMQ_OT_pip_pyzmq
# from bpy.app.handlers import persistent


# Add-on Preferences
Expand Down Expand Up @@ -93,7 +94,15 @@ def draw(self, context):
SOCKET_OT_connect_subscriber,
BlendzmqPreferences,
BLENDZMQ_PT_zmqConnector,
)
)


# # connect socket at startup
# # prevent error: AttributeError: '_RestrictContext' object has no attribute 'view_layer'
# @persistent
# def delayed_start(scene):
# print("Delayed start function")
# bpy.ops.bbpsocket.connect_subscriber()


# one-liner to (un)register if no property registration was needed
Expand All @@ -104,6 +113,7 @@ def register():
bpy.utils.register_class(cls)
bpy.types.WindowManager.install_props = PointerProperty(type=PIPZMQProperties)
bpy.types.WindowManager.socket_settings = PointerProperty(type=ZMQSocketProperties)
# bpy.app.handlers.load_post.append(delayed_start)


def unregister():
Expand Down
52 changes: 39 additions & 13 deletions blendzmq_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,21 @@ class PIPZMQ_OT_pip_pyzmq(bpy.types.Operator):
def execute(self, context): # execute() is called when running the operator.
install_props = context.window_manager.install_props

# enable/import pip
py_exec = self.ensure_pip(install_props=install_props)
# update pip to latest version; not necessary anymore (tested 2.93 LTS & 3.3 LTS)
if bpy.app.version[0] == 2 and bpy.app.version[1] < 91:
self.update_pip(install_props=install_props, py_exec=py_exec)
# install PyZMQ
self.install_pyzmq(install_props=install_props, py_exec=py_exec)

return {'FINISHED'} # Lets Blender know the operator finished successfully

def ensure_pip(self, install_props):
# TODO check permission rights
# TODO Windows ask for permission:
# https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script

# pip in Blender:
# https://blender.stackexchange.com/questions/139718/install-pip-and-packages-from-within-blender-os-independently/
# pip 2.81 issues: https://developer.blender.org/T71856
Expand All @@ -168,6 +183,10 @@ def execute(self, context): # execute() is called when running the operator.
try:
# will likely fail the first time, but works after `ensurepip.bootstrap()` has been called once
import pip

install_props.install_status += "\nPip imported!"
self.report({'INFO'}, "Pip imported!")
# pip not enabled
except ModuleNotFoundError as e:
# only first attempt will reach here
print("Pip import failed with: ", e)
Expand All @@ -181,32 +200,41 @@ def execute(self, context): # execute() is called when running the operator.
install_props.install_status += "\nPip not activated, trying bootstrap()"
self.report({'ERROR'}, "Pip not activated, trying bootstrap()")
print("bootstrap failed with: ", e)
py_exec = bpy.app.binary_path_python

# TODO check permission rights
# TODO Windows ask for permission:
# https://stackoverflow.com/questions/130763/request-uac-elevation-from-within-a-python-script
install_props.install_status += "\nPip activated!"
self.report({'INFO'}, "Pip activated!")
# 2.81 >= Blender < 2.91
if bpy.app.version[0] == 2 and bpy.app.version[1] < 91:
py_exec = bpy.app.binary_path_python
# (tested on 2.93 LTS & 3.3 LTS) Blender >= 2.91
else:
py_exec = sys.executable

return py_exec

install_props.install_status += "\nPip activated! Updating pip..."
self.report({'INFO'}, "Pip activated! Updating pip...")
def update_pip(self, install_props, py_exec):
install_props.install_status += "\nTrying pip upgrade..."
self.report({'INFO'}, "Trying pip upgrade...")

# pip update
try:
print("Trying pip upgrade")
output = subprocess.check_output([py_exec, '-m', 'pip', 'install', '--upgrade', 'pip'])
print(output)
except subprocess.CalledProcessError as e:
install_props.install_status += "\nCouldn't update pip. Please restart Blender and try again."
self.report({'ERROR'}, "Couldn't update pip. Please restart Blender and try again.")
print(e.output)
return {'CANCELLED'}
install_props.install_status += "\nPip working! Installing pyzmq..."
self.report({'INFO'}, "Pip working! Installing pyzmq...")
install_props.install_status += "\nPip working!"
self.report({'INFO'}, "Pip working!")

def install_pyzmq(self, install_props, py_exec):
install_props.install_status += "\nTrying pyzmq install..."
self.report({'INFO'}, "Trying pyzmq install...")

# pyzmq pip install
try:
print("Trying pyzmq install")
output = subprocess.check_output([py_exec, '-m', 'pip', 'install', 'pyzmq'])
output = subprocess.check_output([py_exec, '-m', 'pip', 'install', 'pyzmq==24.0.*'])
print(output)
except subprocess.CalledProcessError as e:
install_props.install_status += "\nCouldn't install pyzmq."
Expand All @@ -217,8 +245,6 @@ def execute(self, context): # execute() is called when running the operator.
install_props.install_status += "\npyzmq installed! READY!"
self.report({'INFO'}, "pyzmq installed! READY!")

return {'FINISHED'} # Lets Blender know the operator finished successfully


def register():
bpy.utils.register_class(PIPZMQ_OT_pip_pyzmq)
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit e8923ad

Please sign in to comment.