Merge branch 'master' into sculpt-dev
This commit is contained in:
commit
1591c9a978
|
@ -157,8 +157,9 @@ option(WITH_BLENDER "Build blender (disable to build only the blender player)" O
|
|||
mark_as_advanced(WITH_BLENDER)
|
||||
|
||||
if(APPLE)
|
||||
# Currently this causes a build error linking, disable.
|
||||
set(WITH_BLENDER_THUMBNAILER OFF)
|
||||
# In future, can be used with `quicklookthumbnailing/qlthumbnailreply` to create file
|
||||
# thumbnails for say Finder. Turn it off for now.
|
||||
option(WITH_BLENDER_THUMBNAILER "Build \"blender-thumbnailer\" thumbnail extraction utility" OFF)
|
||||
elseif(WIN32)
|
||||
option(WITH_BLENDER_THUMBNAILER "Build \"BlendThumb.dll\" helper for Windows explorer integration" ON)
|
||||
else()
|
||||
|
|
|
@ -19,13 +19,10 @@
|
|||
set(FREETYPE_EXTRA_ARGS
|
||||
-DCMAKE_RELEASE_POSTFIX:STRING=2ST
|
||||
-DCMAKE_DEBUG_POSTFIX:STRING=2ST_d
|
||||
-DWITH_BZip2=OFF
|
||||
-DWITH_HarfBuzz=OFF
|
||||
-DFT_WITH_HARFBUZZ=OFF
|
||||
-DFT_WITH_BZIP2=OFF
|
||||
-DFT_WITH_BROTLI=ON
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE
|
||||
-DFT_DISABLE_BZIP2=ON
|
||||
-DFT_DISABLE_HARFBUZZ=ON
|
||||
-DFT_DISABLE_PNG=ON
|
||||
-DFT_REQUIRE_BROTLI=ON
|
||||
-DPC_BROTLIDEC_INCLUDEDIR=${LIBDIR}/brotli/include
|
||||
-DPC_BROTLIDEC_LIBDIR=${LIBDIR}/brotli/lib
|
||||
)
|
||||
|
|
|
@ -83,9 +83,9 @@ else()
|
|||
set(OPENEXR_VERSION_POSTFIX)
|
||||
endif()
|
||||
|
||||
set(FREETYPE_VERSION 2.11.0)
|
||||
set(FREETYPE_VERSION 2.11.1)
|
||||
set(FREETYPE_URI http://prdownloads.sourceforge.net/freetype/freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
set(FREETYPE_HASH cf09172322f6b50cf8f568bf8fe14bde)
|
||||
set(FREETYPE_HASH bd4e3b007474319909a6b79d50908e85)
|
||||
set(FREETYPE_HASH_TYPE MD5)
|
||||
set(FREETYPE_FILE freetype-${FREETYPE_VERSION}.tar.gz)
|
||||
|
||||
|
|
|
@ -4036,14 +4036,14 @@ install_DEB() {
|
|||
INFO "Forced Python building, as requested..."
|
||||
_do_compile_python=true
|
||||
else
|
||||
check_package_version_ge_lt_DEB python3-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
|
||||
check_package_version_ge_lt_DEB python${PYTHON_VERSION_SHORT}-dev $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
|
||||
if [ $? -eq 0 ]; then
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python3-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
install_packages_DEB python3-dev
|
||||
install_packages_DEB python${PYTHON_VERSION_SHORT}-dev
|
||||
clean_Python
|
||||
PRINT ""
|
||||
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_DEB python${PYTHON_VERSION_SHORT}-dev` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
for module in "${PYTHON_MODULES_PACKAGES[@]}"
|
||||
do
|
||||
module=($module)
|
||||
|
@ -4681,11 +4681,11 @@ install_RPM() {
|
|||
else
|
||||
check_package_version_ge_lt_RPM python3-devel $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
|
||||
if [ $? -eq 0 ]; then
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
install_packages_RPM python3-devel
|
||||
clean_Python
|
||||
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_RPM python3-devel` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
for module in "${PYTHON_MODULES_PACKAGES[@]}"
|
||||
do
|
||||
module=($module)
|
||||
|
@ -5224,12 +5224,12 @@ install_ARCH() {
|
|||
else
|
||||
check_package_version_ge_lt_ARCH python $PYTHON_VERSION_MIN $PYTHON_VERSION_MEX
|
||||
if [ $? -eq 0 ]; then
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
install_packages_ARCH python
|
||||
clean_Python
|
||||
PRINT ""
|
||||
|
||||
PYTHON_VERSION_INSTALLED=$(echo `get_package_version_ARCH python` | sed -r 's/^([0-9]+\.[0-9]+).*/\1/')
|
||||
|
||||
for module in "${PYTHON_MODULES_PACKAGES[@]}"
|
||||
do
|
||||
module=($module)
|
||||
|
|
|
@ -34,7 +34,7 @@ IF(NOT PYTHON_ROOT_DIR AND NOT $ENV{PYTHON_ROOT_DIR} STREQUAL "")
|
|||
SET(PYTHON_ROOT_DIR $ENV{PYTHON_ROOT_DIR})
|
||||
ENDIF()
|
||||
|
||||
SET(PYTHON_VERSION 3.9 CACHE STRING "Python Version (major and minor only)")
|
||||
SET(PYTHON_VERSION 3.10 CACHE STRING "Python Version (major and minor only)")
|
||||
MARK_AS_ADVANCED(PYTHON_VERSION)
|
||||
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ Data Access
|
|||
===========
|
||||
|
||||
The most common case for using the reference API is to find out how to access data in the blend-file.
|
||||
Before going any further its best to be aware of ID data-blocks in Blender since you will often find properties
|
||||
Before going any further it's best to be aware of ID data-blocks in Blender since you will often find properties
|
||||
relative to them.
|
||||
|
||||
|
||||
|
@ -55,9 +55,9 @@ Start by collecting the information where the data is located.
|
|||
First find this setting in the interface ``Properties editor -> Object -> Transform -> Location``.
|
||||
From the button context menu select *Online Python Reference*, this will link you to:
|
||||
:class:`bpy.types.Object.location`.
|
||||
Being an API reference, this link often gives little more information then the tooltip, though some of the pages
|
||||
Being an API reference, this link often gives little more information than the tooltip, though some of the pages
|
||||
include examples (normally at the top of the page).
|
||||
But you now know that you have to use ``.location`` and that its an array of three floats.
|
||||
But you now know that you have to use ``.location`` and that it's an array of three floats.
|
||||
|
||||
So the next step is to find out where to access objects, go down to the bottom of the page to the references section,
|
||||
for objects there are many references, but one of the most common places to access objects is via the context.
|
||||
|
@ -154,7 +154,7 @@ The tooltip includes :class:`bpy.types.SubsurfModifier.levels` but you want the
|
|||
|
||||
Note that the text copied won't include the ``bpy.data.collection["name"].`` component since its assumed that
|
||||
you won't be doing collection look-ups on every access and typically you'll want to use the context rather
|
||||
then access each :class:`bpy.types.ID` instance by name.
|
||||
than access each :class:`bpy.types.ID` instance by name.
|
||||
|
||||
Type in the ID path into a Python console :mod:`bpy.context.active_object`.
|
||||
Include the trailing dot and don't execute the code, yet.
|
||||
|
@ -252,6 +252,6 @@ Each entry can be selected, then copied :kbd:`Ctrl-C`, usually to paste in the t
|
|||
.. note::
|
||||
|
||||
Not all operators get registered for display,
|
||||
zooming the view for example isn't so useful to repeat so its excluded from the output.
|
||||
zooming the view for example isn't so useful to repeat so it's excluded from the output.
|
||||
|
||||
To display *every* operator that runs see :ref:`Show All Operators <info_show_all_operators>`.
|
||||
|
|
|
@ -229,7 +229,7 @@ removing the last items first, which is faster (as explained above):
|
|||
|
||||
|
||||
This example shows a fast way of removing items,
|
||||
for use in cases where you can alter the list order without breaking the scripts functionality.
|
||||
for use in cases where you can alter the list order without breaking the script's functionality.
|
||||
This works by swapping two list items, so the item you remove is always last:
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -278,7 +278,7 @@ Here are three ways of joining multiple strings into one string for writing.
|
|||
This also applies to any area of your code that involves a lot of string joining:
|
||||
|
||||
String concatenation
|
||||
This is the slowest option, do **not** use if you can avoid it, especially when writing data in a loop.
|
||||
This is the slowest option, do **not** use this if you can avoid it, especially when writing data in a loop.
|
||||
|
||||
>>> file.write(str1 + " " + str2 + " " + str3 + "\n")
|
||||
|
||||
|
@ -288,7 +288,7 @@ String formatting
|
|||
>>> file.write("%s %s %s\n" % (str1, str2, str3))
|
||||
|
||||
String joining
|
||||
Use to join a list of strings (the list may be temporary). In the following example, the strings are joined with
|
||||
Use this to join a list of strings (the list may be temporary). In the following example, the strings are joined with
|
||||
a space " " in between, other examples are "" or ", ".
|
||||
|
||||
>>> file.write(" ".join((str1, str2, str3, "\n")))
|
||||
|
|
|
@ -12,7 +12,7 @@ that can be troublesome and avoid practices that are known to cause instability.
|
|||
Using Operators
|
||||
===============
|
||||
|
||||
Blender's operators are tools for users to access, that can access with Python too which is very useful.
|
||||
Blender's operators are tools for users to access, that can be accessed with Python too which is very useful.
|
||||
Still operators have limitations that can make them cumbersome to script.
|
||||
|
||||
The main limits are:
|
||||
|
@ -20,13 +20,13 @@ The main limits are:
|
|||
- Can't pass data such as objects, meshes or materials to operate on (operators use the context instead).
|
||||
- The return value from calling an operator is the success (if it finished or was canceled),
|
||||
in some cases it would be more logical from an API perspective to return the result of the operation.
|
||||
- Operators poll function can fail where an API function would raise an exception giving details on exactly why.
|
||||
- Operators' poll function can fail where an API function would raise an exception giving details on exactly why.
|
||||
|
||||
|
||||
Why does an operator's poll fail?
|
||||
---------------------------------
|
||||
|
||||
When calling an operator gives an error like this:
|
||||
When calling an operator it gives an error like this:
|
||||
|
||||
>>> bpy.ops.action.clean(threshold=0.001)
|
||||
RuntimeError: Operator bpy.ops.action.clean.poll() failed, context is incorrect
|
||||
|
@ -49,9 +49,9 @@ you should be able to find the poll function with no knowledge of C.
|
|||
.. note::
|
||||
|
||||
Blender does have the functionality for poll functions to describe why they fail,
|
||||
but its currently not used much, if you're interested to help improve the API
|
||||
but it's currently not used much, if you're interested to help improve the API
|
||||
feel free to add calls to :class:`bpy.types.Operator.poll_message_set` (``CTX_wm_operator_poll_msg_set`` in C)
|
||||
where its not obvious why poll fails, e.g:
|
||||
where it's not obvious why poll fails, e.g:
|
||||
|
||||
>>> bpy.ops.gpencil.draw()
|
||||
RuntimeError: Operator bpy.ops.gpencil.draw.poll() Failed to find Grease Pencil data to draw into
|
||||
|
@ -107,7 +107,7 @@ In this case you need to call :class:`bpy.types.ViewLayer.update` after modifyin
|
|||
|
||||
|
||||
Now all dependent data (child objects, modifiers, drivers, etc.)
|
||||
has been recalculated and is available to the script within active view layer.
|
||||
have been recalculated and are available to the script within the active view layer.
|
||||
|
||||
|
||||
Can I redraw during script execution?
|
||||
|
@ -116,13 +116,13 @@ Can I redraw during script execution?
|
|||
The official answer to this is no, or... *"You don't want to do that"*.
|
||||
To give some background on the topic:
|
||||
|
||||
While a script executes Blender waits for it to finish and is effectively locked until its done,
|
||||
While a script executes, Blender waits for it to finish and is effectively locked until it's done;
|
||||
while in this state Blender won't redraw or respond to user input.
|
||||
Normally this is not such a problem because scripts distributed with Blender
|
||||
tend not to run for an extended period of time,
|
||||
nevertheless scripts *can* take a long time to complete and it would be nice to see progress in the viewport.
|
||||
|
||||
When tools lock Blender in a loop redraw are highly discouraged
|
||||
Tools that lock Blender in a loop redraw are highly discouraged
|
||||
since they conflict with Blender's ability to run multiple operators
|
||||
at once and update different parts of the interface as the tool runs.
|
||||
|
||||
|
@ -130,7 +130,7 @@ So the solution here is to write a **modal** operator, which is an operator that
|
|||
See the modal operator template in the text editor.
|
||||
Modal operators execute on user input or setup their own timers to run frequently,
|
||||
they can handle the events or pass through to be handled by the keymap or other modal operators.
|
||||
Examples of a modal operators are Transform, Painting, Fly Navigation and File Select.
|
||||
Examples of modal operators are Transform, Painting, Fly Navigation and File Select.
|
||||
|
||||
Writing modal operators takes more effort than a simple ``for`` loop
|
||||
that contains draw calls but is more flexible and integrates better with Blender's design.
|
||||
|
@ -240,7 +240,7 @@ Editing
|
|||
Editing is where the three data types vary most.
|
||||
|
||||
- Polygons are very limited for editing,
|
||||
changing materials and options like smooth works but for anything else
|
||||
changing materials and options like smooth works, but for anything else
|
||||
they are too inflexible and are only intended for storage.
|
||||
- Tessfaces should not be used for editing geometry because doing so will cause existing n-gons to be tessellated.
|
||||
- BMesh-faces are by far the best way to manipulate geometry.
|
||||
|
@ -256,7 +256,7 @@ the choice mostly depends on whether the target format supports n-gons or not.
|
|||
- Tessfaces work well for exporting to formats which don't support n-gons,
|
||||
in fact this is the only place where their use is encouraged.
|
||||
- BMesh-Faces can work for exporting too but may not be necessary if polygons can be used
|
||||
since using BMesh gives some overhead because its not the native storage format in Object-Mode.
|
||||
since using BMesh gives some overhead because it's not the native storage format in Object-Mode.
|
||||
|
||||
|
||||
Edit Bones, Pose Bones, Bone... Bones
|
||||
|
@ -348,7 +348,7 @@ Armature Mode Switching
|
|||
While writing scripts that deal with armatures you may find you have to switch between modes,
|
||||
when doing so take care when switching out of Edit-Mode not to keep references
|
||||
to the edit bones or their head/tail vectors.
|
||||
Further access to these will crash Blender so its important the script
|
||||
Further access to these will crash Blender so it's important that the script
|
||||
clearly separates sections of the code which operate in different modes.
|
||||
|
||||
This is mainly an issue with Edit-Mode since pose data can be manipulated without having to be in Pose-Mode,
|
||||
|
@ -386,11 +386,11 @@ Or with name assignment:
|
|||
Data names may not match the assigned values if they exceed the maximum length, are already used or an empty string.
|
||||
|
||||
|
||||
Its better practice not to reference objects by names at all,
|
||||
It's better practice not to reference objects by names at all,
|
||||
once created you can store the data in a list, dictionary, on a class, etc;
|
||||
there is rarely a reason to have to keep searching for the same data by name.
|
||||
|
||||
If you do need to use name references, its best to use a dictionary to maintain
|
||||
If you do need to use name references, it's best to use a dictionary to maintain
|
||||
a mapping between the names of the imported assets and the newly created data,
|
||||
this way you don't run this risk of referencing existing data from the blend-file, or worse modifying it.
|
||||
|
||||
|
@ -414,11 +414,11 @@ Library Collisions
|
|||
Blender keeps data names unique (:class:`bpy.types.ID.name`) so you can't name two objects,
|
||||
meshes, scenes, etc., the same by accident.
|
||||
However, when linking in library data from another blend-file naming collisions can occur,
|
||||
so its best to avoid referencing data by name at all.
|
||||
so it's best to avoid referencing data by name at all.
|
||||
|
||||
This can be tricky at times and not even Blender handles this correctly in some case
|
||||
This can be tricky at times and not even Blender handles this correctly in some cases
|
||||
(when selecting the modifier object for e.g. you can't select between multiple objects with the same name),
|
||||
but its still good to try avoiding these problems in this area.
|
||||
but it's still good to try avoiding these problems in this area.
|
||||
If you need to select between local and library data, there is a feature in ``bpy.data`` members to allow for this.
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -467,11 +467,11 @@ writing a script in ``latin1`` or ``iso-8859-15``.
|
|||
See `PEP 263 <https://www.python.org/dev/peps/pep-0263/>`__.
|
||||
|
||||
However, this complicates matters for Blender's Python API because ``.blend`` files don't have an explicit encoding.
|
||||
To avoid the problem for Python integration and script authors we have decided all strings in blend-files
|
||||
To avoid the problem for Python integration and script authors we have decided that all strings in blend-files
|
||||
**must** be ``UTF-8``, ``ASCII`` compatible.
|
||||
This means assigning strings with different encodings to an object names for instance will raise an error.
|
||||
This means assigning strings with different encodings to an object name, for instance, will raise an error.
|
||||
|
||||
Paths are an exception to this rule since the existence of non-UTF-8 paths on user's file system cannot be ignored.
|
||||
Paths are an exception to this rule since the existence of non-UTF-8 paths on the user's file system cannot be ignored.
|
||||
This means seemingly harmless expressions can raise errors, e.g:
|
||||
|
||||
>>> print(bpy.data.filepath)
|
||||
|
@ -505,7 +505,7 @@ to keep it short about encoding problems -- here are some suggestions:
|
|||
.. note::
|
||||
|
||||
Sometimes it's preferable to avoid string encoding issues by using bytes instead of Python strings,
|
||||
when reading some input its less trouble to read it as binary data
|
||||
when reading some input it's less trouble to read it as binary data
|
||||
though you will still need to decide how to treat any strings you want to use with Blender,
|
||||
some importers do this.
|
||||
|
||||
|
@ -679,7 +679,7 @@ Undo/Redo
|
|||
---------
|
||||
|
||||
For safety, you should assume that undo and redo always invalidates all :class:`bpy.types.ID`
|
||||
instances (Object, Scene, Mesh, Light, etc.), as weel obviously as all of their sub-data.
|
||||
instances (Object, Scene, Mesh, Light, etc.), as well obviously as all of their sub-data.
|
||||
|
||||
This example shows how you can tell undo changes the memory locations:
|
||||
|
||||
|
@ -716,7 +716,7 @@ Tools in Blender are not allowed to modify library data.
|
|||
But Python does not enforce this restriction.
|
||||
|
||||
This can be useful in some cases, using a script to adjust material values for example.
|
||||
But its also possible to use a script to make library data point to newly created local data,
|
||||
But it's also possible to use a script to make library data point to newly created local data,
|
||||
which is not supported since a call to undo will remove the local data
|
||||
but leave the library referencing it and likely crash.
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ but reference an external file rather than including it directly.
|
|||
Executing External Scripts
|
||||
--------------------------
|
||||
|
||||
This is the equivalent to running the script directly, referencing a scripts path from a two line code block.
|
||||
This is the equivalent to running the script directly, referencing a script's path from a two line code block.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
@ -124,7 +124,7 @@ small script which is often useful for testing different settings quickly.
|
|||
|
||||
The other issue with this is the script has to be in Python's module search path.
|
||||
While this is not best practice -- for testing purposes you can extend the search path,
|
||||
this following example adds the current blend-files directory to the search path
|
||||
this following example adds the current blend-file's directory to the search path
|
||||
and then loads the script as a module.
|
||||
|
||||
.. code-block:: python
|
||||
|
@ -302,7 +302,7 @@ Python Safety (Build Option)
|
|||
----------------------------
|
||||
|
||||
Since it's possible to access data which has been removed (see :doc:`Gotchas <info_gotcha>`),
|
||||
can make it hard to track down the cause of crashes.
|
||||
it can be hard to track down the cause of crashes.
|
||||
To raise Python exceptions on accessing freed data (rather than crashing),
|
||||
enable the CMake build option ``WITH_PYTHON_SAFETY``.
|
||||
This enables data tracking which makes data access about two times slower
|
||||
|
|
|
@ -417,7 +417,8 @@ MODULE_GROUPING = {
|
|||
BLENDER_REVISION = str(bpy.app.build_hash, 'utf_8')
|
||||
|
||||
# '2.83.0 Beta' or '2.83.0' or '2.83.1'
|
||||
BLENDER_VERSION_DOTS = bpy.app.version_string
|
||||
BLENDER_VERSION_STRING = bpy.app.version_string
|
||||
BLENDER_VERSION_DOTS = "%d.%d" % (bpy.app.version[0], bpy.app.version[1])
|
||||
|
||||
if BLENDER_REVISION != "Unknown":
|
||||
# SHA1 Git hash
|
||||
|
@ -1724,11 +1725,11 @@ def write_sphinx_conf_py(basepath):
|
|||
fw("import sys, os\n\n")
|
||||
fw("extensions = ['sphinx.ext.intersphinx']\n\n")
|
||||
fw("intersphinx_mapping = {'blender_manual': ('https://docs.blender.org/manual/en/dev/', None)}\n\n")
|
||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("project = 'Blender %s Python API'\n" % BLENDER_VERSION_STRING)
|
||||
fw("master_doc = 'index'\n")
|
||||
fw("copyright = u'Blender Foundation'\n")
|
||||
fw("version = '%s'\n" % BLENDER_VERSION_HASH)
|
||||
fw("release = '%s'\n" % BLENDER_VERSION_HASH)
|
||||
fw("version = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
fw("release = '%s'\n" % BLENDER_VERSION_DOTS)
|
||||
|
||||
# Quiet file not in table-of-contents warnings.
|
||||
fw("exclude_patterns = [\n")
|
||||
|
@ -1749,6 +1750,7 @@ except ModuleNotFoundError:
|
|||
|
||||
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
||||
fw(" html_theme_options = {\n")
|
||||
fw(" 'display_version': False,\n")
|
||||
# fw(" 'analytics_id': '',\n")
|
||||
# fw(" 'collapse_navigation': True,\n")
|
||||
fw(" 'sticky_navigation': False,\n")
|
||||
|
@ -1765,10 +1767,15 @@ except ModuleNotFoundError:
|
|||
fw("html_show_search_summary = True\n")
|
||||
fw("html_split_index = True\n")
|
||||
fw("html_static_path = ['static']\n")
|
||||
fw("templates_path = ['templates']\n")
|
||||
fw("html_context = {'commit': '%s'}\n" % BLENDER_VERSION_HASH)
|
||||
fw("html_extra_path = ['static/favicon.ico', 'static/blender_logo.svg']\n")
|
||||
fw("html_favicon = 'static/favicon.ico'\n")
|
||||
fw("html_logo = 'static/blender_logo.svg'\n")
|
||||
fw("html_last_updated_fmt = '%m/%d/%Y'\n\n")
|
||||
fw("if html_theme == 'sphinx_rtd_theme':\n")
|
||||
fw(" html_css_files = ['css/version_switch.css']\n")
|
||||
fw(" html_js_files = ['js/version_switch.js']\n")
|
||||
|
||||
# needed for latex, pdf gen
|
||||
fw("latex_elements = {\n")
|
||||
|
@ -2125,6 +2132,9 @@ def copy_theme_assets(basepath):
|
|||
shutil.copytree(os.path.join(SCRIPT_DIR, "static"),
|
||||
os.path.join(basepath, "static"),
|
||||
copy_function=shutil.copy)
|
||||
shutil.copytree(os.path.join(SCRIPT_DIR, "templates"),
|
||||
os.path.join(basepath, "templates"),
|
||||
copy_function=shutil.copy)
|
||||
|
||||
|
||||
def rna2sphinx(basepath):
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
/* Override RTD theme */
|
||||
.rst-versions {
|
||||
border-top: 0px;
|
||||
overflow: visible;
|
||||
}
|
||||
.version-btn.vdeact {
|
||||
cursor: default;
|
||||
color: dimgray;
|
||||
}
|
||||
|
||||
.version-btn.vdeact::after {
|
||||
content: "";
|
||||
}
|
||||
#versionwrap {
|
||||
display: flex;
|
||||
padding-top: 2px;
|
||||
font-size: 90%;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.version-btn {
|
||||
display: inline-block;
|
||||
background-color: #272525;
|
||||
width: 140px;
|
||||
text-align: center;
|
||||
padding: 3px 10px;
|
||||
margin: 0px 5px 4px;
|
||||
vertical-align: middle;
|
||||
color: #27AE60;
|
||||
border: solid 1px #444444;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
z-index: 400;
|
||||
transition: border-color 0.4s;
|
||||
}
|
||||
.version-btn::after {
|
||||
content:"\f0d8";
|
||||
display: inline;
|
||||
font: normal normal normal 16px/1 FontAwesome;
|
||||
color: #8d8c8c;
|
||||
vertical-align: top;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
.version-btn-open::after {
|
||||
color: gray;
|
||||
}
|
||||
.version-btn:hover, .version-btn:focus {
|
||||
border-color: #525252;
|
||||
}
|
||||
.version-btn-open {
|
||||
color: gray;
|
||||
border: solid 1px gray;
|
||||
}
|
||||
.version-btn.wait {
|
||||
cursor: wait;
|
||||
}
|
||||
.version-btn.disabled {
|
||||
cursor: not-allowed;
|
||||
color: dimgray;
|
||||
}
|
||||
.version-dialog {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 28px;
|
||||
width: 140px;
|
||||
margin: 0 5px;
|
||||
padding-bottom: 4px;
|
||||
background-color: #0003;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 6px #000C;
|
||||
z-index: 999;
|
||||
max-height: calc(100vh - 30px);
|
||||
overflow-y: auto;
|
||||
cursor: default;
|
||||
}
|
||||
.version-title {
|
||||
padding: 5px;
|
||||
color: black;
|
||||
text-align: center;
|
||||
font-size: 102%;
|
||||
background-color: #27ae60;
|
||||
border-bottom: solid 1.5px #444;
|
||||
}
|
||||
.version-list {
|
||||
margin-bottom: 4px;
|
||||
text-align: center;
|
||||
background-color: #000C;
|
||||
border: solid 1px gray;
|
||||
border-radius: 0px 0px 3px 3px;
|
||||
}
|
||||
.version-list a, .version-list span, .version-list li {
|
||||
position: relative;
|
||||
display: block;
|
||||
font-size: 98%;
|
||||
line-height: 1.15;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 4px 0px;
|
||||
color: #404040;
|
||||
}
|
||||
.version-list li {
|
||||
background-color: #ede9e9;
|
||||
color: #404040;
|
||||
padding: 1px;
|
||||
}
|
||||
.version-list li:hover, .version-list li a:focus {
|
||||
background-color: #b9cfda;
|
||||
}
|
||||
.version-list li.selected, .version-list li.selected:hover {
|
||||
background-color: #8d8c8c;
|
||||
}
|
||||
.version-list li.selected span {
|
||||
cursor: default;
|
||||
outline-color: red;
|
||||
}
|
||||
.version-arrow {
|
||||
position: absolute;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
left: 50%;
|
||||
bottom: 4px;
|
||||
margin-left: -4px;
|
||||
transform: rotate(225deg);
|
||||
background: #ede9e9;
|
||||
border: 1px solid gray;
|
||||
border-width: 1px 0 0 1px;
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
(function() { // switch: v1.2
|
||||
"use strict";
|
||||
|
||||
var versionsFileUrl = "https://docs.blender.org/PROD/versions.json"
|
||||
|
||||
var all_versions;
|
||||
|
||||
var Popover = function() {
|
||||
function Popover(id)
|
||||
{
|
||||
this.isOpen = false;
|
||||
this.type = (id === "version-popover");
|
||||
this.$btn = $('#' + id);
|
||||
this.$dialog = this.$btn.next();
|
||||
this.$list = this.$dialog.children("ul");
|
||||
this.sel = null;
|
||||
this.beforeInit();
|
||||
}
|
||||
|
||||
Popover.prototype = {
|
||||
beforeInit : function() {
|
||||
var that = this;
|
||||
this.$btn.on("click", function(e) {
|
||||
that.init();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
this.$btn.on("keydown", function(e) {
|
||||
if (that.btnKeyFilter(e)) {
|
||||
that.init();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
},
|
||||
init : function() {
|
||||
this.$btn.off("click");
|
||||
this.$btn.off("keydown");
|
||||
|
||||
if (all_versions === undefined) {
|
||||
this.$btn.addClass("wait");
|
||||
this.loadVL(this);
|
||||
}
|
||||
else {
|
||||
this.afterLoad();
|
||||
}
|
||||
},
|
||||
loadVL : function(that) {
|
||||
$.getJSON(versionsFileUrl, function(data) {
|
||||
all_versions = data;
|
||||
that.afterLoad();
|
||||
return true;
|
||||
}).fail(function() {
|
||||
console.log("Version Switch Error: versions.json could not be loaded.");
|
||||
that.$btn.addClass("disabled");
|
||||
return false;
|
||||
});
|
||||
},
|
||||
afterLoad : function() {
|
||||
var release = DOCUMENTATION_OPTIONS.VERSION;
|
||||
const m = release.match(/\d\.\d+/g);
|
||||
if (m) {
|
||||
release = m[0];
|
||||
}
|
||||
|
||||
this.warnOld(release, all_versions);
|
||||
|
||||
var version = this.getNamed(release);
|
||||
var list = this.buildList(version);
|
||||
|
||||
this.$list.children(":first-child").remove();
|
||||
this.$list.append(list);
|
||||
var that = this;
|
||||
this.$list.on("keydown", function(e) {
|
||||
that.keyMove(e);
|
||||
});
|
||||
|
||||
this.$btn.removeClass("wait");
|
||||
this.btnOpenHandler();
|
||||
this.$btn.on("mousedown", function(e) {
|
||||
that.btnOpenHandler();
|
||||
e.preventDefault()
|
||||
});
|
||||
this.$btn.on("keydown", function(e) {
|
||||
if (that.btnKeyFilter(e)) {
|
||||
that.btnOpenHandler();
|
||||
}
|
||||
});
|
||||
},
|
||||
warnOld : function(release, all_versions) {
|
||||
// Note this is effectively disabled now, two issues must fixed:
|
||||
// * versions.js does not contain a current entry, because that leads to
|
||||
// duplicate version numbers in the menu. These need to be deduplicated.
|
||||
// * It only shows the warning after opening the menu to switch version
|
||||
// when versions.js is loaded. This is too late to be useful.
|
||||
var current = all_versions.current
|
||||
if (!current)
|
||||
{
|
||||
// console.log("Version Switch Error: no 'current' in version.json.");
|
||||
return;
|
||||
}
|
||||
const m = current.match(/\d\.\d+/g);
|
||||
if (m) {
|
||||
current = parseFloat(m[0]);
|
||||
}
|
||||
if (release < current) {
|
||||
var currentURL = window.location.pathname.replace(release, current);
|
||||
var warning = $('<div class="admonition warning"> ' +
|
||||
'<p class="first admonition-title">Note</p> ' +
|
||||
'<p class="last"> ' +
|
||||
'You are not using the most up to date version of the documentation. ' +
|
||||
'<a href="#"></a> is the newest version.' +
|
||||
'</p>' +
|
||||
'</div>');
|
||||
|
||||
warning.find('a').attr('href', currentURL).text(current);
|
||||
|
||||
var body = $("div.body");
|
||||
if (!body.length) {
|
||||
body = $("div.document");
|
||||
}
|
||||
body.prepend(warning);
|
||||
}
|
||||
},
|
||||
buildList : function(v) {
|
||||
var url = new URL(window.location.href);
|
||||
let pathSplit = [ "", "api", v ];
|
||||
if (url.pathname.startsWith("/api/")) {
|
||||
pathSplit.push(url.pathname.split('/').slice(3).join('/'));
|
||||
}
|
||||
else {
|
||||
pathSplit.push(url.pathname.substring(1));
|
||||
}
|
||||
if (this.type) {
|
||||
var dyn = all_versions;
|
||||
var cur = v;
|
||||
}
|
||||
var buf = [];
|
||||
var that = this;
|
||||
$.each(dyn, function(ix, title) {
|
||||
buf.push("<li");
|
||||
if (ix === cur) {
|
||||
buf.push(
|
||||
' class="selected" tabindex="-1" role="presentation"><span tabindex="-1" role="menuitem" aria-current="page">' +
|
||||
title + '</spanp></li>');
|
||||
}
|
||||
else {
|
||||
pathSplit[2 + that.type] = ix;
|
||||
var href = new URL(url);
|
||||
href.pathname = pathSplit.join('/');
|
||||
buf.push(' tabindex="-1" role="presentation"><a href ="' + href + '" tabindex="-1">' +
|
||||
title + '</a></li>');
|
||||
}
|
||||
});
|
||||
return buf.join('');
|
||||
},
|
||||
getNamed : function(v) {
|
||||
$.each(all_versions, function(ix, title) {
|
||||
if (ix === "master" || ix === "latest") {
|
||||
var m = title.match(/\d\.\d[\w\d\.]*/)[0];
|
||||
if (parseFloat(m) == v) {
|
||||
v = ix;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return v;
|
||||
},
|
||||
dialogToggle : function(speed) {
|
||||
var wasClose = !this.isOpen;
|
||||
var that = this;
|
||||
if (!this.isOpen) {
|
||||
this.$btn.addClass("version-btn-open");
|
||||
this.$btn.attr("aria-pressed", true);
|
||||
this.$dialog.attr("aria-hidden", false);
|
||||
this.$dialog.fadeIn(speed, function() {
|
||||
that.$btn.parent().on("focusout", function(e) {
|
||||
that.focusoutHandler();
|
||||
e.stopImmediatePropagation();
|
||||
})
|
||||
that.$btn.parent().on("mouseleave", function(e) {
|
||||
that.mouseoutHandler();
|
||||
e.stopImmediatePropagation();
|
||||
});
|
||||
});
|
||||
this.isOpen = true;
|
||||
}
|
||||
else {
|
||||
this.$btn.removeClass("version-btn-open");
|
||||
this.$btn.attr("aria-pressed", false);
|
||||
this.$dialog.attr("aria-hidden", true);
|
||||
this.$btn.parent().off("focusout");
|
||||
this.$btn.parent().off("mouseleave");
|
||||
this.$dialog.fadeOut(speed, function() {
|
||||
if (this.$sel) {
|
||||
this.$sel.attr("tabindex", -1);
|
||||
}
|
||||
that.$btn.attr("tabindex", 0);
|
||||
if (document.activeElement !== null && document.activeElement !== document &&
|
||||
document.activeElement !== document.body) {
|
||||
that.$btn.focus();
|
||||
}
|
||||
});
|
||||
this.isOpen = false;
|
||||
}
|
||||
|
||||
if (wasClose) {
|
||||
if (this.$sel) {
|
||||
this.$sel.attr("tabindex", -1);
|
||||
}
|
||||
if (document.activeElement !== null && document.activeElement !== document &&
|
||||
document.activeElement !== document.body) {
|
||||
var $nw = this.listEnter();
|
||||
$nw.attr("tabindex", 0);
|
||||
$nw.focus();
|
||||
this.$sel = $nw;
|
||||
}
|
||||
}
|
||||
},
|
||||
btnOpenHandler : function() {
|
||||
this.dialogToggle(300);
|
||||
},
|
||||
focusoutHandler : function() {
|
||||
var list = this.$list;
|
||||
var that = this;
|
||||
setTimeout(function() {
|
||||
if (list.find(":focus").length === 0) {
|
||||
that.dialogToggle(200);
|
||||
}
|
||||
}, 200);
|
||||
},
|
||||
mouseoutHandler : function() {
|
||||
this.dialogToggle(200);
|
||||
},
|
||||
btnKeyFilter : function(e) {
|
||||
if (e.ctrlKey || e.shiftKey) {
|
||||
return false;
|
||||
}
|
||||
if (e.key === " " || e.key === "Enter" || (e.key === "ArrowDown" && e.altKey) ||
|
||||
e.key === "ArrowDown" || e.key === "ArrowUp") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
keyMove : function(e) {
|
||||
if (e.ctrlKey || e.shiftKey) {
|
||||
return true;
|
||||
}
|
||||
var p = true;
|
||||
var $nw = $(e.target);
|
||||
switch (e.key) {
|
||||
case "ArrowUp":
|
||||
$nw = this.listPrev($nw);
|
||||
break;
|
||||
case "ArrowDown":
|
||||
$nw = this.listNext($nw);
|
||||
break;
|
||||
case "Home":
|
||||
$nw = this.listFirst();
|
||||
break;
|
||||
case "End":
|
||||
$nw = this.listLast();
|
||||
break;
|
||||
case "Escape":
|
||||
$nw = this.listExit();
|
||||
break;
|
||||
case "ArrowLeft":
|
||||
$nw = this.listExit();
|
||||
break;
|
||||
case "ArrowRight":
|
||||
$nw = this.listExit();
|
||||
break;
|
||||
default:
|
||||
p = false;
|
||||
}
|
||||
if (p) {
|
||||
$nw.attr("tabindex", 0);
|
||||
$nw.focus();
|
||||
if (this.$sel) {
|
||||
this.$sel.attr("tabindex", -1);
|
||||
}
|
||||
this.$sel = $nw;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
listPrev : function($nw) {
|
||||
if ($nw.parent().prev().length !== 0) {
|
||||
return $nw.parent().prev().children(":first-child");
|
||||
}
|
||||
else {
|
||||
return this.listLast();
|
||||
}
|
||||
},
|
||||
listNext : function($nw) {
|
||||
if ($nw.parent().next().length !== 0) {
|
||||
return $nw.parent().next().children(":first-child");
|
||||
}
|
||||
else {
|
||||
return this.listFirst();
|
||||
}
|
||||
},
|
||||
listFirst : function() {
|
||||
return this.$list.children(":first-child").children(":first-child");
|
||||
},
|
||||
listLast : function() {
|
||||
return this.$list.children(":last-child").children(":first-child");
|
||||
},
|
||||
listExit : function() {
|
||||
this.mouseoutHandler();
|
||||
return this.$btn;
|
||||
},
|
||||
listEnter : function() {
|
||||
return this.$list.children(":first-child").children(":first-child");
|
||||
}
|
||||
};
|
||||
return Popover
|
||||
}();
|
||||
|
||||
$(document).ready(function() {
|
||||
var lng_popover = new Popover("version-popover");
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,17 @@
|
|||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="document versions">
|
||||
<ul id="versionwrap" role="presentation">
|
||||
<li role="presentation">
|
||||
<span id="version-popover" class="version-btn" tabindex="0" role="button" aria-label="versions selector" aria-haspopup="true" aria-controls="version-vsnlist" aria-disabled="true">
|
||||
{{ release }}
|
||||
</span>
|
||||
<div class="version-dialog" aria-hidden="true">
|
||||
<div class="version-arrow" aria-hidden="true"></div>
|
||||
<div class="version-title">Versions</div>
|
||||
<ul id="version-vsnlist" class="version-list" role="menu" aria-labelledby="version-popover" aria-hidden="true">
|
||||
<li role="presentation">Loading...</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -74,7 +74,7 @@ enum_panorama_types = (
|
|||
"Similar to most fisheye modern lens, takes sensor dimensions into consideration"),
|
||||
('MIRRORBALL', "Mirror Ball", "Uses the mirror ball mapping"),
|
||||
('FISHEYE_LENS_POLYNOMIAL', "Fisheye Lens Polynomial",
|
||||
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked."),
|
||||
"Defines the lens projection as polynomial to allow real world camera lenses to be mimicked"),
|
||||
)
|
||||
|
||||
enum_curve_shape = (
|
||||
|
@ -901,27 +901,27 @@ class CyclesCameraSettings(bpy.types.PropertyGroup):
|
|||
|
||||
fisheye_polynomial_k0: FloatProperty(
|
||||
name="Fisheye Polynomial K0",
|
||||
description="Coefficient K0 of the lens polinomial",
|
||||
description="Coefficient K0 of the lens polynomial",
|
||||
default=camera.default_fisheye_polynomial[0], precision=6, step=0.1, subtype='ANGLE',
|
||||
)
|
||||
fisheye_polynomial_k1: FloatProperty(
|
||||
name="Fisheye Polynomial K1",
|
||||
description="Coefficient K1 of the lens polinomial",
|
||||
description="Coefficient K1 of the lens polynomial",
|
||||
default=camera.default_fisheye_polynomial[1], precision=6, step=0.1, subtype='ANGLE',
|
||||
)
|
||||
fisheye_polynomial_k2: FloatProperty(
|
||||
name="Fisheye Polynomial K2",
|
||||
description="Coefficient K2 of the lens polinomial",
|
||||
description="Coefficient K2 of the lens polynomial",
|
||||
default=camera.default_fisheye_polynomial[2], precision=6, step=0.1, subtype='ANGLE',
|
||||
)
|
||||
fisheye_polynomial_k3: FloatProperty(
|
||||
name="Fisheye Polynomial K3",
|
||||
description="Coefficient K3 of the lens polinomial",
|
||||
description="Coefficient K3 of the lens polynomial",
|
||||
default=camera.default_fisheye_polynomial[3], precision=6, step=0.1, subtype='ANGLE',
|
||||
)
|
||||
fisheye_polynomial_k4: FloatProperty(
|
||||
name="Fisheye Polynomial K4",
|
||||
description="Coefficient K4 of the lens polinomial",
|
||||
description="Coefficient K4 of the lens polynomial",
|
||||
default=camera.default_fisheye_polynomial[4], precision=6, step=0.1, subtype='ANGLE',
|
||||
)
|
||||
|
||||
|
|
|
@ -669,7 +669,7 @@ class CYCLES_RENDER_PT_performance_acceleration_structure(CyclesButtonsPanel, Pa
|
|||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return not use_optix(context) or has_multi_device(context)
|
||||
return not use_optix(context) or use_multi_device(context)
|
||||
|
||||
def draw(self, context):
|
||||
import _cycles
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "blender/sync.h"
|
||||
#include "blender/util.h"
|
||||
|
||||
|
@ -624,15 +626,36 @@ void BlenderSync::sync_particle_hair(
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_HAIR_NODES
|
||||
static float4 hair_point_as_float4(BL::HairPoint b_point)
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
|
||||
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves)
|
||||
{
|
||||
float4 mP = float3_to_float4(get_float3(b_point.co()));
|
||||
mP.w = b_point.radius();
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.domain() != BL::Attribute::domain_POINT) {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
|
||||
continue;
|
||||
}
|
||||
return BL::FloatAttribute{b_attribute};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static float4 hair_point_as_float4(BL::Curves b_curves,
|
||||
std::optional<BL::FloatAttribute> b_attr_radius,
|
||||
const int index)
|
||||
{
|
||||
float4 mP = float3_to_float4(get_float3(b_curves.position_data[index].vector()));
|
||||
mP.w = b_attr_radius ? b_attr_radius->data[index].value() : 0.0f;
|
||||
return mP;
|
||||
}
|
||||
|
||||
static float4 interpolate_hair_points(BL::Hair b_hair,
|
||||
static float4 interpolate_hair_points(BL::Curves b_curves,
|
||||
std::optional<BL::FloatAttribute> b_attr_radius,
|
||||
const int first_point_index,
|
||||
const int num_points,
|
||||
const float step)
|
||||
|
@ -641,12 +664,12 @@ static float4 interpolate_hair_points(BL::Hair b_hair,
|
|||
const int point_a = clamp((int)curve_t, 0, num_points - 1);
|
||||
const int point_b = min(point_a + 1, num_points - 1);
|
||||
const float t = curve_t - (float)point_a;
|
||||
return lerp(hair_point_as_float4(b_hair.points[first_point_index + point_a]),
|
||||
hair_point_as_float4(b_hair.points[first_point_index + point_b]),
|
||||
return lerp(hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_a),
|
||||
hair_point_as_float4(b_curves, b_attr_radius, first_point_index + point_b),
|
||||
t);
|
||||
}
|
||||
|
||||
static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
||||
static void export_hair_curves(Scene *scene, Hair *hair, BL::Curves b_curves)
|
||||
{
|
||||
/* TODO: optimize so we can straight memcpy arrays from Blender? */
|
||||
|
||||
|
@ -666,17 +689,19 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
|||
}
|
||||
|
||||
/* Reserve memory. */
|
||||
const int num_keys = b_hair.points.length();
|
||||
const int num_curves = b_hair.curves.length();
|
||||
const int num_keys = b_curves.points.length();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
|
||||
hair->reserve_curves(num_curves, num_keys);
|
||||
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
|
||||
|
||||
/* Export curves and points. */
|
||||
vector<float> points_length;
|
||||
|
||||
for (BL::HairCurve &b_curve : b_hair.curves) {
|
||||
const int first_point_index = b_curve.first_point_index();
|
||||
const int num_points = b_curve.num_points();
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = b_curves.curve_offset_data[i].value();
|
||||
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
|
||||
|
||||
float3 prev_co = zero_float3();
|
||||
float length = 0.0f;
|
||||
|
@ -687,10 +712,9 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
|||
|
||||
/* Position and radius. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
BL::HairPoint b_point = b_hair.points[first_point_index + i];
|
||||
|
||||
const float3 co = get_float3(b_point.co());
|
||||
const float radius = b_point.radius();
|
||||
const float3 co = get_float3(b_curves.position_data[first_point_index + i].vector());
|
||||
const float radius = b_attr_radius ? b_attr_radius->data[first_point_index + i].value() :
|
||||
0.0f;
|
||||
hair->add_curve_key(co, radius);
|
||||
|
||||
if (attr_intercept) {
|
||||
|
@ -715,7 +739,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
|||
|
||||
/* Random number per curve. */
|
||||
if (attr_random != NULL) {
|
||||
attr_random->add(hash_uint2_to_float(b_curve.index(), 0));
|
||||
attr_random->add(hash_uint2_to_float(i, 0));
|
||||
}
|
||||
|
||||
/* Curve. */
|
||||
|
@ -724,7 +748,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
|||
}
|
||||
}
|
||||
|
||||
static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_step)
|
||||
static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motion_step)
|
||||
{
|
||||
/* Find or add attribute. */
|
||||
Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
@ -737,14 +761,17 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
|||
|
||||
/* Export motion keys. */
|
||||
const int num_keys = hair->get_curve_keys().size();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
|
||||
bool have_motion = false;
|
||||
int num_motion_keys = 0;
|
||||
int curve_index = 0;
|
||||
|
||||
for (BL::HairCurve &b_curve : b_hair.curves) {
|
||||
const int first_point_index = b_curve.first_point_index();
|
||||
const int num_points = b_curve.num_points();
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
|
||||
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = b_curves.curve_offset_data[i].value();
|
||||
const int num_points = b_curves.curve_offset_data[i + 1].value() - first_point_index;
|
||||
|
||||
Hair::Curve curve = hair->get_curve(curve_index);
|
||||
curve_index++;
|
||||
|
@ -755,7 +782,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
|||
int point_index = first_point_index + i;
|
||||
|
||||
if (point_index < num_keys) {
|
||||
mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]);
|
||||
mP[num_motion_keys] = hair_point_as_float4(b_curves, b_attr_radius, point_index);
|
||||
num_motion_keys++;
|
||||
|
||||
if (!have_motion) {
|
||||
|
@ -774,7 +801,8 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
|||
const float step_size = curve.num_keys > 1 ? 1.0f / (curve.num_keys - 1) : 0.0f;
|
||||
for (int i = 0; i < curve.num_keys; i++) {
|
||||
const float step = i * step_size;
|
||||
mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step);
|
||||
mP[num_motion_keys] = interpolate_hair_points(
|
||||
b_curves, b_attr_radius, first_point_index, num_points, step);
|
||||
num_motion_keys++;
|
||||
}
|
||||
have_motion = true;
|
||||
|
@ -791,12 +819,12 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
|||
void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step)
|
||||
{
|
||||
/* Convert Blender hair to Cycles curves. */
|
||||
BL::Hair b_hair(b_ob_info.object_data);
|
||||
BL::Curves b_curves(b_ob_info.object_data);
|
||||
if (motion) {
|
||||
export_hair_curves_motion(hair, b_hair, motion_step);
|
||||
export_hair_curves_motion(hair, b_curves, motion_step);
|
||||
}
|
||||
else {
|
||||
export_hair_curves(scene, hair, b_hair);
|
||||
export_hair_curves(scene, hair, b_curves);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -819,8 +847,8 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, H
|
|||
new_hair.set_used_shaders(used_shaders);
|
||||
|
||||
if (view_layer.use_hair) {
|
||||
#ifdef WITH_HAIR_NODES
|
||||
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
if (b_ob_info.object_data.is_a(&RNA_Curves)) {
|
||||
/* Hair object. */
|
||||
sync_hair(&new_hair, b_ob_info, false);
|
||||
}
|
||||
|
@ -873,8 +901,8 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph,
|
|||
|
||||
/* Export deformed coordinates. */
|
||||
if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
|
||||
#ifdef WITH_HAIR_NODES
|
||||
if (b_ob_info.object_data.is_a(&RNA_Hair)) {
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
if (b_ob_info.object_data.is_a(&RNA_Curves)) {
|
||||
/* Hair object. */
|
||||
sync_hair(hair, b_ob_info, true, motion_step);
|
||||
return;
|
||||
|
|
|
@ -32,8 +32,8 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_particle_hair)
|
||||
{
|
||||
#ifdef WITH_HAIR_NODES
|
||||
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) {
|
||||
#else
|
||||
if (use_particle_hair) {
|
||||
#endif
|
||||
|
@ -231,8 +231,8 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph,
|
|||
if (progress.get_cancel())
|
||||
return;
|
||||
|
||||
#ifdef WITH_HAIR_NODES
|
||||
if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) {
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
if (b_ob_info.object_data.is_a(&RNA_Curves) || use_particle_hair) {
|
||||
#else
|
||||
if (use_particle_hair) {
|
||||
#endif
|
||||
|
|
|
@ -72,7 +72,7 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info)
|
|||
|
||||
BL::Object::type_enum type = b_ob_info.iter_object.type();
|
||||
|
||||
if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR ||
|
||||
if (type == BL::Object::type_VOLUME || type == BL::Object::type_CURVES ||
|
||||
type == BL::Object::type_POINTCLOUD) {
|
||||
/* Will be exported attached to mesh. */
|
||||
return true;
|
||||
|
@ -97,7 +97,7 @@ bool BlenderSync::object_can_have_geometry(BL::Object &b_ob)
|
|||
case BL::Object::type_SURFACE:
|
||||
case BL::Object::type_META:
|
||||
case BL::Object::type_FONT:
|
||||
case BL::Object::type_HAIR:
|
||||
case BL::Object::type_CURVES:
|
||||
case BL::Object::type_POINTCLOUD:
|
||||
case BL::Object::type_VOLUME:
|
||||
return true;
|
||||
|
|
|
@ -142,6 +142,7 @@ class BVHParams {
|
|||
|
||||
top_level = false;
|
||||
bvh_layout = BVH_LAYOUT_BVH2;
|
||||
use_compact_structure = true;
|
||||
use_unaligned_nodes = false;
|
||||
|
||||
num_motion_curve_steps = 0;
|
||||
|
|
|
@ -905,8 +905,8 @@ void HIPDevice::tex_alloc(device_texture &mem)
|
|||
address_mode = hipAddressModeClamp;
|
||||
break;
|
||||
case EXTENSION_CLIP:
|
||||
// TODO : (Arya) setting this to Mode Clamp instead of Mode Border because it's unsupported
|
||||
// in hip
|
||||
/* TODO(@arya): setting this to Mode Clamp instead of Mode Border
|
||||
* because it's unsupported in HIP. */
|
||||
address_mode = hipAddressModeClamp;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -157,7 +157,7 @@ bool ShaderEval::eval_gpu(Device *device,
|
|||
queue->init_execution();
|
||||
|
||||
/* Execute work on GPU in chunk, so we can cancel.
|
||||
* TODO : query appropriate size from device.*/
|
||||
* TODO: query appropriate size from device. */
|
||||
const int32_t chunk_size = 65536;
|
||||
|
||||
device_ptr d_input = input.device_pointer;
|
||||
|
|
|
@ -193,17 +193,24 @@ ccl_device_forceinline void integrate_surface_direct_light(KernelGlobals kg,
|
|||
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||
shadow_flag |= (shadow_flag & PATH_RAY_ANY_PASS) ? 0 : PATH_RAY_SURFACE_PASS;
|
||||
const float3 throughput = INTEGRATOR_STATE(state, path, throughput) * bsdf_eval_sum(&bsdf_eval);
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
const packed_float3 pass_diffuse_weight =
|
||||
(bounce == 0) ? packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval)) :
|
||||
INTEGRATOR_STATE(state, path, pass_diffuse_weight);
|
||||
const packed_float3 pass_glossy_weight = (bounce == 0) ?
|
||||
packed_float3(
|
||||
bsdf_eval_pass_glossy_weight(&bsdf_eval)) :
|
||||
INTEGRATOR_STATE(state, path, pass_glossy_weight);
|
||||
packed_float3 pass_diffuse_weight;
|
||||
packed_float3 pass_glossy_weight;
|
||||
|
||||
if (shadow_flag & PATH_RAY_ANY_PASS) {
|
||||
/* Indirect bounce, use weights from earlier surface or volume bounce. */
|
||||
pass_diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
|
||||
pass_glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
|
||||
}
|
||||
else {
|
||||
/* Direct light, use BSDFs at this bounce. */
|
||||
shadow_flag |= PATH_RAY_SURFACE_PASS;
|
||||
pass_diffuse_weight = packed_float3(bsdf_eval_pass_diffuse_weight(&bsdf_eval));
|
||||
pass_glossy_weight = packed_float3(bsdf_eval_pass_glossy_weight(&bsdf_eval));
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = pass_glossy_weight;
|
||||
}
|
||||
|
|
|
@ -801,16 +801,26 @@ ccl_device_forceinline void integrate_volume_direct_light(
|
|||
const uint16_t transparent_bounce = INTEGRATOR_STATE(state, path, transparent_bounce);
|
||||
uint32_t shadow_flag = INTEGRATOR_STATE(state, path, flag);
|
||||
shadow_flag |= (is_light) ? PATH_RAY_SHADOW_FOR_LIGHT : 0;
|
||||
shadow_flag |= (shadow_flag & PATH_RAY_ANY_PASS) ? 0 : PATH_RAY_VOLUME_PASS;
|
||||
const float3 throughput_phase = throughput * bsdf_eval_sum(&phase_eval);
|
||||
|
||||
if (kernel_data.kernel_features & KERNEL_FEATURE_LIGHT_PASSES) {
|
||||
const packed_float3 pass_diffuse_weight = (bounce == 0) ?
|
||||
packed_float3(one_float3()) :
|
||||
INTEGRATOR_STATE(
|
||||
state, path, pass_diffuse_weight);
|
||||
packed_float3 pass_diffuse_weight;
|
||||
packed_float3 pass_glossy_weight;
|
||||
|
||||
if (shadow_flag & PATH_RAY_ANY_PASS) {
|
||||
/* Indirect bounce, use weights from earlier surface or volume bounce. */
|
||||
pass_diffuse_weight = INTEGRATOR_STATE(state, path, pass_diffuse_weight);
|
||||
pass_glossy_weight = INTEGRATOR_STATE(state, path, pass_glossy_weight);
|
||||
}
|
||||
else {
|
||||
/* Direct light, no diffuse/glossy distinction needed for volumes. */
|
||||
shadow_flag |= PATH_RAY_VOLUME_PASS;
|
||||
pass_diffuse_weight = packed_float3(one_float3());
|
||||
pass_glossy_weight = packed_float3(zero_float3());
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_diffuse_weight) = pass_diffuse_weight;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = zero_float3();
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, pass_glossy_weight) = pass_glossy_weight;
|
||||
}
|
||||
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_path, render_pixel_index) = INTEGRATOR_STATE(
|
||||
|
|
|
@ -113,22 +113,30 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
|
|||
ls->P = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
|
||||
if (type == LIGHT_SPOT) {
|
||||
ls->Ng = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
|
||||
float radius = klight->spot.radius;
|
||||
const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
const float radius = klight->spot.radius;
|
||||
const float3 dir = make_float3(
|
||||
klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(P - center);
|
||||
ls->P = center;
|
||||
|
||||
if (radius > 0.0f)
|
||||
/* sphere light */
|
||||
ls->P += disk_light_sample(ls->Ng, randu, randv) * radius;
|
||||
/* disk light */
|
||||
ls->P += disk_light_sample(lightN, randu, randv) * radius;
|
||||
|
||||
const float invarea = klight->spot.invarea;
|
||||
ls->pdf = invarea;
|
||||
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
/* we set the light normal to the outgoing direction to support texturing */
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
float invarea = klight->spot.invarea;
|
||||
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
|
||||
ls->pdf = invarea;
|
||||
|
||||
/* spot light attenuation */
|
||||
ls->eval_fac *= spot_light_attenuation(
|
||||
ls->Ng, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
|
||||
dir, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
|
||||
if (!in_volume_segment && ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
@ -137,32 +145,33 @@ ccl_device_inline bool light_sample(KernelGlobals kg,
|
|||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
|
||||
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
|
||||
}
|
||||
else if (type == LIGHT_POINT) {
|
||||
float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
float radius = klight->spot.radius;
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(P - center);
|
||||
ls->P = center;
|
||||
float pdf = 1.0;
|
||||
|
||||
if (radius > 0.0f) {
|
||||
ls->Ng = normalize(P - center);
|
||||
ls->P += disk_light_sample(ls->Ng, randu, randv) * radius;
|
||||
pdf = klight->spot.invarea;
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
}
|
||||
else {
|
||||
ls->Ng = normalize(P - center);
|
||||
ls->P += disk_light_sample(lightN, randu, randv) * radius;
|
||||
}
|
||||
ls->pdf = klight->spot.invarea;
|
||||
|
||||
ls->D = normalize_len(ls->P - P, &ls->t);
|
||||
ls->pdf = pdf;
|
||||
/* we set the light normal to the outgoing direction to support texturing */
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
ls->eval_fac = M_1_PI_F * 0.25f * klight->spot.invarea;
|
||||
if (!in_volume_segment && ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float2 uv = map_to_sphere(ls->Ng);
|
||||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
|
||||
}
|
||||
else {
|
||||
/* area light */
|
||||
|
@ -263,14 +272,16 @@ ccl_device bool lights_intersect(KernelGlobals kg,
|
|||
|
||||
if (type == LIGHT_SPOT) {
|
||||
/* Spot/Disk light. */
|
||||
const float mis_ray_t = INTEGRATOR_STATE(state, path, mis_ray_t);
|
||||
const float3 ray_P = ray->P - ray->D * mis_ray_t;
|
||||
|
||||
const float3 lightP = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
const float3 lightN = make_float3(
|
||||
klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
|
||||
const float radius = klight->spot.radius;
|
||||
if (radius == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(ray_P - lightP);
|
||||
/* One sided. */
|
||||
if (dot(ray->D, lightN) >= 0.0f) {
|
||||
continue;
|
||||
|
@ -292,9 +303,10 @@ ccl_device bool lights_intersect(KernelGlobals kg,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* disk oriented normal */
|
||||
const float3 lightN = normalize(ray_P - lightP);
|
||||
float3 P;
|
||||
const float3 lsN = normalize(ray_P - lightP);
|
||||
if (!ray_disk_intersect(ray->P, ray->D, ray->t, lightP, lsN, radius, &P, &t)) {
|
||||
if (!ray_disk_intersect(ray->P, ray->D, ray->t, lightP, lightN, radius, &P, &t)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -427,7 +439,12 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
ls->D = ray_D;
|
||||
|
||||
if (type == LIGHT_SPOT) {
|
||||
ls->Ng = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
|
||||
const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
const float3 dir = make_float3(klight->spot.dir[0], klight->spot.dir[1], klight->spot.dir[2]);
|
||||
/* the normal of the oriented disk */
|
||||
const float3 lightN = normalize(ray_P - center);
|
||||
/* we set the light normal to the outgoing direction to support texturing*/
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
float invarea = klight->spot.invarea;
|
||||
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
|
||||
|
@ -435,7 +452,7 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
|
||||
/* spot light attenuation */
|
||||
ls->eval_fac *= spot_light_attenuation(
|
||||
ls->Ng, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
|
||||
dir, klight->spot.spot_angle, klight->spot.spot_smooth, -ls->D);
|
||||
|
||||
if (ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
|
@ -447,23 +464,32 @@ ccl_device bool light_sample_from_intersection(KernelGlobals kg,
|
|||
|
||||
/* compute pdf */
|
||||
if (ls->t != FLT_MAX)
|
||||
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, lightN, -ls->D, ls->t);
|
||||
else
|
||||
ls->pdf = 0.f;
|
||||
}
|
||||
else if (type == LIGHT_POINT) {
|
||||
float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
const float3 center = make_float3(klight->co[0], klight->co[1], klight->co[2]);
|
||||
const float3 lighN = normalize(ray_P - center);
|
||||
|
||||
/* we set the light normal to the outgoing direction to support texturing*/
|
||||
ls->Ng = -ls->D;
|
||||
|
||||
ls->Ng = normalize(ray_P - center);
|
||||
float invarea = klight->spot.invarea;
|
||||
ls->eval_fac = (0.25f * M_1_PI_F) * invarea;
|
||||
ls->pdf = invarea;
|
||||
|
||||
if (ls->eval_fac == 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float2 uv = map_to_sphere(ls->Ng);
|
||||
ls->u = uv.x;
|
||||
ls->v = uv.y;
|
||||
|
||||
/* compute pdf */
|
||||
if (ls->t != FLT_MAX)
|
||||
ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
|
||||
ls->pdf *= lamp_light_pdf(kg, lighN, -ls->D, ls->t);
|
||||
else
|
||||
ls->pdf = 0.f;
|
||||
}
|
||||
|
@ -921,4 +947,4 @@ ccl_device_inline bool light_distribution_sample_new_position(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
CCL_NAMESPACE_END
|
|
@ -889,16 +889,11 @@ extern char *GHOST_getClipboard(bool selection);
|
|||
extern void GHOST_putClipboard(const char *buffer, bool selection);
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* \param action:
|
||||
* - 0: Hides
|
||||
* - 1: Shows
|
||||
* - 2: Toggles
|
||||
* - 3: Hides if it runs not from command line
|
||||
* - *: Does nothing
|
||||
* Set the Console State
|
||||
* \param action: console state
|
||||
* \return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
extern int GHOST_toggleConsole(int action);
|
||||
extern int setConsoleWindowState(GHOST_TConsoleWindowState action);
|
||||
|
||||
/**
|
||||
* Use native pixel size (MacBook pro 'retina'), if supported.
|
||||
|
|
|
@ -411,16 +411,11 @@ class GHOST_ISystem {
|
|||
#endif
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* \param action:
|
||||
* - 0: Hides.
|
||||
* - 1: Shows
|
||||
* - 2: Toggles
|
||||
* - 3: Hides if it runs not from command line
|
||||
* - *: Does nothing
|
||||
* Set the Console State
|
||||
* \param action: console state
|
||||
* \return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
virtual int toggleConsole(int action) = 0;
|
||||
virtual int setConsoleWindowState(GHOST_TConsoleWindowState action) = 0;
|
||||
|
||||
/***************************************************************************************
|
||||
* Access to clipboard.
|
||||
|
|
|
@ -152,6 +152,13 @@ typedef enum {
|
|||
// GHOST_kWindowStateUnModified,
|
||||
} GHOST_TWindowState;
|
||||
|
||||
typedef enum {
|
||||
GHOST_kConsoleWindowStateHide = 0,
|
||||
GHOST_kConsoleWindowStateShow,
|
||||
GHOST_kConsoleWindowStateToggle,
|
||||
GHOST_kConsoleWindowStateHideForNonConsoleLaunch
|
||||
} GHOST_TConsoleWindowState;
|
||||
|
||||
typedef enum { GHOST_kWindowOrderTop = 0, GHOST_kWindowOrderBottom } GHOST_TWindowOrder;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -809,10 +809,10 @@ void GHOST_putClipboard(const char *buffer, bool selection)
|
|||
system->putClipboard(buffer, selection);
|
||||
}
|
||||
|
||||
int GHOST_toggleConsole(int action)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
GHOST_ISystem *system = GHOST_ISystem::getSystem();
|
||||
return system->toggleConsole(action);
|
||||
return system->setConsoleWindowState(action);
|
||||
}
|
||||
|
||||
int GHOST_UseNativePixels(void)
|
||||
|
|
|
@ -244,7 +244,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
/**
|
||||
* \see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int action)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -890,7 +890,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
|
|||
bool anyProcessed = false;
|
||||
NSEvent *event;
|
||||
|
||||
// TODO : implement timer ??
|
||||
/* TODO: implement timer? */
|
||||
#if 0
|
||||
do {
|
||||
GHOST_TimerManager* timerMgr = getTimerManager();
|
||||
|
|
|
@ -40,7 +40,7 @@ class GHOST_SystemNULL : public GHOST_System {
|
|||
{
|
||||
return false;
|
||||
}
|
||||
int toggleConsole(int action)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class GHOST_SystemSDL : public GHOST_System {
|
|||
|
||||
bool processEvents(bool waitForEvent);
|
||||
|
||||
int toggleConsole(int action)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1473,7 +1473,7 @@ bool GHOST_SystemWayland::processEvents(bool waitForEvent)
|
|||
return fired || (getEventManager()->getNumEvents() > 0);
|
||||
}
|
||||
|
||||
int GHOST_SystemWayland::toggleConsole(int /*action*/)
|
||||
int GHOST_SystemWayland::setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class GHOST_SystemWayland : public GHOST_System {
|
|||
|
||||
bool processEvents(bool waitForEvent) override;
|
||||
|
||||
int toggleConsole(int action) override;
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action) override;
|
||||
|
||||
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const override;
|
||||
|
||||
|
|
|
@ -105,6 +105,8 @@
|
|||
*/
|
||||
#define BROKEN_PEEK_TOUCHPAD
|
||||
|
||||
static bool isStartedFromCommandPrompt();
|
||||
|
||||
static void initRawInput()
|
||||
{
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
|
@ -166,7 +168,10 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
|
|||
{
|
||||
// Shutdown COM
|
||||
OleUninitialize();
|
||||
toggleConsole(1);
|
||||
|
||||
if (isStartedFromCommandPrompt()) {
|
||||
setConsoleWindowState(GHOST_kConsoleWindowStateShow);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
|
||||
|
@ -2216,31 +2221,30 @@ static bool isStartedFromCommandPrompt()
|
|||
return false;
|
||||
}
|
||||
|
||||
int GHOST_SystemWin32::toggleConsole(int action)
|
||||
int GHOST_SystemWin32::setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
HWND wnd = GetConsoleWindow();
|
||||
|
||||
switch (action) {
|
||||
case 3: // startup: hide if not started from command prompt
|
||||
{
|
||||
case GHOST_kConsoleWindowStateHideForNonConsoleLaunch: {
|
||||
if (!isStartedFromCommandPrompt()) {
|
||||
ShowWindow(wnd, SW_HIDE);
|
||||
m_consoleStatus = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0: // hide
|
||||
case GHOST_kConsoleWindowStateHide:
|
||||
ShowWindow(wnd, SW_HIDE);
|
||||
m_consoleStatus = 0;
|
||||
break;
|
||||
case 1: // show
|
||||
case GHOST_kConsoleWindowStateShow:
|
||||
ShowWindow(wnd, SW_SHOW);
|
||||
if (!isStartedFromCommandPrompt()) {
|
||||
DeleteMenu(GetSystemMenu(wnd, FALSE), SC_CLOSE, MF_BYCOMMAND);
|
||||
}
|
||||
m_consoleStatus = 1;
|
||||
break;
|
||||
case 2: // toggle
|
||||
case GHOST_kConsoleWindowStateToggle:
|
||||
ShowWindow(wnd, m_consoleStatus ? SW_HIDE : SW_SHOW);
|
||||
m_consoleStatus = !m_consoleStatus;
|
||||
if (m_consoleStatus && !isStartedFromCommandPrompt()) {
|
||||
|
|
|
@ -436,16 +436,11 @@ class GHOST_SystemWin32 : public GHOST_System {
|
|||
static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
/**
|
||||
* Toggles console
|
||||
* \param action:
|
||||
* - 0 - Hides
|
||||
* - 1 - Shows
|
||||
* - 2 - Toggles
|
||||
* - 3 - Hides if it runs not from command line
|
||||
* - * - Does nothing
|
||||
* Set the Console State
|
||||
* \param action: console state
|
||||
* \return current status (1 -visible, 0 - hidden)
|
||||
*/
|
||||
int toggleConsole(int action);
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action);
|
||||
|
||||
/** The current state of the modifier keys. */
|
||||
GHOST_ModifierKeys m_modifierKeys;
|
||||
|
|
|
@ -269,7 +269,7 @@ class GHOST_SystemX11 : public GHOST_System {
|
|||
/**
|
||||
* \see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int /*action*/)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ void GHOST_XrContext::initialize(const GHOST_XrContextCreateInfo *create_info)
|
|||
initApiLayers();
|
||||
initExtensions();
|
||||
if (isDebugMode()) {
|
||||
printSDKVersion();
|
||||
printAvailableAPILayersAndExtensionsInfo();
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,16 @@ void GHOST_XrContext::storeInstanceProperties()
|
|||
/** \name Debug Printing
|
||||
* \{ */
|
||||
|
||||
void GHOST_XrContext::printSDKVersion()
|
||||
{
|
||||
const XrVersion sdk_version = XR_CURRENT_API_VERSION;
|
||||
|
||||
printf("OpenXR SDK Version: %u.%u.%u\n",
|
||||
XR_VERSION_MAJOR(sdk_version),
|
||||
XR_VERSION_MINOR(sdk_version),
|
||||
XR_VERSION_PATCH(sdk_version));
|
||||
}
|
||||
|
||||
void GHOST_XrContext::printInstanceInfo()
|
||||
{
|
||||
assert(m_oxr->instance != XR_NULL_HANDLE);
|
||||
|
|
|
@ -126,6 +126,7 @@ class GHOST_XrContext : public GHOST_IXrContext {
|
|||
void storeInstanceProperties();
|
||||
void initDebugMessenger();
|
||||
|
||||
void printSDKVersion();
|
||||
void printInstanceInfo();
|
||||
void printAvailableAPILayersAndExtensionsInfo();
|
||||
void printExtensionsAndAPILayersToEnable();
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
* second intern/ module with MEM_ prefix, for use in c++.
|
||||
*
|
||||
* \subsection memdependencies Dependencies
|
||||
* - stdlib
|
||||
* - stdio
|
||||
* - `stdlib`
|
||||
* - `stdio`
|
||||
*
|
||||
* \subsection memdocs API Documentation
|
||||
* See \ref MEM_guardedalloc.h
|
||||
|
@ -276,6 +276,12 @@ void MEM_use_guarded_allocator(void);
|
|||
* Allocate new memory for and constructs an object of type #T.
|
||||
* #MEM_delete should be used to delete the object. Just calling #MEM_freeN is not enough when #T
|
||||
* is not a trivial type.
|
||||
*
|
||||
* Note that when no arguments are passed, C++ will do recursive member-wise value initialization.
|
||||
* That is because C++ differentiates between creating an object with `T` (default initialization)
|
||||
* and `T()` (value initialization), whereby this function does the latter. Value initialization
|
||||
* rules are complex, but for C-style structs, memory will be zero-initialized. So this doesn't
|
||||
* match a `malloc()`, but a `calloc()` call in this case. See https://stackoverflow.com/a/4982720.
|
||||
*/
|
||||
template<typename T, typename... Args>
|
||||
inline T *MEM_new(const char *allocation_name, Args &&...args)
|
||||
|
|
|
@ -56,7 +56,6 @@ if(WITH_INTERNATIONAL)
|
|||
list(APPEND LIB
|
||||
${BOOST_LIBRARIES}
|
||||
)
|
||||
add_definitions(-DWITH_INTERNATIONAL)
|
||||
add_definitions(${BOOST_DEFINITIONS})
|
||||
endif()
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 93612eddc7cdfa82d1e7c31c362df0988388629b
|
||||
Subproject commit 2d12637a69df7643484a8a3655b7eeb6faa170a7
|
|
@ -1 +1 @@
|
|||
Subproject commit 9207696bbfac648c299f29f031ab5f18d8fa0077
|
||||
Subproject commit 089aef61debbece2baff6516e33fc7491629b1d0
|
|
@ -356,6 +356,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
|
|||
"y",
|
||||
"y = (Ax + B)",
|
||||
# Sub-strings.
|
||||
"and AMD Radeon Pro 21.Q4 driver or newer",
|
||||
"available with",
|
||||
"brown fox",
|
||||
"can't save image while rendering",
|
||||
|
@ -378,6 +379,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
|
|||
"image path can't be written to",
|
||||
"in memory to enable editing!",
|
||||
"insufficient content",
|
||||
"into",
|
||||
"jumps over",
|
||||
"left",
|
||||
"local",
|
||||
|
@ -387,6 +389,7 @@ WARN_MSGID_NOT_CAPITALIZED_ALLOWED = {
|
|||
"performance impact!",
|
||||
"right",
|
||||
"the lazy dog",
|
||||
"to the top level of the tree",
|
||||
"unable to load movie clip",
|
||||
"unable to load text",
|
||||
"unable to open the file",
|
||||
|
|
|
@ -76,10 +76,12 @@ class SpellChecker:
|
|||
"tangency",
|
||||
"vertices",
|
||||
"wasn", # wasn't
|
||||
"zig", "zag",
|
||||
|
||||
# Brands etc.
|
||||
"htc",
|
||||
"huawei",
|
||||
"radeon",
|
||||
"vive",
|
||||
"xbox",
|
||||
|
||||
|
@ -136,6 +138,7 @@ class SpellChecker:
|
|||
"filename", "filenames",
|
||||
"filepath", "filepaths",
|
||||
"forcefield", "forcefields",
|
||||
"framerange",
|
||||
"fulldome", "fulldomes",
|
||||
"fullscreen",
|
||||
"gamepad",
|
||||
|
@ -498,6 +501,7 @@ class SpellChecker:
|
|||
"framerate",
|
||||
"gimbal",
|
||||
"grayscale",
|
||||
"icosahedron",
|
||||
"icosphere",
|
||||
"inpaint",
|
||||
"kerning",
|
||||
|
@ -556,6 +560,7 @@ class SpellChecker:
|
|||
"bspline",
|
||||
"bweight",
|
||||
"colorband",
|
||||
"crazyspace",
|
||||
"datablock", "datablocks",
|
||||
"despeckle",
|
||||
"depsgraph",
|
||||
|
@ -730,6 +735,7 @@ class SpellChecker:
|
|||
"precisa",
|
||||
"px",
|
||||
"qmc",
|
||||
"rdna",
|
||||
"rdp",
|
||||
"rgb", "rgba",
|
||||
"rhs",
|
||||
|
|
|
@ -677,7 +677,6 @@ url_manual_mapping = (
|
|||
("bpy.ops.gpencil.stroke_merge_by_distance*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-merge-by-distance"),
|
||||
("bpy.ops.node.collapse_hide_unused_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-collapse-hide-unused-toggle"),
|
||||
("bpy.ops.object.anim_transforms_to_deltas*", "scene_layout/object/editing/apply.html#bpy-ops-object-anim-transforms-to-deltas"),
|
||||
("bpy.ops.object.convert_proxy_to_override*", "files/linked_libraries/library_overrides.html#bpy-ops-object-convert-proxy-to-override"),
|
||||
("bpy.ops.object.modifier_copy_to_selected*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-copy-to-selected"),
|
||||
("bpy.ops.preferences.app_template_install*", "advanced/app_templates.html#bpy-ops-preferences-app-template-install"),
|
||||
("bpy.types.actionposemarkers.active_index*", "animation/armatures/properties/pose_library.html#bpy-types-actionposemarkers-active-index"),
|
||||
|
@ -2140,7 +2139,6 @@ url_manual_mapping = (
|
|||
("bpy.ops.object.origin_set*", "scene_layout/object/origin.html#bpy-ops-object-origin-set"),
|
||||
("bpy.ops.object.parent_set*", "scene_layout/object/editing/parent.html#bpy-ops-object-parent-set"),
|
||||
("bpy.ops.object.pointcloud*", "modeling/point_cloud.html#bpy-ops-object-pointcloud"),
|
||||
("bpy.ops.object.proxy_make*", "files/linked_libraries/library_proxies.html#bpy-ops-object-proxy-make"),
|
||||
("bpy.ops.object.select_all*", "scene_layout/object/selecting.html#bpy-ops-object-select-all"),
|
||||
("bpy.ops.object.shade_flat*", "scene_layout/object/editing/shading.html#bpy-ops-object-shade-flat"),
|
||||
("bpy.ops.pose.group_assign*", "animation/armatures/properties/bone_groups.html#bpy-ops-pose-group-assign"),
|
||||
|
|
|
@ -298,7 +298,7 @@ def xml2rna(
|
|||
del value_xml_split
|
||||
tp_name = 'ARRAY'
|
||||
|
||||
# print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type))
|
||||
# print(" %s.%s (%s) --- %s" % (type(value).__name__, attr, tp_name, subvalue_type))
|
||||
try:
|
||||
setattr(value, attr, value_xml_coerce)
|
||||
except ValueError:
|
||||
|
@ -340,7 +340,6 @@ def xml2rna(
|
|||
|
||||
else:
|
||||
# print(elems)
|
||||
|
||||
if len(elems) == 1:
|
||||
# sub node named by its type
|
||||
child_xml_real, = elems
|
||||
|
@ -376,7 +375,6 @@ def _get_context_val(context, path):
|
|||
|
||||
|
||||
def xml_file_run(context, filepath, rna_map):
|
||||
|
||||
import xml.dom.minidom
|
||||
|
||||
xml_nodes = xml.dom.minidom.parse(filepath)
|
||||
|
@ -391,27 +389,25 @@ def xml_file_run(context, filepath, rna_map):
|
|||
value = _get_context_val(context, rna_path)
|
||||
|
||||
if value is not Ellipsis and value is not None:
|
||||
print(" loading XML: %r -> %r" % (filepath, rna_path))
|
||||
# print(" loading XML: %r -> %r" % (filepath, rna_path))
|
||||
xml2rna(xml_node, root_rna=value)
|
||||
|
||||
|
||||
def xml_file_write(context, filepath, rna_map, *, skip_typemap=None):
|
||||
with open(filepath, "w", encoding="utf-8") as file:
|
||||
fw = file.write
|
||||
fw("<bpy>\n")
|
||||
|
||||
file = open(filepath, "w", encoding="utf-8")
|
||||
fw = file.write
|
||||
|
||||
fw("<bpy>\n")
|
||||
|
||||
for rna_path, _xml_tag in rna_map:
|
||||
# xml_tag is ignored, we get this from the rna
|
||||
value = _get_context_val(context, rna_path)
|
||||
rna2xml(fw,
|
||||
for rna_path, _xml_tag in rna_map:
|
||||
# xml_tag is ignored, we get this from the rna
|
||||
value = _get_context_val(context, rna_path)
|
||||
rna2xml(
|
||||
fw=fw,
|
||||
root_rna=value,
|
||||
method='ATTR',
|
||||
root_ident=" ",
|
||||
ident_val=" ",
|
||||
skip_typemap=skip_typemap,
|
||||
)
|
||||
)
|
||||
|
||||
fw("</bpy>\n")
|
||||
file.close()
|
||||
fw("</bpy>\n")
|
||||
|
|
|
@ -318,7 +318,8 @@ def load():
|
|||
use_v3d_tab_menu=kc_prefs.use_v3d_tab_menu,
|
||||
use_v3d_shade_ex_pie=kc_prefs.use_v3d_shade_ex_pie,
|
||||
use_gizmo_drag=(is_select_left and kc_prefs.gizmo_action == 'DRAG'),
|
||||
use_fallback_tool=(True if is_select_left else (kc_prefs.rmb_action == 'FALLBACK_TOOL')),
|
||||
use_fallback_tool=True,
|
||||
use_fallback_tool_rmb=(False if is_select_left else kc_prefs.rmb_action == 'FALLBACK_TOOL'),
|
||||
use_alt_tool_or_cursor=(
|
||||
(not use_mouse_emulate_3_button) and
|
||||
(kc_prefs.use_alt_tool if is_select_left else kc_prefs.use_alt_cursor)
|
||||
|
|
|
@ -16,6 +16,16 @@
|
|||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Developer Notes
|
||||
#
|
||||
# - This script should run without Blender (no references to the `bpy` module for example).
|
||||
# - All configuration must be passed into the `generate_keymaps` function (via `Params`).
|
||||
# - Supporting some combinations of options is becoming increasingly complex,
|
||||
# especially `Params.select_mouse` & `Params.use_fallback_tool_rmb`.
|
||||
# To ensure changes don't unintentionally break other configurations, see:
|
||||
# `source/tools/utils/blender_keyconfig_export_permutations.py --help`
|
||||
#
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Configurable Parameters
|
||||
|
@ -46,6 +56,8 @@ class Params:
|
|||
"use_gizmo_drag",
|
||||
# Use the fallback tool instead of tweak for RMB select.
|
||||
"use_fallback_tool",
|
||||
# Only set for RMB select.
|
||||
"use_fallback_tool_rmb",
|
||||
# Use pie menu for tab by default (swap 'Tab/Ctrl-Tab').
|
||||
"use_v3d_tab_menu",
|
||||
# Use extended pie menu for shading.
|
||||
|
@ -64,17 +76,16 @@ class Params:
|
|||
"v3d_tilde_action",
|
||||
# Alt-MMB axis switching 'RELATIVE' or 'ABSOLUTE' axis switching.
|
||||
"v3d_alt_mmb_drag_action",
|
||||
|
||||
# File selector actions on single click.
|
||||
"use_file_single_click",
|
||||
|
||||
# Convenience variables:
|
||||
# (derived from other settings).
|
||||
#
|
||||
# This case needs to be checked often,
|
||||
# Shorthand for: `(params.use_fallback_tool if params.select_mouse ==
|
||||
# 'RIGHTMOUSE' else False)`.
|
||||
"use_fallback_tool_rmb",
|
||||
# Shorthand for: `('CLICK' if params.use_fallback_tool_rmb else
|
||||
# params.select_mouse_value)`.
|
||||
# The fallback tool is activated on the same button as selection.
|
||||
# Shorthand for: `(True if (select_mouse == 'LEFT') else self.use_fallback_tool_rmb)`
|
||||
"use_fallback_tool_select_mouse",
|
||||
# Shorthand for: `('CLICK' if self.use_fallback_tool_rmb else self.select_mouse_value)`.
|
||||
"select_mouse_value_fallback",
|
||||
# Shorthand for: `{"type": params.select_tweak, "value": 'ANY'}`.
|
||||
"select_tweak_event",
|
||||
|
@ -106,6 +117,7 @@ class Params:
|
|||
use_select_all_toggle=False,
|
||||
use_gizmo_drag=True,
|
||||
use_fallback_tool=False,
|
||||
use_fallback_tool_rmb=False,
|
||||
use_v3d_tab_menu=False,
|
||||
use_v3d_shade_ex_pie=False,
|
||||
use_v3d_mmb_pan=False,
|
||||
|
@ -148,7 +160,6 @@ class Params:
|
|||
self.cursor_set_event = {"type": 'LEFTMOUSE', "value": 'CLICK'}
|
||||
self.cursor_tweak_event = None
|
||||
|
||||
self.use_fallback_tool = use_fallback_tool
|
||||
self.tool_modifier = {}
|
||||
else:
|
||||
# Left mouse select uses Click event for selection. This is a
|
||||
|
@ -173,7 +184,6 @@ class Params:
|
|||
|
||||
self.cursor_set_event = {"type": 'RIGHTMOUSE', "value": 'PRESS', "shift": True}
|
||||
self.cursor_tweak_event = {"type": 'EVT_TWEAK_R', "value": 'ANY', "shift": True}
|
||||
self.use_fallback_tool = True
|
||||
|
||||
# Use the "tool" functionality for LMB select.
|
||||
if use_alt_tool_or_cursor:
|
||||
|
@ -201,8 +211,11 @@ class Params:
|
|||
|
||||
self.use_file_single_click = use_file_single_click
|
||||
|
||||
self.use_fallback_tool = use_fallback_tool
|
||||
self.use_fallback_tool_rmb = use_fallback_tool_rmb
|
||||
|
||||
# Convenience variables:
|
||||
self.use_fallback_tool_rmb = self.use_fallback_tool if select_mouse == 'RIGHT' else False
|
||||
self.use_fallback_tool_select_mouse = True if (select_mouse == 'LEFT') else self.use_fallback_tool_rmb
|
||||
self.select_mouse_value_fallback = 'CLICK' if self.use_fallback_tool_rmb else self.select_mouse_value
|
||||
self.select_tweak_event = {"type": self.select_tweak, "value": 'ANY'}
|
||||
self.pie_value = 'CLICK_DRAG' if use_pie_click_drag else 'PRESS'
|
||||
|
@ -1047,9 +1060,7 @@ def km_uv_editor(params):
|
|||
|
||||
items.extend([# Selection modes.
|
||||
*_template_items_uv_select_mode(params),
|
||||
*_template_uv_select(type=params.select_mouse,
|
||||
value=('CLICK' if params.use_fallback_tool_rmb else params.select_mouse_value),
|
||||
legacy=params.legacy,),
|
||||
*_template_uv_select(type=params.select_mouse, value=params.select_mouse_value_fallback, legacy=params.legacy),
|
||||
("uv.mark_seam", {"type": 'E', "value": 'PRESS', "ctrl": True}, None),
|
||||
("uv.select_loop",
|
||||
{"type": params.select_mouse, "value": params.select_mouse_value, "alt": True}, None),
|
||||
|
@ -5660,10 +5671,12 @@ def km_image_editor_tool_uv_select(params, *, fallback):
|
|||
def km_image_editor_tool_uv_select_box(params, *, fallback):
|
||||
return (_fallback_id("Image Editor Tool: Uv, Select Box", fallback),
|
||||
{"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("uv.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this
|
||||
# slot.
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"uv.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -5671,8 +5684,11 @@ def km_image_editor_tool_uv_select_box(params, *, fallback):
|
|||
def km_image_editor_tool_uv_select_circle(params, *, fallback):
|
||||
return (_fallback_id("Image Editor Tool: Uv, Select Circle", fallback),
|
||||
{"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("uv.select_circle",
|
||||
**(params.select_tweak_event if fallback else {"type": params.tool_mouse, "value": 'PRESS'}),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"uv.select_circle",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
{"type": params.tool_mouse, "value": 'PRESS'}),
|
||||
properties=[("wait_for_input", False)])),
|
||||
# No selection fallback since this operates on press.
|
||||
]},)
|
||||
|
@ -5682,8 +5698,11 @@ def km_image_editor_tool_uv_select_lasso(params, *, fallback):
|
|||
return (_fallback_id("Image Editor Tool: Uv, Select Lasso", fallback),
|
||||
{"space_type": 'IMAGE_EDITOR', "region_type": 'WINDOW'},
|
||||
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("uv.select_lasso",
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"uv.select_lasso",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -5753,7 +5772,8 @@ def km_node_editor_tool_select_box(params, *, fallback):
|
|||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"node.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event),
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event),
|
||||
properties=[("tweak", True)],
|
||||
)),
|
||||
]},
|
||||
|
@ -5765,7 +5785,9 @@ def km_node_editor_tool_select_lasso(params, *, fallback):
|
|||
{"space_type": 'NODE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"node.select_lasso", **(params.select_tweak_event if fallback else params.tool_tweak_event),
|
||||
"node.select_lasso",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event),
|
||||
properties=[("tweak", True)]))
|
||||
]},
|
||||
)
|
||||
|
@ -5779,7 +5801,7 @@ def km_node_editor_tool_select_circle(params, *, fallback):
|
|||
"node.select_circle",
|
||||
# Why circle select should be used on tweak?
|
||||
# So that RMB or Shift-RMB is still able to set an element as active.
|
||||
type=params.select_tweak if fallback else params.tool_mouse,
|
||||
type=params.select_tweak if (fallback and params.use_fallback_tool_select_mouse) else params.tool_mouse,
|
||||
value='ANY' if fallback else 'PRESS',
|
||||
properties=[("wait_for_input", False)])),
|
||||
]},
|
||||
|
@ -5820,10 +5842,12 @@ def km_3d_view_tool_select(params, *, fallback):
|
|||
def km_3d_view_tool_select_box(params, *, fallback):
|
||||
return (_fallback_id("3D View Tool: Select Box", fallback),
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions("view3d.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this
|
||||
# slot.
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions(
|
||||
"view3d.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -5833,9 +5857,8 @@ def km_3d_view_tool_select_circle(params, *, fallback):
|
|||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("view3d.select_circle",
|
||||
# Why circle select should be used on tweak?
|
||||
# So that RMB or Shift-RMB is still able to set an element as
|
||||
# active.
|
||||
type=params.select_tweak if fallback else params.tool_mouse,
|
||||
# So that RMB or Shift-RMB is still able to set an element as active.
|
||||
type=params.select_tweak if (fallback and params.use_fallback_tool_select_mouse) else params.tool_mouse,
|
||||
value='ANY' if fallback else 'PRESS',
|
||||
properties=[("wait_for_input", False)])),
|
||||
]},
|
||||
|
@ -5845,8 +5868,11 @@ def km_3d_view_tool_select_circle(params, *, fallback):
|
|||
def km_3d_view_tool_select_lasso(params, *, fallback):
|
||||
return (_fallback_id("3D View Tool: Select Lasso", fallback),
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions("view3d.select_lasso",
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions(
|
||||
"view3d.select_lasso",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]}
|
||||
)
|
||||
|
||||
|
@ -6471,10 +6497,12 @@ def km_3d_view_tool_edit_gpencil_select(params, *, fallback):
|
|||
def km_3d_view_tool_edit_gpencil_select_box(params, *, fallback):
|
||||
return (_fallback_id("3D View Tool: Edit Gpencil, Select Box", fallback),
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions("gpencil.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this
|
||||
# slot.
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions(
|
||||
"gpencil.select_box",
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]},
|
||||
)
|
||||
|
||||
|
@ -6484,9 +6512,8 @@ def km_3d_view_tool_edit_gpencil_select_circle(params, *, fallback):
|
|||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("gpencil.select_circle",
|
||||
# Why circle select should be used on tweak?
|
||||
# So that RMB or Shift-RMB is still able to set an element as
|
||||
# active.
|
||||
type=params.select_tweak if fallback else params.tool_mouse,
|
||||
# So that RMB or Shift-RMB is still able to set an element as active.
|
||||
type=params.select_tweak if (fallback and params.use_fallback_tool_select_mouse) else params.tool_mouse,
|
||||
value='ANY' if fallback else 'PRESS',
|
||||
properties=[("wait_for_input", False)])),
|
||||
]},
|
||||
|
@ -6496,8 +6523,11 @@ def km_3d_view_tool_edit_gpencil_select_circle(params, *, fallback):
|
|||
def km_3d_view_tool_edit_gpencil_select_lasso(params, *, fallback):
|
||||
return (_fallback_id("3D View Tool: Edit Gpencil, Select Lasso", fallback),
|
||||
{"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
|
||||
{"items": [*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions("gpencil.select_lasso",
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event))),
|
||||
{"items": [
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions(
|
||||
"gpencil.select_lasso",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event))),
|
||||
]}
|
||||
)
|
||||
|
||||
|
@ -6606,9 +6636,12 @@ def km_sequencer_editor_tool_generic_select_box(params, *, fallback):
|
|||
return (
|
||||
_fallback_id("Sequencer Tool: Select Box", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple("sequencer.select_box",
|
||||
**(params.select_tweak_event if fallback else params.tool_tweak_event),
|
||||
{"items": [
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"sequencer.select_box",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event),
|
||||
properties=[("tweak", params.select_mouse == 'LEFTMOUSE')])),
|
||||
|
||||
# RMB select can already set the frame, match the tweak tool.
|
||||
|
|
|
@ -2977,94 +2977,76 @@ class WM_MT_splash_quick_setup(Menu):
|
|||
bl_label = "Quick Setup"
|
||||
|
||||
def draw(self, context):
|
||||
wm = context.window_manager
|
||||
# prefs = context.preferences
|
||||
|
||||
layout = self.layout
|
||||
|
||||
layout.operator_context = 'EXEC_DEFAULT'
|
||||
|
||||
show_build_notes(layout)
|
||||
layout.label(text="Quick Setup")
|
||||
|
||||
split = layout.split(factor=0.25)
|
||||
split = layout.split(factor=0.14) # Left margin.
|
||||
split.label()
|
||||
split = split.split(factor=2.0 / 3.0)
|
||||
split = split.split(factor=0.73) # Content width.
|
||||
|
||||
col = split.column()
|
||||
|
||||
col.use_property_split = True
|
||||
col.use_property_decorate = False
|
||||
|
||||
# Languages.
|
||||
if bpy.app.build_options.international:
|
||||
sub = col.split(factor=0.35)
|
||||
row = sub.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Language")
|
||||
prefs = context.preferences
|
||||
sub.prop(prefs.view, "language", text="")
|
||||
col.prop(prefs.view, "language")
|
||||
col.separator()
|
||||
|
||||
col.separator()
|
||||
# Shortcuts.
|
||||
wm = context.window_manager
|
||||
kc = wm.keyconfigs.active
|
||||
kc_prefs = kc.preferences
|
||||
|
||||
sub = col.split(factor=0.35)
|
||||
row = sub.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Shortcuts")
|
||||
text = bpy.path.display_name(wm.keyconfigs.active.name)
|
||||
sub = col.column(heading="Shortcuts")
|
||||
text = bpy.path.display_name(kc.name)
|
||||
if not text:
|
||||
text = "Blender"
|
||||
sub.menu("USERPREF_MT_keyconfigs", text=text)
|
||||
|
||||
kc = wm.keyconfigs.active
|
||||
kc_prefs = kc.preferences
|
||||
has_select_mouse = hasattr(kc_prefs, "select_mouse")
|
||||
if has_select_mouse:
|
||||
sub = col.split(factor=0.35)
|
||||
row = sub.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Select With")
|
||||
sub.row().prop(kc_prefs, "select_mouse", expand=True)
|
||||
has_select_mouse = True
|
||||
col.row().prop(kc_prefs, "select_mouse", text="Select With", expand=True)
|
||||
|
||||
has_spacebar_action = hasattr(kc_prefs, "spacebar_action")
|
||||
if has_spacebar_action:
|
||||
sub = col.split(factor=0.35)
|
||||
row = sub.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Spacebar")
|
||||
sub.row().prop(kc_prefs, "spacebar_action", expand=True)
|
||||
has_select_mouse = True
|
||||
col.row().prop(kc_prefs, "spacebar_action", text="Spacebar")
|
||||
|
||||
col.separator()
|
||||
|
||||
sub = col.split(factor=0.35)
|
||||
row = sub.row()
|
||||
row.alignment = 'RIGHT'
|
||||
row.label(text="Theme")
|
||||
# Themes.
|
||||
sub = col.column(heading="Theme")
|
||||
label = bpy.types.USERPREF_MT_interface_theme_presets.bl_label
|
||||
if label == "Presets":
|
||||
label = "Blender Dark"
|
||||
sub.menu("USERPREF_MT_interface_theme_presets", text=label)
|
||||
|
||||
# Keep height constant
|
||||
# Keep height constant.
|
||||
if not has_select_mouse:
|
||||
col.label()
|
||||
if not has_spacebar_action:
|
||||
col.label()
|
||||
|
||||
layout.label()
|
||||
layout.separator(factor=2.0)
|
||||
|
||||
row = layout.row()
|
||||
# Save settings buttons.
|
||||
sub = layout.row()
|
||||
|
||||
sub = row.row()
|
||||
old_version = bpy.types.PREFERENCES_OT_copy_prev.previous_version()
|
||||
if bpy.types.PREFERENCES_OT_copy_prev.poll(context) and old_version:
|
||||
sub.operator("preferences.copy_prev", text=iface_("Load %d.%d Settings", "Operator") % old_version)
|
||||
sub.operator("preferences.copy_prev", text="Load %d.%d Settings" % old_version)
|
||||
sub.operator("wm.save_userpref", text="Save New Settings")
|
||||
else:
|
||||
sub.label()
|
||||
sub.label()
|
||||
sub.operator("wm.save_userpref", text="Next")
|
||||
|
||||
layout.separator()
|
||||
layout.separator()
|
||||
layout.separator(factor=2.4)
|
||||
|
||||
|
||||
class WM_MT_splash(Menu):
|
||||
|
|
|
@ -33,9 +33,9 @@ _modules = [
|
|||
"properties_data_bone",
|
||||
"properties_data_camera",
|
||||
"properties_data_curve",
|
||||
"properties_data_curves",
|
||||
"properties_data_empty",
|
||||
"properties_data_gpencil",
|
||||
"properties_data_hair",
|
||||
"properties_data_light",
|
||||
"properties_data_lattice",
|
||||
"properties_data_mesh",
|
||||
|
|
|
@ -149,7 +149,6 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
|
|||
col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
|
||||
|
||||
split = layout.split()
|
||||
split.active = (ob.proxy is None)
|
||||
|
||||
col = split.column()
|
||||
col.prop(group, "color_set")
|
||||
|
|
|
@ -30,10 +30,10 @@ class DataButtonsPanel:
|
|||
@classmethod
|
||||
def poll(cls, context):
|
||||
engine = context.scene.render.engine
|
||||
return hasattr(context, 'hair') and context.hair and (engine in cls.COMPAT_ENGINES)
|
||||
return hasattr(context, 'curves') and context.curves and (engine in cls.COMPAT_ENGINES)
|
||||
|
||||
|
||||
class DATA_PT_context_hair(DataButtonsPanel, Panel):
|
||||
class DATA_PT_context_curves(DataButtonsPanel, Panel):
|
||||
bl_label = ""
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
@ -42,21 +42,21 @@ class DATA_PT_context_hair(DataButtonsPanel, Panel):
|
|||
layout = self.layout
|
||||
|
||||
ob = context.object
|
||||
hair = context.hair
|
||||
curves = context.curves
|
||||
space = context.space_data
|
||||
|
||||
if ob:
|
||||
layout.template_ID(ob, "data")
|
||||
elif hair:
|
||||
elif curves:
|
||||
layout.template_ID(space, "pin_id")
|
||||
|
||||
|
||||
class HAIR_MT_add_attribute(Menu):
|
||||
class CURVES_MT_add_attribute(Menu):
|
||||
bl_label = "Add Attribute"
|
||||
|
||||
@staticmethod
|
||||
def add_standard_attribute(layout, hair, name, data_type, domain):
|
||||
exists = hair.attributes.get(name) is not None
|
||||
def add_standard_attribute(layout, curves, name, data_type, domain):
|
||||
exists = curves.attributes.get(name) is not None
|
||||
|
||||
col = layout.column()
|
||||
col.enabled = not exists
|
||||
|
@ -69,10 +69,10 @@ class HAIR_MT_add_attribute(Menu):
|
|||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
hair = context.hair
|
||||
curves = context.curves
|
||||
|
||||
self.add_standard_attribute(layout, hair, 'Radius', 'FLOAT', 'POINT')
|
||||
self.add_standard_attribute(layout, hair, 'Color', 'FLOAT_COLOR', 'POINT')
|
||||
self.add_standard_attribute(layout, curves, 'radius', 'FLOAT', 'POINT')
|
||||
self.add_standard_attribute(layout, curves, 'color', 'FLOAT_COLOR', 'POINT')
|
||||
|
||||
layout.separator()
|
||||
|
||||
|
@ -80,7 +80,7 @@ class HAIR_MT_add_attribute(Menu):
|
|||
layout.operator("geometry.attribute_add", text="Custom...")
|
||||
|
||||
|
||||
class HAIR_UL_attributes(UIList):
|
||||
class CURVES_UL_attributes(UIList):
|
||||
def draw_item(self, _context, layout, _data, attribute, _icon, _active_data, _active_propname, _index):
|
||||
data_type = attribute.bl_rna.properties['data_type'].enum_items[attribute.data_type]
|
||||
domain = attribute.bl_rna.properties['domain'].enum_items[attribute.domain]
|
||||
|
@ -96,44 +96,44 @@ class HAIR_UL_attributes(UIList):
|
|||
sub.label(text=data_type.name)
|
||||
|
||||
|
||||
class DATA_PT_hair_attributes(DataButtonsPanel, Panel):
|
||||
class DATA_PT_CURVES_attributes(DataButtonsPanel, Panel):
|
||||
bl_label = "Attributes"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
def draw(self, context):
|
||||
hair = context.hair
|
||||
curves = context.curves
|
||||
|
||||
layout = self.layout
|
||||
row = layout.row()
|
||||
|
||||
col = row.column()
|
||||
col.template_list(
|
||||
"HAIR_UL_attributes",
|
||||
"CURVES_UL_attributes",
|
||||
"attributes",
|
||||
hair,
|
||||
curves,
|
||||
"attributes",
|
||||
hair.attributes,
|
||||
curves.attributes,
|
||||
"active_index",
|
||||
rows=3,
|
||||
)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.menu("HAIR_MT_add_attribute", icon='ADD', text="")
|
||||
col.menu("CURVES_MT_add_attribute", icon='ADD', text="")
|
||||
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
|
||||
|
||||
|
||||
class DATA_PT_custom_props_hair(DataButtonsPanel, PropertyPanel, Panel):
|
||||
class DATA_PT_custom_props_curves(DataButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
_context_path = "object.data"
|
||||
_property_type = bpy.types.Hair if hasattr(bpy.types, "Hair") else None
|
||||
_property_type = bpy.types.Curves if hasattr(bpy.types, "Curves") else None
|
||||
|
||||
|
||||
classes = (
|
||||
DATA_PT_context_hair,
|
||||
DATA_PT_hair_attributes,
|
||||
DATA_PT_custom_props_hair,
|
||||
HAIR_MT_add_attribute,
|
||||
HAIR_UL_attributes,
|
||||
DATA_PT_context_curves,
|
||||
DATA_PT_CURVES_attributes,
|
||||
DATA_PT_custom_props_curves,
|
||||
CURVES_MT_add_attribute,
|
||||
CURVES_UL_attributes,
|
||||
)
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
|
@ -127,8 +127,8 @@ class DopesheetFilterPopoverBase:
|
|||
flow.prop(dopesheet, "show_lattices", text="Lattices")
|
||||
if bpy.data.metaballs:
|
||||
flow.prop(dopesheet, "show_metaballs", text="Metaballs")
|
||||
if hasattr(bpy.data, "hairs") and bpy.data.hairs:
|
||||
flow.prop(dopesheet, "show_hairs", text="Hairs")
|
||||
if hasattr(bpy.data, "hair_curves") and bpy.data.hair_curves:
|
||||
flow.prop(dopesheet, "show_hair_curves", text="Hair Curves")
|
||||
if hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds:
|
||||
flow.prop(dopesheet, "show_pointclouds", text="Point Clouds")
|
||||
if bpy.data.volumes:
|
||||
|
|
|
@ -291,6 +291,9 @@ class NLA_MT_context_menu(Menu):
|
|||
|
||||
layout.separator()
|
||||
|
||||
props = layout.operator("wm.call_panel", text="Rename...")
|
||||
props.name = "TOPBAR_PT_name"
|
||||
props.keep_open = False
|
||||
layout.operator("nla.duplicate", text="Duplicate").linked = False
|
||||
layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
|
||||
|
||||
|
|
|
@ -448,7 +448,7 @@ class OUTLINER_PT_filter(Panel):
|
|||
if (
|
||||
bpy.data.curves or
|
||||
bpy.data.metaballs or
|
||||
(hasattr(bpy.data, "hairs") and bpy.data.hairs) or
|
||||
(hasattr(bpy.data, "hair_curves") and bpy.data.hair_curves) or
|
||||
(hasattr(bpy.data, "pointclouds") and bpy.data.pointclouds) or
|
||||
bpy.data.volumes or
|
||||
bpy.data.lightprobes or
|
||||
|
|
|
@ -2027,6 +2027,9 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
|
|||
layout.use_property_split = True
|
||||
layout.active = not strip.mute
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(strip.transform, "filter", text="Filter")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(strip.transform, "offset_x", text="Position X")
|
||||
col.prop(strip.transform, "offset_y", text="Y")
|
||||
|
|
|
@ -481,7 +481,7 @@ class TOPBAR_MT_file_export(Menu):
|
|||
bl_owner_use_filter = False
|
||||
|
||||
def draw(self, _context):
|
||||
self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj) - New")
|
||||
self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj)")
|
||||
if bpy.app.build_options.collada:
|
||||
self.layout.operator("wm.collada_export",
|
||||
text="Collada (Default) (.dae)")
|
||||
|
@ -832,6 +832,14 @@ class TOPBAR_PT_name(Panel):
|
|||
row = row_with_icon(layout, 'NODE')
|
||||
row.prop(item, "label", text="")
|
||||
found = True
|
||||
elif space_type == 'NLA_EDITOR':
|
||||
layout.label(text="NLA Strip Name")
|
||||
item = next(
|
||||
(strip for strip in context.selected_nla_strips if strip.active), None)
|
||||
if item:
|
||||
row = row_with_icon(layout, 'NLA')
|
||||
row.prop(item, "name", text="")
|
||||
found = True
|
||||
else:
|
||||
if mode == 'POSE' or (mode == 'WEIGHT_PAINT' and context.pose_object):
|
||||
layout.label(text="Bone Name")
|
||||
|
|
|
@ -2227,7 +2227,9 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
|||
bl_label = "Prototypes"
|
||||
|
||||
def draw(self, context):
|
||||
self._draw_items(context, (({"property": "use_new_hair_type"}, "T68981"),
|
||||
self._draw_items(
|
||||
context, (
|
||||
({"property": "use_new_curves_type"}, "T68981"),
|
||||
({"property": "use_new_point_cloud_type"}, "T75717"),
|
||||
({"property": "use_full_frame_compositor"}, "T88150"),),)
|
||||
|
||||
|
@ -2245,7 +2247,6 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
|
|||
def draw(self, context):
|
||||
self._draw_items(context, (({"property": "use_undo_legacy"}, "T60695"),
|
||||
({"property": "override_auto_resync"}, "T83811"),
|
||||
({"property": "proxy_to_override_auto_conversion"}, "T91671"),
|
||||
({"property": "use_cycles_debug"}, None),
|
||||
({"property": "use_geometry_nodes_legacy"}, "T91274"),
|
||||
({"property": "show_asset_debug_info"}, None),
|
||||
|
|
|
@ -2223,8 +2223,8 @@ class VIEW3D_MT_add(Menu):
|
|||
layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE')
|
||||
layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META')
|
||||
layout.operator("object.text_add", text="Text", icon='OUTLINER_OB_FONT')
|
||||
if context.preferences.experimental.use_new_hair_type:
|
||||
layout.operator("object.hair_add", text="Hair", icon='OUTLINER_OB_HAIR')
|
||||
if context.preferences.experimental.use_new_curves_type:
|
||||
layout.operator("object.hair_curves_add", text="Hair Curves", icon='OUTLINER_OB_CURVES')
|
||||
if context.preferences.experimental.use_new_point_cloud_type:
|
||||
layout.operator("object.pointcloud_add", text="Point Cloud", icon='OUTLINER_OB_POINTCLOUD')
|
||||
layout.menu("VIEW3D_MT_volume_add", text="Volume", icon='OUTLINER_OB_VOLUME')
|
||||
|
@ -2299,8 +2299,6 @@ class VIEW3D_MT_object_relations(Menu):
|
|||
|
||||
layout.operator("object.make_override_library", text="Make Library Override...")
|
||||
|
||||
layout.operator("object.convert_proxy_to_override")
|
||||
|
||||
layout.operator("object.make_dupli_face")
|
||||
|
||||
layout.separator()
|
||||
|
|
|
@ -547,6 +547,8 @@ compositor_node_categories = [
|
|||
NodeItem("CompositorNodeCombYUVA"),
|
||||
NodeItem("CompositorNodeSepYCCA"),
|
||||
NodeItem("CompositorNodeCombYCCA"),
|
||||
NodeItem("CompositorNodeSeparateXYZ"),
|
||||
NodeItem("CompositorNodeCombineXYZ"),
|
||||
NodeItem("CompositorNodeSwitchView"),
|
||||
NodeItem("CompositorNodeConvertColorSpace"),
|
||||
]),
|
||||
|
|
|
@ -48,7 +48,7 @@ set(SRC_DNA_INC
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_modifier_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpencil_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_gpu_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_hair_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_curves_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_image_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_ipo_types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_key_types.h
|
||||
|
|
|
@ -65,6 +65,7 @@ else()
|
|||
)
|
||||
|
||||
add_executable(blender-thumbnailer ${SRC} ${SRC_CMD})
|
||||
setup_platform_linker_flags(blender-thumbnailer)
|
||||
target_link_libraries(blender-thumbnailer bf_blenlib)
|
||||
target_link_libraries(blender-thumbnailer ${PTHREADS_LIBRARIES})
|
||||
endif()
|
||||
|
|
|
@ -309,7 +309,7 @@ void BLF_thumb_preview(const char *filename,
|
|||
/* blf_default.c */
|
||||
|
||||
void BLF_default_dpi(int dpi);
|
||||
void BLF_default_size(int size);
|
||||
void BLF_default_size(float size);
|
||||
void BLF_default_set(int fontid);
|
||||
/**
|
||||
* Get default font ID so we can pass it to other functions.
|
||||
|
|
|
@ -63,10 +63,6 @@ if(WIN32)
|
|||
)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
add_definitions(-DWITH_INTERNATIONAL)
|
||||
endif()
|
||||
|
||||
if(WITH_PYTHON)
|
||||
add_definitions(-DWITH_PYTHON)
|
||||
list(APPEND INC
|
||||
|
|
|
@ -37,15 +37,15 @@
|
|||
/* Default size and dpi, for BLF_draw_default. */
|
||||
static int global_font_default = -1;
|
||||
static int global_font_dpi = 72;
|
||||
/* Keep in sync with `UI_style_get()->widgetlabel.points` */
|
||||
static int global_font_size = 11;
|
||||
/* Keep in sync with `UI_DEFAULT_TEXT_POINTS` */
|
||||
static float global_font_size = 11.0f;
|
||||
|
||||
void BLF_default_dpi(int dpi)
|
||||
{
|
||||
global_font_dpi = dpi;
|
||||
}
|
||||
|
||||
void BLF_default_size(int size)
|
||||
void BLF_default_size(float size)
|
||||
{
|
||||
global_font_size = size;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_ADVANCES_H /* For FT_Get_Advance */
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -826,7 +825,10 @@ float blf_font_height(FontBLF *font,
|
|||
|
||||
float blf_font_fixed_width(FontBLF *font)
|
||||
{
|
||||
return (float)font->fixed_width;
|
||||
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
|
||||
float width = (gc) ? (float)gc->fixed_width : font->size / 2.0f;
|
||||
blf_glyph_cache_release(font);
|
||||
return width;
|
||||
}
|
||||
|
||||
static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font,
|
||||
|
@ -1236,6 +1238,12 @@ FontBLF *blf_font_new(const char *name, const char *filename)
|
|||
font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
|
||||
err = FT_New_Face(ft_lib, filename, 0, &font->face);
|
||||
if (err) {
|
||||
if (ELEM(err, FT_Err_Unknown_File_Format, FT_Err_Unimplemented_Feature)) {
|
||||
printf("Format of this font file is not supported\n");
|
||||
}
|
||||
else {
|
||||
printf("Error encountered while opening font file\n");
|
||||
}
|
||||
MEM_freeN(font);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1318,12 +1326,7 @@ FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int m
|
|||
|
||||
void blf_font_free(FontBLF *font)
|
||||
{
|
||||
BLI_spin_lock(&blf_glyph_cache_mutex);
|
||||
GlyphCacheBLF *gc;
|
||||
|
||||
while ((gc = BLI_pophead(&font->cache))) {
|
||||
blf_glyph_cache_free(gc);
|
||||
}
|
||||
blf_glyph_cache_clear(font);
|
||||
|
||||
if (font->kerning_cache) {
|
||||
MEM_freeN(font->kerning_cache);
|
||||
|
@ -1337,8 +1340,6 @@ void blf_font_free(FontBLF *font)
|
|||
MEM_freeN(font->name);
|
||||
}
|
||||
MEM_freeN(font);
|
||||
|
||||
BLI_spin_unlock(&blf_glyph_cache_mutex);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1347,51 +1348,25 @@ void blf_font_free(FontBLF *font)
|
|||
/** \name Font Configure
|
||||
* \{ */
|
||||
|
||||
void blf_font_size(FontBLF *font, float size, unsigned int dpi)
|
||||
bool blf_font_size(FontBLF *font, float size, unsigned int dpi)
|
||||
{
|
||||
blf_glyph_cache_acquire(font);
|
||||
|
||||
/* FreeType uses fixed-point integers in 64ths. */
|
||||
FT_F26Dot6 ft_size = lroundf(size * 64.0f);
|
||||
/* Adjust our size to be on even 64ths. */
|
||||
/* Adjust our new size to be on even 64ths. */
|
||||
size = (float)ft_size / 64.0f;
|
||||
|
||||
GlyphCacheBLF *gc = blf_glyph_cache_find(font, size, dpi);
|
||||
if (gc && (font->size == size && font->dpi == dpi)) {
|
||||
/* Optimization: do not call FT_Set_Char_Size if size did not change. */
|
||||
}
|
||||
else {
|
||||
const FT_Error err = FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi);
|
||||
if (err) {
|
||||
/* FIXME: here we can go through the fixed size and choice a close one */
|
||||
printf("The current font don't support the size, %f and dpi, %u\n", size, dpi);
|
||||
}
|
||||
else {
|
||||
if (font->size != size || font->dpi != dpi) {
|
||||
if (FT_Set_Char_Size(font->face, 0, ft_size, dpi, dpi) == 0) {
|
||||
font->size = size;
|
||||
font->dpi = dpi;
|
||||
if (gc == NULL) {
|
||||
blf_glyph_cache_new(font);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("The current font does not support the size, %f and dpi, %u\n", size, dpi);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
blf_glyph_cache_release(font);
|
||||
|
||||
/* Set fixed-width size for monospaced output. */
|
||||
FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
|
||||
if (gindex) {
|
||||
FT_Fixed advance = 0;
|
||||
FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
|
||||
/* Use CSS 'ch unit' width, advance of zero character. */
|
||||
font->fixed_width = (int)(advance >> 16);
|
||||
}
|
||||
else {
|
||||
/* Font does not contain "0" so use CSS fallback of 1/2 of em. */
|
||||
font->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
|
||||
}
|
||||
if (font->fixed_width < 1) {
|
||||
font->fixed_width = 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include FT_GLYPH_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_BITMAP_H
|
||||
#include FT_ADVANCES_H /* For FT_Get_Advance. */
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
@ -73,7 +74,7 @@ static FT_Fixed to_16dot16(double val)
|
|||
/** \name Glyph Cache
|
||||
* \{ */
|
||||
|
||||
GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
|
||||
static GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
|
||||
{
|
||||
GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
|
||||
while (gc) {
|
||||
|
@ -86,7 +87,7 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, float size, unsigned int dpi)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
|
||||
static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
|
||||
{
|
||||
GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
|
||||
|
||||
|
@ -100,6 +101,22 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
|
|||
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
|
||||
memset(gc->bucket, 0, sizeof(gc->bucket));
|
||||
|
||||
/* Determine ideal fixed-width size for monospaced output. */
|
||||
FT_UInt gindex = FT_Get_Char_Index(font->face, U'0');
|
||||
if (gindex) {
|
||||
FT_Fixed advance = 0;
|
||||
FT_Get_Advance(font->face, gindex, FT_LOAD_NO_HINTING, &advance);
|
||||
/* Use CSS 'ch unit' width, advance of zero character. */
|
||||
gc->fixed_width = (int)(advance >> 16);
|
||||
}
|
||||
else {
|
||||
/* Font does not contain "0" so use CSS fallback of 1/2 of em. */
|
||||
gc->fixed_width = (int)((font->face->size->metrics.height / 2) >> 6);
|
||||
}
|
||||
if (gc->fixed_width < 1) {
|
||||
gc->fixed_width = 1;
|
||||
}
|
||||
|
||||
BLI_addhead(&font->cache, gc);
|
||||
return gc;
|
||||
}
|
||||
|
@ -122,20 +139,7 @@ void blf_glyph_cache_release(FontBLF *font)
|
|||
BLI_spin_unlock(font->glyph_cache_mutex);
|
||||
}
|
||||
|
||||
void blf_glyph_cache_clear(FontBLF *font)
|
||||
{
|
||||
GlyphCacheBLF *gc;
|
||||
|
||||
BLI_spin_lock(font->glyph_cache_mutex);
|
||||
|
||||
while ((gc = BLI_pophead(&font->cache))) {
|
||||
blf_glyph_cache_free(gc);
|
||||
}
|
||||
|
||||
BLI_spin_unlock(font->glyph_cache_mutex);
|
||||
}
|
||||
|
||||
void blf_glyph_cache_free(GlyphCacheBLF *gc)
|
||||
static void blf_glyph_cache_free(GlyphCacheBLF *gc)
|
||||
{
|
||||
GlyphBLF *g;
|
||||
for (uint i = 0; i < ARRAY_SIZE(gc->bucket); i++) {
|
||||
|
@ -152,6 +156,19 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
|
|||
MEM_freeN(gc);
|
||||
}
|
||||
|
||||
void blf_glyph_cache_clear(FontBLF *font)
|
||||
{
|
||||
GlyphCacheBLF *gc;
|
||||
|
||||
BLI_spin_lock(font->glyph_cache_mutex);
|
||||
|
||||
while ((gc = BLI_pophead(&font->cache))) {
|
||||
blf_glyph_cache_free(gc);
|
||||
}
|
||||
|
||||
BLI_spin_unlock(font->glyph_cache_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a glyph in cache.
|
||||
*
|
||||
|
|
|
@ -56,7 +56,11 @@ struct FontBLF *blf_font_new(const char *name, const char *filename);
|
|||
struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size);
|
||||
void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size);
|
||||
|
||||
void blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
|
||||
/**
|
||||
* Change font's output size. Returns true if successful in changing the size.
|
||||
*/
|
||||
bool blf_font_size(struct FontBLF *font, float size, unsigned int dpi);
|
||||
|
||||
void blf_font_draw(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
|
@ -65,10 +69,7 @@ void blf_font_draw__wrap(struct FontBLF *font,
|
|||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
void blf_font_draw_ascii(struct FontBLF *font,
|
||||
const char *str,
|
||||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
|
||||
/**
|
||||
* Use fixed column width, but an utf8 character may occupy multiple columns.
|
||||
*/
|
||||
|
@ -137,18 +138,9 @@ int blf_font_count_missing_chars(struct FontBLF *font,
|
|||
|
||||
void blf_font_free(struct FontBLF *font);
|
||||
|
||||
/**
|
||||
* Find a glyph cache that matches a size, DPI & styles.
|
||||
*/
|
||||
struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, float size, unsigned int dpi);
|
||||
/**
|
||||
* Create a new glyph cache for the current size, DPI & styles.
|
||||
*/
|
||||
struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font);
|
||||
struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font);
|
||||
void blf_glyph_cache_release(struct FontBLF *font);
|
||||
void blf_glyph_cache_clear(struct FontBLF *font);
|
||||
void blf_glyph_cache_free(struct GlyphCacheBLF *gc);
|
||||
|
||||
/**
|
||||
* Create (or load from cache) a fully-rendered bitmap glyph.
|
||||
|
|
|
@ -73,6 +73,9 @@ typedef struct GlyphCacheBLF {
|
|||
bool bold;
|
||||
bool italic;
|
||||
|
||||
/* Column width when printing monospaced. */
|
||||
int fixed_width;
|
||||
|
||||
/* and the glyphs. */
|
||||
ListBase bucket[257];
|
||||
|
||||
|
@ -207,9 +210,6 @@ typedef struct FontBLF {
|
|||
/* font size. */
|
||||
float size;
|
||||
|
||||
/* Column width when printing monospaced. */
|
||||
int fixed_width;
|
||||
|
||||
/* max texture size. */
|
||||
int tex_size_max;
|
||||
|
||||
|
|
|
@ -61,7 +61,6 @@ void BLF_thumb_preview(const char *filename,
|
|||
int font_shrink = 4;
|
||||
|
||||
FontBLF *font;
|
||||
GlyphCacheBLF *gc;
|
||||
|
||||
/* Create a new blender font obj and fill it with default values */
|
||||
font = blf_font_new("thumb_font", filename);
|
||||
|
@ -90,10 +89,8 @@ void BLF_thumb_preview(const char *filename,
|
|||
const size_t draw_str_i18n_len = strlen(draw_str_i18n);
|
||||
int draw_str_i18n_nbr = 0;
|
||||
|
||||
blf_font_size(font, (float)MAX2(font_size_min, font_size_curr), dpi);
|
||||
gc = blf_glyph_cache_find(font, font->size, font->dpi);
|
||||
/* There will be no matching glyph cache if blf_font_size() failed to set font size. */
|
||||
if (!gc) {
|
||||
CLAMP_MIN(font_size_curr, font_size_min);
|
||||
if (!blf_font_size(font, (float)font_size_curr, dpi)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,14 +104,6 @@ typedef enum DerivedMeshType {
|
|||
DM_TYPE_CCGDM,
|
||||
} DerivedMeshType;
|
||||
|
||||
typedef enum DMDirtyFlag {
|
||||
/* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */
|
||||
DM_DIRTY_TESS_CDLAYERS = 1 << 0,
|
||||
|
||||
/* check this with modifier dependsOnNormals callback to see if normals need recalculation */
|
||||
DM_DIRTY_NORMALS = 1 << 1,
|
||||
} DMDirtyFlag;
|
||||
|
||||
typedef struct DerivedMesh DerivedMesh;
|
||||
struct DerivedMesh {
|
||||
/** Private DerivedMesh data, only for internal DerivedMesh use */
|
||||
|
@ -120,7 +112,6 @@ struct DerivedMesh {
|
|||
int needsFree; /* checked on ->release, is set to 0 for cached results */
|
||||
int deformedOnly; /* set by modifier stack if only deformed from original */
|
||||
DerivedMeshType type;
|
||||
DMDirtyFlag dirty;
|
||||
|
||||
/**
|
||||
* \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
|
||||
|
@ -139,9 +130,6 @@ struct DerivedMesh {
|
|||
|
||||
short tangent_mask; /* which tangent layers are calculated */
|
||||
|
||||
/** Calculate vert and face normals */
|
||||
void (*calcNormals)(DerivedMesh *dm);
|
||||
|
||||
/** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
|
||||
void (*recalcLoopTri)(DerivedMesh *dm);
|
||||
/** accessor functions */
|
||||
|
@ -164,7 +152,6 @@ struct DerivedMesh {
|
|||
*/
|
||||
struct MVert *(*getVertArray)(DerivedMesh *dm);
|
||||
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
|
||||
struct MFace *(*getTessFaceArray)(DerivedMesh *dm);
|
||||
struct MLoop *(*getLoopArray)(DerivedMesh *dm);
|
||||
struct MPoly *(*getPolyArray)(DerivedMesh *dm);
|
||||
|
||||
|
@ -173,7 +160,6 @@ struct DerivedMesh {
|
|||
*/
|
||||
void (*copyVertArray)(DerivedMesh *dm, struct MVert *r_vert);
|
||||
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge);
|
||||
void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *r_face);
|
||||
void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop);
|
||||
void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly);
|
||||
|
||||
|
@ -182,37 +168,18 @@ struct DerivedMesh {
|
|||
*/
|
||||
struct MVert *(*dupVertArray)(DerivedMesh *dm);
|
||||
struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
|
||||
struct MFace *(*dupTessFaceArray)(DerivedMesh *dm);
|
||||
struct MLoop *(*dupLoopArray)(DerivedMesh *dm);
|
||||
struct MPoly *(*dupPolyArray)(DerivedMesh *dm);
|
||||
|
||||
/** Return a pointer to a single element of vert/edge/face custom data
|
||||
* from the derived mesh (this gives a pointer to the actual data, not
|
||||
* a copy)
|
||||
*/
|
||||
void *(*getVertData)(DerivedMesh *dm, int index, int type);
|
||||
void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
|
||||
void *(*getTessFaceData)(DerivedMesh *dm, int index, int type);
|
||||
void *(*getPolyData)(DerivedMesh *dm, int index, int type);
|
||||
|
||||
/** Return a pointer to the entire array of vert/edge/face custom data
|
||||
* from the derived mesh (this gives a pointer to the actual data, not
|
||||
* a copy)
|
||||
*/
|
||||
void *(*getVertDataArray)(DerivedMesh *dm, int type);
|
||||
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
|
||||
void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
|
||||
void *(*getLoopDataArray)(DerivedMesh *dm, int type);
|
||||
void *(*getPolyDataArray)(DerivedMesh *dm, int type);
|
||||
|
||||
/** Retrieves the base CustomData structures for
|
||||
* verts/edges/tessfaces/loops/faces. */
|
||||
CustomData *(*getVertDataLayout)(DerivedMesh *dm);
|
||||
CustomData *(*getEdgeDataLayout)(DerivedMesh *dm);
|
||||
CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm);
|
||||
CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
|
||||
CustomData *(*getPolyDataLayout)(DerivedMesh *dm);
|
||||
|
||||
/** Optional grid access for subsurf */
|
||||
int (*getNumGrids)(DerivedMesh *dm);
|
||||
int (*getGridSize)(DerivedMesh *dm);
|
||||
|
@ -231,11 +198,6 @@ struct DerivedMesh {
|
|||
|
||||
/** Get smooth vertex normal, undefined if index is not valid */
|
||||
void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]);
|
||||
void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]);
|
||||
|
||||
/** Get a map of vertices to faces
|
||||
*/
|
||||
const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm);
|
||||
|
||||
/** Release reference to the DerivedMesh. This function decides internally
|
||||
* if the DerivedMesh will be freed, or cached for later use. */
|
||||
|
@ -265,15 +227,6 @@ void DM_init(DerivedMesh *dm,
|
|||
* Utility function to initialize a DerivedMesh for the desired number
|
||||
* of vertices, edges and faces, with a layer setup copied from source
|
||||
*/
|
||||
void DM_from_template_ex(DerivedMesh *dm,
|
||||
DerivedMesh *source,
|
||||
DerivedMeshType type,
|
||||
int numVerts,
|
||||
int numEdges,
|
||||
int numTessFaces,
|
||||
int numLoops,
|
||||
int numPolys,
|
||||
const struct CustomData_MeshMasks *mask);
|
||||
void DM_from_template(DerivedMesh *dm,
|
||||
DerivedMesh *source,
|
||||
DerivedMeshType type,
|
||||
|
@ -303,25 +256,8 @@ void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask);
|
|||
|
||||
void DM_add_vert_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
|
||||
void DM_add_edge_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
|
||||
void DM_add_tessface_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
|
||||
void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
|
||||
void DM_add_poly_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Custom Data Access Functions
|
||||
*
|
||||
* \return pointer to data from first layer which matches type
|
||||
* if they return NULL for valid indices, data doesn't exist.
|
||||
* \note these return pointers - any change modifies the internals of the mesh.
|
||||
* \{ */
|
||||
|
||||
void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type);
|
||||
void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type);
|
||||
void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type);
|
||||
void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Custom Data Layer Access Functions
|
||||
*
|
||||
|
@ -332,7 +268,6 @@ void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
|
|||
|
||||
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
|
||||
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
|
||||
void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
|
||||
void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type);
|
||||
void *DM_get_loop_data_layer(struct DerivedMesh *dm, int type);
|
||||
|
||||
|
@ -354,8 +289,6 @@ void DM_copy_vert_data(struct DerivedMesh *source,
|
|||
*/
|
||||
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
|
||||
|
||||
void DM_ensure_normals(DerivedMesh *dm);
|
||||
|
||||
/**
|
||||
* Ensure the array is large enough.
|
||||
*
|
||||
|
@ -401,11 +334,6 @@ void makeDerivedMesh(struct Depsgraph *depsgraph,
|
|||
struct Object *ob,
|
||||
const struct CustomData_MeshMasks *dataMask);
|
||||
|
||||
void DM_calc_loop_tangents(DerivedMesh *dm,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -365,7 +365,6 @@ void what_does_obaction(struct Object *ob,
|
|||
char groupname[],
|
||||
const struct AnimationEvalContext *anim_eval_context);
|
||||
|
||||
/* for proxy */
|
||||
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
|
||||
const struct bPoseChannel *pchanfrom);
|
||||
/**
|
||||
|
|
|
@ -163,6 +163,30 @@ void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], bool d
|
|||
/* Bounding box. */
|
||||
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
|
||||
|
||||
/**
|
||||
* Calculate the axis-aligned bounds of `pchan` in world-space,
|
||||
* taking into account custom transform when set.
|
||||
*
|
||||
* `r_min` and `r_max` are expanded to fit `pchan` so the caller must initialize them
|
||||
* (typically using #INIT_MINMAX).
|
||||
*
|
||||
* \note The bounds are calculated based on the head & tail of the bone
|
||||
* or the custom object's bounds (if the bone uses a custom object).
|
||||
* Visual elements such as the envelopes radius & bendy-bone spline segments are *not* included,
|
||||
* making this not so useful for viewport culling.
|
||||
*/
|
||||
void BKE_pchan_minmax(const struct Object *ob,
|
||||
const struct bPoseChannel *pchan,
|
||||
float r_min[3],
|
||||
float r_max[3]);
|
||||
/**
|
||||
* Calculate the axis aligned bounds of the pose of `ob` in world-space.
|
||||
|
||||
* `r_min` and `r_max` are expanded to fit `ob->pose` so the caller must initialize them
|
||||
* (typically using #INIT_MINMAX).
|
||||
*
|
||||
* \note This uses #BKE_pchan_minmax, see its documentation for details on bounds calculation.
|
||||
*/
|
||||
bool BKE_pose_minmax(
|
||||
struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
|
||||
|
||||
|
@ -619,14 +643,6 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph,
|
|||
struct Scene *scene,
|
||||
struct Object *object);
|
||||
|
||||
void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, struct Object *object);
|
||||
void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, struct Object *object);
|
||||
void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, struct Object *object);
|
||||
|
||||
void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
|
||||
struct Object *object,
|
||||
int pchan_index);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Deform 3D Coordinates by Armature (armature_deform.c)
|
||||
* \{ */
|
||||
|
|
|
@ -41,11 +41,11 @@ struct AttributeRef;
|
|||
/* Attribute.domain */
|
||||
typedef enum AttributeDomain {
|
||||
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
|
||||
ATTR_DOMAIN_POINT = 0, /* Mesh, Curve or Point Cloud Point */
|
||||
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
|
||||
ATTR_DOMAIN_FACE = 2, /* Mesh Face */
|
||||
ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
|
||||
ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
|
||||
ATTR_DOMAIN_CURVE = 4, /* A single curve in a larger curve data-block */
|
||||
ATTR_DOMAIN_INSTANCE = 5, /* Instance */
|
||||
|
||||
ATTR_DOMAIN_NUM
|
||||
|
|
|
@ -50,6 +50,9 @@ inline void convert_to_static_type(const CustomDataType data_type, const Func &f
|
|||
case CD_PROP_BOOL:
|
||||
func(bool());
|
||||
break;
|
||||
case CD_PROP_INT8:
|
||||
func(int8_t());
|
||||
break;
|
||||
case CD_PROP_COLOR:
|
||||
func(ColorGeometry4f());
|
||||
break;
|
||||
|
@ -77,6 +80,9 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
|
|||
else if (cpp_type.is<bool>()) {
|
||||
func(bool());
|
||||
}
|
||||
else if (cpp_type.is<int8_t>()) {
|
||||
func(int8_t());
|
||||
}
|
||||
else if (cpp_type.is<ColorGeometry4f>()) {
|
||||
func(ColorGeometry4f());
|
||||
}
|
||||
|
@ -93,6 +99,12 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
|
|||
|
||||
template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
|
||||
|
||||
template<>
|
||||
inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
|
||||
{
|
||||
return static_cast<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
|
||||
}
|
||||
|
||||
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
|
||||
{
|
||||
return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
|
||||
|
@ -147,6 +159,11 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b)
|
|||
return ((1.0f - factor) * a + factor * b) >= 0.5f;
|
||||
}
|
||||
|
||||
template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
|
||||
{
|
||||
return static_cast<int8_t>((1.0f - factor) * a + factor * b);
|
||||
}
|
||||
|
||||
template<> inline int mix2(const float factor, const int &a, const int &b)
|
||||
{
|
||||
return static_cast<int>((1.0f - factor) * a + factor * b);
|
||||
|
@ -364,6 +381,15 @@ template<> struct DefaultMixerStruct<bool> {
|
|||
using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>;
|
||||
};
|
||||
|
||||
template<> struct DefaultMixerStruct<int8_t> {
|
||||
static int8_t float_to_int8_t(const float &value)
|
||||
{
|
||||
return static_cast<int8_t>(value);
|
||||
}
|
||||
/* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
|
||||
using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
|
||||
};
|
||||
|
||||
template<typename T> struct DefaultPropatationMixerStruct {
|
||||
/* Use void by default. This can be checked for in `if constexpr` statements. */
|
||||
using type = typename DefaultMixerStruct<T>::type;
|
||||
|
|
|
@ -39,7 +39,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 0
|
||||
#define BLENDER_FILE_SUBVERSION 3
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and show a warning if the file
|
||||
|
|
|
@ -123,11 +123,20 @@ struct Collection *BKE_collection_object_find(struct Main *bmain,
|
|||
bool BKE_collection_is_empty(const struct Collection *collection);
|
||||
|
||||
/**
|
||||
* Add object to collection
|
||||
* Add object to given collection, ensuring this collection is 'editable' (i.e. local and not a
|
||||
* liboverride), and finding a suitable parent one otherwise.
|
||||
*/
|
||||
bool BKE_collection_object_add(struct Main *bmain,
|
||||
struct Collection *collection,
|
||||
struct Object *ob);
|
||||
/**
|
||||
* Same as #BKE_collection_object_add, but unconditionally adds the object to the given collection.
|
||||
*
|
||||
* NOTE: required in certain cases, like do-versioning or complex ID management tasks.
|
||||
*/
|
||||
bool BKE_collection_object_add_notest(struct Main *bmain,
|
||||
struct Collection *collection,
|
||||
struct Object *ob);
|
||||
/**
|
||||
* Add \a ob_dst to all scene collections that reference object \a ob_src is in.
|
||||
* Used for copying objects.
|
||||
|
|
|
@ -278,18 +278,6 @@ bool BKE_constraint_apply_and_remove_for_pose(struct Depsgraph *depsgraph,
|
|||
|
||||
void BKE_constraint_panel_expand(struct bConstraint *con);
|
||||
|
||||
/* Constraints + Proxies function prototypes */
|
||||
|
||||
/**
|
||||
* Rescue all constraints tagged as being #CONSTRAINT_PROXY_LOCAL
|
||||
* (i.e. added to bone that's proxy-synced in this file).
|
||||
*/
|
||||
void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *src);
|
||||
/**
|
||||
* Returns if the owner of the constraint is proxy-protected.
|
||||
*/
|
||||
bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan);
|
||||
|
||||
/* Constraint Evaluation function prototypes */
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief Low-level operations for curves.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct BoundBox;
|
||||
struct CustomDataLayer;
|
||||
struct Depsgraph;
|
||||
struct Curves;
|
||||
struct Main;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
void *BKE_curves_add(struct Main *bmain, const char *name);
|
||||
|
||||
struct BoundBox *BKE_curves_boundbox_get(struct Object *ob);
|
||||
|
||||
void BKE_curves_update_customdata_pointers(struct Curves *curves);
|
||||
bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer);
|
||||
|
||||
/* Depsgraph */
|
||||
|
||||
struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src,
|
||||
int totpoint,
|
||||
int totcurve);
|
||||
struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
|
||||
|
||||
void BKE_curves_data_update(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *object);
|
||||
|
||||
/* Draw Cache */
|
||||
|
||||
enum {
|
||||
BKE_CURVES_BATCH_DIRTY_ALL = 0,
|
||||
};
|
||||
|
||||
void BKE_curves_batch_cache_dirty_tag(struct Curves *curves, int mode);
|
||||
void BKE_curves_batch_cache_free(struct Curves *curves);
|
||||
|
||||
extern void (*BKE_curves_batch_cache_dirty_tag_cb)(struct Curves *curves, int mode);
|
||||
extern void (*BKE_curves_batch_cache_free_cb)(struct Curves *curves);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -259,6 +259,11 @@ bool CustomData_free_layer_active(struct CustomData *data, int type, int totelem
|
|||
*/
|
||||
void CustomData_free_layers(struct CustomData *data, int type, int totelem);
|
||||
|
||||
/**
|
||||
* Free all anonymous attributes.
|
||||
*/
|
||||
void CustomData_free_layers_anonymous(struct CustomData *data, int totelem);
|
||||
|
||||
/**
|
||||
* Returns true if a layer with the specified type exists.
|
||||
*/
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \brief General operations for hairs.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct BoundBox;
|
||||
struct CustomDataLayer;
|
||||
struct Depsgraph;
|
||||
struct Hair;
|
||||
struct Main;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
||||
void *BKE_hair_add(struct Main *bmain, const char *name);
|
||||
|
||||
struct BoundBox *BKE_hair_boundbox_get(struct Object *ob);
|
||||
|
||||
void BKE_hair_update_customdata_pointers(struct Hair *hair);
|
||||
bool BKE_hair_customdata_required(struct Hair *hair, struct CustomDataLayer *layer);
|
||||
|
||||
/* Depsgraph */
|
||||
|
||||
struct Hair *BKE_hair_new_for_eval(const struct Hair *hair_src, int totpoint, int totcurve);
|
||||
struct Hair *BKE_hair_copy_for_eval(struct Hair *hair_src, bool reference);
|
||||
|
||||
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object);
|
||||
|
||||
/* Draw Cache */
|
||||
|
||||
enum {
|
||||
BKE_HAIR_BATCH_DIRTY_ALL = 0,
|
||||
};
|
||||
|
||||
void BKE_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
|
||||
void BKE_hair_batch_cache_free(struct Hair *hair);
|
||||
|
||||
extern void (*BKE_hair_batch_cache_dirty_tag_cb)(struct Hair *hair, int mode);
|
||||
extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -278,7 +278,7 @@ extern IDTypeInfo IDType_ID_PC;
|
|||
extern IDTypeInfo IDType_ID_CF;
|
||||
extern IDTypeInfo IDType_ID_WS;
|
||||
extern IDTypeInfo IDType_ID_LP;
|
||||
extern IDTypeInfo IDType_ID_HA;
|
||||
extern IDTypeInfo IDType_ID_CV;
|
||||
extern IDTypeInfo IDType_ID_PT;
|
||||
extern IDTypeInfo IDType_ID_VO;
|
||||
extern IDTypeInfo IDType_ID_SIM;
|
||||
|
|
|
@ -23,8 +23,8 @@
|
|||
* image that are changed. These areas are organized in chunks. Changes that happen over time are
|
||||
* organized in changesets.
|
||||
*
|
||||
* A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
|
||||
* changed.
|
||||
* A common use case is to update #GPUTexture for drawing where only that part is uploaded that
|
||||
* only changed.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
|
|
@ -376,10 +376,6 @@ enum {
|
|||
/** Clear asset data (in case the ID can actually be made local, in copy case asset data is never
|
||||
* copied over). */
|
||||
LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR = 1 << 3,
|
||||
|
||||
/* Special type-specific options. */
|
||||
/** For Objects, do not clear the proxy pointers while making the data-block local. */
|
||||
LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING = 1 << 16,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -100,6 +100,9 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
|
|||
* main. You can add more local IDs to be remapped to use new overriding ones by setting their
|
||||
* LIB_TAG_DOIT tag.
|
||||
*
|
||||
* \param owner_library: the library in which the overrides should be created. Besides versioning
|
||||
* and resync code path, this should always be NULL (i.e. the local .blend file).
|
||||
*
|
||||
* \param reference_library: the library from which the linked data being overridden come from
|
||||
* (i.e. the library of the linked reference ID).
|
||||
*
|
||||
|
@ -109,7 +112,8 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
|
|||
* \return \a true on success, \a false otherwise.
|
||||
*/
|
||||
bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
|
||||
const struct Library *reference_library,
|
||||
struct Library *owner_library,
|
||||
const struct ID *id_root_reference,
|
||||
bool do_no_main);
|
||||
/**
|
||||
* Advanced 'smart' function to create fully functional overrides.
|
||||
|
@ -122,16 +126,24 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
|
|||
*
|
||||
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
|
||||
* which case \a scene's master collection children hierarchy is used instead).
|
||||
*
|
||||
* \param owner_library: the library in which the overrides should be created. Besides versioning
|
||||
* and resync code path, this should always be NULL (i.e. the local .blend file).
|
||||
*
|
||||
* \param id_root: The root ID to create an override from.
|
||||
*
|
||||
* \param id_reference: Some reference ID used to do some post-processing after overrides have been
|
||||
* created, may be NULL. Typically, the Empty object instantiating the linked collection we
|
||||
* override, currently.
|
||||
*
|
||||
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
|
||||
*
|
||||
* \return true if override was successfully created.
|
||||
*/
|
||||
bool BKE_lib_override_library_create(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct ViewLayer *view_layer,
|
||||
struct Library *owner_library,
|
||||
struct ID *id_root,
|
||||
struct ID *id_reference,
|
||||
struct ID **r_id_root_override);
|
||||
|
@ -160,6 +172,15 @@ bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
|
|||
*/
|
||||
void BKE_lib_override_library_main_proxy_convert(struct Main *bmain,
|
||||
struct BlendFileReadReport *reports);
|
||||
|
||||
/**
|
||||
* Find and set the 'hierarchy root' ID pointer of all library overrides in given `bmain`.
|
||||
*
|
||||
* NOTE: Cannot be called from `do_versions_after_linking` as this code needs a single complete
|
||||
* Main database, not a split-by-libraries one.
|
||||
*/
|
||||
void BKE_lib_override_library_main_hierarchy_root_ensure(struct Main *bmain);
|
||||
|
||||
/**
|
||||
* Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
|
||||
* data, from an existing override hierarchy.
|
||||
|
|
|
@ -63,7 +63,7 @@ enum {
|
|||
|
||||
/**
|
||||
* That ID is not really used by its owner, it's just an internal hint/helper.
|
||||
* This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from.
|
||||
* This marks the 'from' pointers issue, like Key->from.
|
||||
* How to handle that kind of cases totally depends on what caller code is doing... */
|
||||
IDWALK_CB_LOOPBACK = (1 << 4),
|
||||
|
||||
|
@ -135,7 +135,6 @@ enum {
|
|||
/** Do not process ID pointers inside embedded IDs. Needed by depsgraph processing e.g. */
|
||||
IDWALK_IGNORE_EMBEDDED_ID = (1 << 3),
|
||||
|
||||
IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
|
||||
/** Also process internal ID pointers like `ID.newid` or `ID.orig_id`.
|
||||
* WARNING: Dangerous, use with caution. */
|
||||
IDWALK_DO_INTERNAL_RUNTIME_POINTERS = (1 << 9),
|
||||
|
|
|
@ -68,15 +68,6 @@ enum {
|
|||
* and can cause crashes very easily!
|
||||
*/
|
||||
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
|
||||
/**
|
||||
* Do not consider proxy/_group pointers of local objects as indirect usages...
|
||||
* Our oh-so-beloved proxies again...
|
||||
* Do not consider data used by local proxy object as indirect usage.
|
||||
* This is needed e.g. in reload scenario,
|
||||
* since we have to ensure remapping of Armature data of local proxy
|
||||
* is also performed. Usual nightmare...
|
||||
*/
|
||||
ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
|
||||
/** Do not remap library override pointers. */
|
||||
ID_REMAP_SKIP_OVERRIDE_LIBRARY = 1 << 5,
|
||||
/** Don't touch the user count (use for low level actions such as swapping pointers). */
|
||||
|
|
|
@ -182,7 +182,11 @@ typedef struct Main {
|
|||
ListBase linestyles;
|
||||
ListBase cachefiles;
|
||||
ListBase workspaces;
|
||||
ListBase hairs;
|
||||
/**
|
||||
* \note The name `hair_curves` is chosen to be different than `curves`,
|
||||
* but they are generic curve data-blocks, not just for hair.
|
||||
*/
|
||||
ListBase hair_curves;
|
||||
ListBase pointclouds;
|
||||
ListBase volumes;
|
||||
ListBase simulations;
|
||||
|
|
|
@ -245,10 +245,6 @@ typedef struct ModifierTypeInfo {
|
|||
const struct ModifierEvalContext *ctx,
|
||||
struct Mesh *mesh);
|
||||
|
||||
struct Hair *(*modifyHair)(struct ModifierData *md,
|
||||
const struct ModifierEvalContext *ctx,
|
||||
struct Hair *hair);
|
||||
|
||||
/**
|
||||
* The modifier has to change the geometry set in-place. The geometry set can contain zero or
|
||||
* more geometry components. This callback can be used by modifiers that don't work on any
|
||||
|
@ -470,6 +466,8 @@ void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *u
|
|||
|
||||
struct ModifierData *BKE_modifiers_findby_type(const struct Object *ob, ModifierType type);
|
||||
struct ModifierData *BKE_modifiers_findby_name(const struct Object *ob, const char *name);
|
||||
struct ModifierData *BKE_modifiers_findby_session_uuid(const struct Object *ob,
|
||||
const SessionUUID *session_uuid);
|
||||
void BKE_modifiers_clear_errors(struct Object *ob);
|
||||
/**
|
||||
* used for buttons, to find out if the 'draw deformed in edit-mode option is there.
|
||||
|
@ -568,7 +566,8 @@ const char *BKE_modifier_path_relbase_from_global(struct Object *ob);
|
|||
* For a given modifier data, get corresponding original one.
|
||||
* If the modifier data is already original, return it as-is.
|
||||
*/
|
||||
struct ModifierData *BKE_modifier_get_original(struct ModifierData *md);
|
||||
struct ModifierData *BKE_modifier_get_original(const struct Object *object,
|
||||
struct ModifierData *md);
|
||||
struct ModifierData *BKE_modifier_get_evaluated(struct Depsgraph *depsgraph,
|
||||
struct Object *object,
|
||||
struct ModifierData *md);
|
||||
|
|
|
@ -274,6 +274,9 @@ typedef struct bNodeType {
|
|||
char *label,
|
||||
int maxlen);
|
||||
|
||||
/** Optional override for node class, used for drawing node header. */
|
||||
int (*ui_class)(const struct bNode *node);
|
||||
|
||||
/** Called when the node is updated in the editor. */
|
||||
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
|
||||
/** Check and update if internal ID data has changed. */
|
||||
|
@ -1291,6 +1294,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
|
|||
#define CMP_NODE_POSTERIZE 327
|
||||
#define CMP_NODE_CONVERT_COLOR_SPACE 328
|
||||
#define CMP_NODE_SCENE_TIME 329
|
||||
#define CMP_NODE_SEPARATE_XYZ 330
|
||||
#define CMP_NODE_COMBINE_XYZ 331
|
||||
|
||||
/* channel toggles */
|
||||
#define CMP_CHAN_RGB 1
|
||||
|
|
|
@ -146,18 +146,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
|
|||
void BKE_object_free_modifiers(struct Object *ob, int flag);
|
||||
void BKE_object_free_shaderfx(struct Object *ob, int flag);
|
||||
|
||||
/**
|
||||
* Proxy rule:
|
||||
* - `lib_object->proxy_from` == the one we borrow from, set temporally while object_update.
|
||||
* - `local_object->proxy` == pointer to library object, saved in files and read.
|
||||
* - `local_object->proxy_group` == pointer to collection dupli-object, saved in files and read.
|
||||
*/
|
||||
void BKE_object_make_proxy(struct Main *bmain,
|
||||
struct Object *ob,
|
||||
struct Object *target,
|
||||
struct Object *cob);
|
||||
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
|
||||
|
||||
bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
|
||||
/**
|
||||
* Actual check for internal data, not context or flags.
|
||||
|
@ -446,7 +434,6 @@ void BKE_object_eval_constraints(struct Depsgraph *depsgraph,
|
|||
struct Object *ob);
|
||||
void BKE_object_eval_transform_final(struct Depsgraph *depsgraph, struct Object *ob);
|
||||
|
||||
bool BKE_object_eval_proxy_copy(struct Depsgraph *depsgraph, struct Object *object);
|
||||
void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *ob);
|
||||
void BKE_object_eval_uber_data(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
|
@ -488,12 +475,6 @@ void BKE_object_handle_data_update(struct Depsgraph *depsgraph,
|
|||
*/
|
||||
void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
|
||||
/**
|
||||
* Proxy rule:
|
||||
* - lib_object->proxy_from == the one we borrow from, only set temporal and cleared here.
|
||||
* - local_object->proxy == pointer to library object, saved in files and read.
|
||||
*
|
||||
* Function below is polluted with proxy exceptions, cleanup will follow!
|
||||
*
|
||||
* The main object update call, for object matrix, constraints, keys and #DispList (modifiers)
|
||||
* requires flags to be set!
|
||||
*
|
||||
|
@ -503,8 +484,7 @@ void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene,
|
|||
void BKE_object_handle_update_ex(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob,
|
||||
struct RigidBodyWorld *rbw,
|
||||
bool do_proxy_update);
|
||||
struct RigidBodyWorld *rbw);
|
||||
|
||||
void BKE_object_sculpt_data_create(struct Object *ob);
|
||||
|
||||
|
|
|
@ -710,10 +710,11 @@ typedef struct SculptSession {
|
|||
/* These are always assigned to base mesh data when using PBVH_FACES and PBVH_GRIDS. */
|
||||
struct MVert *mvert;
|
||||
struct MEdge *medge;
|
||||
const float (*vert_normals)[3];
|
||||
struct MLoop *mloop;
|
||||
struct MPoly *mpoly;
|
||||
|
||||
const float (*vert_normals)[3];
|
||||
|
||||
// only assigned in PBVH_FACES and PBVH_GRIDS
|
||||
CustomData *vdata, *edata, *ldata, *pdata;
|
||||
|
||||
|
|
|
@ -127,6 +127,7 @@ set(SRC
|
|||
intern/crazyspace.c
|
||||
intern/cryptomatte.cc
|
||||
intern/curve.cc
|
||||
intern/curves.cc
|
||||
intern/curve_bevel.c
|
||||
intern/curve_convert.c
|
||||
intern/curve_decimate.c
|
||||
|
@ -166,7 +167,6 @@ set(SRC
|
|||
intern/gpencil_curve.c
|
||||
intern/gpencil_geom.cc
|
||||
intern/gpencil_modifier.c
|
||||
intern/hair.cc
|
||||
intern/icons.cc
|
||||
intern/icons_rasterize.c
|
||||
intern/idprop.c
|
||||
|
@ -192,6 +192,7 @@ set(SRC
|
|||
intern/lib_id_eval.c
|
||||
intern/lib_id_remapper.cc
|
||||
intern/lib_override.c
|
||||
intern/lib_override_proxy_conversion.c
|
||||
intern/lib_query.c
|
||||
intern/lib_remap.c
|
||||
intern/library.c
|
||||
|
@ -367,6 +368,7 @@ set(SRC
|
|||
BKE_cryptomatte.h
|
||||
BKE_cryptomatte.hh
|
||||
BKE_curve.h
|
||||
BKE_curves.h
|
||||
BKE_curve_to_mesh.hh
|
||||
BKE_curveprofile.h
|
||||
BKE_customdata.h
|
||||
|
@ -396,7 +398,6 @@ set(SRC
|
|||
BKE_gpencil_curve.h
|
||||
BKE_gpencil_geom.h
|
||||
BKE_gpencil_modifier.h
|
||||
BKE_hair.h
|
||||
BKE_icons.h
|
||||
BKE_idprop.h
|
||||
BKE_idprop.hh
|
||||
|
@ -735,10 +736,6 @@ if(WITH_FFTW3)
|
|||
add_definitions(-DFFTW3=1)
|
||||
endif()
|
||||
|
||||
if(WITH_INTERNATIONAL)
|
||||
add_definitions(-DWITH_INTERNATIONAL)
|
||||
endif()
|
||||
|
||||
if(WITH_FREESTYLE)
|
||||
add_definitions(-DWITH_FREESTYLE)
|
||||
endif()
|
||||
|
|
|
@ -127,30 +127,6 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
|
|||
return medge;
|
||||
}
|
||||
|
||||
static MFace *dm_getTessFaceArray(DerivedMesh *dm)
|
||||
{
|
||||
MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
|
||||
|
||||
if (!mface) {
|
||||
int numTessFaces = dm->getNumTessFaces(dm);
|
||||
|
||||
if (!numTessFaces) {
|
||||
/* Do not add layer if there's no elements in it, this leads to issues later when
|
||||
* this layer is needed with non-zero size, but currently CD stuff does not check
|
||||
* for requested layer size on creation and just returns layer which was previously
|
||||
* added (sergey) */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mface = (MFace *)CustomData_add_layer(
|
||||
&dm->faceData, CD_MFACE, CD_CALLOC, nullptr, numTessFaces);
|
||||
CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
|
||||
dm->copyTessFaceArray(dm, mface);
|
||||
}
|
||||
|
||||
return mface;
|
||||
}
|
||||
|
||||
static MLoop *dm_getLoopArray(DerivedMesh *dm)
|
||||
{
|
||||
MLoop *mloop = (MLoop *)CustomData_get_layer(&dm->loopData, CD_MLOOP);
|
||||
|
@ -203,18 +179,6 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
static MFace *dm_dupFaceArray(DerivedMesh *dm)
|
||||
{
|
||||
MFace *tmp = (MFace *)MEM_malloc_arrayN(
|
||||
dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp");
|
||||
|
||||
if (tmp) {
|
||||
dm->copyTessFaceArray(dm, tmp);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static MLoop *dm_dupLoopArray(DerivedMesh *dm)
|
||||
{
|
||||
MLoop *tmp = (MLoop *)MEM_malloc_arrayN(
|
||||
|
@ -270,42 +234,15 @@ static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
|
|||
return looptri;
|
||||
}
|
||||
|
||||
static CustomData *dm_getVertCData(DerivedMesh *dm)
|
||||
{
|
||||
return &dm->vertData;
|
||||
}
|
||||
|
||||
static CustomData *dm_getEdgeCData(DerivedMesh *dm)
|
||||
{
|
||||
return &dm->edgeData;
|
||||
}
|
||||
|
||||
static CustomData *dm_getTessFaceCData(DerivedMesh *dm)
|
||||
{
|
||||
return &dm->faceData;
|
||||
}
|
||||
|
||||
static CustomData *dm_getLoopCData(DerivedMesh *dm)
|
||||
{
|
||||
return &dm->loopData;
|
||||
}
|
||||
|
||||
static CustomData *dm_getPolyCData(DerivedMesh *dm)
|
||||
{
|
||||
return &dm->polyData;
|
||||
}
|
||||
|
||||
void DM_init_funcs(DerivedMesh *dm)
|
||||
{
|
||||
/* default function implementations */
|
||||
dm->getVertArray = dm_getVertArray;
|
||||
dm->getEdgeArray = dm_getEdgeArray;
|
||||
dm->getTessFaceArray = dm_getTessFaceArray;
|
||||
dm->getLoopArray = dm_getLoopArray;
|
||||
dm->getPolyArray = dm_getPolyArray;
|
||||
dm->dupVertArray = dm_dupVertArray;
|
||||
dm->dupEdgeArray = dm_dupEdgeArray;
|
||||
dm->dupTessFaceArray = dm_dupFaceArray;
|
||||
dm->dupLoopArray = dm_dupLoopArray;
|
||||
dm->dupPolyArray = dm_dupPolyArray;
|
||||
|
||||
|
@ -314,19 +251,8 @@ void DM_init_funcs(DerivedMesh *dm)
|
|||
/* subtypes handle getting actual data */
|
||||
dm->getNumLoopTri = dm_getNumLoopTri;
|
||||
|
||||
dm->getVertDataLayout = dm_getVertCData;
|
||||
dm->getEdgeDataLayout = dm_getEdgeCData;
|
||||
dm->getTessFaceDataLayout = dm_getTessFaceCData;
|
||||
dm->getLoopDataLayout = dm_getLoopCData;
|
||||
dm->getPolyDataLayout = dm_getPolyCData;
|
||||
|
||||
dm->getVertData = DM_get_vert_data;
|
||||
dm->getEdgeData = DM_get_edge_data;
|
||||
dm->getTessFaceData = DM_get_tessface_data;
|
||||
dm->getPolyData = DM_get_poly_data;
|
||||
dm->getVertDataArray = DM_get_vert_data_layer;
|
||||
dm->getEdgeDataArray = DM_get_edge_data_layer;
|
||||
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
|
||||
dm->getPolyDataArray = DM_get_poly_data_layer;
|
||||
dm->getLoopDataArray = DM_get_loop_data_layer;
|
||||
}
|
||||
|
@ -349,7 +275,6 @@ void DM_init(DerivedMesh *dm,
|
|||
DM_init_funcs(dm);
|
||||
|
||||
dm->needsFree = 1;
|
||||
dm->dirty = (DMDirtyFlag)0;
|
||||
|
||||
/* Don't use #CustomData_reset because we don't want to touch custom-data. */
|
||||
copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
|
||||
|
@ -359,16 +284,16 @@ void DM_init(DerivedMesh *dm,
|
|||
copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
|
||||
}
|
||||
|
||||
void DM_from_template_ex(DerivedMesh *dm,
|
||||
DerivedMesh *source,
|
||||
DerivedMeshType type,
|
||||
int numVerts,
|
||||
int numEdges,
|
||||
int numTessFaces,
|
||||
int numLoops,
|
||||
int numPolys,
|
||||
const CustomData_MeshMasks *mask)
|
||||
void DM_from_template(DerivedMesh *dm,
|
||||
DerivedMesh *source,
|
||||
DerivedMeshType type,
|
||||
int numVerts,
|
||||
int numEdges,
|
||||
int numTessFaces,
|
||||
int numLoops,
|
||||
int numPolys)
|
||||
{
|
||||
const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
|
||||
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts);
|
||||
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges);
|
||||
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces);
|
||||
|
@ -387,26 +312,6 @@ void DM_from_template_ex(DerivedMesh *dm,
|
|||
DM_init_funcs(dm);
|
||||
|
||||
dm->needsFree = 1;
|
||||
dm->dirty = (DMDirtyFlag)0;
|
||||
}
|
||||
void DM_from_template(DerivedMesh *dm,
|
||||
DerivedMesh *source,
|
||||
DerivedMeshType type,
|
||||
int numVerts,
|
||||
int numEdges,
|
||||
int numTessFaces,
|
||||
int numLoops,
|
||||
int numPolys)
|
||||
{
|
||||
DM_from_template_ex(dm,
|
||||
source,
|
||||
type,
|
||||
numVerts,
|
||||
numEdges,
|
||||
numTessFaces,
|
||||
numLoops,
|
||||
numPolys,
|
||||
&CD_MASK_DERIVEDMESH);
|
||||
}
|
||||
|
||||
bool DM_release(DerivedMesh *dm)
|
||||
|
@ -464,14 +369,6 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
|
|||
}
|
||||
}
|
||||
|
||||
void DM_ensure_normals(DerivedMesh *dm)
|
||||
{
|
||||
if (dm->dirty & DM_DIRTY_NORMALS) {
|
||||
dm->calcNormals(dm);
|
||||
}
|
||||
BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
|
||||
}
|
||||
|
||||
void DM_ensure_looptri_data(DerivedMesh *dm)
|
||||
{
|
||||
const unsigned int totpoly = dm->numPolyData;
|
||||
|
@ -524,7 +421,7 @@ void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
|
|||
* see replies to r50969, Campbell */
|
||||
#if 0
|
||||
CustomData_set_only_copy(&dm->loopData, mask->lmask);
|
||||
CustomData_set_only_copy(&dm->polyData, mask->pmask);
|
||||
Custom(&dm->polyData, mask->pmask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -552,45 +449,11 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *
|
|||
CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
|
||||
}
|
||||
|
||||
void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
|
||||
{
|
||||
CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
|
||||
}
|
||||
|
||||
void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
|
||||
{
|
||||
CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
|
||||
}
|
||||
|
||||
void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
|
||||
{
|
||||
CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
|
||||
}
|
||||
|
||||
void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
|
||||
{
|
||||
BLI_assert(index >= 0 && index < dm->getNumVerts(dm));
|
||||
return CustomData_get(&dm->vertData, index, type);
|
||||
}
|
||||
|
||||
void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
|
||||
{
|
||||
BLI_assert(index >= 0 && index < dm->getNumEdges(dm));
|
||||
return CustomData_get(&dm->edgeData, index, type);
|
||||
}
|
||||
|
||||
void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
|
||||
{
|
||||
BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm));
|
||||
return CustomData_get(&dm->faceData, index, type);
|
||||
}
|
||||
|
||||
void *DM_get_poly_data(DerivedMesh *dm, int index, int type)
|
||||
{
|
||||
BLI_assert(index >= 0 && index < dm->getNumPolys(dm));
|
||||
return CustomData_get(&dm->polyData, index, type);
|
||||
}
|
||||
|
||||
void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
|
||||
{
|
||||
if (type == CD_MVERT) {
|
||||
|
@ -609,15 +472,6 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
|
|||
return CustomData_get_layer(&dm->edgeData, type);
|
||||
}
|
||||
|
||||
void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
|
||||
{
|
||||
if (type == CD_MFACE) {
|
||||
return dm->getTessFaceArray(dm);
|
||||
}
|
||||
|
||||
return CustomData_get_layer(&dm->faceData, type);
|
||||
}
|
||||
|
||||
void *DM_get_poly_data_layer(DerivedMesh *dm, int type)
|
||||
{
|
||||
return CustomData_get_layer(&dm->polyData, type);
|
||||
|
@ -1731,13 +1585,6 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
|
|||
BKE_id_free(nullptr, mesh_orco);
|
||||
}
|
||||
|
||||
/* Ensure normals calculation below is correct (normal settings have transferred properly).
|
||||
* However, nodes modifiers might create meshes from scratch or transfer meshes from other
|
||||
* objects with different settings, and in general it doesn't make sense to guarantee that
|
||||
* the settings are the same as the original mesh. If necessary, this could become a modifier
|
||||
* type flag. */
|
||||
BLI_assert(mesh_input->smoothresh == mesh_cage->smoothresh);
|
||||
|
||||
/* Compute normals. */
|
||||
editbmesh_calc_modifier_final_normals(mesh_final, &final_datamask);
|
||||
if (mesh_cage && (mesh_cage != mesh_final)) {
|
||||
|
@ -2144,32 +1991,6 @@ void mesh_get_mapped_verts_coords(Mesh *me_eval, float (*r_cos)[3], const int to
|
|||
}
|
||||
}
|
||||
|
||||
void DM_calc_loop_tangents(DerivedMesh *dm,
|
||||
bool calc_active_tangent,
|
||||
const char (*tangent_names)[MAX_NAME],
|
||||
int tangent_names_len)
|
||||
{
|
||||
BKE_mesh_calc_loop_tangent_ex(
|
||||
dm->getVertArray(dm),
|
||||
dm->getPolyArray(dm),
|
||||
dm->getNumPolys(dm),
|
||||
dm->getLoopArray(dm),
|
||||
dm->getLoopTriArray(dm),
|
||||
dm->getNumLoopTri(dm),
|
||||
&dm->loopData,
|
||||
calc_active_tangent,
|
||||
tangent_names,
|
||||
tangent_names_len,
|
||||
(const float(*)[3])CustomData_get_layer(&dm->vertData, CD_NORMAL),
|
||||
(const float(*)[3])CustomData_get_layer(&dm->polyData, CD_NORMAL),
|
||||
(const float(*)[3])dm->getLoopDataArray(dm, CD_NORMAL),
|
||||
(const float(*)[3])dm->getVertDataArray(dm, CD_ORCO), /* may be nullptr */
|
||||
/* result */
|
||||
&dm->loopData,
|
||||
dm->getNumLoops(dm),
|
||||
&dm->tangent_mask);
|
||||
}
|
||||
|
||||
static void mesh_init_origspace(Mesh *mesh)
|
||||
{
|
||||
const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
|
||||
|
|
|
@ -1956,30 +1956,15 @@ void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
|
|||
return;
|
||||
}
|
||||
|
||||
/* always rebuild to match proxy or lib changes, but on Undo */
|
||||
/* Always rebuild to match library changes, except on Undo. */
|
||||
bool rebuild = false;
|
||||
|
||||
if (!BLO_read_lib_is_undo(reader)) {
|
||||
if (ob->proxy || ob->id.lib != arm->id.lib) {
|
||||
if (ob->id.lib != arm->id.lib) {
|
||||
rebuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ob->proxy) {
|
||||
/* sync proxy layer */
|
||||
if (pose->proxy_layer) {
|
||||
arm->layer = pose->proxy_layer;
|
||||
}
|
||||
|
||||
/* sync proxy active bone */
|
||||
if (pose->proxy_act_bone[0]) {
|
||||
Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone);
|
||||
if (bone) {
|
||||
arm->act_bone = bone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
|
||||
BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints);
|
||||
|
||||
|
|
|
@ -1284,8 +1284,8 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
|
|||
/* cache files */
|
||||
ANIMDATA_IDS_CB(bmain->cachefiles.first);
|
||||
|
||||
/* hairs */
|
||||
ANIMDATA_IDS_CB(bmain->hairs.first);
|
||||
/* Hair Curves. */
|
||||
ANIMDATA_IDS_CB(bmain->hair_curves.first);
|
||||
|
||||
/* pointclouds */
|
||||
ANIMDATA_IDS_CB(bmain->pointclouds.first);
|
||||
|
@ -1413,8 +1413,8 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
|
|||
/* cache files */
|
||||
RENAMEFIX_ANIM_IDS(bmain->cachefiles.first);
|
||||
|
||||
/* hairs */
|
||||
RENAMEFIX_ANIM_IDS(bmain->hairs.first);
|
||||
/* Hair Curves. */
|
||||
RENAMEFIX_ANIM_IDS(bmain->hair_curves.first);
|
||||
|
||||
/* pointclouds */
|
||||
RENAMEFIX_ANIM_IDS(bmain->pointclouds.first);
|
||||
|
|
|
@ -3382,8 +3382,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
|
|||
/* cache files */
|
||||
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* hairs */
|
||||
EVAL_ANIM_IDS(main->hairs.first, ADT_RECALC_ANIM);
|
||||
/* Hair Curves. */
|
||||
EVAL_ANIM_IDS(main->hair_curves.first, ADT_RECALC_ANIM);
|
||||
|
||||
/* pointclouds */
|
||||
EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM);
|
||||
|
|
|
@ -69,8 +69,6 @@
|
|||
|
||||
#include "CLG_log.h"
|
||||
|
||||
static CLG_LogRef LOG = {"bke.armature"};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Prototypes
|
||||
* \{ */
|
||||
|
@ -2296,161 +2294,6 @@ void BKE_armature_where_is(bArmature *arm)
|
|||
/** \name Pose Rebuild
|
||||
* \{ */
|
||||
|
||||
/* if bone layer is protected, copy the data from from->pose
|
||||
* when used with linked libraries this copies from the linked pose into the local pose */
|
||||
static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
|
||||
{
|
||||
bPose *pose = ob->pose, *frompose = from->pose;
|
||||
bPoseChannel *pchan, *pchanp;
|
||||
bConstraint *con;
|
||||
int error = 0;
|
||||
|
||||
if (frompose == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* in some cases when rigs change, we can't synchronize
|
||||
* to avoid crashing check for possible errors here */
|
||||
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
if (pchan->bone->layer & layer_protected) {
|
||||
if (BKE_pose_channel_find_name(frompose, pchan->name) == NULL) {
|
||||
CLOG_ERROR(&LOG,
|
||||
"failed to sync proxy armature because '%s' is missing pose channel '%s'",
|
||||
from->id.name,
|
||||
pchan->name);
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear all transformation values from library */
|
||||
BKE_pose_rest(frompose, false);
|
||||
|
||||
/* copy over all of the proxy's bone groups */
|
||||
/* TODO: for later
|
||||
* - implement 'local' bone groups as for constraints
|
||||
* NOTE: this isn't trivial, as bones reference groups by index not by pointer,
|
||||
* so syncing things correctly needs careful attention */
|
||||
BLI_freelistN(&pose->agroups);
|
||||
BLI_duplicatelist(&pose->agroups, &frompose->agroups);
|
||||
pose->active_group = frompose->active_group;
|
||||
|
||||
for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||
pchanp = BKE_pose_channel_find_name(frompose, pchan->name);
|
||||
|
||||
if (UNLIKELY(pchanp == NULL)) {
|
||||
/* happens for proxies that become invalid because of a missing link
|
||||
* for regular cases it shouldn't happen at all */
|
||||
}
|
||||
else if (pchan->bone->layer & layer_protected) {
|
||||
ListBase proxylocal_constraints = {NULL, NULL};
|
||||
bPoseChannel pchanw;
|
||||
|
||||
/* copy posechannel to temp, but restore important pointers */
|
||||
pchanw = *pchanp;
|
||||
pchanw.bone = pchan->bone;
|
||||
pchanw.prev = pchan->prev;
|
||||
pchanw.next = pchan->next;
|
||||
pchanw.parent = pchan->parent;
|
||||
pchanw.child = pchan->child;
|
||||
pchanw.custom_tx = pchan->custom_tx;
|
||||
pchanw.bbone_prev = pchan->bbone_prev;
|
||||
pchanw.bbone_next = pchan->bbone_next;
|
||||
|
||||
pchanw.mpath = pchan->mpath;
|
||||
pchan->mpath = NULL;
|
||||
|
||||
/* Reset runtime data, we don't want to share that with the proxy. */
|
||||
BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime);
|
||||
|
||||
/* this is freed so copy a copy, else undo crashes */
|
||||
if (pchanw.prop) {
|
||||
pchanw.prop = IDP_CopyProperty(pchanw.prop);
|
||||
|
||||
/* use the values from the existing props */
|
||||
if (pchan->prop) {
|
||||
IDP_SyncGroupValues(pchanw.prop, pchan->prop);
|
||||
}
|
||||
}
|
||||
|
||||
/* Constraints - proxy constraints are flushed... local ones are added after
|
||||
* 1: extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints.
|
||||
* 2: copy proxy-pchan's constraints on-to new.
|
||||
* 3: add extracted local constraints back on top.
|
||||
*
|
||||
* Note for BKE_constraints_copy:
|
||||
* When copying constraints, disable 'do_extern' otherwise
|
||||
* we get the libs direct linked in this blend.
|
||||
*/
|
||||
BKE_constraints_proxylocal_extract(&proxylocal_constraints, &pchan->constraints);
|
||||
BKE_constraints_copy(&pchanw.constraints, &pchanp->constraints, false);
|
||||
BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
|
||||
|
||||
/* constraints - set target ob pointer to own object */
|
||||
for (con = pchanw.constraints.first; con; con = con->next) {
|
||||
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
|
||||
ListBase targets = {NULL, NULL};
|
||||
bConstraintTarget *ct;
|
||||
|
||||
if (cti && cti->get_constraint_targets) {
|
||||
cti->get_constraint_targets(con, &targets);
|
||||
|
||||
for (ct = targets.first; ct; ct = ct->next) {
|
||||
if (ct->tar == from) {
|
||||
ct->tar = ob;
|
||||
}
|
||||
}
|
||||
|
||||
if (cti->flush_constraint_targets) {
|
||||
cti->flush_constraint_targets(con, &targets, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free stuff from current channel */
|
||||
BKE_pose_channel_free(pchan);
|
||||
|
||||
/* copy data in temp back over to the cleaned-out (but still allocated) original channel */
|
||||
*pchan = pchanw;
|
||||
if (pchan->custom) {
|
||||
id_us_plus(&pchan->custom->id);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* always copy custom shape */
|
||||
pchan->custom = pchanp->custom;
|
||||
if (pchan->custom) {
|
||||
id_us_plus(&pchan->custom->id);
|
||||
}
|
||||
if (pchanp->custom_tx) {
|
||||
pchan->custom_tx = BKE_pose_channel_find_name(pose, pchanp->custom_tx->name);
|
||||
}
|
||||
|
||||
/* ID-Property Syncing */
|
||||
{
|
||||
IDProperty *prop_orig = pchan->prop;
|
||||
if (pchanp->prop) {
|
||||
pchan->prop = IDP_CopyProperty(pchanp->prop);
|
||||
if (prop_orig) {
|
||||
/* copy existing values across when types match */
|
||||
IDP_SyncGroupValues(pchan->prop, prop_orig);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pchan->prop = NULL;
|
||||
}
|
||||
if (prop_orig) {
|
||||
IDP_FreeProperty(prop_orig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \param r_last_visited_bone_p: The last bone handled by the last call to this function.
|
||||
*/
|
||||
|
@ -2579,16 +2422,6 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
|
|||
|
||||
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
|
||||
|
||||
/* synchronize protected layers with proxy */
|
||||
/* HACK! To preserve 2.7x behavior that you always can pose even locked bones,
|
||||
* do not do any restoration if this is a COW temp copy! */
|
||||
/* Switched back to just NO_MAIN tag, for some reasons (c)
|
||||
* using COW tag was working this morning, but not anymore... */
|
||||
if (ob->proxy != NULL && (ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
|
||||
BKE_object_copy_proxy_drivers(ob, ob->proxy);
|
||||
pose_proxy_sync(ob, ob->proxy, arm->layer_protected);
|
||||
}
|
||||
|
||||
BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
|
||||
|
||||
pose->flag &= ~POSE_RECALC;
|
||||
|
@ -2846,6 +2679,35 @@ BoundBox *BKE_armature_boundbox_get(Object *ob)
|
|||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
void BKE_pchan_minmax(const Object *ob, const bPoseChannel *pchan, float r_min[3], float r_max[3])
|
||||
{
|
||||
const bArmature *arm = ob->data;
|
||||
const bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
|
||||
const BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
|
||||
BKE_object_boundbox_get(pchan->custom) :
|
||||
NULL;
|
||||
if (bb_custom) {
|
||||
float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4];
|
||||
scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
|
||||
rescale_m4(smat, pchan->custom_scale_xyz);
|
||||
eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ);
|
||||
copy_m4_m4(tmp, pchan_tx->pose_mat);
|
||||
translate_m4(tmp,
|
||||
pchan->custom_translation[0],
|
||||
pchan->custom_translation[1],
|
||||
pchan->custom_translation[2]);
|
||||
mul_m4_series(mat, ob->obmat, tmp, rmat, smat);
|
||||
BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
|
||||
}
|
||||
else {
|
||||
float vec[3];
|
||||
mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
|
||||
minmax_v3v3_v3(r_min, r_max, vec);
|
||||
mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
|
||||
minmax_v3v3_v3(r_min, r_max, vec);
|
||||
}
|
||||
}
|
||||
|
||||
bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select)
|
||||
{
|
||||
bool changed = false;
|
||||
|
@ -2859,31 +2721,8 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
|
|||
* (editarmature.c:2592)... Skip in this case too! */
|
||||
if (pchan->bone && (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) &&
|
||||
!((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) {
|
||||
bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
|
||||
BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
|
||||
BKE_object_boundbox_get(pchan->custom) :
|
||||
NULL;
|
||||
if (bb_custom) {
|
||||
float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4];
|
||||
scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
|
||||
rescale_m4(smat, pchan->custom_scale_xyz);
|
||||
eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ);
|
||||
copy_m4_m4(tmp, pchan_tx->pose_mat);
|
||||
translate_m4(tmp,
|
||||
pchan->custom_translation[0],
|
||||
pchan->custom_translation[1],
|
||||
pchan->custom_translation[2]);
|
||||
mul_m4_series(mat, ob->obmat, tmp, rmat, smat);
|
||||
BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
|
||||
}
|
||||
else {
|
||||
float vec[3];
|
||||
mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
|
||||
minmax_v3v3_v3(r_min, r_max, vec);
|
||||
mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
|
||||
minmax_v3v3_v3(r_min, r_max, vec);
|
||||
}
|
||||
|
||||
BKE_pchan_minmax(ob, pchan, r_min, r_max);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -850,10 +850,6 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
|
|||
}
|
||||
|
||||
BLI_assert(pose->chan_array != NULL || BLI_listbase_is_empty(&pose->chanbase));
|
||||
|
||||
if (object->proxy != NULL) {
|
||||
object->proxy->proxy_from = object;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *object)
|
||||
|
@ -1070,57 +1066,3 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph, Scene *scene, Object *ob
|
|||
BIK_release_tree(scene, object, ctime);
|
||||
pose_eval_cleanup_common(object);
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, Object *object)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
|
||||
BLI_assert(object->pose->chan_array != NULL || BLI_listbase_is_empty(&object->pose->chanbase));
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, Object *object)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, Object *object)
|
||||
{
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
|
||||
pose_eval_cleanup_common(object);
|
||||
}
|
||||
|
||||
void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object, int pchan_index)
|
||||
{
|
||||
const bArmature *armature = (bArmature *)object->data;
|
||||
if (armature->edbo != NULL) {
|
||||
return;
|
||||
}
|
||||
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
|
||||
bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
|
||||
BLI_assert(pchan != NULL);
|
||||
DEG_debug_print_eval_subdata(
|
||||
depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
|
||||
/* TODO(sergey): Use indexed lookup, once it's guaranteed to be kept
|
||||
* around for the time while proxies are evaluating.
|
||||
*/
|
||||
#if 0
|
||||
bPoseChannel *pchan_from = pose_pchan_get_indexed(object->proxy_from, pchan_index);
|
||||
#else
|
||||
bPoseChannel *pchan_from = BKE_pose_channel_find_name(object->proxy_from->pose, pchan->name);
|
||||
#endif
|
||||
if (pchan_from == NULL) {
|
||||
printf(
|
||||
"WARNING: Could not find bone %s in linked ID anymore... "
|
||||
"You should delete and re-generate your proxy.\n",
|
||||
pchan->name);
|
||||
return;
|
||||
}
|
||||
BKE_pose_copy_pchan_result(pchan, pchan_from);
|
||||
copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat);
|
||||
BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from);
|
||||
|
||||
pose_channel_flush_to_orig_if_needed(depsgraph, object, pchan);
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue