Skip to main content

No project description provided

Project description

PyPI CI

Basilisp Blender Integration

Basilisp is a Python-based Lisp implementation that offers broad compatibility with Clojure. For more details, refer to the documentation.

Overview

basilisp-blender is a Python library designed to facilitate the execution of Basilisp Clojure code within Blender and manage an nREPL server for interactive programming from within your editor of choice. This library provides functions to evaluate Basilisp code from Blender's Python console, file or Text Editor and to start an nREPL server, allowing seamless integration and communication with Basilisp.

Installation

To install basilisp-blender, use pip install from Python console within the Blender's Scripting workspace:

import pip
pip.main(['install', 'basilisp-blender'])

Adjust the command as needed for your environment. For instance, use -U to upgrade to the latest version or --user to install to your user directory. For additional options, refer to pip options.

Setup

nREPL server control panel

The library includes an nREPL server control panel accessible in Blender’s Properties editor, under the Output panel (icon resembling a printer). From here, users can:

  • Start and stop the server.
  • Configure the local interface address and port.
  • Specify your Basilisp project's root directory, where the .nrepl-port file will be saved for editor discovery.

nrepl cntrl panel output - ready

nrepl cntrl panel output - serving

To enable the control panel, download the latest nrepl_panel_addon_<version>.py file from the releases and install viaEdit>Preferences>Add-ons>Install From Disk.

The add-on should appear in list--be sure to check its box to activate it.

nrepl cntrl panel addon

Usage

Evaluating Basilisp Code

From a Code String

To evaluate a Basilisp code string:

from basilisp_blender.eval import eval_str

eval_str("(+ 1 2)")
# => 3

From a File

To evaluate Basilisp code from a file:

from basilisp_blender.eval import eval_file

eval_file("path/to/your/code.lpy")

From Blender’s Text Editor

To evaluate Basilisp code contained in a Blender text editor block:

from basilisp_blender.eval import eval_editor

# Replace `text_block` with your Blender text block name
eval_editor("<text-block-name>")

Starting an nREPL Server

To start an nREPL server manually within Blender:

from basilisp_blender.nrepl import server_start

shutdown_fn = server_start(host="127.0.0.1", port=8889)

The host and port arguments are optional. If not provided, the server will bind to a random local port. It will also creates an .nrepl-port file in the current working directory containing the port number it bound to.

The return value is a function that you can call without arguments to shut down the server. Note that all nREPL client sessions must be closed before this function can succesfullyl shutdown the server.

For a more convenient setup, you can specify to output .nrepl-port file to your Basilisp's project's root directory. This allows some Clojure editor extensions (such as CIDER or Calva) to automatically detect the port when connect'ing to the server:

from basilisp_blender.nrepl import server_start

shutdown_fn = server_start(nrepl_port_filepath="<project-root-path>/.nrepl-port")

Replace <project-root-path> with the path to your project's root directory.

Examples

Also see the examples directory of this repository.

Here is an example of Basilisp code to create a torus pattern using the bpy Blender Python library:

(ns torus-pattern
  "Creates a torus pattern with randomly colored materials."
  (:import bpy
           math))

(defn clear-mesh-objects []
  (.select-all     bpy.ops/object ** :action "DESELECT")
  (.select-by-type bpy.ops/object ** :type "MESH")
  (.delete         bpy.ops/object))

(clear-mesh-objects)

(defn create-random-material []
  (let [mat  (.new bpy.data/materials ** :name "RandomMaterial")
        _    (set! (.-use-nodes mat) true)
        bsdf (aget (.. mat -node-tree -nodes) "Principled BSDF")]

    (set! (-> bsdf .-inputs (aget "Base Color") .-default-value)
          [(rand) (rand) (rand) 1])
    mat))

(defn create-torus [radius tube-radius location segments]
  (.primitive-torus-add bpy.ops/mesh **
                        :major-radius radius
                        :minor-radius tube-radius
                        :location location
                        :major-segments segments
                        :minor-segments segments)
  (let [material (create-random-material)]
    (-> bpy.context/object .-data .-materials (.append material))))

#_(create-torus 5, 5, [0 0 0] 48)

(defn create-pattern [{:keys [layers-num radius tube-radius]
                       :or {layers-num 2
                            radius 2
                            tube-radius 0.2}}]
  (let [angle-step (/ math/pi 4)]
    (dotimes [i layers-num]
      (let [layer-radius (* radius (inc i))
            objects-num (* 12 (inc i))]
        (dotimes [j objects-num]
          (let [angle (* j angle-step)
                x (* layer-radius (math/cos angle))
                y (* layer-radius (math/sin angle))
                z (* i 0.5)]
            (create-torus (/ radius 2) tube-radius [x y z] 48)))))))

(create-pattern {:layers-num 5})

torus pattern example img

Troubleshooting

If you encounter unexplained errors, enable DEBUG logging and save the output to a file for inspection. For example:

import logging
from basilisp_blender import log_level_set

log_level_set(logging.DEBUG, filepath="bblender.log")

Blender scripting is not hread safe. As a result, the nREPL server cannot be started into a background thread and still expect calling bpy functions to work without corrupting its state.

To work around this limitation, the nREPL server is started in a thread, but client requests are differed into a queue that will be executed later by a bpy custom timer function. The function is run in the main Blender loop at intervals of 0.1 seconds, avoiding parallel operations that could affect Blender's state.

If necessary, you can adjust this interval to better suit your needs by passing the interval_sec argument to the server_start function:

from basilisp_blender.nrepl import server_start

shutdown_fn = server_start(port=8889, interval_sec=0.05)

Development

This package uses the Poetry tool for managing development tasks.

Testing

You can run tests using the following command:

$ poetry run pytest 

Integration testing

To run integration tests, set the $BB_BLENDER_TEST_HOME environment variable to the root directory of the Blender installation where the development package is installed. See next section on how to facilitate the installation.

$ export BB_BLENDER_TEST_HOME="~/blender420"
# or on MS-Windows
> $env:BB_BLENDER_TEST_HOME="c:\local\blender420"

Then run the integration tests with

$ poetry run pytest --integration -v

Installing Blender and the Development Package

To download and install Blender in the directory specified by $BB_BLENDER_TEST_HOME, use:

$ poetry run python scripts/blender_install.py 4.2.0

To install the development version of the package at the same location, use:

$ poetry build                                    # build the package
$ poetry run python scripts/bb_package_install.py # install it in Blender

License

This project is licensed under the Eclipse Public License 2.0. See the LICENSE file for details.

Acknowledgments

The nREPL server is a spin-off of Basilisp's basilisp.contrib.nrepl-server.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

basilisp_blender-0.3.0.tar.gz (26.7 kB view details)

Uploaded Source

Built Distribution

basilisp_blender-0.3.0-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file basilisp_blender-0.3.0.tar.gz.

File metadata

  • Download URL: basilisp_blender-0.3.0.tar.gz
  • Upload date:
  • Size: 26.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.7

File hashes

Hashes for basilisp_blender-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f42bb605d70fbc1f6b26ee0e346478f43cca6c50d2751895487e14f2bb2e18c1
MD5 6d7c971e9d4c93e4c9ce73ea2bd4e371
BLAKE2b-256 50b398e2ace1eda0fac8117c2a0bab596467ae1bcf4a7553a758177569bdb090

See more details on using hashes here.

Provenance

The following attestation bundles were made for basilisp_blender-0.3.0.tar.gz:

Publisher: release.yaml on ikappaki/basilisp-blender

Attestations:

File details

Details for the file basilisp_blender-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for basilisp_blender-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7dbe19c16041120ea8e92e5586061a4c486b6dbc6b5ed393fbcb75b8ba99f127
MD5 2fe8634bfac0d5de95360bd50b952d23
BLAKE2b-256 5d3ab4560f9abeb5d513cddbf646333b2f970d700d443eb3d55f7c2f7d4449fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for basilisp_blender-0.3.0-py3-none-any.whl:

Publisher: release.yaml on ikappaki/basilisp-blender

Attestations:

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page