Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2022-11-12 17:57:25 +0300
committerAntonio Vazquez <blendergit@gmail.com>2022-11-12 17:57:25 +0300
commit53989894ca27907ce3be56ecd03ab8fa9bd42f7c (patch)
tree11920bfb916ea5088a30548bc6af4b6f00b57efa
parent7c576792c93192d652805e6f5352bff53f161e74 (diff)
parent99fe17f52d78cfd228cc3e839374f54b68e49eea (diff)
Merge branch 'master' into asset-lite-greasepencil
-rw-r--r--build_files/cmake/macros.cmake2
-rw-r--r--intern/cycles/device/metal/kernel.mm7
-rw-r--r--intern/cycles/kernel/osl/services_gpu.h131
-rw-r--r--intern/cycles/kernel/osl/shaders/node_geometry.osl5
-rw-r--r--intern/cycles/kernel/osl/shaders/node_normal_map.osl7
-rw-r--r--intern/cycles/kernel/osl/shaders/node_tangent.osl5
-rw-r--r--intern/cycles/kernel/osl/shaders/node_texture_coordinate.osl7
-rw-r--r--intern/cycles/scene/osl.cpp12
-rw-r--r--intern/cycles/scene/shader_nodes.cpp10
-rw-r--r--intern/cycles/scene/shader_nodes.h5
-rw-r--r--intern/cycles/util/path.cpp56
-rw-r--r--intern/cycles/util/path.h11
-rw-r--r--intern/ghost/CMakeLists.txt5
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp131
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.h30
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp293
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h1
-rw-r--r--intern/wayland_dynload/extern/wayland_dynload_client.h22
m---------release/scripts/addons0
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py1
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py5
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py4
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py1
-rw-r--r--source/blender/blenkernel/BKE_attribute.h2
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h18
-rw-r--r--source/blender/blenkernel/BKE_mesh.h15
-rw-r--r--source/blender/blenkernel/BKE_node.h9
-rw-r--r--source/blender/blenkernel/BKE_paint.h1
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/intern/attribute.cc27
-rw-r--r--source/blender/blenkernel/intern/customdata.cc23
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c4
-rw-r--r--source/blender/blenkernel/intern/fcurve.c158
-rw-r--r--source/blender/blenkernel/intern/fmodifier.c2
-rw-r--r--source/blender/blenkernel/intern/key.c4
-rw-r--r--source/blender/blenkernel/intern/lattice_deform_test.cc4
-rw-r--r--source/blender/blenkernel/intern/mesh.cc4
-rw-r--r--source/blender/blenkernel/intern/mesh_mirror.c4
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc414
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c4
-rw-r--r--source/blender/blenkernel/intern/node.cc10
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc52
-rw-r--r--source/blender/blenkernel/intern/pbvh.c7
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c8
-rw-r--r--source/blender/blenlib/BLI_disjoint_set.hh38
-rw-r--r--source/blender/blenlib/BLI_math_vec_types.hh1
-rw-r--r--source/blender/compositor/operations/COM_MovieDistortionOperation.cc51
-rw-r--r--source/blender/compositor/realtime_compositor/COM_scheduler.hh2
-rw-r--r--source/blender/compositor/realtime_compositor/intern/scheduler.cc96
-rw-r--r--source/blender/depsgraph/intern/depsgraph_build.cc5
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_camera.cc4
-rw-r--r--source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc4
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc4
-rw-r--r--source/blender/draw/intern/draw_manager.c1
-rw-r--r--source/blender/editors/animation/anim_markers.c25
-rw-r--r--source/blender/editors/geometry/geometry_attributes.cc158
-rw-r--r--source/blender/editors/geometry/geometry_intern.hh1
-rw-r--r--source/blender/editors/geometry/geometry_ops.cc1
-rw-r--r--source/blender/editors/include/ED_geometry.h17
-rw-r--r--source/blender/editors/include/ED_sculpt.h2
-rw-r--r--source/blender/editors/interface/interface_ops.cc2
-rw-r--r--source/blender/editors/interface/interface_region_color_picker.cc28
-rw-r--r--source/blender/editors/interface/view2d_gizmo_navigate.cc4
-rw-r--r--source/blender/editors/sculpt_paint/CMakeLists.txt2
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_ops.cc100
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.cc78
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c5
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.cc (renamed from source/blender/editors/sculpt_paint/sculpt.c)647
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_ops.c28
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c4
-rw-r--r--source/blender/editors/space_node/node_draw.cc5
-rw-r--r--source/blender/editors/space_node/space_node.cc10
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.cc1
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_navigate.c4
-rw-r--r--source/blender/editors/transform/transform_convert.c2
-rw-r--r--source/blender/editors/transform/transform_generics.c2
-rw-r--r--source/blender/geometry/intern/trim_curves.cc6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c7
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.h2
-rw-r--r--source/blender/makesdna/DNA_scene_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_attribute.c2
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c27
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.cc4
-rw-r--r--source/blender/modifiers/intern/MOD_weighted_normal.cc35
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc8
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc4
-rw-r--r--source/blender/nodes/intern/geometry_nodes_lazy_function.cc3
-rw-r--r--tests/python/CMakeLists.txt2
-rw-r--r--tests/python/bl_io_curve_svg_test.py5
-rwxr-xr-xtests/python/modules/render_report.py3
93 files changed, 1688 insertions, 1290 deletions
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 73883376060..824c587c86e 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -1240,7 +1240,7 @@ endmacro()
macro(set_and_warn_library_found
_library_name _library_found _setting)
- if(NOT ${${_library_found}} AND ${${_setting}})
+ if(((NOT ${_library_found}) OR (NOT ${${_library_found}})) AND ${${_setting}})
if(WITH_STRICT_BUILD_OPTIONS)
message(SEND_ERROR "${_library_name} required but not found")
else()
diff --git a/intern/cycles/device/metal/kernel.mm b/intern/cycles/device/metal/kernel.mm
index dc8af9a5358..35cf832c537 100644
--- a/intern/cycles/device/metal/kernel.mm
+++ b/intern/cycles/device/metal/kernel.mm
@@ -618,7 +618,9 @@ void MetalKernelPipeline::compile()
metalbin_path = path_cache_get(path_join("kernels", metalbin_name));
path_create_directories(metalbin_path);
- if (path_exists(metalbin_path) && use_binary_archive) {
+ /* Retrieve shader binary from disk, and update the file timestamp for LRU purging to work as
+ * intended. */
+ if (use_binary_archive && path_cache_kernel_exists_and_mark_used(metalbin_path)) {
if (@available(macOS 11.0, *)) {
MTLBinaryArchiveDescriptor *archiveDesc = [[MTLBinaryArchiveDescriptor alloc] init];
archiveDesc.url = [NSURL fileURLWithPath:@(metalbin_path.c_str())];
@@ -695,6 +697,9 @@ void MetalKernelPipeline::compile()
metal_printf("Failed to save binary archive, error:\n%s\n",
[[error localizedDescription] UTF8String]);
}
+ else {
+ path_cache_kernel_mark_added_and_clear_old(metalbin_path);
+ }
}
}
};
diff --git a/intern/cycles/kernel/osl/services_gpu.h b/intern/cycles/kernel/osl/services_gpu.h
index e6e19b8c484..75cf39919a0 100644
--- a/intern/cycles/kernel/osl/services_gpu.h
+++ b/intern/cycles/kernel/osl/services_gpu.h
@@ -15,6 +15,14 @@ namespace DeviceStrings {
/* "" */
ccl_device_constant DeviceString _emptystring_ = {0ull};
+/* "common" */
+ccl_device_constant DeviceString u_common = {14645198576927606093ull};
+/* "world" */
+ccl_device_constant DeviceString u_world = {16436542438370751598ull};
+/* "shader" */
+ccl_device_constant DeviceString u_shader = {4279676006089868ull};
+/* "object" */
+ccl_device_constant DeviceString u_object = {973692718279674627ull};
/* "NDC" */
ccl_device_constant DeviceString u_ndc = {5148305047403260775ull};
/* "screen" */
@@ -23,10 +31,6 @@ ccl_device_constant DeviceString u_screen = {14159088609039777114ull};
ccl_device_constant DeviceString u_camera = {2159505832145726196ull};
/* "raster" */
ccl_device_constant DeviceString u_raster = {7759263238610201778ull};
-/* "world" */
-ccl_device_constant DeviceString u_world = {16436542438370751598ull};
-/* "common" */
-ccl_device_constant DeviceString u_common = {14645198576927606093ull};
/* "hsv" */
ccl_device_constant DeviceString u_hsv = {2177035556331879497ull};
/* "hsl" */
@@ -419,10 +423,13 @@ ccl_device_extern bool osl_transformc(ccl_private ShaderGlobals *sg,
c_out[i] = rgb;
}
}
+
+ return true;
}
/* Matrix Utilities */
+#include "kernel/geom/object.h"
#include "util/transform.h"
ccl_device_forceinline void copy_matrix(ccl_private float *res, const Transform &tfm)
@@ -463,24 +470,24 @@ ccl_device_forceinline void copy_matrix(ccl_private float *res, const Projection
res[14] = tfm.z.w;
res[15] = tfm.w.w;
}
-ccl_device_forceinline void copy_identity_matrix(ccl_private float *res)
+ccl_device_forceinline void copy_identity_matrix(ccl_private float *res, float value = 1.0f)
{
- res[0] = 1.0f;
+ res[0] = value;
res[1] = 0.0f;
res[2] = 0.0f;
res[3] = 0.0f;
res[4] = 0.0f;
- res[5] = 1.0f;
+ res[5] = value;
res[6] = 0.0f;
res[7] = 0.0f;
res[8] = 0.0f;
res[9] = 0.0f;
- res[10] = 1.0f;
+ res[10] = value;
res[11] = 0.0f;
res[12] = 0.0f;
res[13] = 0.0f;
res[14] = 0.0f;
- res[15] = 1.0f;
+ res[15] = value;
}
ccl_device_forceinline Transform convert_transform(ccl_private const float *m)
{
@@ -532,22 +539,7 @@ ccl_device_extern void osl_div_mfm(ccl_private float *res, float a, ccl_private
ccl_device_extern void osl_div_m_ff(ccl_private float *res, float a, float b)
{
float f = (b == 0) ? 0.0f : (a / b);
- res[0] = f;
- res[1] = 0.0f;
- res[2] = 0.0f;
- res[3] = 0.0f;
- res[4] = 0.0f;
- res[5] = f;
- res[6] = 0.0f;
- res[7] = 0.0f;
- res[8] = 0.0f;
- res[9] = 0.0f;
- res[10] = f;
- res[11] = 0.0f;
- res[12] = 0.0f;
- res[13] = 0.0f;
- res[14] = 0.0f;
- res[15] = f;
+ copy_identity_matrix(res, f);
}
ccl_device_extern void osl_transform_vmv(ccl_private float3 *res,
@@ -605,27 +597,43 @@ ccl_device_extern void osl_transformn_dvmdv(ccl_private float3 *res,
}
ccl_device_extern bool osl_get_matrix(ccl_private ShaderGlobals *sg,
- ccl_private float *result,
+ ccl_private float *res,
DeviceString from)
{
- if (from == DeviceStrings::u_ndc) {
- copy_matrix(result, kernel_data.cam.ndctoworld);
+ if (from == DeviceStrings::u_common || from == DeviceStrings::u_world) {
+ copy_identity_matrix(res);
return true;
}
- if (from == DeviceStrings::u_raster) {
- copy_matrix(result, kernel_data.cam.rastertoworld);
+ if (from == DeviceStrings::u_shader || from == DeviceStrings::u_object) {
+ KernelGlobals kg = nullptr;
+ ccl_private ShaderData *const sd = static_cast<ccl_private ShaderData *>(sg->renderstate);
+ int object = sd->object;
+
+ if (object != OBJECT_NONE) {
+ const Transform tfm = object_get_transform(kg, sd);
+ copy_matrix(res, tfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ const Transform tfm = lamp_fetch_transform(kg, sd->lamp, false);
+ copy_matrix(res, tfm);
+ return true;
+ }
+ }
+ else if (from == DeviceStrings::u_ndc) {
+ copy_matrix(res, kernel_data.cam.ndctoworld);
return true;
}
- if (from == DeviceStrings::u_screen) {
- copy_matrix(result, kernel_data.cam.screentoworld);
+ else if (from == DeviceStrings::u_raster) {
+ copy_matrix(res, kernel_data.cam.rastertoworld);
return true;
}
- if (from == DeviceStrings::u_camera) {
- copy_matrix(result, kernel_data.cam.cameratoworld);
+ else if (from == DeviceStrings::u_screen) {
+ copy_matrix(res, kernel_data.cam.screentoworld);
return true;
}
- if (from == DeviceStrings::u_world) {
- copy_identity_matrix(result);
+ else if (from == DeviceStrings::u_camera) {
+ copy_matrix(res, kernel_data.cam.cameratoworld);
return true;
}
@@ -636,24 +644,53 @@ ccl_device_extern bool osl_get_inverse_matrix(ccl_private ShaderGlobals *sg,
ccl_private float *res,
DeviceString to)
{
- if (to == DeviceStrings::u_ndc) {
+ if (to == DeviceStrings::u_common || to == DeviceStrings::u_world) {
+ copy_identity_matrix(res);
+ return true;
+ }
+ if (to == DeviceStrings::u_shader || to == DeviceStrings::u_object) {
+ KernelGlobals kg = nullptr;
+ ccl_private ShaderData *const sd = static_cast<ccl_private ShaderData *>(sg->renderstate);
+ int object = sd->object;
+
+ if (object != OBJECT_NONE) {
+ const Transform itfm = object_get_inverse_transform(kg, sd);
+ copy_matrix(res, itfm);
+ return true;
+ }
+ else if (sd->type == PRIMITIVE_LAMP) {
+ const Transform itfm = lamp_fetch_transform(kg, sd->lamp, true);
+ copy_matrix(res, itfm);
+ return true;
+ }
+ }
+ else if (to == DeviceStrings::u_ndc) {
copy_matrix(res, kernel_data.cam.worldtondc);
return true;
}
- if (to == DeviceStrings::u_raster) {
+ else if (to == DeviceStrings::u_raster) {
copy_matrix(res, kernel_data.cam.worldtoraster);
return true;
}
- if (to == DeviceStrings::u_screen) {
+ else if (to == DeviceStrings::u_screen) {
copy_matrix(res, kernel_data.cam.worldtoscreen);
return true;
}
- if (to == DeviceStrings::u_camera) {
+ else if (to == DeviceStrings::u_camera) {
copy_matrix(res, kernel_data.cam.worldtocamera);
return true;
}
- if (to == DeviceStrings::u_world) {
- copy_identity_matrix(res);
+
+ return false;
+}
+
+ccl_device_extern bool osl_prepend_matrix_from(ccl_private ShaderGlobals *sg,
+ ccl_private float *res,
+ DeviceString from)
+{
+ float m_from[16];
+ if (osl_get_matrix(sg, m_from, from)) {
+ osl_mul_mmm(res, m_from, res);
return true;
}
@@ -674,16 +711,6 @@ ccl_device_extern bool osl_get_from_to_matrix(ccl_private ShaderGlobals *sg,
return false;
}
-ccl_device_extern void osl_prepend_matrix_from(ccl_private ShaderGlobals *sg,
- ccl_private float *res,
- DeviceString from)
-{
- float m[16];
- if (osl_get_matrix(sg, m, from)) {
- osl_mul_mmm(res, m, res);
- }
-}
-
ccl_device_extern bool osl_transform_triple(ccl_private ShaderGlobals *sg,
ccl_private float3 *p_in,
int p_in_derivs,
diff --git a/intern/cycles/kernel/osl/shaders/node_geometry.osl b/intern/cycles/kernel/osl/shaders/node_geometry.osl
index cc891abd6e3..5d9284deac2 100644
--- a/intern/cycles/kernel/osl/shaders/node_geometry.osl
+++ b/intern/cycles/kernel/osl/shaders/node_geometry.osl
@@ -3,8 +3,7 @@
#include "stdcycles.h"
-shader node_geometry(normal NormalIn = N,
- string bump_offset = "center",
+shader node_geometry(string bump_offset = "center",
output point Position = point(0.0, 0.0, 0.0),
output normal Normal = normal(0.0, 0.0, 0.0),
@@ -17,7 +16,7 @@ shader node_geometry(normal NormalIn = N,
output float RandomPerIsland = 0.0)
{
Position = P;
- Normal = NormalIn;
+ Normal = N;
TrueNormal = Ng;
Incoming = I;
Parametric = point(1.0 - u - v, u, 0.0);
diff --git a/intern/cycles/kernel/osl/shaders/node_normal_map.osl b/intern/cycles/kernel/osl/shaders/node_normal_map.osl
index 3cda485c686..7e41bbf1720 100644
--- a/intern/cycles/kernel/osl/shaders/node_normal_map.osl
+++ b/intern/cycles/kernel/osl/shaders/node_normal_map.osl
@@ -3,13 +3,12 @@
#include "stdcycles.h"
-shader node_normal_map(normal NormalIn = N,
- float Strength = 1.0,
+shader node_normal_map(float Strength = 1.0,
color Color = color(0.5, 0.5, 1.0),
string space = "tangent",
string attr_name = "geom:tangent",
string attr_sign_name = "geom:tangent_sign",
- output normal Normal = NormalIn)
+ output normal Normal = N)
{
color mcolor = 2.0 * color(Color[0] - 0.5, Color[1] - 0.5, Color[2] - 0.5);
int is_backfacing = backfacing();
@@ -71,5 +70,5 @@ shader node_normal_map(normal NormalIn = N,
}
if (Strength != 1.0)
- Normal = normalize(NormalIn + (Normal - NormalIn) * max(Strength, 0.0));
+ Normal = normalize(N + (Normal - N) * max(Strength, 0.0));
}
diff --git a/intern/cycles/kernel/osl/shaders/node_tangent.osl b/intern/cycles/kernel/osl/shaders/node_tangent.osl
index a302c001f08..b3808778b2f 100644
--- a/intern/cycles/kernel/osl/shaders/node_tangent.osl
+++ b/intern/cycles/kernel/osl/shaders/node_tangent.osl
@@ -3,8 +3,7 @@
#include "stdcycles.h"
-shader node_tangent(normal NormalIn = N,
- string attr_name = "geom:tangent",
+shader node_tangent(string attr_name = "geom:tangent",
string direction_type = "radial",
string axis = "z",
output normal Tangent = normalize(dPdu))
@@ -29,5 +28,5 @@ shader node_tangent(normal NormalIn = N,
}
T = transform("object", "world", T);
- Tangent = cross(NormalIn, normalize(cross(T, NormalIn)));
+ Tangent = cross(N, normalize(cross(T, N)));
}
diff --git a/intern/cycles/kernel/osl/shaders/node_texture_coordinate.osl b/intern/cycles/kernel/osl/shaders/node_texture_coordinate.osl
index 24875ce140a..cd2fdae3cb3 100644
--- a/intern/cycles/kernel/osl/shaders/node_texture_coordinate.osl
+++ b/intern/cycles/kernel/osl/shaders/node_texture_coordinate.osl
@@ -4,7 +4,6 @@
#include "stdcycles.h"
shader node_texture_coordinate(
- normal NormalIn = N,
int is_background = 0,
int is_volume = 0,
int from_dupli = 0,
@@ -27,7 +26,7 @@ shader node_texture_coordinate(
point Pcam = transform("camera", "world", point(0, 0, 0));
Camera = transform("camera", P + Pcam);
getattribute("NDC", Window);
- Normal = NormalIn;
+ Normal = N;
Reflection = I;
}
else {
@@ -59,8 +58,8 @@ shader node_texture_coordinate(
}
Camera = transform("camera", P);
Window = transform("NDC", P);
- Normal = transform("world", "object", NormalIn);
- Reflection = -reflect(I, NormalIn);
+ Normal = transform("world", "object", N);
+ Reflection = -reflect(I, N);
}
if (bump_offset == "dx") {
diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp
index 3ea406b6935..4dc5fb4edf7 100644
--- a/intern/cycles/scene/osl.cpp
+++ b/intern/cycles/scene/osl.cpp
@@ -641,6 +641,8 @@ string OSLCompiler::id(ShaderNode *node)
{
/* assign layer unique name based on pointer address + bump mode */
stringstream stream;
+ stream.imbue(std::locale("C")); /* Ensure that no grouping characters (e.g. commas with en_US
+ locale) are added to the pointer string */
stream << "node_" << node->type->name << "_" << node;
return stream.str();
@@ -1132,12 +1134,12 @@ OSL::ShaderGroupRef OSLCompiler::compile_type(Shader *shader, ShaderGraph *graph
{
current_type = type;
- string name = shader->name.string();
- /* Replace invalid characters. */
- for (size_t i; (i = name.find_first_of(" .,:;+-*/#")) != string::npos;)
- name.replace(i, 1, "_");
+ /* Use name hash to identify shader group to avoid issues with non-alphanumeric characters */
+ stringstream name;
+ name.imbue(std::locale("C"));
+ name << "shader_" << shader->name.hash();
- OSL::ShaderGroupRef group = ss->ShaderGroupBegin(name);
+ OSL::ShaderGroupRef group = ss->ShaderGroupBegin(name.str());
ShaderNode *output = graph->output();
ShaderNodeSet dependencies;
diff --git a/intern/cycles/scene/shader_nodes.cpp b/intern/cycles/scene/shader_nodes.cpp
index a9cd453947b..2c1cd3ee737 100644
--- a/intern/cycles/scene/shader_nodes.cpp
+++ b/intern/cycles/scene/shader_nodes.cpp
@@ -3677,9 +3677,6 @@ NODE_DEFINE(GeometryNode)
{
NodeType *type = NodeType::add("geometry", create, NodeType::SHADER);
- SOCKET_IN_NORMAL(
- normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
-
SOCKET_OUT_POINT(position, "Position");
SOCKET_OUT_NORMAL(normal, "Normal");
SOCKET_OUT_NORMAL(tangent, "Tangent");
@@ -3812,9 +3809,6 @@ NODE_DEFINE(TextureCoordinateNode)
SOCKET_BOOLEAN(use_transform, "Use Transform", false);
SOCKET_TRANSFORM(ob_tfm, "Object Transform", transform_identity());
- SOCKET_IN_NORMAL(
- normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
-
SOCKET_OUT_POINT(generated, "Generated");
SOCKET_OUT_NORMAL(normal, "Normal");
SOCKET_OUT_POINT(UV, "UV");
@@ -7305,8 +7299,6 @@ NODE_DEFINE(NormalMapNode)
SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(
- normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
SOCKET_IN_FLOAT(strength, "Strength", 1.0f);
SOCKET_IN_COLOR(color, "Color", make_float3(0.5f, 0.5f, 1.0f));
@@ -7400,8 +7392,6 @@ NODE_DEFINE(TangentNode)
SOCKET_STRING(attribute, "Attribute", ustring());
- SOCKET_IN_NORMAL(
- normal_osl, "NormalIn", zero_float3(), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
SOCKET_OUT_NORMAL(tangent, "Tangent");
return type;
diff --git a/intern/cycles/scene/shader_nodes.h b/intern/cycles/scene/shader_nodes.h
index a3a931bb0b3..9b4d27b5b31 100644
--- a/intern/cycles/scene/shader_nodes.h
+++ b/intern/cycles/scene/shader_nodes.h
@@ -907,8 +907,6 @@ class GeometryNode : public ShaderNode {
return true;
}
int get_group();
-
- NODE_SOCKET_API(float3, normal_osl)
};
class TextureCoordinateNode : public ShaderNode {
@@ -924,7 +922,6 @@ class TextureCoordinateNode : public ShaderNode {
return true;
}
- NODE_SOCKET_API(float3, normal_osl)
NODE_SOCKET_API(bool, from_dupli)
NODE_SOCKET_API(bool, use_transform)
NODE_SOCKET_API(Transform, ob_tfm)
@@ -1573,7 +1570,6 @@ class NormalMapNode : public ShaderNode {
NODE_SOCKET_API(ustring, attribute)
NODE_SOCKET_API(float, strength)
NODE_SOCKET_API(float3, color)
- NODE_SOCKET_API(float3, normal_osl)
};
class TangentNode : public ShaderNode {
@@ -1592,7 +1588,6 @@ class TangentNode : public ShaderNode {
NODE_SOCKET_API(NodeTangentDirectionType, direction_type)
NODE_SOCKET_API(NodeTangentAxis, axis)
NODE_SOCKET_API(ustring, attribute)
- NODE_SOCKET_API(float3, normal_osl)
};
class BevelNode : public ShaderNode {
diff --git a/intern/cycles/util/path.cpp b/intern/cycles/util/path.cpp
index 17cff2f2977..cb6b8d7a740 100644
--- a/intern/cycles/util/path.cpp
+++ b/intern/cycles/util/path.cpp
@@ -2,8 +2,11 @@
* Copyright 2011-2022 Blender Foundation */
#include "util/path.h"
+#include "util/algorithm.h"
+#include "util/map.h"
#include "util/md5.h"
#include "util/string.h"
+#include "util/vector.h"
#include <OpenImageIO/filesystem.h>
#include <OpenImageIO/strutil.h>
@@ -898,19 +901,54 @@ FILE *path_fopen(const string &path, const string &mode)
#endif
}
-void path_cache_clear_except(const string &name, const set<string> &except)
+/* LRU Cache for Kernels */
+
+static void path_cache_kernel_mark_used(const string &path)
{
- string dir = path_user_get("cache");
+ std::time_t current_time = std::time(nullptr);
+ OIIO::Filesystem::last_write_time(path, current_time);
+}
- if (path_exists(dir)) {
- directory_iterator it(dir), it_end;
+bool path_cache_kernel_exists_and_mark_used(const string &path)
+{
+ if (path_exists(path)) {
+ path_cache_kernel_mark_used(path);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
- for (; it != it_end; ++it) {
- string filename = path_filename(it->path());
+void path_cache_kernel_mark_added_and_clear_old(const string &new_path,
+ const size_t max_old_kernel_of_same_type)
+{
+ path_cache_kernel_mark_used(new_path);
+
+ string dir = path_dirname(new_path);
+ if (!path_exists(dir)) {
+ return;
+ }
+
+ /* Remove older kernels within the same directory. */
+ directory_iterator it(dir), it_end;
+ vector<pair<std::time_t, string>> same_kernel_types;
+
+ for (; it != it_end; ++it) {
+ const string &path = it->path();
+ if (path == new_path) {
+ continue;
+ }
+
+ std::time_t last_time = OIIO::Filesystem::last_write_time(path);
+ same_kernel_types.emplace_back(last_time, path);
+ }
+
+ if (same_kernel_types.size() > max_old_kernel_of_same_type) {
+ sort(same_kernel_types.begin(), same_kernel_types.end());
- if (string_startswith(filename, name.c_str()))
- if (except.find(filename) == except.end())
- path_remove(it->path());
+ for (int i = 0; i < same_kernel_types.size() - max_old_kernel_of_same_type; i++) {
+ path_remove(same_kernel_types[i].second);
}
}
}
diff --git a/intern/cycles/util/path.h b/intern/cycles/util/path.h
index 48b1fb65919..6d02267e182 100644
--- a/intern/cycles/util/path.h
+++ b/intern/cycles/util/path.h
@@ -55,8 +55,15 @@ bool path_remove(const string &path);
/* source code utility */
string path_source_replace_includes(const string &source, const string &path);
-/* cache utility */
-void path_cache_clear_except(const string &name, const set<string> &except);
+/* Simple least-recently-used cache for kernels.
+ *
+ * Kernels of same type are cached in the same directory.
+ * Whenever a kernel is used, its last modified time is updated.
+ * When a new kernel is added to the cache, clear old entries of the same type (i.e. in the same
+ * directory). */
+bool path_cache_kernel_exists_and_mark_used(const string &path);
+void path_cache_kernel_mark_added_and_clear_old(const string &path,
+ const size_t max_old_kernel_of_same_type = 5);
CCL_NAMESPACE_END
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index ea21d831b0c..5c559072625 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -310,6 +310,11 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
add_definitions(-DHAVE_MEMFD_CREATE)
endif()
+ check_symbol_exists(poll "poll.h" HAVE_POLL)
+ if(HAVE_POLL)
+ add_definitions(-DHAVE_POLL)
+ endif()
+
list(APPEND SRC
intern/GHOST_SystemWayland.cpp
intern/GHOST_WindowWayland.cpp
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 42da4a3ebbf..ed0dc9b5949 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -69,6 +69,10 @@
#include <cstring>
#include <mutex>
+#ifdef HAVE_POLL
+# include <poll.h>
+#endif
+
/* Logging, use `ghost.wl.*` prefix. */
#include "CLG_log.h"
@@ -1157,6 +1161,18 @@ static void gwl_registry_entry_update_all(GWL_Display *display, const int interf
/** \name Private Utility Functions
* \{ */
+static void ghost_wl_display_report_error(struct wl_display *display)
+{
+ int ecode = wl_display_get_error(display);
+ GHOST_ASSERT(ecode, "Error not set!");
+ if ((ecode == EPIPE || ecode == ECONNRESET)) {
+ fprintf(stderr, "The Wayland connection broke. Did the Wayland compositor die?\n");
+ }
+ else {
+ fprintf(stderr, "The Wayland connection experienced a fatal error: %s\n", strerror(ecode));
+ }
+}
+
/**
* Callback for WAYLAND to run when there is an error.
*
@@ -1444,6 +1460,89 @@ static int memfd_create_sealed(const char *name)
#endif /* !HAVE_MEMFD_CREATE */
}
+enum {
+ GWL_IOR_READ = 1 << 0,
+ GWL_IOR_WRITE = 1 << 1,
+ GWL_IOR_NO_RETRY = 1 << 2,
+};
+
+static int file_descriptor_is_io_ready(int fd, const int flags, const int timeout_ms)
+{
+ int result;
+
+ GHOST_ASSERT(flags & (GWL_IOR_READ | GWL_IOR_WRITE), "X");
+
+ /* Note: We don't bother to account for elapsed time if we get EINTR */
+ do {
+#ifdef HAVE_POLL
+ struct pollfd info;
+
+ info.fd = fd;
+ info.events = 0;
+ if (flags & GWL_IOR_READ) {
+ info.events |= POLLIN | POLLPRI;
+ }
+ if (flags & GWL_IOR_WRITE) {
+ info.events |= POLLOUT;
+ }
+ result = poll(&info, 1, timeout_ms);
+#else
+ fd_set rfdset, *rfdp = nullptr;
+ fd_set wfdset, *wfdp = nullptr;
+ struct timeval tv, *tvp = nullptr;
+
+ /* If this assert triggers we'll corrupt memory here */
+ GHOST_ASSERT(fd >= 0 && fd < FD_SETSIZE, "X");
+
+ if (flags & GWL_IOR_READ) {
+ FD_ZERO(&rfdset);
+ FD_SET(fd, &rfdset);
+ rfdp = &rfdset;
+ }
+ if (flags & GWL_IOR_WRITE) {
+ FD_ZERO(&wfdset);
+ FD_SET(fd, &wfdset);
+ wfdp = &wfdset;
+ }
+
+ if (timeout_ms >= 0) {
+ tv.tv_sec = timeout_ms / 1000;
+ tv.tv_usec = (timeout_ms % 1000) * 1000;
+ tvp = &tv;
+ }
+
+ result = select(fd + 1, rfdp, wfdp, nullptr, tvp);
+#endif /* !HAVE_POLL */
+ } while (result < 0 && errno == EINTR && !(flags & GWL_IOR_NO_RETRY));
+
+ return result;
+}
+
+static int ghost_wl_display_event_pump(struct wl_display *wl_display)
+{
+ /* Based on SDL's `Wayland_PumpEvents`. */
+ int err;
+
+ /* NOTE: Without this, interactions with window borders via LIBDECOR doesn't function. */
+ wl_display_flush(wl_display);
+
+ if (wl_display_prepare_read(wl_display) == 0) {
+ /* Use #GWL_IOR_NO_RETRY to ensure #SIGINT will break us out of our wait. */
+ if (file_descriptor_is_io_ready(
+ wl_display_get_fd(wl_display), GWL_IOR_READ | GWL_IOR_NO_RETRY, 0) > 0) {
+ err = wl_display_read_events(wl_display);
+ }
+ else {
+ wl_display_cancel_read(wl_display);
+ err = 0;
+ }
+ }
+ else {
+ err = wl_display_dispatch_pending(wl_display);
+ }
+ return err;
+}
+
static size_t ghost_wl_shm_format_as_size(enum wl_shm_format format)
{
switch (format) {
@@ -5152,10 +5251,14 @@ bool GHOST_SystemWayland::processEvents(bool waitForEvent)
#endif /* WITH_INPUT_NDOF */
if (waitForEvent) {
- wl_display_dispatch(display_->wl_display);
+ if (wl_display_dispatch(display_->wl_display) == -1) {
+ ghost_wl_display_report_error(display_->wl_display);
+ }
}
else {
- wl_display_roundtrip(display_->wl_display);
+ if (ghost_wl_display_event_pump(display_->wl_display) == -1) {
+ ghost_wl_display_report_error(display_->wl_display);
+ }
}
if (getEventManager()->getNumEvents() > 0) {
@@ -5891,7 +5994,7 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_
return false;
}
-GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor shape)
+GHOST_TSuccess GHOST_SystemWayland::cursor_shape_set(const GHOST_TStandardCursor shape)
{
GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
@@ -5933,7 +6036,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorShape(const GHOST_TStandardCursor s
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(const GHOST_TStandardCursor cursorShape)
+GHOST_TSuccess GHOST_SystemWayland::cursor_shape_check(const GHOST_TStandardCursor cursorShape)
{
auto cursor_find = ghost_wl_cursors.find(cursorShape);
if (cursor_find == ghost_wl_cursors.end()) {
@@ -5946,13 +6049,13 @@ GHOST_TSuccess GHOST_SystemWayland::hasCursorShape(const GHOST_TStandardCursor c
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
- uint8_t *mask,
- const int sizex,
- const int sizey,
- const int hotX,
- const int hotY,
- const bool /*canInvertColor*/)
+GHOST_TSuccess GHOST_SystemWayland::cursor_shape_custom_set(uint8_t *bitmap,
+ uint8_t *mask,
+ const int sizex,
+ const int sizey,
+ const int hotX,
+ const int hotY,
+ const bool /*canInvertColor*/)
{
GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
@@ -6022,7 +6125,7 @@ GHOST_TSuccess GHOST_SystemWayland::setCustomCursorShape(uint8_t *bitmap,
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
+GHOST_TSuccess GHOST_SystemWayland::cursor_bitmap_get(GHOST_CursorBitmapRef *bitmap)
{
GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
@@ -6048,7 +6151,7 @@ GHOST_TSuccess GHOST_SystemWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitma
return GHOST_kSuccess;
}
-GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(const bool visible)
+GHOST_TSuccess GHOST_SystemWayland::cursor_visibility_set(const bool visible)
{
GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
@@ -6072,7 +6175,7 @@ bool GHOST_SystemWayland::supportsWindowPosition()
return false;
}
-bool GHOST_SystemWayland::getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode)
+bool GHOST_SystemWayland::cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode)
{
GWL_Seat *seat = gwl_display_seat_active_get(display_);
if (UNLIKELY(!seat)) {
diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h
index a8e8d8ddc45..45eb1d9d3e3 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.h
+++ b/intern/ghost/intern/GHOST_SystemWayland.h
@@ -137,26 +137,28 @@ class GHOST_SystemWayland : public GHOST_System {
const bool is_dialog,
const GHOST_IWindow *parentWindow) override;
- GHOST_TSuccess setCursorShape(GHOST_TStandardCursor shape);
+ bool supportsCursorWarp() override;
+ bool supportsWindowPosition() override;
- GHOST_TSuccess hasCursorShape(GHOST_TStandardCursor cursorShape);
+ /* WAYLAND utility functions (share window/system logic). */
- GHOST_TSuccess setCustomCursorShape(uint8_t *bitmap,
- uint8_t *mask,
- int sizex,
- int sizey,
- int hotX,
- int hotY,
- bool canInvertColor);
+ GHOST_TSuccess cursor_shape_set(GHOST_TStandardCursor shape);
- GHOST_TSuccess getCursorBitmap(GHOST_CursorBitmapRef *bitmap);
+ GHOST_TSuccess cursor_shape_check(GHOST_TStandardCursor cursorShape);
- GHOST_TSuccess setCursorVisibility(bool visible);
+ GHOST_TSuccess cursor_shape_custom_set(uint8_t *bitmap,
+ uint8_t *mask,
+ int sizex,
+ int sizey,
+ int hotX,
+ int hotY,
+ bool canInvertColor);
- bool supportsCursorWarp() override;
- bool supportsWindowPosition() override;
+ GHOST_TSuccess cursor_bitmap_get(GHOST_CursorBitmapRef *bitmap);
+
+ GHOST_TSuccess cursor_visibility_set(bool visible);
- bool getCursorGrabUseSoftwareDisplay(const GHOST_TGrabCursorMode mode);
+ bool cursor_grab_use_software_display_get(const GHOST_TGrabCursorMode mode);
/* WAYLAND direct-data access. */
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index ad94a02b514..ef53f6a02e6 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -77,8 +77,13 @@ static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
delete decor;
}
+/* -------------------------------------------------------------------- */
+/** \name Internal #GWL_Window
+ * \{ */
+
struct GWL_Window {
GHOST_WindowWayland *ghost_window = nullptr;
+ GHOST_SystemWayland *ghost_system = nullptr;
struct wl_surface *wl_surface = nullptr;
/**
* Outputs on which the window is currently shown on.
@@ -102,6 +107,8 @@ struct GWL_Window {
WGL_XDG_Decor_Window *xdg_decor = nullptr;
wl_egl_window *egl_window = nullptr;
+
+ std::string title;
bool is_maximised = false;
bool is_fullscreen = false;
bool is_active = false;
@@ -111,6 +118,115 @@ struct GWL_Window {
int32_t size_pending[2] = {0, 0};
};
+static void gwl_window_title_set(GWL_Window *win, const char *title)
+{
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ WGL_LibDecor_Window &decor = *win->libdecor;
+ libdecor_frame_set_title(decor.frame, title);
+ }
+ else
+#endif
+ {
+ WGL_XDG_Decor_Window &decor = *win->xdg_decor;
+ xdg_toplevel_set_title(decor.toplevel, title);
+ }
+
+ win->title = title;
+}
+
+static GHOST_TWindowState gwl_window_state_get(const GWL_Window *win)
+{
+ if (win->is_fullscreen) {
+ return GHOST_kWindowStateFullScreen;
+ }
+ if (win->is_maximised) {
+ return GHOST_kWindowStateMaximized;
+ }
+ return GHOST_kWindowStateNormal;
+}
+
+static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state)
+{
+ const GHOST_TWindowState state_current = gwl_window_state_get(win);
+ switch (state) {
+ case GHOST_kWindowStateNormal:
+ /* Unset states. */
+ switch (state_current) {
+ case GHOST_kWindowStateMaximized: {
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ libdecor_frame_unset_maximized(win->libdecor->frame);
+ }
+ else
+#endif
+ {
+ xdg_toplevel_unset_maximized(win->xdg_decor->toplevel);
+ }
+ break;
+ }
+ case GHOST_kWindowStateFullScreen: {
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ libdecor_frame_unset_fullscreen(win->libdecor->frame);
+ }
+ else
+#endif
+ {
+ xdg_toplevel_unset_fullscreen(win->xdg_decor->toplevel);
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ case GHOST_kWindowStateMaximized: {
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ libdecor_frame_set_maximized(win->libdecor->frame);
+ }
+ else
+#endif
+ {
+ xdg_toplevel_set_maximized(win->xdg_decor->toplevel);
+ }
+ break;
+ }
+ case GHOST_kWindowStateMinimized: {
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ libdecor_frame_set_minimized(win->libdecor->frame);
+ }
+ else
+#endif
+ {
+ xdg_toplevel_set_minimized(win->xdg_decor->toplevel);
+ }
+ break;
+ }
+ case GHOST_kWindowStateFullScreen: {
+#ifdef WITH_GHOST_WAYLAND_LIBDECOR
+ if (use_libdecor) {
+ libdecor_frame_set_fullscreen(win->libdecor->frame, nullptr);
+ }
+ else
+#endif
+ {
+ xdg_toplevel_set_fullscreen(win->xdg_decor->toplevel, nullptr);
+ }
+ break;
+ }
+ case GHOST_kWindowStateEmbedded: {
+ return GHOST_kFailure;
+ }
+ }
+ return GHOST_kSuccess;
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Internal Utilities
* \{ */
@@ -219,7 +335,7 @@ static void xdg_toplevel_handle_close(void *data, xdg_toplevel * /*xdg_toplevel*
static_cast<GWL_Window *>(data)->ghost_window->close();
}
-static const xdg_toplevel_listener toplevel_listener = {
+static const xdg_toplevel_listener xdg_toplevel_listener = {
xdg_toplevel_handle_configure,
xdg_toplevel_handle_close,
};
@@ -248,6 +364,7 @@ static void frame_handle_configure(struct libdecor_frame *frame,
int size_next[2];
enum libdecor_window_state window_state;
struct libdecor_state *state;
+ bool do_redraw = false;
if (!libdecor_configuration_get_content_size(
configuration, frame, &size_next[0], &size_next[1])) {
@@ -255,11 +372,16 @@ static void frame_handle_configure(struct libdecor_frame *frame,
size_next[1] = win->size[1] / win->scale;
}
+ const int size_prev[2] = {UNPACK2(win->size)};
win->size[0] = win->scale * size_next[0];
win->size[1] = win->scale * size_next[1];
- wl_egl_window_resize(win->egl_window, UNPACK2(win->size), 0, 0);
- win->ghost_window->notify_size();
+ const bool do_resize = (size_prev[0] != win->size[0]) || (size_prev[1] != win->size[1]);
+
+ if (do_resize) {
+ wl_egl_window_resize(win->egl_window, UNPACK2(win->size), 0, 0);
+ win->ghost_window->notify_size();
+ }
if (!libdecor_configuration_get_window_state(configuration, &window_state)) {
window_state = LIBDECOR_WINDOW_STATE_NONE;
@@ -267,14 +389,34 @@ static void frame_handle_configure(struct libdecor_frame *frame,
win->is_maximised = window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED;
win->is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN;
+
+ GHOST_SystemWayland *system = win->ghost_system;
+ const bool is_active_prev_ghost = (win->ghost_window ==
+ system->getWindowManager()->getActiveWindow());
win->is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE;
+ if (is_active_prev_ghost != win->is_active) {
+ if (win->is_active) {
+ win->ghost_window->activate();
+ }
+ else {
+ win->ghost_window->deactivate();
+ }
+ }
- win->is_active ? win->ghost_window->activate() : win->ghost_window->deactivate();
+ const bool is_active_prev_decor = win->is_active;
+ if (is_active_prev_decor) {
+ /* Without this, activating another window doesn't refresh the title-bar as inactive. */
+ do_redraw = true;
+ }
state = libdecor_state_new(UNPACK2(size_next));
libdecor_frame_commit(frame, state, configuration);
libdecor_state_free(state);
+ if (do_redraw) {
+ win->ghost_window->swapBuffers();
+ }
+
win->libdecor->configured = true;
}
@@ -322,7 +464,7 @@ static void xdg_toplevel_decoration_handle_configure(
static_cast<GWL_Window *>(data)->xdg_decor->mode = (zxdg_toplevel_decoration_v1_mode)mode;
}
-static const zxdg_toplevel_decoration_v1_listener toplevel_decoration_v1_listener = {
+static const zxdg_toplevel_decoration_v1_listener xdg_toplevel_decoration_v1_listener = {
xdg_toplevel_decoration_handle_configure,
};
@@ -359,11 +501,16 @@ static void xdg_surface_handle_configure(void *data,
win->ghost_window->notify_size();
}
- if (win->is_active) {
- win->ghost_window->activate();
- }
- else {
- win->ghost_window->deactivate();
+ GHOST_SystemWayland *system = win->ghost_system;
+ const bool is_active_prev_ghost = (win->ghost_window ==
+ system->getWindowManager()->getActiveWindow());
+ if (is_active_prev_ghost != win->is_active) {
+ if (win->is_active) {
+ win->ghost_window->activate();
+ }
+ else {
+ win->ghost_window->deactivate();
+ }
}
xdg_surface_ack_configure(xdg_surface, serial);
@@ -418,7 +565,7 @@ static void surface_handle_leave(void *data,
}
}
-static struct wl_surface_listener wl_surface_listener = {
+static const struct wl_surface_listener wl_surface_listener = {
surface_handle_enter,
surface_handle_leave,
};
@@ -435,7 +582,7 @@ static struct wl_surface_listener wl_surface_listener = {
GHOST_TSuccess GHOST_WindowWayland::hasCursorShape(GHOST_TStandardCursor cursorShape)
{
- return system_->hasCursorShape(cursorShape);
+ return system_->cursor_shape_check(cursorShape);
}
GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
@@ -460,6 +607,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
}
window_->ghost_window = this;
+ window_->ghost_system = system;
window_->size[0] = int32_t(width);
window_->size[1] = int32_t(height);
@@ -483,7 +631,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
wl_surface_set_buffer_scale(window_->wl_surface, window_->scale);
- wl_surface_add_listener(window_->wl_surface, &wl_surface_listener, this);
+ wl_surface_add_listener(window_->wl_surface, &wl_surface_listener, window_);
window_->egl_window = wl_egl_window_create(
window_->wl_surface, int(window_->size[0]), int(window_->size[1]));
@@ -537,13 +685,13 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
system_->xdg_decor_manager(), decor.toplevel);
zxdg_toplevel_decoration_v1_add_listener(
- decor.toplevel_decor, &toplevel_decoration_v1_listener, window_);
+ decor.toplevel_decor, &xdg_toplevel_decoration_v1_listener, window_);
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
xdg_surface_add_listener(decor.surface, &xdg_surface_listener, window_);
- xdg_toplevel_add_listener(decor.toplevel, &toplevel_listener, window_);
+ xdg_toplevel_add_listener(decor.toplevel, &xdg_toplevel_listener, window_);
if (parentWindow && is_dialog) {
WGL_XDG_Decor_Window &decor_parent =
@@ -552,7 +700,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
}
}
- setTitle(title);
+ gwl_window_title_set(window_, title);
wl_surface_set_user_data(window_->wl_surface, this);
@@ -582,7 +730,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
if (use_libdecor == false)
#endif
{
- setState(state);
+ gwl_window_state_set(window_, state);
}
/* EGL context. */
@@ -618,47 +766,35 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mo
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorShape(GHOST_TStandardCursor shape)
{
- const GHOST_TSuccess ok = system_->setCursorShape(shape);
+ const GHOST_TSuccess ok = system_->cursor_shape_set(shape);
m_cursorShape = (ok == GHOST_kSuccess) ? shape : GHOST_kStandardCursorDefault;
return ok;
}
bool GHOST_WindowWayland::getCursorGrabUseSoftwareDisplay()
{
- return system_->getCursorGrabUseSoftwareDisplay(m_cursorGrab);
+ return system_->cursor_grab_use_software_display_get(m_cursorGrab);
}
GHOST_TSuccess GHOST_WindowWayland::setWindowCustomCursorShape(
uint8_t *bitmap, uint8_t *mask, int sizex, int sizey, int hotX, int hotY, bool canInvertColor)
{
- return system_->setCustomCursorShape(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
+ return system_->cursor_shape_custom_set(bitmap, mask, sizex, sizey, hotX, hotY, canInvertColor);
}
GHOST_TSuccess GHOST_WindowWayland::getCursorBitmap(GHOST_CursorBitmapRef *bitmap)
{
- return system_->getCursorBitmap(bitmap);
+ return system_->cursor_bitmap_get(bitmap);
}
void GHOST_WindowWayland::setTitle(const char *title)
{
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- WGL_LibDecor_Window &decor = *window_->libdecor;
- libdecor_frame_set_title(decor.frame, title);
- }
- else
-#endif
- {
- WGL_XDG_Decor_Window &decor = *window_->xdg_decor;
- xdg_toplevel_set_title(decor.toplevel, title);
- }
-
- title_ = title;
+ gwl_window_title_set(window_, title);
}
std::string GHOST_WindowWayland::getTitle() const
{
- return title_.empty() ? "untitled" : title_;
+ return window_->title.empty() ? "untitled" : window_->title;
}
void GHOST_WindowWayland::getWindowBounds(GHOST_Rect &bounds) const
@@ -754,96 +890,17 @@ uint16_t GHOST_WindowWayland::getDPIHint()
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
{
- return system_->setCursorVisibility(visible);
+ return system_->cursor_visibility_set(visible);
}
GHOST_TSuccess GHOST_WindowWayland::setState(GHOST_TWindowState state)
{
- switch (state) {
- case GHOST_kWindowStateNormal:
- /* Unset states. */
- switch (getState()) {
- case GHOST_kWindowStateMaximized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_unset_maximized(window_->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_unset_maximized(window_->xdg_decor->toplevel);
- }
- break;
- }
- case GHOST_kWindowStateFullScreen: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_unset_fullscreen(window_->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_unset_fullscreen(window_->xdg_decor->toplevel);
- }
- break;
- }
- default: {
- break;
- }
- }
- break;
- case GHOST_kWindowStateMaximized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_maximized(window_->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_set_maximized(window_->xdg_decor->toplevel);
- }
- break;
- }
- case GHOST_kWindowStateMinimized: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_minimized(window_->libdecor->frame);
- }
- else
-#endif
- {
- xdg_toplevel_set_minimized(window_->xdg_decor->toplevel);
- }
- break;
- }
- case GHOST_kWindowStateFullScreen: {
-#ifdef WITH_GHOST_WAYLAND_LIBDECOR
- if (use_libdecor) {
- libdecor_frame_set_fullscreen(window_->libdecor->frame, nullptr);
- }
- else
-#endif
- {
- xdg_toplevel_set_fullscreen(window_->xdg_decor->toplevel, nullptr);
- }
- break;
- }
- case GHOST_kWindowStateEmbedded: {
- return GHOST_kFailure;
- }
- }
- return GHOST_kSuccess;
+ return gwl_window_state_set(window_, state) ? GHOST_kSuccess : GHOST_kFailure;
}
GHOST_TWindowState GHOST_WindowWayland::getState() const
{
- if (window_->is_fullscreen) {
- return GHOST_kWindowStateFullScreen;
- }
- if (window_->is_maximised) {
- return GHOST_kWindowStateMaximized;
- }
- return GHOST_kWindowStateNormal;
+ return gwl_window_state_get(window_);
}
GHOST_TSuccess GHOST_WindowWayland::invalidate()
@@ -1070,7 +1127,7 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
/* As this is a low-level function, we might want adding this event to be optional,
* always add the event unless it causes issues. */
- GHOST_System *system = (GHOST_System *)GHOST_ISystem::getSystem();
+ GHOST_SystemWayland *system = window_->ghost_system;
system->pushEvent(
new GHOST_Event(system->getMilliSeconds(), GHOST_kEventWindowDPIHintChanged, this));
}
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index ec473c4a710..b9ef45358f2 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -119,7 +119,6 @@ class GHOST_WindowWayland : public GHOST_Window {
private:
GHOST_SystemWayland *system_;
struct GWL_Window *window_;
- std::string title_;
/**
* \param type: The type of rendering context create.
diff --git a/intern/wayland_dynload/extern/wayland_dynload_client.h b/intern/wayland_dynload/extern/wayland_dynload_client.h
index d80ef5c9f0c..22ec33b1ef2 100644
--- a/intern/wayland_dynload/extern/wayland_dynload_client.h
+++ b/intern/wayland_dynload/extern/wayland_dynload_client.h
@@ -14,8 +14,14 @@ extern "C" {
WAYLAND_DYNLOAD_FN(wl_display_connect)
WAYLAND_DYNLOAD_FN(wl_display_disconnect)
WAYLAND_DYNLOAD_FN(wl_display_dispatch)
+WAYLAND_DYNLOAD_FN(wl_display_dispatch_pending)
+WAYLAND_DYNLOAD_FN(wl_display_get_fd)
+WAYLAND_DYNLOAD_FN(wl_display_prepare_read)
+WAYLAND_DYNLOAD_FN(wl_display_read_events)
+WAYLAND_DYNLOAD_FN(wl_display_cancel_read)
WAYLAND_DYNLOAD_FN(wl_display_roundtrip)
WAYLAND_DYNLOAD_FN(wl_display_flush)
+WAYLAND_DYNLOAD_FN(wl_display_get_error)
WAYLAND_DYNLOAD_FN(wl_log_set_handler_client)
WAYLAND_DYNLOAD_FN(wl_proxy_add_listener)
WAYLAND_DYNLOAD_FN(wl_proxy_destroy)
@@ -67,7 +73,13 @@ struct WaylandDynload_Client {
void WL_DYN_FN(wl_display_disconnect)(struct wl_display *display);
int WL_DYN_FN(wl_display_dispatch)(struct wl_display *display);
int WL_DYN_FN(wl_display_roundtrip)(struct wl_display *display);
+ int WL_DYN_FN(wl_display_dispatch_pending)(struct wl_display *display);
+ int WL_DYN_FN(wl_display_get_fd)(struct wl_display *display);
+ int WL_DYN_FN(wl_display_prepare_read)(struct wl_display *display);
+ int WL_DYN_FN(wl_display_read_events)(struct wl_display *display);
+ void WL_DYN_FN(wl_display_cancel_read)(struct wl_display *display);
int WL_DYN_FN(wl_display_flush)(struct wl_display *display);
+ int WL_DYN_FN(wl_display_get_error)(struct wl_display *display);
void WL_DYN_FN(wl_log_set_handler_client)(wl_log_func_t);
int WL_DYN_FN(wl_proxy_add_listener)(struct wl_proxy *proxy,
void (**implementation)(void),
@@ -101,8 +113,18 @@ struct WaylandDynload_Client {
# define wl_display_disconnect(...) \
(*wayland_dynload_client.wl_display_disconnect)(__VA_ARGS__)
# define wl_display_dispatch(...) (*wayland_dynload_client.wl_display_dispatch)(__VA_ARGS__)
+# define wl_display_dispatch_pending(...) \
+ (*wayland_dynload_client.wl_display_dispatch)(__VA_ARGS__)
+# define wl_display_get_fd(...) (*wayland_dynload_client.wl_display_get_fd)(__VA_ARGS__)
+# define wl_display_prepare_read(...) \
+ (*wayland_dynload_client.wl_display_prepare_read)(__VA_ARGS__)
+# define wl_display_read_events(...) \
+ (*wayland_dynload_client.wl_display_read_events)(__VA_ARGS__)
+# define wl_display_cancel_read(...) \
+ (*wayland_dynload_client.wl_display_cancel_read)(__VA_ARGS__)
# define wl_display_roundtrip(...) (*wayland_dynload_client.wl_display_roundtrip)(__VA_ARGS__)
# define wl_display_flush(...) (*wayland_dynload_client.wl_display_flush)(__VA_ARGS__)
+# define wl_display_get_error(...) (*wayland_dynload_client.wl_display_get_error)(__VA_ARGS__)
# define wl_log_set_handler_client(...) \
(*wayland_dynload_client.wl_log_set_handler_client)(__VA_ARGS__)
# define wl_proxy_add_listener(...) \
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject 5a818af95080cccf04dfa8317f0e966bff515c6
+Subproject c226f867affd12881533a54c8c90ac6eebfaca6
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index a6b97fbdc85..fdc9b4572d3 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -81,6 +81,7 @@ class MESH_MT_color_attribute_context_menu(Menu):
"geometry.color_attribute_duplicate",
icon='DUPLICATE',
)
+ layout.operator("geometry.color_attribute_convert")
class MESH_MT_attribute_context_menu(Menu):
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index a1c7e5c54de..b43434d9988 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -310,6 +310,11 @@ class NLA_MT_context_menu(Menu):
layout.separator()
+ layout.operator("nla.meta_add")
+ layout.operator("nla.meta_remove")
+
+ layout.separator()
+
layout.operator("nla.swap")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 6f619498a23..0621f4a02af 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -3213,11 +3213,11 @@ class VIEW3D_MT_sculpt(Menu):
props.action = 'SHOW'
props.area = 'ALL'
- props = layout.operator("paint.hide_show", text="Show Bounding Box")
+ props = layout.operator("paint.hide_show", text="Box Show")
props.action = 'SHOW'
props.area = 'INSIDE'
- props = layout.operator("paint.hide_show", text="Hide Bounding Box")
+ props = layout.operator("paint.hide_show", text="Box Hide")
props.action = 'HIDE'
props.area = 'INSIDE'
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 111fb0d8bae..8ebc385a8ee 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1020,6 +1020,7 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
layout.prop(sculpt, "symmetrize_direction")
layout.operator("sculpt.symmetrize")
+ layout.prop(WindowManager.operator_properties_last("sculpt.symmetrize"), "merge_tolerance")
class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel):
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index 13eefd27bec..3f4981993eb 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -90,7 +90,7 @@ int BKE_id_attributes_length(const struct ID *id,
eCustomDataMask mask);
struct CustomDataLayer *BKE_id_attributes_active_get(struct ID *id);
-void BKE_id_attributes_active_set(struct ID *id, struct CustomDataLayer *layer);
+void BKE_id_attributes_active_set(struct ID *id, const char *name);
int *BKE_id_attributes_active_index_p(struct ID *id);
CustomData *BKE_id_attributes_iterator_next_domain(struct ID *id, struct CustomDataLayer *layers);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index cbdf37e14bd..b4de24e3b64 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -167,7 +167,7 @@ void set_active_fmodifier(ListBase *modifiers, struct FModifier *fcm);
* \param mtype: Type of modifier (if 0, doesn't matter).
* \param acttype: Type of action to perform (if -1, doesn't matter).
*/
-bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype);
+bool list_has_suitable_fmodifier(const ListBase *modifiers, int mtype, short acttype);
typedef struct FModifiersStackStorage {
uint modifier_count;
@@ -369,12 +369,12 @@ int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache,
* Calculate the extents of F-Curve's keyframes.
*/
bool BKE_fcurve_calc_range(
- struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length);
+ const struct FCurve *fcu, float *min, float *max, bool do_sel_only, bool do_min_length);
/**
* Calculate the extents of F-Curve's data.
*/
-bool BKE_fcurve_calc_bounds(struct FCurve *fcu,
+bool BKE_fcurve_calc_bounds(const struct FCurve *fcu,
float *xmin,
float *xmax,
float *ymin,
@@ -421,14 +421,14 @@ void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, flo
* Usability of keyframes refers to whether they should be displayed,
* and also whether they will have any influence on the final result.
*/
-bool BKE_fcurve_are_keyframes_usable(struct FCurve *fcu);
+bool BKE_fcurve_are_keyframes_usable(const struct FCurve *fcu);
/**
* Can keyframes be added to F-Curve?
* Keyframes can only be added if they are already visible.
*/
-bool BKE_fcurve_is_keyframable(struct FCurve *fcu);
-bool BKE_fcurve_is_protected(struct FCurve *fcu);
+bool BKE_fcurve_is_keyframable(const struct FCurve *fcu);
+bool BKE_fcurve_is_protected(const struct FCurve *fcu);
/**
* Are any of the keyframe control points selected on the F-Curve?
@@ -439,7 +439,7 @@ bool BKE_fcurve_has_selected_control_points(const struct FCurve *fcu);
* Checks if the F-Curve has a Cycles modifier with simple settings
* that warrant transition smoothing.
*/
-bool BKE_fcurve_is_cyclic(struct FCurve *fcu);
+bool BKE_fcurve_is_cyclic(const struct FCurve *fcu);
/* Type of infinite cycle for a curve. */
typedef enum eFCU_Cycle_Type {
@@ -453,7 +453,7 @@ typedef enum eFCU_Cycle_Type {
/**
* Checks if the F-Curve has a Cycles modifier, and returns the type of the cycle behavior.
*/
-eFCU_Cycle_Type BKE_fcurve_get_cycle_type(struct FCurve *fcu);
+eFCU_Cycle_Type BKE_fcurve_get_cycle_type(const struct FCurve *fcu);
/**
* Recompute bezier handles of all three given BezTriples, so that `bezt` can be inserted between
@@ -544,7 +544,7 @@ float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna,
/**
* Checks if the curve has valid keys, drivers or modifiers that produce an actual curve.
*/
-bool BKE_fcurve_is_empty(struct FCurve *fcu);
+bool BKE_fcurve_is_empty(const struct FCurve *fcu);
/**
* Calculate the value of the given F-Curve at the given frame,
* and store it's value in #FCurve.curval.
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 8f6786d4113..b1488c93ba6 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -494,15 +494,6 @@ void BKE_mesh_calc_normals_looptri(const struct MVert *mverts,
const struct MLoopTri *looptri,
int looptri_num,
float (*r_tri_nors)[3]);
-void BKE_mesh_loop_manifold_fan_around_vert_next(const struct MLoop *mloops,
- const struct MPoly *mpolys,
- const int *loop_to_poly,
- const int *e2lfan_curr,
- uint mv_pivot_index,
- const struct MLoop **r_mlfan_curr,
- int *r_mlfan_curr_index,
- int *r_mlfan_vert_index,
- int *r_mpfan_curr_index);
/**
* Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
@@ -630,6 +621,8 @@ void BKE_lnor_space_custom_normal_to_data(MLoopNorSpace *lnor_space,
* Compute split normals, i.e. vertex normals associated with each poly (hence 'loop normals').
* Useful to materialize sharp edges (or non-smooth faces) without actually modifying the geometry
* (splitting edges).
+ *
+ * \param loop_to_poly_map: Optional pre-created map from loops to their polygon.
*/
void BKE_mesh_normals_loop_split(const struct MVert *mverts,
const float (*vert_normals)[3],
@@ -644,9 +637,9 @@ void BKE_mesh_normals_loop_split(const struct MVert *mverts,
int numPolys,
bool use_split_normals,
float split_angle,
+ const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
- short (*clnors_data)[2],
- int *r_loop_to_poly);
+ short (*clnors_data)[2]);
void BKE_mesh_normals_loop_custom_set(const struct MVert *mverts,
const float (*vert_normals)[3],
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4d883f9e31e..ae8eea4a6bf 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -746,7 +746,14 @@ struct bNode *nodeFindNodebyName(struct bNodeTree *ntree, const char *name);
/**
* Finds a node based on given socket and returns true on success.
*/
-bool nodeFindNode(struct bNodeTree *ntree,
+bool nodeFindNodeTry(struct bNodeTree *ntree,
+ struct bNodeSocket *sock,
+ struct bNode **r_node,
+ int *r_sockindex);
+/**
+ * Same as above but expects that the socket definitely is in the node tree.
+ */
+void nodeFindNode(struct bNodeTree *ntree,
struct bNodeSocket *sock,
struct bNode **r_node,
int *r_sockindex);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 9fc4aa5307d..434255b2d9c 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -119,6 +119,7 @@ typedef enum ePaintSymmetryAreas {
PAINT_SYMM_AREA_Y = (1 << 1),
PAINT_SYMM_AREA_Z = (1 << 2),
} ePaintSymmetryAreas;
+ENUM_OPERATORS(ePaintSymmetryAreas, PAINT_SYMM_AREA_Z);
#define PAINT_SYMM_AREAS 8
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index b375d69b61c..4badd1bc269 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -416,6 +416,8 @@ typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
} PBVHTopologyUpdateMode;
+ENUM_OPERATORS(PBVHTopologyUpdateMode, PBVH_Collapse);
+
/**
* Collapse short edges, subdivide long edges.
*/
diff --git a/source/blender/blenkernel/intern/attribute.cc b/source/blender/blenkernel/intern/attribute.cc
index 1a54454bf9a..80647362826 100644
--- a/source/blender/blenkernel/intern/attribute.cc
+++ b/source/blender/blenkernel/intern/attribute.cc
@@ -495,29 +495,14 @@ CustomDataLayer *BKE_id_attributes_active_get(ID *id)
return nullptr;
}
-void BKE_id_attributes_active_set(ID *id, CustomDataLayer *active_layer)
+void BKE_id_attributes_active_set(ID *id, const char *name)
{
- DomainInfo info[ATTR_DOMAIN_NUM];
- get_domains(id, info);
-
- int index = 0;
+ const CustomDataLayer *layer = BKE_id_attribute_search(
+ id, name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
+ BLI_assert(layer != nullptr);
- for (const int domain : IndexRange(ATTR_DOMAIN_NUM)) {
- const CustomData *customdata = info[domain].customdata;
- if (customdata == nullptr) {
- continue;
- }
- for (int i = 0; i < customdata->totlayer; i++) {
- const CustomDataLayer *layer = &customdata->layers[i];
- if (layer == active_layer) {
- *BKE_id_attributes_active_index_p(id) = index;
- return;
- }
- if (CD_MASK_PROP_ALL & CD_TYPE_AS_MASK(layer->type)) {
- index++;
- }
- }
- }
+ const int index = BKE_id_attribute_to_index(id, layer, ATTR_DOMAIN_MASK_ALL, CD_MASK_PROP_ALL);
+ *BKE_id_attributes_active_index_p(id) = index;
}
int *BKE_id_attributes_active_index_p(ID *id)
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index 84aa2207400..bccb625feb2 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -2799,6 +2799,14 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
const LayerTypeInfo *typeInfo = layerType_getInfo(type);
int flag = 0;
+ /* Some layer types only support a single layer. */
+ if (!typeInfo->defaultname && CustomData_has_layer(data, type)) {
+ /* This function doesn't support dealing with existing layer data for these layer types when
+ * the layer already exists. */
+ BLI_assert(layerdata == nullptr);
+ return &data->layers[CustomData_get_layer_index(data, type)];
+ }
+
void *newlayerdata = nullptr;
switch (alloctype) {
case CD_SET_DEFAULT:
@@ -2851,21 +2859,6 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
break;
}
- /* Some layer types only support a single layer. */
- const bool reuse_existing_layer = !typeInfo->defaultname && CustomData_has_layer(data, type);
- if (reuse_existing_layer) {
- CustomDataLayer &layer = data->layers[CustomData_get_layer_index(data, type)];
- if (layer.data != nullptr) {
- if (typeInfo->free) {
- typeInfo->free(layer.data, totelem, typeInfo->size);
- }
- MEM_SAFE_FREE(layer.data);
- }
- layer.data = newlayerdata;
- layer.flag = flag;
- return &layer;
- }
-
int index = data->totlayer;
if (index >= data->maxlayer) {
if (!customData_resize(data, CUSTOMDATA_GROW)) {
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index e6afca11b40..7b81f74206d 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -300,8 +300,8 @@ static void data_transfer_dtdata_type_preprocess(Mesh *me_src,
use_split_nors_dst,
split_angle_dst,
NULL,
- custom_nors_dst,
- NULL);
+ NULL,
+ custom_nors_dst);
}
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index d248faaab00..3e772e37177 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -85,8 +85,6 @@ void BKE_fcurve_free(FCurve *fcu)
void BKE_fcurves_free(ListBase *list)
{
- FCurve *fcu, *fcn;
-
/* Sanity check. */
if (list == NULL) {
return;
@@ -96,7 +94,8 @@ void BKE_fcurves_free(ListBase *list)
* as we store reference to next, and freeing only touches the curve
* it's given.
*/
- for (fcu = list->first; fcu; fcu = fcn) {
+ FCurve *fcn = NULL;
+ for (FCurve *fcu = list->first; fcu; fcu = fcn) {
fcn = fcu->next;
BKE_fcurve_free(fcu);
}
@@ -113,15 +112,13 @@ void BKE_fcurves_free(ListBase *list)
FCurve *BKE_fcurve_copy(const FCurve *fcu)
{
- FCurve *fcu_d;
-
/* Sanity check. */
if (fcu == NULL) {
return NULL;
}
/* Make a copy. */
- fcu_d = MEM_dupallocN(fcu);
+ FCurve *fcu_d = MEM_dupallocN(fcu);
fcu_d->next = fcu_d->prev = NULL;
fcu_d->grp = NULL;
@@ -145,8 +142,6 @@ FCurve *BKE_fcurve_copy(const FCurve *fcu)
void BKE_fcurves_copy(ListBase *dst, ListBase *src)
{
- FCurve *dfcu, *sfcu;
-
/* Sanity checks. */
if (ELEM(NULL, dst, src)) {
return;
@@ -156,8 +151,8 @@ void BKE_fcurves_copy(ListBase *dst, ListBase *src)
BLI_listbase_clear(dst);
/* Copy one-by-one. */
- for (sfcu = src->first; sfcu; sfcu = sfcu->next) {
- dfcu = BKE_fcurve_copy(sfcu);
+ LISTBASE_FOREACH (FCurve *, sfcu, src) {
+ FCurve *dfcu = BKE_fcurve_copy(sfcu);
BLI_addtail(dst, dfcu);
}
}
@@ -203,12 +198,10 @@ FCurve *id_data_find_fcurve(
{
/* Anim vars */
AnimData *adt = BKE_animdata_from_id(id);
- FCurve *fcu = NULL;
/* Rna vars */
PointerRNA ptr;
PropertyRNA *prop;
- char *path;
if (r_driven) {
*r_driven = false;
@@ -225,7 +218,7 @@ FCurve *id_data_find_fcurve(
return NULL;
}
- path = RNA_path_from_ID_to_property(&ptr, prop);
+ char *path = RNA_path_from_ID_to_property(&ptr, prop);
if (path == NULL) {
return NULL;
}
@@ -233,7 +226,7 @@ FCurve *id_data_find_fcurve(
/* FIXME: The way drivers are handled here (always NULL-ifying `fcu`) is very weird, this needs
* to be re-checked I think?. */
bool is_driven = false;
- fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, NULL, &is_driven);
+ FCurve *fcu = BKE_animadata_fcurve_find_by_rna_path(adt, path, index, NULL, &is_driven);
if (is_driven) {
if (r_driven != NULL) {
*r_driven = is_driven;
@@ -248,15 +241,13 @@ FCurve *id_data_find_fcurve(
FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_index)
{
- FCurve *fcu;
-
/* Sanity checks. */
- if (ELEM(NULL, list, rna_path) || (array_index < 0)) {
+ if (ELEM(NULL, list, rna_path) || array_index < 0) {
return NULL;
}
/* Check paths of curves, then array indices... */
- for (fcu = list->first; fcu; fcu = fcu->next) {
+ LISTBASE_FOREACH (FCurve *, fcu, list) {
/* Check indices first, much cheaper than a string comparison. */
/* Simple string-compare (this assumes that they have the same root...) */
if (UNLIKELY(fcu->array_index == array_index && fcu->rna_path &&
@@ -276,15 +267,13 @@ FCurve *BKE_fcurve_find(ListBase *list, const char rna_path[], const int array_i
FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
{
- FCurve *fcu;
-
/* Sanity checks. */
if (ELEM(NULL, fcu_iter, rna_path)) {
return NULL;
}
/* Check paths of curves, then array indices... */
- for (fcu = fcu_iter; fcu; fcu = fcu->next) {
+ for (FCurve *fcu = fcu_iter; fcu; fcu = fcu->next) {
/* Simple string-compare (this assumes that they have the same root...) */
if (fcu->rna_path && STREQ(fcu->rna_path, rna_path)) {
return fcu;
@@ -296,7 +285,6 @@ FCurve *BKE_fcurve_iter_step(FCurve *fcu_iter, const char rna_path[])
int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, const char *dataName)
{
- FCurve *fcu;
int matches = 0;
/* Sanity checks. */
@@ -311,7 +299,7 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
char *quotedName = alloca(quotedName_size);
/* Search each F-Curve one by one. */
- for (fcu = src->first; fcu; fcu = fcu->next) {
+ LISTBASE_FOREACH (FCurve *, fcu, src) {
/* Check if quoted string matches the path. */
if (fcu->rna_path == NULL) {
continue;
@@ -487,16 +475,14 @@ static int BKE_fcurve_bezt_binarysearch_index_ex(const BezTriple array[],
* - Keyframe to be added is to be added out of current bounds.
* - Keyframe to be added would replace one of the existing ones on bounds.
*/
- if ((arraylen <= 0) || (array == NULL)) {
+ if (arraylen <= 0 || array == NULL) {
CLOG_WARN(&LOG, "encountered invalid array");
return 0;
}
/* Check whether to add before/after/on. */
- float framenum;
-
/* 'First' Keyframe (when only one keyframe, this case is used) */
- framenum = array[0].vec[1][0];
+ float framenum = array[0].vec[1][0];
if (IS_EQT(frame, framenum, threshold)) {
*r_replace = true;
return 0;
@@ -522,9 +508,9 @@ static int BKE_fcurve_bezt_binarysearch_index_ex(const BezTriple array[],
/* Compute and get midpoint. */
/* We calculate the midpoint this way to avoid int overflows... */
- int mid = start + ((end - start) / 2);
+ const int mid = start + ((end - start) / 2);
- float midfra = array[mid].vec[1][0];
+ const float midfra = array[mid].vec[1][0];
/* Check if exactly equal to midpoint. */
if (IS_EQT(frame, midfra, threshold)) {
@@ -571,7 +557,7 @@ int BKE_fcurve_bezt_binarysearch_index(const BezTriple array[],
/* ...................................... */
/* Helper for calc_fcurve_* functions -> find first and last BezTriple to be used. */
-static short get_fcurve_end_keyframes(FCurve *fcu,
+static short get_fcurve_end_keyframes(const FCurve *fcu,
BezTriple **first,
BezTriple **last,
const bool do_sel_only)
@@ -589,10 +575,8 @@ static short get_fcurve_end_keyframes(FCurve *fcu,
/* Only include selected items? */
if (do_sel_only) {
- BezTriple *bezt;
-
/* Find first selected. */
- bezt = fcu->bezt;
+ BezTriple *bezt = fcu->bezt;
for (int i = 0; i < fcu->totvert; bezt++, i++) {
if (BEZT_ISSEL_ANY(bezt)) {
*first = bezt;
@@ -621,7 +605,7 @@ static short get_fcurve_end_keyframes(FCurve *fcu,
return found;
}
-bool BKE_fcurve_calc_bounds(FCurve *fcu,
+bool BKE_fcurve_calc_bounds(const FCurve *fcu,
float *xmin,
float *xmax,
float *ymin,
@@ -696,10 +680,9 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu,
/* Only loop over keyframes to find extents for values if needed. */
if (ymin || ymax) {
- FPoint *fpt;
- int i;
+ int i = 0;
- for (fpt = fcu->fpt, i = 0; i < fcu->totvert; fpt++, i++) {
+ for (FPoint *fpt = fcu->fpt; i < fcu->totvert; fpt++, i++) {
if (fpt->vec[1] < yminv) {
yminv = fpt->vec[1];
}
@@ -752,7 +735,7 @@ bool BKE_fcurve_calc_bounds(FCurve *fcu,
}
bool BKE_fcurve_calc_range(
- FCurve *fcu, float *start, float *end, const bool do_sel_only, const bool do_min_length)
+ const FCurve *fcu, float *start, float *end, const bool do_sel_only, const bool do_min_length)
{
float min = 999999999.0f, max = -999999999.0f;
bool foundvert = false;
@@ -855,7 +838,7 @@ void BKE_fcurve_active_keyframe_set(FCurve *fcu, const BezTriple *active_bezt)
/* Gracefully handle out-of-bounds pointers. Ideally this would do a BLI_assert() as well, but
* then the unit tests would break in debug mode. */
- ptrdiff_t offset = active_bezt - fcu->bezt;
+ const ptrdiff_t offset = active_bezt - fcu->bezt;
if (offset < 0 || offset >= fcu->totvert) {
fcu->active_keyframe_index = FCURVE_ACTIVE_KEYFRAME_NONE;
return;
@@ -872,8 +855,7 @@ int BKE_fcurve_active_keyframe_index(const FCurve *fcu)
const int active_keyframe_index = fcu->active_keyframe_index;
/* Array access boundary checks. */
- if ((fcu->bezt == NULL) || (active_keyframe_index >= fcu->totvert) ||
- (active_keyframe_index < 0)) {
+ if (fcu->bezt == NULL || active_keyframe_index >= fcu->totvert || active_keyframe_index < 0) {
return FCURVE_ACTIVE_KEYFRAME_NONE;
}
@@ -900,7 +882,7 @@ void BKE_fcurve_keyframe_move_value_with_handles(struct BezTriple *keyframe, con
/** \name Status Checks
* \{ */
-bool BKE_fcurve_are_keyframes_usable(FCurve *fcu)
+bool BKE_fcurve_are_keyframes_usable(const FCurve *fcu)
{
/* F-Curve must exist. */
if (fcu == NULL) {
@@ -914,11 +896,9 @@ bool BKE_fcurve_are_keyframes_usable(FCurve *fcu)
/* If it has modifiers, none of these should "drastically" alter the curve. */
if (fcu->modifiers.first) {
- FModifier *fcm;
-
/* Check modifiers from last to first, as last will be more influential. */
/* TODO: optionally, only check modifier if it is the active one... (Joshua Leung 2010) */
- for (fcm = fcu->modifiers.last; fcm; fcm = fcm->prev) {
+ LISTBASE_FOREACH_BACKWARD (FModifier *, fcm, &fcu->modifiers) {
/* Ignore if muted/disabled. */
if (fcm->flag & (FMODIFIER_FLAG_DISABLED | FMODIFIER_FLAG_MUTED)) {
continue;
@@ -960,9 +940,9 @@ bool BKE_fcurve_are_keyframes_usable(FCurve *fcu)
return true;
}
-bool BKE_fcurve_is_protected(FCurve *fcu)
+bool BKE_fcurve_is_protected(const FCurve *fcu)
{
- return ((fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)));
+ return ((fcu->flag & FCURVE_PROTECTED) || (fcu->grp && (fcu->grp->flag & AGRP_PROTECTED)));
}
bool BKE_fcurve_has_selected_control_points(const FCurve *fcu)
@@ -977,7 +957,7 @@ bool BKE_fcurve_has_selected_control_points(const FCurve *fcu)
return false;
}
-bool BKE_fcurve_is_keyframable(FCurve *fcu)
+bool BKE_fcurve_is_keyframable(const FCurve *fcu)
{
/* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */
if (BKE_fcurve_are_keyframes_usable(fcu) == 0) {
@@ -1048,9 +1028,6 @@ float fcurve_samplingcb_evalcurve(FCurve *fcu, void *UNUSED(data), float evaltim
void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSampleFunc sample_cb)
{
- FPoint *fpt, *new_fpt;
- int cfra;
-
/* Sanity checks. */
/* TODO: make these tests report errors using reports not CLOG's (Joshua Leung 2009) */
if (ELEM(NULL, fcu, sample_cb)) {
@@ -1063,10 +1040,11 @@ void fcurve_store_samples(FCurve *fcu, void *data, int start, int end, FcuSample
}
/* Set up sample data. */
- fpt = new_fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "FPoint Samples");
+ FPoint *new_fpt;
+ FPoint *fpt = new_fpt = MEM_callocN(sizeof(FPoint) * (end - start + 1), "FPoint Samples");
/* Use the sampling callback at 1-frame intervals from start to end frames. */
- for (cfra = start; cfra <= end; cfra++, fpt++) {
+ for (int cfra = start; cfra <= end; cfra++, fpt++) {
fpt->vec[0] = (float)cfra;
fpt->vec[1] = sample_cb(fcu, data, (float)cfra);
}
@@ -1119,12 +1097,12 @@ void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end)
MEM_freeN(fcu->bezt);
}
- BezTriple *bezt;
FPoint *fpt = fcu->fpt;
int keyframes_to_insert = end - start;
int sample_points = fcu->totvert;
- bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)keyframes_to_insert, __func__);
+ BezTriple *bezt = fcu->bezt = MEM_callocN(sizeof(*fcu->bezt) * (size_t)keyframes_to_insert,
+ __func__);
fcu->totvert = keyframes_to_insert;
/* Get first sample point to 'copy' as keyframe. */
@@ -1168,7 +1146,7 @@ void fcurve_samples_to_keyframes(FCurve *fcu, const int start, const int end)
* that the handles are correct.
*/
-eFCU_Cycle_Type BKE_fcurve_get_cycle_type(FCurve *fcu)
+eFCU_Cycle_Type BKE_fcurve_get_cycle_type(const FCurve *fcu)
{
FModifier *fcm = fcu->modifiers.first;
@@ -1201,7 +1179,7 @@ eFCU_Cycle_Type BKE_fcurve_get_cycle_type(FCurve *fcu)
return FCU_CYCLE_NONE;
}
-bool BKE_fcurve_is_cyclic(FCurve *fcu)
+bool BKE_fcurve_is_cyclic(const FCurve *fcu)
{
return BKE_fcurve_get_cycle_type(fcu) != FCU_CYCLE_NONE;
}
@@ -1231,7 +1209,6 @@ static BezTriple *cycle_offset_triple(
void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
{
- BezTriple *bezt, *prev, *next;
int a = fcu->totvert;
/* Error checking:
@@ -1247,12 +1224,12 @@ void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
BezTriple tmp;
- bool cycle = BKE_fcurve_is_cyclic(fcu) && BEZT_IS_AUTOH(first) && BEZT_IS_AUTOH(last);
+ const bool cycle = BKE_fcurve_is_cyclic(fcu) && BEZT_IS_AUTOH(first) && BEZT_IS_AUTOH(last);
/* Get initial pointers. */
- bezt = fcu->bezt;
- prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert - 2], last, first);
- next = (bezt + 1);
+ BezTriple *bezt = fcu->bezt;
+ BezTriple *prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert - 2], last, first);
+ BezTriple *next = (bezt + 1);
/* Loop over all beztriples, adjusting handles. */
while (a--) {
@@ -1319,15 +1296,14 @@ void BKE_fcurve_handles_recalc(FCurve *fcu)
void testhandles_fcurve(FCurve *fcu, eBezTriple_Flag sel_flag, const bool use_handle)
{
- BezTriple *bezt;
- uint a;
-
/* Only beztriples have handles (bpoints don't though). */
if (ELEM(NULL, fcu, fcu->bezt)) {
return;
}
/* Loop over beztriples. */
+ BezTriple *bezt;
+ uint a;
for (a = 0, bezt = fcu->bezt; a < fcu->totvert; a++, bezt++) {
BKE_nurb_bezt_handle_test(bezt, sel_flag, use_handle, false);
}
@@ -1701,12 +1677,12 @@ void BKE_fcurve_delete_key(FCurve *fcu, int index)
bool BKE_fcurve_delete_keys_selected(FCurve *fcu)
{
- bool changed = false;
-
if (fcu->bezt == NULL) { /* ignore baked curves */
return false;
}
+ bool changed = false;
+
/* Delete selected BezTriples */
for (int i = 0; i < fcu->totvert; i++) {
if (fcu->bezt[i].f2 & SELECT) {
@@ -1742,9 +1718,9 @@ void BKE_fcurve_delete_keys_all(FCurve *fcu)
static float fcurve_eval_keyframes_extrapolate(
FCurve *fcu, BezTriple *bezts, float evaltime, int endpoint_offset, int direction_to_neighbor)
{
- BezTriple *endpoint_bezt = bezts + endpoint_offset; /* The first/last keyframe. */
- BezTriple *neighbor_bezt = endpoint_bezt +
- direction_to_neighbor; /* The second (to last) keyframe. */
+ const BezTriple *endpoint_bezt = bezts + endpoint_offset; /* The first/last keyframe. */
+ const BezTriple *neighbor_bezt = endpoint_bezt +
+ direction_to_neighbor; /* The second (to last) keyframe. */
if (endpoint_bezt->ipo == BEZT_IPO_CONST || fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT ||
(fcu->flag & FCURVE_DISCRETE_VALUES) != 0) {
@@ -1759,7 +1735,7 @@ static float fcurve_eval_keyframes_extrapolate(
return endpoint_bezt->vec[1][1];
}
- float dx = endpoint_bezt->vec[1][0] - evaltime;
+ const float dx = endpoint_bezt->vec[1][0] - evaltime;
float fac = neighbor_bezt->vec[1][0] - endpoint_bezt->vec[1][0];
/* Prevent division by zero. */
@@ -1773,8 +1749,8 @@ static float fcurve_eval_keyframes_extrapolate(
/* Use the gradient of the second handle (later) of neighbor to calculate the gradient and thus
* the value of the curve at evaluation time. */
- int handle = direction_to_neighbor > 0 ? 0 : 2;
- float dx = endpoint_bezt->vec[1][0] - evaltime;
+ const int handle = direction_to_neighbor > 0 ? 0 : 2;
+ const float dx = endpoint_bezt->vec[1][0] - evaltime;
float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[handle][0];
/* Prevent division by zero. */
@@ -1786,10 +1762,11 @@ static float fcurve_eval_keyframes_extrapolate(
return endpoint_bezt->vec[1][1] - (fac * dx);
}
-static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, float evaltime)
+static float fcurve_eval_keyframes_interpolate(const FCurve *fcu,
+ const BezTriple *bezts,
+ float evaltime)
{
const float eps = 1.e-8f;
- BezTriple *bezt, *prevbezt;
uint a;
/* Evaltime occurs somewhere in the middle of the curve. */
@@ -1806,7 +1783,7 @@ static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, fl
* This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd.
*/
a = BKE_fcurve_bezt_binarysearch_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact);
- bezt = bezts + a;
+ const BezTriple *bezt = bezts + a;
if (exact) {
/* Index returned must be interpreted differently when it sits on top of an existing keyframe
@@ -1818,7 +1795,7 @@ static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, fl
/* Index returned refers to the keyframe that the eval-time occurs *before*
* - hence, that keyframe marks the start of the segment we're dealing with.
*/
- prevbezt = (a > 0) ? (bezt - 1) : bezt;
+ const BezTriple *prevbezt = (a > 0) ? (bezt - 1) : bezt;
/* Use if the key is directly on the frame, in rare cases this is needed else we get 0.0 instead.
* XXX: consult T39207 for examples of files where failure of these checks can cause issues. */
@@ -2054,7 +2031,7 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, 0, +1);
}
- BezTriple *lastbezt = bezts + fcu->totvert - 1;
+ const BezTriple *lastbezt = bezts + fcu->totvert - 1;
if (lastbezt->vec[1][0] <= evaltime) {
return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, fcu->totvert - 1, -1);
}
@@ -2063,14 +2040,13 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime
}
/* Calculate F-Curve value for 'evaltime' using #FPoint samples. */
-static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
+static float fcurve_eval_samples(const FCurve *fcu, const FPoint *fpts, float evaltime)
{
- FPoint *prevfpt, *lastfpt, *fpt;
float cvalue = 0.0f;
/* Get pointers. */
- prevfpt = fpts;
- lastfpt = prevfpt + fcu->totvert - 1;
+ const FPoint *prevfpt = fpts;
+ const FPoint *lastfpt = prevfpt + fcu->totvert - 1;
/* Evaluation time at or past endpoints? */
if (prevfpt->vec[0] >= evaltime) {
@@ -2085,10 +2061,10 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
float t = fabsf(evaltime - floorf(evaltime));
/* Find the one on the right frame (assume that these are spaced on 1-frame intervals). */
- fpt = prevfpt + ((int)evaltime - (int)prevfpt->vec[0]);
+ const FPoint *fpt = prevfpt + ((int)evaltime - (int)prevfpt->vec[0]);
/* If not exactly on the frame, perform linear interpolation with the next one. */
- if ((t != 0.0f) && (t < 1.0f)) {
+ if (t != 0.0f && t < 1.0f) {
cvalue = interpf(fpt->vec[1], (fpt + 1)->vec[1], 1.0f - t);
}
else {
@@ -2110,15 +2086,14 @@ static float fcurve_eval_samples(FCurve *fcu, FPoint *fpts, float evaltime)
*/
static float evaluate_fcurve_ex(FCurve *fcu, float evaltime, float cvalue)
{
- float devaltime;
-
/* Evaluate modifiers which modify time to evaluate the base curve at. */
FModifiersStackStorage storage;
storage.modifier_count = BLI_listbase_count(&fcu->modifiers);
storage.size_per_modifier = evaluate_fmodifiers_storage_size_per_modifier(&fcu->modifiers);
storage.buffer = alloca(storage.modifier_count * storage.size_per_modifier);
- devaltime = evaluate_time_fmodifiers(&storage, &fcu->modifiers, fcu, cvalue, evaltime);
+ const float devaltime = evaluate_time_fmodifiers(
+ &storage, &fcu->modifiers, fcu, cvalue, evaltime);
/* Evaluate curve-data
* - 'devaltime' instead of 'evaltime', as this is the time that the last time-modifying
@@ -2177,16 +2152,15 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna,
/* Only do a default 1-1 mapping if it's unlikely that anything else will set a value... */
if (fcu->totvert == 0) {
- FModifier *fcm;
bool do_linear = true;
/* Out-of-range F-Modifiers will block, as will those which just plain overwrite the values
* XXX: additive is a bit more dicey; it really depends then if things are in range or not...
*/
- for (fcm = fcu->modifiers.first; fcm; fcm = fcm->next) {
+ LISTBASE_FOREACH (FModifier *, fcm, &fcu->modifiers) {
/* If there are range-restrictions, we must definitely block T36950. */
if ((fcm->flag & FMODIFIER_FLAG_RANGERESTRICT) == 0 ||
- ((fcm->sfra <= evaltime) && (fcm->efra >= evaltime))) {
+ (fcm->sfra <= evaltime && fcm->efra >= evaltime)) {
/* Within range: here it probably doesn't matter,
* though we'd want to check on additive. */
}
@@ -2207,9 +2181,9 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna,
return evaluate_fcurve_ex(fcu, evaltime, cvalue);
}
-bool BKE_fcurve_is_empty(FCurve *fcu)
+bool BKE_fcurve_is_empty(const FCurve *fcu)
{
- return (fcu->totvert == 0) && (fcu->driver == NULL) &&
+ return fcu->totvert == 0 && fcu->driver == NULL &&
!list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE);
}
diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c
index 551bab75d4b..46dc01edbff 100644
--- a/source/blender/blenkernel/intern/fmodifier.c
+++ b/source/blender/blenkernel/intern/fmodifier.c
@@ -1283,7 +1283,7 @@ void set_active_fmodifier(ListBase *modifiers, FModifier *fcm)
}
}
-bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype)
+bool list_has_suitable_fmodifier(const ListBase *modifiers, int mtype, short acttype)
{
FModifier *fcm;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 2ba81c54872..53147c94f43 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -2296,8 +2296,8 @@ void BKE_keyblock_mesh_calc_normals(const KeyBlock *kb,
(mesh->flag & ME_AUTOSMOOTH) != 0,
mesh->smoothresh,
NULL,
- clnors,
- NULL);
+ NULL,
+ clnors);
}
if (free_vert_normals) {
diff --git a/source/blender/blenkernel/intern/lattice_deform_test.cc b/source/blender/blenkernel/intern/lattice_deform_test.cc
index 58aadf652b7..c66feedc878 100644
--- a/source/blender/blenkernel/intern/lattice_deform_test.cc
+++ b/source/blender/blenkernel/intern/lattice_deform_test.cc
@@ -13,6 +13,9 @@
#include "BLI_rand.hh"
+#define DO_PERF_TESTS 0
+
+#if DO_PERF_TESTS
namespace blender::bke::tests {
struct LatticeDeformTestContext {
@@ -122,3 +125,4 @@ TEST(lattice_deform_performance, performance_no_dvert_10000000)
}
} // namespace blender::bke::tests
+#endif
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 2d613f24a0a..b8658139161 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -1829,9 +1829,9 @@ void BKE_mesh_calc_normals_split_ex(Mesh *mesh,
polys.size(),
use_split_normals,
split_angle,
+ nullptr,
r_lnors_spacearr,
- clnors,
- nullptr);
+ clnors);
BKE_mesh_assert_normals_dirty_or_calculated(mesh);
}
diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c
index ce3fc5d99c8..9f00d8860b8 100644
--- a/source/blender/blenkernel/intern/mesh_mirror.c
+++ b/source/blender/blenkernel/intern/mesh_mirror.c
@@ -418,9 +418,9 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd,
totpoly,
true,
mesh->smoothresh,
+ NULL,
&lnors_spacearr,
- clnors,
- NULL);
+ clnors);
/* mirroring has to account for loops being reversed in polys in second half */
MPoly *result_polys = BKE_mesh_polys_for_write(result);
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index ebb5a72d137..404357bda8d 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -33,18 +33,20 @@
#include "BKE_editmesh_cache.h"
#include "BKE_global.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
#include "atomic_ops.h"
using blender::BitVector;
+using blender::float3;
using blender::MutableSpan;
+using blender::short2;
using blender::Span;
-// #define DEBUG_TIME
+#define DEBUG_TIME
#ifdef DEBUG_TIME
-# include "PIL_time.h"
-# include "PIL_time_utildefines.h"
+# include "BLI_timeit.hh"
#endif
/* -------------------------------------------------------------------- */
@@ -442,7 +444,7 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
BKE_mesh_poly_normals_ensure(mesh);
break;
case ME_WRAPPER_TYPE_BMESH: {
- struct BMEditMesh *em = mesh->edit_mesh;
+ BMEditMesh *em = mesh->edit_mesh;
EditMeshData *emd = mesh->runtime->edit_data;
if (emd->vertexCos) {
BKE_editmesh_cache_ensure_vert_normals(em, emd);
@@ -456,12 +458,9 @@ void BKE_mesh_ensure_normals_for_display(Mesh *mesh)
void BKE_mesh_calc_normals(Mesh *mesh)
{
#ifdef DEBUG_TIME
- TIMEIT_START_AVERAGED(BKE_mesh_calc_normals);
+ SCOPED_TIMER_AVERAGED(__func__);
#endif
BKE_mesh_vertex_normals_ensure(mesh);
-#ifdef DEBUG_TIME
- TIMEIT_END_AVERAGED(BKE_mesh_calc_normals);
-#endif
}
void BKE_mesh_calc_normals_looptri(const MVert *mverts,
@@ -788,7 +787,7 @@ struct LoopSplitTaskData {
/** We have to create those outside of tasks, since #MemArena is not thread-safe. */
MLoopNorSpace *lnor_space;
- float (*lnor)[3];
+ float3 *lnor;
const MLoop *ml_curr;
const MLoop *ml_prev;
int ml_curr_index;
@@ -809,22 +808,18 @@ struct LoopSplitTaskDataCommon {
* Note we do not need to protect it, though, since two different tasks will *always* affect
* different elements in the arrays. */
MLoopNorSpaceArray *lnors_spacearr;
- float (*loopnors)[3];
- short (*clnors_data)[2];
+ MutableSpan<float3> loopnors;
+ MutableSpan<short2> clnors_data;
/* Read-only. */
- const MVert *mverts;
- const MEdge *medges;
- const MLoop *mloops;
- const MPoly *mpolys;
+ Span<MVert> verts;
+ MutableSpan<MEdge> edges;
+ Span<MLoop> loops;
+ Span<MPoly> polys;
int (*edge_to_loops)[2];
- int *loop_to_poly;
- const float (*polynors)[3];
- const float (*vert_normals)[3];
-
- int numEdges;
- int numLoops;
- int numPolys;
+ Span<int> loop_to_poly;
+ Span<float3> polynors;
+ Span<float3> vert_normals;
};
#define INDEX_UNSET INT_MIN
@@ -837,47 +832,38 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
const float split_angle,
const bool do_sharp_edges_tag)
{
- const MEdge *medges = data->medges;
- const MLoop *mloops = data->mloops;
+ MutableSpan<MEdge> edges = data->edges;
+ const Span<MPoly> polys = data->polys;
+ const Span<MLoop> loops = data->loops;
+ const Span<int> loop_to_poly = data->loop_to_poly;
- const MPoly *mpolys = data->mpolys;
-
- const int numEdges = data->numEdges;
- const int numPolys = data->numPolys;
-
- float(*loopnors)[3] = data->loopnors; /* NOTE: loopnors may be nullptr here. */
- const float(*polynors)[3] = data->polynors;
+ MutableSpan<float3> loopnors = data->loopnors; /* NOTE: loopnors may be empty here. */
+ const Span<float3> polynors = data->polynors;
int(*edge_to_loops)[2] = data->edge_to_loops;
- int *loop_to_poly = data->loop_to_poly;
BitVector sharp_edges;
if (do_sharp_edges_tag) {
- sharp_edges.resize(numEdges, false);
+ sharp_edges.resize(edges.size(), false);
}
- const MPoly *mp;
- int mp_index;
-
const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- const MLoop *ml_curr;
+ for (const int mp_index : polys.index_range()) {
+ const MPoly &poly = polys[mp_index];
int *e2l;
- int ml_curr_index = mp->loopstart;
- const int ml_last_index = (ml_curr_index + mp->totloop) - 1;
+ int ml_curr_index = poly.loopstart;
+ const int ml_last_index = (ml_curr_index + poly.totloop) - 1;
- ml_curr = &mloops[ml_curr_index];
+ const MLoop *ml_curr = &loops[ml_curr_index];
for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) {
e2l = edge_to_loops[ml_curr->e];
- loop_to_poly[ml_curr_index] = mp_index;
-
/* Pre-populate all loop normals as if their verts were all-smooth,
* this way we don't have to compute those later!
*/
- if (loopnors) {
+ if (!loopnors.is_empty()) {
copy_v3_v3(loopnors[ml_curr_index], data->vert_normals[ml_curr->v]);
}
@@ -886,7 +872,7 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
/* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
e2l[0] = ml_curr_index;
/* We have to check this here too, else we might miss some flat faces!!! */
- e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
+ e2l[1] = (poly.flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
}
else if (e2l[1] == INDEX_UNSET) {
const bool is_angle_sharp = (check_angle &&
@@ -898,8 +884,8 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
* or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the
* same vertex, or angle between both its polys' normals is above split_angle value.
*/
- if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
- ml_curr->v == mloops[e2l[0]].v || is_angle_sharp) {
+ if (!(poly.flag & ME_SMOOTH) || (edges[ml_curr->e].flag & ME_SHARP) ||
+ ml_curr->v == loops[e2l[0]].v || is_angle_sharp) {
/* NOTE: we are sure that loop != 0 here ;). */
e2l[1] = INDEX_INVALID;
@@ -929,69 +915,64 @@ static void mesh_edges_sharp_tag(LoopSplitTaskDataCommon *data,
/* If requested, do actual tagging of edges as sharp in another loop. */
if (do_sharp_edges_tag) {
- MEdge *me;
- int me_index;
- for (me = (MEdge *)medges, me_index = 0; me_index < numEdges; me++, me_index++) {
- if (sharp_edges[me_index]) {
- me->flag |= ME_SHARP;
+ for (const int i : edges.index_range()) {
+ if (sharp_edges[i]) {
+ edges[i].flag |= ME_SHARP;
}
}
}
}
-void BKE_edges_sharp_from_angle_set(const struct MVert *mverts,
- const int /*numVerts*/,
- struct MEdge *medges,
+void BKE_edges_sharp_from_angle_set(const MVert *mverts,
+ const int numVerts,
+ MEdge *medges,
const int numEdges,
- const struct MLoop *mloops,
+ const MLoop *mloops,
const int numLoops,
- const struct MPoly *mpolys,
+ const MPoly *mpolys,
const float (*polynors)[3],
const int numPolys,
const float split_angle)
{
+ using namespace blender;
+ using namespace blender::bke;
if (split_angle >= float(M_PI)) {
/* Nothing to do! */
return;
}
- /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */
+ /* Mapping edge -> loops. See #BKE_mesh_normals_loop_split for details. */
int(*edge_to_loops)[2] = (int(*)[2])MEM_calloc_arrayN(
size_t(numEdges), sizeof(*edge_to_loops), __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = (int *)MEM_malloc_arrayN(size_t(numLoops), sizeof(*loop_to_poly), __func__);
+ const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map({mpolys, numPolys},
+ numLoops);
LoopSplitTaskDataCommon common_data = {};
- common_data.mverts = mverts;
- common_data.medges = medges;
- common_data.mloops = mloops;
- common_data.mpolys = mpolys;
+ common_data.verts = {mverts, numVerts};
+ common_data.edges = {medges, numEdges};
+ common_data.polys = {mpolys, numPolys};
+ common_data.loops = {mloops, numLoops};
common_data.edge_to_loops = edge_to_loops;
common_data.loop_to_poly = loop_to_poly;
- common_data.polynors = polynors;
- common_data.numEdges = numEdges;
- common_data.numPolys = numPolys;
+ common_data.polynors = {reinterpret_cast<const float3 *>(polynors), numPolys};
mesh_edges_sharp_tag(&common_data, true, split_angle, true);
MEM_freeN(edge_to_loops);
- MEM_freeN(loop_to_poly);
}
-void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
- const MPoly *mpolys,
- const int *loop_to_poly,
- const int *e2lfan_curr,
- const uint mv_pivot_index,
- const MLoop **r_mlfan_curr,
- int *r_mlfan_curr_index,
- int *r_mlfan_vert_index,
- int *r_mpfan_curr_index)
+static void loop_manifold_fan_around_vert_next(const Span<MLoop> loops,
+ const Span<MPoly> polys,
+ const Span<int> loop_to_poly,
+ const int *e2lfan_curr,
+ const uint mv_pivot_index,
+ const MLoop **r_mlfan_curr,
+ int *r_mlfan_curr_index,
+ int *r_mlfan_vert_index,
+ int *r_mpfan_curr_index)
{
- const MLoop *mlfan_next;
- const MPoly *mpfan_next;
-
/* WARNING: This is rather complex!
* We have to find our next edge around the vertex (fan mode).
* First we find the next loop, which is either previous or next to mlfan_curr_index, depending
@@ -1005,38 +986,38 @@ void BKE_mesh_loop_manifold_fan_around_vert_next(const MLoop *mloops,
BLI_assert(*r_mlfan_curr_index >= 0);
BLI_assert(*r_mpfan_curr_index >= 0);
- mlfan_next = &mloops[*r_mlfan_curr_index];
- mpfan_next = &mpolys[*r_mpfan_curr_index];
- if (((*r_mlfan_curr)->v == mlfan_next->v && (*r_mlfan_curr)->v == mv_pivot_index) ||
- ((*r_mlfan_curr)->v != mlfan_next->v && (*r_mlfan_curr)->v != mv_pivot_index)) {
+ const MLoop &mlfan_next = loops[*r_mlfan_curr_index];
+ const MPoly &mpfan_next = polys[*r_mpfan_curr_index];
+ if (((*r_mlfan_curr)->v == mlfan_next.v && (*r_mlfan_curr)->v == mv_pivot_index) ||
+ ((*r_mlfan_curr)->v != mlfan_next.v && (*r_mlfan_curr)->v != mv_pivot_index)) {
/* We need the previous loop, but current one is our vertex's loop. */
*r_mlfan_vert_index = *r_mlfan_curr_index;
- if (--(*r_mlfan_curr_index) < mpfan_next->loopstart) {
- *r_mlfan_curr_index = mpfan_next->loopstart + mpfan_next->totloop - 1;
+ if (--(*r_mlfan_curr_index) < mpfan_next.loopstart) {
+ *r_mlfan_curr_index = mpfan_next.loopstart + mpfan_next.totloop - 1;
}
}
else {
/* We need the next loop, which is also our vertex's loop. */
- if (++(*r_mlfan_curr_index) >= mpfan_next->loopstart + mpfan_next->totloop) {
- *r_mlfan_curr_index = mpfan_next->loopstart;
+ if (++(*r_mlfan_curr_index) >= mpfan_next.loopstart + mpfan_next.totloop) {
+ *r_mlfan_curr_index = mpfan_next.loopstart;
}
*r_mlfan_vert_index = *r_mlfan_curr_index;
}
- *r_mlfan_curr = &mloops[*r_mlfan_curr_index];
+ *r_mlfan_curr = &loops[*r_mlfan_curr_index];
/* And now we are back in sync, mlfan_curr_index is the index of `mlfan_curr`! Pff! */
}
static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
- const short(*clnors_data)[2] = common_data->clnors_data;
+ const Span<short2> clnors_data = common_data->clnors_data;
- const MVert *mverts = common_data->mverts;
- const MEdge *medges = common_data->medges;
- const float(*polynors)[3] = common_data->polynors;
+ const Span<MVert> verts = common_data->verts;
+ const Span<MEdge> edges = common_data->edges;
+ const Span<float3> polynors = common_data->polynors;
MLoopNorSpace *lnor_space = data->lnor_space;
- float(*lnor)[3] = data->lnor;
+ float3 *lnor = data->lnor;
const MLoop *ml_curr = data->ml_curr;
const MLoop *ml_prev = data->ml_prev;
const int ml_curr_index = data->ml_curr_index;
@@ -1064,13 +1045,13 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
float vec_curr[3], vec_prev[3];
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
- const MVert *mv_pivot = &mverts[mv_pivot_index];
- const MEdge *me_curr = &medges[ml_curr->e];
- const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
- &mverts[me_curr->v1];
- const MEdge *me_prev = &medges[ml_prev->e];
- const MVert *mv_3 = (me_prev->v1 == mv_pivot_index) ? &mverts[me_prev->v2] :
- &mverts[me_prev->v1];
+ const MVert *mv_pivot = &verts[mv_pivot_index];
+ const MEdge *me_curr = &edges[ml_curr->e];
+ const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &verts[me_curr->v2] :
+ &verts[me_curr->v1];
+ const MEdge *me_prev = &edges[ml_prev->e];
+ const MVert *mv_3 = (me_prev->v1 == mv_pivot_index) ? &verts[me_prev->v2] :
+ &verts[me_prev->v1];
sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
normalize_v3(vec_curr);
@@ -1081,7 +1062,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
/* We know there is only one loop in this space, no need to create a link-list in this case. */
BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, nullptr, true);
- if (clnors_data) {
+ if (!clnors_data.is_empty()) {
BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
}
}
@@ -1090,16 +1071,16 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSplitTaskData *data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
- float(*loopnors)[3] = common_data->loopnors;
- short(*clnors_data)[2] = common_data->clnors_data;
+ MutableSpan<float3> loopnors = common_data->loopnors;
+ MutableSpan<short2> clnors_data = common_data->clnors_data;
- const MVert *mverts = common_data->mverts;
- const MEdge *medges = common_data->medges;
- const MLoop *mloops = common_data->mloops;
- const MPoly *mpolys = common_data->mpolys;
+ const Span<MVert> verts = common_data->verts;
+ const Span<MEdge> edges = common_data->edges;
+ const Span<MPoly> polys = common_data->polys;
+ const Span<MLoop> loops = common_data->loops;
const int(*edge_to_loops)[2] = common_data->edge_to_loops;
- const int *loop_to_poly = common_data->loop_to_poly;
- const float(*polynors)[3] = common_data->polynors;
+ const Span<int> loop_to_poly = common_data->loop_to_poly;
+ const Span<float3> polynors = common_data->polynors;
MLoopNorSpace *lnor_space = data->lnor_space;
#if 0 /* Not needed for 'fan' loops. */
@@ -1121,22 +1102,17 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
* number of sharp edges per vertex, I doubt the additional memory usage would be worth it,
* especially as it should not be a common case in real-life meshes anyway). */
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
- const MVert *mv_pivot = &mverts[mv_pivot_index];
+ const MVert *mv_pivot = &verts[mv_pivot_index];
/* `ml_curr` would be mlfan_prev if we needed that one. */
- const MEdge *me_org = &medges[ml_curr->e];
+ const MEdge *me_org = &edges[ml_curr->e];
- const int *e2lfan_curr;
float vec_curr[3], vec_prev[3], vec_org[3];
- const MLoop *mlfan_curr;
float lnor[3] = {0.0f, 0.0f, 0.0f};
- /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
- */
- int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
/* We validate clnors data on the fly - cheapest way to do! */
int clnors_avg[2] = {0, 0};
- short(*clnor_ref)[2] = nullptr;
+ short2 *clnor_ref = nullptr;
int clnors_count = 0;
bool clnors_invalid = false;
@@ -1145,11 +1121,13 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Temp clnors stack. */
BLI_SMALLSTACK_DECLARE(clnors, short *);
- e2lfan_curr = e2l_prev;
- mlfan_curr = ml_prev;
- mlfan_curr_index = ml_prev_index;
- mlfan_vert_index = ml_curr_index;
- mpfan_curr_index = mp_index;
+ const int *e2lfan_curr = e2l_prev;
+ const MLoop *mlfan_curr = ml_prev;
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
+ int mlfan_curr_index = ml_prev_index;
+ int mlfan_vert_index = ml_curr_index;
+ int mpfan_curr_index = mp_index;
BLI_assert(mlfan_curr_index >= 0);
BLI_assert(mlfan_vert_index >= 0);
@@ -1157,7 +1135,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Only need to compute previous edge's vector once, then we can just reuse old current one! */
{
- const MVert *mv_2 = (me_org->v1 == mv_pivot_index) ? &mverts[me_org->v2] : &mverts[me_org->v1];
+ const MVert *mv_2 = (me_org->v1 == mv_pivot_index) ? &verts[me_org->v2] : &verts[me_org->v1];
sub_v3_v3v3(vec_org, mv_2->co, mv_pivot->co);
normalize_v3(vec_org);
@@ -1171,15 +1149,15 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
// printf("FAN: vert %d, start edge %d\n", mv_pivot_index, ml_curr->e);
while (true) {
- const MEdge *me_curr = &medges[mlfan_curr->e];
+ const MEdge *me_curr = &edges[mlfan_curr->e];
/* Compute edge vectors.
* NOTE: We could pre-compute those into an array, in the first iteration, instead of computing
* them twice (or more) here. However, time gained is not worth memory and time lost,
* given the fact that this code should not be called that much in real-life meshes.
*/
{
- const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &mverts[me_curr->v2] :
- &mverts[me_curr->v1];
+ const MVert *mv_2 = (me_curr->v1 == mv_pivot_index) ? &verts[me_curr->v2] :
+ &verts[me_curr->v1];
sub_v3_v3v3(vec_curr, mv_2->co, mv_pivot->co);
normalize_v3(vec_curr);
@@ -1194,9 +1172,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* Accumulate */
madd_v3_v3fl(lnor, polynors[mpfan_curr_index], fac);
- if (clnors_data) {
+ if (!clnors_data.is_empty()) {
/* Accumulate all clnors, if they are not all equal we have to fix that! */
- short(*clnor)[2] = &clnors_data[mlfan_vert_index];
+ short2 *clnor = &clnors_data[mlfan_vert_index];
if (clnors_count) {
clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
}
@@ -1233,15 +1211,15 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
copy_v3_v3(vec_prev, vec_curr);
/* Find next loop of the smooth fan. */
- BKE_mesh_loop_manifold_fan_around_vert_next(mloops,
- mpolys,
- loop_to_poly,
- e2lfan_curr,
- mv_pivot_index,
- &mlfan_curr,
- &mlfan_curr_index,
- &mlfan_vert_index,
- &mpfan_curr_index);
+ loop_manifold_fan_around_vert_next(loops,
+ polys,
+ loop_to_poly,
+ e2lfan_curr,
+ mv_pivot_index,
+ &mlfan_curr,
+ &mlfan_curr_index,
+ &mlfan_vert_index,
+ &mpfan_curr_index);
e2lfan_curr = edge_to_loops[mlfan_curr->e];
}
@@ -1261,7 +1239,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
BKE_lnor_space_define(lnor_space, lnor, vec_org, vec_curr, edge_vectors);
- if (clnors_data) {
+ if (!clnors_data.is_empty()) {
if (clnors_invalid) {
short *clnor;
@@ -1325,10 +1303,6 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
BLI_stack_new(sizeof(float[3]), __func__) :
nullptr;
-#ifdef DEBUG_TIME
- TIMEIT_START_AVERAGED(loop_split_worker);
-#endif
-
for (int i = 0; i < LOOP_SPLIT_TASK_BLOCK_SIZE; i++, data++) {
/* A nullptr ml_curr is used to tag ended data! */
if (data->ml_curr == nullptr) {
@@ -1341,10 +1315,6 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
if (edge_vectors) {
BLI_stack_free(edge_vectors);
}
-
-#ifdef DEBUG_TIME
- TIMEIT_END_AVERAGED(loop_split_worker);
-#endif
}
/**
@@ -1352,10 +1322,10 @@ static void loop_split_worker(TaskPool *__restrict pool, void *taskdata)
* Needed because cyclic smooth fans have no obvious 'entry point',
* and yet we need to walk them once, and only once.
*/
-static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
- const MPoly *mpolys,
+static bool loop_split_generator_check_cyclic_smooth_fan(const Span<MLoop> mloops,
+ const Span<MPoly> mpolys,
const int (*edge_to_loops)[2],
- const int *loop_to_poly,
+ const Span<int> loop_to_poly,
const int *e2l_prev,
BitVector<> &skip_loops,
const MLoop *ml_curr,
@@ -1365,22 +1335,19 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
const int mp_curr_index)
{
const uint mv_pivot_index = ml_curr->v; /* The vertex we are "fanning" around! */
- const int *e2lfan_curr;
- const MLoop *mlfan_curr;
- /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
- */
- int mlfan_curr_index, mlfan_vert_index, mpfan_curr_index;
- e2lfan_curr = e2l_prev;
+ const int *e2lfan_curr = e2l_prev;
if (IS_EDGE_SHARP(e2lfan_curr)) {
/* Sharp loop, so not a cyclic smooth fan. */
return false;
}
- mlfan_curr = ml_prev;
- mlfan_curr_index = ml_prev_index;
- mlfan_vert_index = ml_curr_index;
- mpfan_curr_index = mp_curr_index;
+ /* `mlfan_vert_index` the loop of our current edge might not be the loop of our current vertex!
+ */
+ const MLoop *mlfan_curr = ml_prev;
+ int mlfan_curr_index = ml_prev_index;
+ int mlfan_vert_index = ml_curr_index;
+ int mpfan_curr_index = mp_curr_index;
BLI_assert(mlfan_curr_index >= 0);
BLI_assert(mlfan_vert_index >= 0);
@@ -1391,15 +1358,15 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
while (true) {
/* Find next loop of the smooth fan. */
- BKE_mesh_loop_manifold_fan_around_vert_next(mloops,
- mpolys,
- loop_to_poly,
- e2lfan_curr,
- mv_pivot_index,
- &mlfan_curr,
- &mlfan_curr_index,
- &mlfan_vert_index,
- &mpfan_curr_index);
+ loop_manifold_fan_around_vert_next(mloops,
+ mpolys,
+ loop_to_poly,
+ e2lfan_curr,
+ mv_pivot_index,
+ &mlfan_curr,
+ &mlfan_curr_index,
+ &mlfan_vert_index,
+ &mpfan_curr_index);
e2lfan_curr = edge_to_loops[mlfan_curr->e];
@@ -1426,24 +1393,14 @@ static bool loop_split_generator_check_cyclic_smooth_fan(const MLoop *mloops,
static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common_data)
{
MLoopNorSpaceArray *lnors_spacearr = common_data->lnors_spacearr;
- float(*loopnors)[3] = common_data->loopnors;
+ MutableSpan<float3> loopnors = common_data->loopnors;
- const MLoop *mloops = common_data->mloops;
- const MPoly *mpolys = common_data->mpolys;
- const int *loop_to_poly = common_data->loop_to_poly;
+ const Span<MLoop> loops = common_data->loops;
+ const Span<MPoly> polys = common_data->polys;
+ const Span<int> loop_to_poly = common_data->loop_to_poly;
const int(*edge_to_loops)[2] = common_data->edge_to_loops;
- const int numLoops = common_data->numLoops;
- const int numPolys = common_data->numPolys;
- const MPoly *mp;
- int mp_index;
-
- const MLoop *ml_curr;
- const MLoop *ml_prev;
- int ml_curr_index;
- int ml_prev_index;
-
- BitVector<> skip_loops(numLoops, false);
+ BitVector<> skip_loops(loops.size(), false);
LoopSplitTaskData *data_buff = nullptr;
int data_idx = 0;
@@ -1453,7 +1410,7 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
BLI_Stack *edge_vectors = nullptr;
#ifdef DEBUG_TIME
- TIMEIT_START_AVERAGED(loop_split_generator);
+ SCOPED_TIMER_AVERAGED(__func__);
#endif
if (!pool) {
@@ -1465,15 +1422,15 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
/* We now know edges that can be smoothed (with their vector, and their two loops),
* and edges that will be hard! Now, time to generate the normals.
*/
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- float(*lnors)[3];
- const int ml_last_index = (mp->loopstart + mp->totloop) - 1;
- ml_curr_index = mp->loopstart;
- ml_prev_index = ml_last_index;
+ for (const int mp_index : polys.index_range()) {
+ const MPoly &poly = polys[mp_index];
+ const int ml_last_index = (poly.loopstart + poly.totloop) - 1;
+ int ml_curr_index = poly.loopstart;
+ int ml_prev_index = ml_last_index;
- ml_curr = &mloops[ml_curr_index];
- ml_prev = &mloops[ml_prev_index];
- lnors = &loopnors[ml_curr_index];
+ const MLoop *ml_curr = &loops[ml_curr_index];
+ const MLoop *ml_prev = &loops[ml_prev_index];
+ float3 *lnors = &loopnors[ml_curr_index];
for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++, lnors++) {
const int *e2l_curr = edge_to_loops[ml_curr->e];
@@ -1499,8 +1456,8 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
* complexity, #loop_manifold_fan_around_vert_next() is quite cheap in term of CPU cycles,
* so really think it's not worth it. */
if (!IS_EDGE_SHARP(e2l_curr) && (skip_loops[ml_curr_index] ||
- !loop_split_generator_check_cyclic_smooth_fan(mloops,
- mpolys,
+ !loop_split_generator_check_cyclic_smooth_fan(loops,
+ polys,
edge_to_loops,
loop_to_poly,
e2l_prev,
@@ -1593,15 +1550,11 @@ static void loop_split_generator(TaskPool *pool, LoopSplitTaskDataCommon *common
if (edge_vectors) {
BLI_stack_free(edge_vectors);
}
-
-#ifdef DEBUG_TIME
- TIMEIT_END_AVERAGED(loop_split_generator);
-#endif
}
void BKE_mesh_normals_loop_split(const MVert *mverts,
const float (*vert_normals)[3],
- const int /*numVerts*/,
+ const int numVerts,
const MEdge *medges,
const int numEdges,
const MLoop *mloops,
@@ -1612,10 +1565,12 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
const int numPolys,
const bool use_split_normals,
const float split_angle,
+ const int *loop_to_poly_map,
MLoopNorSpaceArray *r_lnors_spacearr,
- short (*clnors_data)[2],
- int *r_loop_to_poly)
+ short (*clnors_data)[2])
{
+ using namespace blender;
+ using namespace blender::bke;
/* For now this is not supported.
* If we do not use split normals, we do not generate anything fancy! */
BLI_assert(use_split_normals || !(r_lnors_spacearr));
@@ -1636,9 +1591,6 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
const bool is_poly_flat = ((mp->flag & ME_SMOOTH) == 0);
for (; ml_index < ml_index_end; ml_index++) {
- if (r_loop_to_poly) {
- r_loop_to_poly[ml_index] = mp_index;
- }
if (is_poly_flat) {
copy_v3_v3(r_loopnors[ml_index], polynors[mp_index]);
}
@@ -1668,9 +1620,15 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
size_t(numEdges), sizeof(*edge_to_loops), __func__);
/* Simple mapping from a loop to its polygon index. */
- int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly :
- (int *)MEM_malloc_arrayN(
- size_t(numLoops), sizeof(*loop_to_poly), __func__);
+ Span<int> loop_to_poly;
+ Array<int> local_loop_to_poly_map;
+ if (loop_to_poly_map) {
+ loop_to_poly = {loop_to_poly_map, numLoops};
+ }
+ else {
+ local_loop_to_poly_map = mesh_topology::build_loop_to_poly_map({mpolys, numPolys}, numLoops);
+ loop_to_poly = local_loop_to_poly_map;
+ }
/* When using custom loop normals, disable the angle feature! */
const bool check_angle = (split_angle < float(M_PI)) && (clnors_data == nullptr);
@@ -1678,7 +1636,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
MLoopNorSpaceArray _lnors_spacearr = {nullptr};
#ifdef DEBUG_TIME
- TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
+ SCOPED_TIMER_AVERAGED(__func__);
#endif
if (!r_lnors_spacearr && clnors_data) {
@@ -1692,19 +1650,16 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
/* Init data common to all tasks. */
LoopSplitTaskDataCommon common_data;
common_data.lnors_spacearr = r_lnors_spacearr;
- common_data.loopnors = r_loopnors;
- common_data.clnors_data = clnors_data;
- common_data.mverts = mverts;
- common_data.medges = medges;
- common_data.mloops = mloops;
- common_data.mpolys = mpolys;
+ common_data.loopnors = {reinterpret_cast<float3 *>(r_loopnors), numLoops};
+ common_data.clnors_data = {reinterpret_cast<short2 *>(clnors_data), clnors_data ? numLoops : 0};
+ common_data.verts = {mverts, numVerts};
+ common_data.edges = {const_cast<MEdge *>(medges), numEdges};
+ common_data.polys = {mpolys, numPolys};
+ common_data.loops = {mloops, numLoops};
common_data.edge_to_loops = edge_to_loops;
common_data.loop_to_poly = loop_to_poly;
- common_data.polynors = polynors;
- common_data.vert_normals = vert_normals;
- common_data.numEdges = numEdges;
- common_data.numLoops = numLoops;
- common_data.numPolys = numPolys;
+ common_data.polynors = {reinterpret_cast<const float3 *>(polynors), numPolys};
+ common_data.vert_normals = {reinterpret_cast<const float3 *>(vert_normals), numVerts};
/* This first loop check which edges are actually smooth, and compute edge vectors. */
mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false);
@@ -1724,19 +1679,12 @@ void BKE_mesh_normals_loop_split(const MVert *mverts,
}
MEM_freeN(edge_to_loops);
- if (!r_loop_to_poly) {
- MEM_freeN(loop_to_poly);
- }
if (r_lnors_spacearr) {
if (r_lnors_spacearr == &_lnors_spacearr) {
BKE_lnor_spacearr_free(r_lnors_spacearr);
}
}
-
-#ifdef DEBUG_TIME
- TIMEIT_END_AVERAGED(BKE_mesh_normals_loop_split);
-#endif
}
#undef INDEX_UNSET
@@ -1766,6 +1714,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
short (*r_clnors_data)[2],
const bool use_vertices)
{
+ using namespace blender;
+ using namespace blender::bke;
/* We *may* make that poor #BKE_mesh_normals_loop_split() even more complex by making it handling
* that feature too, would probably be more efficient in absolute.
* However, this function *is not* performance-critical, since it is mostly expected to be called
@@ -1775,7 +1725,8 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
MLoopNorSpaceArray lnors_spacearr = {nullptr};
BitVector<> done_loops(numLoops, false);
float(*lnors)[3] = (float(*)[3])MEM_calloc_arrayN(size_t(numLoops), sizeof(*lnors), __func__);
- int *loop_to_poly = (int *)MEM_malloc_arrayN(size_t(numLoops), sizeof(int), __func__);
+ const Array<int> loop_to_poly = mesh_topology::build_loop_to_poly_map({mpolys, numPolys},
+ numLoops);
/* In this case we always consider split nors as ON,
* and do not want to use angle to define smooth fans! */
const bool use_split_normals = true;
@@ -1797,9 +1748,9 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
numPolys,
use_split_normals,
split_angle,
+ loop_to_poly.data(),
&lnors_spacearr,
- nullptr,
- loop_to_poly);
+ nullptr);
/* Set all given zero vectors to their default value. */
if (use_vertices) {
@@ -1920,9 +1871,9 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
numPolys,
use_split_normals,
split_angle,
+ loop_to_poly.data(),
&lnors_spacearr,
- nullptr,
- loop_to_poly);
+ nullptr);
}
else {
done_loops.fill(true);
@@ -1984,7 +1935,6 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
}
MEM_freeN(lnors);
- MEM_freeN(loop_to_poly);
BKE_lnor_spacearr_free(&lnors_spacearr);
}
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index 90798ea593d..d96cd54e198 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1372,8 +1372,8 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
use_split_nors_dst,
split_angle_dst,
NULL,
- custom_nors_dst,
- NULL);
+ NULL,
+ custom_nors_dst);
}
}
if (need_pnors_src || need_lnors_src) {
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 31fc8afea84..5400fd78ddb 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -2019,7 +2019,7 @@ bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
return (bNode *)BLI_findstring(&ntree->nodes, name, offsetof(bNode, name));
}
-bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
+void nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
{
*r_node = nullptr;
if (!ntree->runtime->topology_cache_is_dirty) {
@@ -2029,9 +2029,15 @@ bool nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_so
ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
*r_sockindex = BLI_findindex(sockets, sock);
}
- return true;
+ return;
}
+ const bool success = nodeFindNodeTry(ntree, sock, r_node, r_sockindex);
+ BLI_assert(success);
+ UNUSED_VARS_NDEBUG(success);
+}
+bool nodeFindNodeTry(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_sockindex)
+{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
ListBase *sockets = (sock->in_out == SOCK_IN) ? &node->inputs : &node->outputs;
int i;
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index 5efd44c620b..cca609a2e0d 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -79,6 +79,8 @@ namespace geo_log = blender::nodes::geo_eval_log;
/** \name Internal Duplicate Context
* \{ */
+static constexpr short GEOMETRY_SET_DUPLI_GENERATOR_TYPE = 1;
+
struct DupliContext {
Depsgraph *depsgraph;
/** XXX child objects are selected from this group if set, could be nicer. */
@@ -87,6 +89,9 @@ struct DupliContext {
Object *obedit;
Scene *scene;
+ /** Root parent object at the scene level. */
+ Object *root_object;
+ /** Immediate parent object in the context. */
Object *object;
float space_mat[4][4];
/**
@@ -106,6 +111,14 @@ struct DupliContext {
*/
Vector<Object *> *instance_stack;
+ /**
+ * Older code relies on the "dupli generator type" for various visibility or processing
+ * decisions. However, new code uses geometry instances in places that weren't using the dupli
+ * system previously. To fix this, keep track of the last dupli generator type that wasn't a
+ * geometry set instance.
+ * */
+ Vector<short> *dupli_gen_type_stack;
+
int persistent_id[MAX_DUPLI_RECUR];
int64_t instance_idx[MAX_DUPLI_RECUR];
const GeometrySet *instance_data[MAX_DUPLI_RECUR];
@@ -132,15 +145,18 @@ static void init_context(DupliContext *r_ctx,
Scene *scene,
Object *ob,
const float space_mat[4][4],
- Vector<Object *> &instance_stack)
+ Vector<Object *> &instance_stack,
+ Vector<short> &dupli_gen_type_stack)
{
r_ctx->depsgraph = depsgraph;
r_ctx->scene = scene;
r_ctx->collection = nullptr;
+ r_ctx->root_object = ob;
r_ctx->object = ob;
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
r_ctx->instance_stack = &instance_stack;
+ r_ctx->dupli_gen_type_stack = &dupli_gen_type_stack;
if (space_mat) {
copy_m4_m4(r_ctx->space_mat, space_mat);
}
@@ -150,6 +166,9 @@ static void init_context(DupliContext *r_ctx,
r_ctx->level = 0;
r_ctx->gen = get_dupli_generator(r_ctx);
+ if (r_ctx->gen && r_ctx->gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
+ r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type);
+ }
r_ctx->duplilist = nullptr;
r_ctx->preview_instance_index = -1;
@@ -191,6 +210,9 @@ static bool copy_dupli_context(DupliContext *r_ctx,
}
r_ctx->gen = get_dupli_generator(r_ctx);
+ if (r_ctx->gen && r_ctx->gen->type != GEOMETRY_SET_DUPLI_GENERATOR_TYPE) {
+ r_ctx->dupli_gen_type_stack->append(r_ctx->gen->type);
+ }
return true;
}
@@ -223,7 +245,7 @@ static DupliObject *make_dupli(const DupliContext *ctx,
dob->ob = ob;
dob->ob_data = const_cast<ID *>(object_data);
mul_m4_m4m4(dob->mat, (float(*)[4])ctx->space_mat, mat);
- dob->type = ctx->gen == nullptr ? 0 : ctx->gen->type;
+ dob->type = ctx->gen == nullptr ? 0 : ctx->dupli_gen_type_stack->last();
dob->preview_base_geometry = ctx->preview_base_geometry;
dob->preview_instance_index = ctx->preview_instance_index;
@@ -264,8 +286,9 @@ static DupliObject *make_dupli(const DupliContext *ctx,
dob->no_draw = true;
}
- /* Random number.
- * The logic here is designed to match Cycles. */
+ /* Random number per instance.
+ * The root object in the scene, persistent ID up to the instance object, and the instance object
+ * name together result in a unique random number. */
dob->random_id = BLI_hash_string(dob->ob->id.name + 2);
if (dob->persistent_id[0] != INT_MAX) {
@@ -277,8 +300,8 @@ static DupliObject *make_dupli(const DupliContext *ctx,
dob->random_id = BLI_hash_int_2d(dob->random_id, 0);
}
- if (ctx->object != ob) {
- dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
+ if (ctx->root_object != ob) {
+ dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->root_object->id.name + 2));
}
return dob;
@@ -321,6 +344,9 @@ static void make_recursive_duplis(const DupliContext *ctx,
ctx->instance_stack->append(ob);
rctx.gen->make_duplis(&rctx);
ctx->instance_stack->remove_last();
+ if (!ctx->dupli_gen_type_stack->is_empty()) {
+ ctx->dupli_gen_type_stack->remove_last();
+ }
}
}
}
@@ -365,6 +391,9 @@ static void make_child_duplis(const DupliContext *ctx,
ob->flag |= OB_DONE; /* Doesn't render. */
}
make_child_duplis_cb(&pctx, userdata, ob);
+ if (!ctx->dupli_gen_type_stack->is_empty()) {
+ ctx->dupli_gen_type_stack->remove_last();
+ }
}
}
}
@@ -390,6 +419,9 @@ static void make_child_duplis(const DupliContext *ctx,
}
make_child_duplis_cb(&pctx, userdata, ob);
+ if (!ctx->dupli_gen_type_stack->is_empty()) {
+ ctx->dupli_gen_type_stack->remove_last();
+ }
}
}
persistent_dupli_id++;
@@ -991,7 +1023,7 @@ static void make_duplis_geometry_set(const DupliContext *ctx)
}
static const DupliGenerator gen_dupli_geometry_set = {
- 0,
+ GEOMETRY_SET_DUPLI_GENERATOR_TYPE,
make_duplis_geometry_set,
};
@@ -1712,8 +1744,9 @@ ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
ListBase *duplilist = MEM_cnew<ListBase>("duplilist");
DupliContext ctx;
Vector<Object *> instance_stack;
+ Vector<short> dupli_gen_type_stack({0});
instance_stack.append(ob);
- init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack);
+ init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack, dupli_gen_type_stack);
if (ctx.gen) {
ctx.duplilist = duplilist;
ctx.gen->make_duplis(&ctx);
@@ -1730,8 +1763,9 @@ ListBase *object_duplilist_preview(Depsgraph *depsgraph,
ListBase *duplilist = MEM_cnew<ListBase>("duplilist");
DupliContext ctx;
Vector<Object *> instance_stack;
+ Vector<short> dupli_gen_type_stack({0});
instance_stack.append(ob_eval);
- init_context(&ctx, depsgraph, sce, ob_eval, nullptr, instance_stack);
+ init_context(&ctx, depsgraph, sce, ob_eval, nullptr, instance_stack, dupli_gen_type_stack);
ctx.duplilist = duplilist;
Object *ob_orig = DEG_get_original_object(ob_eval);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 98e89b09060..24ea2de98f6 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -833,7 +833,12 @@ void BKE_pbvh_build_grids(PBVH *pbvh,
pbvh->gridkey = *key;
pbvh->grid_hidden = grid_hidden;
pbvh->subdiv_ccg = subdiv_ccg;
- pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), 1);
+
+ /* Ensure leaf limit is at least 4 so there's room
+ * to split at original face boundaries.
+ * Fixes T102209.
+ */
+ pbvh->leaf_limit = max_ii(LEAF_LIMIT / (gridsize * gridsize), 4);
/* We need the base mesh attribute layout for PBVH draw. */
pbvh->vdata = &me->vdata;
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 3b0f35263d3..d03f12b98bd 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1527,8 +1527,8 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
- if (len_squared_v3v3(location, cos[j]) <
- len_squared_v3v3(location, nearest_vertex_co)) {
+ if (j == 0 || len_squared_v3v3(location, cos[j]) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, cos[j]);
r_active_vertex->i = (intptr_t)node->bm_orvert[node->bm_ortri[i][j]];
}
@@ -1559,8 +1559,8 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
- if (len_squared_v3v3(location, v_tri[j]->co) <
- len_squared_v3v3(location, nearest_vertex_co)) {
+ if (j == 0 || len_squared_v3v3(location, v_tri[j]->co) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
r_active_vertex->i = (intptr_t)v_tri[j];
}
diff --git a/source/blender/blenlib/BLI_disjoint_set.hh b/source/blender/blenlib/BLI_disjoint_set.hh
index d135aa90307..3adc609dad3 100644
--- a/source/blender/blenlib/BLI_disjoint_set.hh
+++ b/source/blender/blenlib/BLI_disjoint_set.hh
@@ -9,23 +9,24 @@
*/
#include "BLI_array.hh"
+#include "BLI_index_range.hh"
namespace blender {
-class DisjointSet {
+template<typename T = int64_t> class DisjointSet {
private:
- Array<int64_t> parents_;
- Array<int64_t> ranks_;
+ Array<T> parents_;
+ Array<T> ranks_;
public:
/**
* Create a new disjoint set with the given size. Initially, every element is in a separate set.
*/
- DisjointSet(int64_t size) : parents_(size), ranks_(size, 0)
+ DisjointSet(const int64_t size) : parents_(size), ranks_(size, 0)
{
BLI_assert(size >= 0);
- for (int64_t i = 0; i < size; i++) {
- parents_[i] = i;
+ for (const int64_t i : IndexRange(size)) {
+ parents_[i] = T(i);
}
}
@@ -33,10 +34,10 @@ class DisjointSet {
* Join the sets containing elements x and y. Nothing happens when they have been in the same set
* before.
*/
- void join(int64_t x, int64_t y)
+ void join(const T x, const T y)
{
- int64_t root1 = this->find_root(x);
- int64_t root2 = this->find_root(y);
+ T root1 = this->find_root(x);
+ T root2 = this->find_root(y);
/* x and y are in the same set already. */
if (root1 == root2) {
@@ -57,29 +58,30 @@ class DisjointSet {
/**
* Return true when x and y are in the same set.
*/
- bool in_same_set(int64_t x, int64_t y)
+ bool in_same_set(const T x, const T y)
{
- int64_t root1 = this->find_root(x);
- int64_t root2 = this->find_root(y);
+ T root1 = this->find_root(x);
+ T root2 = this->find_root(y);
return root1 == root2;
}
/**
* Find the element that represents the set containing x currently.
*/
- int64_t find_root(int64_t x)
+ T find_root(const T x)
{
/* Find root by following parents. */
- int64_t root = x;
+ T root = x;
while (parents_[root] != root) {
root = parents_[root];
}
/* Compress path. */
- while (parents_[x] != root) {
- int64_t parent = parents_[x];
- parents_[x] = root;
- x = parent;
+ T to_root = x;
+ while (parents_[to_root] != root) {
+ const T parent = parents_[to_root];
+ parents_[to_root] = root;
+ to_root = parent;
}
return root;
diff --git a/source/blender/blenlib/BLI_math_vec_types.hh b/source/blender/blenlib/BLI_math_vec_types.hh
index 0387d0b0440..36f847eec82 100644
--- a/source/blender/blenlib/BLI_math_vec_types.hh
+++ b/source/blender/blenlib/BLI_math_vec_types.hh
@@ -632,6 +632,7 @@ using uint2 = vec_base<uint32_t, 2>;
using uint3 = vec_base<uint32_t, 3>;
using uint4 = vec_base<uint32_t, 4>;
+using short2 = blender::vec_base<int16_t, 2>;
using short3 = blender::vec_base<int16_t, 3>;
using ushort2 = vec_base<uint16_t, 2>;
diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
index b89a48f2a39..353f3da14d7 100644
--- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
+++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cc
@@ -78,34 +78,41 @@ void MovieDistortionOperation::execute_pixel_sampled(float output[4],
float y,
PixelSampler /*sampler*/)
{
- if (distortion_ != nullptr) {
- /* float overscan = 0.0f; */
- const float pixel_aspect = pixel_aspect_;
- const float w = float(this->get_width()) /* / (1 + overscan) */;
- const float h = float(this->get_height()) /* / (1 + overscan) */;
- const float aspx = w / float(calibration_width_);
- const float aspy = h / float(calibration_height_);
- float in[2];
- float out[2];
-
- in[0] = (x /* - 0.5 * overscan * w */) / aspx;
- in[1] = (y /* - 0.5 * overscan * h */) / aspy / pixel_aspect;
+ const int width = this->get_width();
+ const int height = this->get_height();
+ if (distortion_ == nullptr || width == 0 || height == 0) {
+ /* When there is no precomputed distortion pass-through the coordinate as-is to the input
+ * samples.
+ * If the frame size is zero do the same and bypass any math. In theory it is probably more
+ * correct to zero the output but it is easier and safe to let the input to do so than to deal
+ * with possible different number of channels here. */
+ input_operation_->read_sampled(output, x, y, PixelSampler::Bilinear);
+ return;
+ }
- if (apply_) {
- BKE_tracking_distortion_undistort_v2(distortion_, in, out);
- }
- else {
- BKE_tracking_distortion_distort_v2(distortion_, in, out);
- }
+ /* float overscan = 0.0f; */
+ const float w = float(width) /* / (1 + overscan) */;
+ const float h = float(height) /* / (1 + overscan) */;
+ const float pixel_aspect = pixel_aspect_;
+ const float aspx = w / float(calibration_width_);
+ const float aspy = h / float(calibration_height_);
+ float in[2];
+ float out[2];
- float u = out[0] * aspx /* + 0.5 * overscan * w */,
- v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect;
+ in[0] = (x /* - 0.5 * overscan * w */) / aspx;
+ in[1] = (y /* - 0.5 * overscan * h */) / aspy / pixel_aspect;
- input_operation_->read_sampled(output, u, v, PixelSampler::Bilinear);
+ if (apply_) {
+ BKE_tracking_distortion_undistort_v2(distortion_, in, out);
}
else {
- input_operation_->read_sampled(output, x, y, PixelSampler::Bilinear);
+ BKE_tracking_distortion_distort_v2(distortion_, in, out);
}
+
+ float u = out[0] * aspx /* + 0.5 * overscan * w */,
+ v = (out[1] * aspy /* + 0.5 * overscan * h */) * pixel_aspect;
+
+ input_operation_->read_sampled(output, u, v, PixelSampler::Bilinear);
}
bool MovieDistortionOperation::determine_depending_area_of_interest(
diff --git a/source/blender/compositor/realtime_compositor/COM_scheduler.hh b/source/blender/compositor/realtime_compositor/COM_scheduler.hh
index 4f778b32145..9f3bc14ae17 100644
--- a/source/blender/compositor/realtime_compositor/COM_scheduler.hh
+++ b/source/blender/compositor/realtime_compositor/COM_scheduler.hh
@@ -16,6 +16,6 @@ using Schedule = VectorSet<DNode>;
/* Computes the execution schedule of the node tree. This is essentially a post-order depth first
* traversal of the node tree from the output node to the leaf input nodes, with informed order of
* traversal of dependencies based on a heuristic estimation of the number of needed buffers. */
-Schedule compute_schedule(DerivedNodeTree &tree);
+Schedule compute_schedule(const DerivedNodeTree &tree);
} // namespace blender::realtime_compositor
diff --git a/source/blender/compositor/realtime_compositor/intern/scheduler.cc b/source/blender/compositor/realtime_compositor/intern/scheduler.cc
index ac5cc55a73f..0d3cce7af39 100644
--- a/source/blender/compositor/realtime_compositor/intern/scheduler.cc
+++ b/source/blender/compositor/realtime_compositor/intern/scheduler.cc
@@ -8,6 +8,7 @@
#include "NOD_derived_node_tree.hh"
+#include "BKE_node.h"
#include "BKE_node_runtime.hh"
#include "COM_scheduler.hh"
@@ -17,36 +18,103 @@ namespace blender::realtime_compositor {
using namespace nodes::derived_node_tree_types;
-/* Compute the output node whose result should be computed. The output node is the node marked as
- * NODE_DO_OUTPUT. If multiple types of output nodes are marked, then the preference will be
- * CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER. If no output node exists, a null
- * node will be returned. */
-static DNode compute_output_node(DerivedNodeTree &tree)
+/* Find the active context from the given context and its descendants contexts. The active context
+ * is the one whose node instance key matches the active_viewer_key stored in the root node tree.
+ * The instance key of each context is computed by calling BKE_node_instance_key given the key of
+ * the parent as well as the group node making the context. */
+static const DTreeContext *find_active_context_recursive(const DTreeContext *context,
+ bNodeInstanceKey key)
{
- const bNodeTree &root_tree = tree.root_context().btree();
+ /* The instance key of the given context matches the active viewer instance key, so this is the
+ * active context, return it. */
+ if (key.value == context->derived_tree().root_context().btree().active_viewer_key.value) {
+ return context;
+ }
+
+ /* For each of the group nodes, compute their instance key and contexts and call this function
+ * recursively. */
+ for (const bNode *group_node : context->btree().group_nodes()) {
+ const bNodeInstanceKey child_key = BKE_node_instance_key(key, &context->btree(), group_node);
+ const DTreeContext *child_context = context->child_context(*group_node);
+ const DTreeContext *found_context = find_active_context_recursive(child_context, child_key);
+
+ /* If the found context is null, that means neither the child context nor one of its descendant
+ * contexts is active. */
+ if (!found_context) {
+ continue;
+ }
+
+ /* Otherwise, we have found our active context, return it. */
+ return found_context;
+ }
+
+ /* Neither the given context nor one of its descendant contexts is active, so return null. */
+ return nullptr;
+}
+
+/* Find the active context for the given node tree. The active context represents the node tree
+ * currently being edited. In most cases, that would be the top level node tree itself, but in the
+ * case where the user is editing the node tree of a node group, the active context would be a
+ * representation of the node tree of that node group. Note that the context also stores the group
+ * node that the user selected to edit the node tree, so the context fully represents a particular
+ * instance of the node group. */
+static const DTreeContext *find_active_context(const DerivedNodeTree &tree)
+{
+ /* The root context has an instance key of NODE_INSTANCE_KEY_BASE by definition. */
+ return find_active_context_recursive(&tree.root_context(), NODE_INSTANCE_KEY_BASE);
+}
+
+/* Return the output node which is marked as NODE_DO_OUTPUT. If multiple types of output nodes are
+ * marked, then the preference will be CMP_NODE_COMPOSITE > CMP_NODE_VIEWER > CMP_NODE_SPLITVIEWER.
+ * If no output node exists, a null node will be returned. */
+static DNode find_output_in_context(const DTreeContext *context)
+{
+ const bNodeTree &tree = context->btree();
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeComposite")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeComposite")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeViewer")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- for (const bNode *node : root_tree.nodes_by_type("CompositorNodeSplitViewer")) {
+ for (const bNode *node : tree.nodes_by_type("CompositorNodeSplitViewer")) {
if (node->flag & NODE_DO_OUTPUT) {
- return DNode(&tree.root_context(), node);
+ return DNode(context, node);
}
}
- /* No output node found, return a null node. */
return DNode();
}
+/* Compute the output node whose result should be computed. This node is the output node that
+ * satisfies the requirements in the find_output_in_context function. First, the active context is
+ * searched for an output node, if non was found, the root context is search. For more information
+ * on what contexts mean here, see the find_active_context function. */
+static DNode compute_output_node(const DerivedNodeTree &tree)
+{
+ const DTreeContext *active_context = find_active_context(tree);
+
+ const DNode node = find_output_in_context(active_context);
+ if (node) {
+ return node;
+ }
+
+ /* If the active context is the root one and no output node was found, we consider this node tree
+ * to have no output node, even if one of the non-active descendants have an output node. */
+ if (active_context->is_root()) {
+ return DNode();
+ }
+
+ /* The active context doesn't have an output node, search in the root context as a fallback. */
+ return find_output_in_context(&tree.root_context());
+}
+
/* A type representing a mapping that associates each node with a heuristic estimation of the
* number of intermediate buffers needed to compute it and all of its dependencies. See the
* compute_number_of_needed_buffers function for more information. */
@@ -225,7 +293,7 @@ static NeededBuffers compute_number_of_needed_buffers(DNode output_node)
* doesn't always guarantee an optimal evaluation order, as the optimal evaluation order is very
* difficult to compute, however, this method works well in most cases. Moreover it assumes that
* all buffers will have roughly the same size, which may not always be the case. */
-Schedule compute_schedule(DerivedNodeTree &tree)
+Schedule compute_schedule(const DerivedNodeTree &tree)
{
Schedule schedule;
diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc
index 6da290d6c4e..9eeb074bbaa 100644
--- a/source/blender/depsgraph/intern/depsgraph_build.cc
+++ b/source/blender/depsgraph/intern/depsgraph_build.cc
@@ -138,9 +138,14 @@ void DEG_add_node_tree_output_relation(DepsNodeHandle *node_handle,
{
deg::OperationKey ntree_output_key(
&node_tree->id, deg::NodeType::NTREE_OUTPUT, deg::OperationCode::NTREE_OUTPUT);
+ deg::OperationKey ntree_preprocess_key(&node_tree->id,
+ deg::NodeType::NTREE_GEOMETRY_PREPROCESS,
+ deg::OperationCode::NTREE_GEOMETRY_PREPROCESS);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(
ntree_output_key, deg_node_handle, description);
+ deg_node_handle->builder->add_node_handle_relation(
+ ntree_preprocess_key, deg_node_handle, description, deg::RELATION_FLAG_NO_FLUSH);
}
void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
diff --git a/source/blender/draw/engines/eevee_next/eevee_camera.cc b/source/blender/draw/engines/eevee_next/eevee_camera.cc
index ad22219f0ae..4331db4bc4c 100644
--- a/source/blender/draw/engines/eevee_next/eevee_camera.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_camera.cc
@@ -32,7 +32,7 @@ void Camera::init()
CameraData &data = data_;
- if (camera_eval) {
+ if (camera_eval && camera_eval->type == OB_CAMERA) {
const ::Camera *cam = reinterpret_cast<const ::Camera *>(camera_eval->data);
switch (cam->type) {
default:
@@ -112,7 +112,7 @@ void Camera::sync()
data.uv_bias = float2(0.0f);
}
- if (camera_eval) {
+ if (camera_eval && camera_eval->type == OB_CAMERA) {
const ::Camera *cam = reinterpret_cast<const ::Camera *>(camera_eval->data);
data.clip_near = cam->clip_start;
data.clip_far = cam->clip_end;
diff --git a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
index e4c4f6f3f6f..8672cce80b6 100644
--- a/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
+++ b/source/blender/draw/engines/eevee_next/eevee_depth_of_field.cc
@@ -44,7 +44,7 @@ void DepthOfField::init()
{
const SceneEEVEE &sce_eevee = inst_.scene->eevee;
const Object *camera_object_eval = inst_.camera_eval_object;
- const ::Camera *camera = (camera_object_eval) ?
+ const ::Camera *camera = (camera_object_eval && camera_object_eval->type == OB_CAMERA) ?
reinterpret_cast<const ::Camera *>(camera_object_eval->data) :
nullptr;
if (camera == nullptr) {
@@ -70,7 +70,7 @@ void DepthOfField::sync()
{
const Camera &camera = inst_.camera;
const Object *camera_object_eval = inst_.camera_eval_object;
- const ::Camera *camera_data = (camera_object_eval) ?
+ const ::Camera *camera_data = (camera_object_eval && camera_object_eval->type == OB_CAMERA) ?
reinterpret_cast<const ::Camera *>(camera_object_eval->data) :
nullptr;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc
index f606701ed09..1f5157e6b8b 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc
+++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc
@@ -376,8 +376,8 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_
is_auto_smooth,
split_angle,
nullptr,
- clnors,
- nullptr);
+ nullptr,
+ clnors);
}
}
else {
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 4fcfec833eb..c8f0fdde62d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -2039,6 +2039,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
DRW_smoke_exit(DST.vmempool);
drw_manager_exit(&DST);
+ DRW_cache_free_old_subdiv();
/* Reset state after drawing */
DRW_state_reset();
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index 94746837259..c980fd73342 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -663,11 +663,16 @@ static bool ed_markers_poll_selected_markers(bContext *C)
ListBase *markers = ED_context_get_markers(C);
if (!ED_operator_markers_region_active(C)) {
- return 0;
+ return false;
}
/* check if some marker is selected */
- return ED_markers_get_first_selected(markers) != NULL;
+ if (ED_markers_get_first_selected(markers) == NULL) {
+ CTX_wm_operator_poll_msg_set(C, "No markers are selected");
+ return false;
+ }
+
+ return true;
}
static bool ed_markers_poll_selected_no_locked_markers(bContext *C)
@@ -675,12 +680,22 @@ static bool ed_markers_poll_selected_no_locked_markers(bContext *C)
ListBase *markers = ED_context_get_markers(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- if (ts->lock_markers || !ED_operator_markers_region_active(C)) {
- return 0;
+ if (!ED_operator_markers_region_active(C)) {
+ return false;
+ }
+
+ if (ts->lock_markers) {
+ CTX_wm_operator_poll_msg_set(C, "Markers are locked");
+ return false;
}
/* check if some marker is selected */
- return ED_markers_get_first_selected(markers) != NULL;
+ if (ED_markers_get_first_selected(markers) == NULL) {
+ CTX_wm_operator_poll_msg_set(C, "No markers are selected");
+ return false;
+ }
+
+ return true;
}
/* special poll() which checks if there are any markers at all first */
diff --git a/source/blender/editors/geometry/geometry_attributes.cc b/source/blender/editors/geometry/geometry_attributes.cc
index 73b5cab1b25..7f163da493b 100644
--- a/source/blender/editors/geometry/geometry_attributes.cc
+++ b/source/blender/editors/geometry/geometry_attributes.cc
@@ -98,7 +98,7 @@ static int geometry_attribute_add_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- BKE_id_attributes_active_set(id, layer);
+ BKE_id_attributes_active_set(id, layer->name);
DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -275,15 +275,14 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
{
Object *ob = ED_object_context(C);
ID *ob_data = static_cast<ID *>(ob->data);
- const CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data);
- const std::string name = layer->name;
-
+ CustomDataLayer *layer = BKE_id_attributes_active_get(ob_data);
const ConvertAttributeMode mode = static_cast<ConvertAttributeMode>(
RNA_enum_get(op->ptr, "mode"));
-
Mesh *mesh = reinterpret_cast<Mesh *>(ob_data);
bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
+ const std::string name = layer->name;
+
/* General conversion steps are always the same:
* 1. Convert old data to right domain and data type.
* 2. Copy the data into a new array so that it does not depend on the old attribute anymore.
@@ -291,21 +290,13 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
* 4. Create a new attribute based on the previously copied data. */
switch (mode) {
case ConvertAttributeMode::Generic: {
- const eAttrDomain dst_domain = static_cast<eAttrDomain>(RNA_enum_get(op->ptr, "domain"));
- const eCustomDataType dst_type = static_cast<eCustomDataType>(
- RNA_enum_get(op->ptr, "data_type"));
-
- if (ELEM(dst_type, CD_PROP_STRING)) {
- BKE_report(op->reports, RPT_ERROR, "Cannot convert to the selected type");
+ if (!ED_geometry_attribute_convert(mesh,
+ name.c_str(),
+ eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
+ eAttrDomain(RNA_enum_get(op->ptr, "domain")),
+ op->reports)) {
return OPERATOR_CANCELLED;
}
-
- GVArray src_varray = attributes.lookup_or_default(name, dst_domain, dst_type);
- const CPPType &cpp_type = src_varray.type();
- void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__);
- src_varray.materialize_to_uninitialized(new_data);
- attributes.remove(name);
- attributes.add(name, dst_domain, dst_type, blender::bke::AttributeInitMoveArray(new_data));
break;
}
case ConvertAttributeMode::UVMap: {
@@ -319,6 +310,10 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
attributes.remove(name);
CustomData_add_layer_named(
&mesh->ldata, CD_MLOOPUV, CD_ASSIGN, dst_uvs, mesh->totloop, name.c_str());
+ int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
+ if (*active_index > 0) {
+ *active_index -= 1;
+ }
break;
}
case ConvertAttributeMode::VertexGroup: {
@@ -337,18 +332,16 @@ static int geometry_attribute_convert_exec(bContext *C, wmOperator *op)
BKE_defvert_add_index_notest(dverts + i, defgroup_index, weight);
}
}
+ int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
+ if (*active_index > 0) {
+ *active_index -= 1;
+ }
break;
}
}
- int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
- if (*active_index > 0) {
- *active_index -= 1;
- }
-
DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, &mesh->id);
-
return OPERATOR_FINISHED;
}
@@ -590,6 +583,79 @@ static int geometry_attribute_convert_invoke(bContext *C,
return WM_operator_props_dialog_popup(C, op, 300);
}
+static bool geometry_color_attribute_convert_poll(bContext *C)
+{
+ if (!geometry_attributes_poll(C)) {
+ return false;
+ }
+
+ Object *ob = ED_object_context(C);
+ ID *id = static_cast<ID *>(ob->data);
+ if (GS(id->name) != ID_ME) {
+ return false;
+ }
+ CustomDataLayer *layer = BKE_id_attributes_active_color_get(id);
+ if (layer == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+static int geometry_color_attribute_convert_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+ ID *ob_data = static_cast<ID *>(ob->data);
+ CustomDataLayer *layer = BKE_id_attributes_active_color_get(ob_data);
+ ED_geometry_attribute_convert(static_cast<Mesh *>(ob->data),
+ layer->name,
+ eCustomDataType(RNA_enum_get(op->ptr, "data_type")),
+ eAttrDomain(RNA_enum_get(op->ptr, "domain")),
+ op->reports);
+ return OPERATOR_FINISHED;
+}
+
+static void geometry_color_attribute_convert_ui(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *layout = op->layout;
+ uiLayoutSetPropSep(layout, true);
+ uiLayoutSetPropDecorate(layout, false);
+
+ uiItemR(layout, op->ptr, "domain", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+ uiItemR(layout, op->ptr, "data_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
+}
+
+void GEOMETRY_OT_color_attribute_convert(wmOperatorType *ot)
+{
+ ot->name = "Convert Color Attribute";
+ ot->description = "Change how the color attribute is stored";
+ ot->idname = "GEOMETRY_OT_color_attribute_convert";
+
+ ot->invoke = geometry_attribute_convert_invoke;
+ ot->exec = geometry_color_attribute_convert_exec;
+ ot->poll = geometry_color_attribute_convert_poll;
+ ot->ui = geometry_color_attribute_convert_ui;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+
+ prop = RNA_def_enum(ot->srna,
+ "domain",
+ rna_enum_color_attribute_domain_items,
+ ATTR_DOMAIN_POINT,
+ "Domain",
+ "Type of element that attribute is stored on");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
+ prop = RNA_def_enum(ot->srna,
+ "data_type",
+ rna_enum_color_attribute_type_items,
+ CD_PROP_COLOR,
+ "Data Type",
+ "Type of data stored in attribute");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
{
ot->name = "Convert Attribute";
@@ -628,37 +694,31 @@ void GEOMETRY_OT_attribute_convert(wmOperatorType *ot)
} // namespace blender::ed::geometry
-using blender::CPPType;
-using blender::GVArray;
-
bool ED_geometry_attribute_convert(Mesh *mesh,
- const char *layer_name,
- eCustomDataType old_type,
- eAttrDomain old_domain,
- eCustomDataType new_type,
- eAttrDomain new_domain)
+ const char *name,
+ const eCustomDataType dst_type,
+ const eAttrDomain dst_domain,
+ ReportList *reports)
{
- CustomDataLayer *layer = BKE_id_attribute_find(&mesh->id, layer_name, old_type, old_domain);
- const std::string name = layer->name;
-
- if (!layer) {
+ using namespace blender;
+ bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
+ BLI_assert(mesh->attributes().contains(name));
+ BLI_assert(mesh->edit_mesh == nullptr);
+ if (ELEM(dst_type, CD_PROP_STRING)) {
+ if (reports) {
+ BKE_report(reports, RPT_ERROR, "Cannot convert to the selected type");
+ }
return false;
}
- blender::bke::MutableAttributeAccessor attributes = mesh->attributes_for_write();
+ const std::string name_copy = name;
+ const GVArray varray = attributes.lookup_or_default(name_copy, dst_domain, dst_type);
- GVArray src_varray = attributes.lookup_or_default(name, new_domain, new_type);
-
- const CPPType &cpp_type = src_varray.type();
- void *new_data = MEM_malloc_arrayN(src_varray.size(), cpp_type.size(), __func__);
- src_varray.materialize_to_uninitialized(new_data);
- attributes.remove(name);
- attributes.add(name, new_domain, new_type, blender::bke::AttributeInitMoveArray(new_data));
-
- int *active_index = BKE_id_attributes_active_index_p(&mesh->id);
- if (*active_index > 0) {
- *active_index -= 1;
- }
+ const CPPType &cpp_type = varray.type();
+ void *new_data = MEM_malloc_arrayN(varray.size(), cpp_type.size(), __func__);
+ varray.materialize_to_uninitialized(new_data);
+ attributes.remove(name_copy);
+ attributes.add(name_copy, dst_domain, dst_type, bke::AttributeInitMoveArray(new_data));
return true;
}
diff --git a/source/blender/editors/geometry/geometry_intern.hh b/source/blender/editors/geometry/geometry_intern.hh
index a1000a5d01f..0ae63d07c6d 100644
--- a/source/blender/editors/geometry/geometry_intern.hh
+++ b/source/blender/editors/geometry/geometry_intern.hh
@@ -19,5 +19,6 @@ void GEOMETRY_OT_color_attribute_remove(struct wmOperatorType *ot);
void GEOMETRY_OT_color_attribute_render_set(struct wmOperatorType *ot);
void GEOMETRY_OT_color_attribute_duplicate(struct wmOperatorType *ot);
void GEOMETRY_OT_attribute_convert(struct wmOperatorType *ot);
+void GEOMETRY_OT_color_attribute_convert(struct wmOperatorType *ot);
} // namespace blender::ed::geometry
diff --git a/source/blender/editors/geometry/geometry_ops.cc b/source/blender/editors/geometry/geometry_ops.cc
index acac757ecf1..79a0468f51a 100644
--- a/source/blender/editors/geometry/geometry_ops.cc
+++ b/source/blender/editors/geometry/geometry_ops.cc
@@ -24,4 +24,5 @@ void ED_operatortypes_geometry(void)
WM_operatortype_append(GEOMETRY_OT_color_attribute_render_set);
WM_operatortype_append(GEOMETRY_OT_color_attribute_duplicate);
WM_operatortype_append(GEOMETRY_OT_attribute_convert);
+ WM_operatortype_append(GEOMETRY_OT_color_attribute_convert);
}
diff --git a/source/blender/editors/include/ED_geometry.h b/source/blender/editors/include/ED_geometry.h
index 4620181894a..8436df73d10 100644
--- a/source/blender/editors/include/ED_geometry.h
+++ b/source/blender/editors/include/ED_geometry.h
@@ -15,14 +15,21 @@ extern "C" {
#endif
struct Mesh;
+struct ReportList;
void ED_operatortypes_geometry(void);
+
+/**
+ * Convert an attribute with the given name to a new type and domain.
+ * The attribute must already exist.
+ *
+ * \note Does not support meshes in edit mode.
+ */
bool ED_geometry_attribute_convert(struct Mesh *mesh,
- const char *layer_name,
- eCustomDataType old_type,
- eAttrDomain old_domain,
- eCustomDataType new_type,
- eAttrDomain new_domain);
+ const char *name,
+ eCustomDataType dst_type,
+ eAttrDomain dst_domain,
+ ReportList *reports);
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 1c1ce41ef7a..bc4e3b88586 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -22,7 +22,7 @@ struct wmMsgSubscribeValue;
struct wmRegionMessageSubscribeParams;
struct wmOperator;
-/* sculpt.c */
+/* sculpt.cc */
void ED_operatortypes_sculpt(void);
void ED_sculpt_redraw_planes_get(float planes[4][4], struct ARegion *region, struct Object *ob);
diff --git a/source/blender/editors/interface/interface_ops.cc b/source/blender/editors/interface/interface_ops.cc
index 2d06dd2c465..1b576583291 100644
--- a/source/blender/editors/interface/interface_ops.cc
+++ b/source/blender/editors/interface/interface_ops.cc
@@ -1165,7 +1165,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = static_cast<bNodeSocket *>(ptr->data);
- if (nodeFindNode(ntree, sock, &node, nullptr)) {
+ if (nodeFindNodeTry(ntree, sock, &node, nullptr)) {
if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != nullptr) {
/* we're good! */
}
diff --git a/source/blender/editors/interface/interface_region_color_picker.cc b/source/blender/editors/interface/interface_region_color_picker.cc
index 0b2c538331a..8b28e9fece1 100644
--- a/source/blender/editors/interface/interface_region_color_picker.cc
+++ b/source/blender/editors/interface/interface_region_color_picker.cc
@@ -199,7 +199,7 @@ static void ui_update_color_picker_buts_rgb(uiBut *from_but,
* push, so disable it on RNA buttons in the color picker block */
UI_but_flag_disable(bt, UI_BUT_UNDO);
}
- else if (STREQ(bt->str, "Hex: ")) {
+ else if (STREQ(bt->str, "Hex:")) {
float rgb_hex[3];
uchar rgb_hex_uchar[3];
char col[16];
@@ -613,7 +613,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("R:"),
+ IFACE_("Red:"),
0,
yco,
butwidth,
@@ -623,7 +623,7 @@ static void ui_block_colorpicker(uiBlock *block,
0,
0.0,
0.0,
- 0,
+ 10,
3,
TIP_("Red"));
UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
@@ -631,7 +631,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("G:"),
+ IFACE_("Green:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -641,7 +641,7 @@ static void ui_block_colorpicker(uiBlock *block,
1,
0.0,
0.0,
- 0,
+ 10,
3,
TIP_("Green"));
UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
@@ -649,7 +649,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("B:"),
+ IFACE_("Blue:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -659,7 +659,7 @@ static void ui_block_colorpicker(uiBlock *block,
2,
0.0,
0.0,
- 0,
+ 10,
3,
TIP_("Blue"));
UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
@@ -675,7 +675,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("H:"),
+ IFACE_("Hue:"),
0,
yco,
butwidth,
@@ -692,7 +692,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("S:"),
+ IFACE_("Saturation:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -710,7 +710,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("L:"),
+ IFACE_("Lightness:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -726,7 +726,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButF(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("V:"),
+ IFACE_("Value:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -750,7 +750,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefButR_prop(block,
UI_BTYPE_NUM_SLIDER,
0,
- IFACE_("A: "),
+ IFACE_("Alpha:"),
0,
yco -= UI_UNIT_Y,
butwidth,
@@ -760,7 +760,7 @@ static void ui_block_colorpicker(uiBlock *block,
3,
0.0,
0.0,
- 0,
+ 10,
3,
TIP_("Alpha"));
UI_but_func_set(bt, ui_colorpicker_rgba_update_cb, bt, nullptr);
@@ -788,7 +788,7 @@ static void ui_block_colorpicker(uiBlock *block,
bt = uiDefBut(block,
UI_BTYPE_TEXT,
0,
- IFACE_("Hex: "),
+ IFACE_("Hex:"),
0,
yco,
butwidth,
diff --git a/source/blender/editors/interface/view2d_gizmo_navigate.cc b/source/blender/editors/interface/view2d_gizmo_navigate.cc
index 78549a33fc5..f754b2ab088 100644
--- a/source/blender/editors/interface/view2d_gizmo_navigate.cc
+++ b/source/blender/editors/interface/view2d_gizmo_navigate.cc
@@ -110,7 +110,6 @@ struct NavigateWidgetGroup {
struct {
rcti rect_visible;
} state;
- int region_size[2];
};
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType * /*gzgt*/)
@@ -145,9 +144,6 @@ static void WIDGETGROUP_navigate_setup(const bContext * /*C*/, wmGizmoGroup *gzg
{
NavigateWidgetGroup *navgroup = MEM_cnew<NavigateWidgetGroup>(__func__);
- navgroup->region_size[0] = -1;
- navgroup->region_size[1] = -1;
-
const struct NavigateGizmoInfo *navigate_params = navigate_params_from_space_type(
gzgroup->type->gzmap_params.spaceid);
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 2709ac3fd91..b29fc0e9e7d 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -60,7 +60,7 @@ set(SRC
paint_vertex_proj.c
paint_vertex_weight_ops.c
paint_vertex_weight_utils.c
- sculpt.c
+ sculpt.cc
sculpt_automasking.cc
sculpt_boundary.c
sculpt_brush_types.c
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
index df7dd871a94..d6c4d43d5fc 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_ops.cc
@@ -76,7 +76,7 @@ namespace blender::ed::sculpt_paint {
using blender::bke::CurvesGeometry;
/* -------------------------------------------------------------------- */
-/** \name * SCULPT_CURVES_OT_brush_stroke
+/** \name Brush Stroke Operator
* \{ */
float brush_radius_factor(const Brush &brush, const StrokeExtension &stroke_extension)
@@ -271,7 +271,7 @@ static void SCULPT_CURVES_OT_brush_stroke(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name * CURVES_OT_sculptmode_toggle
+/** \name Toggle Sculpt Mode
* \{ */
static void curves_sculptmode_enter(bContext *C)
@@ -592,8 +592,8 @@ namespace select_grow {
struct GrowOperatorDataPerCurve : NonCopyable, NonMovable {
Curves *curves_id;
- Vector<int> selected_point_indices;
- Vector<int> unselected_point_indices;
+ Vector<int> selected_points;
+ Vector<int> unselected_points;
Array<float> distances_to_selected;
Array<float> distances_to_unselected;
@@ -612,34 +612,32 @@ static void update_points_selection(const GrowOperatorDataPerCurve &data,
{
if (distance > 0.0f) {
threading::parallel_for(
- data.unselected_point_indices.index_range(), 256, [&](const IndexRange range) {
+ data.unselected_points.index_range(), 256, [&](const IndexRange range) {
for (const int i : range) {
- const int point_i = data.unselected_point_indices[i];
+ const int point_i = data.unselected_points[i];
const float distance_to_selected = data.distances_to_selected[i];
const float selection = distance_to_selected <= distance ? 1.0f : 0.0f;
points_selection[point_i] = selection;
}
});
- threading::parallel_for(
- data.selected_point_indices.index_range(), 512, [&](const IndexRange range) {
- for (const int point_i : data.selected_point_indices.as_span().slice(range)) {
- points_selection[point_i] = 1.0f;
- }
- });
+ threading::parallel_for(data.selected_points.index_range(), 512, [&](const IndexRange range) {
+ for (const int point_i : data.selected_points.as_span().slice(range)) {
+ points_selection[point_i] = 1.0f;
+ }
+ });
}
else {
+ threading::parallel_for(data.selected_points.index_range(), 256, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int point_i = data.selected_points[i];
+ const float distance_to_unselected = data.distances_to_unselected[i];
+ const float selection = distance_to_unselected <= -distance ? 0.0f : 1.0f;
+ points_selection[point_i] = selection;
+ }
+ });
threading::parallel_for(
- data.selected_point_indices.index_range(), 256, [&](const IndexRange range) {
- for (const int i : range) {
- const int point_i = data.selected_point_indices[i];
- const float distance_to_unselected = data.distances_to_unselected[i];
- const float selection = distance_to_unselected <= -distance ? 0.0f : 1.0f;
- points_selection[point_i] = selection;
- }
- });
- threading::parallel_for(
- data.unselected_point_indices.index_range(), 512, [&](const IndexRange range) {
- for (const int point_i : data.unselected_point_indices.as_span().slice(range)) {
+ data.unselected_points.index_range(), 512, [&](const IndexRange range) {
+ for (const int point_i : data.unselected_points.as_span().slice(range)) {
points_selection[point_i] = 0.0f;
}
});
@@ -707,10 +705,10 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
for (const int point_i : points_selection.index_range()) {
const float point_selection = points_selection[point_i];
if (point_selection > 0.0f) {
- curve_op_data.selected_point_indices.append(point_i);
+ curve_op_data.selected_points.append(point_i);
}
else {
- curve_op_data.unselected_point_indices.append(point_i);
+ curve_op_data.unselected_points.append(point_i);
}
}
@@ -725,12 +723,12 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
const IndexRange points = curves.points_for_curve(curve_i);
if (curve_selection > 0.0f) {
for (const int point_i : points) {
- curve_op_data.selected_point_indices.append(point_i);
+ curve_op_data.selected_points.append(point_i);
}
}
else {
for (const int point_i : points) {
- curve_op_data.unselected_point_indices.append(point_i);
+ curve_op_data.unselected_points.append(point_i);
}
}
}
@@ -739,50 +737,46 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
}
threading::parallel_invoke(
- 1024 < curve_op_data.selected_point_indices.size() +
- curve_op_data.unselected_point_indices.size(),
+ 1024 < curve_op_data.selected_points.size() + curve_op_data.unselected_points.size(),
[&]() {
/* Build KD-tree for the selected points. */
- KDTree_3d *kdtree = BLI_kdtree_3d_new(curve_op_data.selected_point_indices.size());
+ KDTree_3d *kdtree = BLI_kdtree_3d_new(curve_op_data.selected_points.size());
BLI_SCOPED_DEFER([&]() { BLI_kdtree_3d_free(kdtree); });
- for (const int point_i : curve_op_data.selected_point_indices) {
+ for (const int point_i : curve_op_data.selected_points) {
const float3 &position = positions[point_i];
BLI_kdtree_3d_insert(kdtree, point_i, position);
}
BLI_kdtree_3d_balance(kdtree);
/* For each unselected point, compute the distance to the closest selected point. */
- curve_op_data.distances_to_selected.reinitialize(
- curve_op_data.unselected_point_indices.size());
- threading::parallel_for(curve_op_data.unselected_point_indices.index_range(),
- 256,
- [&](const IndexRange range) {
- for (const int i : range) {
- const int point_i = curve_op_data.unselected_point_indices[i];
- const float3 &position = positions[point_i];
- KDTreeNearest_3d nearest;
- BLI_kdtree_3d_find_nearest(kdtree, position, &nearest);
- curve_op_data.distances_to_selected[i] = nearest.dist;
- }
- });
+ curve_op_data.distances_to_selected.reinitialize(curve_op_data.unselected_points.size());
+ threading::parallel_for(
+ curve_op_data.unselected_points.index_range(), 256, [&](const IndexRange range) {
+ for (const int i : range) {
+ const int point_i = curve_op_data.unselected_points[i];
+ const float3 &position = positions[point_i];
+ KDTreeNearest_3d nearest;
+ BLI_kdtree_3d_find_nearest(kdtree, position, &nearest);
+ curve_op_data.distances_to_selected[i] = nearest.dist;
+ }
+ });
},
[&]() {
/* Build KD-tree for the unselected points. */
- KDTree_3d *kdtree = BLI_kdtree_3d_new(curve_op_data.unselected_point_indices.size());
+ KDTree_3d *kdtree = BLI_kdtree_3d_new(curve_op_data.unselected_points.size());
BLI_SCOPED_DEFER([&]() { BLI_kdtree_3d_free(kdtree); });
- for (const int point_i : curve_op_data.unselected_point_indices) {
+ for (const int point_i : curve_op_data.unselected_points) {
const float3 &position = positions[point_i];
BLI_kdtree_3d_insert(kdtree, point_i, position);
}
BLI_kdtree_3d_balance(kdtree);
/* For each selected point, compute the distance to the closest unselected point. */
- curve_op_data.distances_to_unselected.reinitialize(
- curve_op_data.selected_point_indices.size());
+ curve_op_data.distances_to_unselected.reinitialize(curve_op_data.selected_points.size());
threading::parallel_for(
- curve_op_data.selected_point_indices.index_range(), 256, [&](const IndexRange range) {
+ curve_op_data.selected_points.index_range(), 256, [&](const IndexRange range) {
for (const int i : range) {
- const int point_i = curve_op_data.selected_point_indices[i];
+ const int point_i = curve_op_data.selected_points[i];
const float3 &position = positions[point_i];
KDTreeNearest_3d nearest;
BLI_kdtree_3d_find_nearest(kdtree, position, &nearest);
@@ -800,12 +794,12 @@ static void select_grow_invoke_per_curve(Curves &curves_id,
/* Compute how mouse movements in screen space are converted into grow/shrink distances in
* object space. */
curve_op_data.pixel_to_distance_factor = threading::parallel_reduce(
- curve_op_data.selected_point_indices.index_range(),
+ curve_op_data.selected_points.index_range(),
256,
FLT_MAX,
[&](const IndexRange range, float pixel_to_distance_factor) {
for (const int i : range) {
- const int point_i = curve_op_data.selected_point_indices[i];
+ const int point_i = curve_op_data.selected_points[i];
const float3 &pos_cu = positions[point_i];
float2 pos_re;
@@ -1269,7 +1263,7 @@ static void SCULPT_CURVES_OT_min_distance_edit(wmOperatorType *ot)
} // namespace blender::ed::sculpt_paint
/* -------------------------------------------------------------------- */
-/** \name * Registration
+/** \name Registration
* \{ */
void ED_operatortypes_sculpt_curves()
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.cc b/source/blender/editors/sculpt_paint/paint_vertex.cc
index 8e790ac435e..8758d3fa83f 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.cc
+++ b/source/blender/editors/sculpt_paint/paint_vertex.cc
@@ -1162,7 +1162,7 @@ static void do_weight_paint_vertex(
}
}
-/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.c) */
+/* Toggle operator for turning vertex paint mode on or off (copied from sculpt.cc) */
static void vertex_paint_init_session(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
@@ -2388,7 +2388,7 @@ static void wpaint_do_paint(bContext *C,
WeightPaintInfo *wpi,
Mesh *me,
Brush *brush,
- const char symm,
+ const ePaintSymmetryFlags symm,
const int axis,
const int i,
const float angle)
@@ -2415,7 +2415,7 @@ static void wpaint_do_radial_symmetry(bContext *C,
WeightPaintInfo *wpi,
Mesh *me,
Brush *brush,
- const char symm,
+ const ePaintSymmetryFlags symm,
const int axis)
{
for (int i = 1; i < wp->radial_symm[axis - 'X']; i++) {
@@ -2424,7 +2424,7 @@ static void wpaint_do_radial_symmetry(bContext *C,
}
}
-/* near duplicate of: sculpt.c's,
+/* near duplicate of: sculpt.cc's,
* 'do_symmetrical_brush_actions' and 'vpaint_do_symmetrical_brush_actions'. */
static void wpaint_do_symmetrical_brush_actions(
bContext *C, Object *ob, VPaint *wp, Sculpt *sd, WPaintData *wpd, WeightPaintInfo *wpi)
@@ -2437,11 +2437,11 @@ static void wpaint_do_symmetrical_brush_actions(
int i = 0;
/* initial stroke */
- cache->mirror_symmetry_pass = 0;
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'X');
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Y');
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, 0, 'Z');
+ cache->mirror_symmetry_pass = ePaintSymmetryFlags(0);
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, ePaintSymmetryFlags(0), 'X', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, ePaintSymmetryFlags(0), 'X');
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, ePaintSymmetryFlags(0), 'Y');
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, ePaintSymmetryFlags(0), 'Z');
cache->symmetry = symm;
@@ -2456,21 +2456,22 @@ static void wpaint_do_symmetrical_brush_actions(
* X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
for (i = 1; i <= symm; i++) {
if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) {
- cache->mirror_symmetry_pass = i;
+ const ePaintSymmetryFlags symm = ePaintSymmetryFlags(i);
+ cache->mirror_symmetry_pass = symm;
cache->radial_symmetry_pass = 0;
- SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, symm, 0, 0);
if (i & (1 << 0)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'X');
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'X', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'X');
}
if (i & (1 << 1)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Y');
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'Y', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'Y');
}
if (i & (1 << 2)) {
- wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z', 0, 0);
- wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, i, 'Z');
+ wpaint_do_paint(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'Z', 0, 0);
+ wpaint_do_radial_symmetry(C, ob, wp, sd, wpd, wpi, me, brush, symm, 'Z');
}
}
}
@@ -3738,7 +3739,7 @@ static void vpaint_do_paint(bContext *C,
Object *ob,
Mesh *me,
Brush *brush,
- const char symm,
+ const ePaintSymmetryFlags symm,
const int axis,
const int i,
const float angle)
@@ -3769,7 +3770,7 @@ static void vpaint_do_radial_symmetry(bContext *C,
Object *ob,
Mesh *me,
Brush *brush,
- const char symm,
+ const ePaintSymmetryFlags symm,
const int axis)
{
for (int i = 1; i < vp->radial_symm[axis - 'X']; i++) {
@@ -3778,7 +3779,7 @@ static void vpaint_do_radial_symmetry(bContext *C,
}
}
-/* near duplicate of: sculpt.c's,
+/* near duplicate of: sculpt.cc's,
* 'do_symmetrical_brush_actions' and 'wpaint_do_symmetrical_brush_actions'. */
template<typename Color, typename Traits, eAttrDomain domain>
static void vpaint_do_symmetrical_brush_actions(
@@ -3792,11 +3793,15 @@ static void vpaint_do_symmetrical_brush_actions(
int i = 0;
/* initial stroke */
- cache->mirror_symmetry_pass = 0;
- vpaint_do_paint<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'X');
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Y');
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Z');
+ const ePaintSymmetryFlags initial_symm = ePaintSymmetryFlags(0);
+ cache->mirror_symmetry_pass = ePaintSymmetryFlags(0);
+ vpaint_do_paint<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, initial_symm, 'X', 0, 0);
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, initial_symm, 'X');
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, initial_symm, 'Y');
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, initial_symm, 'Z');
cache->symmetry = symm;
@@ -3804,21 +3809,28 @@ static void vpaint_do_symmetrical_brush_actions(
* X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
for (i = 1; i <= symm; i++) {
if (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5))) {
- cache->mirror_symmetry_pass = i;
+ const ePaintSymmetryFlags symm_pass = ePaintSymmetryFlags(i);
+ cache->mirror_symmetry_pass = symm_pass;
cache->radial_symmetry_pass = 0;
- SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, symm_pass, 0, 0);
if (i & (1 << 0)) {
- vpaint_do_paint<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'X', 0, 0);
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'X');
+ vpaint_do_paint<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'X', 0, 0);
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'X');
}
if (i & (1 << 1)) {
- vpaint_do_paint<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Y', 0, 0);
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Y');
+ vpaint_do_paint<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'Y', 0, 0);
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'Y');
}
if (i & (1 << 2)) {
- vpaint_do_paint<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Z', 0, 0);
- vpaint_do_radial_symmetry<Color, Traits, domain>(C, sd, vp, vpd, ob, me, brush, i, 'Z');
+ vpaint_do_paint<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'Z', 0, 0);
+ vpaint_do_radial_symmetry<Color, Traits, domain>(
+ C, sd, vp, vpd, ob, me, brush, symm_pass, 'Z');
}
}
}
diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
index fca25ee2e4b..816e779cd06 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c
@@ -587,6 +587,7 @@ typedef struct WPGradient_userData {
Scene *scene;
Mesh *me;
MDeformVert *dvert;
+ const bool *select_vert;
Brush *brush;
const float *sco_start; /* [2] */
const float *sco_end; /* [2] */
@@ -683,7 +684,7 @@ static void gradientVertInit__mapFunc(void *userData,
WPGradient_userData *grad_data = userData;
WPGradient_vertStore *vs = &grad_data->vert_cache->elem[index];
- if (grad_data->use_select && !(grad_data->dvert[index].flag & SELECT)) {
+ if (grad_data->use_select && (grad_data->select_vert && !grad_data->select_vert[index])) {
copy_v2_fl(vs->sco, FLT_MAX);
return;
}
@@ -811,6 +812,8 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op)
data.scene = scene;
data.me = ob->data;
data.dvert = dverts;
+ data.select_vert = (const bool *)CustomData_get_layer_named(
+ &me->vdata, CD_PROP_BOOL, ".select_vert");
data.sco_start = sco_start;
data.sco_end = sco_end;
data.sco_line_div = 1.0f / len_v2v2(sco_start, sco_end);
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.cc
index 3477285814e..684fcdbff9e 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.cc
@@ -6,6 +6,10 @@
* Implements the Sculpt Mode tools.
*/
+#include <cmath>
+#include <cstdlib>
+#include <cstring>
+
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
@@ -65,10 +69,6 @@
#include "bmesh.h"
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
/* -------------------------------------------------------------------- */
/** \name Sculpt PBVH Abstraction API
*
@@ -121,7 +121,7 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, PBVHVertRef vertex)
return CCG_elem_co(key, CCG_elem_offset(key, elem, vertex_index));
}
}
- return NULL;
+ return nullptr;
}
bool SCULPT_has_loop_colors(const Object *ob)
@@ -209,9 +209,10 @@ void SCULPT_vertex_limit_surface_get(SculptSession *ss, PBVHVertRef vertex, floa
const int grid_index = vertex.i / key->grid_area;
const int vertex_index = vertex.i - grid_index * key->grid_area;
- SubdivCCGCoord coord = {.grid_index = grid_index,
- .x = vertex_index % key->grid_size,
- .y = vertex_index / key->grid_size};
+ SubdivCCGCoord coord{};
+ coord.grid_index = grid_index;
+ coord.x = vertex_index % key->grid_size;
+ coord.y = vertex_index / key->grid_size;
BKE_subdiv_ccg_eval_limit_point(ss->subdiv_ccg, &coord, r_co);
break;
}
@@ -280,9 +281,9 @@ MVert *SCULPT_mesh_deformed_mverts_get(SculptSession *ss)
return ss->mvert;
case PBVH_BMESH:
case PBVH_GRIDS:
- return NULL;
+ return nullptr;
}
- return NULL;
+ return nullptr;
}
float *SCULPT_brush_deform_target_vertex_co_get(SculptSession *ss,
@@ -351,7 +352,7 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex)
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
const bool *hide_vert = BKE_pbvh_get_vert_hide(ss->pbvh);
- return hide_vert == NULL || !hide_vert[vertex.i];
+ return hide_vert == nullptr || !hide_vert[vertex.i];
}
case PBVH_BMESH:
return !BM_elem_flag_test((BMVert *)vertex.i, BM_ELEM_HIDDEN);
@@ -370,8 +371,8 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, PBVHVertRef vertex)
void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visible)
{
- BLI_assert(ss->face_sets != NULL);
- BLI_assert(ss->hide_poly != NULL);
+ BLI_assert(ss->face_sets != nullptr);
+ BLI_assert(ss->hide_poly != nullptr);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
@@ -389,8 +390,8 @@ void SCULPT_face_set_visibility_set(SculptSession *ss, int face_set, bool visibl
void SCULPT_face_visibility_all_invert(SculptSession *ss)
{
- BLI_assert(ss->face_sets != NULL);
- BLI_assert(ss->hide_poly != NULL);
+ BLI_assert(ss->face_sets != nullptr);
+ BLI_assert(ss->hide_poly != nullptr);
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
@@ -415,7 +416,7 @@ void SCULPT_face_visibility_all_set(SculptSession *ss, bool visible)
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES:
case PBVH_GRIDS:
- BLI_assert(ss->hide_poly != NULL);
+ BLI_assert(ss->hide_poly != nullptr);
memset(ss->hide_poly, !visible, sizeof(bool) * ss->totfaces);
break;
case PBVH_BMESH: {
@@ -509,7 +510,7 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
{
switch (BKE_pbvh_type(ss->pbvh)) {
case PBVH_FACES: {
- BLI_assert(ss->face_sets != NULL);
+ BLI_assert(ss->face_sets != nullptr);
const MeshElemMap *vert_map = &ss->pmap[vertex.i];
for (int j = 0; j < vert_map->count; j++) {
const int poly_index = vert_map->indices[j];
@@ -524,7 +525,7 @@ void SCULPT_vertex_face_set_set(SculptSession *ss, PBVHVertRef vertex, int face_
case PBVH_BMESH:
break;
case PBVH_GRIDS: {
- BLI_assert(ss->face_sets != NULL);
+ BLI_assert(ss->face_sets != nullptr);
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int face_index = BKE_subdiv_ccg_grid_to_face_index(ss->subdiv_ccg, grid_index);
@@ -715,9 +716,10 @@ bool SCULPT_vertex_has_unique_face_set(SculptSession *ss, PBVHVertRef vertex)
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int vertex_index = vertex.i - grid_index * key->grid_area;
- const SubdivCCGCoord coord = {.grid_index = grid_index,
- .x = vertex_index % key->grid_size,
- .y = vertex_index / key->grid_size};
+ SubdivCCGCoord coord{};
+ coord.grid_index = grid_index;
+ coord.x = vertex_index % key->grid_size;
+ coord.y = vertex_index / key->grid_size;
int v1, v2;
const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2);
@@ -775,21 +777,23 @@ static void sculpt_vertex_neighbor_add(SculptVertexNeighborIter *iter,
iter->capacity += SCULPT_VERTEX_NEIGHBOR_FIXED_CAPACITY;
if (iter->neighbors == iter->neighbors_fixed) {
- iter->neighbors = MEM_mallocN(iter->capacity * sizeof(PBVHVertRef), "neighbor array");
+ iter->neighbors = static_cast<PBVHVertRef *>(
+ MEM_mallocN(iter->capacity * sizeof(PBVHVertRef), "neighbor array"));
memcpy(iter->neighbors, iter->neighbors_fixed, sizeof(PBVHVertRef) * iter->size);
}
else {
- iter->neighbors = MEM_reallocN_id(
- iter->neighbors, iter->capacity * sizeof(PBVHVertRef), "neighbor array");
+ iter->neighbors = static_cast<PBVHVertRef *>(MEM_reallocN_id(
+ iter->neighbors, iter->capacity * sizeof(PBVHVertRef), "neighbor array"));
}
if (iter->neighbor_indices == iter->neighbor_indices_fixed) {
- iter->neighbor_indices = MEM_mallocN(iter->capacity * sizeof(int), "neighbor array");
+ iter->neighbor_indices = static_cast<int *>(
+ MEM_mallocN(iter->capacity * sizeof(int), "neighbor array"));
memcpy(iter->neighbor_indices, iter->neighbor_indices_fixed, sizeof(int) * iter->size);
}
else {
- iter->neighbor_indices = MEM_reallocN_id(
- iter->neighbor_indices, iter->capacity * sizeof(int), "neighbor array");
+ iter->neighbor_indices = static_cast<int *>(
+ MEM_reallocN_id(iter->neighbor_indices, iter->capacity * sizeof(int), "neighbor array"));
}
}
@@ -849,7 +853,7 @@ static void sculpt_vertex_neighbors_get_faces(SculptSession *ss,
}
if (ss->fake_neighbors.use_fake_neighbors) {
- BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
+ BLI_assert(ss->fake_neighbors.fake_neighbor_index != nullptr);
if (ss->fake_neighbors.fake_neighbor_index[vertex.i] != FAKE_NEIGHBOR_NONE) {
sculpt_vertex_neighbor_add(
iter,
@@ -871,9 +875,10 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
const int grid_index = vertex.i / key->grid_area;
const int vertex_index = vertex.i - grid_index * key->grid_area;
- SubdivCCGCoord coord = {.grid_index = grid_index,
- .x = vertex_index % key->grid_size,
- .y = vertex_index / key->grid_size};
+ SubdivCCGCoord coord{};
+ coord.grid_index = grid_index;
+ coord.x = vertex_index % key->grid_size;
+ coord.y = vertex_index / key->grid_size;
SubdivCCGNeighbors neighbors;
BKE_subdiv_ccg_neighbor_coords_get(ss->subdiv_ccg, &coord, include_duplicates, &neighbors);
@@ -892,7 +897,7 @@ static void sculpt_vertex_neighbors_get_grids(SculptSession *ss,
}
if (ss->fake_neighbors.use_fake_neighbors) {
- BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
+ BLI_assert(ss->fake_neighbors.fake_neighbor_index != nullptr);
if (ss->fake_neighbors.fake_neighbor_index[vertex.i] != FAKE_NEIGHBOR_NONE) {
int v = ss->fake_neighbors.fake_neighbor_index[vertex.i];
sculpt_vertex_neighbor_add(iter, BKE_pbvh_make_vref(v), v);
@@ -946,9 +951,10 @@ bool SCULPT_vertex_is_boundary(const SculptSession *ss, const PBVHVertRef vertex
const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
const int grid_index = vertex.i / key->grid_area;
const int vertex_index = vertex.i - grid_index * key->grid_area;
- const SubdivCCGCoord coord = {.grid_index = grid_index,
- .x = vertex_index % key->grid_size,
- .y = vertex_index / key->grid_size};
+ SubdivCCGCoord coord{};
+ coord.grid_index = grid_index;
+ coord.x = vertex_index % key->grid_size;
+ coord.y = vertex_index / key->grid_size;
int v1, v2;
const SubdivCCGAdjacencyType adjacency = BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(
ss->subdiv_ccg, &coord, ss->mloop, ss->mpoly, &v1, &v2);
@@ -1005,18 +1011,18 @@ bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3],
return is_in_symmetry_area;
}
-typedef struct NearestVertexTLSData {
+struct NearestVertexTLSData {
PBVHVertRef nearest_vertex;
float nearest_vertex_distance_squared;
-} NearestVertexTLSData;
+};
static void do_nearest_vertex_get_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
- NearestVertexTLSData *nvtd = tls->userdata_chunk;
+ NearestVertexTLSData *nvtd = static_cast<NearestVertexTLSData *>(tls->userdata_chunk);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -1030,12 +1036,12 @@ static void do_nearest_vertex_get_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void nearest_vertex_get_reduce(const void *__restrict UNUSED(userdata),
+static void nearest_vertex_get_reduce(const void *__restrict /*userdata*/,
void *__restrict chunk_join,
void *__restrict chunk)
{
- NearestVertexTLSData *join = chunk_join;
- NearestVertexTLSData *nvtd = chunk;
+ NearestVertexTLSData *join = static_cast<NearestVertexTLSData *>(chunk_join);
+ NearestVertexTLSData *nvtd = static_cast<NearestVertexTLSData *>(chunk);
if (join->nearest_vertex.i == PBVH_REF_NONE) {
join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
@@ -1050,26 +1056,24 @@ PBVHVertRef SCULPT_nearest_vertex_get(
Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
{
SculptSession *ss = ob->sculpt;
- PBVHNode **nodes = NULL;
+ PBVHNode **nodes = nullptr;
int totnode;
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = max_distance * max_distance,
- .original = use_original,
- .center = co,
- };
+ SculptSearchSphereData data{};
+ data.sd = sd;
+ data.radius_squared = max_distance * max_distance;
+ data.original = use_original;
+ data.center = co;
+
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
return BKE_pbvh_make_vref(PBVH_REF_NONE);
}
- SculptThreadedTaskData task_data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .max_distance_squared = max_distance * max_distance,
- };
+ SculptThreadedTaskData task_data{};
+ task_data.sd = sd;
+ task_data.ob = ob;
+ task_data.nodes = nodes;
+ task_data.max_distance_squared = max_distance * max_distance;
copy_v3_v3(task_data.nearest_vertex_search_co, co);
NearestVertexTLSData nvtd;
@@ -1103,7 +1107,7 @@ bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3],
continue;
}
float location[3];
- flip_v3_v3(location, br_co, (char)i);
+ flip_v3_v3(location, br_co, ePaintSymmetryFlags(i));
if (len_squared_v3v3(location, vertex) < radius * radius) {
return true;
}
@@ -1176,7 +1180,7 @@ void SCULPT_floodfill_add_initial_with_symmetry(Sculpt *sd,
else if (radius > 0.0f) {
float radius_squared = (radius == FLT_MAX) ? FLT_MAX : radius * radius;
float location[3];
- flip_v3_v3(location, SCULPT_vertex_co_get(ss, vertex), i);
+ flip_v3_v3(location, SCULPT_vertex_co_get(ss, vertex), ePaintSymmetryFlags(i));
v = SCULPT_nearest_vertex_get(sd, ob, location, radius_squared, false);
}
@@ -1203,7 +1207,7 @@ void SCULPT_floodfill_add_active(
}
else if (radius > 0.0f) {
float location[3];
- flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), i);
+ flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), ePaintSymmetryFlags(i));
v = SCULPT_nearest_vertex_get(sd, ob, location, radius, false);
}
@@ -1253,7 +1257,7 @@ void SCULPT_floodfill_free(SculptFloodFill *flood)
{
MEM_SAFE_FREE(flood->visited_verts);
BLI_gsqueue_free(flood->queue);
- flood->queue = NULL;
+ flood->queue = nullptr;
}
/** \} */
@@ -1302,7 +1306,7 @@ static bool sculpt_tool_is_proxy_used(const char sculpt_tool)
static bool sculpt_brush_use_topology_rake(const SculptSession *ss, const Brush *brush)
{
return SCULPT_TOOL_HAS_TOPOLOGY_RAKE(brush->sculpt_tool) &&
- (brush->topology_rake_factor > 0.0f) && (ss->bm != NULL);
+ (brush->topology_rake_factor > 0.0f) && (ss->bm != nullptr);
}
/**
@@ -1340,11 +1344,11 @@ static bool sculpt_brush_needs_rake_rotation(const Brush *brush)
/** \name Sculpt Init/Update
* \{ */
-typedef enum StrokeFlags {
+enum StrokeFlags {
CLIP_X = 1,
CLIP_Y = 2,
CLIP_Z = 4,
-} StrokeFlags;
+};
void SCULPT_orig_vert_data_unode_init(SculptOrigVertData *data, Object *ob, SculptUndoNode *unode)
{
@@ -1399,7 +1403,7 @@ void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter
}
}
-static void sculpt_rake_data_update(struct SculptRakeData *srd, const float co[3])
+static void sculpt_rake_data_update(SculptRakeData *srd, const float co[3])
{
float rake_dist = len_v3v3(srd->follow_co, co);
if (rake_dist > srd->follow_dist) {
@@ -1434,9 +1438,9 @@ bool SCULPT_stroke_is_dynamic_topology(const SculptSession *ss, const Brush *bru
static void paint_mesh_restore_co_task_cb(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
SculptUndoNode *unode;
@@ -1518,19 +1522,18 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob)
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
/**
* Disable multi-threading when dynamic-topology is enabled. Otherwise,
* new entries might be inserted by #SCULPT_undo_push_node() into the #GHash
* used internally by #BM_log_original_vert_co() by a different thread. See T33787.
*/
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true && !ss->bm, totnode);
@@ -1624,7 +1627,7 @@ void SCULPT_brush_test_init(SculptSession *ss, SculptBrushTest *test)
}
else {
copy_v3_v3(test->location, ss->cursor_location);
- test->mirror_symmetry_pass = 0;
+ test->mirror_symmetry_pass = ePaintSymmetryFlags(0);
test->radial_symmetry_pass = 0;
unit_m4(test->symm_rot_mat_inv);
}
@@ -1640,7 +1643,7 @@ void SCULPT_brush_test_init(SculptSession *ss, SculptBrushTest *test)
test->clip_rv3d = rv3d;
}
else {
- test->clip_rv3d = NULL;
+ test->clip_rv3d = nullptr;
}
}
@@ -1837,7 +1840,10 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test,
/* ===== Sculpting =====
*/
-static float calc_overlap(StrokeCache *cache, const char symm, const char axis, const float angle)
+static float calc_overlap(StrokeCache *cache,
+ const ePaintSymmetryFlags symm,
+ const char axis,
+ const float angle)
{
float mirror[3];
float distsq;
@@ -1860,7 +1866,7 @@ static float calc_overlap(StrokeCache *cache, const char symm, const char axis,
static float calc_radial_symmetry_feather(Sculpt *sd,
StrokeCache *cache,
- const char symm,
+ const ePaintSymmetryFlags symm,
const char axis)
{
float overlap = 0.0f;
@@ -1887,11 +1893,11 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
continue;
}
- overlap += calc_overlap(cache, i, 0, 0);
+ overlap += calc_overlap(cache, ePaintSymmetryFlags(i), 0, 0);
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'X');
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'Y');
- overlap += calc_radial_symmetry_feather(sd, cache, i, 'Z');
+ overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'X');
+ overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Y');
+ overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Z');
}
return 1.0f / overlap;
}
@@ -1912,26 +1918,26 @@ static float calc_symmetry_feather(Sculpt *sd, StrokeCache *cache)
* \note These are all _very_ similar, when changing one, check others.
* \{ */
-typedef struct AreaNormalCenterTLSData {
+struct AreaNormalCenterTLSData {
/* 0 = towards view, 1 = flipped */
float area_cos[2][3];
float area_nos[2][3];
int count_no[2];
int count_co[2];
-} AreaNormalCenterTLSData;
+};
static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
- AreaNormalCenterTLSData *anctd = tls->userdata_chunk;
+ AreaNormalCenterTLSData *anctd = static_cast<AreaNormalCenterTLSData *>(tls->userdata_chunk);
const bool use_area_nos = data->use_area_nos;
const bool use_area_cos = data->use_area_cos;
PBVHVertexIter vd;
- SculptUndoNode *unode = NULL;
+ SculptUndoNode *unode = nullptr;
bool use_original = false;
bool normal_test_r, area_test_r;
@@ -1982,7 +1988,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
int(*orco_tris)[3];
int orco_tris_num;
- BKE_pbvh_node_get_bm_orco_data(data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords, NULL);
+ BKE_pbvh_node_get_bm_orco_data(
+ data->nodes[n], &orco_tris, &orco_tris_num, &orco_coords, nullptr);
for (int i = 0; i < orco_tris_num; i++) {
const float *co_tri[3] = {
@@ -2109,12 +2116,12 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
}
}
-static void calc_area_normal_and_center_reduce(const void *__restrict UNUSED(userdata),
+static void calc_area_normal_and_center_reduce(const void *__restrict /*userdata*/,
void *__restrict chunk_join,
void *__restrict chunk)
{
- AreaNormalCenterTLSData *join = chunk_join;
- AreaNormalCenterTLSData *anctd = chunk;
+ AreaNormalCenterTLSData *join = static_cast<AreaNormalCenterTLSData *>(chunk_join);
+ AreaNormalCenterTLSData *anctd = static_cast<AreaNormalCenterTLSData *>(chunk);
/* For flatten center. */
add_v3_v3(join->area_cos[0], anctd->area_cos[0]);
@@ -2137,16 +2144,15 @@ void SCULPT_calc_area_center(
const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
int n;
- /* Intentionally set 'sd' to NULL since we share logic with vertex paint. */
- SculptThreadedTaskData data = {
- .sd = NULL,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .totnode = totnode,
- .has_bm_orco = has_bm_orco,
- .use_area_cos = true,
- };
+ /* Intentionally set 'sd' to nullptr since we share logic with vertex paint. */
+ SculptThreadedTaskData data{};
+ data.sd = nullptr;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.totnode = totnode;
+ data.has_bm_orco = has_bm_orco;
+ data.use_area_cos = true;
AreaNormalCenterTLSData anctd = {{{0}}};
@@ -2195,17 +2201,16 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush,
SculptSession *ss = ob->sculpt;
const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
- /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
- SculptThreadedTaskData data = {
- .sd = NULL,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .totnode = totnode,
- .has_bm_orco = has_bm_orco,
- .use_area_nos = true,
- .any_vertex_sampled = false,
- };
+ /* Intentionally set 'sd' to nullptr since this is used for vertex paint too. */
+ SculptThreadedTaskData data{};
+ data.sd = nullptr;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.totnode = totnode;
+ data.has_bm_orco = has_bm_orco;
+ data.use_area_nos = true;
+ data.any_vertex_sampled = false;
AreaNormalCenterTLSData anctd = {{{0}}};
@@ -2234,17 +2239,16 @@ void SCULPT_calc_area_normal_and_center(
const bool has_bm_orco = ss->bm && SCULPT_stroke_is_dynamic_topology(ss, brush);
int n;
- /* Intentionally set 'sd' to NULL since this is used for vertex paint too. */
- SculptThreadedTaskData data = {
- .sd = NULL,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .totnode = totnode,
- .has_bm_orco = has_bm_orco,
- .use_area_cos = true,
- .use_area_nos = true,
- };
+ /* Intentionally set 'sd' to nullptr since this is used for vertex paint too. */
+ SculptThreadedTaskData data{};
+ data.sd = nullptr;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.totnode = totnode;
+ data.has_bm_orco = has_bm_orco;
+ data.use_area_cos = true;
+ data.use_area_nos = true;
AreaNormalCenterTLSData anctd = {{{0}}};
@@ -2298,7 +2302,7 @@ static float brush_strength(const Sculpt *sd,
const StrokeCache *cache,
const float feather,
const UnifiedPaintSettings *ups,
- const PaintModeSettings *UNUSED(paint_mode_settings))
+ const PaintModeSettings * /*paint_mode_settings*/)
{
const Scene *scene = cache->vc->scene;
const Brush *brush = BKE_paint_brush((Paint *)&sd->paint);
@@ -2545,7 +2549,7 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
{
- SculptSearchSphereData *data = data_v;
+ SculptSearchSphereData *data = static_cast<SculptSearchSphereData *>(data_v);
const float *center;
float nearest[3];
if (data->center) {
@@ -2591,7 +2595,7 @@ bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v)
bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v)
{
- SculptSearchCircleData *data = data_v;
+ SculptSearchCircleData *data = static_cast<SculptSearchCircleData *>(data_v);
float bb_min[3], bb_max[3];
if (data->ignore_fully_ineffective) {
@@ -2653,15 +2657,14 @@ static PBVHNode **sculpt_pbvh_gather_cursor_update(Object *ob,
int *r_totnode)
{
SculptSession *ss = ob->sculpt;
- PBVHNode **nodes = NULL;
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = ss->cursor_radius,
- .original = use_original,
- .ignore_fully_ineffective = false,
- .center = NULL,
- };
+ PBVHNode **nodes = nullptr;
+ SculptSearchSphereData data{};
+ data.ss = ss;
+ data.sd = sd;
+ data.radius_squared = ss->cursor_radius;
+ data.original = use_original;
+ data.ignore_fully_ineffective = false;
+ data.center = nullptr;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
return nodes;
}
@@ -2674,34 +2677,32 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
int *r_totnode)
{
SculptSession *ss = ob->sculpt;
- PBVHNode **nodes = NULL;
+ PBVHNode **nodes = nullptr;
/* Build a list of all nodes that are potentially within the cursor or brush's area of influence.
*/
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = square_f(ss->cache->radius * radius_scale),
- .original = use_original,
- .ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK,
- .center = NULL,
- };
+ SculptSearchSphereData data{};
+ data.ss = ss;
+ data.sd = sd;
+ data.radius_squared = square_f(ss->cache->radius * radius_scale);
+ data.original = use_original;
+ data.ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK;
+ data.center = nullptr;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, r_totnode);
}
else {
- struct DistRayAABB_Precalc dist_ray_to_aabb_precalc;
+ DistRayAABB_Precalc dist_ray_to_aabb_precalc;
dist_squared_ray_to_aabb_v3_precalc(
&dist_ray_to_aabb_precalc, ss->cache->location, ss->cache->view_normal);
- SculptSearchCircleData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = ss->cache ? square_f(ss->cache->radius * radius_scale) :
- ss->cursor_radius,
- .original = use_original,
- .dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
- .ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK,
- };
+ SculptSearchCircleData data{};
+ data.ss = ss;
+ data.sd = sd;
+ data.radius_squared = ss->cache ? square_f(ss->cache->radius * radius_scale) :
+ ss->cursor_radius;
+ data.original = use_original;
+ data.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc;
+ data.ignore_fully_ineffective = brush->sculpt_tool != SCULPT_TOOL_MASK;
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_circle_cb, &data, &nodes, r_totnode);
}
return nodes;
@@ -2899,7 +2900,7 @@ static void sculpt_pbvh_update_pixels(PaintModeSettings *paint_mode_settings,
/** \name Generic Brush Plane & Symmetry Utilities
* \{ */
-typedef struct {
+struct SculptRaycastData {
SculptSession *ss;
const float *ray_start;
const float *ray_normal;
@@ -2912,21 +2913,21 @@ typedef struct {
int active_face_grid_index;
- struct IsectRayPrecalc isect_precalc;
-} SculptRaycastData;
+ IsectRayPrecalc isect_precalc;
+};
-typedef struct {
+struct SculptFindNearestToRayData {
SculptSession *ss;
const float *ray_start, *ray_normal;
bool hit;
float depth;
float dist_sq_to_ray;
bool original;
-} SculptFindNearestToRayData;
+};
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
{
- ePaintSymmetryAreas symm_area = PAINT_SYMM_AREA_DEFAULT;
+ ePaintSymmetryAreas symm_area = ePaintSymmetryAreas(PAINT_SYMM_AREA_DEFAULT);
if (co[0] < 0.0f) {
symm_area |= PAINT_SYMM_AREA_X;
}
@@ -2945,7 +2946,7 @@ void SCULPT_flip_v3_by_symm_area(float v[3],
const float pivot[3])
{
for (int i = 0; i < 3; i++) {
- ePaintSymmetryFlags symm_it = 1 << i;
+ ePaintSymmetryFlags symm_it = ePaintSymmetryFlags(1 << i);
if (!(symm & symm_it)) {
continue;
}
@@ -2964,7 +2965,7 @@ void SCULPT_flip_quat_by_symm_area(float quat[4],
const float pivot[3])
{
for (int i = 0; i < 3; i++) {
- ePaintSymmetryFlags symm_it = 1 << i;
+ ePaintSymmetryFlags symm_it = ePaintSymmetryFlags(1 << i);
if (!(symm & symm_it)) {
continue;
}
@@ -3101,7 +3102,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
float *offset = data->offset;
@@ -3129,7 +3130,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
vd.mask ? *vd.mask : 0.0f,
vd.vertex,
thread_id,
- NULL);
+ nullptr);
mul_v3_v3fl(proxy[vd.i], offset, fade);
@@ -3155,13 +3156,12 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
mul_v3_fl(offset, bstrength);
/* Threaded loop over nodes. */
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .offset = offset,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.offset = offset;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@@ -3177,10 +3177,9 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
Mesh *me = (Mesh *)ob->data;
- float(*ofs)[3] = NULL;
+ float(*ofs)[3] = nullptr;
int a;
const int kb_act_idx = ob->shapenr - 1;
- KeyBlock *currkey;
/* For relative keys editing of base should update other keys. */
if (BKE_keyblock_is_basis(me->key, kb_act_idx)) {
@@ -3192,7 +3191,7 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
}
/* Apply offsets on other keys. */
- for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
+ LISTBASE_FOREACH (KeyBlock *, currkey, &me->key->block) {
if ((currkey != kb) && (currkey->relative == kb_act_idx)) {
BKE_keyblock_update_from_offset(ob, currkey, ofs);
}
@@ -3221,8 +3220,8 @@ void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
static void sculpt_topology_update(Sculpt *sd,
Object *ob,
Brush *brush,
- UnifiedPaintSettings *UNUSED(ups),
- PaintModeSettings *UNUSED(paint_mode_settings))
+ UnifiedPaintSettings * /*ups*/,
+ PaintModeSettings * /*paint_mode_settings*/)
{
SculptSession *ss = ob->sculpt;
@@ -3244,7 +3243,7 @@ static void sculpt_topology_update(Sculpt *sd,
MEM_SAFE_FREE(ss->vertex_info.boundary);
MEM_SAFE_FREE(ss->vertex_info.connected_component);
- PBVHTopologyUpdateMode mode = 0;
+ PBVHTopologyUpdateMode mode = PBVHTopologyUpdateMode(0);
float location[3];
if (!(sd->flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) {
@@ -3289,9 +3288,9 @@ static void sculpt_topology_update(Sculpt *sd,
static void do_brush_action_task_cb(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
bool need_coords = ss->cache->supports_gravity;
@@ -3347,7 +3346,7 @@ static void do_brush_action(Sculpt *sd,
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
/* These brushes need to update all nodes as they are not constrained by the brush radius */
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
}
else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
nodes = SCULPT_cloth_brush_affected_nodes_gather(ss, brush, &totnode);
@@ -3385,7 +3384,7 @@ static void do_brush_action(Sculpt *sd,
/* TODO(pablodp606): This check should be done in the undo code and not here, but the rest of
* the sculpt code is not checking for unsupported undo types that may return a null node. */
if (BKE_pbvh_type(ss->pbvh) != PBVH_BMESH) {
- SCULPT_undo_push_node(ob, NULL, SCULPT_UNDO_FACE_SETS);
+ SCULPT_undo_push_node(ob, nullptr, SCULPT_UNDO_FACE_SETS);
}
if (ss->cache->invert) {
@@ -3412,9 +3411,9 @@ static void do_brush_action(Sculpt *sd,
/* Initialize surface smooth cache. */
if ((brush->sculpt_tool == SCULPT_TOOL_SMOOTH) &&
(brush->smooth_deform_type == BRUSH_SMOOTH_DEFORM_SURFACE)) {
- BLI_assert(ss->cache->surface_smooth_laplacian_disp == NULL);
- ss->cache->surface_smooth_laplacian_disp = MEM_callocN(
- sizeof(float[3]) * SCULPT_vertex_count_get(ss), "HC smooth laplacian b");
+ BLI_assert(ss->cache->surface_smooth_laplacian_disp == nullptr);
+ ss->cache->surface_smooth_laplacian_disp = static_cast<float(*)[3]>(
+ MEM_callocN(sizeof(float[3]) * SCULPT_vertex_count_get(ss), "HC smooth laplacian b"));
}
}
}
@@ -3426,12 +3425,11 @@ static void do_brush_action(Sculpt *sd,
float location[3];
if (!use_pixels) {
- SculptThreadedTaskData task_data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- };
+ SculptThreadedTaskData task_data{};
+ task_data.sd = sd;
+ task_data.ob = ob;
+ task_data.brush = brush;
+ task_data.nodes = nodes;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@@ -3627,7 +3625,7 @@ static void do_brush_action(Sculpt *sd,
static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
{
SculptSession *ss = ob->sculpt;
- Mesh *me = ob->data;
+ Mesh *me = static_cast<Mesh *>(ob->data);
float disp[3], newco[3];
int index = vd->vert_indices[vd->i];
@@ -3646,9 +3644,9 @@ static void sculpt_flush_pbvhvert_deform(Object *ob, PBVHVertexIter *vd)
static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
Sculpt *sd = data->sd;
Object *ob = data->ob;
@@ -3657,7 +3655,7 @@ static void sculpt_combine_proxies_task_cb(void *__restrict userdata,
PBVHVertexIter vd;
PBVHProxyNode *proxies;
int proxy_count;
- float(*orco)[3] = NULL;
+ float(*orco)[3] = nullptr;
if (use_orco && !ss->bm) {
orco = SCULPT_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS)->co;
@@ -3718,13 +3716,12 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob)
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .use_proxies_orco = use_orco,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.use_proxies_orco = use_orco;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@@ -3739,12 +3736,11 @@ void SCULPT_combine_transform_proxies(Sculpt *sd, Object *ob)
int totnode;
BKE_pbvh_gather_proxies(ss->pbvh, &nodes, &totnode);
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .use_proxies_orco = false,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.nodes = nodes;
+ data.use_proxies_orco = false;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@@ -3783,9 +3779,9 @@ static void sculpt_update_keyblock(Object *ob)
static void SCULPT_flush_stroke_deform_task_cb(void *__restrict userdata,
const int n,
- const TaskParallelTLS *__restrict UNUSED(tls))
+ const TaskParallelTLS *__restrict /*tls*/)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
Object *ob = data->ob;
float(*vertCos)[3] = data->vertCos;
@@ -3817,25 +3813,25 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
int totnode;
Mesh *me = (Mesh *)ob->data;
PBVHNode **nodes;
- float(*vertCos)[3] = NULL;
+ float(*vertCos)[3] = nullptr;
if (ss->shapekey_active) {
- vertCos = MEM_mallocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts");
+ vertCos = static_cast<float(*)[3]>(
+ MEM_mallocN(sizeof(*vertCos) * me->totvert, "flushStrokeDeofrm keyVerts"));
/* Mesh could have isolated verts which wouldn't be in BVH, to deal with this we copy old
* coordinates over new ones and then update coordinates for all vertices from BVH. */
memcpy(vertCos, ss->orig_cos, sizeof(*vertCos) * me->totvert);
}
- BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ BKE_pbvh_search_gather(ss->pbvh, nullptr, nullptr, &nodes, &totnode);
- SculptThreadedTaskData data = {
- .sd = sd,
- .ob = ob,
- .brush = brush,
- .nodes = nodes,
- .vertCos = vertCos,
- };
+ SculptThreadedTaskData data{};
+ data.sd = sd;
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+ data.vertCos = vertCos;
TaskParallelSettings settings;
BKE_pbvh_parallel_range_settings(&settings, true, totnode);
@@ -3854,7 +3850,7 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used)
}
void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
- const char symm,
+ const ePaintSymmetryFlags symm,
const char axis,
const float angle)
{
@@ -3904,11 +3900,11 @@ void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
}
}
-typedef void (*BrushActionFunc)(Sculpt *sd,
- Object *ob,
- Brush *brush,
- UnifiedPaintSettings *ups,
- PaintModeSettings *paint_mode_settings);
+using BrushActionFunc = void (*)(Sculpt *sd,
+ Object *ob,
+ Brush *brush,
+ UnifiedPaintSettings *ups,
+ PaintModeSettings *paint_mode_settings);
static void do_tiled(Sculpt *sd,
Object *ob,
@@ -3980,9 +3976,9 @@ static void do_radial_symmetry(Sculpt *sd,
UnifiedPaintSettings *ups,
PaintModeSettings *paint_mode_settings,
BrushActionFunc action,
- const char symm,
+ const ePaintSymmetryFlags symm,
const int axis,
- const float UNUSED(feather))
+ const float /*feather*/)
{
SculptSession *ss = ob->sculpt;
@@ -4031,15 +4027,16 @@ static void do_symmetrical_brush_actions(Sculpt *sd,
if (!SCULPT_is_symmetry_iteration_valid(i, symm)) {
continue;
}
- cache->mirror_symmetry_pass = i;
+ const ePaintSymmetryFlags symm = ePaintSymmetryFlags(i);
+ cache->mirror_symmetry_pass = symm;
cache->radial_symmetry_pass = 0;
- SCULPT_cache_calc_brushdata_symm(cache, i, 0, 0);
+ SCULPT_cache_calc_brushdata_symm(cache, symm, 0, 0);
do_tiled(sd, ob, brush, ups, paint_mode_settings, action);
- do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, i, 'X', feather);
- do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, i, 'Y', feather);
- do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, i, 'Z', feather);
+ do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, symm, 'X', feather);
+ do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, symm, 'Y', feather);
+ do_radial_symmetry(sd, ob, brush, ups, paint_mode_settings, action, symm, 'Z', feather);
}
}
@@ -4172,11 +4169,9 @@ void SCULPT_cache_free(StrokeCache *cache)
/* Initialize mirror modifier clipping. */
static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss)
{
- ModifierData *md;
-
unit_m4(ss->cache->clip_mirror_mtx);
- for (md = ob->modifiers.first; md; md = md->next) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (!(md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime))) {
continue;
}
@@ -4272,11 +4267,12 @@ static void smooth_brush_toggle_off(const bContext *C, Paint *paint, StrokeCache
static void sculpt_update_cache_invariants(
bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mval[2])
{
- StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache");
+ StrokeCache *cache = static_cast<StrokeCache *>(
+ MEM_callocN(sizeof(StrokeCache), "stroke cache"));
ToolSettings *tool_settings = CTX_data_tool_settings(C);
UnifiedPaintSettings *ups = &tool_settings->unified_paint_settings;
Brush *brush = BKE_paint_brush(&sd->paint);
- ViewContext *vc = paint_stroke_view_context(op->customdata);
+ ViewContext *vc = paint_stroke_view_context(static_cast<PaintStroke *>(op->customdata));
Object *ob = CTX_data_active_object(C);
float mat[3][3];
float viewDir[3] = {0.0f, 0.0f, 1.0f};
@@ -4830,8 +4826,8 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
if (BKE_pbvh_node_get_tmin(node) >= *tmin) {
return;
}
- SculptRaycastData *srd = data_v;
- float(*origco)[3] = NULL;
+ SculptRaycastData *srd = static_cast<SculptRaycastData *>(data_v);
+ float(*origco)[3] = nullptr;
bool use_origco = false;
if (srd->original && srd->ss->cache) {
@@ -4841,7 +4837,7 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
else {
/* Intersect with coordinates from before we started stroke. */
SculptUndoNode *unode = SCULPT_undo_get_node(node, SCULPT_UNDO_COORDS);
- origco = (unode) ? unode->co : NULL;
+ origco = (unode) ? unode->co : nullptr;
use_origco = origco ? true : false;
}
}
@@ -4867,8 +4863,8 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
if (BKE_pbvh_node_get_tmin(node) >= *tmin) {
return;
}
- SculptFindNearestToRayData *srd = data_v;
- float(*origco)[3] = NULL;
+ SculptFindNearestToRayData *srd = static_cast<SculptFindNearestToRayData *>(data_v);
+ float(*origco)[3] = nullptr;
bool use_origco = false;
if (srd->original && srd->ss->cache) {
@@ -4878,7 +4874,7 @@ static void sculpt_find_nearest_to_ray_cb(PBVHNode *node, void *data_v, float *t
else {
/* Intersect with coordinates from before we started stroke. */
SculptUndoNode *unode = SCULPT_undo_get_node(node, SCULPT_UNDO_COORDS);
- origco = (unode) ? unode->co : NULL;
+ origco = (unode) ? unode->co : nullptr;
use_origco = origco ? true : false;
}
}
@@ -4906,7 +4902,7 @@ float SCULPT_raycast_init(ViewContext *vc,
float obimat[4][4];
float dist;
Object *ob = vc->obact;
- RegionView3D *rv3d = vc->region->regiondata;
+ RegionView3D *rv3d = static_cast<RegionView3D *>(vc->region->regiondata);
View3D *v3d = vc->v3d;
/* TODO: what if the segment is totally clipped? (return == 0). */
@@ -4967,15 +4963,15 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
SCULPT_stroke_modifiers_check(C, ob, brush);
- SculptRaycastData srd = {
- .original = original,
- .ss = ob->sculpt,
- .hit = false,
- .ray_start = ray_start,
- .ray_normal = ray_normal,
- .depth = depth,
- .face_normal = face_normal,
- };
+ SculptRaycastData srd{};
+ srd.original = original;
+ srd.ss = ob->sculpt;
+ srd.hit = false;
+ srd.ray_start = ray_start;
+ srd.ray_normal = ray_normal;
+ srd.depth = depth;
+ srd.face_normal = face_normal;
+
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
@@ -5123,15 +5119,15 @@ bool SCULPT_stroke_get_location(bContext *C,
return hit;
}
- SculptFindNearestToRayData srd = {
- .original = original,
- .ss = ob->sculpt,
- .hit = false,
- .ray_start = ray_start,
- .ray_normal = ray_normal,
- .depth = FLT_MAX,
- .dist_sq_to_ray = FLT_MAX,
- };
+ SculptFindNearestToRayData srd{};
+ srd.original = original;
+ srd.ss = ob->sculpt;
+ srd.hit = false;
+ srd.ray_start = ray_start;
+ srd.ray_normal = ray_normal;
+ srd.depth = FLT_MAX;
+ srd.dist_sq_to_ray = FLT_MAX;
+
BKE_pbvh_find_nearest_to_ray(
ss->pbvh, sculpt_find_nearest_to_ray_cb, &srd, ray_start, ray_normal, srd.original);
if (srd.hit) {
@@ -5155,7 +5151,7 @@ static void sculpt_brush_init_tex(Sculpt *sd, SculptSession *ss)
ntreeTexBeginExecTree(mtex->tex->nodetree);
}
- if (ss->tex_pool == NULL) {
+ if (ss->tex_pool == nullptr) {
ss->tex_pool = BKE_image_pool_new();
}
}
@@ -5256,7 +5252,7 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags)
rv3d->rflag |= RV3D_PAINTING;
}
- if (mmd != NULL) {
+ if (mmd != nullptr) {
multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED);
}
@@ -5317,7 +5313,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
wmWindowManager *wm = CTX_wm_manager(C);
RegionView3D *current_rv3d = CTX_wm_region_view3d(C);
SculptSession *ss = ob->sculpt;
- Mesh *mesh = ob->data;
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
/* Always needed for linked duplicates. */
bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
@@ -5329,7 +5325,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
bScreen *screen = WM_window_get_active_screen(win);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- SpaceLink *sl = area->spacedata.first;
+ SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
if (sl->spacetype != SPACE_VIEW3D) {
continue;
}
@@ -5339,7 +5335,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
* current viewport was deactivated. */
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
if (region->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = region->regiondata;
+ RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
if (rv3d != current_rv3d) {
need_tag |= !BKE_sculptsession_use_pbvh_draw(ob, rv3d);
}
@@ -5351,7 +5347,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
if (update_flags & SCULPT_UPDATE_IMAGE) {
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- SpaceLink *sl = area->spacedata.first;
+ SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
if (sl->spacetype != SPACE_IMAGE) {
continue;
}
@@ -5397,7 +5393,7 @@ void SCULPT_flush_update_done(const bContext *C, Object *ob, SculptUpdateType up
/* Returns whether the mouse/stylus is over the mesh (1)
* or over the background (0). */
-static bool over_mesh(bContext *C, struct wmOperator *UNUSED(op), const float mval[2])
+static bool over_mesh(bContext *C, wmOperator * /*op*/, const float mval[2])
{
float co_dummy[3];
return SCULPT_stroke_get_location(C, co_dummy, mval, false);
@@ -5453,13 +5449,13 @@ bool SCULPT_handles_colors_report(SculptSession *ss, ReportList *reports)
return false;
}
-static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const float mval[2])
+static bool sculpt_stroke_test_start(bContext *C, wmOperator *op, const float mval[2])
{
/* Don't start the stroke until `mval` goes over the mesh.
* NOTE: `mval` will only be null when re-executing the saved stroke.
* We have exception for 'exec' strokes since they may not set `mval`,
* only 'location', see: T52195. */
- if (((op->flag & OP_IS_INVOKE) == 0) || (mval == NULL) || over_mesh(C, op, mval)) {
+ if (((op->flag & OP_IS_INVOKE) == 0) || (mval == nullptr) || over_mesh(C, op, mval)) {
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
@@ -5494,8 +5490,8 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
}
static void sculpt_stroke_update_step(bContext *C,
- wmOperator *UNUSED(op),
- struct PaintStroke *stroke,
+ wmOperator * /*op*/,
+ PaintStroke *stroke,
PointerRNA *itemptr)
{
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
@@ -5582,7 +5578,7 @@ static void sculpt_brush_exit_tex(Sculpt *sd)
}
}
-static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(stroke))
+static void sculpt_stroke_done(const bContext *C, PaintStroke * /*stroke*/)
{
Object *ob = CTX_data_active_object(C);
SculptSession *ss = ob->sculpt;
@@ -5614,7 +5610,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
BKE_pbvh_node_color_buffer_free(ss->pbvh);
SCULPT_cache_free(ss->cache);
- ss->cache = NULL;
+ ss->cache = nullptr;
sculpt_stroke_undo_end(C, brush);
@@ -5640,7 +5636,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str
static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- struct PaintStroke *stroke;
+ PaintStroke *stroke;
int ignore_background_click;
int retval;
Object *ob = CTX_data_active_object(C);
@@ -5682,7 +5678,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step,
- NULL,
+ nullptr,
sculpt_stroke_done,
event->type);
@@ -5690,15 +5686,15 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent
/* For tablet rotation. */
ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
-
- if (ignore_background_click && !over_mesh(C, op, (const float[2]){UNPACK2(event->mval)})) {
- paint_stroke_free(C, op, op->customdata);
+ const float mval[2] = {float(event->mval[0]), float(event->mval[1])};
+ if (ignore_background_click && !over_mesh(C, op, mval)) {
+ paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
return OPERATOR_PASS_THROUGH;
}
retval = op->type->modal(C, op, event);
if (ELEM(retval, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
- paint_stroke_free(C, op, op->customdata);
+ paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
return retval;
}
/* Add modal handler. */
@@ -5719,12 +5715,12 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
SCULPT_stroke_get_location,
sculpt_stroke_test_start,
sculpt_stroke_update_step,
- NULL,
+ nullptr,
sculpt_stroke_done,
0);
/* Frees op->customdata. */
- paint_stroke_exec(C, op, op->customdata);
+ paint_stroke_exec(C, op, static_cast<PaintStroke *>(op->customdata));
return OPERATOR_FINISHED;
}
@@ -5742,11 +5738,11 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
paint_mesh_restore_co(sd, ob);
}
- paint_stroke_cancel(C, op, op->customdata);
+ paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata));
if (ss->cache) {
SCULPT_cache_free(ss->cache);
- ss->cache = NULL;
+ ss->cache = nullptr;
}
sculpt_brush_exit_tex(sd);
@@ -5754,9 +5750,9 @@ static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
- bool started = op->customdata && paint_stroke_started((struct PaintStroke *)op->customdata);
+ bool started = op->customdata && paint_stroke_started((PaintStroke *)op->customdata);
- int retval = paint_stroke_modal(C, op, event, (struct PaintStroke **)&op->customdata);
+ int retval = paint_stroke_modal(C, op, event, (PaintStroke **)&op->customdata);
if (!started && ELEM(retval, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
/* Did the stroke never start? If so push a blank sculpt undo
@@ -5779,7 +5775,7 @@ static int sculpt_brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent
return retval;
}
-static void sculpt_redo_empty_ui(bContext *UNUSED(C), wmOperator *UNUSED(op))
+static void sculpt_redo_empty_ui(bContext * /*C*/, wmOperator * /*op*/)
{
}
@@ -5850,8 +5846,8 @@ static int SCULPT_vertex_get_connected_component(SculptSession *ss, PBVHVertRef
static void SCULPT_fake_neighbor_init(SculptSession *ss, const float max_dist)
{
const int totvert = SCULPT_vertex_count_get(ss);
- ss->fake_neighbors.fake_neighbor_index = MEM_malloc_arrayN(
- totvert, sizeof(int), "fake neighbor");
+ ss->fake_neighbors.fake_neighbor_index = static_cast<int *>(
+ MEM_malloc_arrayN(totvert, sizeof(int), "fake neighbor"));
for (int i = 0; i < totvert; i++) {
ss->fake_neighbors.fake_neighbor_index[i] = FAKE_NEIGHBOR_NONE;
}
@@ -5875,19 +5871,20 @@ static void sculpt_pose_fake_neighbors_free(SculptSession *ss)
MEM_SAFE_FREE(ss->fake_neighbors.fake_neighbor_index);
}
-typedef struct NearestVertexFakeNeighborTLSData {
+struct NearestVertexFakeNeighborTLSData {
PBVHVertRef nearest_vertex;
float nearest_vertex_distance_squared;
int current_topology_id;
-} NearestVertexFakeNeighborTLSData;
+};
static void do_fake_neighbor_search_task_cb(void *__restrict userdata,
const int n,
const TaskParallelTLS *__restrict tls)
{
- SculptThreadedTaskData *data = userdata;
+ SculptThreadedTaskData *data = static_cast<SculptThreadedTaskData *>(userdata);
SculptSession *ss = data->ob->sculpt;
- NearestVertexFakeNeighborTLSData *nvtd = tls->userdata_chunk;
+ NearestVertexFakeNeighborTLSData *nvtd = static_cast<NearestVertexFakeNeighborTLSData *>(
+ tls->userdata_chunk);
PBVHVertexIter vd;
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
@@ -5905,12 +5902,13 @@ static void do_fake_neighbor_search_task_cb(void *__restrict userdata,
BKE_pbvh_vertex_iter_end;
}
-static void fake_neighbor_search_reduce(const void *__restrict UNUSED(userdata),
+static void fake_neighbor_search_reduce(const void *__restrict /*userdata*/,
void *__restrict chunk_join,
void *__restrict chunk)
{
- NearestVertexFakeNeighborTLSData *join = chunk_join;
- NearestVertexFakeNeighborTLSData *nvtd = chunk;
+ NearestVertexFakeNeighborTLSData *join = static_cast<NearestVertexFakeNeighborTLSData *>(
+ chunk_join);
+ NearestVertexFakeNeighborTLSData *nvtd = static_cast<NearestVertexFakeNeighborTLSData *>(chunk);
if (join->nearest_vertex.i == PBVH_REF_NONE) {
join->nearest_vertex = nvtd->nearest_vertex;
join->nearest_vertex_distance_squared = nvtd->nearest_vertex_distance_squared;
@@ -5927,27 +5925,26 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
float max_distance)
{
SculptSession *ss = ob->sculpt;
- PBVHNode **nodes = NULL;
+ PBVHNode **nodes = nullptr;
int totnode;
- SculptSearchSphereData data = {
- .ss = ss,
- .sd = sd,
- .radius_squared = max_distance * max_distance,
- .original = false,
- .center = SCULPT_vertex_co_get(ss, vertex),
- };
+ SculptSearchSphereData data{};
+ data.ss = ss;
+ data.sd = sd;
+ data.radius_squared = max_distance * max_distance;
+ data.original = false;
+ data.center = SCULPT_vertex_co_get(ss, vertex);
+
BKE_pbvh_search_gather(ss->pbvh, SCULPT_search_sphere_cb, &data, &nodes, &totnode);
if (totnode == 0) {
return BKE_pbvh_make_vref(PBVH_REF_NONE);
}
- SculptThreadedTaskData task_data = {
- .sd = sd,
- .ob = ob,
- .nodes = nodes,
- .max_distance_squared = max_distance * max_distance,
- };
+ SculptThreadedTaskData task_data{};
+ task_data.sd = sd;
+ task_data.ob = ob;
+ task_data.nodes = nodes;
+ task_data.max_distance_squared = max_distance * max_distance;
copy_v3_v3(task_data.nearest_vertex_search_co, SCULPT_vertex_co_get(ss, vertex));
@@ -5968,17 +5965,14 @@ static PBVHVertRef SCULPT_fake_neighbor_search(Sculpt *sd,
return nvtd.nearest_vertex;
}
-typedef struct SculptTopologyIDFloodFillData {
+struct SculptTopologyIDFloodFillData {
int next_id;
-} SculptTopologyIDFloodFillData;
+};
-static bool SCULPT_connected_components_floodfill_cb(SculptSession *ss,
- PBVHVertRef from_v,
- PBVHVertRef to_v,
- bool UNUSED(is_duplicate),
- void *userdata)
+static bool SCULPT_connected_components_floodfill_cb(
+ SculptSession *ss, PBVHVertRef from_v, PBVHVertRef to_v, bool /*is_duplicate*/, void *userdata)
{
- SculptTopologyIDFloodFillData *data = userdata;
+ SculptTopologyIDFloodFillData *data = static_cast<SculptTopologyIDFloodFillData *>(userdata);
int from_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, from_v);
int to_v_i = BKE_pbvh_vertex_to_index(ss->pbvh, to_v);
@@ -6000,7 +5994,8 @@ void SCULPT_connected_components_ensure(Object *ob)
}
const int totvert = SCULPT_vertex_count_get(ss);
- ss->vertex_info.connected_component = MEM_malloc_arrayN(totvert, sizeof(int), "topology ID");
+ ss->vertex_info.connected_component = static_cast<int *>(
+ MEM_malloc_arrayN(totvert, sizeof(int), "topology ID"));
for (int i = 0; i < totvert; i++) {
ss->vertex_info.connected_component[i] = SCULPT_TOPOLOGY_ID_NONE;
@@ -6036,8 +6031,8 @@ void SCULPT_boundary_info_ensure(Object *object)
const MLoop *loops = BKE_mesh_loops(base_mesh);
ss->vertex_info.boundary = BLI_BITMAP_NEW(base_mesh->totvert, "Boundary info");
- int *adjacent_faces_edge_count = MEM_calloc_arrayN(
- base_mesh->totedge, sizeof(int), "Adjacent face edge count");
+ int *adjacent_faces_edge_count = static_cast<int *>(
+ MEM_calloc_arrayN(base_mesh->totedge, sizeof(int), "Adjacent face edge count"));
for (int p = 0; p < base_mesh->totpoly; p++) {
const MPoly *poly = &polys[p];
@@ -6091,14 +6086,14 @@ void SCULPT_fake_neighbors_ensure(Sculpt *sd, Object *ob, const float max_dist)
void SCULPT_fake_neighbors_enable(Object *ob)
{
SculptSession *ss = ob->sculpt;
- BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
+ BLI_assert(ss->fake_neighbors.fake_neighbor_index != nullptr);
ss->fake_neighbors.use_fake_neighbors = true;
}
void SCULPT_fake_neighbors_disable(Object *ob)
{
SculptSession *ss = ob->sculpt;
- BLI_assert(ss->fake_neighbors.fake_neighbor_index != NULL);
+ BLI_assert(ss->fake_neighbors.fake_neighbor_index != nullptr);
ss->fake_neighbors.use_fake_neighbors = false;
}
@@ -6109,7 +6104,7 @@ void SCULPT_fake_neighbors_free(Object *ob)
}
void SCULPT_automasking_node_begin(Object *ob,
- const SculptSession *UNUSED(ss),
+ const SculptSession * /*ss*/,
AutomaskingCache *automasking,
AutomaskingNodeData *automask_data,
PBVHNode *node)
@@ -6131,7 +6126,7 @@ void SCULPT_automasking_node_begin(Object *ob,
}
}
-void SCULPT_automasking_node_update(SculptSession *UNUSED(ss),
+void SCULPT_automasking_node_update(SculptSession * /*ss*/,
AutomaskingNodeData *automask_data,
PBVHVertexIter *vd)
{
@@ -6177,7 +6172,7 @@ void SCULPT_stroke_id_next(Object *ob)
/* Manually wrap in int32 space to avoid tripping up undefined behavior
* sanitizers.
*/
- ob->sculpt->stroke_id = (uchar)(((int)ob->sculpt->stroke_id + 1) & 255);
+ ob->sculpt->stroke_id = uchar((int(ob->sculpt->stroke_id) + 1) & 255);
}
void SCULPT_stroke_id_ensure(Object *ob)
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index bf47b64d176..852b3c2719a 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -341,7 +341,7 @@ typedef struct SculptBrushTest {
float radius;
float location[3];
float dist;
- int mirror_symmetry_pass;
+ ePaintSymmetryFlags mirror_symmetry_pass;
int radial_symmetry_pass;
float symm_rot_mat_inv[4][4];
@@ -556,7 +556,8 @@ typedef struct StrokeCache {
/* Symmetry index between 0 and 7 bit combo 0 is Brush only;
* 1 is X mirror; 2 is Y mirror; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
int symmetry;
- int mirror_symmetry_pass; /* The symmetry pass we are currently on between 0 and 7. */
+ ePaintSymmetryFlags
+ mirror_symmetry_pass; /* The symmetry pass we are currently on between 0 and 7. */
float true_view_normal[3];
float view_normal[3];
@@ -1526,7 +1527,10 @@ bool SCULPT_pbvh_calc_area_normal(const struct Brush *brush,
* Flip all the edit-data across the axis/axes specified by \a symm.
* Used to calculate multiple modifications to the mesh when symmetry is enabled.
*/
-void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache, char symm, char axis, float angle);
+void SCULPT_cache_calc_brushdata_symm(StrokeCache *cache,
+ ePaintSymmetryFlags symm,
+ char axis,
+ float angle);
void SCULPT_cache_free(StrokeCache *cache);
/* -------------------------------------------------------------------- */
diff --git a/source/blender/editors/sculpt_paint/sculpt_ops.c b/source/blender/editors/sculpt_paint/sculpt_ops.c
index 8affb0e9d53..0e7873bc652 100644
--- a/source/blender/editors/sculpt_paint/sculpt_ops.c
+++ b/source/blender/editors/sculpt_paint/sculpt_ops.c
@@ -246,15 +246,17 @@ static void SCULPT_OT_symmetrize(wmOperatorType *ot)
ot->exec = sculpt_symmetrize_exec;
ot->poll = sculpt_no_multires_poll;
- RNA_def_float(ot->srna,
- "merge_tolerance",
- 0.001f,
- 0.0f,
- FLT_MAX,
- "Merge Distance",
- "Distance within which symmetrical vertices are merged",
- 0.0f,
- 1.0f);
+ PropertyRNA *prop = RNA_def_float(ot->srna,
+ "merge_tolerance",
+ 0.0005f,
+ 0.0f,
+ FLT_MAX,
+ "Merge Distance",
+ "Distance within which symmetrical vertices are merged",
+ 0.0f,
+ 1.0f);
+
+ RNA_def_property_ui_range(prop, 0.0, FLT_MAX, 0.001, 5);
}
/**** Toggle operator for turning sculpt mode on or off ****/
@@ -1202,7 +1204,7 @@ static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot)
RNA_def_boolean(ot->srna,
"use_automask_settings",
false,
- "Use Automask Settings",
+ "Automask Settings",
"Use default settings from Options panel in sculpt mode");
RNA_def_float(ot->srna,
@@ -1210,7 +1212,7 @@ static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot)
0.5f,
0.0f,
5.0f,
- "Cavity Factor",
+ "Factor",
"The contrast of the cavity mask",
0.0f,
1.0f);
@@ -1219,11 +1221,11 @@ static void SCULPT_OT_mask_from_cavity(wmOperatorType *ot)
2,
0,
25,
- "Cavity Blur",
+ "Blur",
"The number of times the cavity mask is blurred",
0,
25);
- RNA_def_boolean(ot->srna, "use_curve", false, "Use Curve", "");
+ RNA_def_boolean(ot->srna, "use_curve", false, "Custom Curve", "");
RNA_def_boolean(ot->srna, "invert", false, "Cavity (Inverted)", "");
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index eb92c865f18..833f62d4955 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -1823,9 +1823,7 @@ static void sculpt_undo_set_active_layer(struct bContext *C, SculptAttrRef *attr
if (!layer) {
layer = BKE_id_attribute_search(&me->id, attr->name, CD_MASK_PROP_ALL, ATTR_DOMAIN_MASK_ALL);
if (layer) {
- const eAttrDomain domain = BKE_id_attribute_domain(&me->id, layer);
- if (ED_geometry_attribute_convert(
- me, attr->name, layer->type, domain, attr->type, attr->domain)) {
+ if (ED_geometry_attribute_convert(me, attr->name, attr->type, attr->domain, NULL)) {
layer = BKE_id_attribute_find(&me->id, attr->name, attr->type, attr->domain);
}
}
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 5ae6573df7c..151f04e0a2d 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -854,6 +854,11 @@ static void create_inspection_string_for_generic_value(const GPointer value, std
else if (type.is<blender::float3>()) {
ss << *(blender::float3 *)buffer << TIP_(" (Vector)");
}
+ else if (type.is<blender::ColorGeometry4f>()) {
+ const blender::ColorGeometry4f &color = *(blender::ColorGeometry4f *)buffer;
+ ss << "(" << color.r << ", " << color.g << ", " << color.b << ", " << color.a << ")"
+ << TIP_(" (Color)");
+ }
else if (type.is<bool>()) {
ss << ((*(bool *)buffer) ? TIP_("True") : TIP_("False")) << TIP_(" (Boolean)");
}
diff --git a/source/blender/editors/space_node/space_node.cc b/source/blender/editors/space_node/space_node.cc
index ce0273eec81..c993fa57d76 100644
--- a/source/blender/editors/space_node/space_node.cc
+++ b/source/blender/editors/space_node/space_node.cc
@@ -5,6 +5,7 @@
* \ingroup spnode
*/
+#include "DNA_ID.h"
#include "DNA_gpencil_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
@@ -28,6 +29,8 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "DEG_depsgraph.h"
+
#include "BLO_read_write.h"
#include "RNA_access.h"
@@ -191,6 +194,13 @@ void ED_node_set_active_viewer_key(SpaceNode *snode)
{
bNodeTreePath *path = (bNodeTreePath *)snode->treepath.last;
if (snode->nodetree && path) {
+ /* A change in active viewer may result in the change of the output node used by the
+ * compositor, so we need to get notified about such changes. */
+ if (snode->nodetree->active_viewer_key.value != path->parent_key.value) {
+ DEG_id_tag_update(&snode->nodetree->id, ID_RECALC_NTREE_OUTPUT);
+ WM_main_add_notifier(NC_NODE, nullptr);
+ }
+
snode->nodetree->active_viewer_key = path->parent_key;
}
}
diff --git a/source/blender/editors/space_view3d/view3d_draw.cc b/source/blender/editors/space_view3d/view3d_draw.cc
index 5d4ed032bb4..6400a015ef1 100644
--- a/source/blender/editors/space_view3d/view3d_draw.cc
+++ b/source/blender/editors/space_view3d/view3d_draw.cc
@@ -1717,6 +1717,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
do_color_management,
ofs,
viewport);
+ DRW_cache_free_old_subdiv();
GPU_matrix_pop_projection();
GPU_matrix_pop();
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
index 22ab6636c47..35ae745bab3 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_navigate.c
@@ -106,7 +106,6 @@ struct NavigateWidgetGroup {
char viewlock;
} rv3d;
} state;
- int region_size[2];
};
static bool WIDGETGROUP_navigate_poll(const bContext *C, wmGizmoGroupType *UNUSED(gzgt))
@@ -124,9 +123,6 @@ static void WIDGETGROUP_navigate_setup(const bContext *C, wmGizmoGroup *gzgroup)
{
struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
- navgroup->region_size[0] = -1;
- navgroup->region_size[1] = -1;
-
wmOperatorType *ot_view_axis = WM_operatortype_find("VIEW3D_OT_view_axis", true);
wmOperatorType *ot_view_camera = WM_operatortype_find("VIEW3D_OT_view_camera", true);
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index a5b2442f11c..d71a3897cbc 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1109,7 +1109,7 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
PE_start_edit(PE_get_current(t->depsgraph, t->scene, ob))) {
return &TransConvertType_Particle;
}
- if (ob && (ob->mode & OB_MODE_ALL_PAINT)) {
+ if (ob && ((ob->mode & OB_MODE_ALL_PAINT) || (ob->mode & OB_MODE_SCULPT_CURVES))) {
if ((t->options & CTX_PAINT_CURVE) && !ELEM(t->mode, TFM_SHEAR, TFM_SHRINKFATTEN)) {
return &TransConvertType_PaintCurve;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index e1f93bf881b..e7ef408b848 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -309,7 +309,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->flag |= T_V3D_ALIGN;
}
- if (object_mode & OB_MODE_ALL_PAINT) {
+ if ((object_mode & OB_MODE_ALL_PAINT) || (object_mode & OB_MODE_SCULPT_CURVES)) {
Paint *p = BKE_paint_get_active_from_context(C);
if (p && p->brush && (p->brush->flag & BRUSH_CURVE)) {
t->options |= CTX_PAINT_CURVE;
diff --git a/source/blender/geometry/intern/trim_curves.cc b/source/blender/geometry/intern/trim_curves.cc
index 82e9ee78592..c68b5eaf5de 100644
--- a/source/blender/geometry/intern/trim_curves.cc
+++ b/source/blender/geometry/intern/trim_curves.cc
@@ -718,7 +718,7 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
for (const int64_t curve_i : selection.slice(range)) {
/* Interpolate onto the evaluated point domain and sample the evaluated domain. */
const IndexRange src_evaluated_points = src_curves.evaluated_points_for_curve(curve_i);
- GArray evaluated_data(CPPType::get<T>(), src_evaluated_points.size());
+ GArray<> evaluated_data(CPPType::get<T>(), src_evaluated_points.size());
GMutableSpan evaluated_span = evaluated_data.as_mutable_span();
src_curves.interpolate_to_evaluated(
curve_i, attribute.src.slice(src_curves.points_for_curve(curve_i)), evaluated_span);
@@ -785,8 +785,8 @@ static void compute_curve_trim_parameters(const bke::CurvesGeometry &curves,
/* Single point. */
dst_curve_size[curve_i] = 1;
src_ranges[curve_i] = bke::curves::IndexRangeCyclic(0, 0, 1, 1);
- start_points[curve_i] = {0, 0, 0.0f};
- end_points[curve_i] = {0, 0, 0.0f};
+ start_points[curve_i] = {{0, 0}, 0.0f};
+ end_points[curve_i] = {{0, 0}, 0.0f};
continue;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
index 455d8b0b528..dff8d14564a 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloutline.c
@@ -287,7 +287,7 @@ static void updateDepsgraph(GpencilModifierData *md,
DEG_add_object_relation(ctx->node, ctx->object, DEG_OB_COMP_TRANSFORM, "Outline Modifier");
}
-static void panel_draw(const bContext *UNUSED(C), Panel *panel)
+static void panel_draw(const bContext *C, Panel *panel)
{
uiLayout *layout = panel->layout;
@@ -302,6 +302,11 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel)
uiItemR(layout, ptr, "outline_material", 0, NULL, ICON_NONE);
uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE);
+ Scene *scene = CTX_data_scene(C);
+ if (scene->camera == NULL) {
+ uiItemL(layout, IFACE_("Outline requires an active camera"), ICON_ERROR);
+ }
+
gpencil_modifier_panel_end(layout, ptr);
}
diff --git a/source/blender/gpu/intern/gpu_node_graph.h b/source/blender/gpu/intern/gpu_node_graph.h
index de0a0687b13..2f617713749 100644
--- a/source/blender/gpu/intern/gpu_node_graph.h
+++ b/source/blender/gpu/intern/gpu_node_graph.h
@@ -66,7 +66,7 @@ typedef enum {
GPU_NODE_TAG_COMPOSITOR = (1 << 6),
} eGPUNodeTag;
-ENUM_OPERATORS(eGPUNodeTag, GPU_NODE_TAG_FUNCTION)
+ENUM_OPERATORS(eGPUNodeTag, GPU_NODE_TAG_COMPOSITOR)
struct GPUNode {
struct GPUNode *next, *prev;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8d02b274c65..274b2094ee7 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -2302,6 +2302,7 @@ typedef enum ePaintSymmetryFlags {
PAINT_TILE_Y = (1 << 5),
PAINT_TILE_Z = (1 << 6),
} ePaintSymmetryFlags;
+ENUM_OPERATORS(ePaintSymmetryFlags, PAINT_TILE_Z);
#define PAINT_SYMM_AXIS_ALL (PAINT_SYMM_X | PAINT_SYMM_Y | PAINT_SYMM_Z)
diff --git a/source/blender/makesrna/intern/rna_attribute.c b/source/blender/makesrna/intern/rna_attribute.c
index e1b6fb429a7..20c6e24b735 100644
--- a/source/blender/makesrna/intern/rna_attribute.c
+++ b/source/blender/makesrna/intern/rna_attribute.c
@@ -534,7 +534,7 @@ static void rna_AttributeGroup_active_set(PointerRNA *ptr,
{
ID *id = ptr->owner_id;
CustomDataLayer *layer = attribute_ptr.data;
- BKE_id_attributes_active_set(id, layer);
+ BKE_id_attributes_active_set(id, layer->name);
}
static void rna_AttributeGroup_active_index_set(PointerRNA *ptr, int value)
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index cfec020c739..c6115711c1a 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -1302,8 +1302,8 @@ static bNodeLink *rna_NodeTree_link_new(bNodeTree *ntree,
return NULL;
}
- nodeFindNode(ntree, fromsock, &fromnode, NULL);
- nodeFindNode(ntree, tosock, &tonode, NULL);
+ nodeFindNodeTry(ntree, fromsock, &fromnode, NULL);
+ nodeFindNodeTry(ntree, tosock, &tonode, NULL);
/* check validity of the sockets:
* if sockets from different trees are passed in this will fail!
*/
@@ -2417,6 +2417,11 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value)
BKE_animdata_fix_paths_rename_all(NULL, "nodes", oldname, node->name);
}
+static bool allow_changing_sockets(bNode *node)
+{
+ return ELEM(node->type, NODE_CUSTOM, SH_NODE_SCRIPT);
+}
+
static bNodeSocket *rna_Node_inputs_new(ID *id,
bNode *node,
Main *bmain,
@@ -2425,7 +2430,7 @@ static bNodeSocket *rna_Node_inputs_new(ID *id,
const char *name,
const char *identifier)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Cannot add socket to built-in node");
return NULL;
}
@@ -2452,7 +2457,7 @@ static bNodeSocket *rna_Node_outputs_new(ID *id,
const char *name,
const char *identifier)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Cannot add socket to built-in node");
return NULL;
}
@@ -2474,7 +2479,7 @@ static bNodeSocket *rna_Node_outputs_new(ID *id,
static void rna_Node_socket_remove(
ID *id, bNode *node, Main *bmain, ReportList *reports, bNodeSocket *sock)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Unable to remove socket from built-in node");
return;
}
@@ -2494,7 +2499,7 @@ static void rna_Node_socket_remove(
static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain, ReportList *reports)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Unable to remove sockets from built-in node");
return;
}
@@ -2513,7 +2518,7 @@ static void rna_Node_inputs_clear(ID *id, bNode *node, Main *bmain, ReportList *
static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain, ReportList *reports)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Unable to remove socket from built-in node");
return;
}
@@ -2533,7 +2538,7 @@ static void rna_Node_outputs_clear(ID *id, bNode *node, Main *bmain, ReportList
static void rna_Node_inputs_move(
ID *id, bNode *node, Main *bmain, ReportList *reports, int from_index, int to_index)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Unable to move sockets in built-in node");
return;
}
@@ -2571,7 +2576,7 @@ static void rna_Node_inputs_move(
static void rna_Node_outputs_move(
ID *id, bNode *node, Main *bmain, ReportList *reports, int from_index, int to_index)
{
- if (node->type != NODE_CUSTOM) {
+ if (!allow_changing_sockets(node)) {
BKE_report(reports, RPT_ERROR, "Unable to move sockets in built-in node");
return;
}
@@ -2784,9 +2789,7 @@ static char *rna_NodeSocket_path(const PointerRNA *ptr)
int socketindex;
char name_esc[sizeof(node->name) * 2];
- if (!nodeFindNode(ntree, sock, &node, &socketindex)) {
- return NULL;
- }
+ nodeFindNode(ntree, sock, &node, &socketindex);
BLI_str_escape(name_esc, node->name, sizeof(name_esc));
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.cc b/source/blender/modifiers/intern/MOD_normal_edit.cc
index 7d422826cf8..29404fb044a 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.cc
+++ b/source/blender/modifiers/intern/MOD_normal_edit.cc
@@ -563,8 +563,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
true,
result->smoothresh,
nullptr,
- clnors,
- nullptr);
+ nullptr,
+ clnors);
}
if (clnors == nullptr) {
diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.cc b/source/blender/modifiers/intern/MOD_weighted_normal.cc
index 1ebd5423d39..9d2460be2be 100644
--- a/source/blender/modifiers/intern/MOD_weighted_normal.cc
+++ b/source/blender/modifiers/intern/MOD_weighted_normal.cc
@@ -23,6 +23,7 @@
#include "BKE_deform.h"
#include "BKE_lib_id.h"
#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
#include "BKE_screen.h"
#include "UI_interface.h"
@@ -76,6 +77,7 @@ struct WeightedNormalData {
MEdge *medge;
const MLoop *mloop;
+ blender::Span<int> loop_to_poly;
short (*clnors)[2];
bool has_clnors; /* True if clnors already existed, false if we had to create them. */
float split_angle;
@@ -97,8 +99,6 @@ struct WeightedNormalData {
WeightedNormalDataAggregateItem *items_data;
ModePair *mode_pair;
-
- int *loop_to_poly;
};
/**
@@ -181,6 +181,7 @@ static void aggregate_item_normal(WeightedNormalModifierData *wnmd,
static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
WeightedNormalData *wn_data)
{
+ using namespace blender;
const int verts_num = wn_data->verts_num;
const int edges_num = wn_data->edges_num;
const int loops_num = wn_data->loops_num;
@@ -191,7 +192,7 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
const MLoop *mloop = wn_data->mloop;
short(*clnors)[2] = wn_data->clnors;
- int *loop_to_poly = wn_data->loop_to_poly;
+ const Span<int> loop_to_poly = wn_data->loop_to_poly;
const MPoly *mpoly = wn_data->mpoly;
const float(*polynors)[3] = wn_data->polynors;
@@ -235,9 +236,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
polys_num,
true,
split_angle,
+ loop_to_poly.data(),
&lnors_spacearr,
- has_clnors ? clnors : nullptr,
- loop_to_poly);
+ has_clnors ? clnors : nullptr);
items_num = lnors_spacearr.spaces_num;
items_data = static_cast<WeightedNormalDataAggregateItem *>(
@@ -315,8 +316,6 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
break;
case MOD_WEIGHTEDNORMAL_MODE_ANGLE:
case MOD_WEIGHTEDNORMAL_MODE_FACE_ANGLE:
- BLI_assert(loop_to_poly != nullptr);
-
for (int i = 0; i < loops_num; i++) {
const int ml_index = mode_pair[i].index;
const float ml_val = mode_pair[i].val;
@@ -419,9 +418,9 @@ static void apply_weights_vertex_normal(WeightedNormalModifierData *wnmd,
polys_num,
true,
split_angle,
+ loop_to_poly.data(),
nullptr,
- has_clnors ? clnors : nullptr,
- loop_to_poly);
+ has_clnors ? clnors : nullptr);
for (int ml_index = 0; ml_index < loops_num; ml_index++) {
const int item_index = mloop[ml_index].v;
@@ -489,9 +488,6 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData
const MPoly *mp;
int mp_index;
- int *loop_to_poly = static_cast<int *>(
- MEM_malloc_arrayN(size_t(loops_num), sizeof(*loop_to_poly), __func__));
-
ModePair *corner_angle = static_cast<ModePair *>(
MEM_malloc_arrayN(size_t(loops_num), sizeof(*corner_angle), __func__));
@@ -508,15 +504,12 @@ static void wn_corner_angle(WeightedNormalModifierData *wnmd, WeightedNormalData
ml_index++, c_angl++, angl++) {
c_angl->val = float(M_PI) - *angl;
c_angl->index = ml_index;
-
- loop_to_poly[ml_index] = mp_index;
}
MEM_freeN(index_angle);
}
qsort(corner_angle, loops_num, sizeof(*corner_angle), modepair_cmp_by_val_inverse);
- wn_data->loop_to_poly = loop_to_poly;
wn_data->mode_pair = corner_angle;
apply_weights_vertex_normal(wnmd, wn_data);
}
@@ -533,9 +526,6 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD
const MPoly *mp;
int mp_index;
- int *loop_to_poly = static_cast<int *>(
- MEM_malloc_arrayN(size_t(loops_num), sizeof(*loop_to_poly), __func__));
-
ModePair *combined = static_cast<ModePair *>(
MEM_malloc_arrayN(size_t(loops_num), sizeof(*combined), __func__));
@@ -554,21 +544,19 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD
/* In this case val is product of corner angle and face area. */
cmbnd->val = (float(M_PI) - *angl) * face_area;
cmbnd->index = ml_index;
-
- loop_to_poly[ml_index] = mp_index;
}
MEM_freeN(index_angle);
}
qsort(combined, loops_num, sizeof(*combined), modepair_cmp_by_val_inverse);
- wn_data->loop_to_poly = loop_to_poly;
wn_data->mode_pair = combined;
apply_weights_vertex_normal(wnmd, wn_data);
}
static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
+ using namespace blender;
WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md;
Object *ob = ctx->object;
@@ -633,6 +621,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
int defgrp_index;
MOD_get_vgroup(ctx->object, mesh, wnmd->defgrp_name, &dvert, &defgrp_index);
+ const Array<int> loop_to_poly_map = bke::mesh_topology::build_loop_to_poly_map(result->polys(),
+ result->totloop);
+
WeightedNormalData wn_data{};
wn_data.verts_num = verts_num;
wn_data.edges_num = edges_num;
@@ -644,6 +635,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
wn_data.medge = medge;
wn_data.mloop = mloop;
+ wn_data.loop_to_poly = loop_to_poly_map;
wn_data.clnors = clnors;
wn_data.has_clnors = has_clnors;
wn_data.split_angle = split_angle;
@@ -672,7 +664,6 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
break;
}
- MEM_SAFE_FREE(wn_data.loop_to_poly);
MEM_SAFE_FREE(wn_data.mode_pair);
MEM_SAFE_FREE(wn_data.items_data);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index bc319ce905a..bee30c1fd99 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -50,10 +50,8 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet profile_set = params.extract_input<GeometrySet>("Profile Curve");
const bool fill_caps = params.extract_input<bool>("Fill Caps");
- bool has_curves = false;
curve_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (geometry_set.has_curves()) {
- has_curves = true;
geometry_set_curve_to_mesh(geometry_set, profile_set, fill_caps);
}
geometry_set.keep_only_during_modify({GEO_COMPONENT_TYPE_MESH});
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
index 6b54828b042..d658b14092a 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_island.cc
@@ -35,7 +35,7 @@ class IslandFieldInput final : public bke::MeshFieldInput {
{
const Span<MEdge> edges = mesh.edges();
- DisjointSet islands(mesh.totvert);
+ DisjointSet<int> islands(mesh.totvert);
for (const int i : edges.index_range()) {
islands.join(edges[i].v1, edges[i].v2);
}
@@ -43,7 +43,7 @@ class IslandFieldInput final : public bke::MeshFieldInput {
Array<int> output(mesh.totvert);
VectorSet<int> ordered_roots;
for (const int i : IndexRange(mesh.totvert)) {
- const int64_t root = islands.find_root(i);
+ const int root = islands.find_root(i);
output[i] = ordered_roots.index_of_or_add(root);
}
@@ -81,14 +81,14 @@ class IslandCountFieldInput final : public bke::MeshFieldInput {
{
const Span<MEdge> edges = mesh.edges();
- DisjointSet islands(mesh.totvert);
+ DisjointSet<int> islands(mesh.totvert);
for (const int i : edges.index_range()) {
islands.join(edges[i].v1, edges[i].v2);
}
Set<int> island_list;
for (const int i_vert : IndexRange(mesh.totvert)) {
- const int64_t root = islands.find_root(i_vert);
+ const int root = islands.find_root(i_vert);
island_list.add(root);
}
diff --git a/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc b/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc
index d4e18321665..13636b67c9b 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_interpolate_domain.cc
@@ -104,7 +104,7 @@ class InterpolateDomain final : public bke::GeometryFieldInput {
const bke::GeometryFieldContext other_domain_context{
context.geometry(), context.type(), src_domain_};
const int64_t src_domain_size = attributes.domain_size(src_domain_);
- GArray values(src_field_.cpp_type(), src_domain_size);
+ GArray<> values(src_field_.cpp_type(), src_domain_size);
FieldEvaluator value_evaluator{other_domain_context, src_domain_size};
value_evaluator.add_with_destination(src_field_, values.as_mutable_span());
value_evaluator.evaluate();
diff --git a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc
index 5f1baa23511..3cfdafa76c0 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc
@@ -248,7 +248,7 @@ static Vector<ElementIsland> prepare_face_islands(const Mesh &mesh, const IndexM
const Span<MLoop> loops = mesh.loops();
/* Use the disjoint set data structure to determine which vertices have to be scaled together. */
- DisjointSet disjoint_set(mesh.totvert);
+ DisjointSet<int> disjoint_set(mesh.totvert);
for (const int poly_index : face_selection) {
const MPoly &poly = polys[poly_index];
const Span<MLoop> poly_loops = loops.slice(poly.loopstart, poly.totloop);
@@ -344,7 +344,7 @@ static Vector<ElementIsland> prepare_edge_islands(const Mesh &mesh, const IndexM
const Span<MEdge> edges = mesh.edges();
/* Use the disjoint set data structure to determine which vertices have to be scaled together. */
- DisjointSet disjoint_set(mesh.totvert);
+ DisjointSet<int> disjoint_set(mesh.totvert);
for (const int edge_index : edge_selection) {
const MEdge &edge = edges[edge_index];
disjoint_set.join(edge.v1, edge.v2);
diff --git a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
index 197f0997160..96c369f2f6b 100644
--- a/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
+++ b/source/blender/nodes/intern/geometry_nodes_lazy_function.cc
@@ -527,7 +527,8 @@ class LazyFunctionForViewerNode : public LazyFunction {
debug_name_ = "Viewer";
Vector<const bNodeSocket *> dummy_used_outputs;
lazy_function_interface_from_node(bnode, r_used_inputs, dummy_used_outputs, inputs_, outputs_);
- if (!r_used_inputs[1]->is_directly_linked()) {
+ const Span<const bNodeLink *> links = r_used_inputs[1]->directly_linked_links();
+ if (links.is_empty() || nodeIsDanglingReroute(&bnode.owner_tree(), links.first()->fromnode)) {
use_field_input_ = false;
r_used_inputs.pop_last();
inputs_.pop_last();
diff --git a/tests/python/CMakeLists.txt b/tests/python/CMakeLists.txt
index 0d74cfafda5..14b00ace251 100644
--- a/tests/python/CMakeLists.txt
+++ b/tests/python/CMakeLists.txt
@@ -632,7 +632,7 @@ endif()
# SVG Import
if(True)
- set(_svg_render_tests path)
+ set(_svg_render_tests complex path)
foreach(render_test ${_svg_render_tests})
add_python_test(
diff --git a/tests/python/bl_io_curve_svg_test.py b/tests/python/bl_io_curve_svg_test.py
index 092dfa5497a..f36036a5b52 100644
--- a/tests/python/bl_io_curve_svg_test.py
+++ b/tests/python/bl_io_curve_svg_test.py
@@ -50,7 +50,10 @@ def main():
from modules import render_report
report = render_report.Report('IO Curve SVG', output_dir, idiff)
report.set_pixelated(True)
- print(test_dir)
+
+ test_dir_name = Path(test_dir).name
+ if test_dir_name == 'complex':
+ report.set_fail_percent(0.01)
ok = report.run(test_dir, blender, get_arguments, batch=True)
diff --git a/tests/python/modules/render_report.py b/tests/python/modules/render_report.py
index 15d46d6d127..5dcb73b65cc 100755
--- a/tests/python/modules/render_report.py
+++ b/tests/python/modules/render_report.py
@@ -166,6 +166,9 @@ class Report:
def set_fail_threshold(self, threshold):
self.fail_threshold = threshold
+ def set_fail_percent(self, percent):
+ self.fail_percent = percent
+
def set_reference_dir(self, reference_dir):
self.reference_dir = reference_dir