| Name | basilisp-blender JSON |
| Version |
0.1.0
JSON |
| download |
| home_page | None |
| Summary | None |
| upload_time | 2024-08-03 12:21:07 |
| maintainer | None |
| docs_url | None |
| author | ikappaki |
| requires_python | <4.0,>=3.8 |
| license | None |
| keywords |
|
| VCS |
|
| bugtrack_url |
|
| requirements |
No requirements were recorded.
|
| Travis-CI |
No Travis.
|
| coveralls test coverage |
No coveralls.
|
[](https://pypi.org/project/basilisp-blender/) [](https://github.com/ikappaki/basilisp-blender/actions/workflows/tests-run.yml)
# Basilisp Blender Integration
[Basilisp](https://github.com/basilisp-lang/basilisp) is a Python-based Lisp implementation that offers broad compatibility with Clojure. For more details, refer to the [documentation](https://basilisp.readthedocs.io/en/latest/index.html).
## Overview
`basilisp-blender` is a Python library designed to facilitate the execution of Basilisp Clojure code within [Blender](https://www.blender.org/) and manage an nREPL server for interactive programming.
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` from Blender's Python console:
```python
import pip
pip.main(['install', 'basilisp-blender'])
```
## Usage
### Evaluating Basilisp Code
#### From a Code String
To evaluate a Basilisp code string:
```python
from basilisp_blender.eval import eval_str
eval_str("(+ 1 2)")
# => 3
```
#### From a File
To evaluate Basilisp code from a file:
```python
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:
```python
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 within Blender:
```python
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](https://docs.cider.mx/cider/index.html) or [Calva](https://calva.io/)) to automatically detect the port when `connect`'ing to the server:
```python
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](examples/) directory of this repository.
Here is an example of Basilisp code to create a torus pattern using the bpy Blender Python library:
```clojure
(ns torus-pattern
"Creates a torus pattern with randomly colored materials."
(:import bpy
math))
(def object (.. bpy/ops -object))
(def materials (.. bpy/data -materials))
(def mesh (.. bpy/ops -mesh))
(defn clear-mesh-objects []
(.select-all object ** :action "DESELECT")
(.select-by-type object ** :type "MESH")
(.delete object))
(clear-mesh-objects)
(defn create-random-material []
(let [mat (.new 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 mesh **
:major-radius radius
:minor-radius tube-radius
:location location
:major-segments segments
:minor-segments segments)
(let [obj (.. bpy/context -object)
material (create-random-material)]
(-> obj .-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})
```

# Troubleshooting
If you encounter unexplained errors, enable `DEBUG` logging and save the output to a file for inspection. For example:
```python
import logging
from basilisp_blender import log_level_set
log_level_set(logging.DEBUG, filepath="bblender.log")
```
Blender scripting [is not hread safe](https://docs.blender.org/api/current/info_gotcha.html#strange-errors-when-using-the-threading-module).
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:
```python
from basilisp_blender.nrepl import server_start
shutdown_fn = server_start(port=8889, interval_sec=0.05)
```
# Development
This package uses the [Poetry tool](https://python-poetry.org/docs/) for managing development tasks.
## Testing
You can run tests using the following command:
```bash
$ 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.
```bash
$ export BB_BLENDER_TEST_HOME="~/blender420"
# or on MS-Windows
> $env:BB_BLENDER_TEST_HOME="c:\local\blender420"
```
Then run the integration tests with
```bash
$ poetry run pytest -m integration
```
### Installing Blender and the Development Package
To download and install Blender in the directory specified by `$BB_BLENDER_TEST_HOME`, use:
```bash
$ poetry run python scripts/blender_install.py 4.2.0
```
To install the development version of the package at the same location, use:
```bash
$ poetry build # build the package
$ poetry run python scripts/bb_install.py # install it in Blender
```
Raw data
{
"_id": null,
"home_page": null,
"name": "basilisp-blender",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": null,
"author": "ikappaki",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/15/3a/d377df0ff7de77e15b2eae571eecc552828c2912266666e5214fba973c0c/basilisp_blender-0.1.0.tar.gz",
"platform": null,
"description": "[](https://pypi.org/project/basilisp-blender/) [](https://github.com/ikappaki/basilisp-blender/actions/workflows/tests-run.yml)\n\n# Basilisp Blender Integration\n\n[Basilisp](https://github.com/basilisp-lang/basilisp) is a Python-based Lisp implementation that offers broad compatibility with Clojure. For more details, refer to the [documentation](https://basilisp.readthedocs.io/en/latest/index.html).\n\n## Overview\n`basilisp-blender` is a Python library designed to facilitate the execution of Basilisp Clojure code within [Blender](https://www.blender.org/) and manage an nREPL server for interactive programming. \nThis 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.\n\n## Installation\nTo install `basilisp-blender`, use `pip` from Blender's Python console:\n\n```python\nimport pip\npip.main(['install', 'basilisp-blender'])\n```\n\n## Usage\n### Evaluating Basilisp Code\n\n#### From a Code String\nTo evaluate a Basilisp code string:\n\n```python\nfrom basilisp_blender.eval import eval_str\n\neval_str(\"(+ 1 2)\")\n# => 3\n```\n\n#### From a File\nTo evaluate Basilisp code from a file:\n\n```python\nfrom basilisp_blender.eval import eval_file\n\neval_file(\"path/to/your/code.lpy\")\n```\n\n#### From Blender\u2019s Text Editor\nTo evaluate Basilisp code contained in a Blender text editor block:\n\n```python\nfrom basilisp_blender.eval import eval_editor\n\n# Replace `text_block` with your Blender text block name\neval_editor(\"<text-block-name>\")\n```\n\n#### Starting an nREPL Server\nTo start an nREPL server within Blender:\n\n```python\nfrom basilisp_blender.nrepl import server_start\n\nshutdown_fn = server_start(host=\"127.0.0.1\", port=8889)\n```\n\nThe `host` and `port` arguments are optional.\nIf not provided, the server will bind to a random local port.\nIt will also creates an `.nrepl-port` file in the current working directory containing the port number it bound to.\n\nThe return value is a function that you can call without arguments to shut down the server.\nNote that all nREPL client sessions must be closed before this function can succesfullyl shutdown the server.\n\nFor a more convenient setup, you can specify to output `.nrepl-port` file to your Basilisp's project's root directory.\nThis allows some Clojure editor extensions (such as [CIDER](https://docs.cider.mx/cider/index.html) or [Calva](https://calva.io/)) to automatically detect the port when `connect`'ing to the server:\n\n```python\nfrom basilisp_blender.nrepl import server_start\n\nshutdown_fn = server_start(nrepl_port_filepath=\"<project-root-path>/.nrepl-port\")\n```\n\nReplace `<project-root-path>` with the path to your project's root directory.\n\n# Examples\n\nAlso see the [examples](examples/) directory of this repository.\n\nHere is an example of Basilisp code to create a torus pattern using the bpy Blender Python library:\n\n```clojure\n(ns torus-pattern\n \"Creates a torus pattern with randomly colored materials.\"\n (:import bpy\n math))\n\n(def object (.. bpy/ops -object))\n(def materials (.. bpy/data -materials))\n(def mesh (.. bpy/ops -mesh))\n\n\n(defn clear-mesh-objects []\n (.select-all object ** :action \"DESELECT\")\n (.select-by-type object ** :type \"MESH\")\n (.delete object))\n\n(clear-mesh-objects)\n\n(defn create-random-material []\n (let [mat (.new materials ** :name \"RandomMaterial\")\n _ (set! (.-use-nodes mat) true)\n bsdf (aget (.. mat -node-tree -nodes) \"Principled BSDF\")]\n\n (set! (-> bsdf .-inputs (aget \"Base Color\") .-default-value)\n [(rand) (rand) (rand) 1])\n mat))\n\n(defn create-torus [radius tube-radius location segments]\n (.primitive-torus-add mesh **\n :major-radius radius\n :minor-radius tube-radius\n :location location\n :major-segments segments\n :minor-segments segments)\n (let [obj (.. bpy/context -object)\n material (create-random-material)]\n (-> obj .-data .-materials (.append material))))\n\n#_(create-torus 5, 5, [0 0 0] 48)\n\n(defn create-pattern [{:keys [layers-num radius tube-radius]\n :or {layers-num 2\n radius 2\n tube-radius 0.2}}]\n (let [angle-step (/ math/pi 4)]\n (dotimes [i layers-num]\n (let [layer-radius (* radius (inc i))\n objects-num (* 12 (inc i))]\n (dotimes [j objects-num]\n (let [angle (* j angle-step)\n x (* layer-radius (math/cos angle))\n y (* layer-radius (math/sin angle))\n z (* i 0.5)]\n (create-torus (/ radius 2) tube-radius [x y z] 48)))))))\n\n(create-pattern {:layers-num 5})\n```\n\n\n\n# Troubleshooting\n\nIf you encounter unexplained errors, enable `DEBUG` logging and save the output to a file for inspection. For example:\n\n```python\nimport logging\nfrom basilisp_blender import log_level_set\n\nlog_level_set(logging.DEBUG, filepath=\"bblender.log\")\n```\n\nBlender scripting [is not hread safe](https://docs.blender.org/api/current/info_gotcha.html#strange-errors-when-using-the-threading-module). \nAs a result, the nREPL server cannot be started into a background thread and still expect calling `bpy` functions to work without corrupting its state.\n\nTo 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. \nThe function is run in the main Blender loop at intervals of 0.1 seconds, avoiding parallel operations that could affect Blender's state.\n\nIf necessary, you can adjust this interval to better suit your needs by passing the `interval_sec` argument to the `server_start` function:\n\n```python\nfrom basilisp_blender.nrepl import server_start\n\nshutdown_fn = server_start(port=8889, interval_sec=0.05)\n```\n\n# Development\n\nThis package uses the [Poetry tool](https://python-poetry.org/docs/) for managing development tasks.\n\n## Testing\n\nYou can run tests using the following command:\n\n```bash\n$ poetry run pytest \n```\n### Integration testing\n\nTo 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.\n\n```bash\n$ export BB_BLENDER_TEST_HOME=\"~/blender420\"\n# or on MS-Windows\n> $env:BB_BLENDER_TEST_HOME=\"c:\\local\\blender420\"\n```\nThen run the integration tests with\n\n```bash\n$ poetry run pytest -m integration\n```\n\n### Installing Blender and the Development Package\n\nTo download and install Blender in the directory specified by `$BB_BLENDER_TEST_HOME`, use:\n\n```bash\n$ poetry run python scripts/blender_install.py 4.2.0\n```\n\nTo install the development version of the package at the same location, use:\n\n```bash\n$ poetry build # build the package\n$ poetry run python scripts/bb_install.py # install it in Blender\n```\n\n\n",
"bugtrack_url": null,
"license": null,
"summary": null,
"version": "0.1.0",
"project_urls": null,
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "22695f62555908dd3ef7761b342ec7be75925174b8d9f3e5daf69b74ca967dcc",
"md5": "7245c0a179c7e405ddcafd79591b5c51",
"sha256": "30c98085bc66410fad293d07541c92bf9c2283c4a278128186ec873274129b13"
},
"downloads": -1,
"filename": "basilisp_blender-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7245c0a179c7e405ddcafd79591b5c51",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 18680,
"upload_time": "2024-08-03T12:21:06",
"upload_time_iso_8601": "2024-08-03T12:21:06.454142Z",
"url": "https://files.pythonhosted.org/packages/22/69/5f62555908dd3ef7761b342ec7be75925174b8d9f3e5daf69b74ca967dcc/basilisp_blender-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "153ad377df0ff7de77e15b2eae571eecc552828c2912266666e5214fba973c0c",
"md5": "1e44efce65f412c4b7ddb6520ac4d28c",
"sha256": "b5a5c398b1ce735b32846affa742579329ff7d3b61ae7fc43e817289f27c4525"
},
"downloads": -1,
"filename": "basilisp_blender-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "1e44efce65f412c4b7ddb6520ac4d28c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 19437,
"upload_time": "2024-08-03T12:21:07",
"upload_time_iso_8601": "2024-08-03T12:21:07.613798Z",
"url": "https://files.pythonhosted.org/packages/15/3a/d377df0ff7de77e15b2eae571eecc552828c2912266666e5214fba973c0c/basilisp_blender-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-03 12:21:07",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "basilisp-blender"
}