The Python File Nodes were always picking up the group owner's
`plAGMasterMod` key instead of the group's `plMsgForwarder` key. This is
fixed by using the appropriate generic method for fetching an
animation's key.
Blender's `bpy.ops.object.duplicate()` operator changes the underlying
object that's selected to be the duplicate while the code expected for
the underlying object to remain unchanged. This uses a lower-level ID
copy mechanism that should hopefully give the intended result.
There are some things that exist in `pre_export()`, eg animations, that
don't actually generate anything that needs to be memory managed. So,
it's ok if `pre_export()` isn't actually a generator function. It does
need to return either a generator or `None`, however.
Previously, this functionality was implemented in context-dependent operators. Considering that Korman is becoming increasingly complex and is now generating entirely new objects (potentially with modifiers) as part of its export process, it was becoming cumbersome to use those operators.
It is now possible to write
```python
my_object = yield create_something()
```
to ensure that temporary objects are always managed by the exporter. Previously, the more verbose
```python
my_object = create_something()
yield my_object
```
was needed.
In an attempt to address #359, I separated 3D stereo sounds into
separate emitter scene objects and allow the engine to position them
around the listener such that the left channel is actually on the left
of the listener (and the same for the right channel). Unfortunately,
this did not fix the bug in question. However, the code that interfaces
with sounds from the outside is now much simpler, and the improved
behavior is a win, IMO, so let's keep this.
This fixes review comments left on #367 that were caused by missing
pretends-to-be-a semantics. `BMeshObject` is intended to provide
pass-through access to `bpy.types.Object`'s attributes.
When a responder node is linked to a Python file node's
ptAttribNamedResponder socket, it will now export with the same name as
the node itself. In that way, the responder can be addressed in the
attribute's value mapping in the Python script itself.
Previously, the indentation level was hardcoded everywhere. This was
tedious before in that changing the log structure would require changing
many manual indentation values. Now that objects can be trivially
generated at export time, the export code might be much more nested that
before. So, it's better to let indentation be more implicit. This,
therefore, adds a context manager to increase the indentation using
`with` blocks. Manual indentation specification remains for
compatibility with Python 2.2 where required.
This adds a page type distinction. It will primarily be geared toward
things like GUIs and avatar animations. However, for now, we can abuse
it to allow externally created pages, such as those created by PRPShop
hacking (for particles) or from 3dsMax (avatar animations, GUIs, etc.)
to coexist more easily with our Korman-generated .age files.
If a sound message was being sent to a random sound modifier, the
responder tree might crash on export. This fixes that particular problem
and adds a mitigation to the responder code itself. Remember kids that,
in Python `None and True` is `None`...
This allows Region Sensor nodes to export
`plObjectInVolumeAndFacingDetector`, which only triggers the region
sensor when an avatar is in the region, facing a certain direction
(within a tolerance amount), and (optionally) moving forward.
BREAKING CHANGE: The Facing Target node can now only link to a single
condition node.
`find_input_socket()`.
It's possible that we may want to address input sockets before the
Node's `update()` method is called. In that case, we need to initialize
the socket ourselves. This is most likely to happen if you're doing
something gnawty in a Node's `init()` method.
- The object the modifier is on is now the clickable (matches the
behavior of journals).
- Improved object selector icons.
- Automatically generate a clickable region.
- Alert if no camera is set.
These attributes are strings, not paths. It is safe to format with a
path -- paths are implicitly convertible to strings by formatters. We
use a `PurePath` because we only care about getting the string name and
not actually performing any path manipulation.
This was fixed in H-uru/libhsplasma#242 originally, but Win32 APIs seem
to have terrible performance without user mode buffering, which
negatively impacted PRP loading in other tools, such as PRP Shop.
Therefore, the fix was reverted in H-uru/libhsplasma#246. This fixes the
race condition closer to the point of impact using the Win32 stream
introduced by H-uru/libhsplasma#264.