Merge remote-tracking branch 'origin' into temp_bmesh_multires

This commit is contained in:
Joseph Eagar 2020-11-03 22:41:57 -08:00
commit 6d704d57ad
149 changed files with 1966 additions and 478 deletions

View File

@ -1678,10 +1678,14 @@ if(WITH_COMPILER_SHORT_FILE_MACRO)
endif()
endif()
if(WITH_COMPILER_SHORT_FILE_MACRO)
path_ensure_trailing_slash(_src_dir "${CMAKE_SOURCE_DIR}")
path_ensure_trailing_slash(_bin_dir "${CMAKE_BINARY_DIR}")
set(PLATFORM_CFLAGS "${PLATFORM_CFLAGS} \
-fmacro-prefix-map='${CMAKE_SOURCE_DIR}/'='' \
-fmacro-prefix-map='${CMAKE_BINARY_DIR}/'=''"
-fmacro-prefix-map=\"${_src_dir}\"=\"\" \
-fmacro-prefix-map=\"${_bin_dir}\"=\"\""
)
unset(_src_dir)
unset(_bin_dir)
endif()
else()
message_first_run(WARNING

View File

@ -60,6 +60,19 @@ function(list_assert_duplicates
unset(_len_after)
endfunction()
# Adds a native path separator to the end of the path:
#
# - 'example' -> 'example/'
# - '/example///' -> '/example/'
#
macro(path_ensure_trailing_slash
path_new path_input
)
file(TO_NATIVE_PATH "/" _path_sep)
string(REGEX REPLACE "[${_path_sep}]+$" "" ${path_new} ${path_input})
set(${path_new} "${${path_new}}${_path_sep}")
unset(_path_sep)
endmacro()
# foo_bar.spam --> foo_barMySuffix.spam
macro(file_suffix

View File

@ -60,6 +60,17 @@ if(WITH_OPENAL)
endif()
endif()
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
)
if(NOT JACK_FRAMEWORK)
set(WITH_JACK OFF)
else()
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
endif()
endif()
if(NOT DEFINED LIBDIR)
set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin)
# Prefer lib directory paths
@ -94,17 +105,6 @@ if(WITH_OPENSUBDIV)
find_package(OpenSubdiv)
endif()
if(WITH_JACK)
find_library(JACK_FRAMEWORK
NAMES jackmp
)
if(NOT JACK_FRAMEWORK)
set(WITH_JACK OFF)
else()
set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers)
endif()
endif()
if(WITH_CODEC_SNDFILE)
find_package(SndFile)
find_library(_sndfile_FLAC_LIBRARY NAMES flac HINTS ${LIBDIR}/sndfile/lib)

View File

@ -30,7 +30,9 @@ static inline IndexInt indexUFace(const Vec3 &pos, const MACGrid &ref)
{
const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
const IndexInt index = f.x * ref.getStrideX() + c.y * ref.getStrideY() + c.z * ref.getStrideZ();
assertDeb(ref.isInBounds(index), "Grid index out of bounds");
assertDeb(ref.isInBounds(index),
"U face index out of bounds for particle position [" << pos.x << ", " << pos.y << ", "
<< pos.z << "]");
return (ref.isInBounds(index)) ? index : -1;
}
@ -38,7 +40,9 @@ static inline IndexInt indexVFace(const Vec3 &pos, const MACGrid &ref)
{
const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
const IndexInt index = c.x * ref.getStrideX() + f.y * ref.getStrideY() + c.z * ref.getStrideZ();
assertDeb(ref.isInBounds(index), "Grid index out of bounds");
assertDeb(ref.isInBounds(index),
"V face index out of bounds for particle position [" << pos.x << ", " << pos.y << ", "
<< pos.z << "]");
return (ref.isInBounds(index)) ? index : -1;
}
@ -46,7 +50,9 @@ static inline IndexInt indexWFace(const Vec3 &pos, const MACGrid &ref)
{
const Vec3i f = toVec3i(pos), c = toVec3i(pos - 0.5);
const IndexInt index = c.x * ref.getStrideX() + c.y * ref.getStrideY() + f.z * ref.getStrideZ();
assertDeb(ref.isInBounds(index), "Grid index out of bounds");
assertDeb(ref.isInBounds(index),
"W face index out of bounds for particle position [" << pos.x << ", " << pos.y << ", "
<< pos.z << "]");
return (ref.isInBounds(index)) ? index : -1;
}
@ -57,7 +63,7 @@ static inline IndexInt indexOffset(
const IndexInt dY[2] = {0, ref.getStrideY()};
const IndexInt dZ[2] = {0, ref.getStrideZ()};
const IndexInt index = gidx + dX[i] + dY[j] + dZ[k];
assertDeb(ref.isInBounds(index), "Grid index out of bounds");
assertDeb(ref.isInBounds(index), "Offset index " << index << " is out of bounds");
return (ref.isInBounds(index)) ? index : -1;
}
@ -271,18 +277,18 @@ void apicMapPartsToMAC(const FlagGrid &flags,
const int boundaryWidth = 0)
{
// affine map: let's assume that the particle mass is constant, 1.0
if (!mass) {
MACGrid tmpmass(vel.getParent());
mass = &tmpmass;
}
MACGrid tmpmass(vel.getParent());
mass->clear();
tmpmass.clear();
vel.clear();
knApicMapLinearVec3ToMACGrid(
parts, *mass, vel, partVel, cpx, cpy, cpz, ptype, exclude, boundaryWidth);
mass->stomp(VECTOR_EPSILON);
vel.safeDivide(*mass);
parts, tmpmass, vel, partVel, cpx, cpy, cpz, ptype, exclude, boundaryWidth);
tmpmass.stomp(VECTOR_EPSILON);
vel.safeDivide(tmpmass);
if (mass)
(*mass).swap(tmpmass);
}
static PyObject *_W_0(PyObject *_self, PyObject *_linargs, PyObject *_kwds)
{

View File

@ -352,7 +352,7 @@ static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CDa
/* check allocation */
if ((hair->curve_keys.size() != num_keys) || (hair->num_curves() != num_curves)) {
VLOG(1) << "Allocation failed, clearing data";
hair->clear();
hair->clear(true);
}
}
@ -817,10 +817,7 @@ void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motio
}
#endif
void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
BL::Object b_ob,
Hair *hair,
const vector<Shader *> &used_shaders)
void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair)
{
/* Compares curve_keys rather than strands in order to handle quick hair
* adjustments in dynamic BVH - other methods could probably do this better. */
@ -829,8 +826,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph,
oldcurve_keys.steal_data(hair->curve_keys);
oldcurve_radius.steal_data(hair->curve_radius);
hair->clear();
hair->used_shaders = used_shaders;
hair->clear(true);
if (view_layer.use_hair) {
if (b_ob.type() == BL::Object::type_HAIR) {

View File

@ -138,6 +138,9 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
geom->name = ustring(b_ob_data.name().c_str());
/* Store the shaders immediately for the object attribute code. */
geom->used_shaders = used_shaders;
auto sync_func = [=]() mutable {
if (progress.get_cancel())
return;
@ -146,15 +149,15 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (geom_type == Geometry::HAIR) {
Hair *hair = static_cast<Hair *>(geom);
sync_hair(b_depsgraph, b_ob, hair, used_shaders);
sync_hair(b_depsgraph, b_ob, hair);
}
else if (geom_type == Geometry::VOLUME) {
Volume *volume = static_cast<Volume *>(geom);
sync_volume(b_ob, volume, used_shaders);
sync_volume(b_ob, volume);
}
else {
Mesh *mesh = static_cast<Mesh *>(geom);
sync_mesh(b_depsgraph, b_ob, mesh, used_shaders);
sync_mesh(b_depsgraph, b_ob, mesh);
}
};

View File

@ -1023,10 +1023,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh)
}
}
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph,
BL::Object b_ob,
Mesh *mesh,
const vector<Shader *> &used_shaders)
void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh)
{
array<int> oldtriangles;
array<Mesh::SubdFace> oldsubd_faces;
@ -1035,8 +1032,7 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph,
oldsubd_faces.steal_data(mesh->subd_faces);
oldsubd_face_corners.steal_data(mesh->subd_face_corners);
mesh->clear();
mesh->used_shaders = used_shaders;
mesh->clear(true);
mesh->subdivision_type = Mesh::SUBDIVISION_NONE;

View File

@ -234,6 +234,10 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* special case not tracked by object update flags */
if (sync_object_attributes(b_instance, object)) {
object_updated = true;
}
/* holdout */
if (use_holdout != object->use_holdout) {
object->use_holdout = use_holdout;
@ -343,6 +347,132 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
return object;
}
/* This function mirrors drw_uniform_property_lookup in draw_instance_data.cpp */
static bool lookup_property(BL::ID b_id, const string &name, float4 *r_value)
{
PointerRNA ptr;
PropertyRNA *prop;
if (!RNA_path_resolve(&b_id.ptr, name.c_str(), &ptr, &prop)) {
return false;
}
PropertyType type = RNA_property_type(prop);
int arraylen = RNA_property_array_length(&ptr, prop);
if (arraylen == 0) {
float value;
if (type == PROP_FLOAT)
value = RNA_property_float_get(&ptr, prop);
else if (type == PROP_INT)
value = RNA_property_int_get(&ptr, prop);
else
return false;
*r_value = make_float4(value, value, value, 1.0f);
return true;
}
else if (type == PROP_FLOAT && arraylen <= 4) {
*r_value = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
RNA_property_float_get_array(&ptr, prop, &r_value->x);
return true;
}
return false;
}
/* This function mirrors drw_uniform_attribute_lookup in draw_instance_data.cpp */
static float4 lookup_instance_property(BL::DepsgraphObjectInstance &b_instance,
const string &name,
bool use_instancer)
{
string idprop_name = string_printf("[\"%s\"]", name.c_str());
float4 value;
/* If requesting instance data, check the parent particle system and object. */
if (use_instancer && b_instance.is_instance()) {
BL::ParticleSystem b_psys = b_instance.particle_system();
if (b_psys) {
if (lookup_property(b_psys.settings(), idprop_name, &value) ||
lookup_property(b_psys.settings(), name, &value)) {
return value;
}
}
if (lookup_property(b_instance.parent(), idprop_name, &value) ||
lookup_property(b_instance.parent(), name, &value)) {
return value;
}
}
/* Check the object and mesh. */
BL::Object b_ob = b_instance.object();
BL::ID b_data = b_ob.data();
if (lookup_property(b_ob, idprop_name, &value) || lookup_property(b_ob, name, &value) ||
lookup_property(b_data, idprop_name, &value) || lookup_property(b_data, name, &value)) {
return value;
}
return make_float4(0.0f);
}
bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object)
{
/* Find which attributes are needed. */
AttributeRequestSet requests = object->geometry->needed_attributes();
/* Delete attributes that became unnecessary. */
vector<ParamValue> &attributes = object->attributes;
bool changed = false;
for (int i = attributes.size() - 1; i >= 0; i--) {
if (!requests.find(attributes[i].name())) {
attributes.erase(attributes.begin() + i);
changed = true;
}
}
/* Update attribute values. */
foreach (AttributeRequest &req, requests.requests) {
ustring name = req.name;
std::string real_name;
BlenderAttributeType type = blender_attribute_name_split_type(name, &real_name);
if (type != BL::ShaderNodeAttribute::attribute_type_GEOMETRY) {
bool use_instancer = (type == BL::ShaderNodeAttribute::attribute_type_INSTANCER);
float4 value = lookup_instance_property(b_instance, real_name, use_instancer);
/* Try finding the existing attribute value. */
ParamValue *param = NULL;
for (size_t i = 0; i < attributes.size(); i++) {
if (attributes[i].name() == name) {
param = &attributes[i];
break;
}
}
/* Replace or add the value. */
ParamValue new_param(name, TypeDesc::TypeFloat4, 1, &value);
assert(new_param.datasize() == sizeof(value));
if (!param) {
changed = true;
attributes.push_back(new_param);
}
else if (memcmp(param->data(), &value, sizeof(value)) != 0) {
changed = true;
*param = new_param;
}
}
}
return changed;
}
/* Object Loop */
void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,

View File

@ -97,6 +97,53 @@ static ImageAlphaType get_image_alpha_type(BL::Image &b_image)
return (ImageAlphaType)validate_enum_value(value, IMAGE_ALPHA_NUM_TYPES, IMAGE_ALPHA_AUTO);
}
/* Attribute name translation utilities */
/* Since Eevee needs to know whether the attribute is uniform or varying
* at the time it compiles the shader for the material, Blender had to
* introduce different namespaces (types) in its attribute node. However,
* Cycles already has object attributes that form a uniform namespace with
* the more common varying attributes. Without completely reworking the
* attribute handling in Cycles to introduce separate namespaces (this could
* be especially hard for OSL which directly uses the name string), the
* space identifier has to be added to the attribute name as a prefix.
*
* The prefixes include a control character to ensure the user specified
* name can't accidentally include a special prefix.
*/
static const string_view object_attr_prefix("\x01object:");
static const string_view instancer_attr_prefix("\x01instancer:");
static ustring blender_attribute_name_add_type(const string &name, BlenderAttributeType type)
{
switch (type) {
case BL::ShaderNodeAttribute::attribute_type_OBJECT:
return ustring::concat(object_attr_prefix, name);
case BL::ShaderNodeAttribute::attribute_type_INSTANCER:
return ustring::concat(instancer_attr_prefix, name);
default:
return ustring(name);
}
}
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name)
{
string_view sname(name);
if (sname.substr(0, object_attr_prefix.size()) == object_attr_prefix) {
*r_real_name = sname.substr(object_attr_prefix.size());
return BL::ShaderNodeAttribute::attribute_type_OBJECT;
}
if (sname.substr(0, instancer_attr_prefix.size()) == instancer_attr_prefix) {
*r_real_name = sname.substr(instancer_attr_prefix.size());
return BL::ShaderNodeAttribute::attribute_type_INSTANCER;
}
return BL::ShaderNodeAttribute::attribute_type_GEOMETRY;
}
/* Graph */
static BL::NodeSocket get_node_output(BL::Node &b_node, const string &name)
@ -369,7 +416,8 @@ static ShaderNode *add_node(Scene *scene,
else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = b_attr_node.attribute_name();
attr->attribute = blender_attribute_name_add_type(b_attr_node.attribute_name(),
b_attr_node.attribute_type());
node = attr;
}
else if (b_node.is_a(&RNA_ShaderNodeBackground)) {

View File

@ -149,21 +149,17 @@ class BlenderSync {
bool *use_portal,
TaskPool *geom_task_pool);
bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object);
/* Volume */
void sync_volume(BL::Object &b_ob, Volume *volume, const vector<Shader *> &used_shaders);
void sync_volume(BL::Object &b_ob, Volume *volume);
/* Mesh */
void sync_mesh(BL::Depsgraph b_depsgraph,
BL::Object b_ob,
Mesh *mesh,
const vector<Shader *> &used_shaders);
void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh);
void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step);
/* Hair */
void sync_hair(BL::Depsgraph b_depsgraph,
BL::Object b_ob,
Hair *hair,
const vector<Shader *> &used_shaders);
void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair);
void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step);
void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0);
void sync_particle_hair(

View File

@ -40,6 +40,9 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile);
CCL_NAMESPACE_BEGIN
typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType;
BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name);
void python_thread_state_save(void **python_thread_state);
void python_thread_state_restore(void **python_thread_state);

View File

@ -320,14 +320,11 @@ static vector<int> get_voxel_image_slots(Mesh *mesh)
return slots;
}
void BlenderSync::sync_volume(BL::Object &b_ob,
Volume *volume,
const vector<Shader *> &used_shaders)
void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume)
{
vector<int> old_voxel_slots = get_voxel_image_slots(volume);
volume->clear();
volume->used_shaders = used_shaders;
volume->clear(true);
if (view_layer.use_volumes) {
if (b_ob.type() == BL::Object::type_VOLUME) {

View File

@ -37,6 +37,9 @@ BVHOptiX::BVHOptiX(const BVHParams &params_,
const vector<Object *> &objects_)
: BVH(params_, geometry_, objects_)
{
optix_handle = 0;
optix_data_handle = 0;
do_refit = false;
}
BVHOptiX::~BVHOptiX()
@ -216,8 +219,7 @@ void BVHOptiX::pack_nodes(const BVHNode *)
void BVHOptiX::refit_nodes()
{
// TODO(pmours): Implement?
VLOG(1) << "Refit is not yet implemented for OptiX BVH.";
do_refit = true;
}
BVHNode *BVHOptiX::widen_children_nodes(const BVHNode *)

View File

@ -33,6 +33,10 @@ class BVHOptiX : public BVH {
friend class BVH;
public:
uint64_t optix_handle;
uint64_t optix_data_handle;
bool do_refit;
BVHOptiX(const BVHParams &params,
const vector<Geometry *> &geometry,
const vector<Object *> &objects);

View File

@ -18,6 +18,7 @@
#ifdef WITH_OPTIX
# include "bvh/bvh.h"
# include "bvh/bvh_optix.h"
# include "device/cuda/device_cuda.h"
# include "device/device_denoising.h"
# include "device/device_intern.h"
@ -1078,23 +1079,23 @@ class OptiXDevice : public CUDADevice {
bool build_optix_bvh(const OptixBuildInput &build_input,
uint16_t num_motion_steps,
OptixTraversableHandle &out_handle)
OptixTraversableHandle &out_handle,
CUdeviceptr &out_data,
OptixBuildOperation operation)
{
out_handle = 0;
const CUDAContextScope scope(cuContext);
// Compute memory usage
OptixAccelBufferSizes sizes = {};
OptixAccelBuildOptions options;
options.operation = OPTIX_BUILD_OPERATION_BUILD;
options.operation = operation;
if (background) {
// Prefer best performance and lowest memory consumption in background
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE | OPTIX_BUILD_FLAG_ALLOW_COMPACTION;
}
else {
// Prefer fast updates in viewport
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD;
options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_BUILD | OPTIX_BUILD_FLAG_ALLOW_UPDATE;
}
options.motionOptions.numKeys = num_motion_steps;
@ -1119,8 +1120,10 @@ class OptiXDevice : public CUDADevice {
move_textures_to_host(size - free, false);
}
CUdeviceptr out_data = 0;
check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes));
if (operation == OPTIX_BUILD_OPERATION_BUILD) {
check_result_cuda_ret(cuMemAlloc(&out_data, sizes.outputSizeInBytes));
}
as_mem.push_back(out_data);
// Finally build the acceleration structure
@ -1187,10 +1190,21 @@ class OptiXDevice : public CUDADevice {
unordered_map<Geometry *, OptixTraversableHandle> geometry;
geometry.reserve(bvh->geometry.size());
// Free all previous acceleration structures
for (CUdeviceptr mem : as_mem) {
cuMemFree(mem);
// Free all previous acceleration structures which can not be refit
std::set<CUdeviceptr> refit_mem;
for (Geometry *geom : bvh->geometry) {
if (static_cast<BVHOptiX *>(geom->bvh)->do_refit) {
refit_mem.insert(static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle);
}
}
for (CUdeviceptr mem : as_mem) {
if (refit_mem.find(mem) == refit_mem.end()) {
cuMemFree(mem);
}
}
as_mem.clear();
// Build bottom level acceleration structures (BLAS)
@ -1201,6 +1215,21 @@ class OptiXDevice : public CUDADevice {
if (geometry.find(geom) != geometry.end())
continue;
OptixTraversableHandle handle;
OptixBuildOperation operation;
CUdeviceptr out_data;
// Refit is only possible in viewport for now.
if (static_cast<BVHOptiX *>(geom->bvh)->do_refit && !background) {
out_data = static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle;
handle = static_cast<BVHOptiX *>(geom->bvh)->optix_handle;
operation = OPTIX_BUILD_OPERATION_UPDATE;
}
else {
out_data = 0;
handle = 0;
operation = OPTIX_BUILD_OPERATION_BUILD;
}
if (geom->type == Geometry::HAIR) {
// Build BLAS for curve primitives
Hair *const hair = static_cast<Hair *const>(ob->geometry);
@ -1364,9 +1393,11 @@ class OptiXDevice : public CUDADevice {
}
// Allocate memory for new BLAS and build it
OptixTraversableHandle handle;
if (build_optix_bvh(build_input, num_motion_steps, handle)) {
if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) {
geometry.insert({ob->geometry, handle});
static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data;
static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle;
static_cast<BVHOptiX *>(geom->bvh)->do_refit = false;
}
else {
return false;
@ -1436,9 +1467,11 @@ class OptiXDevice : public CUDADevice {
build_input.triangleArray.primitiveIndexOffset = mesh->optix_prim_offset;
// Allocate memory for new BLAS and build it
OptixTraversableHandle handle;
if (build_optix_bvh(build_input, num_motion_steps, handle)) {
if (build_optix_bvh(build_input, num_motion_steps, handle, out_data, operation)) {
geometry.insert({ob->geometry, handle});
static_cast<BVHOptiX *>(geom->bvh)->optix_data_handle = out_data;
static_cast<BVHOptiX *>(geom->bvh)->optix_handle = handle;
static_cast<BVHOptiX *>(geom->bvh)->do_refit = false;
}
else {
return false;
@ -1612,7 +1645,9 @@ class OptiXDevice : public CUDADevice {
build_input.instanceArray.instances = instances.device_pointer;
build_input.instanceArray.numInstances = num_instances;
return build_optix_bvh(build_input, 0, tlas_handle);
CUdeviceptr out_data = 0;
tlas_handle = 0;
return build_optix_bvh(build_input, 0, tlas_handle, out_data, OPTIX_BUILD_OPERATION_BUILD);
}
void const_copy_to(const char *name, void *host, size_t size) override

View File

@ -81,9 +81,11 @@ Geometry::~Geometry()
delete bvh;
}
void Geometry::clear()
void Geometry::clear(bool preserve_shaders)
{
used_shaders.clear();
if (!preserve_shaders)
used_shaders.clear();
transform_applied = false;
transform_negative_scaled = false;
transform_normal = transform_identity();

View File

@ -99,7 +99,7 @@ class Geometry : public Node {
virtual ~Geometry();
/* Geometry */
virtual void clear();
virtual void clear(bool preserve_shaders = false);
virtual void compute_bounds() = 0;
virtual void apply_transform(const Transform &tfm, const bool apply_to_motion) = 0;

View File

@ -321,9 +321,9 @@ void Hair::reserve_curves(int numcurves, int numkeys)
attributes.resize(true);
}
void Hair::clear()
void Hair::clear(bool preserve_shaders)
{
Geometry::clear();
Geometry::clear(preserve_shaders);
curve_keys.clear();
curve_radius.clear();

View File

@ -103,7 +103,7 @@ class Hair : public Geometry {
~Hair();
/* Geometry */
void clear() override;
void clear(bool preserve_shaders = false) override;
void resize_curves(int numcurves, int numkeys);
void reserve_curves(int numcurves, int numkeys);

View File

@ -213,9 +213,9 @@ void Mesh::reserve_subd_faces(int numfaces, int num_ngons_, int numcorners)
subd_attributes.resize(true);
}
void Mesh::clear(bool preserve_voxel_data)
void Mesh::clear(bool preserve_shaders, bool preserve_voxel_data)
{
Geometry::clear();
Geometry::clear(preserve_shaders);
/* clear all verts and triangles */
verts.clear();
@ -243,9 +243,9 @@ void Mesh::clear(bool preserve_voxel_data)
patch_table = NULL;
}
void Mesh::clear()
void Mesh::clear(bool preserve_shaders)
{
clear(false);
clear(preserve_shaders, false);
}
void Mesh::add_vertex(float3 P)

View File

@ -174,8 +174,7 @@ class Mesh : public Geometry {
void reserve_mesh(int numverts, int numfaces);
void resize_subd_faces(int numfaces, int num_ngons, int numcorners);
void reserve_subd_faces(int numfaces, int num_ngons, int numcorners);
void clear(bool preserve_voxel_data);
void clear() override;
void clear(bool preserve_shaders = false) override;
void add_vertex(float3 P);
void add_vertex_slow(float3 P);
void add_triangle(int v0, int v1, int v2, int shader, bool smooth);
@ -202,6 +201,9 @@ class Mesh : public Geometry {
void pack_patches(uint *patch_data, uint vert_offset, uint face_offset, uint corner_offset);
void tessellate(DiagSplit *split);
protected:
void clear(bool preserve_shaders, bool preserve_voxel_data);
};
CCL_NAMESPACE_END

View File

@ -56,9 +56,9 @@ Volume::Volume() : Mesh(node_type, Geometry::VOLUME)
object_space = false;
}
void Volume::clear()
void Volume::clear(bool preserve_shaders)
{
Mesh::clear(true);
Mesh::clear(preserve_shaders, true);
}
struct QuadData {

View File

@ -32,7 +32,7 @@ class Volume : public Mesh {
float step_size;
bool object_space;
virtual void clear() override;
virtual void clear(bool preserve_shaders = false) override;
};
CCL_NAMESPACE_END

View File

@ -1137,11 +1137,6 @@ void GHOST_SystemWin32::processPointerEvent(
break;
case WM_POINTERLEAVE:
window->m_tabletInRange = false;
system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
GHOST_kEventCursorMove,
window,
pointerInfo[0].buttonMask,
pointerInfo[0].tabletData));
break;
default:
break;

View File

@ -84,6 +84,7 @@ url_manual_mapping = (
("bpy.types.materialgpencilstyle.use_fill_texture_mix*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-use-fill-texture-mix"),
("bpy.types.rendersettings_simplify_gpencil_shader_fx*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-shader-fx"),
("bpy.types.rendersettings_simplify_gpencil_view_fill*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-view-fill"),
("bpy.types.brush.cloth_constraint_softbody_strength*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-constraint-softbody-strength"),
("bpy.types.brush.elastic_deform_volume_preservation*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-volume-preservation"),
("bpy.types.brushgpencilsettings.fill_simplify_level*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-fill-simplify-level"),
("bpy.types.brushgpencilsettings.use_jitter_pressure*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-use-jitter-pressure"),
@ -99,6 +100,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_gpencil_weight_data_add*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-weight-data-add"),
("bpy.types.view3doverlay.texture_paint_mode_opacity*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-texture-paint-mode-opacity"),
("bpy.types.brush.surface_smooth_shape_preservation*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-shape-preservation"),
("bpy.types.brush.use_cloth_pin_simulation_boundary*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-pin-simulation-boundary"),
("bpy.types.cyclesrendersettings.camera_cull_margin*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-camera-cull-margin"),
("bpy.types.fluiddomainsettings.export_manta_script*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-export-manta-script"),
("bpy.types.fluiddomainsettings.fractions_threshold*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-fractions-threshold"),
@ -139,7 +141,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_gpencil_draw_additive*", "grease_pencil/modes/draw/introduction.html#bpy-types-toolsettings-use-gpencil-draw-additive"),
("bpy.types.toolsettings.use_snap_backface_culling*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-backface-culling"),
("bpy.types.toolsettings.use_transform_data_origin*", "scene_layout/object/tools/tool_settings.html#bpy-types-toolsettings-use-transform-data-origin"),
("bpy.types.view3doverlay.sculpt_mode_mask_opacity*", "sculpt_paint/sculpting/hide_mask.html#bpy-types-view3doverlay-sculpt-mode-mask-opacity"),
("bpy.types.view3doverlay.sculpt_mode_mask_opacity*", "sculpt_paint/sculpting/editing/mask.html#bpy-types-view3doverlay-sculpt-mode-mask-opacity"),
("bpy.ops.outliner.collection_indirect_only_clear*", "render/layers/layers.html#bpy-ops-outliner-collection-indirect-only-clear"),
("bpy.types.cyclesrendersettings.max_subdivisions*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-max-subdivisions"),
("bpy.types.fluiddomainsettings.cache_data_format*", "physics/fluid/type/domain/cache.html#bpy-types-fluiddomainsettings-cache-data-format"),
@ -175,6 +177,7 @@ url_manual_mapping = (
("bpy.ops.sequencer.deinterlace_selected_movies*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-deinterlace-selected-movies"),
("bpy.types.brush.surface_smooth_current_vertex*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-current-vertex"),
("bpy.types.brush.use_multiplane_scrape_dynamic*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-use-multiplane-scrape-dynamic"),
("bpy.types.brushgpencilsettings.fill_direction*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-fill-direction"),
("bpy.types.brushgpencilsettings.fill_draw_mode*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-fill-draw-mode"),
("bpy.types.brushgpencilsettings.fill_threshold*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-fill-threshold"),
("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
@ -233,6 +236,7 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.velocity_normal*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-velocity-normal"),
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/grease_pencil_shader.html#bpy-types-materialgpencilstyle-stroke-style"),
("bpy.types.rendersettings.use_file_extension*", "render/output/settings.html#bpy-types-rendersettings-use-file-extension"),
("bpy.types.sculpt.constant_detail_resolution*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-constant-detail-resolution"),
("bpy.types.spaceview3d.transform_orientation*", "editors/3dview/controls/orientation.html#bpy-types-spaceview3d-transform-orientation"),
("bpy.types.spaceview3d.use_local_collections*", "editors/3dview/sidebar.html#bpy-types-spaceview3d-use-local-collections"),
("bpy.ops.object.constraint_add_with_targets*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraint-add-with-targets"),
@ -264,8 +268,8 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_normalize_all*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-normalize-all"),
("bpy.ops.outliner.collection_exclude_clear*", "render/layers/layers.html#bpy-ops-outliner-collection-exclude-clear"),
("bpy.ops.outliner.collection_holdout_clear*", "render/layers/layers.html#bpy-ops-outliner-collection-holdout-clear"),
("bpy.ops.sculpt.face_set_change_visibility*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-face-set-change-visibility"),
("bpy.ops.sculpt.face_sets_randomize_colors*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-face-sets-randomize-colors"),
("bpy.ops.sculpt.face_set_change_visibility*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-set-change-visibility"),
("bpy.ops.sculpt.face_sets_randomize_colors*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-sets-randomize-colors"),
("bpy.types.brush.disconnected_distance_max*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-disconnected-distance-max"),
("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-pen-jitter"),
@ -298,6 +302,7 @@ url_manual_mapping = (
("bpy.ops.object.anim_transforms_to_deltas*", "scene_layout/object/editing/apply.html#bpy-ops-object-anim-transforms-to-deltas"),
("bpy.ops.preferences.app_template_install*", "advanced/app_templates.html#bpy-ops-preferences-app-template-install"),
("bpy.types.actionposemarkers.active_index*", "animation/armatures/properties/pose_library.html#bpy-types-actionposemarkers-active-index"),
("bpy.types.brush.cloth_force_falloff_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-force-falloff-type"),
("bpy.types.brushgpencilsettings.fill_leak*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-fill-leak"),
("bpy.types.brushgpencilsettings.show_fill*", "grease_pencil/modes/draw/tool_settings/brushes/fill_brush.html#bpy-types-brushgpencilsettings-show-fill"),
("bpy.types.brushgpencilsettings.uv_random*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-uv-random"),
@ -364,6 +369,7 @@ url_manual_mapping = (
("bpy.types.armature.rigify_theme_to_add*", "addons/rigging/rigify/metarigs.html#bpy-types-armature-rigify-theme-to-add"),
("bpy.types.brush.pose_smooth_iterations*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-pose-smooth-iterations"),
("bpy.types.brush.use_grab_active_vertex*", "sculpt_paint/sculpting/tools/grab.html#bpy-types-brush-use-grab-active-vertex"),
("bpy.types.brush.use_pose_lock_rotation*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-pose-lock-rotation"),
("bpy.types.compositornodebrightcontrast*", "compositing/types/color/bright_contrast.html#bpy-types-compositornodebrightcontrast"),
("bpy.types.compositornodedoubleedgemask*", "compositing/types/matte/double_edge_mask.html#bpy-types-compositornodedoubleedgemask"),
("bpy.types.fluiddomainsettings.clipping*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-clipping"),
@ -392,11 +398,13 @@ url_manual_mapping = (
("bpy.ops.object.visual_transform_apply*", "scene_layout/object/editing/apply.html#bpy-ops-object-visual-transform-apply"),
("bpy.ops.sequencer.change_effect_input*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-change-effect-input"),
("bpy.types.armature.rigify_colors_lock*", "addons/rigging/rigify/metarigs.html#bpy-types-armature-rigify-colors-lock"),
("bpy.types.brush.boundary_falloff_type*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-falloff-type"),
("bpy.types.brush.texture_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-texture-overlay-alpha"),
("bpy.types.brushgpencilsettings.random*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brushgpencilsettings-random"),
("bpy.types.clothsettings.target_volume*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-target-volume"),
("bpy.types.compositornodebilateralblur*", "compositing/types/filter/bilateral_blur.html#bpy-types-compositornodebilateralblur"),
("bpy.types.compositornodedistancematte*", "compositing/types/matte/distance_key.html#bpy-types-compositornodedistancematte"),
("bpy.types.dopesheet.use_filter_invert*", "editors/graph_editor/channels.html#bpy-types-dopesheet-use-filter-invert"),
("bpy.types.fluiddomainsettings.gravity*", "physics/fluid/type/domain/settings.html#bpy-types-fluiddomainsettings-gravity"),
("bpy.types.fluidflowsettings.flow_type*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-flow-type"),
("bpy.types.fluidflowsettings.subframes*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-subframes"),
@ -409,6 +417,7 @@ url_manual_mapping = (
("bpy.types.rigidbodyconstraint.object1*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-object1"),
("bpy.types.rigidbodyconstraint.object2*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-object2"),
("bpy.types.sceneeevee.volumetric_light*", "render/eevee/render_settings/volumetrics.html#bpy-types-sceneeevee-volumetric-light"),
("bpy.types.sculpt.detail_refine_method*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-refine-method"),
("bpy.types.sculpt.symmetrize_direction*", "sculpt_paint/sculpting/tool_settings/symmetry.html#bpy-types-sculpt-symmetrize-direction"),
("bpy.types.sequenceeditor.show_overlay*", "video_editing/preview/properties.html#bpy-types-sequenceeditor-show-overlay"),
("bpy.types.spacetexteditor.show_margin*", "editors/text_editor.html#bpy-types-spacetexteditor-show-margin"),
@ -423,6 +432,7 @@ url_manual_mapping = (
("bpy.ops.sequencer.change_effect_type*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-change-effect-type"),
("bpy.ops.view3d.localview_remove_from*", "editors/3dview/navigate/local_view.html#bpy-ops-view3d-localview-remove-from"),
("bpy.types.animdata.action_blend_type*", "editors/nla/properties_modifiers.html#bpy-types-animdata-action-blend-type"),
("bpy.types.brush.boundary_deform_type*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-deform-type"),
("bpy.types.brush.cursor_overlay_alpha*", "sculpt_paint/brush/cursor.html#bpy-types-brush-cursor-overlay-alpha"),
("bpy.types.brush.normal_radius_factor*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-normal-radius-factor"),
("bpy.types.brush.topology_rake_factor*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-brush-topology-rake-factor"),
@ -461,6 +471,7 @@ url_manual_mapping = (
("bpy.types.armature.layers_protected*", "animation/armatures/properties/skeleton.html#bpy-types-armature-layers-protected"),
("bpy.types.brush.crease_pinch_factor*", "sculpt_paint/sculpting/tools/snake_hook.html#bpy-types-brush-crease-pinch-factor"),
("bpy.types.brush.elastic_deform_type*", "sculpt_paint/sculpting/tools/elastic_deform.html#bpy-types-brush-elastic-deform-type"),
("bpy.types.brush.use_cloth_collision*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-use-cloth-collision"),
("bpy.types.brush.use_primary_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-primary-overlay"),
("bpy.types.camera.passepartout_alpha*", "render/cameras.html#bpy-types-camera-passepartout-alpha"),
("bpy.types.compositornodechromamatte*", "compositing/types/matte/chroma_key.html#bpy-types-compositornodechromamatte"),
@ -481,6 +492,8 @@ url_manual_mapping = (
("bpy.types.rigidbodyconstraint.limit*", "physics/rigid_body/constraints/introduction.html#bpy-types-rigidbodyconstraint-limit"),
("bpy.types.scene.audio_doppler_speed*", "scene_layout/scene/properties.html#bpy-types-scene-audio-doppler-speed"),
("bpy.types.sceneeevee.bokeh_max_size*", "render/eevee/render_settings/depth_of_field.html#bpy-types-sceneeevee-bokeh-max-size"),
("bpy.types.sculpt.detail_type_method*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-type-method"),
("bpy.types.sculpt.use_smooth_shading*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-use-smooth-shading"),
("bpy.types.shadernodebsdfanisotropic*", "render/shader_nodes/shader/anisotropic.html#bpy-types-shadernodebsdfanisotropic"),
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
@ -491,7 +504,7 @@ url_manual_mapping = (
("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"),
("bpy.ops.mesh.customdata_mask_clear*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-mesh-customdata-mask-clear"),
("bpy.ops.mesh.customdata_mask_clear*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-mesh-customdata-mask-clear"),
("bpy.ops.mesh.extrude_vertices_move*", "modeling/meshes/editing/vertex/extrude_vertices.html#bpy-ops-mesh-extrude-vertices-move"),
("bpy.ops.mesh.mod_weighted_strength*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-mesh-mod-weighted-strength"),
("bpy.ops.mesh.quads_convert_to_tris*", "modeling/meshes/editing/face/triangulate_faces.html#bpy-ops-mesh-quads-convert-to-tris"),
@ -557,10 +570,12 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
("bpy.ops.preferences.theme_install*", "editors/preferences/themes.html#bpy-ops-preferences-theme-install"),
("bpy.ops.render.play-rendered-anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sequencer.reassign_inputs*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-reassign-inputs"),
("bpy.ops.view3d.view_center_camera*", "editors/3dview/navigate/camera_view.html#bpy-ops-view3d-view-center-camera"),
("bpy.types.armaturegpencilmodifier*", "grease_pencil/modifiers/deform/armature.html#bpy-types-armaturegpencilmodifier"),
("bpy.types.brush.cloth_deform_type*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-deform-type"),
("bpy.types.brush.cloth_sim_falloff*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-sim-falloff"),
("bpy.types.brush.slide_deform_type*", "sculpt_paint/sculpting/tools/slide_relax.html#bpy-types-brush-slide-deform-type"),
("bpy.types.camera.show_composition*", "render/cameras.html#bpy-types-camera-show-composition"),
("bpy.types.compositornodealphaover*", "compositing/types/color/alpha_over.html#bpy-types-compositornodealphaover"),
@ -583,6 +598,7 @@ url_manual_mapping = (
("bpy.types.gpencilsculptguide.type*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-type"),
("bpy.types.laplaciandeformmodifier*", "modeling/modifiers/deform/laplacian_deform.html#bpy-types-laplaciandeformmodifier"),
("bpy.types.laplaciansmoothmodifier*", "modeling/modifiers/deform/laplacian_smooth.html#bpy-types-laplaciansmoothmodifier"),
("bpy.types.layercollection.exclude*", "editors/outliner/interface.html#bpy-types-layercollection-exclude"),
("bpy.types.layercollection.holdout*", "editors/outliner/interface.html#bpy-types-layercollection-holdout"),
("bpy.types.limitdistanceconstraint*", "animation/constraints/transform/limit_distance.html#bpy-types-limitdistanceconstraint"),
("bpy.types.limitlocationconstraint*", "animation/constraints/transform/limit_location.html#bpy-types-limitlocationconstraint"),
@ -615,8 +631,9 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_move*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-move"),
("bpy.ops.object.vertex_group_sort*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-sort"),
("bpy.ops.object.vertex_parent_set*", "modeling/meshes/editing/vertex/make_vertex_parent.html#bpy-ops-object-vertex-parent-set"),
("bpy.ops.paint.mask_lasso_gesture*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-paint-mask-lasso-gesture"),
("bpy.ops.paint.mask_lasso_gesture*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask-lasso-gesture"),
("bpy.ops.screen.spacedata_cleanup*", "advanced/operators.html#bpy-ops-screen-spacedata-cleanup"),
("bpy.ops.sculpt.detail_flood_fill*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-ops-sculpt-detail-flood-fill"),
("bpy.ops.sequencer.duplicate_move*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-duplicate-move"),
("bpy.ops.uv.average_islands_scale*", "modeling/meshes/uv/editing.html#bpy-ops-uv-average-islands-scale"),
("bpy.types.armature.pose_position*", "animation/armatures/properties/skeleton.html#bpy-types-armature-pose-position"),
@ -675,6 +692,7 @@ url_manual_mapping = (
("bpy.ops.mesh.extrude_edges_move*", "modeling/meshes/editing/edge/extrude_edges.html#bpy-ops-mesh-extrude-edges-move"),
("bpy.ops.mesh.extrude_faces_move*", "modeling/meshes/editing/face/extrude_individual_faces.html#bpy-ops-mesh-extrude-faces-move"),
("bpy.ops.mesh.faces_shade_smooth*", "modeling/meshes/editing/face/shading.html#bpy-ops-mesh-faces-shade-smooth"),
("bpy.ops.mesh.paint_mask_extract*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-mesh-paint-mask-extract"),
("bpy.ops.mesh.subdivide_edgering*", "modeling/meshes/editing/edge/subdivide_edge_ring.html#bpy-ops-mesh-subdivide-edgering"),
("bpy.ops.object.constraints_copy*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-copy"),
("bpy.ops.object.gpencil_modifier*", "grease_pencil/modifiers/index.html#bpy-ops-object-gpencil-modifier"),
@ -688,7 +706,7 @@ url_manual_mapping = (
("bpy.ops.preferences.studiolight*", "editors/preferences/lights.html#bpy-ops-preferences-studiolight"),
("bpy.ops.scene.view_layer_remove*", "render/layers/layers.html#bpy-ops-scene-view-layer-remove"),
("bpy.ops.screen.screen_full_area*", "interface/window_system/areas.html#bpy-ops-screen-screen-full-area"),
("bpy.ops.sculpt.face_sets_create*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-face-sets-create"),
("bpy.ops.sculpt.face_sets_create*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-sets-create"),
("bpy.ops.transform.rotate_normal*", "modeling/meshes/editing/mesh/normals.html#bpy-ops-transform-rotate-normal"),
("bpy.ops.transform.shrink_fatten*", "modeling/meshes/editing/mesh/transform/shrink-fatten.html#bpy-ops-transform-shrink-fatten"),
("bpy.ops.transform.vertex_random*", "modeling/meshes/editing/mesh/transform/randomize.html#bpy-ops-transform-vertex-random"),
@ -696,6 +714,8 @@ url_manual_mapping = (
("bpy.ops.wm.operator_cheat_sheet*", "advanced/operators.html#bpy-ops-wm-operator-cheat-sheet"),
("bpy.ops.wm.previews_batch_clear*", "files/blend/previews.html#bpy-ops-wm-previews-batch-clear"),
("bpy.types.armature.use_mirror_x*", "animation/armatures/bones/tools/tool_settings.html#bpy-types-armature-use-mirror-x"),
("bpy.types.brush.boundary_offset*", "sculpt_paint/sculpting/tools/boundary.html#bpy-types-brush-boundary-offset"),
("bpy.types.brush.cloth_sim_limit*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-sim-limit"),
("bpy.types.brush.use_custom_icon*", "sculpt_paint/brush/brush.html#bpy-types-brush-use-custom-icon"),
("bpy.types.brushtextureslot.mask*", "sculpt_paint/brush/texture.html#bpy-types-brushtextureslot-mask"),
("bpy.types.camerabackgroundimage*", "render/cameras.html#bpy-types-camerabackgroundimage"),
@ -712,6 +732,7 @@ url_manual_mapping = (
("bpy.types.curve.use_path_follow*", "modeling/curves/properties/path_animation.html#bpy-types-curve-use-path-follow"),
("bpy.types.dampedtrackconstraint*", "animation/constraints/tracking/damped_track.html#bpy-types-dampedtrackconstraint"),
("bpy.types.distortednoisetexture*", "render/materials/legacy_textures/types/distorted_noise.html#bpy-types-distortednoisetexture"),
("bpy.types.dopesheet.filter_text*", "editors/graph_editor/channels.html#bpy-types-dopesheet-filter-text"),
("bpy.types.fluideffectorsettings*", "physics/fluid/type/effector.html#bpy-types-fluideffectorsettings"),
("bpy.types.followtrackconstraint*", "animation/constraints/motion_tracking/follow_track.html#bpy-types-followtrackconstraint"),
("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"),
@ -724,6 +745,7 @@ url_manual_mapping = (
("bpy.types.posebone.custom_shape*", "animation/armatures/bones/properties/display.html#bpy-types-posebone-custom-shape"),
("bpy.types.rigifyselectioncolors*", "addons/rigging/rigify/metarigs.html#bpy-types-rigifyselectioncolors"),
("bpy.types.sceneeevee.volumetric*", "render/eevee/render_settings/volumetrics.html#bpy-types-sceneeevee-volumetric"),
("bpy.types.sculpt.detail_percent*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-percent"),
("bpy.types.sculpt.gravity_object*", "sculpt_paint/sculpting/tool_settings/options.html#bpy-types-sculpt-gravity-object"),
("bpy.types.shadernodebsdfdiffuse*", "render/shader_nodes/shader/diffuse.html#bpy-types-shadernodebsdfdiffuse"),
("bpy.types.shadernodelayerweight*", "render/shader_nodes/input/layer_weight.html#bpy-types-shadernodelayerweight"),
@ -749,8 +771,9 @@ url_manual_mapping = (
("bpy.ops.nla.action_sync_length*", "editors/nla/editing.html#bpy-ops-nla-action-sync-length"),
("bpy.ops.object.paths_calculate*", "animation/motion_paths.html#bpy-ops-object-paths-calculate"),
("bpy.ops.object.transform_apply*", "scene_layout/object/editing/apply.html#bpy-ops-object-transform-apply"),
("bpy.ops.outliner.lib_operation*", "files/linked_libraries/introduction.html#bpy-ops-outliner-lib-operation"),
("bpy.ops.outliner.lib_operation*", "files/linked_libraries/link_append.html#bpy-ops-outliner-lib-operation"),
("bpy.ops.outliner.orphans_purge*", "editors/outliner/interface.html#bpy-ops-outliner-orphans-purge"),
("bpy.ops.paint.mask_box_gesture*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask-box-gesture"),
("bpy.ops.screen.region_quadview*", "editors/3dview/navigate/views.html#bpy-ops-screen-region-quadview"),
("bpy.ops.sequencer.offset_clear*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-offset-clear"),
("bpy.ops.uv.follow_active_quads*", "modeling/meshes/editing/uv.html#bpy-ops-uv-follow-active-quads"),
@ -780,6 +803,7 @@ url_manual_mapping = (
("bpy.types.limitscaleconstraint*", "animation/constraints/transform/limit_scale.html#bpy-types-limitscaleconstraint"),
("bpy.types.materialgpencilstyle*", "grease_pencil/materials/index.html#bpy-types-materialgpencilstyle"),
("bpy.types.mesh.use_auto_smooth*", "modeling/meshes/structure.html#bpy-types-mesh-use-auto-smooth"),
("bpy.types.object.hide_viewport*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-viewport"),
("bpy.types.posebone.rigify_type*", "addons/rigging/rigify/rig_types/index.html#bpy-types-posebone-rigify-type"),
("bpy.types.preferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-preferencesfilepaths"),
("bpy.types.scene.background_set*", "scene_layout/scene/properties.html#bpy-types-scene-background-set"),
@ -812,8 +836,9 @@ url_manual_mapping = (
("bpy.ops.mesh.blend_from_shape*", "modeling/meshes/editing/vertex/blend_shape.html#bpy-ops-mesh-blend-from-shape"),
("bpy.ops.mesh.dissolve_limited*", "modeling/meshes/editing/mesh/delete.html#bpy-ops-mesh-dissolve-limited"),
("bpy.ops.mesh.face_make_planar*", "modeling/meshes/editing/mesh/cleanup.html#bpy-ops-mesh-face-make-planar"),
("bpy.ops.mesh.face_set_extract*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-mesh-face-set-extract"),
("bpy.ops.mesh.faces_shade_flat*", "modeling/meshes/editing/face/shading.html#bpy-ops-mesh-faces-shade-flat"),
("bpy.ops.mesh.paint_mask_slice*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-mesh-paint-mask-slice"),
("bpy.ops.mesh.paint_mask_slice*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-mesh-paint-mask-slice"),
("bpy.ops.mesh.select_ungrouped*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-ungrouped"),
("bpy.ops.object.duplicate_move*", "scene_layout/object/editing/duplicate.html#bpy-ops-object-duplicate-move"),
("bpy.ops.object.hook_add_selob*", "modeling/meshes/editing/vertex/hooks.html#bpy-ops-object-hook-add-selob"),
@ -821,13 +846,13 @@ url_manual_mapping = (
("bpy.ops.object.select_grouped*", "scene_layout/object/selecting.html#bpy-ops-object-select-grouped"),
("bpy.ops.object.select_pattern*", "scene_layout/object/selecting.html#bpy-ops-object-select-pattern"),
("bpy.ops.outliner.id_operation*", "editors/outliner/editing.html#bpy-ops-outliner-id-operation"),
("bpy.ops.paint.mask_flood_fill*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-paint-mask-flood-fill"),
("bpy.ops.paint.mask_flood_fill*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask-flood-fill"),
("bpy.ops.pose.quaternions_flip*", "animation/armatures/posing/editing/flip_quats.html#bpy-ops-pose-quaternions-flip"),
("bpy.ops.pose.transforms_clear*", "animation/armatures/posing/editing/clear.html#bpy-ops-pose-transforms-clear"),
("bpy.ops.preferences.copy_prev*", "editors/preferences/introduction.html#bpy-ops-preferences-copy-prev"),
("bpy.ops.preferences.keyconfig*", "editors/preferences/keymap.html#bpy-ops-preferences-keyconfig"),
("bpy.ops.screen.repeat_history*", "interface/undo_redo.html#bpy-ops-screen-repeat-history"),
("bpy.ops.sculpt.face_sets_init*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-face-sets-init"),
("bpy.ops.sculpt.face_sets_init*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-sets-init"),
("bpy.ops.sequencer.change_path*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-change-path"),
("bpy.ops.sequencer.refresh_all*", "video_editing/sequencer/navigating.html#bpy-ops-sequencer-refresh-all"),
("bpy.ops.sequencer.swap_inputs*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-swap-inputs"),
@ -836,6 +861,7 @@ url_manual_mapping = (
("bpy.ops.transform.edge_crease*", "modeling/meshes/editing/edge/edge_data.html#bpy-ops-transform-edge-crease"),
("bpy.ops.transform.skin_resize*", "modeling/meshes/editing/mesh/transform/skin_resize.html#bpy-ops-transform-skin-resize"),
("bpy.ops.uv.seams_from_islands*", "modeling/meshes/uv/editing.html#bpy-ops-uv-seams-from-islands"),
("bpy.types.brush.cloth_damping*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-damping"),
("bpy.types.brush.icon_filepath*", "sculpt_paint/brush/brush.html#bpy-types-brush-icon-filepath"),
("bpy.types.brush.smooth_stroke*", "grease_pencil/modes/draw/tool_settings/brushes/draw_brush.html#bpy-types-brush-smooth-stroke"),
("bpy.types.brush.tip_roundness*", "sculpt_paint/sculpting/tools/clay_strips.html#bpy-types-brush-tip-roundness"),
@ -914,7 +940,7 @@ url_manual_mapping = (
("bpy.ops.pose.rigify_generate*", "addons/rigging/rigify/basics.html#bpy-ops-pose-rigify-generate"),
("bpy.ops.preferences.autoexec*", "editors/preferences/save_load.html#bpy-ops-preferences-autoexec"),
("bpy.ops.scene.view_layer_add*", "render/layers/layers.html#bpy-ops-scene-view-layer-add"),
("bpy.ops.sculpt.face_set_edit*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-face-set-edit"),
("bpy.ops.sculpt.face_set_edit*", "sculpt_paint/sculpting/editing/face_sets.html#bpy-ops-sculpt-face-set-edit"),
("bpy.ops.sequencer.gap_insert*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-gap-insert"),
("bpy.ops.sequencer.gap_remove*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-gap-remove"),
("bpy.ops.sequencer.rendersize*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-rendersize"),
@ -950,9 +976,11 @@ url_manual_mapping = (
("bpy.types.nodeoutputfileslot*", "compositing/types/output/file.html#bpy-types-nodeoutputfileslot"),
("bpy.types.normaleditmodifier*", "modeling/modifiers/modify/normal_edit.html#bpy-types-normaleditmodifier"),
("bpy.types.object.empty_image*", "modeling/empties.html#bpy-types-object-empty-image"),
("bpy.types.object.hide_render*", "editors/outliner/interface.html#bpy-types-object-hide-render"),
("bpy.types.object.hide_render*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-render"),
("bpy.types.object.hide_select*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-select"),
("bpy.types.object.show_bounds*", "scene_layout/object/properties/display.html#bpy-types-object-show-bounds"),
("bpy.types.scene.audio_volume*", "scene_layout/scene/properties.html#bpy-types-scene-audio-volume"),
("bpy.types.sculpt.detail_size*", "sculpt_paint/sculpting/tool_settings/dyntopo.html#bpy-types-sculpt-detail-size"),
("bpy.types.shadernodebsdfhair*", "render/shader_nodes/shader/hair.html#bpy-types-shadernodebsdfhair"),
("bpy.types.shadernodebsdftoon*", "render/shader_nodes/shader/toon.html#bpy-types-shadernodebsdftoon"),
("bpy.types.shadernodeemission*", "render/shader_nodes/shader/emission.html#bpy-types-shadernodeemission"),
@ -1093,8 +1121,8 @@ url_manual_mapping = (
("bpy.ops.object.track_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-track-clear"),
("bpy.ops.poselib.apply_pose*", "animation/armatures/properties/pose_library.html#bpy-ops-poselib-apply-pose"),
("bpy.ops.screen.repeat_last*", "interface/undo_redo.html#bpy-ops-screen-repeat-last"),
("bpy.ops.sculpt.mask_expand*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-sculpt-mask-expand"),
("bpy.ops.sculpt.mask_filter*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-sculpt-mask-filter"),
("bpy.ops.sculpt.mask_expand*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-mask-expand"),
("bpy.ops.sculpt.mask_filter*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-mask-filter"),
("bpy.ops.transform.tosphere*", "modeling/meshes/editing/mesh/transform/to_sphere.html#bpy-ops-transform-tosphere"),
("bpy.ops.view3d.clip_border*", "editors/3dview/navigate/regions.html#bpy-ops-view3d-clip-border"),
("bpy.ops.wm.previews_ensure*", "files/blend/previews.html#bpy-ops-wm-previews-ensure"),
@ -1102,6 +1130,7 @@ url_manual_mapping = (
("bpy.types.actionconstraint*", "animation/constraints/relationship/action.html#bpy-types-actionconstraint"),
("bpy.types.addonpreferences*", "editors/preferences/addons.html#bpy-types-addonpreferences"),
("bpy.types.armaturemodifier*", "modeling/modifiers/deform/armature.html#bpy-types-armaturemodifier"),
("bpy.types.brush.cloth_mass*", "sculpt_paint/sculpting/tools/cloth.html#bpy-types-brush-cloth-mass"),
("bpy.types.colormixsequence*", "video_editing/sequencer/strips/effects/color_mix.html#bpy-types-colormixsequence"),
("bpy.types.curve.dimensions*", "modeling/curves/properties/shape.html#bpy-types-curve-dimensions"),
("bpy.types.curve.twist_mode*", "modeling/curves/properties/shape.html#bpy-types-curve-twist-mode"),
@ -1115,7 +1144,6 @@ url_manual_mapping = (
("bpy.types.multicamsequence*", "video_editing/sequencer/strips/effects/multicam.html#bpy-types-multicamsequence"),
("bpy.types.multiplysequence*", "video_editing/sequencer/strips/effects/multiply.html#bpy-types-multiplysequence"),
("bpy.types.multiresmodifier*", "modeling/modifiers/generate/multiresolution.html#bpy-types-multiresmodifier"),
("bpy.types.object.use_extra*", "scene_layout/object/properties/relations.html#bpy-types-object-use-extra"),
("bpy.types.overdropsequence*", "video_editing/sequencer/strips/effects/alpha_over_under_overdrop.html#bpy-types-overdropsequence"),
("bpy.types.paint.show_brush*", "sculpt_paint/brush/cursor.html#bpy-types-paint-show-brush"),
("bpy.types.paint.use_cavity*", "sculpt_paint/texture_paint/tool_settings/mask.html#bpy-types-paint-use-cavity"),
@ -1124,7 +1152,7 @@ url_manual_mapping = (
("bpy.types.preferencesinput*", "editors/preferences/input.html#bpy-types-preferencesinput"),
("bpy.types.rigifyparameters*", "addons/rigging/rigify/rig_types/index.html#bpy-types-rigifyparameters"),
("bpy.types.sceneeevee.bloom*", "render/eevee/render_settings/bloom.html#bpy-types-sceneeevee-bloom"),
("bpy.types.sculpt.show_mask*", "sculpt_paint/sculpting/hide_mask.html#bpy-types-sculpt-show-mask"),
("bpy.types.sculpt.show_mask*", "sculpt_paint/sculpting/editing/mask.html#bpy-types-sculpt-show-mask"),
("bpy.types.sequencemodifier*", "video_editing/sequencer/properties/modifiers.html#bpy-types-sequencemodifier"),
("bpy.types.shaderfxcolorize*", "grease_pencil/visual_effects/colorize.html#bpy-types-shaderfxcolorize"),
("bpy.types.shaderfxpixelate*", "grease_pencil/visual_effects/pixelate.html#bpy-types-shaderfxpixelate"),
@ -1163,7 +1191,7 @@ url_manual_mapping = (
("bpy.ops.nla.tracks_delete*", "editors/nla/editing.html#bpy-ops-nla-tracks-delete"),
("bpy.ops.object.lightprobe*", "render/eevee/light_probes/index.html#bpy-ops-object-lightprobe"),
("bpy.ops.object.make_links*", "scene_layout/object/editing/make_links.html#bpy-ops-object-make-links"),
("bpy.ops.object.make_local*", "files/linked_libraries/introduction.html#bpy-ops-object-make-local"),
("bpy.ops.object.make_local*", "files/linked_libraries/link_append.html#bpy-ops-object-make-local"),
("bpy.ops.object.origin_set*", "scene_layout/object/origin.html#bpy-ops-object-origin-set"),
("bpy.ops.object.parent_set*", "scene_layout/object/editing/parent.html#bpy-ops-object-parent-set"),
("bpy.ops.object.pointcloud*", "modeling/point_cloud.html#bpy-ops-object-pointcloud"),
@ -1174,7 +1202,7 @@ url_manual_mapping = (
("bpy.ops.preferences.addon*", "editors/preferences/addons.html#bpy-ops-preferences-addon"),
("bpy.ops.scene.light_cache*", "render/eevee/render_settings/indirect_lighting.html#bpy-ops-scene-light-cache"),
("bpy.ops.screen.area_dupli*", "interface/window_system/areas.html#bpy-ops-screen-area-dupli"),
("bpy.ops.sculpt.dirty_mask*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-sculpt-dirty-mask"),
("bpy.ops.sculpt.dirty_mask*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-dirty-mask"),
("bpy.ops.sculpt.symmetrize*", "sculpt_paint/sculpting/tool_settings/symmetry.html#bpy-ops-sculpt-symmetrize"),
("bpy.ops.uv.remove_doubles*", "modeling/meshes/uv/editing.html#bpy-ops-uv-remove-doubles"),
("bpy.ops.uv.sphere_project*", "modeling/meshes/editing/uv.html#bpy-ops-uv-sphere-project"),
@ -1298,7 +1326,7 @@ url_manual_mapping = (
("bpy.ops.object.face_map*", "modeling/meshes/properties/object_data.html#bpy-ops-object-face-map"),
("bpy.ops.pose.relax_rest*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-relax-rest"),
("bpy.ops.rigidbody.world*", "physics/rigid_body/world.html#bpy-ops-rigidbody-world"),
("bpy.ops.sculpt.optimize*", "sculpt_paint/sculpting/editing.html#bpy-ops-sculpt-optimize"),
("bpy.ops.sculpt.optimize*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-optimize"),
("bpy.ops.sequencer.split*", "video_editing/sequencer/editing.html#bpy-ops-sequencer-split"),
("bpy.ops.transform.shear*", "modeling/meshes/editing/mesh/transform/shear.html#bpy-ops-transform-shear"),
("bpy.ops.uv.cube_project*", "modeling/meshes/editing/uv.html#bpy-ops-uv-cube-project"),
@ -1528,7 +1556,7 @@ url_manual_mapping = (
("bpy.ops.mesh.screw*", "modeling/meshes/editing/edge/screw.html#bpy-ops-mesh-screw"),
("bpy.ops.mesh.split*", "modeling/meshes/editing/mesh/split.html#bpy-ops-mesh-split"),
("bpy.ops.nla.delete*", "editors/nla/editing.html#bpy-ops-nla-delete"),
("bpy.ops.paint.mask*", "sculpt_paint/sculpting/hide_mask.html#bpy-ops-paint-mask"),
("bpy.ops.paint.mask*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-paint-mask"),
("bpy.ops.pose.paste*", "animation/armatures/posing/editing/copy_paste.html#bpy-ops-pose-paste"),
("bpy.ops.pose.relax*", "animation/armatures/posing/editing/in_betweens.html#bpy-ops-pose-relax"),
("bpy.ops.safe_areas*", "render/cameras.html#bpy-ops-safe-areas"),
@ -1562,6 +1590,7 @@ url_manual_mapping = (
("bpy.ops.uv.select*", "editors/uv/selecting.html#bpy-ops-uv-select"),
("bpy.ops.uv.stitch*", "modeling/meshes/uv/editing.html#bpy-ops-uv-stitch"),
("bpy.ops.uv.unwrap*", "modeling/meshes/editing/uv.html#bpy-ops-uv-unwrap"),
("bpy.ops.wm.append*", "files/linked_libraries/link_append.html#bpy-ops-wm-append"),
("bpy.ops.wm.search*", "interface/controls/templates/operator_search.html#bpy-ops-wm-search"),
("bpy.types.animviz*", "animation/motion_paths.html#bpy-types-animviz"),
("bpy.types.lattice*", "animation/lattice.html#bpy-types-lattice"),
@ -1603,6 +1632,7 @@ url_manual_mapping = (
("bpy.ops.surface*", "modeling/surfaces/index.html#bpy-ops-surface"),
("bpy.ops.texture*", "render/materials/legacy_textures/index.html#bpy-ops-texture"),
("bpy.ops.uv.weld*", "modeling/meshes/uv/editing.html#bpy-ops-uv-weld"),
("bpy.ops.wm.link*", "files/linked_libraries/link_append.html#bpy-ops-wm-link"),
("bpy.ops.wm.tool*", "interface/tool_system.html#bpy-ops-wm-tool"),
("bpy.types.addon*", "editors/preferences/addons.html#bpy-types-addon"),
("bpy.types.brush*", "sculpt_paint/brush/brush.html#bpy-types-brush"),

View File

@ -404,20 +404,21 @@ class GPENCIL_MT_cleanup(Menu):
layout = self.layout
layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes").mode = 'ACTIVE'
layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes all Frames").mode = 'ALL'
layout.separator()
layout.operator("gpencil.frame_clean_loose", text="Delete Loose Points")
layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicated Frames")
if ob.mode != 'PAINT_GPENCIL':
layout.operator("gpencil.stroke_merge_by_distance", text="Merge by Distance")
layout.separator()
layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes").mode = 'ACTIVE'
layout.operator("gpencil.frame_clean_fill", text="Boundary Strokes all Frames").mode = 'ALL'
layout.operator("gpencil.frame_clean_duplicate", text="Delete Duplicated Frames")
layout.operator("gpencil.recalc_geometry", text="Recalculate Geometry")
if ob.mode != 'PAINT_GPENCIL':
layout.separator()
layout.operator("gpencil.reproject")

View File

@ -815,10 +815,12 @@ class VIEW3D_MT_editor_menus(Menu):
# Select Menu
if gp_edit:
if mode_string not in {'PAINT_GPENCIL', 'WEIGHT_GPENCIL'}:
if mode_string == 'SCULPT_GPENCIL' and \
(ts.use_gpencil_select_mask_point or
ts.use_gpencil_select_mask_stroke or
ts.use_gpencil_select_mask_segment):
if (
mode_string == 'SCULPT_GPENCIL' and
(ts.use_gpencil_select_mask_point or
ts.use_gpencil_select_mask_stroke or
ts.use_gpencil_select_mask_segment)
):
layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string == 'EDIT_GPENCIL':
layout.menu("VIEW3D_MT_select_gpencil")
@ -6126,18 +6128,21 @@ class VIEW3D_PT_overlay_geometry(Panel):
sub.active = overlay.show_wireframes or is_wireframes
sub.prop(overlay, "wireframe_threshold", text="Wireframe")
col = layout.column(align=True)
col.active = display_all
col.prop(overlay, "show_face_orientation")
row = col.row(align=True)
if context.mode not in {'EDIT_ARMATURE', 'POSE', 'OBJECT', 'PAINT_GPENCIL',\
'VERTEX_GPENCIL', 'WEIGHT_GPENCIL', 'SCULPT_GPENCIL', 'EDIT_GPENCIL'}:
if context.mode not in {
'EDIT_ARMATURE', 'POSE', 'OBJECT',
'PAINT_GPENCIL', 'VERTEX_GPENCIL', 'WEIGHT_GPENCIL', 'SCULPT_GPENCIL', 'EDIT_GPENCIL',
}:
row.prop(overlay, "show_fade_inactive", text="")
sub = row.row()
sub.active = overlay.show_fade_inactive
sub.prop(overlay, "fade_inactive_alpha", text="Fade Inactive Geometry")
col = layout.column(align=True)
col.active = display_all
col.prop(overlay, "show_face_orientation")
# sub.prop(overlay, "show_onion_skins")

View File

@ -102,6 +102,10 @@ typedef void (*IDTypeBlendReadDataFunction)(struct BlendDataReader *reader, stru
typedef void (*IDTypeBlendReadLibFunction)(struct BlendLibReader *reader, struct ID *id);
typedef void (*IDTypeBlendReadExpandFunction)(struct BlendExpander *expander, struct ID *id);
typedef void (*IDTypeBlendReadUndoPreserve)(struct BlendLibReader *reader,
struct ID *id_new,
struct ID *id_old);
typedef struct IDTypeInfo {
/* ********** General IDType data. ********** */
@ -196,6 +200,13 @@ typedef struct IDTypeInfo {
* Specify which other id data blocks should be loaded when the current one is loaded.
*/
IDTypeBlendReadExpandFunction blend_read_expand;
/**
* Allow an ID type to preserve some of its data across (memfile) undo steps.
*
* \note Called from #setup_app_data when undoing or redoing a memfile step.
*/
IDTypeBlendReadUndoPreserve blend_read_undo_preserve;
} IDTypeInfo;
/* ********** Declaration of each IDTypeInfo. ********** */

View File

@ -295,6 +295,8 @@ IDTypeInfo IDType_ID_AC = {
.blend_read_data = action_blend_read_data,
.blend_read_lib = action_blend_read_lib,
.blend_read_expand = action_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/* ***************** Library data level operations on action ************** */

View File

@ -329,6 +329,8 @@ IDTypeInfo IDType_ID_AR = {
.blend_read_data = armature_blend_read_data,
.blend_read_lib = armature_blend_read_lib,
.blend_read_expand = armature_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/** \} */

View File

@ -355,6 +355,37 @@ static void brush_blend_read_expand(BlendExpander *expander, ID *id)
}
}
static int brush_undo_preserve_cb(LibraryIDLinkCallbackData *cb_data)
{
BlendLibReader *reader = cb_data->user_data;
ID *id_old = *cb_data->id_pointer;
/* Old data has not been remapped to new values of the pointers, if we want to keep the old
* pointer here we need its new address. */
ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
NULL;
BLI_assert(id_old_new == NULL || ELEM(id_old, id_old_new, id_old_new->orig_id));
if (cb_data->cb_flag & IDWALK_CB_USER) {
id_us_plus_no_lib(id_old_new);
id_us_min(id_old);
}
*cb_data->id_pointer = id_old_new;
return IDWALK_RET_NOP;
}
static void brush_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
{
/* Whole Brush is preserved accross undo's. */
BKE_lib_id_swap(NULL, id_new, id_old);
/* `id_new` now has content from `id_old`, we need to ensure those old ID pointers are valid.
* Note: Since we want to re-use all old pointers here, code is much simpler than for Scene. */
BKE_library_foreach_ID_link(NULL, id_new, brush_undo_preserve_cb, reader, IDWALK_NOP);
/* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
SWAP(IDProperty *, id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_BR = {
.id_code = ID_BR,
.id_filter = FILTER_ID_BR,
@ -376,6 +407,8 @@ IDTypeInfo IDType_ID_BR = {
.blend_read_data = brush_blend_read_data,
.blend_read_lib = brush_blend_read_lib,
.blend_read_expand = brush_blend_read_expand,
.blend_read_undo_preserve = brush_undo_preserve,
};
static RNG *brush_rng;

View File

@ -140,6 +140,8 @@ IDTypeInfo IDType_ID_CF = {
.blend_read_data = cache_file_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/* TODO: make this per cache file to avoid global locks. */

View File

@ -201,6 +201,8 @@ IDTypeInfo IDType_ID_CA = {
.blend_read_data = camera_blend_read_data,
.blend_read_lib = camera_blend_read_lib,
.blend_read_expand = camera_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/** \} */

View File

@ -359,6 +359,8 @@ IDTypeInfo IDType_ID_GR = {
.blend_read_data = collection_blend_read_data,
.blend_read_lib = collection_blend_read_lib,
.blend_read_expand = collection_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/** \} */

View File

@ -325,6 +325,8 @@ IDTypeInfo IDType_ID_CU = {
.blend_read_data = curve_blend_read_data,
.blend_read_lib = curve_blend_read_lib,
.blend_read_expand = curve_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static int cu_isectLL(const float v1[3],
@ -2636,7 +2638,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
BPoint *bp;
BevList *blnew;
BevPoint *bevp2, *bevp1 = NULL, *bevp0;
const float treshold = 0.00001f;
const float threshold = 0.00001f;
float min, inp;
float *seglen = NULL;
struct BevelSort *sortdata, *sd, *sd1;
@ -2732,7 +2734,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
*seglen = len_v3v3(bevp->vec, bp->vec);
bevp++;
bevp->offset = *seglen;
if (*seglen > treshold) {
if (*seglen > threshold) {
*segbevcount = 1;
}
else {
@ -2808,7 +2810,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp->offset = *seglen;
seglen++;
/* match segbevcount to the cleaned up bevel lists (see STEP 2) */
if (bevp->offset > treshold) {
if (bevp->offset > threshold) {
*segbevcount = 1;
}
segbevcount++;
@ -2873,7 +2875,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
bevp++;
bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
/* match seglen and segbevcount to the cleaned up bevel lists (see STEP 2) */
if (bevp->offset > treshold) {
if (bevp->offset > threshold) {
*seglen += bevp->offset;
*segbevcount += 1;
}
@ -2942,7 +2944,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
/* We keep last bevel segment zero-length. */
for (j = 0; j < ((nr == 1) ? (resolu - 1) : resolu); j++) {
bevp->offset = len_v3v3(bevp0->vec, bevp->vec);
if (bevp->offset > treshold) {
if (bevp->offset > threshold) {
*seglen += bevp->offset;
*segbevcount += 1;
}
@ -2968,6 +2970,8 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
continue;
}
/* Scale the threshold so high resolution shapes don't get over reduced, see: T49850. */
const float threshold_resolu = 0.00001f / resolu;
bool is_cyclic = bl->poly != -1;
nr = bl->nr;
if (is_cyclic) {
@ -2982,19 +2986,15 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
nr--;
while (nr--) {
if (seglen != NULL) {
if (fabsf(bevp1->offset) < treshold) {
if (fabsf(bevp1->offset) < threshold) {
bevp0->dupe_tag = true;
bl->dupe_nr++;
}
}
else {
if (fabsf(bevp0->vec[0] - bevp1->vec[0]) < 0.00001f) {
if (fabsf(bevp0->vec[1] - bevp1->vec[1]) < 0.00001f) {
if (fabsf(bevp0->vec[2] - bevp1->vec[2]) < 0.00001f) {
bevp0->dupe_tag = true;
bl->dupe_nr++;
}
}
if (compare_v3v3(bevp0->vec, bevp1->vec, threshold_resolu)) {
bevp0->dupe_tag = true;
bl->dupe_nr++;
}
}
bevp0 = bevp1;

View File

@ -3043,7 +3043,7 @@ void CustomData_free_elem(CustomData *data, int index, int count)
/**
* Interpolate given custom data source items into a single destination one.
*
* \param src_indices Indices of every source items to interpolate into the destination one.
* \param src_indices: Indices of every source items to interpolate into the destination one.
* \param weights: The weight to apply to each source value individually. If NULL, they will be
* averaged.
* \param sub_weights: The weights of sub-items, only used to affect each corners of a

View File

@ -168,6 +168,8 @@ IDTypeInfo IDType_ID_VF = {
.blend_read_data = vfont_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/***************************** VFont *******************************/

View File

@ -288,6 +288,8 @@ IDTypeInfo IDType_ID_GD = {
.blend_read_data = greasepencil_blend_read_data,
.blend_read_lib = greasepencil_blend_read_lib,
.blend_read_expand = greasepencil_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/* ************************************************** */

View File

@ -195,6 +195,8 @@ IDTypeInfo IDType_ID_HA = {
.blend_read_data = hair_blend_read_data,
.blend_read_lib = hair_blend_read_lib,
.blend_read_expand = hair_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static void hair_random(Hair *hair)

View File

@ -325,6 +325,8 @@ IDTypeInfo IDType_ID_IM = {
.blend_read_data = image_blend_read_data,
.blend_read_lib = image_blend_read_lib,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/* prototypes */

View File

@ -132,6 +132,8 @@ IDTypeInfo IDType_ID_IP = {
.blend_read_data = NULL,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/* *************************************************** */

View File

@ -214,6 +214,8 @@ IDTypeInfo IDType_ID_KE = {
.blend_read_data = shapekey_blend_read_data,
.blend_read_lib = shapekey_blend_read_lib,
.blend_read_expand = shapekey_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
#define KEY_MODE_DUMMY 0 /* use where mode isn't checked for */

View File

@ -203,6 +203,8 @@ IDTypeInfo IDType_ID_LT = {
.blend_read_data = lattice_blend_read_data,
.blend_read_lib = lattice_blend_read_lib,
.blend_read_expand = lattice_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w)

View File

@ -101,6 +101,15 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
.copy_data = NULL,
.free_data = NULL,
.make_local = NULL,
.foreach_id = NULL,
.foreach_cache = NULL,
.blend_write = NULL,
.blend_read_data = NULL,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/* GS reads the memory pointed at in a specific ordering.

View File

@ -82,6 +82,8 @@ IDTypeInfo IDType_ID_LI = {
.blend_read_data = NULL,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath)

View File

@ -207,6 +207,8 @@ IDTypeInfo IDType_ID_LA = {
.blend_read_data = light_blend_read_data,
.blend_read_lib = light_blend_read_lib,
.blend_read_expand = light_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
Light *BKE_light_add(Main *bmain, const char *name)

View File

@ -105,6 +105,8 @@ IDTypeInfo IDType_ID_LP = {
.blend_read_data = lightprobe_blend_read_data,
.blend_read_lib = lightprobe_blend_read_lib,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
void BKE_lightprobe_type_set(LightProbe *probe, const short lightprobe_type)

View File

@ -765,6 +765,8 @@ IDTypeInfo IDType_ID_LS = {
.blend_read_data = linestyle_blend_read_data,
.blend_read_lib = linestyle_blend_read_lib,
.blend_read_expand = linestyle_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static const char *modifier_name[LS_MODIFIER_NUM] = {

View File

@ -268,6 +268,8 @@ IDTypeInfo IDType_ID_MSK = {
.blend_read_data = mask_blend_read_data,
.blend_read_lib = mask_blend_read_lib,
.blend_read_expand = mask_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static struct {

View File

@ -272,6 +272,8 @@ IDTypeInfo IDType_ID_MA = {
.blend_read_data = material_blend_read_data,
.blend_read_lib = material_blend_read_lib,
.blend_read_expand = material_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
void BKE_gpencil_material_attr_init(Material *ma)

View File

@ -202,6 +202,8 @@ IDTypeInfo IDType_ID_MB = {
.blend_read_data = metaball_blend_read_data,
.blend_read_lib = metaball_blend_read_lib,
.blend_read_expand = metaball_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/* Functions */

View File

@ -333,6 +333,8 @@ IDTypeInfo IDType_ID_ME = {
.blend_read_data = mesh_blend_read_data,
.blend_read_lib = mesh_blend_read_lib,
.blend_read_expand = mesh_read_expand,
.blend_read_undo_preserve = NULL,
};
enum {
@ -879,6 +881,7 @@ void BKE_mesh_copy_settings(Mesh *me_dst, const Mesh *me_src)
me_dst->remesh_voxel_size = me_src->remesh_voxel_size;
me_dst->remesh_voxel_adaptivity = me_src->remesh_voxel_adaptivity;
me_dst->remesh_mode = me_src->remesh_mode;
me_dst->symmetry = me_src->symmetry;
me_dst->face_sets_color_seed = me_src->face_sets_color_seed;
me_dst->face_sets_color_default = me_src->face_sets_color_default;

View File

@ -359,6 +359,8 @@ IDTypeInfo IDType_ID_MC = {
.blend_read_data = movieclip_blend_read_data,
.blend_read_lib = movieclip_blend_read_lib,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/*********************** movieclip buffer loaders *************************/

View File

@ -853,6 +853,8 @@ IDTypeInfo IDType_ID_NT = {
.blend_read_data = ntree_blend_read_data,
.blend_read_lib = ntree_blend_read_lib,
.blend_read_expand = ntree_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)

View File

@ -538,6 +538,8 @@ IDTypeInfo IDType_ID_OB = {
.blend_read_data = NULL,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
void BKE_object_workob_clear(Object *workob)

View File

@ -125,6 +125,16 @@ static void palette_blend_read_data(BlendDataReader *reader, ID *id)
BLO_read_list(reader, &palette->colors);
}
static void palette_undo_preserve(BlendLibReader *UNUSED(reader), ID *id_new, ID *id_old)
{
/* Whole Palette is preserved accross undo's, and it has no extra pointer, simple. */
/* Note: We do not care about potential internal references to self here, Palette has none. */
/* Note: We do not swap IDProperties, as dealing with potential ID pointers in those would be
* fairly delicate. */
BKE_lib_id_swap(NULL, id_new, id_old);
SWAP(IDProperty *, id_new->properties, id_old->properties);
}
IDTypeInfo IDType_ID_PAL = {
.id_code = ID_PAL,
.id_filter = FILTER_ID_PAL,
@ -146,6 +156,8 @@ IDTypeInfo IDType_ID_PAL = {
.blend_read_data = palette_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = palette_undo_preserve,
};
static void paint_curve_copy_data(Main *UNUSED(bmain),
@ -207,6 +219,8 @@ IDTypeInfo IDType_ID_PC = {
.blend_read_data = paint_curve_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100};

View File

@ -506,6 +506,8 @@ IDTypeInfo IDType_ID_PA = {
.blend_read_data = particle_settings_blend_read_data,
.blend_read_lib = particle_settings_blend_read_lib,
.blend_read_expand = particle_settings_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];

View File

@ -184,6 +184,8 @@ IDTypeInfo IDType_ID_PT = {
.blend_read_data = pointcloud_blend_read_data,
.blend_read_lib = pointcloud_blend_read_lib,
.blend_read_expand = pointcloud_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
static void pointcloud_random(PointCloud *pointcloud)

View File

@ -104,6 +104,8 @@
#include "SEQ_sequencer.h"
#include "BLO_read_write.h"
#include "engines/eevee/eevee_lightcache.h"
#include "PIL_time.h"
@ -455,53 +457,216 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE
BKE_lib_query_foreachid_process(data, id_pointer, cb_flag);
}
static void scene_foreach_paint(LibraryForeachIDData *data, Paint *paint)
/**
* This code is shared by both the regular `foreach_id` looper, and the code trying to restore or
* preserve ID pointers like brushes across undoes.
*/
typedef enum eSceneForeachUndoPreserveProcess {
/* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID
* pointer from its old scene's value. */
SCENE_FOREACH_UNDO_RESTORE,
/* Undo when preserving tool-settings from old scene, we want to keep the new value of that ID
* pointer. */
SCENE_FOREACH_UNDO_NO_RESTORE,
} eSceneForeachUndoPreserveProcess;
static void scene_foreach_toolsettings_id_pointer_process(
ID **id_p,
const eSceneForeachUndoPreserveProcess action,
BlendLibReader *reader,
ID **id_old_p,
const uint cb_flag)
{
BKE_LIB_FOREACHID_PROCESS(data, paint->brush, IDWALK_CB_USER);
for (int i = 0; i < paint->tool_slots_len; i++) {
BKE_LIB_FOREACHID_PROCESS(data, paint->tool_slots[i].brush, IDWALK_CB_USER);
switch (action) {
case SCENE_FOREACH_UNDO_RESTORE: {
ID *id_old = *id_old_p;
/* Old data has not been remapped to new values of the pointers, if we want to keep the old
* pointer here we need its new address. */
ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
NULL;
if (id_old_new != NULL) {
BLI_assert(ELEM(id_old, id_old_new, id_old_new->orig_id));
*id_old_p = id_old_new;
if (cb_flag & IDWALK_CB_USER) {
id_us_plus_no_lib(id_old_new);
id_us_min(id_old);
}
break;
}
/* We failed to find a new valid pointer for the previous ID, just keep the current one as
* if we had been under SCENE_FOREACH_UNDO_NO_RESTORE case. */
SWAP(ID *, *id_p, *id_old_p);
break;
}
case SCENE_FOREACH_UNDO_NO_RESTORE:
/* Counteract the swap of the whole ToolSettings container struct. */
SWAP(ID *, *id_p, *id_old_p);
break;
}
BKE_LIB_FOREACHID_PROCESS(data, paint->palette, IDWALK_CB_USER);
}
static void scene_foreach_toolsettings(LibraryForeachIDData *data, ToolSettings *toolsett)
{
BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.scene, IDWALK_CB_NOP);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.object, IDWALK_CB_NOP);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->particle.shape_object, IDWALK_CB_NOP);
#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS( \
__data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \
{ \
if (__do_undo_restore) { \
scene_foreach_toolsettings_id_pointer_process( \
(ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \
} \
else { \
BKE_LIB_FOREACHID_PROCESS(__data, __id, __cb_flag); \
} \
} \
(void)0
scene_foreach_paint(data, &toolsett->imapaint.paint);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.stencil, IDWALK_CB_USER);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.clone, IDWALK_CB_USER);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->imapaint.canvas, IDWALK_CB_USER);
static void scene_foreach_paint(LibraryForeachIDData *data,
Paint *paint,
const bool do_undo_restore,
BlendLibReader *reader,
Paint *paint_old)
{
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
paint->brush,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
paint_old->brush,
IDWALK_CB_USER);
for (int i = 0; i < paint_old->tool_slots_len; i++) {
/* This is a bit tricky.
* - In case we do not do `undo_restore`, `paint` and `paint_old` pointers are the same, so
* this is equivalent to simply looping over slots from `paint`.
* - In case we do `undo_restore`, we only want to consider the slots from the old one, since
* those are the one we keep in the end.
* + In case the new data has less valid slots, we feed in a dummy NULL pointer.
* + In case the new data has more valid slots, the extra ones are ignored.
*/
Brush *brush_tmp = NULL;
Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp;
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
*brush_p,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
paint_old->brush,
IDWALK_CB_USER);
}
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
paint->palette,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
paint_old->palette,
IDWALK_CB_USER);
}
static void scene_foreach_toolsettings(LibraryForeachIDData *data,
ToolSettings *toolsett,
const bool do_undo_restore,
BlendLibReader *reader,
ToolSettings *toolsett_old)
{
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->particle.scene,
do_undo_restore,
SCENE_FOREACH_UNDO_NO_RESTORE,
reader,
toolsett_old->particle.scene,
IDWALK_CB_NOP);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->particle.object,
do_undo_restore,
SCENE_FOREACH_UNDO_NO_RESTORE,
reader,
toolsett_old->particle.object,
IDWALK_CB_NOP);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->particle.shape_object,
do_undo_restore,
SCENE_FOREACH_UNDO_NO_RESTORE,
reader,
toolsett_old->particle.shape_object,
IDWALK_CB_NOP);
scene_foreach_paint(
data, &toolsett->imapaint.paint, do_undo_restore, reader, &toolsett_old->imapaint.paint);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->imapaint.stencil,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
toolsett_old->imapaint.stencil,
IDWALK_CB_USER);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->imapaint.clone,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
toolsett_old->imapaint.clone,
IDWALK_CB_USER);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->imapaint.canvas,
do_undo_restore,
SCENE_FOREACH_UNDO_RESTORE,
reader,
toolsett_old->imapaint.canvas,
IDWALK_CB_USER);
if (toolsett->vpaint) {
scene_foreach_paint(data, &toolsett->vpaint->paint);
scene_foreach_paint(
data, &toolsett->vpaint->paint, do_undo_restore, reader, &toolsett_old->vpaint->paint);
}
if (toolsett->wpaint) {
scene_foreach_paint(data, &toolsett->wpaint->paint);
scene_foreach_paint(
data, &toolsett->wpaint->paint, do_undo_restore, reader, &toolsett_old->wpaint->paint);
}
if (toolsett->sculpt) {
scene_foreach_paint(data, &toolsett->sculpt->paint);
BKE_LIB_FOREACHID_PROCESS(data, toolsett->sculpt->gravity_object, IDWALK_CB_NOP);
scene_foreach_paint(
data, &toolsett->sculpt->paint, do_undo_restore, reader, &toolsett_old->sculpt->paint);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->sculpt->gravity_object,
do_undo_restore,
SCENE_FOREACH_UNDO_NO_RESTORE,
reader,
toolsett_old->sculpt->gravity_object,
IDWALK_CB_NOP);
}
if (toolsett->uvsculpt) {
scene_foreach_paint(data, &toolsett->uvsculpt->paint);
scene_foreach_paint(
data, &toolsett->uvsculpt->paint, do_undo_restore, reader, &toolsett_old->uvsculpt->paint);
}
if (toolsett->gp_paint) {
scene_foreach_paint(data, &toolsett->gp_paint->paint);
scene_foreach_paint(
data, &toolsett->gp_paint->paint, do_undo_restore, reader, &toolsett_old->gp_paint->paint);
}
if (toolsett->gp_vertexpaint) {
scene_foreach_paint(data, &toolsett->gp_vertexpaint->paint);
scene_foreach_paint(data,
&toolsett->gp_vertexpaint->paint,
do_undo_restore,
reader,
&toolsett_old->gp_vertexpaint->paint);
}
if (toolsett->gp_sculptpaint) {
scene_foreach_paint(data, &toolsett->gp_sculptpaint->paint);
scene_foreach_paint(data,
&toolsett->gp_sculptpaint->paint,
do_undo_restore,
reader,
&toolsett_old->gp_sculptpaint->paint);
}
if (toolsett->gp_weightpaint) {
scene_foreach_paint(data, &toolsett->gp_weightpaint->paint);
scene_foreach_paint(data,
&toolsett->gp_weightpaint->paint,
do_undo_restore,
reader,
&toolsett_old->gp_weightpaint->paint);
}
BKE_LIB_FOREACHID_PROCESS(data, toolsett->gp_sculpt.guide.reference_object, IDWALK_CB_NOP);
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS(data,
toolsett->gp_sculpt.guide.reference_object,
do_undo_restore,
SCENE_FOREACH_UNDO_NO_RESTORE,
reader,
toolsett_old->gp_sculpt.guide.reference_object,
IDWALK_CB_NOP);
}
static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb)
@ -593,7 +758,7 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
ToolSettings *toolsett = scene->toolsettings;
if (toolsett) {
scene_foreach_toolsettings(data, toolsett);
scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett);
}
if (scene->rigidbody_world) {
@ -620,6 +785,22 @@ static void scene_foreach_cache(ID *id,
user_data);
}
static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
{
Scene *scene_new = (Scene *)id_new;
Scene *scene_old = (Scene *)id_old;
SWAP(View3DCursor, scene_old->cursor, scene_new->cursor);
if (scene_new->toolsettings != NULL && scene_old->toolsettings != NULL) {
/* First try to restore ID pointers that can be and should be preserved (like brushes or
* palettes), and counteract the swap of the whole ToolSettings structs below for the others
* (like object ones). */
scene_foreach_toolsettings(
NULL, scene_new->toolsettings, true, reader, scene_old->toolsettings);
SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings);
}
}
IDTypeInfo IDType_ID_SCE = {
.id_code = ID_SCE,
.id_filter = FILTER_ID_SCE,
@ -643,6 +824,8 @@ IDTypeInfo IDType_ID_SCE = {
.blend_read_data = NULL,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = scene_undo_preserve,
};
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";

View File

@ -293,6 +293,8 @@ IDTypeInfo IDType_ID_SCR = {
.blend_read_data = NULL,
.blend_read_lib = screen_blend_read_lib,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/* ************ Spacetype/regiontype handling ************** */

View File

@ -171,6 +171,8 @@ IDTypeInfo IDType_ID_SIM = {
/* blend_read_data */ simulation_blend_read_data,
/* blend_read_lib */ simulation_blend_read_lib,
/* blend_read_expand */ simulation_blend_read_expand,
/* blend_read_undo_preserve */ NULL,
};
void *BKE_simulation_add(Main *bmain, const char *name)

View File

@ -212,6 +212,8 @@ IDTypeInfo IDType_ID_SO = {
.blend_read_data = sound_blend_read_data,
.blend_read_lib = sound_blend_read_lib,
.blend_read_expand = sound_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
#ifdef WITH_AUDASPACE

View File

@ -112,6 +112,8 @@ IDTypeInfo IDType_ID_SPK = {
.blend_read_data = speaker_blend_read_data,
.blend_read_lib = speaker_blend_read_lib,
.blend_read_expand = speaker_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
void *BKE_speaker_add(Main *bmain, const char *name)

View File

@ -256,6 +256,8 @@ IDTypeInfo IDType_ID_TXT = {
.blend_read_data = text_blend_read_data,
.blend_read_lib = NULL,
.blend_read_expand = NULL,
.blend_read_undo_preserve = NULL,
};
/** \} */

View File

@ -224,6 +224,8 @@ IDTypeInfo IDType_ID_TE = {
.blend_read_data = texture_blend_read_data,
.blend_read_lib = texture_blend_read_lib,
.blend_read_expand = texture_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/* Utils for all IDs using those texture slots. */

View File

@ -633,6 +633,8 @@ IDTypeInfo IDType_ID_VO = {
/* blend_read_data */ volume_blend_read_data,
/* blend_read_lib */ volume_blend_read_lib,
/* blend_read_expand */ volume_blend_read_expand,
/* blend_read_undo_preserve */ NULL,
};
void BKE_volume_init_grids(Volume *volume)

View File

@ -190,6 +190,8 @@ IDTypeInfo IDType_ID_WS = {
.blend_read_data = workspace_blend_read_data,
.blend_read_lib = workspace_blend_read_lib,
.blend_read_expand = workspace_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
/* -------------------------------------------------------------------- */

View File

@ -204,6 +204,8 @@ IDTypeInfo IDType_ID_WO = {
.blend_read_data = world_blend_read_data,
.blend_read_lib = world_blend_read_lib,
.blend_read_expand = world_blend_read_expand,
.blend_read_undo_preserve = NULL,
};
World *BKE_world_add(Main *bmain, const char *name)

View File

@ -106,7 +106,7 @@ typedef unsigned int BLI_bitmap;
#define BLI_BITMAP_RESIZE(_bitmap, _tot) \
{ \
CHECK_TYPE(_bitmap, BLI_bitmap *); \
(_bitmap) = MEM_reallocN(_bitmap, BLI_BITMAP_SIZE(_tot)); \
(_bitmap) = MEM_recallocN(_bitmap, BLI_BITMAP_SIZE(_tot)); \
} \
(void)0

View File

@ -29,7 +29,7 @@
#include "BLI_path_util.h"
/**
* \param r_targetpath Buffer for the target path an alias points to.
* \param r_targetpath: Buffer for the target path an alias points to.
* \return Whether the file at the input path is an alias.
*/
/* False alarm by clang-tidy: #getFileSystemRepresentation changes the return value argument. */

View File

@ -2522,7 +2522,9 @@ static void direct_link_ipo(BlendDataReader *reader, Ipo *ipo)
/* Undo generic endian switching. */
if (BLO_read_requires_endian_switch(reader)) {
BLI_endian_switch_int16(&ipo->blocktype);
BLI_endian_switch_int16(&icu->driver->blocktype);
if (icu->driver != NULL) {
BLI_endian_switch_int16(&icu->driver->blocktype);
}
}
}
}
@ -5670,15 +5672,6 @@ static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main,
const short idcode = GS(id->name);
/* XXX 3DCursor (witch is UI data and as such should not be affected by undo) is stored in
* Scene... So this requires some special handling, previously done in `blo_lib_link_restore()`,
* but this cannot work anymore when we overwrite existing memory... */
if (idcode == ID_SCE) {
Scene *scene_old = (Scene *)id_old;
Scene *scene = (Scene *)id;
SWAP(View3DCursor, scene_old->cursor, scene->cursor);
}
Main *old_bmain = fd->old_mainlist->first;
ListBase *old_lb = which_libbase(old_bmain, idcode);
ListBase *new_lb = which_libbase(main, idcode);
@ -5690,6 +5683,11 @@ static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main,
* process). So we can pass NULL for the Main pointer parameter. */
BKE_lib_id_swap_full(NULL, id, id_old);
/* Special temporary usage of this pointer, necessary for the `undo_preserve` call after
* lib-linking to restore some data that should never be affected by undo, e.g. the 3D cursor of
* #Scene. */
id_old->orig_id = id;
BLI_addtail(new_lb, id_old);
BLI_addtail(old_lb, id);
}
@ -6121,6 +6119,18 @@ static void lib_link_all(FileData *fd, Main *bmain)
}
id->tag &= ~LIB_TAG_NEED_LINK;
/* Some data that should be persistent, like the 3DCursor or the tool settings, are
* stored in IDs affected by undo, like Scene. So this requires some specific handling. */
if (id_type->blend_read_undo_preserve != NULL && id->orig_id != NULL) {
id_type->blend_read_undo_preserve(&reader, id, id->orig_id);
}
}
FOREACH_MAIN_ID_END;
/* Cleanup `ID.orig_id`, this is now reserved for depsgraph/COW usage only. */
FOREACH_MAIN_ID_BEGIN (bmain, id) {
id->orig_id = NULL;
}
FOREACH_MAIN_ID_END;

View File

@ -3420,7 +3420,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
case SPACE_OUTLINER: {
SpaceOutliner *space_outliner = (SpaceOutliner *)sl;
space_outliner->filter &= ~(SO_FILTER_UNUSED_1 | SO_FILTER_UNUSED_5 |
SO_FILTER_UNUSED_12);
SO_FILTER_OB_STATE_SELECTABLE);
space_outliner->storeflag &= ~(SO_TREESTORE_UNUSED_1);
break;
}

View File

@ -59,6 +59,8 @@
#define BEVEL_SMALL_ANG DEG2RADF(10.0f)
/** Difference in dot products that corresponds to 10 degree difference between vectors. */
#define BEVEL_SMALL_ANG_DOT 1 - cosf(BEVEL_SMALL_ANG)
/** Difference in dot products that corresponds to 2.0 degree difference between vectors. */
#define BEVEL_EPSILON_ANG_DOT 1 - cosf(BEVEL_EPSILON_ANG)
#define BEVEL_MAX_ADJUST_PCT 10.0f
#define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f
#define BEVEL_MATCH_SPEC_WEIGHT 0.2
@ -301,14 +303,14 @@ typedef enum {
} FKind;
/** Helper for keeping track of angle kind. */
enum {
typedef enum AngleKind {
/** Angle less than 180 degrees. */
ANGLE_SMALLER = -1,
/** 180 degree angle. */
ANGLE_STRAIGHT = 0,
/** Angle greater than 180 degrees. */
ANGLE_LARGER = 1,
};
} AngleKind;
/** Bevel parameters and state. */
typedef struct BevelParams {
@ -432,6 +434,18 @@ static bool nearly_parallel(const float d1[3], const float d2[3])
return (fabsf(ang) < BEVEL_EPSILON_ANG) || (fabsf(ang - (float)M_PI) < BEVEL_EPSILON_ANG);
}
/**
* \return True if d1 and d2 are parallel or nearly parallel.
*/
static bool nearly_parallel_normalized(const float d1[3], const float d2[3])
{
BLI_ASSERT_UNIT_V3(d1);
BLI_ASSERT_UNIT_V3(d2);
const float direction_dot = dot_v3v3(d1, d2);
return compare_ff(fabsf(direction_dot), 1.0f, BEVEL_EPSILON_ANG_DOT);
}
/* Make a new BoundVert of the given kind, inserting it at the end of the circular linked
* list with entry point bv->boundstart, and return it. */
static BoundVert *add_new_bound_vert(MemArena *mem_arena, VMesh *vm, const float co[3])
@ -1087,7 +1101,7 @@ static bool is_outside_edge(EdgeHalf *e, const float co[3], BMVert **ret_closer_
}
/* Return whether the angle is less than, equal to, or larger than 180 degrees. */
static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
static AngleKind edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
{
BMVert *v1 = BM_edge_other_vert(e1->e, v);
BMVert *v2 = BM_edge_other_vert(e2->e, v);
@ -1096,6 +1110,12 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
sub_v3_v3v3(dir2, v->co, v2->co);
normalize_v3(dir1);
normalize_v3(dir2);
/* First check for in-line edges using a simpler test. */
if (nearly_parallel_normalized(dir1, dir2)) {
return ANGLE_STRAIGHT;
}
/* Angles are in [0,pi]. Need to compare cross product with normal to see if they are reflex. */
float cross[3];
cross_v3_v3v3(cross, dir1, dir2);
@ -1110,11 +1130,8 @@ static int edges_angle_kind(EdgeHalf *e1, EdgeHalf *e2, BMVert *v)
else {
no = v->no;
}
float dot = dot_v3v3(cross, no);
if (fabsf(dot) < BEVEL_EPSILON_BIG) {
return ANGLE_STRAIGHT;
}
if (dot < 0.0f) {
if (dot_v3v3(cross, no) < 0.0f) {
return ANGLE_LARGER;
}
return ANGLE_SMALLER;
@ -3010,7 +3027,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
for (EdgeHalf *e3 = e->next; e3 != e2; e3 = e3->next) {
e3->leftv = e3->rightv = v;
}
int ang_kind = edges_angle_kind(e, e2, bv->v);
AngleKind ang_kind = edges_angle_kind(e, e2, bv->v);
/* Are we doing special mitering?
* There can only be one outer reflex angle, so only one outer miter,
@ -3088,7 +3105,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct)
}
}
else { /* construct == false. */
int ang_kind = edges_angle_kind(e, e2, bv->v);
AngleKind ang_kind = edges_angle_kind(e, e2, bv->v);
if ((miter_outer != BEVEL_MITER_SHARP && !emiter && ang_kind == ANGLE_LARGER) ||
(miter_inner != BEVEL_MITER_SHARP && ang_kind == ANGLE_SMALLER)) {
if (ang_kind == ANGLE_LARGER) {
@ -4911,7 +4928,7 @@ static VMesh *square_out_adj_vmesh(BevelParams *bp, BevVert *bv)
copy_v3_v3(bndco, bndv->nv.co);
EdgeHalf *e1 = bndv->efirst;
EdgeHalf *e2 = bndv->elast;
int ang_kind = ANGLE_STRAIGHT;
AngleKind ang_kind = ANGLE_STRAIGHT;
if (e1 && e2) {
ang_kind = edges_angle_kind(e1, e2, bv->v);
}

View File

@ -36,6 +36,7 @@ struct ARegion;
struct DRWInstanceDataList;
struct Depsgraph;
struct DrawEngineType;
struct GHash;
struct GPUMaterial;
struct GPUOffScreen;
struct GPUViewport;
@ -147,6 +148,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
/* This is here because GPUViewport needs it */
struct DRWInstanceDataList *DRW_instance_data_list_create(void);
void DRW_instance_data_list_free(struct DRWInstanceDataList *idatalist);
void DRW_uniform_attrs_pool_free(struct GHash *table);
void DRW_render_context_enable(struct Render *render);
void DRW_render_context_disable(struct Render *render);

View File

@ -1586,10 +1586,13 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob)
const bool draw_xform = draw_ctx->object_mode == OB_MODE_OBJECT &&
(scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) &&
(ob->base_flag & BASE_SELECTED) && !is_select_mode;
/* Don't show fluid domain overlay extras outside of cache range. */
const bool draw_volume = !from_dupli &&
(md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) &&
(BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) &&
(((FluidModifierData *)md)->domain != NULL);
(((FluidModifierData *)md)->domain != NULL) &&
(CFRA >= (((FluidModifierData *)md)->domain->cache_frame_start)) &&
(CFRA <= (((FluidModifierData *)md)->domain->cache_frame_end));
float *color;
int theme_id = DRW_object_wire_theme_get(ob, view_layer, &color);

View File

@ -496,10 +496,8 @@ static void mesh_batch_cache_init(Mesh *me)
cache->mat_len = mesh_render_mat_len_get(me);
cache->surface_per_mat = MEM_callocN(sizeof(*cache->surface_per_mat) * cache->mat_len, __func__);
FOREACH_MESH_BUFFER_CACHE (cache, mbufcache) {
mbufcache->tris_per_mat = MEM_callocN(sizeof(*mbufcache->tris_per_mat) * cache->mat_len,
cache->final.tris_per_mat = MEM_callocN(sizeof(*cache->final.tris_per_mat) * cache->mat_len,
__func__);
}
cache->is_dirty = false;
cache->batch_ready = 0;
@ -707,16 +705,13 @@ static void mesh_batch_cache_clear(Mesh *me)
for (int i = 0; i < sizeof(mbufcache->ibo) / sizeof(void *); i++) {
GPU_INDEXBUF_DISCARD_SAFE(ibos[i]);
}
BLI_assert((mbufcache->tris_per_mat != NULL) || (cache->mat_len == 0));
BLI_assert((mbufcache->tris_per_mat != NULL) && (cache->mat_len > 0));
if (mbufcache->tris_per_mat) {
for (int i = 0; i < cache->mat_len; i++) {
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->tris_per_mat[i]);
}
MEM_SAFE_FREE(mbufcache->tris_per_mat);
}
}
for (int i = 0; i < cache->mat_len; i++) {
GPU_INDEXBUF_DISCARD_SAFE(cache->final.tris_per_mat[i]);
}
MEM_SAFE_FREE(cache->final.tris_per_mat);
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
GPUBatch **batch = (GPUBatch **)&cache->batch;
GPU_BATCH_DISCARD_SAFE(batch[i]);

View File

@ -30,9 +30,20 @@
*/
#include "draw_instance_data.h"
#include "draw_manager.h"
#include "DRW_engine.h"
#include "DRW_render.h" /* For DRW_shgroup_get_instance_count() */
#include "GPU_material.h"
#include "DNA_particle_types.h"
#include "BKE_duplilist.h"
#include "RNA_access.h"
#include "BLI_bitmap.h"
#include "BLI_memblock.h"
#include "BLI_mempool.h"
#include "BLI_utildefines.h"
@ -408,3 +419,362 @@ void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist)
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Sparse Uniform Buffer
* \{ */
#define CHUNK_LIST_STEP (1 << 4)
/** A chunked UBO manager that doesn't actually allocate unneeded chunks. */
typedef struct DRWSparseUniformBuf {
/* Memory buffers used to stage chunk data before transfer to UBOs. */
char **chunk_buffers;
/* Uniform buffer objects with flushed data. */
struct GPUUniformBuf **chunk_ubos;
/* True if the relevant chunk contains data (distinct from simply being allocated). */
BLI_bitmap *chunk_used;
int num_chunks;
unsigned int item_size, chunk_size, chunk_bytes;
} DRWSparseUniformBuf;
static void drw_sparse_uniform_buffer_init(DRWSparseUniformBuf *buffer,
unsigned int item_size,
unsigned int chunk_size)
{
buffer->chunk_buffers = NULL;
buffer->chunk_used = NULL;
buffer->chunk_ubos = NULL;
buffer->num_chunks = 0;
buffer->item_size = item_size;
buffer->chunk_size = chunk_size;
buffer->chunk_bytes = item_size * chunk_size;
}
/** Allocate a chunked UBO with the specified item and chunk size. */
DRWSparseUniformBuf *DRW_sparse_uniform_buffer_new(unsigned int item_size, unsigned int chunk_size)
{
DRWSparseUniformBuf *buf = MEM_mallocN(sizeof(DRWSparseUniformBuf), __func__);
drw_sparse_uniform_buffer_init(buf, item_size, chunk_size);
return buf;
}
/** Flush data from ordinary memory to UBOs. */
void DRW_sparse_uniform_buffer_flush(DRWSparseUniformBuf *buffer)
{
for (int i = 0; i < buffer->num_chunks; i++) {
if (BLI_BITMAP_TEST(buffer->chunk_used, i)) {
if (buffer->chunk_ubos[i] == NULL) {
buffer->chunk_ubos[i] = GPU_uniformbuf_create(buffer->chunk_bytes);
}
GPU_uniformbuf_update(buffer->chunk_ubos[i], buffer->chunk_buffers[i]);
}
}
}
/** Clean all buffers and free unused ones. */
void DRW_sparse_uniform_buffer_clear(DRWSparseUniformBuf *buffer, bool free_all)
{
int max_used_chunk = 0;
for (int i = 0; i < buffer->num_chunks; i++) {
/* Delete buffers that were not used since the last clear call. */
if (free_all || !BLI_BITMAP_TEST(buffer->chunk_used, i)) {
MEM_SAFE_FREE(buffer->chunk_buffers[i]);
if (buffer->chunk_ubos[i]) {
GPU_uniformbuf_free(buffer->chunk_ubos[i]);
buffer->chunk_ubos[i] = NULL;
}
}
else {
max_used_chunk = i + 1;
}
}
/* Shrink the chunk array if appropriate. */
const int old_num_chunks = buffer->num_chunks;
buffer->num_chunks = (max_used_chunk + CHUNK_LIST_STEP - 1) & ~(CHUNK_LIST_STEP - 1);
if (buffer->num_chunks == 0) {
/* Ensure that an empty pool holds no memory allocations. */
MEM_SAFE_FREE(buffer->chunk_buffers);
MEM_SAFE_FREE(buffer->chunk_used);
MEM_SAFE_FREE(buffer->chunk_ubos);
return;
}
if (buffer->num_chunks != old_num_chunks) {
buffer->chunk_buffers = MEM_recallocN(buffer->chunk_buffers,
buffer->num_chunks * sizeof(void *));
buffer->chunk_ubos = MEM_recallocN(buffer->chunk_ubos, buffer->num_chunks * sizeof(void *));
BLI_BITMAP_RESIZE(buffer->chunk_used, buffer->num_chunks);
}
BLI_bitmap_set_all(buffer->chunk_used, false, buffer->num_chunks);
}
/** Frees the buffer. */
void DRW_sparse_uniform_buffer_free(DRWSparseUniformBuf *buffer)
{
DRW_sparse_uniform_buffer_clear(buffer, true);
MEM_freeN(buffer);
}
/** Checks if the buffer contains any allocated chunks. */
bool DRW_sparse_uniform_buffer_is_empty(DRWSparseUniformBuf *buffer)
{
return buffer->num_chunks == 0;
}
static GPUUniformBuf *drw_sparse_uniform_buffer_get_ubo(DRWSparseUniformBuf *buffer, int chunk)
{
if (buffer && chunk < buffer->num_chunks && BLI_BITMAP_TEST(buffer->chunk_used, chunk)) {
return buffer->chunk_ubos[chunk];
}
return NULL;
}
/** Bind the UBO for the given chunk, if present. A NULL buffer pointer is handled as empty. */
void DRW_sparse_uniform_buffer_bind(DRWSparseUniformBuf *buffer, int chunk, int location)
{
GPUUniformBuf *ubo = drw_sparse_uniform_buffer_get_ubo(buffer, chunk);
if (ubo) {
GPU_uniformbuf_bind(ubo, location);
}
}
/** Unbind the UBO for the given chunk, if present. A NULL buffer pointer is handled as empty. */
void DRW_sparse_uniform_buffer_unbind(DRWSparseUniformBuf *buffer, int chunk)
{
GPUUniformBuf *ubo = drw_sparse_uniform_buffer_get_ubo(buffer, chunk);
if (ubo) {
GPU_uniformbuf_unbind(ubo);
}
}
/** Returns a pointer to the given item of the given chunk, allocating memory if necessary. */
void *DRW_sparse_uniform_buffer_ensure_item(DRWSparseUniformBuf *buffer, int chunk, int item)
{
if (chunk >= buffer->num_chunks) {
buffer->num_chunks = (chunk + CHUNK_LIST_STEP) & ~(CHUNK_LIST_STEP - 1);
buffer->chunk_buffers = MEM_recallocN(buffer->chunk_buffers,
buffer->num_chunks * sizeof(void *));
buffer->chunk_ubos = MEM_recallocN(buffer->chunk_ubos, buffer->num_chunks * sizeof(void *));
BLI_BITMAP_RESIZE(buffer->chunk_used, buffer->num_chunks);
}
char *chunk_buffer = buffer->chunk_buffers[chunk];
if (chunk_buffer == NULL) {
buffer->chunk_buffers[chunk] = chunk_buffer = MEM_callocN(buffer->chunk_bytes, __func__);
}
else if (!BLI_BITMAP_TEST(buffer->chunk_used, chunk)) {
memset(chunk_buffer, 0, buffer->chunk_bytes);
}
BLI_BITMAP_ENABLE(buffer->chunk_used, chunk);
return chunk_buffer + buffer->item_size * item;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Uniform Attribute Buffers
* \{ */
/** Sparse UBO buffer for a specific uniform attribute list. */
typedef struct DRWUniformAttrBuf {
/* Attribute list (also used as hash table key) handled by this buffer. */
GPUUniformAttrList key;
/* Sparse UBO buffer containing the attribute values. */
DRWSparseUniformBuf ubos;
/* Last handle used to update the buffer, checked for avoiding redundant updates. */
DRWResourceHandle last_handle;
/* Linked list pointer used for freeing the empty unneeded buffers. */
struct DRWUniformAttrBuf *next_empty;
} DRWUniformAttrBuf;
static DRWUniformAttrBuf *drw_uniform_attrs_pool_ensure(GHash *table, GPUUniformAttrList *key)
{
void **pkey, **pval;
if (!BLI_ghash_ensure_p_ex(table, key, &pkey, &pval)) {
DRWUniformAttrBuf *buffer = MEM_callocN(sizeof(*buffer), __func__);
*pkey = &buffer->key;
*pval = buffer;
GPU_uniform_attr_list_copy(&buffer->key, key);
drw_sparse_uniform_buffer_init(
&buffer->ubos, key->count * sizeof(float[4]), DRW_RESOURCE_CHUNK_LEN);
buffer->last_handle = (DRWResourceHandle)-1;
}
return (DRWUniformAttrBuf *)*pval;
}
/* This function mirrors lookup_property in cycles/blender/blender_object.cpp */
static bool drw_uniform_property_lookup(ID *id, const char *name, float r_data[4])
{
PointerRNA ptr, id_ptr;
PropertyRNA *prop;
if (!id) {
return false;
}
RNA_id_pointer_create(id, &id_ptr);
if (!RNA_path_resolve(&id_ptr, name, &ptr, &prop)) {
return false;
}
PropertyType type = RNA_property_type(prop);
int arraylen = RNA_property_array_length(&ptr, prop);
if (arraylen == 0) {
float value;
if (type == PROP_FLOAT) {
value = RNA_property_float_get(&ptr, prop);
}
else if (type == PROP_INT) {
value = RNA_property_int_get(&ptr, prop);
}
else {
return false;
}
copy_v4_fl4(r_data, value, value, value, 1);
return true;
}
if (type == PROP_FLOAT && arraylen <= 4) {
copy_v4_fl4(r_data, 0, 0, 0, 1);
RNA_property_float_get_array(&ptr, prop, r_data);
return true;
}
return false;
}
/* This function mirrors lookup_instance_property in cycles/blender/blender_object.cpp */
static void drw_uniform_attribute_lookup(GPUUniformAttr *attr,
Object *ob,
Object *dupli_parent,
DupliObject *dupli_source,
float r_data[4])
{
char idprop_name[sizeof(attr->name) + 4];
copy_v4_fl(r_data, 0);
sprintf(idprop_name, "[\"%s\"]", attr->name);
/* If requesting instance data, check the parent particle system and object. */
if (attr->use_dupli) {
if (dupli_source && dupli_source->particle_system) {
ParticleSettings *settings = dupli_source->particle_system->part;
if (drw_uniform_property_lookup((ID *)settings, idprop_name, r_data) ||
drw_uniform_property_lookup((ID *)settings, attr->name, r_data)) {
return;
}
}
if (drw_uniform_property_lookup((ID *)dupli_parent, idprop_name, r_data) ||
drw_uniform_property_lookup((ID *)dupli_parent, attr->name, r_data)) {
return;
}
}
/* Check the object and mesh. */
if (ob) {
if (drw_uniform_property_lookup((ID *)ob, idprop_name, r_data) ||
drw_uniform_property_lookup((ID *)ob, attr->name, r_data) ||
drw_uniform_property_lookup((ID *)ob->data, idprop_name, r_data) ||
drw_uniform_property_lookup((ID *)ob->data, attr->name, r_data)) {
return;
}
}
}
void drw_uniform_attrs_pool_update(GHash *table,
GPUUniformAttrList *key,
DRWResourceHandle *handle,
Object *ob,
Object *dupli_parent,
DupliObject *dupli_source)
{
DRWUniformAttrBuf *buffer = drw_uniform_attrs_pool_ensure(table, key);
if (buffer->last_handle != *handle) {
buffer->last_handle = *handle;
int chunk = DRW_handle_chunk_get(handle);
int item = DRW_handle_id_get(handle);
float(*values)[4] = DRW_sparse_uniform_buffer_ensure_item(&buffer->ubos, chunk, item);
LISTBASE_FOREACH (GPUUniformAttr *, attr, &buffer->key.list) {
drw_uniform_attribute_lookup(attr, ob, dupli_parent, dupli_source, *values++);
}
}
}
DRWSparseUniformBuf *DRW_uniform_attrs_pool_find_ubo(GHash *table, struct GPUUniformAttrList *key)
{
DRWUniformAttrBuf *buffer = BLI_ghash_lookup(table, key);
return buffer ? &buffer->ubos : NULL;
}
GHash *DRW_uniform_attrs_pool_new()
{
return GPU_uniform_attr_list_hash_new("obattr_hash");
}
void DRW_uniform_attrs_pool_flush_all(GHash *table)
{
GHASH_FOREACH_BEGIN (DRWUniformAttrBuf *, buffer, table) {
DRW_sparse_uniform_buffer_flush(&buffer->ubos);
}
GHASH_FOREACH_END();
}
static void drw_uniform_attrs_pool_free_cb(void *ptr)
{
DRWUniformAttrBuf *buffer = ptr;
GPU_uniform_attr_list_free(&buffer->key);
DRW_sparse_uniform_buffer_clear(&buffer->ubos, true);
MEM_freeN(buffer);
}
void DRW_uniform_attrs_pool_clear_all(GHash *table)
{
DRWUniformAttrBuf *remove_list = NULL;
GHASH_FOREACH_BEGIN (DRWUniformAttrBuf *, buffer, table) {
buffer->last_handle = (DRWResourceHandle)-1;
DRW_sparse_uniform_buffer_clear(&buffer->ubos, false);
if (DRW_sparse_uniform_buffer_is_empty(&buffer->ubos)) {
buffer->next_empty = remove_list;
remove_list = buffer;
}
}
GHASH_FOREACH_END();
while (remove_list) {
DRWUniformAttrBuf *buffer = remove_list;
remove_list = buffer->next_empty;
BLI_ghash_remove(table, &buffer->key, NULL, drw_uniform_attrs_pool_free_cb);
}
}
void DRW_uniform_attrs_pool_free(GHash *table)
{
BLI_ghash_free(table, NULL, drw_uniform_attrs_pool_free_cb);
}
/** \} */

View File

@ -31,8 +31,12 @@
#define DRW_BUFFER_VERTS_CHUNK 128
struct GHash;
struct GPUUniformAttrList;
typedef struct DRWInstanceData DRWInstanceData;
typedef struct DRWInstanceDataList DRWInstanceDataList;
typedef struct DRWSparseUniformBuf DRWSparseUniformBuf;
void *DRW_instance_data_next(DRWInstanceData *idata);
DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size);
@ -54,3 +58,21 @@ void DRW_instance_buffer_finish(DRWInstanceDataList *idatalist);
void DRW_instance_data_list_reset(DRWInstanceDataList *idatalist);
void DRW_instance_data_list_free_unused(DRWInstanceDataList *idatalist);
void DRW_instance_data_list_resize(DRWInstanceDataList *idatalist);
/* Sparse chunked UBO manager. */
DRWSparseUniformBuf *DRW_sparse_uniform_buffer_new(unsigned int item_size,
unsigned int chunk_size);
void DRW_sparse_uniform_buffer_flush(DRWSparseUniformBuf *buffer);
void DRW_sparse_uniform_buffer_clear(DRWSparseUniformBuf *buffer, bool free_all);
void DRW_sparse_uniform_buffer_free(DRWSparseUniformBuf *buffer);
bool DRW_sparse_uniform_buffer_is_empty(DRWSparseUniformBuf *buffer);
void DRW_sparse_uniform_buffer_bind(DRWSparseUniformBuf *buffer, int chunk, int location);
void DRW_sparse_uniform_buffer_unbind(DRWSparseUniformBuf *buffer, int chunk);
void *DRW_sparse_uniform_buffer_ensure_item(DRWSparseUniformBuf *buffer, int chunk, int item);
/* Uniform attribute UBO management. */
struct GHash *DRW_uniform_attrs_pool_new(void);
void DRW_uniform_attrs_pool_flush_all(struct GHash *table);
void DRW_uniform_attrs_pool_clear_all(struct GHash *table);
struct DRWSparseUniformBuf *DRW_uniform_attrs_pool_find_ubo(struct GHash *table,
struct GPUUniformAttrList *key);

View File

@ -467,6 +467,8 @@ static void drw_viewport_cache_resize(void)
BLI_memblock_clear(DST.vmempool->passes, NULL);
BLI_memblock_clear(DST.vmempool->views, NULL);
BLI_memblock_clear(DST.vmempool->images, NULL);
DRW_uniform_attrs_pool_clear_all(DST.vmempool->obattrs_ubo_pool);
}
DRW_instance_data_list_free_unused(DST.idatalist);
@ -593,6 +595,9 @@ static void drw_viewport_var_init(void)
if (DST.vmempool->images == NULL) {
DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
}
if (DST.vmempool->obattrs_ubo_pool == NULL) {
DST.vmempool->obattrs_ubo_pool = DRW_uniform_attrs_pool_new();
}
DST.resource_handle = 0;
DST.pass_handle = 0;

View File

@ -43,6 +43,9 @@
#include "draw_instance_data.h"
struct Object;
struct DupliObject;
/* Use draw manager to call GPU_select, see: DRW_draw_select_loop */
#define USE_GPU_SELECT
@ -286,6 +289,7 @@ typedef enum {
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
DRW_UNIFORM_BLOCK_OBINFOS,
DRW_UNIFORM_BLOCK_OBATTRS,
DRW_UNIFORM_RESOURCE_CHUNK,
DRW_UNIFORM_RESOURCE_ID,
/** Legacy / Fallback */
@ -317,6 +321,8 @@ struct DRWUniform {
float fvalue[4];
/* DRW_UNIFORM_INT_COPY */
int ivalue[4];
/* DRW_UNIFORM_BLOCK_OBATTRS */
struct GPUUniformAttrList *uniform_attrs;
};
int location; /* Uniform location or binding point for textures and ubos. */
uint8_t type; /* DRWUniformType */
@ -340,6 +346,9 @@ struct DRWShadingGroup {
struct {
int objectinfo; /* Equal to 1 if the shader needs obinfos. */
DRWResourceHandle pass_handle; /* Memblock key to parent pass. */
/* Set of uniform attributes used by this shader. */
struct GPUUniformAttrList *uniform_attrs;
};
/* This struct is used after cache populate if using the Z sorting.
* It will not conflict with the above struct. */
@ -598,3 +607,10 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool);
GPUBatch *drw_cache_procedural_points_get(void);
GPUBatch *drw_cache_procedural_lines_get(void);
GPUBatch *drw_cache_procedural_triangles_get(void);
void drw_uniform_attrs_pool_update(struct GHash *table,
struct GPUUniformAttrList *key,
DRWResourceHandle *handle,
struct Object *ob,
struct Object *dupli_parent,
struct DupliObject *dupli_source);

View File

@ -128,6 +128,8 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
GPU_uniformbuf_update(vmempool->obinfos_ubo[i], data_infos);
}
DRW_uniform_attrs_pool_flush_all(vmempool->obattrs_ubo_pool);
/* Aligned alloc to avoid unaligned memcpy. */
DRWCommandChunk *chunk_tmp = MEM_mallocN_aligned(sizeof(DRWCommandChunk), 16, "tmp call chunk");
DRWCommandChunk *chunk;
@ -209,6 +211,9 @@ static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
uni->texture_ref = (GPUTexture **)value;
uni->sampler_state = sampler_state;
break;
case DRW_UNIFORM_BLOCK_OBATTRS:
uni->uniform_attrs = (GPUUniformAttrList *)value;
break;
default:
uni->pvalue = (const float *)value;
break;
@ -611,6 +616,15 @@ static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup,
}
}
if (shgroup->uniform_attrs) {
drw_uniform_attrs_pool_update(DST.vmempool->obattrs_ubo_pool,
shgroup->uniform_attrs,
&DST.ob_handle,
ob,
DST.dupli_parent,
DST.dupli_source);
}
return DST.ob_handle;
}
@ -1184,6 +1198,7 @@ void DRW_buffer_add_entry_array(DRWCallBuffer *callbuf, const void *attr[], uint
static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
{
shgroup->uniforms = NULL;
shgroup->uniform_attrs = NULL;
int view_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_VIEW);
int model_ubo_location = GPU_shader_get_builtin_block(shader, GPU_UNIFORM_BLOCK_MODEL);
@ -1329,6 +1344,13 @@ void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial
if (ubo != NULL) {
DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
}
GPUUniformAttrList *uattrs = GPU_material_uniform_attributes(material);
if (uattrs != NULL) {
int loc = GPU_shader_get_uniform_block_binding(grp->shader, GPU_ATTRIBUTE_UBO_BLOCK_NAME);
drw_shgroup_uniform_create_ex(grp, loc, DRW_UNIFORM_BLOCK_OBATTRS, uattrs, 0, 0, 1);
grp->uniform_attrs = uattrs;
}
}
GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],

View File

@ -57,12 +57,15 @@ typedef struct DRWCommandsState {
/* Resource location. */
int obmats_loc;
int obinfos_loc;
int obattrs_loc;
int baseinst_loc;
int chunkid_loc;
int resourceid_loc;
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
/* Uniform Attributes. */
DRWSparseUniformBuf *obattrs_ubo;
/* Selection ID state. */
GPUVertBuf *select_buf;
uint select_id;
@ -648,6 +651,12 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
state->obinfos_loc = uni->location;
GPU_uniformbuf_bind(DST.vmempool->obinfos_ubo[0], uni->location);
break;
case DRW_UNIFORM_BLOCK_OBATTRS:
state->obattrs_loc = uni->location;
state->obattrs_ubo = DRW_uniform_attrs_pool_find_ubo(DST.vmempool->obattrs_ubo_pool,
uni->uniform_attrs);
DRW_sparse_uniform_buffer_bind(state->obattrs_ubo, 0, uni->location);
break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
GPU_shader_uniform_int(shgroup->shader, uni->location, 0);
@ -762,6 +771,10 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa
GPU_uniformbuf_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
GPU_uniformbuf_bind(DST.vmempool->obinfos_ubo[chunk], state->obinfos_loc);
}
if (state->obattrs_loc != -1) {
DRW_sparse_uniform_buffer_unbind(state->obattrs_ubo, state->resource_chunk);
DRW_sparse_uniform_buffer_bind(state->obattrs_ubo, chunk, state->obattrs_loc);
}
state->resource_chunk = chunk;
}
@ -884,6 +897,9 @@ static void draw_call_batching_finish(DRWShadingGroup *shgroup, DRWCommandsState
if (state->obinfos_loc != -1) {
GPU_uniformbuf_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
}
if (state->obattrs_loc != -1) {
DRW_sparse_uniform_buffer_unbind(state->obattrs_ubo, state->resource_chunk);
}
}
static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
@ -893,11 +909,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
DRWCommandsState state = {
.obmats_loc = -1,
.obinfos_loc = -1,
.obattrs_loc = -1,
.baseinst_loc = -1,
.chunkid_loc = -1,
.resourceid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
.obattrs_ubo = NULL,
.drw_state_enabled = 0,
.drw_state_disabled = 0,
};

View File

@ -626,7 +626,7 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
FILE_OPENFILE,
WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
}
/** \} */
@ -2160,7 +2160,7 @@ void FONT_OT_open(wmOperatorType *ot)
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
}
/** \} */

View File

@ -413,7 +413,7 @@ static int gpencil_analyze_strokes(tGPencilPointCache *src_array,
BLI_ghash_free(strokes, NULL, NULL);
/* add the stroke to array */
if (gps->next != NULL) {
if (gps_next != NULL) {
BLI_ghash_insert(all_strokes, gps_next, gps_next);
last = gpencil_insert_to_array(src_array, dst_array, totpoints, gps_next, reverse, last);
/* replace last end */

View File

@ -35,6 +35,7 @@ struct SpaceFile;
struct bContext;
struct bScreen;
struct uiBlock;
struct wmOperator;
struct wmWindow;
struct wmWindowManager;
@ -145,6 +146,9 @@ void ED_fileselect_window_params_get(const struct wmWindow *win,
int win_size[2],
bool *is_maximized);
struct ScrArea *ED_fileselect_handler_area_find(const struct wmWindow *win,
const struct wmOperator *file_operator);
int ED_path_extension_type(const char *path);
int ED_file_extension_icon(const char *path);

View File

@ -900,6 +900,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
/* Move button over from oldblock to new block. */
BLI_remlink(&oldblock->buttons, oldbut);
BLI_insertlinkafter(&block->buttons, but, oldbut);
/* Add the old button to the button groups in the new block. */
ui_button_group_replace_but_ptr(block, but, oldbut);
oldbut->block = block;
*but_p = oldbut;

View File

@ -87,8 +87,8 @@ void ui_button_group_replace_but_ptr(uiBlock *block, const void *old_but_ptr, ui
}
}
/* The button should be in a group. */
BLI_assert(false);
/* The button should be in a group, otherwise there are no button groups at all. */
BLI_assert(BLI_listbase_is_empty(&block->button_groups));
}
/** \} */

View File

@ -907,13 +907,11 @@ bool UI_panel_matches_search_filter(const Panel *panel)
}
/**
* Set the flag telling the panel to use its search result status for
* its expansion. Also activate animation if that changes the expansion.
* Set the flag telling the panel to use its search result status for its expansion.
*/
static void panel_set_expansion_from_seach_filter_recursive(const bContext *C,
Panel *panel,
const bool use_search_closed,
const bool use_animation)
const bool use_search_closed)
{
/* This has to run on inactive panels that may not have a type,
* but we can prevent running on header-less panels in some cases. */
@ -924,8 +922,7 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C,
LISTBASE_FOREACH (Panel *, child_panel, &panel->children) {
/* Don't check if the sub-panel is active, otherwise the
* expansion won't be reset when the parent is closed. */
panel_set_expansion_from_seach_filter_recursive(
C, child_panel, use_search_closed, use_animation);
panel_set_expansion_from_seach_filter_recursive(C, child_panel, use_search_closed);
}
}
@ -934,15 +931,10 @@ static void panel_set_expansion_from_seach_filter_recursive(const bContext *C,
*/
static void region_panels_set_expansion_from_seach_filter(const bContext *C,
ARegion *region,
const bool use_search_closed,
const bool use_animation)
const bool use_search_closed)
{
LISTBASE_FOREACH (Panel *, panel, &region->panels) {
/* Checking if the panel is active is only an optimization, it would be fine to run this on
* inactive panels. */
if (panel->runtime_flag & PANEL_ACTIVE) {
panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed, use_animation);
}
panel_set_expansion_from_seach_filter_recursive(C, panel, use_search_closed);
}
set_panels_list_data_expand_flag(C, region);
}
@ -1906,10 +1898,10 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y)
const bool region_search_filter_active = region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE;
if (properties_space_needs_realign(area, region)) {
region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, false);
region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active);
}
else if (region->flag & RGN_FLAG_SEARCH_FILTER_UPDATE) {
region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active, true);
region_panels_set_expansion_from_seach_filter(C, region, region_search_filter_active);
}
if (region->flag & RGN_FLAG_SEARCH_FILTER_ACTIVE) {

View File

@ -3304,7 +3304,6 @@ static void colorband_buttons_layout(uiLayout *layout,
row = uiLayoutRow(split, false);
uiItemR(row, &ptr, "position", 0, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
UI_but_func_set(bt, colorband_update_cb, bt, coba);
row = uiLayoutRow(layout, false);
@ -3336,7 +3335,6 @@ static void colorband_buttons_layout(uiLayout *layout,
row = uiLayoutRow(subsplit, false);
uiItemR(row, &ptr, "position", UI_ITEM_R_SLIDER, IFACE_("Pos"), ICON_NONE);
bt = block->buttons.last;
bt->a1 = 1.0f; /* gives a bit more precision for modifying position */
UI_but_func_set(bt, colorband_update_cb, bt, coba);
row = uiLayoutRow(split, false);

View File

@ -292,7 +292,7 @@ void WM_OT_alembic_export(wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_int(ot->srna,
"start",
@ -677,7 +677,7 @@ void WM_OT_alembic_import(wmOperatorType *ot)
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_float(
ot->srna,

View File

@ -134,7 +134,7 @@ void CACHEFILE_OT_open(wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
}
/* ***************************** Reload Operator **************************** */

View File

@ -507,7 +507,7 @@ void WM_OT_collada_export(wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_enum(func,
"prop_bc_export_ui_section",
@ -828,7 +828,7 @@ void WM_OT_collada_import(wmOperatorType *ot)
FILE_OPENFILE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_boolean(ot->srna,
"import_units",

View File

@ -185,7 +185,7 @@ void WM_OT_usd_export(struct wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_boolean(ot->srna,
"selected_objects_only",

View File

@ -127,15 +127,10 @@ enum {
static float get_bevel_offset(wmOperator *op)
{
float val;
if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
val = RNA_float_get(op->ptr, "offset_pct");
return RNA_float_get(op->ptr, "offset_pct");
}
else {
val = RNA_float_get(op->ptr, "offset");
}
return val;
return RNA_float_get(op->ptr, "offset");
}
static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
@ -145,14 +140,12 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
char *p = buf;
int available_len = sizeof(buf);
Scene *sce = CTX_data_scene(C);
char offset_str[NUM_STR_REP_LEN];
const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str;
PropertyRNA *prop;
#define WM_MODALKEY(_id) \
WM_modalkeymap_operator_items_to_string_buf( \
op->type, (_id), true, UI_MAX_SHORTCUT_STR, &available_len, &p)
char offset_str[NUM_STR_REP_LEN];
if (RNA_enum_get(op->ptr, "offset_type") == BEVEL_AMT_PERCENT) {
BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%.1f%%", RNA_float_get(op->ptr, "offset_pct"));
}
@ -167,6 +160,8 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
true);
}
PropertyRNA *prop;
const char *mode_str, *omiter_str, *imiter_str, *vmesh_str, *profile_type_str, *affect_str;
prop = RNA_struct_find_property(op->ptr, "offset_type");
RNA_property_enum_name_gettexted(
C, op->ptr, prop, RNA_property_enum_get(op->ptr, prop), &mode_str);
@ -240,18 +235,17 @@ static void edbm_bevel_update_status_text(bContext *C, wmOperator *op)
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
ToolSettings *ts = CTX_data_tool_settings(C);
BevelData *opdata;
ViewLayer *view_layer = CTX_data_view_layer(C);
float pixels_per_inch;
int i, otype;
if (is_modal) {
RNA_float_set(op->ptr, "offset", 0.0f);
RNA_float_set(op->ptr, "offset_pct", 0.0f);
}
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
op->customdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
BevelData *opdata = op->customdata;
uint objects_used_len = 0;
opdata->max_obj_scale = FLT_MIN;
@ -261,7 +255,7 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
uint ob_store_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
view_layer, CTX_wm_view3d(C), &ob_store_len);
view_layer, v3d, &ob_store_len);
opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
Object *obedit = objects[ob_index];
@ -278,12 +272,12 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
}
opdata->is_modal = is_modal;
otype = RNA_enum_get(op->ptr, "offset_type");
int otype = RNA_enum_get(op->ptr, "offset_type");
opdata->value_mode = (otype == BEVEL_AMT_PERCENT) ? OFFSET_VALUE_PERCENT : OFFSET_VALUE;
opdata->segments = (float)RNA_int_get(op->ptr, "segments");
pixels_per_inch = U.dpi * U.pixelsize;
float pixels_per_inch = U.dpi * U.pixelsize;
for (i = 0; i < NUM_VALUE_KINDS; i++) {
for (int i = 0; i < NUM_VALUE_KINDS; i++) {
opdata->shift_value[i] = -1.0f;
opdata->initial_length[i] = -1.0f;
/* note: scale for OFFSET_VALUE will get overwritten in edbm_bevel_invoke */
@ -304,7 +298,6 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
/* avoid the cost of allocating a bm copy */
if (is_modal) {
View3D *v3d = CTX_wm_view3d(C);
ARegion *region = CTX_wm_region(C);
for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
@ -491,23 +484,21 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op)
static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event, bool mode_changed)
{
BevelData *opdata;
float mlen[2], len, value, sc, st;
int vmode;
opdata = op->customdata;
mlen[0] = opdata->mcenter[0] - event->mval[0];
mlen[1] = opdata->mcenter[1] - event->mval[1];
len = len_v2(mlen);
vmode = opdata->value_mode;
BevelData *opdata = op->customdata;
const float mlen[2] = {
opdata->mcenter[0] - event->mval[0],
opdata->mcenter[1] - event->mval[1],
};
float len = len_v2(mlen);
int vmode = opdata->value_mode;
if (mode_changed || opdata->initial_length[vmode] == -1.0f) {
/* If current value is not default start value, adjust len so that
* the scaling and offset in edbm_bevel_mouse_set_value will
* start at current value */
value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
RNA_float_get(op->ptr, value_rna_name[vmode]);
sc = opdata->scale[vmode];
st = value_start[vmode];
float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
RNA_float_get(op->ptr, value_rna_name[vmode]);
float sc = opdata->scale[vmode];
float st = value_start[vmode];
if (value != value_start[vmode]) {
len = (st + sc * (len - MVAL_PIXEL_MARGIN) - value) / sc;
}
@ -518,18 +509,17 @@ static void edbm_bevel_calc_initial_length(wmOperator *op, const wmEvent *event,
static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
BevelData *opdata;
float center_3d[3];
if (!edbm_bevel_init(C, op, true)) {
return OPERATOR_CANCELLED;
}
opdata = op->customdata;
BevelData *opdata = op->customdata;
opdata->launch_event = WM_userdef_event_type_from_keymap_type(event->type);
/* initialize mouse values */
float center_3d[3];
if (!calculateTransformCenter(C, V3D_AROUND_CENTER_MEDIAN, center_3d, opdata->mcenter)) {
/* in this case the tool will likely do nothing,
* ideally this will never happen and should be checked for above */
@ -561,13 +551,13 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
{
BevelData *opdata = op->customdata;
int vmode = opdata->value_mode;
float mdiff[2];
float value;
mdiff[0] = opdata->mcenter[0] - event->mval[0];
mdiff[1] = opdata->mcenter[1] - event->mval[1];
const float mdiff[2] = {
opdata->mcenter[0] - event->mval[0],
opdata->mcenter[1] - event->mval[1],
};
value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
float value = ((len_v2(mdiff) - MVAL_PIXEL_MARGIN) - opdata->initial_length[vmode]);
/* Scale according to value mode */
value = value_start[vmode] + value * opdata->scale[vmode];
@ -599,12 +589,10 @@ static void edbm_bevel_mouse_set_value(wmOperator *op, const wmEvent *event)
static void edbm_bevel_numinput_set_value(wmOperator *op)
{
BevelData *opdata = op->customdata;
float value;
int vmode;
vmode = opdata->value_mode;
value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
RNA_float_get(op->ptr, value_rna_name[vmode]);
int vmode = opdata->value_mode;
float value = (vmode == SEGMENTS_VALUE) ? opdata->segments :
RNA_float_get(op->ptr, value_rna_name[vmode]);
applyNumInput(&opdata->num_input[vmode], &value);
CLAMP(value, value_clamp_min[vmode], value_clamp_max[vmode]);
if (vmode == SEGMENTS_VALUE) {
@ -616,27 +604,6 @@ static void edbm_bevel_numinput_set_value(wmOperator *op)
}
}
/* Hide one of offset or offset_pct, depending on offset_type */
static bool edbm_bevel_poll_property(const bContext *UNUSED(C),
wmOperator *op,
const PropertyRNA *prop)
{
const char *prop_id = RNA_property_identifier(prop);
if (STRPREFIX(prop_id, "offset")) {
int offset_type = RNA_enum_get(op->ptr, "offset_type");
if (STREQ(prop_id, "offset") && offset_type == BEVEL_AMT_PERCENT) {
return false;
}
if (STREQ(prop_id, "offset_pct") && offset_type != BEVEL_AMT_PERCENT) {
return false;
}
}
return true;
}
wmKeyMap *bevel_modal_keymap(wmKeyConfig *keyconf)
{
static const EnumPropertyItem modal_items[] = {
@ -1109,7 +1076,6 @@ void MESH_OT_bevel(wmOperatorType *ot)
ot->modal = edbm_bevel_modal;
ot->cancel = edbm_bevel_cancel;
ot->poll = ED_operator_editmesh;
ot->poll_property = edbm_bevel_poll_property;
ot->ui = edbm_bevel_ui;
/* flags */

View File

@ -225,6 +225,8 @@ static int geometry_extract_apply(bContext *C,
/* Remove the mask from the new object so it can be sculpted directly after extracting. */
CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert);
BKE_mesh_copy_settings(new_ob_mesh, mesh);
if (params->apply_shrinkwrap) {
BKE_shrinkwrap_mesh_nearest_surface_deform(C, new_ob, ob);
}
@ -556,8 +558,12 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op)
mesh);
BM_mesh_free(bm);
/* Remove the mask from the new object so it can be sculpted directly after slicing. */
CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert);
BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true);
BKE_mesh_calc_normals(new_ob->data);
BKE_mesh_copy_settings(new_ob->data, mesh);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob);
BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL);
DEG_relations_tag_update(bmain);

View File

@ -880,6 +880,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
BMLoop *l;
BMEdge *e_best;
BMVert *v;
const int totvert_orig = bm->totvert;
const int totedge_orig = bm->totedge;
float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]};
@ -988,7 +989,7 @@ static int edbm_rip_invoke__edge(bContext *C, const wmEvent *event, Object *obed
MEM_freeN(fill_uloop_pairs);
}
if (totedge_orig == bm->totedge) {
if ((totvert_orig == bm->totvert) && (totedge_orig == bm->totedge)) {
return OPERATOR_CANCELLED;
}

View File

@ -1906,7 +1906,7 @@ void OBJECT_OT_multires_external_save(wmOperatorType *ot)
FILE_SAVE,
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
edit_modifier_properties(ot);
}

View File

@ -2664,12 +2664,23 @@ static void vgroup_assign_verts(Object *ob, const float weight)
static bool vertex_group_supported_poll_ex(bContext *C, const Object *ob)
{
if (!ED_operator_object_active_local_editable_ex(C, ob)) {
CTX_wm_operator_poll_msg_set(C, "No active editable object");
return false;
}
if (!OB_TYPE_SUPPORT_VGROUP(ob->type)) {
CTX_wm_operator_poll_msg_set(C, "Object type does not support vertex groups");
return false;
}
/* Data checks. */
const ID *data = ob->data;
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
/* Data checks. */
(data != NULL) && !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data));
if (data == NULL || ID_IS_LINKED(data) || ID_IS_OVERRIDE_LIBRARY(data)) {
CTX_wm_operator_poll_msg_set(C, "Object type \"%s\" does not have editable data");
return false;
}
return true;
}
static bool vertex_group_supported_poll(bContext *C)
@ -2678,32 +2689,61 @@ static bool vertex_group_supported_poll(bContext *C)
return vertex_group_supported_poll_ex(C, ob);
}
static bool vertex_group_poll_ex(bContext *C, Object *ob)
{
if (!vertex_group_supported_poll_ex(C, ob)) {
return false;
}
if (BLI_listbase_is_empty(&ob->defbase)) {
CTX_wm_operator_poll_msg_set(C, "Object has no vertex groups");
return false;
}
return true;
}
static bool vertex_group_poll(bContext *C)
{
Object *ob = ED_object_context(C);
return (vertex_group_supported_poll(C) && ob->defbase.first);
return vertex_group_poll_ex(C, ob);
}
static bool vertex_group_mesh_poll(bContext *C)
static bool vertex_group_mesh_poll_ex(bContext *C, Object *ob)
{
Object *ob = ED_object_context(C);
if (!vertex_group_poll_ex(C, ob)) {
return false;
}
return (vertex_group_poll(C) && ob->type == OB_MESH);
if (ob->type != OB_MESH) {
CTX_wm_operator_poll_msg_set(C, "Only mesh objects are supported");
return false;
}
return true;
}
static bool UNUSED_FUNCTION(vertex_group_mesh_supported_poll)(bContext *C)
static bool vertex_group_mesh_with_dvert_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (!vertex_group_mesh_poll_ex(C, ob)) {
return false;
}
return (vertex_group_supported_poll(C) && ob->type == OB_MESH);
Mesh *me = ob->data;
if (me->dvert == NULL) {
CTX_wm_operator_poll_msg_set(C, "The active mesh object has no vertex group data");
return false;
}
return true;
}
static bool UNUSED_FUNCTION(vertex_group_poll_edit)(bContext *C)
{
Object *ob = ED_object_context(C);
if (!vertex_group_supported_poll(C)) {
if (!vertex_group_supported_poll_ex(C, ob)) {
return false;
}
@ -2717,7 +2757,7 @@ static bool vertex_group_vert_poll_ex(bContext *C,
{
Object *ob = ED_object_context(C);
if (!vertex_group_supported_poll(C)) {
if (!vertex_group_supported_poll_ex(C, ob)) {
return false;
}
@ -2770,7 +2810,7 @@ static bool vertex_group_vert_select_unlocked_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (!vertex_group_supported_poll(C)) {
if (!vertex_group_supported_poll_ex(C, ob)) {
return false;
}
@ -2791,7 +2831,7 @@ static bool vertex_group_vert_select_mesh_poll(bContext *C)
{
Object *ob = ED_object_context(C);
if (!vertex_group_supported_poll(C)) {
if (!vertex_group_supported_poll_ex(C, ob)) {
return false;
}
@ -3313,7 +3353,7 @@ void OBJECT_OT_vertex_group_fix(wmOperatorType *ot)
"groups' weights (this tool may be slow for many vertices)";
/* api callbacks */
ot->poll = vertex_group_mesh_poll;
ot->poll = vertex_group_mesh_with_dvert_poll;
ot->exec = vertex_group_fix_exec;
/* flags */

View File

@ -184,7 +184,7 @@ void OBJECT_OT_volume_import(wmOperatorType *ot)
WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES |
WM_FILESEL_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
RNA_def_boolean(
ot->srna,

View File

@ -210,5 +210,5 @@ void RIGIDBODY_OT_world_export(wmOperatorType *ot)
FILE_SAVE,
FILE_RELPATH,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
FILE_SORT_DEFAULT);
}

Some files were not shown because too many files have changed in this diff Show More