Merge remote-tracking branch 'origin' into temp_bmesh_multires
This commit is contained in:
commit
6d704d57ad
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -37,6 +37,9 @@ BVHOptiX::BVHOptiX(const BVHParams ¶ms_,
|
|||
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 *)
|
||||
|
|
|
@ -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 ¶ms,
|
||||
const vector<Geometry *> &geometry,
|
||||
const vector<Object *> &objects);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
|
|
|
@ -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. ********** */
|
||||
|
|
|
@ -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 ************** */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 *******************************/
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/* ************************************************** */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/* *************************************************** */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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] = {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *************************/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 ************** */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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[],
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -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, ®ion->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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 **************************** */
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue