Compare commits
117 Commits
temp-viewp
...
soc-2021-s
Author | SHA1 | Date | |
---|---|---|---|
9e8835c1a9 | |||
f5dd77d290 | |||
ad35f6181e | |||
e1846b874b | |||
211ac7b94b | |||
6c0987a2d5 | |||
81da638c44 | |||
19100aa57d | |||
2c7f2a0ba4 | |||
68a21697be | |||
59a7095f79 | |||
![]() |
f021d46752 | ||
![]() |
452a7f6731 | ||
55c90df316 | |||
5d9d2565d2 | |||
460d1a4cb3 | |||
3267c91b4d | |||
530be35516 | |||
de71860555 | |||
923ccf6b10 | |||
98c242affd | |||
32278b79a8 | |||
0617efd51b | |||
1995aae6e3 | |||
67c12ed765 | |||
8abd8865d2 | |||
![]() |
7047bd41c6 | ||
667b4bc0e4 | |||
9d674d9852 | |||
7df651367f | |||
e5fc579073 | |||
b76918717d | |||
770793e545 | |||
![]() |
229d0ace02 | ||
11d785edea | |||
674e4640f6 | |||
![]() |
880e85fc80 | ||
fe1816f67f | |||
b8c764c5d1 | |||
65d287a14a | |||
d3e9d74a5f | |||
eb071e3d3c | |||
2f7aecb6ce | |||
2f868e5647 | |||
![]() |
fe4e85a924 | ||
a7b5982030 | |||
![]() |
a5dd1bc53d | ||
b3bb51dd83 | |||
d9b1bd01f7 | |||
3cd686cae8 | |||
![]() |
1c5f2e49b7 | ||
6766699530 | |||
2b14aa0a39 | |||
7e6066c9c3 | |||
![]() |
94866ef84f | ||
f199f03994 | |||
![]() |
1d59a7aa77 | ||
![]() |
9261bc9476 | ||
96cda4da28 | |||
17ffc6c140 | |||
ccddbec168 | |||
e9ab60e092 | |||
eef2698182 | |||
dacfa8fb23 | |||
3cb9c6efad | |||
b31083a008 | |||
d7dc751a94 | |||
12e5b9420e | |||
cfaaf58023 | |||
d4f44e67c4 | |||
b4aafcc368 | |||
e53880a122 | |||
c79955fd28 | |||
8be22e2ef1 | |||
e789dd4d4c | |||
da57f6eb66 | |||
9b9ff57095 | |||
045e7b58e4 | |||
0d04e138b1 | |||
ea208f067f | |||
012445eb14 | |||
94de2bf12c | |||
dc15562b7c | |||
96e5a771fb | |||
8256bfacee | |||
0d09f5e486 | |||
5a7f89354b | |||
ccdb32ab7a | |||
d6e15033da | |||
f82df13492 | |||
2980e9791f | |||
083082fcc9 | |||
fddc6bc5e9 | |||
1109e900ce | |||
ea2406f249 | |||
ca154310a6 | |||
0ccbeb64f8 | |||
3c14b78dac | |||
16cddb290e | |||
f36974123b | |||
c604a944df | |||
b9903c78c1 | |||
aad804bac0 | |||
5cb618f828 | |||
1ddeff9999 | |||
b1d04825e0 | |||
244fab5876 | |||
337eb4306c | |||
63c8bf807d | |||
5f5b1e51a4 | |||
93f6db102d | |||
fbd14c1c75 | |||
9545f3ec67 | |||
cfe1f39b5f | |||
87e6e4d3ad | |||
4bc0ec4dda | |||
b826df8aa1 |
@@ -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
|
||||
|
@@ -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',
|
||||
)
|
||||
|
||||
|
@@ -626,11 +626,11 @@ void BlenderSync::sync_particle_hair(
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_HAIR_NODES
|
||||
#ifdef WITH_NEW_CURVES_TYPE
|
||||
|
||||
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Hair b_hair)
|
||||
static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Curves b_curves)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_hair.attributes) {
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
continue;
|
||||
}
|
||||
@@ -645,16 +645,16 @@ static std::optional<BL::FloatAttribute> find_curves_radius_attribute(BL::Hair b
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static float4 hair_point_as_float4(BL::Hair b_hair,
|
||||
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_hair.position_data[index].vector()));
|
||||
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,
|
||||
@@ -664,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, b_attr_radius, first_point_index + point_a),
|
||||
hair_point_as_float4(b_hair, b_attr_radius, 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? */
|
||||
|
||||
@@ -689,19 +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_hair);
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_curves);
|
||||
|
||||
/* Export curves and points. */
|
||||
vector<float> points_length;
|
||||
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = b_hair.curve_offset_data[i].value();
|
||||
const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
|
||||
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;
|
||||
@@ -712,7 +712,7 @@ static void export_hair_curves(Scene *scene, Hair *hair, BL::Hair b_hair)
|
||||
|
||||
/* Position and radius. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
const float3 co = get_float3(b_hair.position_data[first_point_index + i].vector());
|
||||
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);
|
||||
@@ -748,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);
|
||||
@@ -761,17 +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_hair.curves.length();
|
||||
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;
|
||||
|
||||
std::optional<BL::FloatAttribute> b_attr_radius = find_curves_radius_attribute(b_hair);
|
||||
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_hair.curve_offset_data[i].value();
|
||||
const int num_points = b_hair.curve_offset_data[i + 1].value() - first_point_index;
|
||||
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++;
|
||||
@@ -782,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, b_attr_radius, point_index);
|
||||
mP[num_motion_keys] = hair_point_as_float4(b_curves, b_attr_radius, point_index);
|
||||
num_motion_keys++;
|
||||
|
||||
if (!have_motion) {
|
||||
@@ -802,7 +802,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st
|
||||
for (int i = 0; i < curve.num_keys; i++) {
|
||||
const float step = i * step_size;
|
||||
mP[num_motion_keys] = interpolate_hair_points(
|
||||
b_hair, b_attr_radius, first_point_index, num_points, step);
|
||||
b_curves, b_attr_radius, first_point_index, num_points, step);
|
||||
num_motion_keys++;
|
||||
}
|
||||
have_motion = true;
|
||||
@@ -819,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
|
||||
@@ -847,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);
|
||||
}
|
||||
@@ -901,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;
|
||||
|
@@ -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.
|
||||
|
@@ -140,6 +140,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)
|
||||
|
@@ -13,11 +13,9 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Video mode switching
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Ported from Quake 2 by Alex Fraser <alex@phatcore.com>
|
||||
* Copyright 2001-2002 NaN Holding BV. All rights reserved.
|
||||
* 1997-2001 Id Software, Inc. Video mode switching.
|
||||
Ported from Quake 2 by Alex Fraser <alex@phatcore.com>.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -14,9 +14,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: some of this file.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -14,9 +14,6 @@
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: some of this file.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -244,7 +244,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
||||
/**
|
||||
* \see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int action)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState action)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -13,10 +13,9 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Part of this code has been taken from Qt, under LGPL license
|
||||
* Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
* Copyright 2001-2002 NaN Holding BV. All rights reserved.
|
||||
* 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
Part of this code has been taken from Qt, under LGPL license.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -269,7 +269,7 @@ class GHOST_SystemX11 : public GHOST_System {
|
||||
/**
|
||||
* \see GHOST_ISystem
|
||||
*/
|
||||
int toggleConsole(int /*action*/)
|
||||
int setConsoleWindowState(GHOST_TConsoleWindowState /*action*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
1
intern/iksolver/extern/IK_solver.h
vendored
1
intern/iksolver/extern/IK_solver.h
vendored
@@ -15,7 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Original author: Laurence
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Original author: Laurence
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Original author: Laurence
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -15,7 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
* Original author: Laurence
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
427
intern/libmv/third_party/msinttypes/inttypes.h
vendored
427
intern/libmv/third_party/msinttypes/inttypes.h
vendored
@@ -29,277 +29,276 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
#ifndef _MSC_VER // [
|
||||
# error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_INTTYPES_H_ // [
|
||||
#define _MSC_INTTYPES_H_
|
||||
#ifndef _MSC_INTTYPES_H_ // [
|
||||
# define _MSC_INTTYPES_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
# if _MSC_VER > 1000
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
#include <stdint.h>
|
||||
# include <stdint.h>
|
||||
|
||||
// 7.8 Format conversion of integer types
|
||||
|
||||
typedef struct {
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
// 7.8.1 Macros for format specifiers
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
|
||||
# if !defined(__cplusplus) || \
|
||||
defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
|
||||
|
||||
// The fprintf macros for signed integers are:
|
||||
#define PRId8 "d"
|
||||
#define PRIi8 "i"
|
||||
#define PRIdLEAST8 "d"
|
||||
#define PRIiLEAST8 "i"
|
||||
#define PRIdFAST8 "d"
|
||||
#define PRIiFAST8 "i"
|
||||
# define PRId8 "d"
|
||||
# define PRIi8 "i"
|
||||
# define PRIdLEAST8 "d"
|
||||
# define PRIiLEAST8 "i"
|
||||
# define PRIdFAST8 "d"
|
||||
# define PRIiFAST8 "i"
|
||||
|
||||
#define PRId16 "hd"
|
||||
#define PRIi16 "hi"
|
||||
#define PRIdLEAST16 "hd"
|
||||
#define PRIiLEAST16 "hi"
|
||||
#define PRIdFAST16 "hd"
|
||||
#define PRIiFAST16 "hi"
|
||||
# define PRId16 "hd"
|
||||
# define PRIi16 "hi"
|
||||
# define PRIdLEAST16 "hd"
|
||||
# define PRIiLEAST16 "hi"
|
||||
# define PRIdFAST16 "hd"
|
||||
# define PRIiFAST16 "hi"
|
||||
|
||||
#define PRId32 "I32d"
|
||||
#define PRIi32 "I32i"
|
||||
#define PRIdLEAST32 "I32d"
|
||||
#define PRIiLEAST32 "I32i"
|
||||
#define PRIdFAST32 "I32d"
|
||||
#define PRIiFAST32 "I32i"
|
||||
# define PRId32 "I32d"
|
||||
# define PRIi32 "I32i"
|
||||
# define PRIdLEAST32 "I32d"
|
||||
# define PRIiLEAST32 "I32i"
|
||||
# define PRIdFAST32 "I32d"
|
||||
# define PRIiFAST32 "I32i"
|
||||
|
||||
#define PRId64 "I64d"
|
||||
#define PRIi64 "I64i"
|
||||
#define PRIdLEAST64 "I64d"
|
||||
#define PRIiLEAST64 "I64i"
|
||||
#define PRIdFAST64 "I64d"
|
||||
#define PRIiFAST64 "I64i"
|
||||
# define PRId64 "I64d"
|
||||
# define PRIi64 "I64i"
|
||||
# define PRIdLEAST64 "I64d"
|
||||
# define PRIiLEAST64 "I64i"
|
||||
# define PRIdFAST64 "I64d"
|
||||
# define PRIiFAST64 "I64i"
|
||||
|
||||
#define PRIdMAX "I64d"
|
||||
#define PRIiMAX "I64i"
|
||||
# define PRIdMAX "I64d"
|
||||
# define PRIiMAX "I64i"
|
||||
|
||||
#define PRIdPTR "Id"
|
||||
#define PRIiPTR "Ii"
|
||||
# define PRIdPTR "Id"
|
||||
# define PRIiPTR "Ii"
|
||||
|
||||
// The fprintf macros for unsigned integers are:
|
||||
#define PRIo8 "o"
|
||||
#define PRIu8 "u"
|
||||
#define PRIx8 "x"
|
||||
#define PRIX8 "X"
|
||||
#define PRIoLEAST8 "o"
|
||||
#define PRIuLEAST8 "u"
|
||||
#define PRIxLEAST8 "x"
|
||||
#define PRIXLEAST8 "X"
|
||||
#define PRIoFAST8 "o"
|
||||
#define PRIuFAST8 "u"
|
||||
#define PRIxFAST8 "x"
|
||||
#define PRIXFAST8 "X"
|
||||
# define PRIo8 "o"
|
||||
# define PRIu8 "u"
|
||||
# define PRIx8 "x"
|
||||
# define PRIX8 "X"
|
||||
# define PRIoLEAST8 "o"
|
||||
# define PRIuLEAST8 "u"
|
||||
# define PRIxLEAST8 "x"
|
||||
# define PRIXLEAST8 "X"
|
||||
# define PRIoFAST8 "o"
|
||||
# define PRIuFAST8 "u"
|
||||
# define PRIxFAST8 "x"
|
||||
# define PRIXFAST8 "X"
|
||||
|
||||
#define PRIo16 "ho"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
#define PRIX16 "hX"
|
||||
#define PRIoLEAST16 "ho"
|
||||
#define PRIuLEAST16 "hu"
|
||||
#define PRIxLEAST16 "hx"
|
||||
#define PRIXLEAST16 "hX"
|
||||
#define PRIoFAST16 "ho"
|
||||
#define PRIuFAST16 "hu"
|
||||
#define PRIxFAST16 "hx"
|
||||
#define PRIXFAST16 "hX"
|
||||
# define PRIo16 "ho"
|
||||
# define PRIu16 "hu"
|
||||
# define PRIx16 "hx"
|
||||
# define PRIX16 "hX"
|
||||
# define PRIoLEAST16 "ho"
|
||||
# define PRIuLEAST16 "hu"
|
||||
# define PRIxLEAST16 "hx"
|
||||
# define PRIXLEAST16 "hX"
|
||||
# define PRIoFAST16 "ho"
|
||||
# define PRIuFAST16 "hu"
|
||||
# define PRIxFAST16 "hx"
|
||||
# define PRIXFAST16 "hX"
|
||||
|
||||
#define PRIo32 "I32o"
|
||||
#define PRIu32 "I32u"
|
||||
#define PRIx32 "I32x"
|
||||
#define PRIX32 "I32X"
|
||||
#define PRIoLEAST32 "I32o"
|
||||
#define PRIuLEAST32 "I32u"
|
||||
#define PRIxLEAST32 "I32x"
|
||||
#define PRIXLEAST32 "I32X"
|
||||
#define PRIoFAST32 "I32o"
|
||||
#define PRIuFAST32 "I32u"
|
||||
#define PRIxFAST32 "I32x"
|
||||
#define PRIXFAST32 "I32X"
|
||||
# define PRIo32 "I32o"
|
||||
# define PRIu32 "I32u"
|
||||
# define PRIx32 "I32x"
|
||||
# define PRIX32 "I32X"
|
||||
# define PRIoLEAST32 "I32o"
|
||||
# define PRIuLEAST32 "I32u"
|
||||
# define PRIxLEAST32 "I32x"
|
||||
# define PRIXLEAST32 "I32X"
|
||||
# define PRIoFAST32 "I32o"
|
||||
# define PRIuFAST32 "I32u"
|
||||
# define PRIxFAST32 "I32x"
|
||||
# define PRIXFAST32 "I32X"
|
||||
|
||||
#define PRIo64 "I64o"
|
||||
#define PRIu64 "I64u"
|
||||
#define PRIx64 "I64x"
|
||||
#define PRIX64 "I64X"
|
||||
#define PRIoLEAST64 "I64o"
|
||||
#define PRIuLEAST64 "I64u"
|
||||
#define PRIxLEAST64 "I64x"
|
||||
#define PRIXLEAST64 "I64X"
|
||||
#define PRIoFAST64 "I64o"
|
||||
#define PRIuFAST64 "I64u"
|
||||
#define PRIxFAST64 "I64x"
|
||||
#define PRIXFAST64 "I64X"
|
||||
# define PRIo64 "I64o"
|
||||
# define PRIu64 "I64u"
|
||||
# define PRIx64 "I64x"
|
||||
# define PRIX64 "I64X"
|
||||
# define PRIoLEAST64 "I64o"
|
||||
# define PRIuLEAST64 "I64u"
|
||||
# define PRIxLEAST64 "I64x"
|
||||
# define PRIXLEAST64 "I64X"
|
||||
# define PRIoFAST64 "I64o"
|
||||
# define PRIuFAST64 "I64u"
|
||||
# define PRIxFAST64 "I64x"
|
||||
# define PRIXFAST64 "I64X"
|
||||
|
||||
#define PRIoMAX "I64o"
|
||||
#define PRIuMAX "I64u"
|
||||
#define PRIxMAX "I64x"
|
||||
#define PRIXMAX "I64X"
|
||||
# define PRIoMAX "I64o"
|
||||
# define PRIuMAX "I64u"
|
||||
# define PRIxMAX "I64x"
|
||||
# define PRIXMAX "I64X"
|
||||
|
||||
#define PRIoPTR "Io"
|
||||
#define PRIuPTR "Iu"
|
||||
#define PRIxPTR "Ix"
|
||||
#define PRIXPTR "IX"
|
||||
# define PRIoPTR "Io"
|
||||
# define PRIuPTR "Iu"
|
||||
# define PRIxPTR "Ix"
|
||||
# define PRIXPTR "IX"
|
||||
|
||||
// The fscanf macros for signed integers are:
|
||||
#define SCNd8 "d"
|
||||
#define SCNi8 "i"
|
||||
#define SCNdLEAST8 "d"
|
||||
#define SCNiLEAST8 "i"
|
||||
#define SCNdFAST8 "d"
|
||||
#define SCNiFAST8 "i"
|
||||
# define SCNd8 "d"
|
||||
# define SCNi8 "i"
|
||||
# define SCNdLEAST8 "d"
|
||||
# define SCNiLEAST8 "i"
|
||||
# define SCNdFAST8 "d"
|
||||
# define SCNiFAST8 "i"
|
||||
|
||||
#define SCNd16 "hd"
|
||||
#define SCNi16 "hi"
|
||||
#define SCNdLEAST16 "hd"
|
||||
#define SCNiLEAST16 "hi"
|
||||
#define SCNdFAST16 "hd"
|
||||
#define SCNiFAST16 "hi"
|
||||
# define SCNd16 "hd"
|
||||
# define SCNi16 "hi"
|
||||
# define SCNdLEAST16 "hd"
|
||||
# define SCNiLEAST16 "hi"
|
||||
# define SCNdFAST16 "hd"
|
||||
# define SCNiFAST16 "hi"
|
||||
|
||||
#define SCNd32 "ld"
|
||||
#define SCNi32 "li"
|
||||
#define SCNdLEAST32 "ld"
|
||||
#define SCNiLEAST32 "li"
|
||||
#define SCNdFAST32 "ld"
|
||||
#define SCNiFAST32 "li"
|
||||
# define SCNd32 "ld"
|
||||
# define SCNi32 "li"
|
||||
# define SCNdLEAST32 "ld"
|
||||
# define SCNiLEAST32 "li"
|
||||
# define SCNdFAST32 "ld"
|
||||
# define SCNiFAST32 "li"
|
||||
|
||||
#define SCNd64 "I64d"
|
||||
#define SCNi64 "I64i"
|
||||
#define SCNdLEAST64 "I64d"
|
||||
#define SCNiLEAST64 "I64i"
|
||||
#define SCNdFAST64 "I64d"
|
||||
#define SCNiFAST64 "I64i"
|
||||
# define SCNd64 "I64d"
|
||||
# define SCNi64 "I64i"
|
||||
# define SCNdLEAST64 "I64d"
|
||||
# define SCNiLEAST64 "I64i"
|
||||
# define SCNdFAST64 "I64d"
|
||||
# define SCNiFAST64 "I64i"
|
||||
|
||||
#define SCNdMAX "I64d"
|
||||
#define SCNiMAX "I64i"
|
||||
# define SCNdMAX "I64d"
|
||||
# define SCNiMAX "I64i"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNdPTR "I64d"
|
||||
# define SCNiPTR "I64i"
|
||||
#else // _WIN64 ][
|
||||
# define SCNdPTR "ld"
|
||||
# define SCNiPTR "li"
|
||||
#endif // _WIN64 ]
|
||||
# ifdef _WIN64 // [
|
||||
# define SCNdPTR "I64d"
|
||||
# define SCNiPTR "I64i"
|
||||
# else // _WIN64 ][
|
||||
# define SCNdPTR "ld"
|
||||
# define SCNiPTR "li"
|
||||
# endif // _WIN64 ]
|
||||
|
||||
// The fscanf macros for unsigned integers are:
|
||||
#define SCNo8 "o"
|
||||
#define SCNu8 "u"
|
||||
#define SCNx8 "x"
|
||||
#define SCNX8 "X"
|
||||
#define SCNoLEAST8 "o"
|
||||
#define SCNuLEAST8 "u"
|
||||
#define SCNxLEAST8 "x"
|
||||
#define SCNXLEAST8 "X"
|
||||
#define SCNoFAST8 "o"
|
||||
#define SCNuFAST8 "u"
|
||||
#define SCNxFAST8 "x"
|
||||
#define SCNXFAST8 "X"
|
||||
# define SCNo8 "o"
|
||||
# define SCNu8 "u"
|
||||
# define SCNx8 "x"
|
||||
# define SCNX8 "X"
|
||||
# define SCNoLEAST8 "o"
|
||||
# define SCNuLEAST8 "u"
|
||||
# define SCNxLEAST8 "x"
|
||||
# define SCNXLEAST8 "X"
|
||||
# define SCNoFAST8 "o"
|
||||
# define SCNuFAST8 "u"
|
||||
# define SCNxFAST8 "x"
|
||||
# define SCNXFAST8 "X"
|
||||
|
||||
#define SCNo16 "ho"
|
||||
#define SCNu16 "hu"
|
||||
#define SCNx16 "hx"
|
||||
#define SCNX16 "hX"
|
||||
#define SCNoLEAST16 "ho"
|
||||
#define SCNuLEAST16 "hu"
|
||||
#define SCNxLEAST16 "hx"
|
||||
#define SCNXLEAST16 "hX"
|
||||
#define SCNoFAST16 "ho"
|
||||
#define SCNuFAST16 "hu"
|
||||
#define SCNxFAST16 "hx"
|
||||
#define SCNXFAST16 "hX"
|
||||
# define SCNo16 "ho"
|
||||
# define SCNu16 "hu"
|
||||
# define SCNx16 "hx"
|
||||
# define SCNX16 "hX"
|
||||
# define SCNoLEAST16 "ho"
|
||||
# define SCNuLEAST16 "hu"
|
||||
# define SCNxLEAST16 "hx"
|
||||
# define SCNXLEAST16 "hX"
|
||||
# define SCNoFAST16 "ho"
|
||||
# define SCNuFAST16 "hu"
|
||||
# define SCNxFAST16 "hx"
|
||||
# define SCNXFAST16 "hX"
|
||||
|
||||
#define SCNo32 "lo"
|
||||
#define SCNu32 "lu"
|
||||
#define SCNx32 "lx"
|
||||
#define SCNX32 "lX"
|
||||
#define SCNoLEAST32 "lo"
|
||||
#define SCNuLEAST32 "lu"
|
||||
#define SCNxLEAST32 "lx"
|
||||
#define SCNXLEAST32 "lX"
|
||||
#define SCNoFAST32 "lo"
|
||||
#define SCNuFAST32 "lu"
|
||||
#define SCNxFAST32 "lx"
|
||||
#define SCNXFAST32 "lX"
|
||||
# define SCNo32 "lo"
|
||||
# define SCNu32 "lu"
|
||||
# define SCNx32 "lx"
|
||||
# define SCNX32 "lX"
|
||||
# define SCNoLEAST32 "lo"
|
||||
# define SCNuLEAST32 "lu"
|
||||
# define SCNxLEAST32 "lx"
|
||||
# define SCNXLEAST32 "lX"
|
||||
# define SCNoFAST32 "lo"
|
||||
# define SCNuFAST32 "lu"
|
||||
# define SCNxFAST32 "lx"
|
||||
# define SCNXFAST32 "lX"
|
||||
|
||||
#define SCNo64 "I64o"
|
||||
#define SCNu64 "I64u"
|
||||
#define SCNx64 "I64x"
|
||||
#define SCNX64 "I64X"
|
||||
#define SCNoLEAST64 "I64o"
|
||||
#define SCNuLEAST64 "I64u"
|
||||
#define SCNxLEAST64 "I64x"
|
||||
#define SCNXLEAST64 "I64X"
|
||||
#define SCNoFAST64 "I64o"
|
||||
#define SCNuFAST64 "I64u"
|
||||
#define SCNxFAST64 "I64x"
|
||||
#define SCNXFAST64 "I64X"
|
||||
# define SCNo64 "I64o"
|
||||
# define SCNu64 "I64u"
|
||||
# define SCNx64 "I64x"
|
||||
# define SCNX64 "I64X"
|
||||
# define SCNoLEAST64 "I64o"
|
||||
# define SCNuLEAST64 "I64u"
|
||||
# define SCNxLEAST64 "I64x"
|
||||
# define SCNXLEAST64 "I64X"
|
||||
# define SCNoFAST64 "I64o"
|
||||
# define SCNuFAST64 "I64u"
|
||||
# define SCNxFAST64 "I64x"
|
||||
# define SCNXFAST64 "I64X"
|
||||
|
||||
#define SCNoMAX "I64o"
|
||||
#define SCNuMAX "I64u"
|
||||
#define SCNxMAX "I64x"
|
||||
#define SCNXMAX "I64X"
|
||||
# define SCNoMAX "I64o"
|
||||
# define SCNuMAX "I64u"
|
||||
# define SCNxMAX "I64x"
|
||||
# define SCNXMAX "I64X"
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define SCNoPTR "I64o"
|
||||
# define SCNuPTR "I64u"
|
||||
# define SCNxPTR "I64x"
|
||||
# define SCNXPTR "I64X"
|
||||
#else // _WIN64 ][
|
||||
# define SCNoPTR "lo"
|
||||
# define SCNuPTR "lu"
|
||||
# define SCNxPTR "lx"
|
||||
# define SCNXPTR "lX"
|
||||
#endif // _WIN64 ]
|
||||
# ifdef _WIN64 // [
|
||||
# define SCNoPTR "I64o"
|
||||
# define SCNuPTR "I64u"
|
||||
# define SCNxPTR "I64x"
|
||||
# define SCNXPTR "I64X"
|
||||
# else // _WIN64 ][
|
||||
# define SCNoPTR "lo"
|
||||
# define SCNuPTR "lu"
|
||||
# define SCNxPTR "lx"
|
||||
# define SCNXPTR "lX"
|
||||
# endif // _WIN64 ]
|
||||
|
||||
#endif // __STDC_FORMAT_MACROS ]
|
||||
# endif // __STDC_FORMAT_MACROS ]
|
||||
|
||||
// 7.8.2 Functions for greatest-width integer types
|
||||
|
||||
// 7.8.2.1 The imaxabs function
|
||||
#define imaxabs _abs64
|
||||
# define imaxabs _abs64
|
||||
|
||||
// 7.8.2.2 The imaxdiv function
|
||||
|
||||
// This is modified version of div() function from Microsoft's div.c found
|
||||
// in %MSVC.NET%\crt\src\div.c
|
||||
#ifdef STATIC_IMAXDIV // [
|
||||
# ifdef STATIC_IMAXDIV // [
|
||||
static
|
||||
#else // STATIC_IMAXDIV ][
|
||||
# else // STATIC_IMAXDIV ][
|
||||
_inline
|
||||
#endif // STATIC_IMAXDIV ]
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
|
||||
{
|
||||
imaxdiv_t result;
|
||||
# endif // STATIC_IMAXDIV ]
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) {
|
||||
imaxdiv_t result;
|
||||
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
// did division wrong; must fix up
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
// did division wrong; must fix up
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
// 7.8.2.3 The strtoimax and strtoumax functions
|
||||
#define strtoimax _strtoi64
|
||||
#define strtoumax _strtoui64
|
||||
# define strtoimax _strtoi64
|
||||
# define strtoumax _strtoui64
|
||||
|
||||
// 7.8.2.4 The wcstoimax and wcstoumax functions
|
||||
#define wcstoimax _wcstoi64
|
||||
#define wcstoumax _wcstoui64
|
||||
# define wcstoimax _wcstoi64
|
||||
# define wcstoumax _wcstoui64
|
||||
|
||||
|
||||
#endif // _MSC_INTTYPES_H_ ]
|
||||
#endif // _MSC_INTTYPES_H_ ]
|
||||
|
305
intern/libmv/third_party/msinttypes/stdint.h
vendored
305
intern/libmv/third_party/msinttypes/stdint.h
vendored
@@ -29,40 +29,40 @@
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
#ifndef _MSC_VER // [
|
||||
# error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
# define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
# if _MSC_VER > 1000
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
#include <limits.h>
|
||||
# include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && \
|
||||
_MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
@@ -71,177 +71,176 @@ extern "C" {
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
# if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
# else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
# endif
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
# ifdef _WIN64 // [
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
# else // _WIN64 ][
|
||||
typedef _W64 int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
# endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
# if !defined(__cplusplus) || \
|
||||
defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and
|
||||
// footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
# define INT8_MIN ((int8_t)_I8_MIN)
|
||||
# define INT8_MAX _I8_MAX
|
||||
# define INT16_MIN ((int16_t)_I16_MIN)
|
||||
# define INT16_MAX _I16_MAX
|
||||
# define INT32_MIN ((int32_t)_I32_MIN)
|
||||
# define INT32_MAX _I32_MAX
|
||||
# define INT64_MIN ((int64_t)_I64_MIN)
|
||||
# define INT64_MAX _I64_MAX
|
||||
# define UINT8_MAX _UI8_MAX
|
||||
# define UINT16_MAX _UI16_MAX
|
||||
# define UINT32_MAX _UI32_MAX
|
||||
# define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
# define INT_LEAST8_MIN INT8_MIN
|
||||
# define INT_LEAST8_MAX INT8_MAX
|
||||
# define INT_LEAST16_MIN INT16_MIN
|
||||
# define INT_LEAST16_MAX INT16_MAX
|
||||
# define INT_LEAST32_MIN INT32_MIN
|
||||
# define INT_LEAST32_MAX INT32_MAX
|
||||
# define INT_LEAST64_MIN INT64_MIN
|
||||
# define INT_LEAST64_MAX INT64_MAX
|
||||
# define UINT_LEAST8_MAX UINT8_MAX
|
||||
# define UINT_LEAST16_MAX UINT16_MAX
|
||||
# define UINT_LEAST32_MAX UINT32_MAX
|
||||
# define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
# define INT_FAST8_MIN INT8_MIN
|
||||
# define INT_FAST8_MAX INT8_MAX
|
||||
# define INT_FAST16_MIN INT16_MIN
|
||||
# define INT_FAST16_MAX INT16_MAX
|
||||
# define INT_FAST32_MIN INT32_MIN
|
||||
# define INT_FAST32_MAX INT32_MAX
|
||||
# define INT_FAST64_MIN INT64_MIN
|
||||
# define INT_FAST64_MAX INT64_MAX
|
||||
# define UINT_FAST8_MAX UINT8_MAX
|
||||
# define UINT_FAST16_MAX UINT16_MAX
|
||||
# define UINT_FAST32_MAX UINT32_MAX
|
||||
# define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
# ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
# endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
# define INTMAX_MIN INT64_MIN
|
||||
# define INTMAX_MAX INT64_MAX
|
||||
# define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
# ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
# endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
# define SIG_ATOMIC_MIN INT_MIN
|
||||
# define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
# ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
# endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
# ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
# endif // WCHAR_MIN ]
|
||||
# ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
# endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
# define WINT_MIN 0
|
||||
# define WINT_MAX _UI16_MAX
|
||||
|
||||
# endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
# if !defined(__cplusplus) || \
|
||||
defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
# define INT8_C(val) val##i8
|
||||
# define INT16_C(val) val##i16
|
||||
# define INT32_C(val) val##i32
|
||||
# define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
# define UINT8_C(val) val##ui8
|
||||
# define UINT16_C(val) val##ui16
|
||||
# define UINT32_C(val) val##ui32
|
||||
# define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
# define INTMAX_C INT64_C
|
||||
# define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
# endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
#endif // _MSC_STDINT_H_ ]
|
||||
|
@@ -1,20 +1,20 @@
|
||||
// Copyright 2019 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Author: Sebastian Parborg, Pablo Dobarro
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2019 Blender Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
|
@@ -1,20 +1,20 @@
|
||||
// Copyright 2019 Blender Foundation. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// Author: Sebastian Parborg, Pablo Dobarro
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Copyright 2019 Blender Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef QUADRIFLOW_CAPI_HPP
|
||||
#define QUADRIFLOW_CAPI_HPP
|
||||
|
@@ -81,6 +81,16 @@ void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iter
|
||||
/* Split Impulse */
|
||||
void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse);
|
||||
|
||||
/* Get latest applied impulse */
|
||||
void RB_dworld_get_impulse(rbDynamicsWorld *world,
|
||||
rbRigidBody *rbo,
|
||||
float timeSubStep,
|
||||
float norm_forces[3][3],
|
||||
float fric_forces[3][3],
|
||||
float vec_locations[3][3],
|
||||
bool norm_flag,
|
||||
bool fric_flag);
|
||||
|
||||
/* Simulation ----------------------- */
|
||||
|
||||
/* Step the simulation by the desired amount (in seconds) with extra controls on substep sizes and
|
||||
@@ -264,6 +274,10 @@ void RB_shape_trimesh_update(rbCollisionShape *shape,
|
||||
int vert_stride,
|
||||
float min[3],
|
||||
float max[3]);
|
||||
/* Get scale data */
|
||||
void RB_box_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents);
|
||||
void RB_cone_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents);
|
||||
void RB_cylinder_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents);
|
||||
|
||||
/* ********************************** */
|
||||
/* Constraints */
|
||||
@@ -361,6 +375,20 @@ void RB_constraint_set_target_velocity_motor(rbConstraint *con,
|
||||
float velocity_lin,
|
||||
float velocity_ang);
|
||||
|
||||
/* Get object transforms */
|
||||
void RB_constraint_get_transforms_hinge(rbConstraint *con,
|
||||
float r_ob1_basis[3][3],
|
||||
float r_ob2_basis[3][3],
|
||||
float r_ob1_orig[3],
|
||||
float r_ob2_orig[3]);
|
||||
|
||||
void RB_constraint_get_transforms_slider(rbConstraint *con,
|
||||
float r_ob1_basis[3][3],
|
||||
float r_ob2_basis[3][3],
|
||||
float r_ob1_orig[3],
|
||||
float r_ob2_orig[3],
|
||||
float r_initial_dist[]);
|
||||
|
||||
/* Set number of constraint solver iterations made per step, this overrided world setting
|
||||
* To use default set it to -1 */
|
||||
void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations);
|
||||
|
@@ -204,6 +204,103 @@ void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse)
|
||||
info.m_splitImpulse = split_impulse;
|
||||
}
|
||||
|
||||
/* Get last applied impulse at contact points */
|
||||
/* TODO: this may not be the most efficient way to do it. get all forces at once and store in a
|
||||
* lookup table. */
|
||||
void RB_dworld_get_impulse(rbDynamicsWorld *world,
|
||||
rbRigidBody *rbo,
|
||||
float timeSubStep,
|
||||
float norm_forces[3][3],
|
||||
float fric_forces[3][3],
|
||||
float vec_locations[3][3],
|
||||
bool norm_flag,
|
||||
bool fric_flag)
|
||||
{
|
||||
int numManifolds = world->dispatcher->getNumManifolds();
|
||||
int num_norm_forces = 0;
|
||||
int num_fric_forces = 0;
|
||||
|
||||
/* Loop through all persisent contact manifolds. The persistant manifold contains all contact points between
|
||||
* 2 overlapping objects in the world. It can contain between 0 and 4 points. This is the contact point cache
|
||||
* after reduction of the contact manifold. */
|
||||
for (int i = 0; i < numManifolds; i++) {
|
||||
btPersistentManifold *contactManifold = world->dispatcher->getManifoldByIndexInternal(i);
|
||||
/* The 2 overlapping obejcts. */
|
||||
const void *obA = contactManifold->getBody0();
|
||||
const void *obB = contactManifold->getBody1();
|
||||
|
||||
/* Break if we cannot store any more forces. upperlimit is 3 */
|
||||
/* Friction cannot exist without a normal force, so counting number of normal forces stored is enough. */
|
||||
if (num_norm_forces > 2) {
|
||||
break;
|
||||
}
|
||||
/* Continue to next manifold if this one does not invlove the current rigid body. */
|
||||
if (obA != rbo->body && obB != rbo->body) {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
btVector3 tot_impulse = btVector3(0.0, 0.0, 0.0);
|
||||
btVector3 final_loc = btVector3(0.0, 0.0, 0.0);
|
||||
btScalar tot_impulse_magnitude = 0.f;
|
||||
btVector3 tot_lat_impulse = btVector3(0.0, 0.0, 0.0);
|
||||
int numContacts = contactManifold->getNumContacts();
|
||||
int num_impulse_points = 0;
|
||||
/* Find points where impulse was appplied. */
|
||||
for (int j = 0; j < numContacts; j++) {
|
||||
btManifoldPoint &pt = contactManifold->getContactPoint(j);
|
||||
if (pt.getAppliedImpulse() > 0.f || -pt.getAppliedImpulse() > 0.f) {
|
||||
num_impulse_points++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop throught contact points and add impulses applied at each point.
|
||||
* Devide by time to get the equivilant force. */
|
||||
for (int j = 0; j < numContacts; j++) {
|
||||
btManifoldPoint &pt = contactManifold->getContactPoint(j);
|
||||
if (pt.getAppliedImpulse() > 0.f || -pt.getAppliedImpulse() > 0.f) {
|
||||
const btVector3 &loc = pt.getPositionWorldOnB();
|
||||
const btVector3 imp = (rbo->body == obB) ?
|
||||
-pt.m_normalWorldOnB * pt.getAppliedImpulse() / timeSubStep :
|
||||
pt.m_normalWorldOnB * pt.getAppliedImpulse() / timeSubStep;
|
||||
tot_impulse_magnitude += pt.getAppliedImpulse() > 0.f? pt.getAppliedImpulse() : -pt.getAppliedImpulse();
|
||||
tot_impulse += imp;
|
||||
final_loc += num_impulse_points > 1 ? loc * pt.getAppliedImpulse() : loc;
|
||||
if (fric_flag) {
|
||||
const btVector3 lat_imp1 = (rbo->body == obB) ?
|
||||
-pt.m_appliedImpulseLateral1 *
|
||||
pt.m_lateralFrictionDir1 / timeSubStep :
|
||||
pt.m_appliedImpulseLateral1 * pt.m_lateralFrictionDir1 /
|
||||
timeSubStep;
|
||||
const btVector3 lat_imp2 = (rbo->body == obB) ?
|
||||
-pt.m_appliedImpulseLateral2 *
|
||||
pt.m_lateralFrictionDir2 / timeSubStep :
|
||||
pt.m_appliedImpulseLateral2 * pt.m_lateralFrictionDir2 /
|
||||
timeSubStep;
|
||||
tot_lat_impulse += lat_imp1 + lat_imp2;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If impulse was applied at more than one point, the location of the force is taken as average of points
|
||||
* weighted by the magnitude of impulse applied at each point. */
|
||||
if(fabsf(tot_impulse_magnitude)==0.0f){
|
||||
continue;
|
||||
}
|
||||
if (num_impulse_points > 1) {
|
||||
final_loc = final_loc / tot_impulse_magnitude;
|
||||
}
|
||||
copy_v3_btvec3(vec_locations[num_norm_forces], final_loc);
|
||||
if (norm_flag) {
|
||||
copy_v3_btvec3(norm_forces[num_norm_forces], tot_impulse);
|
||||
num_norm_forces++;
|
||||
}
|
||||
if (fric_flag) {
|
||||
copy_v3_btvec3(fric_forces[num_fric_forces], tot_lat_impulse);
|
||||
num_fric_forces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Simulation ----------------------- */
|
||||
|
||||
void RB_dworld_step_simulation(rbDynamicsWorld *world,
|
||||
@@ -930,6 +1027,25 @@ void RB_shape_set_margin(rbCollisionShape *shape, float value)
|
||||
shape->cshape->setMargin(value);
|
||||
}
|
||||
|
||||
/* Get scale data--------------------------- */
|
||||
void RB_box_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents)
|
||||
{
|
||||
btBoxShape *box = (btBoxShape*)shape->cshape;
|
||||
copy_v3_btvec3(r_half_extents, box->getHalfExtentsWithMargin());
|
||||
}
|
||||
|
||||
void RB_cone_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents)
|
||||
{
|
||||
btConeShapeZ *cone = (btConeShapeZ*)shape->cshape;
|
||||
copy_v3_btvec3(r_half_extents, btVector3(cone->getRadius(), cone->getRadius(), cone->getHeight()*0.5));
|
||||
}
|
||||
|
||||
void RB_cylinder_shape_get_half_extents(rbCollisionShape *shape, float *r_half_extents)
|
||||
{
|
||||
btCylinderShapeZ *box = (btCylinderShapeZ*)shape->cshape;
|
||||
copy_v3_btvec3(r_half_extents, box->getHalfExtentsWithMargin());
|
||||
}
|
||||
|
||||
/* ********************************** */
|
||||
/* Constraints */
|
||||
|
||||
@@ -1302,4 +1418,51 @@ void RB_constraint_set_target_velocity_motor(rbConstraint *con,
|
||||
constraint->getRotationalLimitMotor(0)->m_targetVelocity = velocity_ang;
|
||||
}
|
||||
|
||||
void RB_constraint_get_transforms_hinge(rbConstraint *con,
|
||||
float r_ob1_basis[3][3],
|
||||
float r_ob2_basis[3][3],
|
||||
float r_ob1_orig[3],
|
||||
float r_ob2_orig[3]) {
|
||||
btHingeConstraint *constraint = reinterpret_cast<btHingeConstraint *>(con);
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
transform1 = constraint->getAFrame();
|
||||
transform2 = constraint->getBFrame();
|
||||
|
||||
for(int i=0; i<3; i++) {
|
||||
copy_v3_btvec3(r_ob1_basis[i], btVector3(transform1.getBasis()[0][i],transform1.getBasis()[1][i], transform1.getBasis()[2][i]));
|
||||
copy_v3_btvec3(r_ob2_basis[i], btVector3(transform2.getBasis()[0][i],transform2.getBasis()[1][i], transform2.getBasis()[2][i]));
|
||||
}
|
||||
copy_v3_btvec3(r_ob1_orig, btVector3(transform1.getOrigin().x(),transform1.getOrigin().y(), transform1.getOrigin().z()));
|
||||
copy_v3_btvec3(r_ob2_orig, btVector3(transform2.getOrigin().x() ,transform2.getOrigin().y(), transform2.getOrigin().z()));
|
||||
|
||||
}
|
||||
|
||||
void RB_constraint_get_transforms_slider(rbConstraint *con,
|
||||
float r_ob1_basis[3][3],
|
||||
float r_ob2_basis[3][3],
|
||||
float r_ob1_orig[3],
|
||||
float r_ob2_orig[3],
|
||||
float r_initial_dist[3]) {
|
||||
btSliderConstraint *constraint = reinterpret_cast<btSliderConstraint *>(con);
|
||||
btTransform transform1;
|
||||
btTransform transform2;
|
||||
|
||||
transform1 = constraint->getFrameOffsetA();
|
||||
transform2 = constraint->getFrameOffsetB();
|
||||
|
||||
for(int i=0; i<3; i++) {
|
||||
copy_v3_btvec3(r_ob1_basis[i], btVector3(transform1.getBasis()[0][i],transform1.getBasis()[1][i], transform1.getBasis()[2][i]));
|
||||
copy_v3_btvec3(r_ob2_basis[i], btVector3(transform2.getBasis()[0][i],transform2.getBasis()[1][i], transform2.getBasis()[2][i]));
|
||||
}
|
||||
copy_v3_btvec3(r_ob1_orig, btVector3(transform1.getOrigin().x(),transform1.getOrigin().y(), transform1.getOrigin().z()));
|
||||
copy_v3_btvec3(r_ob2_orig, btVector3(transform2.getOrigin().x() ,transform2.getOrigin().y(), transform2.getOrigin().z()));
|
||||
|
||||
if(r_initial_dist) {
|
||||
btTransform transform3 = transform1 * transform2.inverse();
|
||||
copy_v3_btvec3(r_initial_dist, btVector3(transform3.getOrigin().x() ,transform3.getOrigin().y(), transform3.getOrigin().z()));
|
||||
}
|
||||
}
|
||||
|
||||
/* ********************************** */
|
||||
|
@@ -1,32 +1,30 @@
|
||||
/*
|
||||
This source is published under the following 3-clause BSD license.
|
||||
|
||||
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* None of the names of the contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * None of the names of the contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* ============================================================================
|
||||
|
||||
|
@@ -1,32 +1,30 @@
|
||||
/*
|
||||
This source is published under the following 3-clause BSD license.
|
||||
|
||||
Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* None of the names of the contributors may be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * None of the names of the contributors may be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (c) 2012 - 2013, Lukas Hosek and Alexander Wilkie
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* ============================================================================
|
||||
|
||||
|
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* Copyright 2011-2020 Blender Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
@@ -12,6 +10,8 @@
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Copyright 2011-2020 Blender Foundation
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
Submodule release/datafiles/locale updated: 0500584174...2d12637a69
Submodule release/scripts/addons updated: faa9fc7f98...089aef61de
@@ -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",
|
||||
|
@@ -1,5 +1,3 @@
|
||||
# Copyright (c) 2009 www.stani.be (GPL license)
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@@ -18,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# Copyright (c) 2009 www.stani.be
|
||||
|
||||
# <pep8 compliant>
|
||||
|
||||
"""Package for console specific modules."""
|
||||
|
@@ -1,5 +1,3 @@
|
||||
# Copyright (c) 2009 www.stani.be (GPL license)
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@@ -18,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# Copyright (c) 2009 www.stani.be
|
||||
|
||||
# <pep8-80 compliant>
|
||||
|
||||
import inspect
|
||||
|
@@ -1,5 +1,3 @@
|
||||
# Copyright (c) 2009 Fernando Perez, www.stani.be (GPL license)
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@@ -18,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# Copyright (c) 2009 Fernando Perez, www.stani.be
|
||||
|
||||
# Original copyright (see docstring):
|
||||
# ****************************************************************************
|
||||
# Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
|
||||
|
@@ -1,5 +1,3 @@
|
||||
# Copyright (c) 2009 www.stani.be (GPL license)
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@@ -18,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# Copyright (c) 2009 www.stani.be
|
||||
|
||||
# <pep8-80 compliant>
|
||||
|
||||
"""Autocomplete with the standard library"""
|
||||
|
@@ -1,5 +1,3 @@
|
||||
# Copyright (c) 2009 www.stani.be (GPL license)
|
||||
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
@@ -18,6 +16,8 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# Copyright (c) 2009 www.stani.be
|
||||
|
||||
# <pep8-80 compliant>
|
||||
|
||||
"""This module provides intellisense features such as:
|
||||
|
@@ -2139,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"),
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@@ -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.
|
@@ -1,5 +1,4 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@@ -307,6 +307,72 @@ class PHYSICS_PT_rigid_body_dynamics_deactivation(PHYSICS_PT_rigidbody_panel, Pa
|
||||
# TODO: other params such as time?
|
||||
|
||||
|
||||
class PHYSICS_PT_rigid_body_display_options(PHYSICS_PT_rigidbody_panel, Panel):
|
||||
bl_label = "Display Options"
|
||||
bl_parent_id = 'PHYSICS_PT_rigid_body'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.object
|
||||
if obj.parent is not None and obj.parent.rigid_body is not None:
|
||||
return False
|
||||
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ob = context.object
|
||||
rbo = ob.rigid_body
|
||||
|
||||
if rbo is None:
|
||||
rigid_body_warning(layout, "Object does not have a Rigid Body")
|
||||
return
|
||||
|
||||
|
||||
col = layout.column()
|
||||
if rbo.type == 'ACTIVE' and not rbo.kinematic:
|
||||
col.prop(rbo, "display_acceleration")
|
||||
col.prop(rbo, "display_velocity")
|
||||
col.prop(rbo, "display_collisions")
|
||||
col.prop(rbo, "display_data_text")
|
||||
col.prop(rbo, "display_state")
|
||||
|
||||
class PHYSICS_PT_rigid_body_display_force_types(PHYSICS_PT_rigidbody_panel, Panel):
|
||||
bl_label = "Forces"
|
||||
bl_parent_id = 'PHYSICS_PT_rigid_body_display_options'
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
obj = context.object
|
||||
if obj.parent is not None and obj.parent.rigid_body is not None:
|
||||
return False
|
||||
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
|
||||
|
||||
def draw_header(self, context):
|
||||
ob = context.object
|
||||
rbo = ob.rigid_body
|
||||
|
||||
self.layout.prop(rbo, "display_forces", text="")
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
ob = context.object
|
||||
rbo = ob.rigid_body
|
||||
col = layout.column()
|
||||
col.active = rbo.display_forces
|
||||
col.prop(rbo, "show_gravity")
|
||||
col.prop(rbo, "show_effectors_force")
|
||||
col.prop(rbo, "show_normal_force")
|
||||
col.prop(rbo, "show_frictional_force")
|
||||
col.prop(rbo, "show_net_force")
|
||||
|
||||
classes = (
|
||||
PHYSICS_PT_rigid_body,
|
||||
PHYSICS_PT_rigid_body_settings,
|
||||
@@ -316,10 +382,13 @@ classes = (
|
||||
PHYSICS_PT_rigid_body_collisions_collections,
|
||||
PHYSICS_PT_rigid_body_dynamics,
|
||||
PHYSICS_PT_rigid_body_dynamics_deactivation,
|
||||
PHYSICS_PT_rigid_body_display_options,
|
||||
PHYSICS_PT_rigid_body_display_force_types,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__": # only for live edit.
|
||||
from bpy.utils import register_class
|
||||
from bpy.utils import register_class, unregister_class
|
||||
for cls in classes:
|
||||
register_class(cls)
|
||||
|
||||
|
@@ -474,6 +474,34 @@ class PHYSICS_PT_rigid_body_constraint_springs_linear(PHYSICS_PT_rigidbody_const
|
||||
sub.prop(rbc, "spring_stiffness_z", text="Stiffness")
|
||||
sub.prop(rbc, "spring_damping_z", text="Damping")
|
||||
|
||||
class PHYSICS_PT_rigid_body_constraint_debug_draw(PHYSICS_PT_rigidbody_constraint_panel, Panel):
|
||||
bl_label = "Debug draw"
|
||||
bl_parent_id = 'PHYSICS_PT_rigid_body_constraint'
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
ob = context.object
|
||||
rbc = ob.rigid_body_constraint
|
||||
|
||||
return (ob and rbc
|
||||
and (rbc.type in {'SLIDER', 'HINGE', 'PISTON'})
|
||||
and context.engine in cls.COMPAT_ENGINES)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
|
||||
|
||||
ob = context.object
|
||||
rbc = ob.rigid_body_constraint
|
||||
|
||||
col = flow.column()
|
||||
col.prop(rbc, "debug_draw_limits", text="Debug draw")
|
||||
|
||||
if rbc.type in {'PISTON', 'SLIDER'}:
|
||||
col = flow.column()
|
||||
col.prop(rbc, "debug_draw_fade_walls", text="Fade walls")
|
||||
|
||||
classes = (
|
||||
PHYSICS_PT_rigid_body_constraint,
|
||||
@@ -489,6 +517,7 @@ classes = (
|
||||
PHYSICS_PT_rigid_body_constraint_springs,
|
||||
PHYSICS_PT_rigid_body_constraint_springs_angular,
|
||||
PHYSICS_PT_rigid_body_constraint_springs_linear,
|
||||
PHYSICS_PT_rigid_body_constraint_debug_draw,
|
||||
)
|
||||
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
# ##### BEGIN GPL LICENSE BLOCK #####
|
||||
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
@@ -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:
|
||||
|
@@ -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")
|
||||
|
@@ -2295,7 +2295,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
|
||||
def draw(self, context):
|
||||
self._draw_items(
|
||||
context, (
|
||||
({"property": "use_new_hair_type"}, "T68981"),
|
||||
({"property": "use_new_curves_type"}, "T68981"),
|
||||
({"property": "use_new_point_cloud_type"}, "T75717"),
|
||||
({"property": "use_full_frame_compositor"}, "T88150"),
|
||||
),
|
||||
|
@@ -2148,8 +2148,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')
|
||||
|
@@ -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
|
||||
|
@@ -1238,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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -40,11 +40,11 @@ struct ReportList;
|
||||
/* 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
|
||||
|
@@ -39,7 +39,7 @@ extern "C" {
|
||||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 1
|
||||
#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
|
||||
|
68
source/blender/blenkernel/BKE_curves.h
Normal file
68
source/blender/blenkernel/BKE_curves.h
Normal file
@@ -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
|
@@ -140,7 +140,8 @@ void BKE_effectors_apply(struct ListBase *effectors,
|
||||
struct EffectedPoint *point,
|
||||
float *force,
|
||||
float *wind_force,
|
||||
float *impulse);
|
||||
float *impulse,
|
||||
float r_eff_forces[3][3]);
|
||||
void BKE_effectors_free(struct ListBase *lb);
|
||||
|
||||
void pd_point_from_particle(struct ParticleSimulationData *sim,
|
||||
|
@@ -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;
|
||||
|
@@ -113,7 +113,7 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
|
||||
*/
|
||||
bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
|
||||
struct Library *owner_library,
|
||||
const struct Library *reference_library,
|
||||
const struct ID *id_root_reference,
|
||||
bool do_no_main);
|
||||
/**
|
||||
* Advanced 'smart' function to create fully functional overrides.
|
||||
@@ -172,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.
|
||||
|
@@ -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;
|
||||
|
@@ -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. */
|
||||
|
@@ -13,11 +13,8 @@
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2007 by Janne Karhu.
|
||||
* All rights reserved.
|
||||
* Adaptive time step
|
||||
* Classical SPH
|
||||
* Copyright 2011-2012 AutoCRC
|
||||
* Copyright 2007 Janne Karhu. All rights reserved.
|
||||
* 2011-2012 AutoCRC (adaptive time step, Classical SPH).
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "DNA_boid_types.h" /* for #BoidData */
|
||||
#include "DNA_pointcache_types.h" /* for #BPHYS_TOT_DATA */
|
||||
#include "DNA_rigidbody_types.h"
|
||||
|
||||
#include <stdio.h> /* for #FILE */
|
||||
|
||||
@@ -103,6 +104,12 @@ typedef struct PTCacheData {
|
||||
float size;
|
||||
float times[3];
|
||||
struct BoidData boids;
|
||||
struct sim_data_vec eff_forces[3];
|
||||
struct sim_data_vec norm_forces[3];
|
||||
struct sim_data_vec fric_forces[3];
|
||||
struct sim_data_vec vec_locations[3];
|
||||
float pvel[3];
|
||||
int colliding_faces[3];
|
||||
} PTCacheData;
|
||||
|
||||
typedef struct PTCacheFile {
|
||||
|
@@ -244,6 +244,12 @@ void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
|
||||
/* -------------------- */
|
||||
/* Debug draw collision shapes */
|
||||
/* -------------------- */
|
||||
void BKE_rigidbody_store_convex_hull_draw_data(struct Object *ob);
|
||||
void BKE_rigidbody_store_trimesh_draw_data(struct Object *ob);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -119,6 +119,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
|
||||
@@ -156,7 +157,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
|
||||
@@ -356,6 +356,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
|
||||
@@ -384,7 +385,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
|
||||
|
@@ -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);
|
||||
|
@@ -2679,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;
|
||||
@@ -2692,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;
|
||||
}
|
||||
}
|
||||
|
@@ -15,8 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Defines and code for core node types
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -15,8 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2015 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Defines and code for core node types
|
||||
*/
|
||||
|
||||
/** \file
|
||||
|
@@ -15,13 +15,12 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Implementation of generic geometry attributes management. This is built
|
||||
* on top of CustomData, which manages individual domains.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* Implementation of generic geometry attributes management. This is built
|
||||
* on top of CustomData, which manages individual domains.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -29,8 +28,8 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_hair_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
#include "DNA_pointcloud_types.h"
|
||||
@@ -38,9 +37,9 @@
|
||||
#include "BLI_string_utf8.h"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_hair.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_report.h"
|
||||
|
||||
@@ -88,12 +87,12 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ID_HA: {
|
||||
Hair *hair = (Hair *)id;
|
||||
info[ATTR_DOMAIN_POINT].customdata = &hair->geometry.point_data;
|
||||
info[ATTR_DOMAIN_POINT].length = hair->geometry.point_size;
|
||||
info[ATTR_DOMAIN_CURVE].customdata = &hair->geometry.curve_data;
|
||||
info[ATTR_DOMAIN_CURVE].length = hair->geometry.curve_size;
|
||||
case ID_CV: {
|
||||
Curves *curves = (Curves *)id;
|
||||
info[ATTR_DOMAIN_POINT].customdata = &curves->geometry.point_data;
|
||||
info[ATTR_DOMAIN_POINT].length = curves->geometry.point_size;
|
||||
info[ATTR_DOMAIN_CURVE].customdata = &curves->geometry.curve_data;
|
||||
info[ATTR_DOMAIN_CURVE].length = curves->geometry.curve_size;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -301,8 +300,8 @@ bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer)
|
||||
case ID_PT: {
|
||||
return BKE_pointcloud_customdata_required((PointCloud *)id, layer);
|
||||
}
|
||||
case ID_HA: {
|
||||
return BKE_hair_customdata_required((Hair *)id, layer);
|
||||
case ID_CV: {
|
||||
return BKE_curves_customdata_required((Curves *)id, layer);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@@ -372,8 +371,8 @@ int *BKE_id_attributes_active_index_p(ID *id)
|
||||
case ID_ME: {
|
||||
return &((Mesh *)id)->attributes_active_index;
|
||||
}
|
||||
case ID_HA: {
|
||||
return &((Hair *)id)->attributes_active_index;
|
||||
case ID_CV: {
|
||||
return &((Curves *)id)->attributes_active_index;
|
||||
}
|
||||
default:
|
||||
return NULL;
|
||||
|
@@ -374,6 +374,10 @@ static void setup_app_data(bContext *C,
|
||||
BKE_lib_override_library_main_proxy_convert(bmain, reports);
|
||||
}
|
||||
|
||||
if (mode != LOAD_UNDO && !blendfile_or_libraries_versions_atleast(bmain, 302, 3)) {
|
||||
BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
|
||||
}
|
||||
|
||||
bmain->recovered = 0;
|
||||
|
||||
/* startup.blend or recovered startup */
|
||||
|
@@ -1374,6 +1374,7 @@ void boid_body(BoidBrainData *bbd, ParticleData *pa)
|
||||
&epoint,
|
||||
force,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (ELEM(bpa->data.mode, eBoidMode_OnLand, eBoidMode_Climbing)) {
|
||||
|
@@ -15,13 +15,12 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||
* All rights reserved.
|
||||
* Implementation of CDDerivedMesh.
|
||||
*
|
||||
* BKE_cdderivedmesh.h contains the function prototypes for this file.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* Implementation of #CDDerivedMesh.
|
||||
* BKE_cdderivedmesh.h contains the function prototypes for this file.
|
||||
*/
|
||||
|
||||
#include "atomic_ops.h"
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
@@ -59,6 +60,7 @@
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_spline.hh"
|
||||
#include "BKE_vfont.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
@@ -68,6 +70,7 @@
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
using blender::float3;
|
||||
using blender::IndexRange;
|
||||
|
||||
/* globals */
|
||||
@@ -503,7 +506,10 @@ BoundBox *BKE_curve_boundbox_get(Object *ob)
|
||||
float min[3], max[3];
|
||||
|
||||
INIT_MINMAX(min, max);
|
||||
BKE_curve_minmax(cu, true, min, max);
|
||||
if (!BKE_curve_minmax(cu, true, min, max)) {
|
||||
copy_v3_fl(min, -1.0f);
|
||||
copy_v3_fl(max, 1.0f);
|
||||
}
|
||||
|
||||
if (ob->runtime.bb == nullptr) {
|
||||
ob->runtime.bb = (BoundBox *)MEM_mallocN(sizeof(*ob->runtime.bb), __func__);
|
||||
@@ -5066,6 +5072,16 @@ void BKE_curve_nurb_vert_active_validate(Curve *cu)
|
||||
|
||||
bool BKE_curve_minmax(Curve *cu, bool use_radius, float min[3], float max[3])
|
||||
{
|
||||
if (cu->curve_eval != nullptr) {
|
||||
float3 eval_min(FLT_MAX);
|
||||
float3 eval_max(-FLT_MAX);
|
||||
if (cu->curve_eval->bounds_min_max(eval_min, eval_max, false)) {
|
||||
copy_v3_v3(min, eval_min);
|
||||
copy_v3_v3(max, eval_max);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ListBase *nurb_lb = BKE_curve_nurbs_get(cu);
|
||||
ListBase temp_nurb_lb = {nullptr, nullptr};
|
||||
const bool is_font = (BLI_listbase_is_empty(nurb_lb)) && (cu->len != 0);
|
||||
|
473
source/blender/blenkernel/intern/curves.cc
Normal file
473
source/blender/blenkernel/intern/curves.cc
Normal file
@@ -0,0 +1,473 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_curves.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::RandomNumberGenerator;
|
||||
|
||||
static const char *ATTR_POSITION = "position";
|
||||
static const char *ATTR_RADIUS = "radius";
|
||||
|
||||
static void curves_random(Curves *curves);
|
||||
|
||||
static void curves_init_data(ID *id)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(curves, id));
|
||||
|
||||
MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id);
|
||||
|
||||
CustomData_reset(&curves->geometry.point_data);
|
||||
CustomData_reset(&curves->geometry.curve_data);
|
||||
|
||||
CustomData_add_layer_named(&curves->geometry.point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
curves->geometry.point_size,
|
||||
ATTR_POSITION);
|
||||
CustomData_add_layer_named(&curves->geometry.point_data,
|
||||
CD_PROP_FLOAT,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
curves->geometry.point_size,
|
||||
ATTR_RADIUS);
|
||||
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
|
||||
curves_random(curves);
|
||||
}
|
||||
|
||||
static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
|
||||
{
|
||||
Curves *curves_dst = (Curves *)id_dst;
|
||||
const Curves *curves_src = (const Curves *)id_src;
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
|
||||
curves_dst->geometry.point_size = curves_src->geometry.point_size;
|
||||
curves_dst->geometry.curve_size = curves_src->geometry.curve_size;
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&curves_src->geometry.point_data,
|
||||
&curves_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
curves_dst->geometry.point_size);
|
||||
CustomData_copy(&curves_src->geometry.curve_data,
|
||||
&curves_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
curves_dst->geometry.curve_size);
|
||||
BKE_curves_update_customdata_pointers(curves_dst);
|
||||
|
||||
curves_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(curves_src->geometry.offsets));
|
||||
|
||||
curves_dst->batch_cache = nullptr;
|
||||
}
|
||||
|
||||
static void curves_free_data(ID *id)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
BKE_animdata_free(&curves->id, false);
|
||||
|
||||
BKE_curves_batch_cache_free(curves);
|
||||
|
||||
CustomData_free(&curves->geometry.point_data, curves->geometry.point_size);
|
||||
CustomData_free(&curves->geometry.curve_data, curves->geometry.curve_size);
|
||||
|
||||
MEM_SAFE_FREE(curves->geometry.offsets);
|
||||
|
||||
MEM_SAFE_FREE(curves->mat);
|
||||
}
|
||||
|
||||
static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
for (int i = 0; i < curves->totcol; i++) {
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER);
|
||||
}
|
||||
}
|
||||
|
||||
static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
|
||||
CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
|
||||
CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
|
||||
CustomData_blend_write_prepare(
|
||||
&curves->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
|
||||
CustomData_blend_write_prepare(
|
||||
&curves->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
|
||||
|
||||
/* Write LibData */
|
||||
BLO_write_id_struct(writer, Curves, id_address, &curves->id);
|
||||
BKE_id_blend_write(writer, &curves->id);
|
||||
|
||||
/* Direct data */
|
||||
CustomData_blend_write(writer,
|
||||
&curves->geometry.point_data,
|
||||
players,
|
||||
curves->geometry.point_size,
|
||||
CD_MASK_ALL,
|
||||
&curves->id);
|
||||
CustomData_blend_write(writer,
|
||||
&curves->geometry.curve_data,
|
||||
clayers,
|
||||
curves->geometry.curve_size,
|
||||
CD_MASK_ALL,
|
||||
&curves->id);
|
||||
|
||||
BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.offsets);
|
||||
|
||||
BLO_write_pointer_array(writer, curves->totcol, curves->mat);
|
||||
if (curves->adt) {
|
||||
BKE_animdata_blend_write(writer, curves->adt);
|
||||
}
|
||||
|
||||
/* Remove temporary data. */
|
||||
if (players && players != players_buff) {
|
||||
MEM_freeN(players);
|
||||
}
|
||||
if (clayers && clayers != clayers_buff) {
|
||||
MEM_freeN(clayers);
|
||||
}
|
||||
}
|
||||
|
||||
static void curves_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
BLO_read_data_address(reader, &curves->adt);
|
||||
BKE_animdata_blend_read_data(reader, curves->adt);
|
||||
|
||||
/* Geometry */
|
||||
CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_size);
|
||||
CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.point_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
|
||||
BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.offsets);
|
||||
|
||||
/* Materials */
|
||||
BLO_read_pointer_array(reader, (void **)&curves->mat);
|
||||
}
|
||||
|
||||
static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
for (int a = 0; a < curves->totcol; a++) {
|
||||
BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
|
||||
}
|
||||
}
|
||||
|
||||
static void curves_blend_read_expand(BlendExpander *expander, ID *id)
|
||||
{
|
||||
Curves *curves = (Curves *)id;
|
||||
for (int a = 0; a < curves->totcol; a++) {
|
||||
BLO_expand(expander, curves->mat[a]);
|
||||
}
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_CV = {
|
||||
/*id_code */ ID_CV,
|
||||
/*id_filter */ FILTER_ID_CV,
|
||||
/*main_listbase_index */ INDEX_ID_CV,
|
||||
/*struct_size */ sizeof(Curves),
|
||||
/*name */ "Hair Curves",
|
||||
/*name_plural */ "Hair Curves",
|
||||
/*translation_context */ BLT_I18NCONTEXT_ID_CURVES,
|
||||
/*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
||||
/*asset_type_info */ nullptr,
|
||||
|
||||
/*init_data */ curves_init_data,
|
||||
/*copy_data */ curves_copy_data,
|
||||
/*free_data */ curves_free_data,
|
||||
/*make_local */ nullptr,
|
||||
/*foreach_id */ curves_foreach_id,
|
||||
/*foreach_cache */ nullptr,
|
||||
/*foreach_path */ nullptr,
|
||||
/*owner_get */ nullptr,
|
||||
|
||||
/*blend_write */ curves_blend_write,
|
||||
/*blend_read_data */ curves_blend_read_data,
|
||||
/*blend_read_lib */ curves_blend_read_lib,
|
||||
/*blend_read_expand */ curves_blend_read_expand,
|
||||
|
||||
/*blend_read_undo_preserve */ nullptr,
|
||||
|
||||
/*lib_override_apply_post */ nullptr,
|
||||
};
|
||||
|
||||
static void curves_random(Curves *curves)
|
||||
{
|
||||
CurvesGeometry &geometry = curves->geometry;
|
||||
const int numpoints = 8;
|
||||
|
||||
geometry.curve_size = 500;
|
||||
|
||||
geometry.curve_size = 500;
|
||||
geometry.point_size = geometry.curve_size * numpoints;
|
||||
|
||||
curves->geometry.offsets = (int *)MEM_calloc_arrayN(
|
||||
curves->geometry.curve_size + 1, sizeof(int), __func__);
|
||||
CustomData_realloc(&geometry.point_data, geometry.point_size);
|
||||
CustomData_realloc(&geometry.curve_data, geometry.curve_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
|
||||
MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
|
||||
MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
|
||||
MutableSpan<float> radii{geometry.radius, geometry.point_size};
|
||||
|
||||
for (const int i : offsets.index_range()) {
|
||||
geometry.offsets[i] = numpoints * i;
|
||||
}
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
|
||||
for (int i = 0; i < geometry.curve_size; i++) {
|
||||
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
|
||||
MutableSpan<float3> curve_positions = positions.slice(curve_range);
|
||||
MutableSpan<float> curve_radii = radii.slice(curve_range);
|
||||
|
||||
const float theta = 2.0f * M_PI * rng.get_float();
|
||||
const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
|
||||
|
||||
float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
|
||||
no = blender::math::normalize(no);
|
||||
|
||||
float3 co = no;
|
||||
for (int key = 0; key < numpoints; key++) {
|
||||
float t = key / (float)(numpoints - 1);
|
||||
curve_positions[key] = co;
|
||||
curve_radii[key] = 0.02f * (1.0f - t);
|
||||
|
||||
float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
|
||||
co += (offset + no) / numpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *BKE_curves_add(Main *bmain, const char *name)
|
||||
{
|
||||
Curves *curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, name));
|
||||
|
||||
return curves;
|
||||
}
|
||||
|
||||
BoundBox *BKE_curves_boundbox_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_CURVES);
|
||||
Curves *curves = static_cast<Curves *>(ob->data);
|
||||
|
||||
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
|
||||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
if (ob->runtime.bb == nullptr) {
|
||||
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
|
||||
|
||||
float min[3], max[3];
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
float(*curves_co)[3] = curves->geometry.position;
|
||||
float *curves_radius = curves->geometry.radius;
|
||||
for (int a = 0; a < curves->geometry.point_size; a++) {
|
||||
float *co = curves_co[a];
|
||||
float radius = (curves_radius) ? curves_radius[a] : 0.0f;
|
||||
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
|
||||
const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
|
||||
DO_MIN(co_min, min);
|
||||
DO_MAX(co_max, max);
|
||||
}
|
||||
|
||||
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
|
||||
}
|
||||
|
||||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
void BKE_curves_update_customdata_pointers(Curves *curves)
|
||||
{
|
||||
curves->geometry.position = (float(*)[3])CustomData_get_layer_named(
|
||||
&curves->geometry.point_data, CD_PROP_FLOAT3, ATTR_POSITION);
|
||||
curves->geometry.radius = (float *)CustomData_get_layer_named(
|
||||
&curves->geometry.point_data, CD_PROP_FLOAT, ATTR_RADIUS);
|
||||
}
|
||||
|
||||
bool BKE_curves_customdata_required(Curves *UNUSED(curves), CustomDataLayer *layer)
|
||||
{
|
||||
return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, ATTR_POSITION);
|
||||
}
|
||||
|
||||
/* Dependency Graph */
|
||||
|
||||
Curves *BKE_curves_new_for_eval(const Curves *curves_src, int totpoint, int totcurve)
|
||||
{
|
||||
Curves *curves_dst = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
|
||||
|
||||
STRNCPY(curves_dst->id.name, curves_src->id.name);
|
||||
curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
|
||||
curves_dst->totcol = curves_src->totcol;
|
||||
|
||||
curves_dst->geometry.point_size = totpoint;
|
||||
curves_dst->geometry.curve_size = totcurve;
|
||||
CustomData_copy(&curves_src->geometry.point_data,
|
||||
&curves_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totpoint);
|
||||
CustomData_copy(&curves_src->geometry.curve_data,
|
||||
&curves_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totcurve);
|
||||
BKE_curves_update_customdata_pointers(curves_dst);
|
||||
|
||||
return curves_dst;
|
||||
}
|
||||
|
||||
Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
||||
if (reference) {
|
||||
flags |= LIB_ID_COPY_CD_REFERENCE;
|
||||
}
|
||||
|
||||
Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
Object *object,
|
||||
Curves *curves_input)
|
||||
{
|
||||
Curves *curves = curves_input;
|
||||
|
||||
/* Modifier evaluation modes. */
|
||||
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
|
||||
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
|
||||
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
|
||||
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
|
||||
|
||||
/* Get effective list of modifiers to execute. Some effects like shape keys
|
||||
* are added as virtual modifiers before the user created modifiers. */
|
||||
VirtualModifierData virtualModifierData;
|
||||
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
|
||||
|
||||
/* Evaluate modifiers. */
|
||||
for (; md; md = md->next) {
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
|
||||
|
||||
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mti->type == eModifierTypeType_OnlyDeform) &&
|
||||
(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
|
||||
/* Ensure we are not modifying the input. */
|
||||
if (curves == curves_input) {
|
||||
curves = BKE_curves_copy_for_eval(curves, true);
|
||||
}
|
||||
|
||||
/* Ensure we are not overwriting referenced data. */
|
||||
CustomData_duplicate_referenced_layer_named(&curves->geometry.point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
ATTR_POSITION,
|
||||
curves->geometry.point_size);
|
||||
BKE_curves_update_customdata_pointers(curves);
|
||||
|
||||
/* Created deformed coordinates array on demand. */
|
||||
mti->deformVerts(
|
||||
md, &mectx, nullptr, curves->geometry.position, curves->geometry.point_size);
|
||||
}
|
||||
}
|
||||
|
||||
return curves;
|
||||
}
|
||||
|
||||
void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
|
||||
{
|
||||
/* Free any evaluated data and restore original data. */
|
||||
BKE_object_free_derived_caches(object);
|
||||
|
||||
/* Evaluate modifiers. */
|
||||
Curves *curves = static_cast<Curves *>(object->data);
|
||||
Curves *curves_eval = curves_evaluate_modifiers(depsgraph, scene, object, curves);
|
||||
|
||||
/* Assign evaluated object. */
|
||||
const bool is_owned = (curves != curves_eval);
|
||||
BKE_object_eval_assign_data(object, &curves_eval->id, is_owned);
|
||||
}
|
||||
|
||||
/* Draw Cache */
|
||||
|
||||
void (*BKE_curves_batch_cache_dirty_tag_cb)(Curves *curves, int mode) = nullptr;
|
||||
void (*BKE_curves_batch_cache_free_cb)(Curves *curves) = nullptr;
|
||||
|
||||
void BKE_curves_batch_cache_dirty_tag(Curves *curves, int mode)
|
||||
{
|
||||
if (curves->batch_cache) {
|
||||
BKE_curves_batch_cache_dirty_tag_cb(curves, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_curves_batch_cache_free(Curves *curves)
|
||||
{
|
||||
if (curves->batch_cache) {
|
||||
BKE_curves_batch_cache_free_cb(curves);
|
||||
}
|
||||
}
|
@@ -15,13 +15,13 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2006 Blender Foundation.
|
||||
* All rights reserved.
|
||||
* Implementation of CustomData.
|
||||
*
|
||||
* BKE_customdata.h contains the function prototypes for this file.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* Implementation of CustomData.
|
||||
*
|
||||
* BKE_customdata.h contains the function prototypes for this file.
|
||||
*/
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@@ -31,7 +31,6 @@
|
||||
|
||||
#include "DNA_ID.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_hair_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
|
@@ -5082,7 +5082,8 @@ static void dynamic_paint_prepare_effect_cb(void *__restrict userdata,
|
||||
EffectedPoint epoint;
|
||||
pd_point_from_loc(scene, realCoord[bData->s_pos[index]].v, vel, index, &epoint);
|
||||
epoint.vel_to_sec = 1.0f;
|
||||
BKE_effectors_apply(effectors, NULL, surface->effector_weights, &epoint, forc, NULL, NULL);
|
||||
BKE_effectors_apply(
|
||||
effectors, NULL, surface->effector_weights, &epoint, forc, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/* if global gravity is enabled, add it too */
|
||||
|
@@ -1135,7 +1135,8 @@ void BKE_effectors_apply(ListBase *effectors,
|
||||
EffectedPoint *point,
|
||||
float *force,
|
||||
float *wind_force,
|
||||
float *impulse)
|
||||
float *impulse,
|
||||
float r_eff_forces[3][3])
|
||||
{
|
||||
/* WARNING(@campbellbarton): historic comment?
|
||||
* Many of these parameters don't exist!
|
||||
@@ -1173,6 +1174,8 @@ void BKE_effectors_apply(ListBase *effectors,
|
||||
/* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */
|
||||
/* Check for min distance here? (yes would be cool to add that, ton) */
|
||||
|
||||
int num_eff_forces = 0;
|
||||
float out_force[3] = {0, 0, 0};
|
||||
if (effectors) {
|
||||
for (eff = effectors->first; eff; eff = eff->next) {
|
||||
/* object effectors were fully checked to be OK to evaluate! */
|
||||
@@ -1187,7 +1190,7 @@ void BKE_effectors_apply(ListBase *effectors,
|
||||
efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point);
|
||||
}
|
||||
if (efd.falloff > 0.0f) {
|
||||
float out_force[3] = {0, 0, 0};
|
||||
zero_v3(out_force);
|
||||
|
||||
if (eff->pd->forcefield == PFIELD_TEXTURE) {
|
||||
do_texture_effector(eff, &efd, point, out_force);
|
||||
@@ -1214,6 +1217,11 @@ void BKE_effectors_apply(ListBase *effectors,
|
||||
/* special case for harmonic effector */
|
||||
add_v3_v3v3(impulse, impulse, efd.vel);
|
||||
}
|
||||
|
||||
if (r_eff_forces != NULL && num_eff_forces < 3) {
|
||||
copy_v3_v3(r_eff_forces[num_eff_forces], out_force);
|
||||
num_eff_forces++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3195,7 +3195,7 @@ static void update_effectors_task_cb(void *__restrict userdata,
|
||||
/* Do effectors. */
|
||||
pd_point_from_loc(data->scene, voxel_center, vel, index, &epoint);
|
||||
BKE_effectors_apply(
|
||||
data->effectors, NULL, fds->effector_weights, &epoint, retvel, NULL, NULL);
|
||||
data->effectors, NULL, fds->effector_weights, &epoint, retvel, NULL, NULL, NULL);
|
||||
|
||||
/* Convert retvel to local space. */
|
||||
mag = len_v3(retvel);
|
||||
|
@@ -1,474 +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.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_hair_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
#include "BLI_index_range.hh"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vec_types.hh"
|
||||
#include "BLI_rand.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_hair.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
#include "BKE_lib_remap.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_object.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "BLO_read_write.h"
|
||||
|
||||
using blender::float3;
|
||||
using blender::IndexRange;
|
||||
using blender::MutableSpan;
|
||||
using blender::RandomNumberGenerator;
|
||||
|
||||
static const char *HAIR_ATTR_POSITION = "position";
|
||||
static const char *HAIR_ATTR_RADIUS = "radius";
|
||||
|
||||
/* Hair datablock */
|
||||
|
||||
static void hair_random(Hair *hair);
|
||||
|
||||
static void hair_init_data(ID *id)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hair, id));
|
||||
|
||||
MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id);
|
||||
|
||||
CustomData_reset(&hair->geometry.point_data);
|
||||
CustomData_reset(&hair->geometry.curve_data);
|
||||
|
||||
CustomData_add_layer_named(&hair->geometry.point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
hair->geometry.point_size,
|
||||
HAIR_ATTR_POSITION);
|
||||
CustomData_add_layer_named(&hair->geometry.point_data,
|
||||
CD_PROP_FLOAT,
|
||||
CD_CALLOC,
|
||||
nullptr,
|
||||
hair->geometry.point_size,
|
||||
HAIR_ATTR_RADIUS);
|
||||
|
||||
BKE_hair_update_customdata_pointers(hair);
|
||||
|
||||
hair_random(hair);
|
||||
}
|
||||
|
||||
static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
|
||||
{
|
||||
Hair *hair_dst = (Hair *)id_dst;
|
||||
const Hair *hair_src = (const Hair *)id_src;
|
||||
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
|
||||
|
||||
hair_dst->geometry.point_size = hair_src->geometry.point_size;
|
||||
hair_dst->geometry.curve_size = hair_src->geometry.curve_size;
|
||||
|
||||
const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
|
||||
CustomData_copy(&hair_src->geometry.point_data,
|
||||
&hair_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
hair_dst->geometry.point_size);
|
||||
CustomData_copy(&hair_src->geometry.curve_data,
|
||||
&hair_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
alloc_type,
|
||||
hair_dst->geometry.curve_size);
|
||||
BKE_hair_update_customdata_pointers(hair_dst);
|
||||
|
||||
hair_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(hair_src->geometry.offsets));
|
||||
|
||||
hair_dst->batch_cache = nullptr;
|
||||
}
|
||||
|
||||
static void hair_free_data(ID *id)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
BKE_animdata_free(&hair->id, false);
|
||||
|
||||
BKE_hair_batch_cache_free(hair);
|
||||
|
||||
CustomData_free(&hair->geometry.point_data, hair->geometry.point_size);
|
||||
CustomData_free(&hair->geometry.curve_data, hair->geometry.curve_size);
|
||||
|
||||
MEM_SAFE_FREE(hair->geometry.offsets);
|
||||
|
||||
MEM_SAFE_FREE(hair->mat);
|
||||
}
|
||||
|
||||
static void hair_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
for (int i = 0; i < hair->totcol; i++) {
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, hair->mat[i], IDWALK_CB_USER);
|
||||
}
|
||||
}
|
||||
|
||||
static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
|
||||
CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
|
||||
CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
|
||||
CustomData_blend_write_prepare(
|
||||
&hair->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
|
||||
CustomData_blend_write_prepare(
|
||||
&hair->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
|
||||
|
||||
/* Write LibData */
|
||||
BLO_write_id_struct(writer, Hair, id_address, &hair->id);
|
||||
BKE_id_blend_write(writer, &hair->id);
|
||||
|
||||
/* Direct data */
|
||||
CustomData_blend_write(writer,
|
||||
&hair->geometry.point_data,
|
||||
players,
|
||||
hair->geometry.point_size,
|
||||
CD_MASK_ALL,
|
||||
&hair->id);
|
||||
CustomData_blend_write(writer,
|
||||
&hair->geometry.curve_data,
|
||||
clayers,
|
||||
hair->geometry.curve_size,
|
||||
CD_MASK_ALL,
|
||||
&hair->id);
|
||||
|
||||
BLO_write_int32_array(writer, hair->geometry.curve_size + 1, hair->geometry.offsets);
|
||||
|
||||
BLO_write_pointer_array(writer, hair->totcol, hair->mat);
|
||||
if (hair->adt) {
|
||||
BKE_animdata_blend_write(writer, hair->adt);
|
||||
}
|
||||
|
||||
/* Remove temporary data. */
|
||||
if (players && players != players_buff) {
|
||||
MEM_freeN(players);
|
||||
}
|
||||
if (clayers && clayers != clayers_buff) {
|
||||
MEM_freeN(clayers);
|
||||
}
|
||||
}
|
||||
|
||||
static void hair_blend_read_data(BlendDataReader *reader, ID *id)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
BLO_read_data_address(reader, &hair->adt);
|
||||
BKE_animdata_blend_read_data(reader, hair->adt);
|
||||
|
||||
/* Geometry */
|
||||
CustomData_blend_read(reader, &hair->geometry.point_data, hair->geometry.point_size);
|
||||
CustomData_blend_read(reader, &hair->geometry.curve_data, hair->geometry.point_size);
|
||||
BKE_hair_update_customdata_pointers(hair);
|
||||
|
||||
BLO_read_int32_array(reader, hair->geometry.curve_size + 1, &hair->geometry.offsets);
|
||||
|
||||
/* Materials */
|
||||
BLO_read_pointer_array(reader, (void **)&hair->mat);
|
||||
}
|
||||
|
||||
static void hair_blend_read_lib(BlendLibReader *reader, ID *id)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
for (int a = 0; a < hair->totcol; a++) {
|
||||
BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]);
|
||||
}
|
||||
}
|
||||
|
||||
static void hair_blend_read_expand(BlendExpander *expander, ID *id)
|
||||
{
|
||||
Hair *hair = (Hair *)id;
|
||||
for (int a = 0; a < hair->totcol; a++) {
|
||||
BLO_expand(expander, hair->mat[a]);
|
||||
}
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_HA = {
|
||||
/*id_code */ ID_HA,
|
||||
/*id_filter */ FILTER_ID_HA,
|
||||
/*main_listbase_index */ INDEX_ID_HA,
|
||||
/*struct_size */ sizeof(Hair),
|
||||
/*name */ "Hair",
|
||||
/*name_plural */ "hairs",
|
||||
/*translation_context */ BLT_I18NCONTEXT_ID_HAIR,
|
||||
/*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
|
||||
/*asset_type_info */ nullptr,
|
||||
|
||||
/*init_data */ hair_init_data,
|
||||
/*copy_data */ hair_copy_data,
|
||||
/*free_data */ hair_free_data,
|
||||
/*make_local */ nullptr,
|
||||
/*foreach_id */ hair_foreach_id,
|
||||
/*foreach_cache */ nullptr,
|
||||
/*foreach_path */ nullptr,
|
||||
/*owner_get */ nullptr,
|
||||
|
||||
/*blend_write */ hair_blend_write,
|
||||
/*blend_read_data */ hair_blend_read_data,
|
||||
/*blend_read_lib */ hair_blend_read_lib,
|
||||
/*blend_read_expand */ hair_blend_read_expand,
|
||||
|
||||
/*blend_read_undo_preserve */ nullptr,
|
||||
|
||||
/*lib_override_apply_post */ nullptr,
|
||||
};
|
||||
|
||||
static void hair_random(Hair *hair)
|
||||
{
|
||||
CurvesGeometry &geometry = hair->geometry;
|
||||
const int numpoints = 8;
|
||||
|
||||
geometry.curve_size = 500;
|
||||
|
||||
geometry.curve_size = 500;
|
||||
geometry.point_size = geometry.curve_size * numpoints;
|
||||
|
||||
hair->geometry.offsets = (int *)MEM_calloc_arrayN(
|
||||
hair->geometry.curve_size + 1, sizeof(int), __func__);
|
||||
CustomData_realloc(&geometry.point_data, geometry.point_size);
|
||||
CustomData_realloc(&geometry.curve_data, geometry.curve_size);
|
||||
BKE_hair_update_customdata_pointers(hair);
|
||||
|
||||
MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
|
||||
MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
|
||||
MutableSpan<float> radii{geometry.radius, geometry.point_size};
|
||||
|
||||
for (const int i : offsets.index_range()) {
|
||||
geometry.offsets[i] = numpoints * i;
|
||||
}
|
||||
|
||||
RandomNumberGenerator rng;
|
||||
|
||||
for (int i = 0; i < geometry.curve_size; i++) {
|
||||
const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
|
||||
MutableSpan<float3> curve_positions = positions.slice(curve_range);
|
||||
MutableSpan<float> curve_radii = radii.slice(curve_range);
|
||||
|
||||
const float theta = 2.0f * M_PI * rng.get_float();
|
||||
const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
|
||||
|
||||
float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
|
||||
no = blender::math::normalize(no);
|
||||
|
||||
float3 co = no;
|
||||
for (int key = 0; key < numpoints; key++) {
|
||||
float t = key / (float)(numpoints - 1);
|
||||
curve_positions[key] = co;
|
||||
curve_radii[key] = 0.02f * (1.0f - t);
|
||||
|
||||
float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
|
||||
co += (offset + no) / numpoints;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *BKE_hair_add(Main *bmain, const char *name)
|
||||
{
|
||||
Hair *hair = static_cast<Hair *>(BKE_id_new(bmain, ID_HA, name));
|
||||
|
||||
return hair;
|
||||
}
|
||||
|
||||
BoundBox *BKE_hair_boundbox_get(Object *ob)
|
||||
{
|
||||
BLI_assert(ob->type == OB_HAIR);
|
||||
Hair *hair = static_cast<Hair *>(ob->data);
|
||||
|
||||
if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
|
||||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
if (ob->runtime.bb == nullptr) {
|
||||
ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
|
||||
|
||||
float min[3], max[3];
|
||||
INIT_MINMAX(min, max);
|
||||
|
||||
float(*hair_co)[3] = hair->geometry.position;
|
||||
float *hair_radius = hair->geometry.radius;
|
||||
for (int a = 0; a < hair->geometry.point_size; a++) {
|
||||
float *co = hair_co[a];
|
||||
float radius = (hair_radius) ? hair_radius[a] : 0.0f;
|
||||
const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
|
||||
const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
|
||||
DO_MIN(co_min, min);
|
||||
DO_MAX(co_max, max);
|
||||
}
|
||||
|
||||
BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
|
||||
}
|
||||
|
||||
return ob->runtime.bb;
|
||||
}
|
||||
|
||||
void BKE_hair_update_customdata_pointers(Hair *hair)
|
||||
{
|
||||
hair->geometry.position = (float(*)[3])CustomData_get_layer_named(
|
||||
&hair->geometry.point_data, CD_PROP_FLOAT3, HAIR_ATTR_POSITION);
|
||||
hair->geometry.radius = (float *)CustomData_get_layer_named(
|
||||
&hair->geometry.point_data, CD_PROP_FLOAT, HAIR_ATTR_RADIUS);
|
||||
}
|
||||
|
||||
bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer)
|
||||
{
|
||||
return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, HAIR_ATTR_POSITION);
|
||||
}
|
||||
|
||||
/* Dependency Graph */
|
||||
|
||||
Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve)
|
||||
{
|
||||
Hair *hair_dst = static_cast<Hair *>(BKE_id_new_nomain(ID_HA, nullptr));
|
||||
|
||||
STRNCPY(hair_dst->id.name, hair_src->id.name);
|
||||
hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
|
||||
hair_dst->totcol = hair_src->totcol;
|
||||
|
||||
hair_dst->geometry.point_size = totpoint;
|
||||
hair_dst->geometry.curve_size = totcurve;
|
||||
CustomData_copy(&hair_src->geometry.point_data,
|
||||
&hair_dst->geometry.point_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totpoint);
|
||||
CustomData_copy(&hair_src->geometry.curve_data,
|
||||
&hair_dst->geometry.curve_data,
|
||||
CD_MASK_ALL,
|
||||
CD_CALLOC,
|
||||
totcurve);
|
||||
BKE_hair_update_customdata_pointers(hair_dst);
|
||||
|
||||
return hair_dst;
|
||||
}
|
||||
|
||||
Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference)
|
||||
{
|
||||
int flags = LIB_ID_COPY_LOCALIZE;
|
||||
|
||||
if (reference) {
|
||||
flags |= LIB_ID_COPY_CD_REFERENCE;
|
||||
}
|
||||
|
||||
Hair *result = (Hair *)BKE_id_copy_ex(nullptr, &hair_src->id, nullptr, flags);
|
||||
return result;
|
||||
}
|
||||
|
||||
static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
Object *object,
|
||||
Hair *hair_input)
|
||||
{
|
||||
Hair *hair = hair_input;
|
||||
|
||||
/* Modifier evaluation modes. */
|
||||
const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
|
||||
const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
|
||||
ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
|
||||
const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
|
||||
|
||||
/* Get effective list of modifiers to execute. Some effects like shape keys
|
||||
* are added as virtual modifiers before the user created modifiers. */
|
||||
VirtualModifierData virtualModifierData;
|
||||
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
|
||||
|
||||
/* Evaluate modifiers. */
|
||||
for (; md; md = md->next) {
|
||||
const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
|
||||
|
||||
if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((mti->type == eModifierTypeType_OnlyDeform) &&
|
||||
(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
|
||||
/* Ensure we are not modifying the input. */
|
||||
if (hair == hair_input) {
|
||||
hair = BKE_hair_copy_for_eval(hair, true);
|
||||
}
|
||||
|
||||
/* Ensure we are not overwriting referenced data. */
|
||||
CustomData_duplicate_referenced_layer_named(&hair->geometry.point_data,
|
||||
CD_PROP_FLOAT3,
|
||||
HAIR_ATTR_POSITION,
|
||||
hair->geometry.point_size);
|
||||
BKE_hair_update_customdata_pointers(hair);
|
||||
|
||||
/* Created deformed coordinates array on demand. */
|
||||
mti->deformVerts(md, &mectx, nullptr, hair->geometry.position, hair->geometry.point_size);
|
||||
}
|
||||
}
|
||||
|
||||
return hair;
|
||||
}
|
||||
|
||||
void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
|
||||
{
|
||||
/* Free any evaluated data and restore original data. */
|
||||
BKE_object_free_derived_caches(object);
|
||||
|
||||
/* Evaluate modifiers. */
|
||||
Hair *hair = static_cast<Hair *>(object->data);
|
||||
Hair *hair_eval = hair_evaluate_modifiers(depsgraph, scene, object, hair);
|
||||
|
||||
/* Assign evaluated object. */
|
||||
const bool is_owned = (hair != hair_eval);
|
||||
BKE_object_eval_assign_data(object, &hair_eval->id, is_owned);
|
||||
}
|
||||
|
||||
/* Draw Cache */
|
||||
|
||||
void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = nullptr;
|
||||
void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = nullptr;
|
||||
|
||||
void BKE_hair_batch_cache_dirty_tag(Hair *hair, int mode)
|
||||
{
|
||||
if (hair->batch_cache) {
|
||||
BKE_hair_batch_cache_dirty_tag_cb(hair, mode);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_hair_batch_cache_free(Hair *hair)
|
||||
{
|
||||
if (hair->batch_cache) {
|
||||
BKE_hair_batch_cache_free_cb(hair);
|
||||
}
|
||||
}
|
@@ -15,9 +15,6 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
|
||||
* All rights reserved.
|
||||
* Modifier stack implementation.
|
||||
*
|
||||
* BKE_modifier.h contains the function prototypes for this file.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
@@ -110,7 +107,7 @@ static void id_type_init(void)
|
||||
INIT_TYPE(ID_CF);
|
||||
INIT_TYPE(ID_WS);
|
||||
INIT_TYPE(ID_LP);
|
||||
INIT_TYPE(ID_HA);
|
||||
INIT_TYPE(ID_CV);
|
||||
INIT_TYPE(ID_PT);
|
||||
INIT_TYPE(ID_VO);
|
||||
INIT_TYPE(ID_SIM);
|
||||
@@ -237,7 +234,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
|
||||
CASE_IDFILTER(CU);
|
||||
CASE_IDFILTER(GD);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(HA);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
CASE_IDFILTER(LA);
|
||||
CASE_IDFILTER(LS);
|
||||
@@ -286,7 +283,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
|
||||
CASE_IDFILTER(CU);
|
||||
CASE_IDFILTER(GD);
|
||||
CASE_IDFILTER(GR);
|
||||
CASE_IDFILTER(HA);
|
||||
CASE_IDFILTER(CV);
|
||||
CASE_IDFILTER(IM);
|
||||
CASE_IDFILTER(LA);
|
||||
CASE_IDFILTER(LS);
|
||||
@@ -334,7 +331,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
|
||||
CASE_IDINDEX(CU);
|
||||
CASE_IDINDEX(GD);
|
||||
CASE_IDINDEX(GR);
|
||||
CASE_IDINDEX(HA);
|
||||
CASE_IDINDEX(CV);
|
||||
CASE_IDINDEX(IM);
|
||||
CASE_IDINDEX(IP);
|
||||
CASE_IDINDEX(KE);
|
||||
@@ -393,7 +390,7 @@ short BKE_idtype_idcode_from_index(const int index)
|
||||
CASE_IDCODE(CU);
|
||||
CASE_IDCODE(GD);
|
||||
CASE_IDCODE(GR);
|
||||
CASE_IDCODE(HA);
|
||||
CASE_IDCODE(CV);
|
||||
CASE_IDCODE(IM);
|
||||
CASE_IDCODE(IP);
|
||||
CASE_IDCODE(KE);
|
||||
|
@@ -161,6 +161,8 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f
|
||||
(ID *)src_id;
|
||||
id_us_plus(dst_id->override_library->reference);
|
||||
|
||||
dst_id->override_library->hierarchy_root = src_id->override_library->hierarchy_root;
|
||||
|
||||
if (do_full_copy) {
|
||||
BLI_duplicatelist(&dst_id->override_library->properties,
|
||||
&src_id->override_library->properties);
|
||||
@@ -293,6 +295,7 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
|
||||
* mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
|
||||
* Ref T94650. */
|
||||
local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY;
|
||||
local_id->override_library->hierarchy_root = local_id;
|
||||
|
||||
if (do_tagged_remap) {
|
||||
Key *reference_key, *local_key = NULL;
|
||||
@@ -328,9 +331,11 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
|
||||
|
||||
bool BKE_lib_override_library_create_from_tag(Main *bmain,
|
||||
Library *owner_library,
|
||||
const Library *reference_library,
|
||||
const ID *id_root_reference,
|
||||
const bool do_no_main)
|
||||
{
|
||||
const Library *reference_library = id_root_reference->lib;
|
||||
|
||||
ID *reference_id;
|
||||
bool success = true;
|
||||
|
||||
@@ -383,6 +388,8 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
|
||||
/* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
|
||||
* existing linked IDs usages. */
|
||||
if (success) {
|
||||
ID *hierarchy_root_id = id_root_reference->newid;
|
||||
|
||||
for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
|
||||
reference_id = todo_id_iter->data;
|
||||
ID *local_id = reference_id->newid;
|
||||
@@ -391,6 +398,8 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
|
||||
continue;
|
||||
}
|
||||
|
||||
local_id->override_library->hierarchy_root = hierarchy_root_id;
|
||||
|
||||
Key *reference_key, *local_key = NULL;
|
||||
if ((reference_key = BKE_key_from_id(reference_id)) != NULL) {
|
||||
local_key = BKE_key_from_id(reference_id->newid);
|
||||
@@ -459,6 +468,7 @@ typedef struct LibOverrideGroupTagData {
|
||||
Main *bmain;
|
||||
Scene *scene;
|
||||
ID *id_root;
|
||||
ID *hierarchy_root_id;
|
||||
uint tag;
|
||||
uint missing_tag;
|
||||
/* Whether we are looping on override data, or their references (linked) one. */
|
||||
@@ -769,6 +779,8 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner));
|
||||
BLI_assert(data->is_override);
|
||||
|
||||
ID *id_hierarchy_root = data->hierarchy_root_id;
|
||||
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner) &&
|
||||
(id_owner->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) != 0) {
|
||||
return;
|
||||
@@ -800,9 +812,15 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
|
||||
if (ELEM(to_id, NULL, id_owner)) {
|
||||
continue;
|
||||
}
|
||||
/* Different libraries or different hierarchy roots are break points in override hierarchies.
|
||||
*/
|
||||
if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id_owner->lib)) {
|
||||
continue;
|
||||
}
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id) &&
|
||||
to_id->override_library->hierarchy_root != id_hierarchy_root) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Library *reference_lib = lib_override_get(bmain, id_owner)->reference->lib;
|
||||
ID *to_id_reference = lib_override_get(bmain, to_id)->reference;
|
||||
@@ -832,6 +850,11 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
|
||||
BLI_assert(data->is_override);
|
||||
|
||||
ID *id_hierarchy_root = data->hierarchy_root_id;
|
||||
BLI_assert(id_hierarchy_root != NULL);
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root));
|
||||
UNUSED_VARS_NDEBUG(id_hierarchy_root);
|
||||
|
||||
if (id_root->override_library->reference->tag & LIB_TAG_MISSING) {
|
||||
id_root->tag |= data->missing_tag;
|
||||
}
|
||||
@@ -865,7 +888,10 @@ static bool lib_override_library_create_do(Main *bmain,
|
||||
BKE_main_relations_free(bmain);
|
||||
lib_override_group_tag_data_clear(&data);
|
||||
|
||||
return BKE_lib_override_library_create_from_tag(bmain, owner_library, id_root->lib, false);
|
||||
const bool success = BKE_lib_override_library_create_from_tag(
|
||||
bmain, owner_library, id_root, false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static void lib_override_library_create_post_process(Main *bmain,
|
||||
@@ -1047,6 +1073,189 @@ bool BKE_lib_override_library_template_create(struct ID *id)
|
||||
return true;
|
||||
}
|
||||
|
||||
static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level)
|
||||
{
|
||||
if (curr_level > 1000) {
|
||||
CLOG_ERROR(&LOG,
|
||||
"Levels of dependency relationships between library overrides IDs is way too high, "
|
||||
"skipping further processing loops (involves at least '%s')",
|
||||
id->name);
|
||||
BLI_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ID_IS_OVERRIDE_LIBRARY(id)) {
|
||||
BLI_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
|
||||
BLI_assert(entry != NULL);
|
||||
|
||||
int best_level_candidate = curr_level;
|
||||
ID *best_root_id_candidate = id;
|
||||
|
||||
for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
|
||||
from_id_entry = from_id_entry->next) {
|
||||
if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
|
||||
/* Never consider non-overridable relationships as actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
|
||||
ID *from_id = from_id_entry->id_pointer.from;
|
||||
if (ELEM(from_id, NULL, id)) {
|
||||
continue;
|
||||
}
|
||||
if (!ID_IS_OVERRIDE_LIBRARY(from_id) || (from_id->lib != id->lib)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int level_candidate = curr_level + 1;
|
||||
/* Recursively process the parent. */
|
||||
ID *root_id_candidate = lib_override_root_find(
|
||||
bmain, from_id, curr_level + 1, &level_candidate);
|
||||
if (level_candidate > best_level_candidate && root_id_candidate != NULL) {
|
||||
best_root_id_candidate = root_id_candidate;
|
||||
best_level_candidate = level_candidate;
|
||||
}
|
||||
}
|
||||
|
||||
*r_best_level = best_level_candidate;
|
||||
return best_root_id_candidate;
|
||||
}
|
||||
|
||||
static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from)
|
||||
{
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
if (id->override_library->hierarchy_root == id_root) {
|
||||
/* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set
|
||||
* then. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Hierarchy root already set, and not matching currently propsed one, try to find which is
|
||||
* best. */
|
||||
if (id->override_library->hierarchy_root != NULL) {
|
||||
/* Check if given `id_from` matches with the hierarchy of the linked reference ID, in which
|
||||
* case we assume that the given hierarchy root is the 'real' one.
|
||||
*
|
||||
* NOTE: This can fail if user mixed dependencies between several overrides of a same
|
||||
* reference linked hierarchy. Not much to be done in that case, it's virtually impossible to
|
||||
* fix this automatically in a reliable way. */
|
||||
if (id_from == NULL || !ID_IS_OVERRIDE_LIBRARY_REAL(id_from)) {
|
||||
/* Too complicated to deal with for now. */
|
||||
CLOG_WARN(&LOG,
|
||||
"Inconsistency in library override hierarchy of ID '%s'.\n"
|
||||
"\tNot enough data to verify validity of current proposed root '%s', assuming "
|
||||
"already set one '%s' is valid.",
|
||||
id->name,
|
||||
id_root->name,
|
||||
id->override_library->hierarchy_root->name);
|
||||
return;
|
||||
}
|
||||
|
||||
ID *id_from_ref = id_from->override_library->reference;
|
||||
MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers,
|
||||
id->override_library->reference);
|
||||
BLI_assert(entry != NULL);
|
||||
|
||||
bool do_replace_root = false;
|
||||
for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
|
||||
from_id_entry = from_id_entry->next) {
|
||||
if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
|
||||
/* Never consider non-overridable relationships as actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id_from_ref == from_id_entry->id_pointer.from) {
|
||||
/* A matching parent was found in reference linked data, assume given hierarchy root is
|
||||
* the valid one. */
|
||||
do_replace_root = true;
|
||||
CLOG_WARN(
|
||||
&LOG,
|
||||
"Inconsistency in library override hierarchy of ID '%s'.\n"
|
||||
"\tCurrent proposed root '%s' detected as valid, will replace already set one '%s'.",
|
||||
id->name,
|
||||
id_root->name,
|
||||
id->override_library->hierarchy_root->name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!do_replace_root) {
|
||||
CLOG_WARN(
|
||||
&LOG,
|
||||
"Inconsistency in library override hierarchy of ID '%s'.\n"
|
||||
"\tCurrent proposed root '%s' not detected as valid, keeping already set one '%s'.",
|
||||
id->name,
|
||||
id_root->name,
|
||||
id->override_library->hierarchy_root->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
id->override_library->hierarchy_root = id_root;
|
||||
}
|
||||
|
||||
MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
|
||||
BLI_assert(entry != NULL);
|
||||
|
||||
for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
|
||||
to_id_entry = to_id_entry->next) {
|
||||
if ((to_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
|
||||
/* Never consider non-overridable relationships as actual dependencies. */
|
||||
continue;
|
||||
}
|
||||
|
||||
ID *to_id = *to_id_entry->id_pointer.to;
|
||||
if (ELEM(to_id, NULL, id)) {
|
||||
continue;
|
||||
}
|
||||
if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id->lib)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Recursively process the sub-hierarchy. */
|
||||
lib_override_root_hierarchy_set(bmain, id_root, to_id, id);
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
|
||||
{
|
||||
ID *id;
|
||||
|
||||
BKE_main_relations_create(bmain, 0);
|
||||
|
||||
FOREACH_MAIN_ID_BEGIN (bmain, id) {
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
continue;
|
||||
}
|
||||
if (id->override_library->hierarchy_root != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int best_level = 0;
|
||||
ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
|
||||
|
||||
if (!ELEM(id_root->override_library->hierarchy_root, id_root, NULL)) {
|
||||
CLOG_WARN(&LOG,
|
||||
"Potential inconsistency in library override hierarchy of ID '%s', detected as "
|
||||
"part of the hierarchy of '%s', which has a different root '%s'",
|
||||
id->name,
|
||||
id_root->name,
|
||||
id_root->override_library->hierarchy_root->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
lib_override_root_hierarchy_set(bmain, id_root, id_root, NULL);
|
||||
|
||||
BLI_assert(id->override_library->hierarchy_root != NULL);
|
||||
}
|
||||
FOREACH_MAIN_ID_END;
|
||||
|
||||
BKE_main_relations_free(bmain);
|
||||
}
|
||||
|
||||
static void lib_override_library_remap(Main *bmain,
|
||||
const ID *id_root_reference,
|
||||
GHash *linkedref_to_old_override)
|
||||
@@ -1112,6 +1321,7 @@ static bool lib_override_library_resync(Main *bmain,
|
||||
LibOverrideGroupTagData data = {.bmain = bmain,
|
||||
.scene = scene,
|
||||
.id_root = id_root,
|
||||
.hierarchy_root_id = id_root->override_library->hierarchy_root,
|
||||
.tag = LIB_TAG_DOIT,
|
||||
.missing_tag = LIB_TAG_MISSING,
|
||||
.is_override = true,
|
||||
@@ -1214,7 +1424,7 @@ static bool lib_override_library_resync(Main *bmain,
|
||||
* override IDs (including within the old overrides themselves, since those are tagged too
|
||||
* above). */
|
||||
const bool success = BKE_lib_override_library_create_from_tag(
|
||||
bmain, NULL, id_root_reference->lib, true);
|
||||
bmain, NULL, id_root_reference, true);
|
||||
|
||||
if (!success) {
|
||||
return success;
|
||||
@@ -1533,46 +1743,20 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain,
|
||||
*
|
||||
* NOTE: Related to `lib_override_resync_tagging_finalize` above.
|
||||
*/
|
||||
static ID *lib_override_library_main_resync_find_root_recurse(ID *id, int *level)
|
||||
static ID *lib_override_library_main_resync_root_get(Main *bmain, ID *id)
|
||||
{
|
||||
(*level)++;
|
||||
ID *return_id = id;
|
||||
|
||||
switch (GS(id->name)) {
|
||||
case ID_GR: {
|
||||
/* Find the highest valid collection in the parenting hierarchy.
|
||||
* Note that in practice, in any decent common case there is only one well defined root
|
||||
* collection anyway. */
|
||||
int max_level = *level;
|
||||
Collection *collection = (Collection *)id;
|
||||
LISTBASE_FOREACH (CollectionParent *, collection_parent_iter, &collection->parents) {
|
||||
Collection *collection_parent = collection_parent_iter->collection;
|
||||
if (ID_IS_OVERRIDE_LIBRARY_REAL(collection_parent) &&
|
||||
collection_parent->id.lib == id->lib) {
|
||||
int tmp_level = *level;
|
||||
ID *tmp_id = lib_override_library_main_resync_find_root_recurse(&collection_parent->id,
|
||||
&tmp_level);
|
||||
if (tmp_level > max_level) {
|
||||
max_level = tmp_level;
|
||||
return_id = tmp_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
|
||||
const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
|
||||
if (id_type->owner_get != NULL) {
|
||||
id = id_type->owner_get(bmain, id);
|
||||
}
|
||||
case ID_OB: {
|
||||
Object *object = (Object *)id;
|
||||
if (object->parent != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(object->parent) &&
|
||||
object->parent->id.lib == id->lib) {
|
||||
return_id = lib_override_library_main_resync_find_root_recurse(&object->parent->id, level);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
|
||||
}
|
||||
|
||||
return return_id;
|
||||
ID *hierarchy_root_id = id->override_library->hierarchy_root;
|
||||
BLI_assert(hierarchy_root_id != NULL);
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(hierarchy_root_id));
|
||||
return hierarchy_root_id;
|
||||
}
|
||||
|
||||
/* Ensure resync of all overrides at one level of indirect usage.
|
||||
@@ -1714,14 +1898,13 @@ static void lib_override_library_main_resync_on_library_indirect_level(
|
||||
|
||||
Library *library = id->lib;
|
||||
|
||||
int level = 0;
|
||||
/* In complex non-supported cases, with several different override hierarchies sharing
|
||||
* relations between each-other, we may end up not actually updating/replacing the given
|
||||
* root id (see e.g. pro/shots/110_rextoria/110_0150_A/110_0150_A.anim.blend of sprites
|
||||
* project repository, r2687).
|
||||
* This can lead to infinite loop here, at least avoid this. */
|
||||
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
|
||||
id = lib_override_library_main_resync_find_root_recurse(id, &level);
|
||||
id = lib_override_library_main_resync_root_get(bmain, id);
|
||||
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
|
||||
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
|
||||
BLI_assert(id->lib == library);
|
||||
@@ -1879,6 +2062,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
|
||||
LibOverrideGroupTagData data = {.bmain = bmain,
|
||||
.scene = NULL,
|
||||
.id_root = id_root,
|
||||
.hierarchy_root_id = id_root->override_library->hierarchy_root,
|
||||
.tag = LIB_TAG_DOIT,
|
||||
.missing_tag = LIB_TAG_MISSING,
|
||||
.is_override = true,
|
||||
|
@@ -323,6 +323,8 @@ static bool library_foreach_ID_link(Main *bmain,
|
||||
IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
|
||||
CALLBACK_INVOKE_ID(id->override_library->storage,
|
||||
IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
|
||||
|
||||
CALLBACK_INVOKE_ID(id->override_library->hierarchy_root, IDWALK_CB_LOOPBACK);
|
||||
}
|
||||
|
||||
IDP_foreach_property(id->properties,
|
||||
@@ -471,7 +473,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
|
||||
return ELEM(id_type_used, ID_MA);
|
||||
case ID_WS:
|
||||
return ELEM(id_type_used, ID_SCR, ID_SCE);
|
||||
case ID_HA:
|
||||
case ID_CV:
|
||||
return ELEM(id_type_used, ID_MA);
|
||||
case ID_PT:
|
||||
return ELEM(id_type_used, ID_MA);
|
||||
|
@@ -558,7 +558,7 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_
|
||||
case ID_ME:
|
||||
case ID_CU:
|
||||
case ID_MB:
|
||||
case ID_HA:
|
||||
case ID_CV:
|
||||
case ID_PT:
|
||||
case ID_VO:
|
||||
if (new_id) { /* Only affects us in case obdata was relinked (changed). */
|
||||
|
@@ -643,8 +643,8 @@ ListBase *which_libbase(Main *bmain, short type)
|
||||
return &(bmain->cachefiles);
|
||||
case ID_WS:
|
||||
return &(bmain->workspaces);
|
||||
case ID_HA:
|
||||
return &(bmain->hairs);
|
||||
case ID_CV:
|
||||
return &(bmain->hair_curves);
|
||||
case ID_PT:
|
||||
return &(bmain->pointclouds);
|
||||
case ID_VO:
|
||||
@@ -688,7 +688,7 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
|
||||
lb[INDEX_ID_ME] = &(bmain->meshes);
|
||||
lb[INDEX_ID_CU] = &(bmain->curves);
|
||||
lb[INDEX_ID_MB] = &(bmain->metaballs);
|
||||
lb[INDEX_ID_HA] = &(bmain->hairs);
|
||||
lb[INDEX_ID_CV] = &(bmain->hair_curves);
|
||||
lb[INDEX_ID_PT] = &(bmain->pointclouds);
|
||||
lb[INDEX_ID_VO] = &(bmain->volumes);
|
||||
|
||||
|
@@ -36,10 +36,10 @@
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_collection_types.h"
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_curves_types.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
#include "DNA_defaults.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_hair_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
@@ -341,9 +341,9 @@ Material ***BKE_object_material_array_p(Object *ob)
|
||||
bGPdata *gpd = ob->data;
|
||||
return &(gpd->mat);
|
||||
}
|
||||
if (ob->type == OB_HAIR) {
|
||||
Hair *hair = ob->data;
|
||||
return &(hair->mat);
|
||||
if (ob->type == OB_CURVES) {
|
||||
Curves *curves = ob->data;
|
||||
return &(curves->mat);
|
||||
}
|
||||
if (ob->type == OB_POINTCLOUD) {
|
||||
PointCloud *pointcloud = ob->data;
|
||||
@@ -374,9 +374,9 @@ short *BKE_object_material_len_p(Object *ob)
|
||||
bGPdata *gpd = ob->data;
|
||||
return &(gpd->totcol);
|
||||
}
|
||||
if (ob->type == OB_HAIR) {
|
||||
Hair *hair = ob->data;
|
||||
return &(hair->totcol);
|
||||
if (ob->type == OB_CURVES) {
|
||||
Curves *curves = ob->data;
|
||||
return &(curves->totcol);
|
||||
}
|
||||
if (ob->type == OB_POINTCLOUD) {
|
||||
PointCloud *pointcloud = ob->data;
|
||||
@@ -403,8 +403,8 @@ Material ***BKE_id_material_array_p(ID *id)
|
||||
return &(((MetaBall *)id)->mat);
|
||||
case ID_GD:
|
||||
return &(((bGPdata *)id)->mat);
|
||||
case ID_HA:
|
||||
return &(((Hair *)id)->mat);
|
||||
case ID_CV:
|
||||
return &(((Curves *)id)->mat);
|
||||
case ID_PT:
|
||||
return &(((PointCloud *)id)->mat);
|
||||
case ID_VO:
|
||||
@@ -429,8 +429,8 @@ short *BKE_id_material_len_p(ID *id)
|
||||
return &(((MetaBall *)id)->totcol);
|
||||
case ID_GD:
|
||||
return &(((bGPdata *)id)->totcol);
|
||||
case ID_HA:
|
||||
return &(((Hair *)id)->totcol);
|
||||
case ID_CV:
|
||||
return &(((Curves *)id)->totcol);
|
||||
case ID_PT:
|
||||
return &(((PointCloud *)id)->totcol);
|
||||
case ID_VO:
|
||||
@@ -454,7 +454,7 @@ static void material_data_index_remove_id(ID *id, short index)
|
||||
BKE_curve_material_index_remove((Curve *)id, index);
|
||||
break;
|
||||
case ID_MB:
|
||||
case ID_HA:
|
||||
case ID_CV:
|
||||
case ID_PT:
|
||||
case ID_VO:
|
||||
/* No material indices for these object data types. */
|
||||
@@ -509,7 +509,7 @@ static void material_data_index_clear_id(ID *id)
|
||||
BKE_curve_material_index_clear((Curve *)id);
|
||||
break;
|
||||
case ID_MB:
|
||||
case ID_HA:
|
||||
case ID_CV:
|
||||
case ID_PT:
|
||||
case ID_VO:
|
||||
/* No material indices for these object data types. */
|
||||
|
@@ -15,6 +15,11 @@
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*
|
||||
* MetaBalls are created from a single Object (with a name without number in it),
|
||||
* here the DispList and BoundBox also is located.
|
||||
* All objects with the same name (but with a number in it) are added to this.
|
||||
@@ -22,10 +27,6 @@
|
||||
* texture coordinates are patched within the displist
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
@@ -43,6 +43,7 @@
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_stack.h"
|
||||
#include "BLI_task.h"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
@@ -373,22 +374,28 @@ const float (*BKE_mesh_vertex_normals_ensure(const Mesh *mesh))[3]
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->vdata, CD_NORMAL);
|
||||
}
|
||||
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
float(*vert_normals)[3];
|
||||
float(*poly_normals)[3];
|
||||
|
||||
float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
|
||||
float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
|
||||
mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals,
|
||||
vert_normals);
|
||||
vert_normals = BKE_mesh_vertex_normals_for_write(&mesh_mutable);
|
||||
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
mesh_calc_normals_poly_and_vertex(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals,
|
||||
vert_normals);
|
||||
|
||||
BKE_mesh_vertex_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return vert_normals;
|
||||
@@ -413,19 +420,24 @@ const float (*BKE_mesh_poly_normals_ensure(const Mesh *mesh))[3]
|
||||
return (const float(*)[3])CustomData_get_layer(&mesh->pdata, CD_NORMAL);
|
||||
}
|
||||
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
float(*poly_normals)[3];
|
||||
|
||||
float(*poly_normals)[3] = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
/* Isolate task because a mutex is locked and computing normals is multi-threaded. */
|
||||
blender::threading::isolate_task([&]() {
|
||||
Mesh &mesh_mutable = *const_cast<Mesh *>(mesh);
|
||||
|
||||
BKE_mesh_calc_normals_poly(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals);
|
||||
poly_normals = BKE_mesh_poly_normals_for_write(&mesh_mutable);
|
||||
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
BKE_mesh_calc_normals_poly(mesh_mutable.mvert,
|
||||
mesh_mutable.totvert,
|
||||
mesh_mutable.mloop,
|
||||
mesh_mutable.totloop,
|
||||
mesh_mutable.mpoly,
|
||||
mesh_mutable.totpoly,
|
||||
poly_normals);
|
||||
|
||||
BKE_mesh_poly_normals_clear_dirty(&mesh_mutable);
|
||||
});
|
||||
|
||||
BLI_mutex_unlock(normals_mutex);
|
||||
return poly_normals;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user