Compare commits

...

48 Commits

Author SHA1 Message Date
3e85bb34d0 Version: Blender 2.90.1 release 2020-09-23 08:43:51 +02:00
6f28e6998b Fix T80899: Crash on editing multiple UVs of multiple different objects at the same time
The issue was two fold.

First something sets the loop element tag and doesn't clear it before
the UV code in question tries to use the tags. Added a sanity clear to
make sure that it operates on a clean tag state.

The next one was that the UV maps in question had quite a few points
that had zero length UV loop edges. This would lead to division by
zero.

Reviewed By: Jeroen Bakker, Brecht

Differential Revision: http://developer.blender.org/D8967
2020-09-21 16:13:18 +02:00
9743a58f7d Fix T80771: Avoid changing the visibility of loose geometry when entering Sculpt Mode
When entering scultp mode the visibility from the Face Sets is copied to
the base mesh. This steps was considering that if a vertex belongs to a
face with a visibible Face Set ID, it should be visible. As loose
geometry may not have any faces, those vertex were set to hidden.

Now this function check if a vertex visibility should be modified by the
face sets (by checking the loops), avoiding modifying the visibility of
loose geometry unintentionally.

Reviewed By: sergey

Maniphest Tasks: T80771

Differential Revision: https://developer.blender.org/D8899
2020-09-21 11:17:42 +02:00
60fbed3dba Fix T80520: Tris to Quads ignores UV delimit option 2020-09-21 09:49:15 +02:00
9ec325b59d Fix T61985: NLA Bake exception baking pose with non-pose selection 2020-09-21 09:48:26 +02:00
Cody Winchester
be8935852b Fix invert vertex group weight miscalculation for modifiers
Warp & weight vertex-group editing modifiers miscalculated vertex weight
inversion, the weights were multiplied before being subtracted from 1.

Ref D8241
2020-09-21 09:47:24 +02:00
c65e4f4e39 Fix T78793, T79707: Cycles crash on macOS with older CPUs
Embree static libraries need additional linking flags to avoid SSE and
AVX symbols getting mixed up.
2020-09-21 09:46:23 +02:00
Stefan Werner
918ef5f835 Cycles: Separate Embree device for each CPU Device.
Before, Cycles was using a shared Embree device across all instances.
This could result in crashes when viewport rendering and material
preview were using Cycles simultaneously.

Fixes issue T80042

Maniphest Tasks: T80042

Differential Revision: https://developer.blender.org/D8772
2020-09-21 09:45:52 +02:00
41e4079365 Fix T80437: Auto IK Double Generates IK constraints
Caused by rB9a7f5f1bb422.

If using Auto IK (or targetless IK and Auto IK together), two temporary
constraints were added.
- from pose_grab_with_ik_add (even for targetless IK)
- from add_pose_transdata (even for Auto IK)

Since both both do similar things, but cannot work in tandem (with
possibly different chainlengths for example), we have to decide which
type to prefer over the other (as in: do not create a constraint for the
other).
It seems better to ignore the 'Auto IK' option on bones that will
have targetless IK set up for them specificallly [e.g. defining special
chainlength]. This way you can still work with 'Auto IK' ON generally
[with interactive chainlength control], but also have specific bones that
need their own custom chainlength.

For now, the most straightforward fix is to
- only add constraints for Auto IK from pose_grab_with_ik_add()
- only add constraints for targetless IK from add_pose_transdata()

Note: this area has some potential for later refactoring:
- move creation of all temporary constraints to a single place
[preferably pose_grab_with_ik_add]
- use only those temporary constraints in transform code [atm. we still
flip CONSTRAINT_IK_AUTO around on the "original" -- unneccesarily, after
rB9a7f5f1bb422 a dedicated temporary constraint is now always available]
- clarify CONSTRAINT_IK_AUTO vs. CONSTRAINT_IK_TEMP
- obeying standard rotation locks on bones in the chain (not just the
the IK locks) is not consistent between targetless IK and Auto IK

Potential candidate for 2.90.1 as well as 2.83 LTS

Maniphest Tasks: T80437

Differential Revision: https://developer.blender.org/D8930
2020-09-21 09:42:27 +02:00
a5b6d6de0a Fix T80885: Texture paint camera project crashes after undo/redo
Unmatched ED_image_undo_push_{begin/end},
add doc-strings noting why this is needed.

Thanks to @Baardaap for the initial fix.
2020-09-21 09:42:20 +02:00
8ab98d0ed7 Add versioning for 2.90 files that may have invalid mesh
rBf2d26409e83b fixed a serious problem with invalid mesh after an
operation with the extrude manifold.

Since BKE_mesh_validate_arrays is a slow operation, the chosen
interval between versions is relatively small and also only the
mentioned invalid mesh problem is tested.

Differential Revision: https://developer.blender.org/D8898
2020-09-21 09:40:01 +02:00
0f72e7c3eb Fix OpenCL render error in large scenes
In scenes such as Cosmos Laundromat, there were memory allocations bigger than
2GB which would overflow.

Problem and solution found by AMD, thanks!
2020-09-21 09:36:25 +02:00
7347228d56 Fix T80630: potential crash in volume grids in Eevee shaders
Found by address sanitizer.
2020-09-21 09:35:32 +02:00
adcb3c6ee1 Fix T80728: UV edge select splits UV's for lasso/box/circle select
Oversight in 411c5238a2 ignored sticky selection.

Use 'uvedit_edge_select_set_with_sticky' to make sure
sticky options are respected.

Also skip checking the existing selection since that only checks the
current UV, not all connected UV's which is needed for sticky selection.

The extra checks to avoid updating UV's isn't such an advantage as
only meshed in the selected region are tagged for updating.
2020-09-21 09:33:53 +02:00
1442827a4f Fix T78392: [2.83.5, 2.90, 2.91] Crash on undo/ redo after changing modes.
During undo/redo read code is expected to clear the `OB_MODE_EDIT`
bitflag of `Object.mode`, for some reasons.

This was not done anymore for re-used Objects, we need to add a special
handling case for that too.

Should be backported to 2.90 and 2.83 (will probably not be straight
forward for the latter).
2020-09-21 09:32:39 +02:00
f822cd511c Fix T80457: Library Override - Custom Property to Drive Child Particles results in Crash.
RNA diffing code was not dealing properly valid NULL PointerRNA (like
the empty texture slots of a ParticleSettings e.g., which were cause of
crash in that report).

To be backported to 2.90 and 2.83.
2020-09-21 09:30:53 +02:00
27ea086242 Fix T80694: Crash reloading scripts from the Python console
Running `bpy.ops.script.reload()` from Python was crashing
since the operator being called was it's self freed.

Change the reload operator to defer execution - as supporting
re-registration during execution is quite involved for a corner-case.
2020-09-21 09:30:36 +02:00
2c8f8765a1 Fix T80589: Translations in python scripts are missing.
Python 3.8 changed handling of constant values in its AST tool.
This code should work on both officialy supported 3.7, and newer 3.8,
for now.
2020-09-21 09:25:02 +02:00
9d290c9fc6 Fix T62504: Crash accessing depsgraph from evaluated view layer
Use correct owner_id types for depsgraph view_layer properties
instead of inheriting from the Depsgraph which is set to NULL.
2020-09-21 09:23:53 +02:00
39af4d8bfe Fix T77584: Edit Mode crash with shape keys created on blank mesh
Entering edit-mode after creating shape keys on a blank mesh would crash.

Regression in 9b9f84b317 which prevented initializing empty
shape keys when there is no shape key offset data available.
2020-09-21 09:22:59 +02:00
4f6e51aa52 Fix T80623: Correct Face Attributes affecting modes not listed
Some transform modes (such as Mirror) are not listed to have UV corrected
during the transformation.

It messed up the UV of all of these.
2020-09-21 09:22:07 +02:00
bff56477c9 Fix T78225: Vertex Colors not showing in edit mode
This should be using the mesh_cd_ldata_get_from_mesh function in
order to get ldata from BMesh in edit mode.

Reviewed By: sergey

Maniphest Tasks: T78225

Differential Revision: https://developer.blender.org/D8818
2020-09-21 09:20:50 +02:00
3ff6541c5d Fix T80372: Mantaflow Noise Not working with Smoke/Smoke and Fire
Modular caches for noise, particles and meshes require that additional data is baked (i.e. is resumable option). With this commit users will be explicitly asked to enable this option before being able to bake noise, particles or meshes.
2020-09-21 09:19:36 +02:00
5d10814ccc Fix T79626: 2.91 Mantaflow crash when adaptive domain + noise are enabled
Crash was caused by an incorect domain size of the noise solver and an index out of bounds.
2020-09-21 09:18:18 +02:00
21e3b89634 Fix T80516: Hook modifier crashes without vertex group data
Checks for existence of a vertex group must check the array isn't NULL.

Regression in c1386795a9.
2020-09-21 09:17:36 +02:00
5f66510a21 Fix T71012: Cycles baking crash with locked-UI & background-mode 2020-09-21 09:16:21 +02:00
7447233f76 Fix T80464: Crash deleting bone constraints when the armature layer is
not active

Caused by {rB608d9b5aa1f1}

Prior to rB608d9b5aa1f1, the constraint was gotten using **context**
[CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint) -- which is
valid for bones on hidden layers].
After rB608d9b5aa1f1, the constraint is found (or isnt) using
`edit_constraint_property_get` [this is **not** valid for bones on
hidden layers because internally `BKE_pose_channel_active` checks if the
bone is on an active layer].

Some observations:
- Every operator using `edit_constraint_property_get` doesnt work for
bones on inactive layers [delete, moveup, movedown, move to index (drag
n drop nowadays)]
-- moveup, movedown, move to index check if they could find a constraint
beforehand though (dont crash)
-- delete crashes (doesnt check if a constraint could actually be found)
- Every operator using `edit_constraint_property_get` for constraint
data doesnt work for bones on inactive layers [stretchto_reset,
limitdistance_reset, childof_set_inverse, ...]
-- these all check if they could find a constraint beforehand though
(dont crash)

This is because the poll function is using **context** to get the
constraint, the operators themselves use
**edit_constraint_property_get** which leads to inconsistent/unexpected
results.

Possible solutions were:
- [1] let the delete operator just work with the context constraint
again (like prior to rB608d9b5aa1f1) -- allows for deleting constraints
on bones in inactive layers
- [2] check if we could get a constraint -- prevents the crash, but does
**not** allow for deleting constraints on bones in inactive layers
- [3] make the poll `edit_constraint_poll_generic` be as strict as the
operators -- dont use **context** to get the constraint, but something
like **edit_constraint_property_get**
- [4] make the operators be more graceful and let them act on bones on
hidden layers -- let **edit_constraint_property_get** actually use the
same **context**

This patch implements [4], so poll an doperators are now in sync.
- prevents reported crash
- also enables operators for bone constraints on hidden layers
- also enables drag and drop reordering of constraints on hidden layers

This might be a candidate for 2.90.1? (if it is, take care to include
prior "Refactor getting constraints" refactoring commit)

Note: Adding constraints also doesnt work for bones on inactive layers
[that was the case in 2.79 as well -- it is also using
`BKE_pose_channel_active`]

Maniphest Tasks: T80464

Differential Revision: https://developer.blender.org/D8805
2020-09-21 09:15:13 +02:00
9f473e2275 Fix for failing constraints test
Caused by own rB6dc7266cf1f4.

When overriding context for constraint operators (such as in constraint
tests), it could happen that context "active_pose_bone" is set, but
"pose_bone" isnt. Now check for both in ED_object_pose_constraint_list.
2020-09-21 09:14:02 +02:00
8b953fa83d Refactor getting constraints
This is the refactoring part of D8805 (should be no functional changes).

- exposes pose-related part of former 'get_constraints()' from
interface_templates.c to new ED_object_pose_constraint_list
- rename ED_object_constraint_list_from_context -->
ED_object_constraint_active_list

Also clarify comments on both of these.

ref T80464
ref https://developer.blender.org/D8805
2020-09-21 09:13:11 +02:00
d52d56e83d Fix T80604: BLI_polyfill_calc exceeds stack size allocating points
On systems with 512kb stack this happened at around 13k points.

This happened at times with grease-pencil, although callers that
frequently use complex polygons should be using BLI_polyfill_calc_arena.
2020-09-21 08:56:51 +02:00
6de33ee656 Fix T80238: Crash adding properties to material node-trees
The localized node-tree was freeing the materials ID properties twice.

This matches how animation data behaves, setting to NULL after freeing.
2020-09-21 08:53:51 +02:00
961bcf9e50 Fix T80561: Crash when multi-mesh editing UVs with proportional editing
Because of a `goto` we would free a variable before it was declared.
Declare it before the `goto` and `NULL`-check the value before freeing.
2020-09-21 08:52:46 +02:00
0ed4fa6541 PY API doc: fix doc for new override option of properties.
Reported by Demeter Dzadik (@Mets) on blender.chat, thanks.

Candidate to be backported to a potential 2.90.1.
2020-09-21 08:52:46 +02:00
ea2d025a98 Fix T79718: Eevee OpenVDB render error when frames miss part of the grids
Improved fix that handles the distinct cases of missing grids and zero
size grids.
2020-09-21 08:49:25 +02:00
90312da85a Fix T80332: principle volume shader not working for world in Eevee
The handling of missing volume grids for the principled volume shader was
incomplete, different inputs need different default values.
2020-09-21 08:48:37 +02:00
56076e0492 Fix T80224: Crash after duplicating and hiding vertices while using X Axis Mirror
The mirror map can reference a hidden vertex that is currently ignored
in the transformation.

Thus the mirror element array is not filled.
2020-09-21 08:40:02 +02:00
293acae922 Fix T80426: Crash when deleting custom orientation
Indices referencing other orientations were not being updated,
2020-09-21 08:38:54 +02:00
Germano Cavalcante
211b390871 Fix T79973: Re-ordering face maps messes up the names of other face maps
Use a remap function instead a swap.

Reviewed By: campbellbarton

Differential Revision: https://developer.blender.org/D8739
2020-09-21 08:36:51 +02:00
0e9a3882be Fix T80233: Extrude manifold can generate invalid geometry
Faces with only 2 sides were sometimes generated.
2020-09-21 08:35:52 +02:00
0da0b5984a Fix T80289: GPencil Opacity modifier not working
This error was introduced in the refactor of the modifier panels.
2020-09-21 08:35:27 +02:00
cb1875c6f5 Decimate Modifier: Restore vertex group factor property in UI
This property was inadvertently removed from the modifier's panel and
it wasn't caught in time for the release of 2.90. Thanks to the user
"VermossomreV" for bringing this to my attention.

Differential Revision: https://developer.blender.org/D8790
2020-09-21 08:32:04 +02:00
0f21e3b688 Version: Blender 2.90.1 Beta 2020-09-21 08:28:53 +02:00
Yevgeny Makarov
0330d1af29 Fix T77900: File Browser in macOS fullscreen crashes
When Blender is started in fullscreen mode from the command line,
or if the fullscreen state is saved in the startup file, all temporary windows
will also open in fullscreen mode. When closing the fullscreen File Browser,
Blender would either crash or parent window becomes black.

This does not happen if the Blender switches to full screen manually.

`NSWindowCollectionBehaviorFullScreenPrimary` should be set for windows that
can enter full-screen mode. Otherwise macOS will turn the wrong window into
full-screen.

Similar fix: rB4b39de677d20

Differential Revision: https://developer.blender.org/D8708

Reviewed by: Julian Eisel
2020-08-31 13:26:23 +02:00
cb0b0416f4 Fix T80258: UILayout.prop_search() issues with datablock names
If the search menu was used for a string property, and a data-block was
selected from the search, the value set would be an invalid name. The
property would get the modified UI string, not the proper data name set.

This problem was already once solved in rB249ccab111ac, but resurfaced
in rB937d89afba36.

Now only use the modified UI string if requires_exact_data_name is not
true.

Note: the comments in rB249ccab111ac [reg. library hints and string
properties, also that pointer properties are preferred over string
properties when dealing with IDs] still apply.

Reviewers: severin, campbellbarton

Subscribers:
2020-08-31 13:15:48 +02:00
defe21a7bb Doversion: move (fix) 2.80 checks to 2.90
Some doversion checks were done in the wrong file, meaning they could potentially
be running in the wrong order if they require another fix to run prior to them.

This is technically is a cleanup. And technically a fixup for
9e0a4fcaad.
2020-08-31 12:42:59 +02:00
834613a50e Splash: new image for 2.90 by Daniel Bystedt 2020-08-31 11:28:37 +02:00
9e0a4fcaad Blender 2.90 subversion bump
Preparing for release.
2020-08-31 11:28:37 +02:00
1558c006fb Linux: 2.90 release information in appdata 2020-08-31 11:17:16 +02:00
67 changed files with 709 additions and 493 deletions

View File

@@ -40,9 +40,9 @@ FIND_PATH(EMBREE_INCLUDE_DIR
SET(_embree_FIND_COMPONENTS
embree3
embree_sse42
embree_avx
embree_avx2
embree_sse42
lexers
math
simd

View File

@@ -392,6 +392,16 @@ endif()
if(WITH_CYCLES_EMBREE)
find_package(Embree 3.8.0 REQUIRED)
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -Xlinker -stack_size -Xlinker 0x100000")
# Embree static library linking can mix up SSE and AVX symbols, causing
# crashes on macOS systems with older CPUs that don't have AVX. Using
# force load avoids that. The Embree shared library does not suffer from
# this problem, precisely because linking a shared library uses force load.
set(_embree_libraries_force_load)
foreach(_embree_library ${EMBREE_LIBRARIES})
list(APPEND _embree_libraries_force_load "-Wl,-force_load,${_embree_library}")
endforeach()
set(EMBREE_LIBRARIES ${_embree_libraries_force_load})
endif()
if(WITH_OPENIMAGEDENOISE)

View File

@@ -717,7 +717,11 @@ void BlenderSync::free_data_after_sync(BL::Depsgraph &b_depsgraph)
* footprint during synchronization process.
*/
const bool is_interface_locked = b_engine.render() && b_engine.render().use_lock_interface();
const bool can_free_caches = BlenderSession::headless || is_interface_locked;
const bool can_free_caches = (BlenderSession::headless || is_interface_locked) &&
/* Baking re-uses the depsgraph multiple times, clearing crashes
* reading un-evaluated mesh data which isn't aligned with the
* geometry we're baking, see T71012. */
!scene->bake_manager->get_baking();
if (!can_free_caches) {
return;
}

View File

@@ -98,14 +98,15 @@ BVH::BVH(const BVHParams &params_,
BVH *BVH::create(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects)
const vector<Object *> &objects,
const Device *device)
{
switch (params.bvh_layout) {
case BVH_LAYOUT_BVH2:
return new BVH2(params, geometry, objects);
case BVH_LAYOUT_EMBREE:
#ifdef WITH_EMBREE
return new BVHEmbree(params, geometry, objects);
return new BVHEmbree(params, geometry, objects, device);
#else
break;
#endif

View File

@@ -89,7 +89,8 @@ class BVH {
static BVH *create(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects);
const vector<Object *> &objects,
const Device *device);
virtual ~BVH()
{
}

View File

@@ -36,6 +36,8 @@
# include "bvh/bvh_embree.h"
# include "device/device.h"
/* Kernel includes are necessary so that the filter function for Embree can access the packed BVH.
*/
# include "kernel/bvh/bvh_embree.h"
@@ -298,12 +300,6 @@ static bool rtc_progress_func(void *user_ptr, const double n)
return !progress->get_cancel();
}
/* This is to have a shared device between all BVH instances.
It would be useful to actually to use a separte RTCDevice per Cycles instance. */
RTCDevice BVHEmbree::rtc_shared_device = NULL;
int BVHEmbree::rtc_shared_users = 0;
thread_mutex BVHEmbree::rtc_shared_mutex;
static size_t count_primitives(Geometry *geom)
{
if (geom->type == Geometry::MESH) {
@@ -320,11 +316,13 @@ static size_t count_primitives(Geometry *geom)
BVHEmbree::BVHEmbree(const BVHParams &params_,
const vector<Geometry *> &geometry_,
const vector<Object *> &objects_)
const vector<Object *> &objects_,
const Device *device)
: BVH(params_, geometry_, objects_),
scene(NULL),
mem_used(0),
top_level(NULL),
rtc_device((RTCDevice)device->bvh_device()),
stats(NULL),
curve_subdivisions(params.curve_subdivisions),
build_quality(RTC_BUILD_QUALITY_REFIT),
@@ -332,47 +330,8 @@ BVHEmbree::BVHEmbree(const BVHParams &params_,
{
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
_MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
thread_scoped_lock lock(rtc_shared_mutex);
if (rtc_shared_users == 0) {
rtc_shared_device = rtcNewDevice("verbose=0");
/* Check here if Embree was built with the correct flags. */
ssize_t ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED);
if (ret != 1) {
assert(0);
VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED flag."
"Ray visibility will not work.";
}
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED);
if (ret != 1) {
assert(0);
VLOG(1)
<< "Embree is compiled without the RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED flag."
"Renders may not look as expected.";
}
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED);
if (ret != 1) {
assert(0);
VLOG(1)
<< "Embree is compiled without the RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED flag. "
"Line primitives will not be rendered.";
}
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED);
if (ret != 1) {
assert(0);
VLOG(1) << "Embree is compiled without the RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED "
"flag. "
"Triangle primitives will not be rendered.";
}
ret = rtcGetDeviceProperty(rtc_shared_device, RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED);
if (ret != 0) {
assert(0);
VLOG(1) << "Embree is compiled with the RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED flag. "
"Renders may not look as expected.";
}
}
++rtc_shared_users;
rtcSetDeviceErrorFunction(rtc_shared_device, rtc_error_func, NULL);
rtcSetDeviceErrorFunction(rtc_device, rtc_error_func, NULL);
pack.root_index = -1;
}
@@ -390,12 +349,6 @@ void BVHEmbree::destroy(RTCScene scene)
rtcReleaseScene(scene);
scene = NULL;
}
thread_scoped_lock lock(rtc_shared_mutex);
--rtc_shared_users;
if (rtc_shared_users == 0) {
rtcReleaseDevice(rtc_shared_device);
rtc_shared_device = NULL;
}
}
void BVHEmbree::delete_rtcScene()
@@ -421,9 +374,9 @@ void BVHEmbree::delete_rtcScene()
void BVHEmbree::build(Progress &progress, Stats *stats_)
{
assert(rtc_shared_device);
assert(rtc_device);
stats = stats_;
rtcSetDeviceMemoryMonitorFunction(rtc_shared_device, rtc_memory_monitor_func, stats);
rtcSetDeviceMemoryMonitorFunction(rtc_device, rtc_memory_monitor_func, stats);
progress.set_substatus("Building BVH");
@@ -434,7 +387,7 @@ void BVHEmbree::build(Progress &progress, Stats *stats_)
const bool dynamic = params.bvh_type == SceneParams::BVH_DYNAMIC;
scene = rtcNewScene(rtc_shared_device);
scene = rtcNewScene(rtc_device);
const RTCSceneFlags scene_flags = (dynamic ? RTC_SCENE_FLAG_DYNAMIC : RTC_SCENE_FLAG_NONE) |
RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST;
rtcSetSceneFlags(scene, scene_flags);
@@ -561,7 +514,7 @@ void BVHEmbree::add_instance(Object *ob, int i)
const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT);
assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE);
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_INSTANCE);
rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene);
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
@@ -615,7 +568,7 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i)
assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT);
const size_t num_triangles = mesh->num_triangles();
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE);
RTCGeometry geom_id = rtcNewGeometry(rtc_device, RTC_GEOMETRY_TYPE_TRIANGLE);
rtcSetGeometryBuildQuality(geom_id, build_quality);
rtcSetGeometryTimeStepCount(geom_id, num_motion_steps);
@@ -804,7 +757,7 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i)
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE :
RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);
RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type);
RTCGeometry geom_id = rtcNewGeometry(rtc_device, type);
rtcSetGeometryTessellationRate(geom_id, curve_subdivisions + 1);
unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer(
geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments);

View File

@@ -50,7 +50,8 @@ class BVHEmbree : public BVH {
friend class BVH;
BVHEmbree(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects);
const vector<Object *> &objects,
const Device *device);
virtual void pack_nodes(const BVHNode *) override;
virtual void refit_nodes() override;
@@ -73,9 +74,7 @@ class BVHEmbree : public BVH {
void update_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh);
void update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair);
static RTCDevice rtc_shared_device;
static int rtc_shared_users;
static thread_mutex rtc_shared_mutex;
RTCDevice rtc_device;
Stats *stats;
vector<RTCScene> delayed_delete_scenes;

View File

@@ -373,6 +373,12 @@ class Device {
return NULL;
}
/* Device specific pointer for BVH creation. Currently only used by Embree. */
virtual void *bvh_device() const
{
return NULL;
}
/* load/compile kernels, must be called before adding tasks */
virtual bool load_kernels(const DeviceRequestedFeatures & /*requested_features*/)
{

View File

@@ -24,6 +24,10 @@
# include <OSL/oslexec.h>
#endif
#ifdef WITH_EMBREE
# include <embree3/rtcore.h>
#endif
#include "device/device.h"
#include "device/device_denoising.h"
#include "device/device_intern.h"
@@ -183,6 +187,9 @@ class CPUDevice : public Device {
oidn::FilterRef oidn_filter;
#endif
thread_spin_lock oidn_task_lock;
#ifdef WITH_EMBREE
RTCDevice embree_device;
#endif
bool use_split_kernel;
@@ -301,6 +308,9 @@ class CPUDevice : public Device {
#ifdef WITH_OSL
kernel_globals.osl = &osl_globals;
#endif
#ifdef WITH_EMBREE
embree_device = rtcNewDevice("verbose=0");
#endif
use_split_kernel = DebugFlags().cpu.split_kernel;
if (use_split_kernel) {
@@ -339,6 +349,9 @@ class CPUDevice : public Device {
~CPUDevice()
{
#ifdef WITH_EMBREE
rtcReleaseDevice(embree_device);
#endif
task_pool.cancel();
texture_info.free();
}
@@ -523,6 +536,15 @@ class CPUDevice : public Device {
#endif
}
void *bvh_device() const override
{
#ifdef WITH_EMBREE
return embree_device;
#else
return NULL;
#endif
}
void thread_run(DeviceTask &task)
{
if (task.type == DeviceTask::RENDER)

View File

@@ -65,7 +65,7 @@ void MemoryManager::DeviceBuffer::update_device_memory(OpenCLDevice *device)
}
/* Always allocate non-empty buffer, NULL pointers cause problems with some drivers. */
total_size = max(total_size, 16);
total_size = std::max(total_size, (size_t)16);
if (need_realloc) {
cl_ulong max_buffer_size;

View File

@@ -214,7 +214,7 @@ void Geometry::compute_bvh(
bparams.curve_subdivisions = params->curve_subdivisions();
delete bvh;
bvh = BVH::create(bparams, geometry, objects);
bvh = BVH::create(bparams, geometry, objects, device);
MEM_GUARDED_CALL(progress, bvh->build, *progress);
}
}
@@ -1029,7 +1029,7 @@ void GeometryManager::device_update_bvh(Device *device,
VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout) << " layout.";
BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects);
BVH *bvh = BVH::create(bparams, scene->geometry, scene->objects, device);
bvh->build(progress, &device->stats);
if (progress.get_cancel()) {

View File

@@ -415,7 +415,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa(GHOST_SystemCocoa *systemCocoa,
[parentWindow->getCocoaWindow() addChildWindow:m_window ordered:NSWindowAbove];
[m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
}
else if (state != GHOST_kWindowStateFullScreen) {
else {
[m_window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 KiB

After

Width:  |  Height:  |  Size: 968 KiB

View File

@@ -40,6 +40,31 @@
</screenshot>
</screenshots>
<releases>
<release version="2.90" date="2020-08-31">
<description>
<p>New features:</p>
<ul>
<li>Nishita sky texture for Cycles</li>
<li>EEVEE motion blur</li>
<li>Cloth filter</li>
<li>Ocean modifier spray</li>
<li>Correct face attributes modeling</li>
<li>OpenVDB fluid integration with mantaflow</li>
<li>Nuke lens distortion model for motion tracking</li>
</ul>
<p>Enhancements:</p>
<ul>
<li>Intel Embree for faster motion blur in Cycles</li>
<li>Viewport Intel OpenImageDenoise</li>
<li>Shadow terminator offset setting</li>
<li>NVLink support for CUDA and Optix</li>
<li>Multires unsubdivide, rebuild and modes</li>
<li>Pose brush transformations</li>
<li>Correct face attributes modeling</li>
<li>User interface improvements: new search, modifiers, headings, stats</li>
</ul>
</description>
</release>
<release version="2.83" date="2020-06-03">
<description>
<p>New features:</p>

View File

@@ -456,9 +456,11 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
Recursively get strings, needed in case we have "Blah" + "Blah", passed as an argument in that case it won't
evaluate to a string. However, break on some kind of stopper nodes, like e.g. Subscript.
"""
if type(node) == ast.Str:
# New in py 3.8: all constants are of type 'ast.Constant'.
# 'ast.Str' will have to be removed when we officially switch to this version.
if type(node) in {ast.Str, getattr(ast, "Constant", None)}:
eval_str = ast.literal_eval(node)
if eval_str:
if eval_str and type(eval_str) == str:
yield (is_split, eval_str, (node,))
else:
is_split = (type(node) in separate_nodes)
@@ -624,6 +626,7 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
}
for fp in files:
# ~ print("Checking File ", fp)
with open(fp, 'r', encoding="utf8") as filedata:
root_node = ast.parse(filedata.read(), fp, 'exec')
@@ -631,8 +634,8 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
for node in ast.walk(root_node):
if type(node) == ast.Call:
# print("found function at")
# print("%s:%d" % (fp, node.lineno))
# ~ print("found function at")
# ~ print("%s:%d" % (fp, node.lineno))
# We can't skip such situations! from blah import foo\nfoo("bar") would also be an ast.Name func!
if type(node.func) == ast.Name:
@@ -657,31 +660,31 @@ def dump_py_messages_from_files(msgs, reports, files, settings):
if kw.arg == arg_kw:
context_elements[arg_kw] = kw.value
break
# print(context_elements)
# ~ print(context_elements)
for kws, proc in translate_kw[msgid]:
if set(kws) <= context_elements.keys():
args = tuple(context_elements[k] for k in kws)
#print("running ", proc, " with ", args)
# ~ print("running ", proc, " with ", args)
ctxt = proc(*args)
if ctxt:
msgctxts[msgid] = ctxt
break
# print(translate_args)
# ~ print(func_args)
# do nothing if not found
for arg_kw, (arg_pos, _) in func_args.items():
msgctxt = msgctxts[arg_kw]
estr_lst = [(None, ())]
if arg_pos < len(node.args):
estr_lst = extract_strings_split(node.args[arg_pos])
#print(estr, nds)
else:
for kw in node.keywords:
if kw.arg == arg_kw:
# ~ print(kw.arg, kw.value)
estr_lst = extract_strings_split(kw.value)
break
#print(estr, nds)
for estr, nds in estr_lst:
# ~ print(estr, nds)
if estr:
if nds:
msgsrc = "{}:{}".format(fp_rel, sorted({nd.lineno for nd in nds})[0])

View File

@@ -283,6 +283,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
del _initialize
if reload_scripts:
_bpy.context.window_manager.tag_script_reload()
import gc
print("gc.collect() -> %d" % gc.collect())

View File

@@ -260,7 +260,13 @@ class NLA_OT_bake(Operator):
def execute(self, context):
from bpy_extras import anim_utils
do_pose = 'POSE' in self.bake_types
do_object = 'OBJECT' in self.bake_types
objects = context.selected_editable_objects
if do_pose and not do_object:
objects = [obj for obj in objects if obj.pose is not None]
object_action_pairs = (
[(obj, getattr(obj.animation_data, "action", None)) for obj in objects]
if self.use_current_action else
@@ -271,8 +277,8 @@ class NLA_OT_bake(Operator):
object_action_pairs,
frames=range(self.frame_start, self.frame_end + 1, self.step),
only_selected=self.only_selected,
do_pose='POSE' in self.bake_types,
do_object='OBJECT' in self.bake_types,
do_pose=do_pose,
do_object=do_object,
do_visual_keying=self.visual_keying,
do_constraint_clear=self.clear_constraints,
do_parents_clear=self.clear_parents,

View File

@@ -731,11 +731,18 @@ class PHYSICS_PT_noise(PhysicButtonsPanel, Panel):
# Deactivate bake operator if data has not been baked yet.
note_flag = True
if domain.use_noise and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
if domain.use_noise and domain.cache_type == 'MODULAR':
label = ""
if not domain.has_cache_baked_data:
label = "Unbaked Data: Bake Data first"
if not domain.cache_resumable:
label = "Non Resumable Cache: Enable resumable option first"
if label:
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text=label)
split = layout.split()
split.enabled = domain.has_cache_baked_data and note_flag and ob.mode == 'OBJECT'
@@ -817,11 +824,18 @@ class PHYSICS_PT_mesh(PhysicButtonsPanel, Panel):
# Deactivate bake operator if data has not been baked yet.
note_flag = True
if domain.use_mesh and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
if domain.use_mesh and domain.cache_type == 'MODULAR':
label = ""
if not domain.has_cache_baked_data:
label = "Unbaked Data: Bake Data first"
if not domain.cache_resumable:
label = "Non Resumable Cache: Enable resumable option first"
if label:
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text=label)
split = layout.split()
split.enabled = domain.has_cache_baked_data and note_flag and ob.mode == 'OBJECT'
@@ -931,11 +945,18 @@ class PHYSICS_PT_particles(PhysicButtonsPanel, Panel):
# Deactivate bake operator if data has not been baked yet.
note_flag = True
if using_particles and not domain.has_cache_baked_data and domain.cache_type == 'MODULAR':
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text="Unbaked Data: Bake Data first")
if using_particles and domain.cache_type == 'MODULAR':
label = ""
if not domain.has_cache_baked_data:
label = "Unbaked Data: Bake Data first"
if not domain.cache_resumable:
label = "Non Resumable Cache: Enable resumable option first"
if label:
note = layout.split()
note_flag = False
note.enabled = note_flag
note.label(icon='INFO', text=label)
split = layout.split()
split.enabled = (

View File

@@ -33,13 +33,13 @@ extern "C" {
/* Blender major and minor version. */
#define BLENDER_VERSION 290
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
#define BLENDER_VERSION_PATCH 1
/** Blender release cycle stage: alpha/beta/rc/release. */
#define BLENDER_VERSION_CYCLE beta
#define BLENDER_VERSION_CYCLE release
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 7
#define BLENDER_FILE_SUBVERSION 8
/* 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

View File

@@ -181,7 +181,6 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
float *n_b = manta_smoke_get_color_b(fds->fluid);
/* Noise smoke fields. */
int wt_res_old[3];
float *o_wt_dens = manta_noise_get_density(fluid_old);
float *o_wt_react = manta_noise_get_react(fluid_old);
float *o_wt_flame = manta_noise_get_flame(fluid_old);
@@ -210,6 +209,7 @@ void BKE_fluid_reallocate_copy_fluid(FluidDomainSettings *fds,
float *n_wt_tcv2 = manta_noise_get_texture_v2(fds->fluid);
float *n_wt_tcw2 = manta_noise_get_texture_w2(fds->fluid);
int wt_res_old[3];
manta_noise_get_res(fluid_old, wt_res_old);
for (int z = o_min[2]; z < o_max[2]; z++) {
@@ -3790,6 +3790,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
}
}
/* Adaptive domain needs to know about current state, so save it here. */
int o_res[3], o_min[3], o_max[3], o_shift[3];
copy_v3_v3_int(o_res, fds->res);
copy_v3_v3_int(o_min, fds->res_min);
copy_v3_v3_int(o_max, fds->res_max);
copy_v3_v3_int(o_shift, fds->shift);
/* Ensure that time parameters are initialized correctly before every step. */
float fps = scene->r.frs_sec / scene->r.frs_sec_base;
fds->frame_length = DT_DEFAULT * (25.0f / fps) * fds->time_scale;
@@ -3870,8 +3877,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
bool with_gdomain;
with_gdomain = (fds->guide_source == FLUID_DOMAIN_GUIDE_SRC_DOMAIN);
int o_res[3], o_min[3], o_max[3], o_shift[3];
/* Cache mode specific settings. */
switch (mode) {
case FLUID_DOMAIN_CACHE_ALL:
@@ -3935,12 +3940,6 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *fmd,
break;
}
/* Adaptive domain needs to know about current state, so save it here. */
copy_v3_v3_int(o_res, fds->res);
copy_v3_v3_int(o_min, fds->res_min);
copy_v3_v3_int(o_max, fds->res_max);
copy_v3_v3_int(o_shift, fds->shift);
bool read_partial = false, read_all = false;
/* Try to read from cache and keep track of read success. */
if (read_cache) {

View File

@@ -56,10 +56,12 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
if (id->properties) {
IDP_FreePropertyContent_ex(id->properties, do_id_user);
MEM_freeN(id->properties);
id->properties = NULL;
}
if (id->override_library) {
BKE_lib_override_library_free(&id->override_library, do_id_user);
id->override_library = NULL;
}
BKE_animdata_free(id, do_id_user);

View File

@@ -1832,18 +1832,31 @@ static void sculpt_sync_face_sets_visibility_to_base_mesh(Mesh *mesh)
return;
}
for (int i = 0; i < mesh->totvert; i++) {
mesh->mvert[i].flag |= ME_HIDE;
}
/* Enabled if the vertex should be visible according to the Face Sets. */
BLI_bitmap *visibile_vertex = BLI_BITMAP_NEW(mesh->totvert, "visible vertices");
/* Enabled if the visibility of this vertex can be affected by the Face Sets to avoid modifying
* disconnected geometry. */
BLI_bitmap *modified_vertex = BLI_BITMAP_NEW(mesh->totvert, "modified vertices");
for (int i = 0; i < mesh->totpoly; i++) {
if (face_sets[i] >= 0) {
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l];
mesh->mvert[loop->v].flag &= ~ME_HIDE;
const bool is_face_set_visible = face_sets[i] >= 0;
for (int l = 0; l < mesh->mpoly[i].totloop; l++) {
MLoop *loop = &mesh->mloop[mesh->mpoly[i].loopstart + l];
if (is_face_set_visible) {
BLI_BITMAP_ENABLE(visibile_vertex, loop->v);
}
BLI_BITMAP_ENABLE(modified_vertex, loop->v);
}
}
for (int i = 0; i < mesh->totvert; i++) {
if (BLI_BITMAP_TEST(modified_vertex, i) && !BLI_BITMAP_TEST(visibile_vertex, i)) {
mesh->mvert[i].flag |= ME_HIDE;
}
}
MEM_SAFE_FREE(visibile_vertex);
MEM_SAFE_FREE(modified_vertex);
}
static void sculpt_sync_face_sets_visibility_to_grids(Mesh *mesh, SubdivCCG *subdiv_ccg)

View File

@@ -2402,6 +2402,10 @@ void BKE_scene_transform_orientation_remove(Scene *scene, TransformOrientation *
orient_slot->type = V3D_ORIENT_GLOBAL;
orient_slot->index_custom = -1;
}
else if (orient_slot->index_custom > orientation_index) {
BLI_assert(orient_slot->type == V3D_ORIENT_CUSTOM);
orient_slot->index_custom--;
}
}
BLI_freelinkN(&scene->transform_spaces, orientation);

View File

@@ -3335,10 +3335,16 @@ float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3],
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
{
float h[2], u[2], lambda;
float h[2], u[2], lambda, denom;
sub_v2_v2v2(u, l2, l1);
sub_v2_v2v2(h, p, l1);
lambda = dot_v2v2(u, h) / dot_v2v2(u, u);
denom = dot_v2v2(u, u);
if (denom == 0.0f) {
r_close[0] = l1[0];
r_close[1] = l1[1];
return 0.0f;
}
lambda = dot_v2v2(u, h) / denom;
r_close[0] = l1[0] + u[0] * lambda;
r_close[1] = l1[1] + u[1] * lambda;
return lambda;
@@ -3353,12 +3359,12 @@ double closest_to_line_v2_db(double r_close[2],
sub_v2_v2v2_db(u, l2, l1);
sub_v2_v2v2_db(h, p, l1);
denom = dot_v2v2_db(u, u);
if (denom < DBL_EPSILON) {
if (denom == 0.0) {
r_close[0] = l1[0];
r_close[1] = l1[1];
return 0.0;
}
lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u);
lambda = dot_v2v2_db(u, h) / denom;
r_close[0] = l1[0] + u[0] * lambda;
r_close[1] = l1[1] + u[1] * lambda;
return lambda;

View File

@@ -909,6 +909,19 @@ void BLI_polyfill_calc(const float (*coords)[2],
const int coords_sign,
uint (*r_tris)[3])
{
/* Fallback to heap memory for large allocations.
* Avoid running out of stack memory on systems with 512kb stack (macOS).
* This happens at around 13,000 points, use a much lower value to be safe. */
if (UNLIKELY(coords_tot > 8192)) {
/* The buffer size only accounts for the index allocation,
* worst case we do two allocations when concave, while we should try to be efficient,
* any caller that relies on this frequently should use #BLI_polyfill_calc_arena directly. */
MemArena *arena = BLI_memarena_new(sizeof(PolyIndex) * coords_tot, __func__);
BLI_polyfill_calc_arena(coords, coords_tot, coords_sign, r_tris, arena);
BLI_memarena_free(arena);
return;
}
PolyFill pf;
PolyIndex *indices = BLI_array_alloca(indices, coords_tot);

View File

@@ -9153,6 +9153,9 @@ static void read_libblock_undo_restore_identical(
if (ob->proxy != NULL) {
ob->proxy->proxy_from = ob;
}
/* For undo we stay in object mode during undo presses, so keep editmode disabled for re-used
* data-blocks too. */
ob->mode &= ~OB_MODE_EDIT;
}
}

View File

@@ -1749,24 +1749,6 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
*/
{
/* Keep this block, even when empty. */
/* Paint Brush. This ensure that the brush paints by default. Used during the development and
* patch review of the initial Sculpt Vertex Colors implementation (D5975) */
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (brush->ob_mode & OB_MODE_SCULPT && brush->sculpt_tool == SCULPT_TOOL_PAINT) {
brush->tip_roundness = 1.0f;
brush->flow = 1.0f;
brush->density = 1.0f;
brush->tip_scale_x = 1.0f;
}
}
/* Pose Brush with support for loose parts. */
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (brush->sculpt_tool == SCULPT_TOOL_POSE && brush->disconnected_distance_max == 0.0f) {
brush->flag2 |= BRUSH_USE_CONNECTED_ONLY;
brush->disconnected_distance_max = 0.1f;
}
}
}
}
@@ -5091,29 +5073,6 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
* \note Keep this message at the bottom of the function.
*/
{
/* Set the cloth wind factor to 1 for old forces. */
if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "f_wind_factor")) {
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
if (ob->pd) {
ob->pd->f_wind_factor = 1.0f;
}
}
LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
if (part->pd) {
part->pd->f_wind_factor = 1.0f;
}
if (part->pd2) {
part->pd2->f_wind_factor = 1.0f;
}
}
}
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
/* Don't rotate light with the viewer by default, make it fixed. Shading settings can't be
* edited and this flag should always be set. So we can always execute this. */
wm->xr.session_settings.shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
}
/* Keep this block, even when empty. */
}
}

View File

@@ -29,8 +29,12 @@
#include "DNA_genfile.h"
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_screen_types.h"
#include "DNA_shader_fx_types.h"
@@ -39,6 +43,7 @@
#include "BKE_gpencil.h"
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BLO_readfile.h"
@@ -206,6 +211,36 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 290, 8)) {
/* Paint Brush. This ensure that the brush paints by default. Used during the development and
* patch review of the initial Sculpt Vertex Colors implementation (D5975) */
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (brush->ob_mode & OB_MODE_SCULPT && brush->sculpt_tool == SCULPT_TOOL_PAINT) {
brush->tip_roundness = 1.0f;
brush->flow = 1.0f;
brush->density = 1.0f;
brush->tip_scale_x = 1.0f;
}
}
/* Pose Brush with support for loose parts. */
LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) {
if (brush->sculpt_tool == SCULPT_TOOL_POSE && brush->disconnected_distance_max == 0.0f) {
brush->flag2 |= BRUSH_USE_CONNECTED_ONLY;
brush->disconnected_distance_max = 0.1f;
}
}
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
if (BKE_collection_cycles_fix(bmain, collection)) {
printf(
"WARNING: Cycle detected in collection '%s', fixed as best as possible.\n"
"You may have to reconstruct your View Layers...\n",
collection->id.name);
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
@@ -217,14 +252,6 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
* \note Keep this message at the bottom of the function.
*/
{
LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
if (BKE_collection_cycles_fix(bmain, collection)) {
printf(
"WARNING: Cycle detected in collection '%s', fixed as best as possible.\n"
"You may have to reconstruct your View Layers...\n",
collection->id.name);
}
}
/* Keep this block, even when empty. */
}
}
@@ -233,6 +260,33 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
{
UNUSED_VARS(fd);
if (MAIN_VERSION_ATLEAST(bmain, 290, 2) && MAIN_VERSION_OLDER(bmain, 291, 1)) {
/* In this range, the extrude manifold could generate meshes with degenerated face. */
LISTBASE_FOREACH (Mesh *, me, &bmain->meshes) {
for (MPoly *mp = me->mpoly, *mp_end = mp + me->totpoly; mp < mp_end; mp++) {
if (mp->totloop == 2) {
bool changed;
BKE_mesh_validate_arrays(me,
me->mvert,
me->totvert,
me->medge,
me->totedge,
me->mface,
me->totface,
me->mloop,
me->totloop,
me->mpoly,
me->totpoly,
me->dvert,
false,
true,
&changed);
break;
}
}
}
}
/** Repair files from duplicate brushes added to blend files, see: T76738. */
if (!MAIN_VERSION_ATLEAST(bmain, 290, 2)) {
{
@@ -407,17 +461,29 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
if (!MAIN_VERSION_ATLEAST(bmain, 290, 8)) {
/* Set the cloth wind factor to 1 for old forces. */
if (!DNA_struct_elem_find(fd->filesdna, "PartDeflect", "float", "f_wind_factor")) {
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
if (ob->pd) {
ob->pd->f_wind_factor = 1.0f;
}
}
LISTBASE_FOREACH (ParticleSettings *, part, &bmain->particles) {
if (part->pd) {
part->pd->f_wind_factor = 1.0f;
}
if (part->pd2) {
part->pd2->f_wind_factor = 1.0f;
}
}
}
for (wmWindowManager *wm = bmain->wm.first; wm; wm = wm->id.next) {
/* Don't rotate light with the viewer by default, make it fixed. Shading settings can't be
* edited and this flag should always be set. So we can always execute this. */
wm->xr.session_settings.shading.flag |= V3D_SHADING_WORLD_ORIENTATION;
}
/* Initialize additional parameter of the Nishita sky model and change altitude unit. */
if (!DNA_struct_elem_find(fd->filesdna, "NodeTexSky", "float", "sun_intensity")) {
@@ -449,4 +515,17 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
/**
* Versioning code until next subversion bump goes here.
*
* \note Be sure to check when bumping the version:
* - "versioning_userdef.c", #BLO_version_defaults_userpref_blend
* - "versioning_userdef.c", #do_versions_theme
*
* \note Keep this message at the bottom of the function.
*/
{
/* Keep this block, even when empty. */
}
}

View File

@@ -758,6 +758,12 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
userdef->statusbar_flag = STATUSBAR_SHOW_VERSION;
}
if (!USER_VERSION_ATLEAST(290, 8)) {
if (userdef->collection_instance_empty_size == 0) {
userdef->collection_instance_empty_size = 1.0f;
}
}
/**
* Versioning code until next subversion bump goes here.
*
@@ -769,10 +775,6 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef)
*/
{
/* Keep this block, even when empty. */
if (userdef->collection_instance_empty_size == 0) {
userdef->collection_instance_empty_size = 1.0f;
}
}
if (userdef->pixelsize == 0.0f) {

View File

@@ -1844,10 +1844,17 @@ static void write_shaderfxs(BlendWriter *writer, ListBase *fxbase)
static void write_object(BlendWriter *writer, Object *ob, const void *id_address)
{
if (ob->id.us > 0 || BLO_write_is_undo(writer)) {
const bool is_undo = BLO_write_is_undo(writer);
if (ob->id.us > 0 || is_undo) {
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
BKE_object_runtime_reset(ob);
if (is_undo) {
/* For undo we stay in object mode during undo presses, so keep editmode disabled on save as
* well, can help reducing false detection of changed datablocks. */
ob->mode &= ~OB_MODE_EDIT;
}
/* write LibData */
BLO_write_id_struct(writer, Object, id_address, &ob->id);
write_iddata(writer, &ob->id);

View File

@@ -884,19 +884,14 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
const bool apply_offset = (ofs && (currkey != actkey) &&
(bm->shapenr - 1 == currkey->relative));
int cd_shape_offset;
int keyi;
const float(*ofs_pt)[3] = ofs;
float *newkey, (*oldkey)[3], *fp;
j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
if (cd_shape_offset < 0) {
/* The target Mesh has more shapekeys than the BMesh. */
continue;
}
const int cd_shape_offset = CustomData_get_n_offset(&bm->vdata, CD_SHAPEKEY, j);
const bool apply_offset = (cd_shape_offset != -1) && (ofs != NULL) && (currkey != actkey) &&
(bm->shapenr - 1 == currkey->relative);
fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
oldkey = currkey->data;
@@ -918,7 +913,7 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh
}
}
}
else if (j != -1) {
else if (cd_shape_offset != -1) {
/* In most cases this runs. */
copy_v3_v3(fp, BM_ELEM_CD_GET_VOID_P(eve, cd_shape_offset));
}

View File

@@ -614,7 +614,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op)
BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v);
if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) {
/* Lose edge or BMVert is edge pair. */
BM_edge_collapse(bm, BMO_elem_flag_test(bm, e, EXT_TAG) ? e : e_other, v, true, false);
BM_edge_collapse(bm, BMO_elem_flag_test(bm, e, EXT_TAG) ? e : e_other, v, true, true);
}
else {
BLI_assert(!BM_vert_is_edge_pair(v));

View File

@@ -166,7 +166,7 @@ static bool bm_edge_delimit_cdata(CustomData *ldata,
r_delim_cd->cd_type = type;
r_delim_cd->cd_size = CustomData_sizeof(r_delim_cd->cd_type);
r_delim_cd->cd_offset = CustomData_get_n_offset(ldata, type, 0);
r_delim_cd->cd_offset_end = r_delim_cd->cd_size * layer_len;
r_delim_cd->cd_offset_end = r_delim_cd->cd_offset + (r_delim_cd->cd_size * layer_len);
return (r_delim_cd->cd_offset != -1);
}

View File

@@ -63,10 +63,9 @@ static struct {
GPUTexture *depth_src;
GPUTexture *dummy_density;
GPUTexture *dummy_color;
GPUTexture *dummy_zero;
GPUTexture *dummy_one;
GPUTexture *dummy_flame;
GPUTexture *dummy_missing;
GPUTexture *dummy_scatter;
GPUTexture *dummy_transmit;
@@ -150,14 +149,26 @@ static void eevee_create_shader_volumes(void)
e_data.volumetric_accum_sh = DRW_shader_create_fullscreen(datatoc_volumetric_accum_frag_glsl,
NULL);
const float density[4] = {1.0f, 1.0f, 1.0f, 1.0f};
e_data.dummy_density = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, density);
const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
e_data.dummy_zero = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, zero);
const float one[4] = {1.0f, 1.0f, 1.0f, 1.0f};
e_data.dummy_one = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, one);
const float flame = 0.0f;
e_data.dummy_flame = DRW_texture_create_3d(1, 1, 1, GPU_R8, DRW_TEX_WRAP, &flame);
}
const float missing[4] = {0.0f, 0.0f, 0.0f, 0.0f};
e_data.dummy_missing = DRW_texture_create_3d(1, 1, 1, GPU_RGBA8, DRW_TEX_WRAP, missing);
static GPUTexture *eevee_volume_default_texture(eGPUVolumeDefaultValue default_value)
{
switch (default_value) {
case GPU_VOLUME_DEFAULT_0:
return e_data.dummy_zero;
case GPU_VOLUME_DEFAULT_1:
return e_data.dummy_one;
}
return e_data.dummy_zero;
}
void EEVEE_volumes_set_jitter(EEVEE_ViewLayerData *sldata, uint current_sample)
@@ -378,7 +389,8 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, &gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_missing);
DRW_shgroup_uniform_texture(
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
}
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -465,8 +477,16 @@ static bool eevee_volume_object_grids_init(Object *ob, ListBase *gpu_grids, DRWS
DRW_volume_batch_cache_get_grid(volume, volume_grid) :
NULL;
DRW_shgroup_uniform_texture(
grp, gpu_grid->sampler_name, (drw_grid) ? drw_grid->texture : e_data.dummy_missing);
/* Handle 3 cases here:
* - Grid exists and texture was loaded -> use texture.
* - Grid exists but has zero size or failed to load -> use zero.
* - Grid does not exist -> use default value. */
GPUTexture *grid_tex = (drw_grid) ? drw_grid->texture :
(volume_grid) ?
e_data.dummy_zero :
eevee_volume_default_texture(gpu_grid->default_value);
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, grid_tex);
if (drw_grid && multiple_transforms) {
/* Specify per-volume transform matrix that is applied after the
@@ -519,21 +539,20 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
if (STREQ(gpu_grid->name, "density")) {
DRW_shgroup_uniform_texture_ref(grp,
gpu_grid->sampler_name,
fds->tex_density ? &fds->tex_density :
&e_data.dummy_density);
DRW_shgroup_uniform_texture_ref(
grp, gpu_grid->sampler_name, fds->tex_density ? &fds->tex_density : &e_data.dummy_one);
}
else if (STREQ(gpu_grid->name, "color")) {
DRW_shgroup_uniform_texture_ref(
grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_density);
grp, gpu_grid->sampler_name, fds->tex_color ? &fds->tex_color : &e_data.dummy_one);
}
else if (STREQ(gpu_grid->name, "flame") || STREQ(gpu_grid->name, "temperature")) {
DRW_shgroup_uniform_texture_ref(
grp, gpu_grid->sampler_name, fds->tex_flame ? &fds->tex_flame : &e_data.dummy_flame);
}
else {
DRW_shgroup_uniform_texture_ref(grp, gpu_grid->sampler_name, &e_data.dummy_density);
DRW_shgroup_uniform_texture(
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
}
}
@@ -549,7 +568,8 @@ static bool eevee_volume_object_mesh_init(Scene *scene,
}
else {
LISTBASE_FOREACH (GPUMaterialVolumeGrid *, gpu_grid, gpu_grids) {
DRW_shgroup_uniform_texture(grp, gpu_grid->sampler_name, e_data.dummy_density);
DRW_shgroup_uniform_texture(
grp, gpu_grid->sampler_name, eevee_volume_default_texture(gpu_grid->default_value));
}
}
@@ -858,10 +878,9 @@ void EEVEE_volumes_free(void)
DRW_TEXTURE_FREE_SAFE(e_data.dummy_scatter);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_transmit);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_density);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_zero);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_one);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_flame);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_color);
DRW_TEXTURE_FREE_SAFE(e_data.dummy_missing);
DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh);
DRW_SHADER_FREE_SAFE(e_data.scatter_sh);

View File

@@ -169,7 +169,7 @@ static void mesh_cd_calc_active_vcol_layer(const Mesh *me, DRW_MeshCDMask *cd_us
static void mesh_cd_calc_active_mloopcol_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const Mesh *me_final = editmesh_final_or_this(me);
const CustomData *cd_ldata = &me_final->ldata;
const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final);
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL);
if (layer != -1) {

View File

@@ -59,6 +59,7 @@ void EDBM_verts_mirror_cache_begin_ex(struct BMEditMesh *em,
const int axis,
const bool use_self,
const bool use_select,
const bool respecthide,
const bool use_topology,
float maxdist,
int *r_index);
@@ -66,6 +67,7 @@ void EDBM_verts_mirror_cache_begin(struct BMEditMesh *em,
const int axis,
const bool use_self,
const bool use_select,
const bool respecthide,
const bool use_toplogy);
void EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);

View File

@@ -310,7 +310,8 @@ void ED_objects_recalculate_paths(struct bContext *C,
eObjectPathCalcRange range);
/* constraints */
struct ListBase *ED_object_constraint_list_from_context(struct Object *ob);
struct ListBase *ED_object_constraint_active_list(struct Object *ob);
struct ListBase *ED_object_pose_constraint_list(const struct bContext *C);
struct ListBase *ED_object_constraint_list_from_constraint(struct Object *ob,
struct bConstraint *con,
struct bPoseChannel **r_pchan);

View File

@@ -1950,18 +1950,13 @@ static bool constraint_panel_is_bone(Panel *panel)
*/
static ListBase *get_constraints(const bContext *C, bool use_bone_constraints)
{
ListBase *constraints = {NULL};
ListBase *constraints = NULL;
if (use_bone_constraints) {
bPoseChannel *pose_bone = CTX_data_pointer_get(C, "pose_bone").data;
if (pose_bone != NULL) {
constraints = &pose_bone->constraints;
}
constraints = ED_object_pose_constraint_list(C);
}
else {
Object *ob = ED_object_active_context(C);
if (ob != NULL) {
constraints = &ob->constraints;
}
constraints = ED_object_constraint_active_list(ob);
}
return constraints;
}
@@ -2043,7 +2038,13 @@ void uiTemplateConstraints(uiLayout *UNUSED(layout), bContext *C, bool use_bone_
ARegion *region = CTX_wm_region(C);
Object *ob = ED_object_active_context(C);
ListBase *constraints = get_constraints(C, use_bone_constraints);
ListBase *constraints = {NULL};
if (use_bone_constraints) {
constraints = ED_object_pose_constraint_list(C);
}
else {
constraints = ED_object_constraint_active_list(ob);
}
/* Switch between the bone panel ID function and the object panel ID function. */
uiListPanelIDFromDataFunc panel_id_func = use_bone_constraints ? bone_constraint_panel_id :

View File

@@ -489,7 +489,7 @@ void ui_rna_collection_search_update_fn(const struct bContext *C,
/* If no item has an own icon to display, libraries can use the library icons rather than the
* name prefix for showing the library status. */
int name_prefix_offset = cis->name_prefix_offset;
if (!has_id_icon && cis->is_id) {
if (!has_id_icon && cis->is_id && !requires_exact_data_name) {
cis->iconid = UI_library_icon_get(cis->data);
/* No need to re-allocate, string should be shorter than before (lib status prefix is
* removed). */

View File

@@ -110,7 +110,7 @@ void EDBM_select_mirrored(BMEditMesh *em,
}
}
EDBM_verts_mirror_cache_begin(em, axis, true, true, use_topology);
EDBM_verts_mirror_cache_begin(em, axis, true, true, false, use_topology);
if (!extend) {
EDBM_flag_disable_all(em, BM_ELEM_SELECT);

View File

@@ -2513,7 +2513,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
/* mirror before smooth */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
}
/* if there is a mirror modifier with clipping, flag the verts that
@@ -2658,7 +2658,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
/* Mirror before smooth. */
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
EDBM_verts_mirror_cache_begin(em, 0, false, true, use_topology);
EDBM_verts_mirror_cache_begin(em, 0, false, true, false, use_topology);
}
bool failed_repeat_loop = false;
@@ -7600,7 +7600,7 @@ static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op)
BMVert *v;
int i;
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, use_topology, thresh, index);
EDBM_verts_mirror_cache_begin_ex(em, axis, true, true, false, use_topology, thresh, index);
BM_mesh_elem_table_ensure(bm, BM_VERT);

View File

@@ -1059,6 +1059,7 @@ static BMVert *cache_mirr_intptr_as_bmvert(const intptr_t *index_lookup, int ind
* \param em: Editmesh.
* \param use_self: Allow a vertex to point to its self (middle verts).
* \param use_select: Restrict to selected verts.
* \param respecthide: Skip hidden vertices.
* \param use_topology: Use topology mirror.
* \param maxdist: Distance for close point test.
* \param r_index: Optional array to write into, as an alternative to a customdata layer
@@ -1068,6 +1069,7 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
const int axis,
const bool use_self,
const bool use_select,
const bool respecthide,
/* extra args */
const bool use_topology,
float maxdist,
@@ -1110,6 +1112,10 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
else {
tree = BLI_kdtree_3d_new(bm->totvert);
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
continue;
}
BLI_kdtree_3d_insert(tree, i, v->co);
}
BLI_kdtree_3d_balance(tree);
@@ -1118,44 +1124,45 @@ void EDBM_verts_mirror_cache_begin_ex(BMEditMesh *em,
#define VERT_INTPTR(_v, _i) (r_index ? &r_index[_i] : BM_ELEM_CD_GET_VOID_P(_v, cd_vmirr_offset))
BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) {
BLI_assert(BM_elem_index_get(v) == i);
if (respecthide && BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
continue;
}
/* temporary for testing, check for selection */
if (use_select && !BM_elem_flag_test(v, BM_ELEM_SELECT)) {
/* do nothing */
continue;
}
BLI_assert(BM_elem_index_get(v) == i);
BMVert *v_mirr;
int *idx = VERT_INTPTR(v, i);
if (use_topology) {
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
}
else {
BMVert *v_mirr;
int *idx = VERT_INTPTR(v, i);
int i_mirr;
float co[3];
copy_v3_v3(co, v->co);
co[axis] *= -1.0f;
if (use_topology) {
v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, i);
}
else {
int i_mirr;
float co[3];
copy_v3_v3(co, v->co);
co[axis] *= -1.0f;
v_mirr = NULL;
i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
if (i_mirr != -1) {
BMVert *v_test = BM_vert_at_index(bm, i_mirr);
if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
v_mirr = v_test;
}
v_mirr = NULL;
i_mirr = BLI_kdtree_3d_find_nearest(tree, co, NULL);
if (i_mirr != -1) {
BMVert *v_test = BM_vert_at_index(bm, i_mirr);
if (len_squared_v3v3(co, v_test->co) < maxdist_sq) {
v_mirr = v_test;
}
}
}
if (v_mirr && (use_self || (v_mirr != v))) {
const int i_mirr = BM_elem_index_get(v_mirr);
*idx = i_mirr;
idx = VERT_INTPTR(v_mirr, i_mirr);
*idx = i;
}
else {
*idx = -1;
}
if (v_mirr && (use_self || (v_mirr != v))) {
const int i_mirr = BM_elem_index_get(v_mirr);
*idx = i_mirr;
idx = VERT_INTPTR(v_mirr, i_mirr);
*idx = i;
}
else {
*idx = -1;
}
}
@@ -1173,12 +1180,14 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em,
const int axis,
const bool use_self,
const bool use_select,
const bool respecthide,
const bool use_topology)
{
EDBM_verts_mirror_cache_begin_ex(em,
axis,
use_self,
use_select,
respecthide,
/* extra args */
use_topology,
BM_SEARCH_MAXDIST_MIRR,

View File

@@ -80,8 +80,9 @@
/** \name Constraint Data Accessors
* \{ */
/* if object in posemode, active bone constraints, else object constraints */
ListBase *ED_object_constraint_list_from_context(Object *ob)
/* If object is in posemode, return active bone constraints, else object constraints. No
* constraints are returned for a bone on an inactive bonelayer. */
ListBase *ED_object_constraint_active_list(Object *ob)
{
if (ob == NULL) {
return NULL;
@@ -102,6 +103,21 @@ ListBase *ED_object_constraint_list_from_context(Object *ob)
return NULL;
}
/* Get the constraints for the active pose bone. Bone may be on an inactive bonelayer (unlike
* ED_object_constraint_active_list, such constraints are not excluded here). */
ListBase *ED_object_pose_constraint_list(const bContext *C)
{
bPoseChannel *pose_bone = CTX_data_pointer_get(C, "active_pose_bone").data;
if (pose_bone == NULL) {
pose_bone = CTX_data_pointer_get(C, "pose_bone").data;
if (pose_bone == NULL) {
return NULL;
}
}
return &pose_bone->constraints;
}
/* Find the list that a given constraint belongs to,
* and/or also get the posechannel this is from (if applicable) */
ListBase *ED_object_constraint_list_from_constraint(Object *ob,
@@ -147,7 +163,7 @@ ListBase *ED_object_constraint_list_from_constraint(Object *ob,
/* single constraint */
bConstraint *ED_object_constraint_active_get(Object *ob)
{
return BKE_constraints_active_get(ED_object_constraint_list_from_context(ob));
return BKE_constraints_active_get(ED_object_constraint_active_list(ob));
}
/** \} */
@@ -780,7 +796,7 @@ static bool edit_constraint_invoke_properties(bContext *C,
return false;
}
static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int type)
static bConstraint *edit_constraint_property_get(bContext *C, wmOperator *op, Object *ob, int type)
{
char constraint_name[MAX_NAME];
int owner = RNA_enum_get(op->ptr, "owner");
@@ -789,31 +805,11 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
RNA_string_get(op->ptr, "constraint", constraint_name);
if (owner == EDIT_CONSTRAINT_OWNER_OBJECT) {
list = &ob->constraints;
}
else if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
bPoseChannel *pchan = BKE_pose_channel_active(ob);
if (pchan) {
list = &pchan->constraints;
}
else {
#if 0
if (G.debug & G_DEBUG) {
printf("edit_constraint_property_get: No active bone for object '%s'\n",
(ob) ? ob->id.name + 2 : "<None>");
}
#endif
return NULL;
}
if (owner == EDIT_CONSTRAINT_OWNER_BONE) {
list = ED_object_pose_constraint_list(C);
}
else {
#if 0
if (G.debug & G_DEBUG) {
printf("edit_constraint_property_get: defaulting to getting list in the standard way\n");
}
#endif
list = ED_object_constraint_list_from_context(ob);
list = ED_object_constraint_active_list(ob);
}
con = BKE_constraints_find_name(list, constraint_name);
@@ -842,7 +838,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_STRETCHTO);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_STRETCHTO);
bStretchToConstraint *data = (con) ? (bStretchToConstraint *)con->data : NULL;
/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -897,7 +893,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_DISTLIMIT);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_DISTLIMIT);
bDistLimitConstraint *data = (con) ? (bDistLimitConstraint *)con->data : NULL;
/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -969,7 +965,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -1023,7 +1019,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_CHILDOF);
bChildOfConstraint *data = (con) ? (bChildOfConstraint *)con->data : NULL;
if (data == NULL) {
@@ -1077,7 +1073,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_FOLLOWPATH);
bFollowPathConstraint *data = (con) ? (bFollowPathConstraint *)con->data : NULL;
bAction *act = NULL;
@@ -1221,7 +1217,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -1283,7 +1279,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bConstraint *con = edit_constraint_property_get(C, op, ob, CONSTRAINT_TYPE_OBJECTSOLVER);
bObjectSolverConstraint *data = (con) ? (bObjectSolverConstraint *)con->data : NULL;
if (data == NULL) {
@@ -1431,7 +1427,7 @@ static int constraint_delete_exec(bContext *C, wmOperator *op)
{
Main *bmain = CTX_data_main(C);
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
ListBase *lb = ED_object_constraint_list_from_constraint(ob, con, NULL);
/* Store name temporarily for report. */
@@ -1497,7 +1493,7 @@ void CONSTRAINT_OT_delete(wmOperatorType *ot)
static int constraint_move_down_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
if (con && con->next) {
ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
@@ -1552,7 +1548,7 @@ void CONSTRAINT_OT_move_down(wmOperatorType *ot)
static int constraint_move_up_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
if (con && con->prev) {
ListBase *conlist = ED_object_constraint_list_from_constraint(ob, con, NULL);
@@ -1605,7 +1601,7 @@ void CONSTRAINT_OT_move_up(wmOperatorType *ot)
static int constraint_move_to_index_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_active_context(C);
bConstraint *con = edit_constraint_property_get(op, ob, 0);
bConstraint *con = edit_constraint_property_get(C, op, ob, 0);
int new_index = RNA_int_get(op->ptr, "index");
if (new_index < 0) {
@@ -2162,8 +2158,7 @@ static int pose_constraint_add_exec(bContext *C, wmOperator *op)
with_targets = 1;
}
return constraint_add_exec(
C, op, ob, ED_object_constraint_list_from_context(ob), type, with_targets);
return constraint_add_exec(C, op, ob, ED_object_constraint_active_list(ob), type, with_targets);
}
/* ------------------ */
@@ -2364,12 +2359,8 @@ static int pose_ik_add_exec(bContext *C, wmOperator *op)
/* add the constraint - all necessary checks should have
* been done by the invoke() callback already... */
return constraint_add_exec(C,
op,
ob,
ED_object_constraint_list_from_context(ob),
CONSTRAINT_TYPE_KINEMATIC,
with_targets);
return constraint_add_exec(
C, op, ob, ED_object_constraint_active_list(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
}
void POSE_OT_ik_add(wmOperatorType *ot)

View File

@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -99,71 +100,61 @@ void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
}
}
static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (ob->type != OB_MESH) {
return;
}
if (me->edit_mesh) {
BMEditMesh *em = me->edit_mesh;
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
Mesh *me = ob->data;
if (me->edit_mesh) {
BMEditMesh *em = me->edit_mesh;
const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
if (cd_fmap_offset != -1) {
BMFace *efa;
BMIter iter;
int *map;
if (cd_fmap_offset != -1) {
BMFace *efa;
BMIter iter;
int *map;
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
if (map) {
if (num1 != -1) {
if (*map == num1) {
*map = num2;
}
else if (*map == num2) {
*map = num1;
}
}
}
if (map && *map != -1) {
*map = remap[*map];
}
}
}
}
}
static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
static void object_fmap_remap_object_mode(Object *ob, const int *remap)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
if (ob->type != OB_MESH) {
return;
}
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
int i;
Mesh *me = ob->data;
if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
int i;
if (map) {
for (i = 0; i < me->totpoly; i++) {
if (num1 != -1) {
if (map[i] == num1) {
map[i] = num2;
}
else if (map[i] == num2) {
map[i] = num1;
}
}
if (map) {
for (i = 0; i < me->totpoly; i++) {
if (map[i] != -1) {
map[i] = remap[map[i]];
}
}
}
}
}
static void object_facemap_swap(Object *ob, int num1, int num2)
static void object_facemap_remap(Object *ob, const int *remap)
{
if (BKE_object_is_in_editmode(ob)) {
object_fmap_swap_edit_mode(ob, num1, num2);
object_fmap_remap_edit_mode(ob, remap);
}
else {
object_fmap_swap_object_mode(ob, num1, num2);
object_fmap_remap_object_mode(ob, remap);
}
}
@@ -432,45 +423,46 @@ static int face_map_move_exec(bContext *C, wmOperator *op)
Object *ob = ED_object_context(C);
bFaceMap *fmap;
int dir = RNA_enum_get(op->ptr, "direction");
int pos1, pos2 = -1, count;
fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
if (!fmap) {
return OPERATOR_CANCELLED;
}
count = BLI_listbase_count(&ob->fmaps);
pos1 = BLI_findindex(&ob->fmaps, fmap);
if (!fmap->prev && !fmap->next) {
return OPERATOR_CANCELLED;
}
int pos1 = BLI_findindex(&ob->fmaps, fmap);
int pos2 = pos1 - dir;
int len = BLI_listbase_count(&ob->fmaps);
int *map = MEM_mallocN(len * sizeof(*map), __func__);
if (!IN_RANGE(pos2, -1, len)) {
const int offset = len - dir;
for (int i = 0; i < len; i++) {
map[i] = (i + offset) % len;
}
pos2 = map[pos1];
}
else {
range_vn_i(map, len, 0);
SWAP(int, map[pos1], map[pos2]);
}
void *prev = fmap->prev;
void *next = fmap->next;
BLI_remlink(&ob->fmaps, fmap);
if (dir == 1) { /*up*/
void *prev = fmap->prev;
if (prev) {
pos2 = pos1 - 1;
}
else {
pos2 = count - 1;
}
BLI_remlink(&ob->fmaps, fmap);
BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
}
else { /*down*/
void *next = fmap->next;
if (next) {
pos2 = pos1 + 1;
}
else {
pos2 = 0;
}
BLI_remlink(&ob->fmaps, fmap);
BLI_insertlinkafter(&ob->fmaps, next, fmap);
}
/* iterate through mesh and substitute the indices as necessary */
object_facemap_swap(ob, pos2, pos1);
/* Iterate through mesh and substitute the indices as necessary. */
object_facemap_remap(ob, map);
MEM_freeN(map);
ob->actfmap = pos2 + 1;

View File

@@ -2407,7 +2407,7 @@ void ED_vgroup_mirror(Object *ob,
goto cleanup;
}
EDBM_verts_mirror_cache_begin(em, 0, true, false, use_topology);
EDBM_verts_mirror_cache_begin(em, 0, true, false, false, use_topology);
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);

View File

@@ -6114,8 +6114,6 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
/* allocate and initialize spatial data structures */
project_paint_begin(C, &ps, false, 0);
@@ -6125,8 +6123,10 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
float pos[2] = {0.0, 0.0};
float lastpos[2] = {0.0, 0.0};
ED_image_undo_push_begin(op->type->name, PAINT_MODE_TEXTURE_3D);
const float pos[2] = {0.0, 0.0};
const float lastpos[2] = {0.0, 0.0};
int a;
project_paint_op(&ps, lastpos, pos);
@@ -6140,6 +6140,8 @@ static int texture_paint_camera_project_exec(bContext *C, wmOperator *op)
project_paint_end(&ps);
ED_image_undo_push_end();
scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING;
BKE_brush_size_set(scene, ps.brush, orig_brush_size);

View File

@@ -1005,6 +1005,14 @@ void ED_image_undosys_type(UndoType *ut)
/* -------------------------------------------------------------------- */
/** \name Utilities
*
* \note image undo exposes #ED_image_undo_push_begin, #ED_image_undo_push_end
* which must be called by the operator directly.
*
* Unlike most other undo stacks this is needed:
* - So we can always access the state before the image was painted onto,
* which is needed if previous undo states aren't image-type.
* - So operators can access the pixel-data before the stroke was applied, at run-time.
* \{ */
ListBase *ED_image_paint_tile_list_get(void)
@@ -1042,6 +1050,10 @@ static ImageUndoStep *image_undo_push_begin(const char *name, int paint_mode)
return us;
}
/**
* The caller is responsible for running #ED_image_undo_push_end,
* failure to do so causes an invalid state for the undo system.
*/
void ED_image_undo_push_begin(const char *name, int paint_mode)
{
image_undo_push_begin(name, paint_mode);

View File

@@ -115,15 +115,32 @@ static int script_reload_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
WM_script_tag_reload();
/* TODO(campbell): this crashes on netrender and keying sets, need to look into why
* disable for now unless running in debug mode. */
/* It would be nice if we could detect when this is called from the Python
* only postponing in that case, for now always do it. */
if (true) {
/* Postpone when called from Python so this can be called from an operator
* that might be re-registered, crashing Blender when we try to read from the
* freed operator type which, see T80694. */
BPY_execute_string(C,
(const char *[]){"bpy", NULL},
"def fn():\n"
" bpy.utils.load_scripts(reload_scripts=True)\n"
" return None\n"
"bpy.app.timers.register(fn)");
}
else {
WM_cursor_wait(true);
BPY_execute_string(
C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
WM_cursor_wait(false);
}
/* Note that #WM_script_tag_reload is called from `bpy.utils.load_scripts`,
* any additional updates required by this operator should go there. */
/* TODO, this crashes on netrender and keying sets, need to look into why
* disable for now unless running in debug mode */
WM_cursor_wait(1);
BPY_execute_string(
C, (const char *[]){"bpy", NULL}, "bpy.utils.load_scripts(reload_scripts=True)");
WM_cursor_wait(0);
WM_event_add_notifier(C, NC_WINDOW, NULL);
return OPERATOR_FINISHED;
#else
UNUSED_VARS(C, op);

View File

@@ -349,6 +349,10 @@ static short pose_grab_with_ik_add(bPoseChannel *pchan)
}
}
}
/* Return early (as in: don't actually create a temporary constraint here), since adding
* will take place later in add_pose_transdata() for targetless constraints. */
return 0;
}
}
@@ -702,10 +706,14 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr
/* Add a temporary auto IK constraint here, as we will only temporarily active this
* targetless bone during transform. (Targetless IK constraints are treated as if they are
* disabled unless they are transformed). */
add_temporary_ik_constraint(pchan, data);
Main *bmain = CTX_data_main(t->context);
update_deg_with_temporary_ik(bmain, ob);
* disabled unless they are transformed).
* Only do this for targetless IK though, AutoIK already added a constraint in
* pose_grab_with_ik_add() beforehand. */
if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
add_temporary_ik_constraint(pchan, data);
Main *bmain = CTX_data_main(t->context);
update_deg_with_temporary_ik(bmain, ob);
}
/* only object matrix correction */
copy_m3_m3(td->mtx, omat);
@@ -1350,10 +1358,14 @@ static void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, O
data->flag |= CONSTRAINT_IK_AUTO;
/* Add a temporary auto IK constraint here, as we will only temporarily active this
* target-less bone during transform. (Target-less IK constraints are treated as if they are
* disabled unless they are transformed) */
add_temporary_ik_constraint(pchan, data);
Main *bmain = CTX_data_main(t->context);
update_deg_with_temporary_ik(bmain, ob);
* disabled unless they are transformed).
* Only do this for targetless IK though, AutoIK already added a constraint in
* pose_grab_with_ik_add() beforehand. */
if ((data->flag & CONSTRAINT_IK_TEMP) == 0) {
add_temporary_ik_constraint(pchan, data);
Main *bmain = CTX_data_main(t->context);
update_deg_with_temporary_ik(bmain, ob);
}
}
if (pid) {

View File

@@ -507,7 +507,7 @@ static void editmesh_mirror_data_calc(BMEditMesh *em,
index[a] = MEM_mallocN(totvert * sizeof(*index[a]), __func__);
EDBM_verts_mirror_cache_begin_ex(
em, a, false, test_selected_only, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
em, a, false, test_selected_only, true, use_topology, TRANSFORM_MAXDIST_MIRROR, index[a]);
flag = TD_MIRROR_X << a;
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
@@ -1293,6 +1293,9 @@ void mesh_customdatacorrect_init(TransInfo *t)
use_merge_group = (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT_KEEP_CONNECTED) != 0;
}
}
else {
return;
}
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
mesh_customdatacorrect_init_container(tc, use_merge_group);

View File

@@ -301,6 +301,9 @@ void createTransUVs(bContext *C, TransInfo *t)
BM_elem_flag_enable(efa, BM_ELEM_TAG);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
/* Make sure that the loop element flag is cleared for when we use it in
* uv_set_connectivity_distance later. */
BM_elem_flag_disable(l, BM_ELEM_TAG);
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
countsel++;
@@ -322,6 +325,8 @@ void createTransUVs(bContext *C, TransInfo *t)
}
}
float *prop_dists = NULL;
/* Support other objects using PET to adjust these, unless connected is enabled. */
if (((is_prop_edit && !is_prop_connected) ? count : countsel) == 0) {
goto finally;
@@ -349,8 +354,6 @@ void createTransUVs(bContext *C, TransInfo *t)
td = tc->data;
td2d = tc->data_2d;
float *prop_dists = NULL;
if (is_prop_connected) {
prop_dists = MEM_callocN(em->bm->totloop * sizeof(float), "TransObPropDists(UV Editing)");
@@ -397,7 +400,7 @@ void createTransUVs(bContext *C, TransInfo *t)
finally:
if (is_prop_connected) {
MEM_freeN(prop_dists);
MEM_SAFE_FREE(prop_dists);
}
if (is_island_center) {
BM_uv_element_map_free(elementmap);

View File

@@ -2855,9 +2855,6 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
}
}
else if (use_edge && !pinned) {
changed = true;
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
@@ -2865,29 +2862,18 @@ static int uv_box_select_exec(bContext *C, wmOperator *op)
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
if ((select != luv_select) || (select != luv_select_prev)) {
if (BLI_rctf_isect_pt_v(&rectf, luv->uv) &&
BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
}
if (BLI_rctf_isect_pt_v(&rectf, luv->uv) && BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) {
uvedit_edge_select_set_with_sticky(
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
changed = true;
}
l_prev = l;
luv_prev = luv;
luv_select_prev = luv_select;
}
}
if (sima->sticky == SI_STICKY_VERTEX) {
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
}
}
else {
/* other selection modes */
@@ -3086,8 +3072,6 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
}
}
else if (use_edge) {
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
@@ -3095,29 +3079,18 @@ static int uv_circle_select_exec(bContext *C, wmOperator *op)
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
if ((select != luv_select) || (select != luv_select_prev)) {
if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
changed = true;
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
}
if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) {
uvedit_edge_select_set_with_sticky(
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
changed = true;
}
l_prev = l;
luv_prev = luv;
luv_select_prev = luv_select;
}
}
if (sima->sticky == SI_STICKY_VERTEX) {
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
}
}
else {
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
@@ -3277,8 +3250,6 @@ static bool do_lasso_select_mesh_uv(bContext *C,
}
}
else if (use_edge) {
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!uvedit_face_visible_test(scene, efa)) {
continue;
@@ -3286,32 +3257,21 @@ static bool do_lasso_select_mesh_uv(bContext *C,
BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev;
MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset);
bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset);
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset);
if ((select != luv_select) || (select != luv_select_prev)) {
if (do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv->uv) &&
do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
uvedit_uv_select_set(scene, em, l, select, false, cd_loop_uv_offset);
uvedit_uv_select_set(scene, em, l_prev, select, false, cd_loop_uv_offset);
changed = true;
BM_elem_flag_enable(l->v, BM_ELEM_TAG);
BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG);
}
if (do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv->uv) &&
do_lasso_select_mesh_uv_is_point_inside(
region, &rect, mcoords, mcoords_len, luv_prev->uv)) {
uvedit_edge_select_set_with_sticky(
sima, scene, em, l_prev, select, false, cd_loop_uv_offset);
changed = true;
}
l_prev = l;
luv_prev = luv;
luv_select_prev = luv_select;
}
}
if (sima->sticky == SI_STICKY_VERTEX) {
uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset);
}
}
else { /* Vert Sel */
BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false);

View File

@@ -227,8 +227,8 @@ static void panel_draw(const bContext *C, Panel *panel)
else {
uiItemR(layout, &ptr, "normalize_opacity", 0, NULL, ICON_NONE);
const char *text = (RNA_boolean_get(&ptr, "normalize_opacity")) ? IFACE_("Strength") :
IFACE_("Opacity Factor");
uiItemR(layout, &ptr, "hardness", 0, text, ICON_NONE);
IFACE_("Opacity Factor");
uiItemR(layout, &ptr, "factor", 0, text, ICON_NONE);
}
gpencil_modifier_panel_end(layout, &ptr);

View File

@@ -136,6 +136,11 @@ typedef enum eGPUMaterialStatus {
GPU_MAT_SUCCESS,
} eGPUMaterialStatus;
typedef enum eGPUVolumeDefaultValue {
GPU_VOLUME_DEFAULT_0,
GPU_VOLUME_DEFAULT_1,
} eGPUVolumeDefaultValue;
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
@@ -149,7 +154,9 @@ GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
eGPUSamplerState sampler_state);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat,
const char *name,
eGPUVolumeDefaultValue default_value);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
@@ -242,6 +249,7 @@ typedef struct GPUMaterialTexture {
typedef struct GPUMaterialVolumeGrid {
struct GPUMaterialVolumeGrid *next, *prev;
char *name;
eGPUVolumeDefaultValue default_value;
char sampler_name[32]; /* Name of sampler in GLSL. */
char transform_name[32]; /* Name of 4x4 matrix in GLSL. */
int users;

View File

@@ -333,13 +333,15 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
return tex;
}
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph, const char *name)
static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph,
const char *name,
eGPUVolumeDefaultValue default_value)
{
/* Find existing volume grid. */
int num_grids = 0;
GPUMaterialVolumeGrid *grid = graph->volume_grids.first;
for (; grid; grid = grid->next) {
if (STREQ(grid->name, name)) {
if (STREQ(grid->name, name) && grid->default_value == default_value) {
break;
}
num_grids++;
@@ -349,6 +351,7 @@ static GPUMaterialVolumeGrid *gpu_node_graph_add_volume_grid(GPUNodeGraph *graph
if (grid == NULL) {
grid = MEM_callocN(sizeof(*grid), __func__);
grid->name = BLI_strdup(name);
grid->default_value = default_value;
BLI_snprintf(grid->sampler_name, sizeof(grid->sampler_name), "vsamp%d", num_grids);
BLI_snprintf(grid->transform_name, sizeof(grid->transform_name), "vtfm%d", num_grids);
BLI_addtail(&graph->volume_grids, grid);
@@ -442,18 +445,21 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
return link;
}
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name)
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat,
const char *name,
eGPUVolumeDefaultValue default_value)
{
/* NOTE: this could be optimized by automatically merging duplicate
* lookups of the same attribute. */
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_VOLUME_GRID;
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name);
link->volume_grid = gpu_node_graph_add_volume_grid(graph, name, default_value);
GPUNodeLink *transform_link = gpu_node_link_create();
transform_link->link_type = GPU_NODE_LINK_VOLUME_GRID_TRANSFORM;
transform_link->volume_grid = link->volume_grid;
transform_link->volume_grid->users++;
/* Two special cases, where we adjust the output values of smoke grids to
* bring the into standard range without having to modify the grid values. */

View File

@@ -271,7 +271,7 @@ void BCAnimationSampler::find_depending_animated(std::set<Object *> &animated_ob
std::set<Object *>::iterator it;
for (it = candidates.begin(); it != candidates.end(); ++it) {
Object *cob = *it;
ListBase *conlist = ED_object_constraint_list_from_context(cob);
ListBase *conlist = ED_object_constraint_active_list(cob);
if (is_animated_by_constraint(cob, conlist, animated_objects)) {
animated_objects.insert(cob);
candidates.erase(cob);

View File

@@ -43,6 +43,8 @@
# include "BLI_iterator.h"
# include "BLI_math.h"
# include "RNA_access.h"
# include "BKE_duplilist.h"
# include "BKE_object.h"
# include "BKE_scene.h"
@@ -461,14 +463,19 @@ static PointerRNA rna_Depsgraph_scene_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene = DEG_get_input_scene(depsgraph);
return rna_pointer_inherit_refine(ptr, &RNA_Scene, scene);
PointerRNA newptr;
RNA_pointer_create(&scene->id, &RNA_Scene, scene, &newptr);
return newptr;
}
static PointerRNA rna_Depsgraph_view_layer_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene = DEG_get_input_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer);
PointerRNA newptr;
RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer, &newptr);
return newptr;
}
static PointerRNA rna_Depsgraph_scene_eval_get(PointerRNA *ptr)
@@ -476,13 +483,19 @@ static PointerRNA rna_Depsgraph_scene_eval_get(PointerRNA *ptr)
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
return rna_pointer_inherit_refine(ptr, &RNA_Scene, scene_eval);
PointerRNA newptr;
RNA_pointer_create(&scene_eval->id, &RNA_Scene, scene_eval, &newptr);
return newptr;
}
static PointerRNA rna_Depsgraph_view_layer_eval_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
return rna_pointer_inherit_refine(ptr, &RNA_ViewLayer, view_layer_eval);
PointerRNA newptr;
RNA_pointer_create(&scene_eval->id, &RNA_ViewLayer, view_layer_eval, &newptr);
return newptr;
}
#else

View File

@@ -1187,9 +1187,12 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop
* This helps a lot in library override case, especially to detect inserted items in collections.
*/
if (!no_prop_name && (is_valid_for_diffing || do_force_name)) {
PropertyRNA *nameprop_a = RNA_struct_name_property(propptr_a->type);
PropertyRNA *nameprop_b = (propptr_b != NULL) ? RNA_struct_name_property(propptr_b->type) :
NULL;
PropertyRNA *nameprop_a = (propptr_a->type != NULL) ?
RNA_struct_name_property(propptr_a->type) :
NULL;
PropertyRNA *nameprop_b = (propptr_b != NULL && propptr_b->type != NULL) ?
RNA_struct_name_property(propptr_b->type) :
NULL;
int propname_a_len = 0, propname_b_len = 0;
char *propname_a = NULL;

View File

@@ -558,6 +558,12 @@ static void rna_WindowManager_print_undo_steps(wmWindowManager *wm)
BKE_undosys_print(wm->undo_stack);
}
static void rna_WindowManager_tag_script_reload(void)
{
WM_script_tag_reload();
WM_main_add_notifier(NC_WINDOW, NULL);
}
static PointerRNA rna_WindoManager_operator_properties_last(const char *idname)
{
wmOperatorType *ot = WM_operatortype_find(idname, true);
@@ -913,6 +919,12 @@ void RNA_api_wm(StructRNA *srna)
RNA_def_function(srna, "print_undo_steps", "rna_WindowManager_print_undo_steps");
/* Used by (#SCRIPT_OT_reload). */
func = RNA_def_function(srna, "tag_script_reload", "rna_WindowManager_tag_script_reload");
RNA_def_function_ui_description(
func, "Tag for refreshing the interface after scripts have been reloaded");
RNA_def_function_flag(func, FUNC_NO_SELF);
parm = RNA_def_property(srna, "is_interface_locked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_ui_text(
parm,

View File

@@ -258,6 +258,10 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, &ptr, "use_collapse_triangulate", 0, NULL, ICON_NONE);
modifier_vgroup_ui(layout, &ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
sub = uiLayoutRow(layout, true);
bool has_vertex_group = RNA_string_length(&ptr, "vertex_group") != 0;
uiLayoutSetActive(sub, has_vertex_group);
uiItemR(sub, &ptr, "vertex_group_factor", 0, NULL, ICON_NONE);
}
else if (decimate_type == MOD_DECIM_MODE_UNSUBDIV) {
uiItemR(layout, &ptr, "iterations", 0, NULL, ICON_NONE);

View File

@@ -313,10 +313,19 @@ static void deformVerts_do(HookModifierData *hmd,
MOD_get_vgroup(ob, mesh, hmd->name, &dvert, &hd.defgrp_index);
int cd_dvert_offset = -1;
if ((em != NULL) && (hd.defgrp_index != -1)) {
cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
if (cd_dvert_offset == -1) {
hd.defgrp_index = -1;
if (hd.defgrp_index != -1) {
/* Edit-mesh. */
if (em != NULL) {
cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT);
if (cd_dvert_offset == -1) {
hd.defgrp_index = -1;
}
}
else {
/* Regular mesh. */
if (dvert == NULL) {
hd.defgrp_index = -1;
}
}
}

View File

@@ -280,8 +280,9 @@ static void warpModifier_do(WarpModifierData *wmd,
/* skip if no vert group found */
if (defgrp_index != -1) {
dv = &dvert[i];
weight = invert_vgroup ? 1.0f - BKE_defvert_find_weight(dv, defgrp_index) * strength :
BKE_defvert_find_weight(dv, defgrp_index) * strength;
weight = (invert_vgroup ? (1.0f - BKE_defvert_find_weight(dv, defgrp_index)) :
BKE_defvert_find_weight(dv, defgrp_index)) *
strength;
if (weight <= 0.0f) {
continue;
}

View File

@@ -249,9 +249,10 @@ void weightvg_do_mask(const ModifierEvalContext *ctx,
/* For each weight (vertex), make the mix between org and new weights. */
for (i = 0; i < num; i++) {
int idx = indices ? indices[i] : i;
const float f = invert_vgroup_mask ?
1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact :
BKE_defvert_find_weight(&dvert[idx], ref_didx) * fact;
const float f = (invert_vgroup_mask ?
(1.0f - BKE_defvert_find_weight(&dvert[idx], ref_didx)) :
BKE_defvert_find_weight(&dvert[idx], ref_didx)) *
fact;
org_w[i] = (new_w[i] * f) + (org_w[i] * (1.0f - f));
/* If that vertex is not in ref vgroup, assume null factor, and hence do nothing! */
}

View File

@@ -44,13 +44,13 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
if (GPU_material_is_volume_shader(mat)) {
if (out[0].hasoutput) {
out[0].link = GPU_volume_grid(mat, attr->name);
out[0].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
}
if (out[1].hasoutput) {
out[1].link = GPU_volume_grid(mat, attr->name);
out[1].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
}
if (out[2].hasoutput) {
out[2].link = GPU_volume_grid(mat, attr->name);
out[2].link = GPU_volume_grid(mat, attr->name, GPU_VOLUME_DEFAULT_0);
}
return 1;

View File

@@ -34,16 +34,16 @@ static int node_shader_gpu_volume_info(GPUMaterial *mat,
GPUNodeStack *out)
{
if (out[0].hasoutput) {
out[0].link = GPU_volume_grid(mat, "color");
out[0].link = GPU_volume_grid(mat, "color", GPU_VOLUME_DEFAULT_0);
}
if (out[1].hasoutput) {
out[1].link = GPU_volume_grid(mat, "density");
out[1].link = GPU_volume_grid(mat, "density", GPU_VOLUME_DEFAULT_0);
}
if (out[2].hasoutput) {
out[2].link = GPU_volume_grid(mat, "flame");
out[2].link = GPU_volume_grid(mat, "flame", GPU_VOLUME_DEFAULT_0);
}
if (out[3].hasoutput) {
out[3].link = GPU_volume_grid(mat, "temperature");
out[3].link = GPU_volume_grid(mat, "temperature", GPU_VOLUME_DEFAULT_0);
}
return true;

View File

@@ -78,13 +78,13 @@ static int node_shader_gpu_volume_principled(GPUMaterial *mat,
}
if (STREQ(sock->name, "Density Attribute")) {
density = GPU_volume_grid(mat, attribute_name);
density = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
}
else if (STREQ(sock->name, "Color Attribute")) {
color = GPU_volume_grid(mat, attribute_name);
color = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_1);
}
else if (use_blackbody && STREQ(sock->name, "Temperature Attribute")) {
temperature = GPU_volume_grid(mat, attribute_name);
temperature = GPU_volume_grid(mat, attribute_name, GPU_VOLUME_DEFAULT_0);
}
}

View File

@@ -93,13 +93,13 @@ static const EnumPropertyItem property_flag_override_items[] = {
"LIBRARY_OVERRIDABLE",
0,
"Library Overridable",
"Allow that property to be overridable from library linked data-blocks"},
"Make that property editable in library overrides of linked data-blocks"},
{0, NULL, 0, NULL, NULL},
};
#define BPY_PROPDEF_OPTIONS_OVERRIDE_DOC \
" :arg options: Enumerator in ['LIBRARY_OVERRIDE'].\n" \
" :type options: set\n"
" :arg override: Enumerator in ['LIBRARY_OVERRIDABLE'].\n" \
" :type override: set\n"
static const EnumPropertyItem property_flag_override_collection_items[] = {
{PROPOVERRIDE_OVERRIDABLE_LIBRARY,
@@ -116,8 +116,8 @@ static const EnumPropertyItem property_flag_override_collection_items[] = {
};
#define BPY_PROPDEF_OPTIONS_OVERRIDE_COLLECTION_DOC \
" :arg options: Enumerator in ['LIBRARY_OVERRIDE', 'NO_PROPERTY_NAME'].\n" \
" :type options: set\n"
" :arg override: Enumerator in ['LIBRARY_OVERRIDABLE', 'NO_PROPERTY_NAME'].\n" \
" :type override: set\n"
/* subtypes */
/* XXX Keep in sync with rna_rna.c's rna_enum_property_subtype_items ???