Work in progress starting to restructure docs in preparation for next release

This commit is contained in:
Dion Moult
2024-08-22 23:56:43 +10:00
parent 951b2b76a6
commit 53d7624fc4
192 changed files with 151 additions and 825 deletions
@@ -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>`__
Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

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.