Work in progress starting to restructure docs in preparation for next release
@@ -0,0 +1,323 @@
|
||||
Hello, world!
|
||||
=============
|
||||
|
||||
Bonsai takes a unique approach to authoring BIM data. Traditional BIM authoring
|
||||
apps create features that are tailored for a single discipline's paradigm, such
|
||||
as a 3D environment, or a spreadsheet view, and store their data structure in a
|
||||
schema that is unique to their application. In order to interoperate with
|
||||
others, there is an export or import process that translates between their
|
||||
bespoke schema to and from open data standards. The most famous ISO standard
|
||||
for BIM is IFC. After this translation, they then serialise it typically into a
|
||||
format, which may be saved to disk.
|
||||
|
||||
Bonsai does things differently.
|
||||
|
||||
Bonsai does not have its own bespoke data structure and does not import or
|
||||
export. Bonsai uses ISO open data standards directly in memory. Most commonly,
|
||||
this is IFC data. We will place a focus on IFC on this guide, but the reader
|
||||
should be aware that Bonsai also takes the same approach to dealing with other
|
||||
open data standards, like Brickschema or BCF. The same concepts will apply. We
|
||||
can call this Native OpenBIM authoring, which is a paradigm shift from
|
||||
traditional BIM which relies on translated IFC data.
|
||||
|
||||
.. image:: images/native-openbim.png
|
||||
|
||||
Every user operation reads or writes this data structure in memory, and the IFC
|
||||
data becomes the source of truth for all data. There is no such thing as an
|
||||
import or export. The data is always represented in IFC. When a BIM model is
|
||||
opened or saved, it is simply a serialisation or deserialisation operation. This
|
||||
also means that you are using Blender simply as an interface to interact with
|
||||
IFC, and the ``.blend`` container is largely unnecessary, as nothing of
|
||||
significance is stored in the Blender system, it is simply a snapshot of your
|
||||
working session.
|
||||
|
||||
Due to this significant difference, hacking on Bonsai requires knowledge not
|
||||
just about how Blender works, but also how open data standards like IFC works.
|
||||
|
||||
Just show me the code!
|
||||
----------------------
|
||||
|
||||
Sometimes, the best way to learn how to hack on a project is to just start
|
||||
hacking away. First, download the code. To keep things simple, you can download
|
||||
the source as a zip file for now, but keep in mind that sooner or later you'll
|
||||
need to :ref:`use Git to collaborate <submitting-code-to-git>`.
|
||||
|
||||
.. container:: blockbutton
|
||||
|
||||
`Download Source
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/archive/refs/heads/v0.8.0.zip>`__
|
||||
|
||||
BIM authoring is a really big topic. As a result, the Bonsai code is separated
|
||||
into modules. Each module focuses on a particular topic of BIM. Most modules
|
||||
are self-contained, but sometimes they connect to one another, just like how
|
||||
BIM works.
|
||||
|
||||
.. image:: images/module-architecture.png
|
||||
|
||||
Modules are not arbitrary divisions. They tend to reflect how portions of BIM
|
||||
data are segregated in the IFC international standard. This allows us to
|
||||
minimise the overlap between modules, so that developers can work on a single
|
||||
portion of the code with relative certainty that their actions will not affects
|
||||
other developers.
|
||||
|
||||
- `Bonsai modules <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/bonsai/bonsai/bim/module>`__
|
||||
- `IFC modules <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/ifcopenshell-python/ifcopenshell/api>`__
|
||||
|
||||
Bonsai comes with a secret **demo module** which is basically a hello world
|
||||
coding tutorial which teaches you about all the moving parts. It's far more
|
||||
interesting to read this code rather than 15 pages of abstract software
|
||||
architecture flow charts and diagrams. The code and its comments will guide you
|
||||
through the process.
|
||||
|
||||
Before playing with the demo module, you may want to switch to using a source
|
||||
installation. See `bonsai/installation <./installation.html>`_ for details.
|
||||
|
||||
To see the demo module in action, you'll need to enable it. In
|
||||
``src/bonsai/bonsai/bim/__init__.py``, uncomment the line for the demo
|
||||
module. When you restart Blender, you will see a new demo panel in your scene
|
||||
properties interface tab. Have fun!
|
||||
|
||||
.. image:: images/demo-module.png
|
||||
|
||||
Now you're ready to learn how to code! Here are all the files associated with
|
||||
the demo module. Feel free to read them in any order. Each file is heavily
|
||||
commented with explanations about what each line of code does. Change some of
|
||||
the code, reload Blender, and see what happens!
|
||||
|
||||
::
|
||||
|
||||
src/bonsai/bonsai/bim/module/demo/__init__.py
|
||||
src/bonsai/bonsai/bim/module/demo/operator.py
|
||||
src/bonsai/bonsai/bim/module/demo/prop.py
|
||||
src/bonsai/bonsai/bim/module/demo/ui.py
|
||||
src/bonsai/bonsai/bim/module/demo/data.py
|
||||
src/bonsai/bonsai/core/demo.py
|
||||
src/bonsai/bonsai/tool/demo.py
|
||||
|
||||
|
||||
Wow! That's a lot of files needed for a hello world! Don't worry, it's mostly
|
||||
tutorial comments and it's there to teach you the basics from how Blender's
|
||||
add-on system works, how interfaces work, to how Bonsai works, and how to test
|
||||
and structure it so that you can build incredibly complex features in a
|
||||
maintainable way.
|
||||
|
||||
Tests for quality checking also exist. The system is designed so that you can
|
||||
do "Test Driven Development". For reference on how to run these tests, see `bonsai/running_tests <./running_tests.html>`_
|
||||
for details. You can find the tests here:
|
||||
|
||||
::
|
||||
|
||||
src/bonsai/test/bim/feature/demo.feature
|
||||
src/bonsai/test/core/test_demo.py
|
||||
src/bonsai/test/tool/test_demo.py
|
||||
|
||||
Not all developers, especially those learning how to code, are familiar with
|
||||
testing and how to write tests. That's OK! Feel free to ignore the tests at
|
||||
first until you get a bit more comfortable with coding, and others can help
|
||||
guide you when you're ready to make the leap. Don't let this stop you from
|
||||
building things, others can also help write tests for you and clean your code.
|
||||
It's a great way to learn!
|
||||
|
||||
Once you're through, you should be able to understand how most of Bonsai is
|
||||
built and where to find things.
|
||||
|
||||
There are many Blender Python tutorials out there. A good place to start is the
|
||||
`Start coding for Blender
|
||||
<https://wiki.osarch.org/index.php?title=Start_coding_for_Blender>`__ from the
|
||||
OSArch Wiki. In addition, the Blender text editor comes with a menu called
|
||||
``Templates > Python`` which gives you a whole list of example code of how to
|
||||
create an add-on which creates objects, creates gizmos, new buttons, interfaces,
|
||||
and so on. This is a great way to try out how to build different extensions.
|
||||
|
||||
Naturally, if you just want to tweak Bonsai or build a small feature just for
|
||||
yourself, you're free to ignore this advice, skip all the tests, and just write
|
||||
half the code in a single file and it'll get the job done.
|
||||
|
||||
Software architecture
|
||||
---------------------
|
||||
|
||||
If code isn't good enough for you and you want to learn more about why the code
|
||||
is structured the way it is, here is a list of design principles we follow:
|
||||
|
||||
1. Big systems are hard to maintain. Break big systems into small systems.
|
||||
2. Separate abstract code from concrete code. Start with abstract code, and
|
||||
deal with the details later.
|
||||
3. Good code reads like poetry. Every usecase should have a poem.
|
||||
4. Separate UI code from domain logic. UI code should be as dumb as possible.
|
||||
5. Follow the Unix philosophy. We're dealing with a big industry problem here.
|
||||
Building a shared ecosystem of tools is better than one behemoth.
|
||||
6. Everything should be testable. You should be able to test first.
|
||||
7. Have different types of tests. Inversely correlate test speed and scope.
|
||||
8. Community first. Allow beginner programmers to join in the fun! Code should
|
||||
feel easy, not like a course in design pattern jargon.
|
||||
9. Incremental change, not waterfall. Don't trash and rebuild. Refactor and
|
||||
redesign one commit at a time. With each commit, ask if you're making the
|
||||
code nicer.
|
||||
10. Perfect is the enemy of the good. Half broken is better than completely
|
||||
broken.
|
||||
|
||||
The rest of this contains nasty software architecture jargon. If that's not your
|
||||
thing, stop reading now.
|
||||
|
||||
Bonsai code may be understood in three separate layers: **Delivery**,
|
||||
**Domain**, and **Data**. The Bonsai architecture separates these three layers
|
||||
from one another. Because they are separate, they can be tested and built
|
||||
separately.
|
||||
|
||||
.. image:: images/architecture.png
|
||||
|
||||
The **Delivery** mechanism is how the application is delivered to
|
||||
the user and handles user interactions. It covers the interface and triggering
|
||||
events as inputs into the application, and rendering responses.
|
||||
|
||||
As advertised in the name, the **Delivery** mechanism is based on **Blender**.
|
||||
**Blender** is a well established 3D platform. Out of the box, it provides an
|
||||
incredibly advanced interface to allow users to interact with geometry. The
|
||||
delivery mechanism code extends Blender extensively, including new *Operations*
|
||||
that users can perform, new *Properties* to store custom data, and new *UI*
|
||||
layouts to display information.
|
||||
|
||||
When an event such as an *Operation* is triggered, the **Delivery** mechanism
|
||||
executes the **Domain** layer through dependency injection. The **Domain** layer
|
||||
will then decide how to process this input.
|
||||
|
||||
The **Domain** layer is divided into two halves: an abstract *Core* and concrete
|
||||
*Tools*. The *Core* describes abstract, high-level application logic flow for
|
||||
every single possible usecase in application. The *Tools* actually implement
|
||||
this abstract logic, and figure out how things actually work, whether it is
|
||||
manipulating the Blender scene, writing and reading files, building new IFC
|
||||
graph relationships, and so on. The **Domain** layer also has interface classes
|
||||
to describe what it needs.
|
||||
|
||||
Whenever the application needs to remember or store information, it does so
|
||||
using a **Data** repository. The data ensures that stored information confirms
|
||||
to a defined schema and is valid, and can be retrieved later. Some data is
|
||||
stored in Blender, such as information about your working session and active
|
||||
scene. Other data is stored in IFC, such as all the relationships in your BIM
|
||||
model. We mention **Data** specifically because OpenBIM data authoring is such
|
||||
a big aspect of Bonsai. In fact, it's so big that most of it is completely
|
||||
separated from the Bonsai code and lives elsewhere.
|
||||
|
||||
For example, all the code that handles IFC data, which you can think of as a
|
||||
graph database, is in a completely separate codebase, even under a different
|
||||
software license. You can find it in the IfcOpenShell-python API module. Many of
|
||||
the various data processing functions are built as separate Unix-like utilities,
|
||||
even with their own CLI. This **Data** layer isn't a single folder of code we
|
||||
can point to, it's an ecosystem of libraries and utilities that we want to share
|
||||
with the entire industry.
|
||||
|
||||
IfcOpenShell Architecture
|
||||
-------------------------
|
||||
|
||||
A large part of Bonsai is understanding how IFC data is modified. This code is
|
||||
not technically part of the Bonsai codebase, but it is vital to understand. You
|
||||
will need to be familiar with the IfcOpenShell Python module.
|
||||
|
||||
Manipulating IFC data is not simple. IFC may be serialised into multiple
|
||||
formats, multiple schema versions must be supported, and geometry may be defined
|
||||
in a highly parametric or implicit manner, which geometry kernels do not
|
||||
natively support. All this heavy lifting is performed by the IfcOpenShell
|
||||
library.
|
||||
|
||||
The IfcOpenShell library consists of a C++ based core. Its geometry processing
|
||||
is done using OpenCascade, and optionally CGAL as an experimental option. By the
|
||||
time Bonsai interacts with IFC, it uses the IfcOpenShell Python bindings, so
|
||||
all IFC data is already deserialised into Python objects. The inner workings of
|
||||
the C++ base is out of scope.
|
||||
|
||||
.. image:: images/ifcopenshell-architecture.png
|
||||
|
||||
IfcOpenShell offers a core set of low-level functionality to read and write this
|
||||
data. An example of the core functionality would be:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import ifcopenshell
|
||||
model = ifcopenshell.open("foo.ifc")
|
||||
wall = model.create_entity("IfcWall")
|
||||
wall.Name = "Foobar"
|
||||
|
||||
Core functions are simple read and write operations with no post processing.
|
||||
Core functions also include geometry processing, which converts IFC geometry
|
||||
into OpenCascade objects.
|
||||
|
||||
Sometimes, there are repetitive actions that need to be performed. These
|
||||
functions are grouped into a ``util`` module. These include utility functions
|
||||
for coordinate calculations, date conversions, filtering elements, unit
|
||||
conversions, and more. Utility functions make no assumption about the context in
|
||||
which they are used, and so perform highly specific tasks and nothing else.
|
||||
Here's an example of utility functionality:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.date
|
||||
import ifcopenshell.util.geolocation
|
||||
start = ifcopenshell.util.date.ifc2datetime(task_time.ScheduleStart)
|
||||
coordinates = ifcopenshell.util.geolocation.local2global(matrix, eastings, ...)
|
||||
|
||||
When authoring, core and utility functions are usually too low-level. To cater
|
||||
for this, a high level API is provided. The API is divided into mostly isolated
|
||||
modules, each module representing a distinct set of concepts in the IFC schema.
|
||||
Unlike the util module, these API modules are highly context-sensitive, and
|
||||
assume that you intend to be authoring native IFC.
|
||||
|
||||
This context-sensitive assumption means that the functions within the modules
|
||||
are designed around typical usecases in an authoring environment. It performs
|
||||
all the necessary manipulations to achieve a domain-specific usecase. Authoring
|
||||
is complex and requires a deep knowledge of IFC to perform correctly and ensure
|
||||
that the IFC graph state is well maintained. Typically, any authoring operation
|
||||
that does not use the API is likely to contain mistakes.
|
||||
|
||||
Here's an example of it in action:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import ifcopenshell.api
|
||||
ifcopenshell.api.run("grid.create_grid_axis", model, ...)
|
||||
ifcopenshell.api.run("structural.add_structural_load", model, ...)
|
||||
|
||||
Because the API performs all the IFC manipulations to achieve a usecase, no
|
||||
further interaction is required in a typical native IFC authoring environment.
|
||||
For this reason, Bonsai only interacts with the API for its authoring
|
||||
capabilities.
|
||||
|
||||
The code for IfcOpenShell's various systems can be found here:
|
||||
|
||||
- `ifcopenshell (core) <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/ifcopenshell-python/ifcopenshell>`__
|
||||
- `ifcopenshell.util <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/ifcopenshell-python/ifcopenshell/util>`__
|
||||
- `ifcopenshell.api <https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/ifcopenshell-python/ifcopenshell/api>`__
|
||||
|
||||
.. _submitting-code-to-git:
|
||||
|
||||
Submitting code to Git
|
||||
----------------------
|
||||
|
||||
So, you've written some code, fixed a bug, made an improvement, and would like
|
||||
to get your code added to the Git repository? If your change is relatively
|
||||
small, you can submit your changes just using the Github website. Browse to the
|
||||
`IfcOpenShell repository <https://github.com/ifcopenshell/ifcopenshell>`__ and
|
||||
navigate to the file you want to edit the code of. Then just press the edit icon
|
||||
to begin editing. When you're done, you'll be prompted to submit your changes.
|
||||
|
||||
.. image:: images/github-editing.png
|
||||
|
||||
If you're making a large change, you'll need to create a **Pull Request**.
|
||||
Github has an excellent comprehensive guide on `how to contribute to projects
|
||||
<https://docs.github.com/en/get-started/quickstart/contributing-to-projects>`__
|
||||
which you can follow.
|
||||
|
||||
If you make regular contributions, you are also welcome to officially join the
|
||||
IfcOpenShell developer team, where you'll be able to make changes without
|
||||
waiting for code reviews and approvals.
|
||||
|
||||
Asking for help
|
||||
---------------
|
||||
|
||||
It's no fun to code alone! It's encouraged to reach out if there are any issues,
|
||||
if you'd like to code together with another developer, need a code review, or
|
||||
need further testing. Here are some places to reach out:
|
||||
|
||||
- `Github issues <https://github.com/IfcOpenShell/IfcOpenShell/issues>`__
|
||||
- `OSArch live chat <https://osarch.org/chat>`__
|
||||
- `OSArch community forum <https://community.osarch.org>`__
|
||||
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,16 @@
|
||||
Development
|
||||
===========
|
||||
|
||||
This chapter covers how you can help contribute to Bonsai.
|
||||
|
||||
.. container:: global-index-toc
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
:maxdepth: 2
|
||||
|
||||
hello_world
|
||||
running_tests
|
||||
translations
|
||||
undo_system
|
||||
writing_docs
|
||||
@@ -0,0 +1,178 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
There are different methods of installation, depending on your situation.
|
||||
|
||||
1. **Unstable installation** is recommended for power users helping with testing.
|
||||
2. **Bundling for Blender** is recommended for distributing the add-on.
|
||||
3. **Live development environment** is recommended for developers who are actively coding.
|
||||
4. **Packaged installation** is recommended for those who use a package manager.
|
||||
|
||||
Unstable installation
|
||||
---------------------
|
||||
|
||||
**Unstable installation** is almost the same as **Stable installation**, except
|
||||
that they are typically updated every day. Simply download a daily build from
|
||||
the `GitHub releases page
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/releases?q=bonsai&expanded=true>`__,
|
||||
then follow the usual :doc:`installation
|
||||
instructions</users/quickstart/installation>`.
|
||||
|
||||
Bonsai officially supports all major 64-bit platforms, as well as the Python
|
||||
version shipped by the Blender Foundation for the most recent three major
|
||||
Blender versions:
|
||||
|
||||
- 64-bit Linux (``linux-x64``)
|
||||
- 64-bit MacOS Intel (``macos-x64``)
|
||||
- 64-bit MacOS Silicon (``macos-arm64``)
|
||||
- 64-bit Windows (``windows-x64``)
|
||||
- Blender 4.2 with Python 3.11
|
||||
|
||||
Due to significant changes in the Blender extensions system, Blender versions
|
||||
<4.2 are not supported.
|
||||
|
||||
Developer builds may exist for different versions of Python but there will be
|
||||
no guarantee of the uptime or stability of these builds.
|
||||
|
||||
Other system specifications match the `Blender Requirements
|
||||
<https://www.blender.org/download/requirements/>`_ and the `VFX Platform
|
||||
<https://vfxplatform.com/>`_ standard.
|
||||
|
||||
Sometimes, a build may be delayed, or contain broken code. We try to avoid this,
|
||||
but it happens.
|
||||
|
||||
Bundling for Blender
|
||||
--------------------
|
||||
|
||||
Instead of waiting for an official release on the Bonsai website, it
|
||||
is possible to make your own Blender add-on from the bleeding edge source code
|
||||
of Bonsai. Bonsai is coded in Python and doesn't require any
|
||||
compilation, so this is a relatively easy process.
|
||||
|
||||
Note that Bonsai depends on IfcOpenShell, and IfcOpenShell does require
|
||||
compilation. The following instructions will use a pre-built IfcOpenShell
|
||||
(using an IfcOpenBot build) for convenience. Instructions on how to compile
|
||||
IfcOpenShell is out of scope of this document.
|
||||
|
||||
You can create your own package by using the Makefile as shown below. You can
|
||||
choose between a ``PLATFORM`` of ``linux``, ``macos``, ``macosm1``, and ``win``.
|
||||
You can choose between a ``PYVERSION`` of ``py312``, ``py311``, ``py310``, or
|
||||
``py39``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd src/bonsai
|
||||
make dist PLATFORM=linux PYVERSION=py311
|
||||
ls dist/
|
||||
|
||||
This will give you a fully packaged Blender add-on zip that you can distribute
|
||||
and install.
|
||||
|
||||
Live development environment
|
||||
----------------------------
|
||||
|
||||
One option for developers who want to actively develop from source is to follow
|
||||
the instructions from :ref:`devs/installation:Bundling for Blender`. However,
|
||||
creating a build, uninstalling the old add-on, and installing a new build is a
|
||||
slow process. Although it works, it is very slow, so we do not recommend it.
|
||||
|
||||
A more rapid approach is to follow the :ref:`devs/installation:Unstable
|
||||
installation` method, as this provides all dependencies for you out of the box.
|
||||
|
||||
Once you've done this, you can replace certain Python files that tend to be
|
||||
updated frequently with those from the Git repository. We're going to use
|
||||
symbolic links, so we can code in our Git repository, and see the changes in
|
||||
our Blender installation (you will need to restart Blender to see changes).
|
||||
|
||||
For Linux or Mac:
|
||||
|
||||
.. literalinclude:: ../../scripts/installation/dev_environment.sh
|
||||
:language: bash
|
||||
:caption: dev_environment.sh
|
||||
|
||||
Or, if you're on Windows, you can use the batch script below. You need to run
|
||||
it as an administrator. Before running it follow the instructions descibed
|
||||
in the `rem` tags.
|
||||
|
||||
.. literalinclude:: ../../scripts/installation/dev_environment.bat
|
||||
:language: bat
|
||||
:caption: dev_environment.bat
|
||||
|
||||
After you modify your code in the Git repository, you will need to restart
|
||||
Blender for the changes to take effect.
|
||||
|
||||
The downside with this approach is that if a new dependency is added, or a
|
||||
compiled dependency version requirement has changed, or the build system
|
||||
changes, you'll need to fix your setup manually. But this is relatively rare.
|
||||
Reviewing the Makefile history, `here <https://github.com/IfcOpenShell/IfcOpenShell/commits/v0.8.0/src/bonsai/Makefile>`__, is one quick way to see if a dependency has changed.
|
||||
|
||||
.. seealso::
|
||||
|
||||
There is a `useful Blender Addon
|
||||
<https://blenderartists.org/uploads/short-url/yto1sjw7pqDRVNQzpVLmn51PEDN.zip>`__
|
||||
(see `forum thread
|
||||
<https://blenderartists.org/t/reboot-blender-addon/640465/13>`__) that adds
|
||||
a Reboot button in File menu. In this way, it's possible to directly
|
||||
restart Blender and test the modified source code. There is also a VS Code
|
||||
add-on called `Blender Development
|
||||
<https://marketplace.visualstudio.com/items?itemName=JacquesLucke.blender-development>`__
|
||||
that has a similar functionality.
|
||||
|
||||
|
||||
Packaged installation
|
||||
---------------------
|
||||
|
||||
- **Arch Linux**: `Direct from Git <https://aur.archlinux.org/packages/ifcopenshell-git/>`__.
|
||||
- **Chocolatey on Windows**: `Unstable <https://community.chocolatey.org/packages/bonsai-nightly/>`__.
|
||||
|
||||
Tips for package managers
|
||||
-------------------------
|
||||
|
||||
Bonsai is fully contained in the ``bonsai/`` subfolder of the Blender add-ons
|
||||
directory. This is typically distributed as a zipfile as per Blender add-on
|
||||
conventions. Within this folder, you'll find the following file structure:
|
||||
|
||||
::
|
||||
|
||||
core/ (Blender agnostic core logic)
|
||||
tool/ (Blender specific shared functionality)
|
||||
bim/ (Blender specific UI)
|
||||
libs/ (other assets)
|
||||
wheels/ (dependencies)
|
||||
__init__.py
|
||||
|
||||
This corresponds to the structure found in the source code `here
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/bonsai/bonsai>`__.
|
||||
|
||||
Bonsai is complex, and requires many dependencies, including Python modules,
|
||||
binaries, and static assets. When packaged for users, these dependencies are
|
||||
bundled with the add-on for convenience.
|
||||
|
||||
If you choose to install Bonsai and use your own system dependencies, the
|
||||
source of truth for how dependencies are bundled are found in
|
||||
the `Makefile
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.8.0/src/bonsai/Makefile>`__
|
||||
in the ``dist`` target.
|
||||
|
||||
Add-on compatibility
|
||||
--------------------
|
||||
|
||||
Bonsai is a non-trivial add-on. By turning Blender into a graphical front-end
|
||||
to a native IFC authoring platform, some fundamental Blender features (such as
|
||||
hotkeys for basic functionality like object deletion or duplication) have been
|
||||
patched and many dependencies have been introduced.
|
||||
|
||||
Other add-ons may no longer work as intended when Bonsai is enabled, or vice
|
||||
versa, Bonsai may no longer work as intended when other add-ons are enabled.
|
||||
|
||||
Known scenarios which will lead to add-on incompatibility include:
|
||||
|
||||
- The add-on also overrides the same hotkeys. For example, if an add-on
|
||||
overrides the "X" key to delete an object, you will need to manually trigger
|
||||
(either via menu or custom hotkey) the Bonsai equivalent operator
|
||||
(e.g. IFC Delete).
|
||||
- The add-on uses object deletion or duplication macros with dictionary
|
||||
override. Note that this is also deprecated in Blender, so the other add-on
|
||||
should be updated to fix this.
|
||||
- The add-on requires a conflicting dependency, or a conflicting version of the
|
||||
same dependency. Neither add-on may work simultaneously.
|
||||
@@ -0,0 +1,140 @@
|
||||
Running tests
|
||||
=============
|
||||
|
||||
Bonsai has three layers of tests for each of its three technology layers:
|
||||
|
||||
1. **Core tests**: abstract domain logic unit tests agnostic of Blender
|
||||
2. **Tool tests**: low-level concrete unit tests dependent on Blender
|
||||
3. **UI tests**: high-level integration UI and smoke tests dependent on Blender
|
||||
|
||||
These tests use ``pytest`` as the test framework and runner, so install it:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install pytest
|
||||
|
||||
All development is expected to use test driven development, and so we expect
|
||||
test coverage to be 100% where it is technically possible to test.
|
||||
|
||||
When running tests, Makefile targets are provided for convenience so you can
|
||||
type in a simple command without knowing the internals. This means you can run
|
||||
tests by using the ``make`` command.
|
||||
|
||||
Because Bonsai depends on IfcOpenShell, it is advised to also run tests for
|
||||
IfcOpenShell and its Python bindings, which is not covered in this document.
|
||||
|
||||
Core tests
|
||||
----------
|
||||
|
||||
The core layer tests are pure Python unit tests with no dependencies on Blender
|
||||
or other modules. They are designed to be fast and easy to run as they test
|
||||
purely abstract domain logic.
|
||||
|
||||
Although they are vanilla Python tests, they do not use the Python Mock module.
|
||||
Instead, a lightweight ``Prophecy`` mocker class is used, which allows tests to
|
||||
be written in a highly concise, expressive manner. For those coming from a
|
||||
BDD background in Ruby's RSpec, PHP's PHPSpec, and PHP's Prophecy, this is very
|
||||
similar.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd src/bonsai/
|
||||
make test-core
|
||||
# If you're on Windows, and don't want to use make, use:
|
||||
pytest -p no:pytest-blender test/core
|
||||
|
||||
Tool tests
|
||||
----------
|
||||
|
||||
The tool layer tests actual concrete functions. You will need to install the
|
||||
following dependencies:
|
||||
|
||||
* pytest-blender, accessible to your system's Python
|
||||
* Blender executable, accessible to pytest-blender on your system's Python
|
||||
(e.g. through the ``blender`` command in your path)
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install pytest-blender
|
||||
# Check that "Blender" is in your system's path
|
||||
blender
|
||||
|
||||
On Windows, you can add Blender to the system path by doing:
|
||||
|
||||
1. Open the start menu and launch **Control Panel** > **System** > **Edit the
|
||||
system environment variables**
|
||||
2. In the **System Properties** window, under the **Advanced** tab press
|
||||
**Environment Variables**. This will open a dialog showing a list of all your
|
||||
variables.
|
||||
3. In the **System Variables** section select the entry named **Path**, and
|
||||
press **Edit...**. This will open a new dialog showing all the directories
|
||||
stored in the **Path** variable.
|
||||
4. Press **New** and browse to the directory where your **blender.exe** is
|
||||
located, such as in ``C:\Program Files\Blender Foundation\Blender 3.2``.
|
||||
|
||||
In addition, you will need to install these dependencies for Blender:
|
||||
|
||||
* pytest, accessible to your Blender Python
|
||||
* pytest-bdd, accessible to your Blender Python
|
||||
|
||||
You can install the dependencies by running the ``setup_pytest.py`` script in
|
||||
Blender:
|
||||
|
||||
1. Launch Blender
|
||||
2. Load ``src/bonsai/scripts/setup_pytest.py`` in the Blender text editor
|
||||
3. Run the script by pressing ``Text > Run Script``.
|
||||
4. Check the Blender console for any errors or success messages.
|
||||
|
||||
.. warning::
|
||||
|
||||
The ``scripts/setup_pytest.py`` may not work for all operating systems and
|
||||
installation environments. In this case, you may be required to install the
|
||||
dependencies manually.
|
||||
|
||||
Please be aware that some Blender may come packaged with its own Python,
|
||||
which may be separate to the Python installation on your system. Be sure to
|
||||
install the dependencies to the correct Python environment.
|
||||
|
||||
Then, run the tests. This will launch Blender headlessly and check the behaviour
|
||||
of all concrete functions.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd src/bonsai/
|
||||
make test-tool # Test everything
|
||||
make test-tool MODULE=foo # Only test a single module
|
||||
# If you're on Windows, and don't want to use make, use:
|
||||
pytest test/tool # Test everything
|
||||
pytest test/tool/test_foo.py # Only test a single module
|
||||
|
||||
UI tests
|
||||
--------
|
||||
|
||||
The UI layer acts as a full integration test.
|
||||
|
||||
Before running these tests, follow the instructions for running tool tests
|
||||
above.
|
||||
|
||||
You will also need to enable the **Sun Position** add-on, as it is required to
|
||||
test georeferencing features: ``Edit > Preferences > Add-ons`` and install
|
||||
**Lighting: Sun Position**.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd src/bonsai/
|
||||
make test-bim # Test everything
|
||||
make test-bim MODULE=foo # Only test a single module
|
||||
# If you're on Windows, and don't want to use make, use:
|
||||
pytest test/bim # Test everything
|
||||
pytest test/bim -m "foo" ./ --maxfail=1 # Only test a single module
|
||||
|
||||
Code styling
|
||||
------------
|
||||
|
||||
`Black <https://black.readthedocs.io/en/stable/index.html>`__ is used for code
|
||||
formatting. The settings for black are configured in the ``pyproject.toml`` at
|
||||
the project root. At the project root, just run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
black .
|
||||
@@ -0,0 +1,76 @@
|
||||
Translations
|
||||
============
|
||||
|
||||
Bonsai supports translations to all languages that Blender supports. We'll
|
||||
describe how you can help translate the add-on as a translator, or how you can
|
||||
ensure your strings are translatable as a developer. Translations are managed
|
||||
using a separate add-on built for this purpose.
|
||||
|
||||
1. Clone the `bonsai-translations
|
||||
<https://github.com/IfcOpenShell/bonsai-translations>`_ repository. This
|
||||
repository holds all the core translation strings in ``.po`` format.
|
||||
2. Download the `bonsai-translations add-on
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.8.0/src/bonsai/scripts/bbim_translations.py>`_
|
||||
and install it as a Blender add-on. This add-on lets you convert translation
|
||||
data to and from the ``.po`` files for Bonsai.
|
||||
3. In the **Render Properties** tab, find the **Bonsai Translations**
|
||||
panel, and browse to where you have closed the ``bonsai-translations``
|
||||
repository, and click on **Setup Translation UI**.
|
||||
|
||||
You should now see a new interface with two buttons.
|
||||
|
||||
.. image:: images/translation-panel.png
|
||||
|
||||
How to translate the add-on
|
||||
---------------------------
|
||||
|
||||
Before beginning, look inside the ``bonsai-translations`` repository for a
|
||||
``.po`` file for the language you want to translate to (e.g. ``de_DE.po`` for
|
||||
German). If this file does not yet exist, congratulations! You are the first
|
||||
person to translate to this language! Create a folder in
|
||||
``bonsai-translations`` with your language code and copy the
|
||||
``bonsai.pot`` language template file to that folder and rename it
|
||||
according to your language (e.g. for German you would copy ``bonsai.pot`` to
|
||||
``de_DE/de_DE.po``).
|
||||
|
||||
Supported language codes are:
|
||||
|
||||
.. code-block::
|
||||
|
||||
'ca_AD', 'en_US', 'es', 'fr_FR', 'ja_JP', 'sk_SK', 'cs_CZ', 'de_DE',
|
||||
'it_IT', 'ka', 'ko_KR', 'pt_BR', 'pt_PT', 'ru_RU', 'uk_UA', 'vi_VN',
|
||||
'zh_HANS', 'zh_HANT', 'ab', 'ar_EG', 'bg_BG', 'el_GR', 'eo', 'eu_EU',
|
||||
'fa_IR', 'fi_FI', 'ha', 'he_IL', 'hi_IN', 'hr_HR', 'hu_HU', 'id_ID',
|
||||
'ky_KG', 'ne_NP', 'nl_NL', 'pl_PL', 'sr_RS', 'sr_RS@latin', 'sv_SE', 'sw',
|
||||
'ta', 'th_TH', 'tr_TR'.
|
||||
|
||||
As a translator, it is recommended to translate text in bulk by modifying the
|
||||
``.po`` files directly. We recommend installing software such as `Poedit
|
||||
<https://poedit.net/>`_. These translation software offer features such as auto
|
||||
translation, suggestions, and tracking. Alternatively, you may edit the ``.po``
|
||||
file as a text file.
|
||||
|
||||
Once you have edited the relevant language's ``.po`` file, click on the
|
||||
**Update Translations From .po** button in the **Bonsai Translations**
|
||||
panel.
|
||||
|
||||
How to add new translation strings
|
||||
----------------------------------
|
||||
|
||||
When you have new strings to translate, press the **Parse Bonsai strings to
|
||||
.pot** button. This detects strings in the source code using regex patterns and
|
||||
writes out to the ``bonsai.pot`` language template file. You may then diff
|
||||
this file and propagate changes manually to all translated ``.po`` files.
|
||||
|
||||
The ``.pot`` file is only used as a blank template for users to create or
|
||||
compare ``.po`` files. The ``.po`` files are the source of truth for
|
||||
translation strings. Blender does not read from the ``.pot`` or ``.po`` files.
|
||||
Instead, Blender reads from ``bonsai/translations.py`` which contains a
|
||||
dictionary of strings formatted specifically for Blender. The
|
||||
``translations.py`` file is generated from the ``.po`` files. This is generated
|
||||
when we distribute installable packages, or when translators manually press the
|
||||
**Update Translations From .po** button.
|
||||
|
||||
.. warning::
|
||||
|
||||
Do not commit the ``translations.py`` file as it is auto-generated.
|
||||
@@ -0,0 +1,117 @@
|
||||
Undo system
|
||||
===========
|
||||
|
||||
Supporting undo and redo is quite a complex problem because the Blender undo
|
||||
system only keeps track of changes occurring in the Blender system. However,
|
||||
changes actually occur in two other locations that Blender doesn't know about:
|
||||
the IFC dataset, and the Bonsai system that synchronises Blender and the IFC
|
||||
dataset.
|
||||
|
||||
Let's see how undo works in a basic Blender add-on without IFC or Bonsai
|
||||
getting involved.
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 4
|
||||
|
||||
class Foobar(bpy.types.Operator):
|
||||
bl_idname = "foobar"
|
||||
bl_label = "Foobar"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.name = "Foobar"
|
||||
return {"FINISHED"}
|
||||
|
||||
This operation changes Blender data. The important line is ``bl_options =
|
||||
{"REGISTER", "UNDO"}``, which tells Blender to keep track of it as a single
|
||||
transaction in its undo history. When you press undo or redo, Blender figures
|
||||
out all the changes automatically and you don't need to do anything.
|
||||
|
||||
If you have an operator that only manipulates (creates, removes, or edits)
|
||||
Blender data, this solution is sufficient.
|
||||
|
||||
Now let's look at pure IfcOpenShell.
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 3,5
|
||||
|
||||
import ifcopenshell
|
||||
model = ifcopenshell.open("foo.ifc")
|
||||
model.begin_transaction()
|
||||
model.create_entity("IfcWall")
|
||||
model.end_transaction()
|
||||
model.undo()
|
||||
model.redo()
|
||||
|
||||
Pure IfcOpenShell let's you start and stop recording transactions whenever you
|
||||
want. Since IfcOpenShell has no interface, you manually run code like
|
||||
``model.undo()`` and ``model.redo()`` to undo and redo.
|
||||
|
||||
This scenario where there is pure IfcOpenShell never occurs with Bonsai.
|
||||
Instead, stuff happens in Blender operators.
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 6,7
|
||||
|
||||
class Foobar(bpy.types.Operator):
|
||||
bl_idname = "foobar"
|
||||
bl_label = "Foobar"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
return IfcStore.execute_ifc_operator(self, context)
|
||||
|
||||
def _execute(self, context):
|
||||
ifcopenshell.api.run("foo.bar", IfcStore.get_file())
|
||||
return {"FINISHED"}
|
||||
|
||||
When your operator manipulates (creates, removes, or edits) IFC data directly or
|
||||
indirectly (i.e. through calling another operator), your operator must be
|
||||
wrapped in an ``IfcStore.execute_ifc_operator`` call. This wrapper will:
|
||||
|
||||
1. Begin a Bonsai transaction
|
||||
2. Begin an IfcOpenShell transaction
|
||||
3. Run your operator's ``_execute``.
|
||||
4. End the IfcOpenShell transaction
|
||||
5. End the Bonsai transaction
|
||||
|
||||
The IfcOpenShell transaction keeps track of IFC data changes, and the Bonsai
|
||||
transaction keeps track of all other custom data changes, like changes in the
|
||||
``id_map`` and ``guid_map``. For the vast majority of operations, this wrapper
|
||||
provides everything that you need.
|
||||
|
||||
If, however, your operator manipulates data that is not tracked by Blender, is
|
||||
not tracked in the IFC data, and is not tracked in the element map, then you
|
||||
will have to write your own rollback (undo) and commit (redo) code for your
|
||||
operator. Here is an example.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class Foobar(bpy.types.Operator):
|
||||
bl_idname = "foobar"
|
||||
bl_label = "Foobar"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
IfcStore.begin_transaction(operator)
|
||||
old_value = Foo.bar
|
||||
result = self._execute(context)
|
||||
new_value = Foo.bar
|
||||
self.transaction_data = {"old_value": old_value, "new_value": new_value}
|
||||
IfcStore.add_transaction_operation(self)
|
||||
IfcStore.end_transaction(operator)
|
||||
return result
|
||||
|
||||
def _execute(self, context):
|
||||
Foo.bar = "baz"
|
||||
return {"FINISHED"}
|
||||
|
||||
def rollback(self, data):
|
||||
Foo.baz = data["old_value"]
|
||||
|
||||
def commit(self, data):
|
||||
Foo.baz = data["new_value"]
|
||||
|
||||
Note that there is still a distinction between ``execute`` and ``_execute``.
|
||||
This recommended convention allows you to quickly discern undo state tracking
|
||||
code from regular operation code.
|
||||
@@ -0,0 +1,189 @@
|
||||
Writing documentation
|
||||
=====================
|
||||
|
||||
A great way to contribute without writing code is to help writing
|
||||
documentation. Please reach out before contributing as the software is still in
|
||||
an alpha state and portions may not be worth documenting as it changes too
|
||||
frequently.
|
||||
|
||||
Philosophy
|
||||
----------
|
||||
|
||||
The documentation is split into three sections:
|
||||
|
||||
1. **Quickstart**: a crash course where a user should be able to go from
|
||||
nothing to doing the most basic, common tasks. It is not comprehensive, but
|
||||
a highly focused tutorial style "taster" of what's available. It should be
|
||||
kept very short, aiming to acquaint new users within an hour.
|
||||
2. **Guides**: a guidebook style, topic-driven series of articles discussing
|
||||
things of interest, or tutorials that cover common workflows. This should
|
||||
contain lots of images.
|
||||
3. **Reference**: a comprehensive index of the entire interface and all
|
||||
available features.
|
||||
|
||||
Documentation should not be a guide to IFC. Users should not have to know what
|
||||
IFC is.
|
||||
|
||||
Official documentation should be polished and maintained. Less documentation of
|
||||
a higher quality that is kept updated with every release is preferred to more
|
||||
documentation with stubs, incomplete or inaccurate information.
|
||||
|
||||
Syntax
|
||||
------
|
||||
|
||||
All documentation is written in ReStructured Text and is available in the
|
||||
`Bonsai docs directory
|
||||
<https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.8.0/src/bonsai/docs>`_.
|
||||
You can press the edit button on the top right on any documentation page to
|
||||
quickly edit their content.
|
||||
|
||||
Links
|
||||
^^^^^
|
||||
|
||||
You can link to
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
`external websites
|
||||
<https://docs.readthedocs.io/en/stable/guides/cross-referencing-with-sphinx.html>`_
|
||||
|
||||
(note the space between the url and the link text). You can also link to
|
||||
sections on the same page, like
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
:ref:`contribute/writing_docs:Writing technical documentation`
|
||||
|
||||
or with
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
:ref:`custom text<contribute/writing_docs:writing technical documentation>`.
|
||||
|
||||
Traditional references like
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
`Writing technical documentation`_
|
||||
|
||||
work too but are discouraged. You can link to other pages, like this:
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
:doc:`Hello World<hello_world>`
|
||||
|
||||
or sections within other pages, like this:
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
:ref:`devs/installation:unstable installation`
|
||||
|
||||
We have ``autosectionlabel`` enabled so it is not necessary to manually create labels. The depth of sections
|
||||
with automatic labels is set to 2, so the third level of titles
|
||||
will not get automatic labels to avoid duplication.
|
||||
|
||||
You can still create labels manually. This way you would ensure links still works when documentation is refactored.
|
||||
|
||||
.. code-block:: restructuredtext
|
||||
|
||||
.. _My label:
|
||||
|
||||
My Section
|
||||
==========
|
||||
|
||||
:ref:`Link to My Section <My label>`
|
||||
|
||||
This link will work across the documentation. Make sure the label is globally unique.
|
||||
|
||||
Images
|
||||
^^^^^^
|
||||
|
||||
The following colours and annotation styles should be used for annotating
|
||||
images. All stroke widths are 3px with a corner radius of 3px. Horizontal
|
||||
underlines are 5px with a corner radius of 2px. The dark green is ``39b54a`` and
|
||||
the light green is ``d9e021``.
|
||||
|
||||
.. image:: images/documentation-style.png
|
||||
|
||||
Special keywords such as **Technical Terminology** that the user should be
|
||||
aware of should be bolded, titlecased, and used consistently. You *may*
|
||||
use italics to emphasize words or phrases. Inline code must be ``quoted`` and
|
||||
longer code snippets may use code blocks.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd /path/to/bonsai
|
||||
ls
|
||||
|
||||
Be sure to specify the language to enable syntax highlighting.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
print("Hello, world!")
|
||||
|
||||
A button may be used to point users to a critical sample file or
|
||||
download.
|
||||
|
||||
.. container:: blockbutton
|
||||
|
||||
`Visit critical link <https://bonsaibim.org>`__
|
||||
|
||||
You can use bulleted lists:
|
||||
|
||||
- Like.
|
||||
- This.
|
||||
|
||||
Or ordered lists:
|
||||
|
||||
1. Like.
|
||||
2. This.
|
||||
|
||||
.. note::
|
||||
|
||||
Instead of writing "Note that XYZ ..." you should use notes sparingly to
|
||||
highlight "gotchas".
|
||||
|
||||
.. tip::
|
||||
|
||||
Tips may be used to add a useful but optional suggestion.
|
||||
|
||||
.. warning::
|
||||
|
||||
Warnings may be used to highlight common mistakes.
|
||||
|
||||
.. seealso::
|
||||
|
||||
See also blocks should be used to reference `further reading
|
||||
<https://bonsaibim.org>`__ links.
|
||||
|
||||
Tables can be very annoying to format. You can use a CSV table instead.
|
||||
|
||||
.. csv-table::
|
||||
:header: "Foo", "Bar", "Baz"
|
||||
|
||||
"ABC", "01", "02"
|
||||
"DEF", "03", "04"
|
||||
|
||||
Building documentation
|
||||
----------------------
|
||||
|
||||
If you want to build the documentation locally, the documentation system uses
|
||||
`Sphinx <https://www.sphinx-doc.org/en/master/>`_. First, install the theme and
|
||||
theme dependencies:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install furo
|
||||
pip install sphinx-autoapi
|
||||
pip install sphinx-copybutton
|
||||
|
||||
Now you can generate the documentation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd /path/to/ifcopenshell/src/bonsai/docs/
|
||||
make html
|
||||
cd _build/html
|
||||
python -m http.server
|
||||
|
||||
You will now have a local webserver running hosting the documentation.
|
||||