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:
authorFabian Schempp <fabianschempp@googlemail.com>2022-04-11 08:14:28 +0300
committerFabian Schempp <fabianschempp@googlemail.com>2022-04-11 08:14:28 +0300
commitf06d361da1249c93568153bae88bcdf43b4774a1 (patch)
tree5acd7443d2c13d3f89b40e81f7d93df5e2a56008
parentab6939ff78f131e5270e17b9ee73075b512a1a3f (diff)
parent5e47056e8d97e414c9dabacea71fac2bdc7d2818 (diff)
Merge branch 'master' into soc-2021-porting-modifiers-to-nodes-remesh-voxel
# Conflicts: # intern/cycles/app/opengl/display_driver.cpp # intern/cycles/app/opengl/display_driver.h # intern/cycles/app/opengl/shader.cpp # intern/cycles/app/opengl/shader.h # intern/cycles/app/opengl/window.cpp # intern/cycles/app/opengl/window.h # intern/cycles/blender/addon/ui.py # intern/cycles/util/view.cpp # intern/cycles/util/view.h # release/scripts/startup/bl_ui/properties_data_armature.py # release/scripts/startup/bl_ui/properties_view_layer.py # source/blender/blenkernel/BKE_armature.h # source/blender/blenkernel/BKE_blender_version.h # source/blender/blenkernel/BKE_curves.hh # source/blender/blenkernel/BKE_gpencil_update_cache.h # source/blender/blenkernel/BKE_node.h # source/blender/blenkernel/CMakeLists.txt # source/blender/blenkernel/intern/curve_eval.cc # source/blender/blenkernel/intern/curves_geometry.cc # source/blender/blenkernel/intern/geometry_component_curves.cc # source/blender/blenkernel/intern/lib_override.c # source/blender/blenkernel/intern/lib_override_proxy_conversion.c # source/blender/blenkernel/intern/scene.cc # source/blender/blenkernel/intern/type_conversions.cc # source/blender/blenloader/intern/versioning_300.c # source/blender/draw/engines/eevee/eevee_data.c # source/blender/draw/engines/image/image_drawing_mode.hh # source/blender/draw/engines/image/image_space.hh # source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh # source/blender/draw/intern/draw_cache_impl_subdivision.cc # source/blender/editors/gpencil/gpencil_fill.c # source/blender/editors/include/ED_paint.h # source/blender/editors/object/object_bake.c # source/blender/editors/render/render_intern.hh # source/blender/editors/render/render_ops.cc # source/blender/editors/render/render_shading.cc # source/blender/editors/screen/area.c # source/blender/editors/sculpt_paint/paint_canvas.cc # source/blender/editors/sculpt_paint/sculpt_intern.h # source/blender/editors/sculpt_paint/sculpt_paint_color.c # source/blender/editors/space_node/node_intern.hh # source/blender/editors/space_outliner/outliner_tools.cc # source/blender/editors/transform/transform_convert_sequencer.c # source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c # source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc # source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc # source/blender/makesdna/DNA_ID.h # source/blender/makesdna/DNA_curves_types.h # source/blender/makesrna/intern/rna_internal.h # source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc # source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
-rw-r--r--intern/cycles/app/opengl/display_driver.cpp17
-rw-r--r--intern/cycles/app/opengl/display_driver.h17
-rw-r--r--intern/cycles/app/opengl/shader.cpp17
-rw-r--r--intern/cycles/app/opengl/shader.h17
-rw-r--r--intern/cycles/app/opengl/window.cpp17
-rw-r--r--intern/cycles/app/opengl/window.h17
-rw-r--r--intern/cycles/blender/addon/engine.py6
-rw-r--r--intern/cycles/blender/addon/ui.py19
-rw-r--r--intern/cycles/kernel/svm/aov.h2
-rw-r--r--intern/cycles/scene/pass.cpp2
-rw-r--r--intern/cycles/util/view.cpp269
-rw-r--r--intern/cycles/util/view.h35
m---------release/datafiles/locale0
m---------release/scripts/addons0
m---------release/scripts/addons_contrib0
-rw-r--r--release/scripts/modules/rna_manual_reference.py62
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py19
-rw-r--r--release/scripts/startup/bl_ui/space_image.py72
-rw-r--r--source/blender/blenkernel/BKE_armature.h2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/BKE_callbacks.h2
-rw-r--r--source/blender/blenkernel/BKE_cryptomatte.hh2
-rw-r--r--source/blender/blenkernel/BKE_curves.hh54
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h16
-rw-r--r--source/blender/blenkernel/BKE_gpencil_update_cache.h19
-rw-r--r--source/blender/blenkernel/BKE_node.h4
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/constraint.c4
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc8
-rw-r--r--source/blender/blenkernel/intern/curve_poly.cc154
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc141
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc133
-rw-r--r--source/blender/blenkernel/intern/lib_override.c1
-rw-r--r--source/blender/blenkernel/intern/lib_override_proxy_conversion.c27
-rw-r--r--source/blender/blenkernel/intern/mask_rasterize.c52
-rw-r--r--source/blender/blenkernel/intern/scene.cc1
-rw-r--r--source/blender/blenkernel/intern/type_conversions.cc2
-rw-r--r--source/blender/blenlib/BLI_delaunay_2d.h4
-rw-r--r--source/blender/blenlib/BLI_fileops.h2
-rw-r--r--source/blender/blenlib/BLI_mesh_intersect.hh4
-rw-r--r--source/blender/blenlib/BLI_string.h2
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.cc2
-rw-r--r--source/blender/blenlib/intern/math_boolean.cc30
-rw-r--r--source/blender/blenloader/intern/versioning_300.c53
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc2
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c126
-rw-r--r--source/blender/draw/engines/image/image_drawing_mode.hh3
-rw-r--r--source/blender/draw/engines/image/image_space.hh6
-rw-r--r--source/blender/draw/engines/overlay/overlay_grid.c25
-rw-r--r--source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_subdivision.cc258
-rw-r--r--source/blender/editors/armature/pose_slide.c6
-rw-r--r--source/blender/editors/asset/intern/asset_list.cc2
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_sculpt_paint.c2
-rw-r--r--source/blender/editors/include/ED_paint.h1
-rw-r--r--source/blender/editors/include/ED_uvedit.h2
-rw-r--r--source/blender/editors/interface/interface_intern.h2
-rw-r--r--source/blender/editors/object/object_bake.c14
-rw-r--r--source/blender/editors/object/object_bake_api.c5
-rw-r--r--source/blender/editors/render/render_intern.hh2
-rw-r--r--source/blender/editors/render/render_ops.cc2
-rw-r--r--source/blender/editors/render/render_shading.cc108
-rw-r--r--source/blender/editors/screen/area.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_canvas.cc2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h12
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_paint_color.c2
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_node/node_intern.hh2
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.cc184
-rw-r--r--source/blender/editors/transform/transform_convert_sequencer.c176
-rw-r--r--source/blender/freestyle/intern/view_map/Interface1D.h55
-rw-r--r--source/blender/functions/FN_multi_function_builder.hh2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c6
-rw-r--r--source/blender/io/usd/intern/usd_reader_material.h2
-rw-r--r--source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc18
-rw-r--r--source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc2
-rw-r--r--source/blender/makesdna/DNA_ID.h6
-rw-r--r--source/blender/makesdna/DNA_curves_types.h6
-rw-r--r--source/blender/makesdna/DNA_space_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_camera.c4
-rw-r--r--source/blender/makesrna/intern/rna_internal.h6
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h12
-rw-r--r--source/blender/makesrna/intern/rna_space.c7
-rw-r--r--source/blender/nodes/NOD_math_functions.hh8
-rw-r--r--source/blender/nodes/NOD_socket_search_link.hh4
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc3
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc2
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc99
-rw-r--r--source/blender/python/BPY_extern_run.h2
-rw-r--r--source/blender/python/intern/bpy.c2
-rw-r--r--source/blender/sequencer/intern/image_cache.c9
m---------source/tools0
95 files changed, 1574 insertions, 966 deletions
diff --git a/intern/cycles/app/opengl/display_driver.cpp b/intern/cycles/app/opengl/display_driver.cpp
index b86a2b80713..8b99f3b6feb 100644
--- a/intern/cycles/app/opengl/display_driver.cpp
+++ b/intern/cycles/app/opengl/display_driver.cpp
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
#include "app/opengl/display_driver.h"
#include "app/opengl/shader.h"
diff --git a/intern/cycles/app/opengl/display_driver.h b/intern/cycles/app/opengl/display_driver.h
index 7645d7905b4..92578412d68 100644
--- a/intern/cycles/app/opengl/display_driver.h
+++ b/intern/cycles/app/opengl/display_driver.h
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
#pragma once
diff --git a/intern/cycles/app/opengl/shader.cpp b/intern/cycles/app/opengl/shader.cpp
index 48ccafa0d95..9db9ea7fce9 100644
--- a/intern/cycles/app/opengl/shader.cpp
+++ b/intern/cycles/app/opengl/shader.cpp
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
#include "app/opengl/shader.h"
diff --git a/intern/cycles/app/opengl/shader.h b/intern/cycles/app/opengl/shader.h
index 682463891d5..6ca121ca6ff 100644
--- a/intern/cycles/app/opengl/shader.h
+++ b/intern/cycles/app/opengl/shader.h
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 OpenGL Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 OpenGL Foundation */
#pragma once
diff --git a/intern/cycles/app/opengl/window.cpp b/intern/cycles/app/opengl/window.cpp
index 4da0ebdece5..7351ae3eecd 100644
--- a/intern/cycles/app/opengl/window.cpp
+++ b/intern/cycles/app/opengl/window.cpp
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
#include <stdio.h>
#include <stdlib.h>
diff --git a/intern/cycles/app/opengl/window.h b/intern/cycles/app/opengl/window.h
index 4f9e418e5c2..531b5cab3fc 100644
--- a/intern/cycles/app/opengl/window.h
+++ b/intern/cycles/app/opengl/window.h
@@ -1,18 +1,5 @@
-/*
- * Copyright 2011-2022 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
#pragma once
diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index b7713dc7110..61f47c0765b 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -226,7 +226,11 @@ def list_render_passes(scene, srl):
if aov.type == 'VALUE':
yield (aov.name, "X", 'VALUE')
else:
- yield (aov.name, "RGB", 'COLOR')
+ yield (aov.name, "RGBA", 'COLOR')
+
+ # Light groups.
+ for lightgroup in srl.lightgroups:
+ yield ("Combined_%s" % lightgroup.name, "RGB", 'COLOR')
# Light groups.
for lightgroup in srl.lightgroups:
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 2c6788b867b..739a555f037 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1916,13 +1916,20 @@ class CYCLES_RENDER_PT_bake_output_margin(CyclesButtonsPanel, Panel):
cbk = scene.render.bake
rd = scene.render
- if rd.use_bake_multires:
- layout.prop(rd, "bake_margin_type", text="Type")
- layout.prop(rd, "bake_margin", text="Size")
+ if (cscene.bake_type == 'NORMAL' and cbk.normal_space == 'TANGENT') or cscene.bake_type == 'UV':
+ if rd.use_bake_multires:
+ layout.prop(rd, "bake_margin", text="Size")
+ else:
+ if cbk.target == 'IMAGE_TEXTURES':
+ layout.prop(cbk, "margin", text="Size")
else:
- if cbk.target == 'IMAGE_TEXTURES':
- layout.prop(cbk, "margin_type", text="Type")
- layout.prop(cbk, "margin", text="Size")
+ if rd.use_bake_multires:
+ layout.prop(rd, "bake_margin_type", text="Type")
+ layout.prop(rd, "bake_margin", text="Size")
+ else:
+ if cbk.target == 'IMAGE_TEXTURES':
+ layout.prop(cbk, "margin_type", text="Type")
+ layout.prop(cbk, "margin", text="Size")
diff --git a/intern/cycles/kernel/svm/aov.h b/intern/cycles/kernel/svm/aov.h
index 334fb79cb75..9b818f0e6f8 100644
--- a/intern/cycles/kernel/svm/aov.h
+++ b/intern/cycles/kernel/svm/aov.h
@@ -32,7 +32,7 @@ ccl_device void svm_node_aov_color(KernelGlobals kg,
kernel_data.film.pass_stride;
ccl_global float *buffer = render_buffer + render_buffer_offset +
(kernel_data.film.pass_aov_color + node.z);
- kernel_write_pass_float3(buffer, make_float3(val.x, val.y, val.z));
+ kernel_write_pass_float4(buffer, make_float4(val.x, val.y, val.z, 1.0f));
}
}
diff --git a/intern/cycles/scene/pass.cpp b/intern/cycles/scene/pass.cpp
index 5f5b19e710d..c2f12355ac7 100644
--- a/intern/cycles/scene/pass.cpp
+++ b/intern/cycles/scene/pass.cpp
@@ -321,7 +321,7 @@ PassInfo Pass::get_info(const PassType type, const bool include_albedo, const bo
break;
case PASS_AOV_COLOR:
- pass_info.num_components = 3;
+ pass_info.num_components = 4;
break;
case PASS_AOV_VALUE:
pass_info.num_components = 1;
diff --git a/intern/cycles/util/view.cpp b/intern/cycles/util/view.cpp
deleted file mode 100644
index 475f8dbcee8..00000000000
--- a/intern/cycles/util/view.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0
- * Copyright 2011-2022 Blender Foundation */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "util/opengl.h"
-#include "util/string.h"
-#include "util/time.h"
-#include "util/version.h"
-#include "util/view.h"
-
-#ifdef __APPLE__
-# include <GLUT/glut.h>
-#else
-# include <GL/glut.h>
-#endif
-
-CCL_NAMESPACE_BEGIN
-
-/* structs */
-
-struct View {
- ViewInitFunc initf;
- ViewExitFunc exitf;
- ViewResizeFunc resize;
- ViewDisplayFunc display;
- ViewKeyboardFunc keyboard;
- ViewMotionFunc motion;
-
- bool first_display;
- bool redraw;
-
- int mouseX, mouseY;
- int mouseBut0, mouseBut2;
-
- int width, height;
-} V;
-
-/* public */
-
-static void view_display_text(int x, int y, const char *text)
-{
- const char *c;
-
- glRasterPos3f(x, y, 0);
-
- for (c = text; *c != '\0'; c++)
- glutBitmapCharacter(GLUT_BITMAP_HELVETICA_10, *c);
-}
-
-void view_display_info(const char *info)
-{
- const int height = 20;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0.1f, 0.1f, 0.1f, 0.8f);
- glRectf(0.0f, V.height - height, V.width, V.height);
- glDisable(GL_BLEND);
-
- glColor3f(0.5f, 0.5f, 0.5f);
-
- view_display_text(10, 7 + V.height - height, info);
-
- glColor3f(1.0f, 1.0f, 1.0f);
-}
-
-void view_display_help()
-{
- const int w = (int)((float)V.width / 1.15f);
- const int h = (int)((float)V.height / 1.15f);
-
- const int x1 = (V.width - w) / 2;
- const int x2 = x1 + w;
-
- const int y1 = (V.height - h) / 2;
- const int y2 = y1 + h;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0.5f, 0.5f, 0.5f, 0.8f);
- glRectf(x1, y1, x2, y2);
- glDisable(GL_BLEND);
-
- glColor3f(0.8f, 0.8f, 0.8f);
-
- string info = string("Cycles Renderer ") + CYCLES_VERSION_STRING;
-
- view_display_text(x1 + 20, y2 - 20, info.c_str());
- view_display_text(x1 + 20, y2 - 40, "(C) 2011-2022 Blender Foundation");
- view_display_text(x1 + 20, y2 - 80, "Controls:");
- view_display_text(x1 + 20, y2 - 100, "h: Info/Help");
- view_display_text(x1 + 20, y2 - 120, "r: Reset");
- view_display_text(x1 + 20, y2 - 140, "p: Pause");
- view_display_text(x1 + 20, y2 - 160, "esc: Cancel");
- view_display_text(x1 + 20, y2 - 180, "q: Quit program");
-
- view_display_text(x1 + 20, y2 - 210, "i: Interactive mode");
- view_display_text(x1 + 20, y2 - 230, "Left mouse: Move camera");
- view_display_text(x1 + 20, y2 - 250, "Right mouse: Rotate camera");
- view_display_text(x1 + 20, y2 - 270, "W/A/S/D: Move camera");
- view_display_text(x1 + 20, y2 - 290, "0/1/2/3: Set max bounces");
-
- glColor3f(1.0f, 1.0f, 1.0f);
-}
-
-static void view_display()
-{
- if (V.first_display) {
- if (V.initf)
- V.initf();
- if (V.exitf)
- atexit(V.exitf);
-
- V.first_display = false;
- }
-
- glClearColor(0.05f, 0.05f, 0.05f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(0, V.width, 0, V.height, -1, 1);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glRasterPos3f(0, 0, 0);
-
- if (V.display)
- V.display();
-
- glutSwapBuffers();
-}
-
-static void view_reshape(int width, int height)
-{
- if (width <= 0 || height <= 0)
- return;
-
- V.width = width;
- V.height = height;
-
- glViewport(0, 0, width, height);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- if (V.resize)
- V.resize(width, height);
-}
-
-static void view_keyboard(unsigned char key, int x, int y)
-{
- if (V.keyboard)
- V.keyboard(key);
-
- if (key == 'm')
- printf("mouse %d %d\n", x, y);
- if (key == 'q') {
- if (V.exitf)
- V.exitf();
- exit(0);
- }
-}
-
-static void view_mouse(int button, int state, int x, int y)
-{
- if (button == 0) {
- if (state == GLUT_DOWN) {
- V.mouseX = x;
- V.mouseY = y;
- V.mouseBut0 = 1;
- }
- else if (state == GLUT_UP) {
- V.mouseBut0 = 0;
- }
- }
- else if (button == 2) {
- if (state == GLUT_DOWN) {
- V.mouseX = x;
- V.mouseY = y;
- V.mouseBut2 = 1;
- }
- else if (state == GLUT_UP) {
- V.mouseBut2 = 0;
- }
- }
-}
-
-static void view_motion(int x, int y)
-{
- const int but = V.mouseBut0 ? 0 : 2;
- const int distX = x - V.mouseX;
- const int distY = y - V.mouseY;
-
- if (V.motion)
- V.motion(distX, distY, but);
-
- V.mouseX = x;
- V.mouseY = y;
-}
-
-static void view_idle()
-{
- if (V.redraw) {
- V.redraw = false;
- glutPostRedisplay();
- }
-
- time_sleep(0.1);
-}
-
-void view_main_loop(const char *title,
- int width,
- int height,
- ViewInitFunc initf,
- ViewExitFunc exitf,
- ViewResizeFunc resize,
- ViewDisplayFunc display,
- ViewKeyboardFunc keyboard,
- ViewMotionFunc motion)
-{
- const char *name = "app";
- char *argv = (char *)name;
- int argc = 1;
-
- memset(&V, 0, sizeof(V));
- V.width = width;
- V.height = height;
- V.first_display = true;
- V.redraw = false;
- V.initf = initf;
- V.exitf = exitf;
- V.resize = resize;
- V.display = display;
- V.keyboard = keyboard;
- V.motion = motion;
-
- glutInit(&argc, &argv);
- glutInitWindowSize(width, height);
- glutInitWindowPosition(0, 0);
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
- glutCreateWindow(title);
-
- glewInit();
-
- view_reshape(width, height);
-
- glutDisplayFunc(view_display);
- glutIdleFunc(view_idle);
- glutReshapeFunc(view_reshape);
- glutKeyboardFunc(view_keyboard);
- glutMouseFunc(view_mouse);
- glutMotionFunc(view_motion);
-
- glutMainLoop();
-}
-
-void view_redraw()
-{
- V.redraw = true;
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/view.h b/intern/cycles/util/view.h
deleted file mode 100644
index 51c242c21f7..00000000000
--- a/intern/cycles/util/view.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: Apache-2.0
- * Copyright 2011-2022 Blender Foundation */
-
-#ifndef __UTIL_VIEW_H__
-#define __UTIL_VIEW_H__
-
-/* Functions to display a simple OpenGL window using GLUT, simplified to the
- * bare minimum we need to reduce boilerplate code in tests apps. */
-
-CCL_NAMESPACE_BEGIN
-
-typedef void (*ViewInitFunc)();
-typedef void (*ViewExitFunc)();
-typedef void (*ViewResizeFunc)(int width, int height);
-typedef void (*ViewDisplayFunc)();
-typedef void (*ViewKeyboardFunc)(unsigned char key);
-typedef void (*ViewMotionFunc)(int x, int y, int button);
-
-void view_main_loop(const char *title,
- int width,
- int height,
- ViewInitFunc initf,
- ViewExitFunc exitf,
- ViewResizeFunc resize,
- ViewDisplayFunc display,
- ViewKeyboardFunc keyboard,
- ViewMotionFunc motion);
-
-void view_display_info(const char *info);
-void view_display_help();
-void view_redraw();
-
-CCL_NAMESPACE_END
-
-#endif /*__UTIL_VIEW_H__*/
diff --git a/release/datafiles/locale b/release/datafiles/locale
-Subproject 620b85f16d03a6aadd7cae56969c9c29b06b992
+Subproject 716dc02ec30c0810513f7b4adc4ae865ae50c4e
diff --git a/release/scripts/addons b/release/scripts/addons
-Subproject c08568cc376d2e4298710c4172fb0c74f0611de
+Subproject 787ea78f7fa6f0373d80ba1247768402df93f8a
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
-Subproject 7936dde9ece881d531b1a2ee6c45ddb56d30038
+Subproject 61e45814503f51963c91c51aaf764612e7c5dc7
diff --git a/release/scripts/modules/rna_manual_reference.py b/release/scripts/modules/rna_manual_reference.py
index 63ee2d1144e..af6634a791a 100644
--- a/release/scripts/modules/rna_manual_reference.py
+++ b/release/scripts/modules/rna_manual_reference.py
@@ -47,7 +47,6 @@ url_manual_mapping = (
("bpy.types.lineartgpencilmodifier.use_offset_towards_custom_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-offset-towards-custom-camera"),
("bpy.types.movietrackingsettings.refine_intrinsics_principal_point*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-refine-intrinsics-principal-point"),
("bpy.types.cyclesobjectsettings.shadow_terminator_geometry_offset*", "render/cycles/object_settings/object_data.html#bpy-types-cyclesobjectsettings-shadow-terminator-geometry-offset"),
- ("bpy.types.cyclesrenderlayersettings.denoising_optix_input_passes*", "render/layers/denoising.html#bpy-types-cyclesrenderlayersettings-denoising-optix-input-passes"),
("bpy.types.sequencertoolsettings.use_snap_current_frame_to_strips*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-use-snap-current-frame-to-strips"),
("bpy.types.fluiddomainsettings.sndparticle_potential_max_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-max-energy"),
("bpy.types.fluiddomainsettings.sndparticle_potential_min_energy*", "physics/fluid/type/domain/liquid/particles.html#bpy-types-fluiddomainsettings-sndparticle-potential-min-energy"),
@@ -111,6 +110,7 @@ url_manual_mapping = (
("bpy.types.gpencilsculptsettings.intersection_threshold*", "grease_pencil/modes/draw/tools/cutter.html#bpy-types-gpencilsculptsettings-intersection-threshold"),
("bpy.types.gpencilsculptsettings.use_multiframe_falloff*", "grease_pencil/multiframe.html#bpy-types-gpencilsculptsettings-use-multiframe-falloff"),
("bpy.types.lineartgpencilmodifier.use_intersection_mask*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-intersection-mask"),
+ ("bpy.types.lineartgpencilmodifier.use_invert_collection*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-invert-collection"),
("bpy.types.movietrackingsettings.use_keyframe_selection*", "movie_clip/tracking/clip/toolbar/solve.html#bpy-types-movietrackingsettings-use-keyframe-selection"),
("bpy.types.rendersettings.simplify_gpencil_antialiasing*", "render/cycles/render_settings/simplify.html#bpy-types-rendersettings-simplify-gpencil-antialiasing"),
("bpy.types.sequencertimelineoverlay.show_strip_duration*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-strip-duration"),
@@ -120,7 +120,6 @@ url_manual_mapping = (
("bpy.types.brush.show_multiplane_scrape_planes_preview*", "sculpt_paint/sculpting/tools/multiplane_scrape.html#bpy-types-brush-show-multiplane-scrape-planes-preview"),
("bpy.types.brushgpencilsettings.eraser_strength_factor*", "grease_pencil/modes/draw/tools/erase.html#bpy-types-brushgpencilsettings-eraser-strength-factor"),
("bpy.types.cyclesmaterialsettings.volume_interpolation*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-volume-interpolation"),
- ("bpy.types.cyclesrendersettings.debug_optix_curves_api*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-optix-curves-api"),
("bpy.types.cyclesrendersettings.denoising_input_passes*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-denoising-input-passes"),
("bpy.types.cyclesrendersettings.film_transparent_glass*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-transparent-glass"),
("bpy.types.cyclesrendersettings.offscreen_dicing_scale*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-offscreen-dicing-scale"),
@@ -354,6 +353,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.use_keyframe_insert_auto*", "editors/timeline.html#bpy-types-toolsettings-use-keyframe-insert-auto"),
("bpy.types.viewlayer.use_pass_cryptomatte_object*", "render/layers/passes.html#bpy-types-viewlayer-use-pass-cryptomatte-object"),
("bpy.ops.armature.rigify_apply_selection_colors*", "addons/rigging/rigify/metarigs.html#bpy-ops-armature-rigify-apply-selection-colors"),
+ ("bpy.ops.ed.lib_id_generate_preview_from_object*", "editors/asset_browser.html#bpy-ops-ed-lib-id-generate-preview-from-object"),
("bpy.types.brushgpencilsettings.fill_layer_mode*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-fill-layer-mode"),
("bpy.types.brushgpencilsettings.random_strength*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-random-strength"),
("bpy.types.brushgpencilsettings.simplify_factor*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-simplify-factor"),
@@ -375,6 +375,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_split_pattern*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-split-pattern"),
("bpy.types.freestylesettings.use_view_map_cache*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-view-map-cache"),
("bpy.types.geometrynodecurvehandletypeselection*", "modeling/geometry_nodes/curve/handle_type_selection.html#bpy-types-geometrynodecurvehandletypeselection"),
+ ("bpy.types.geometrynodeinputmeshvertexneighbors*", "modeling/geometry_nodes/mesh/vertex_neighbors.html#bpy-types-geometrynodeinputmeshvertexneighbors"),
("bpy.types.greasepencil.curve_edit_corner_angle*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-corner-angle"),
("bpy.types.lineartgpencilmodifier.source_camera*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-source-camera"),
("bpy.types.lineartgpencilmodifier.use_face_mark*", "grease_pencil/modifiers/generate/line_art.html#bpy-types-lineartgpencilmodifier-use-face-mark"),
@@ -401,7 +402,6 @@ url_manual_mapping = (
("bpy.types.brushgpencilsettings.use_fill_limit*", "grease_pencil/modes/draw/tools/fill.html#bpy-types-brushgpencilsettings-use-fill-limit"),
("bpy.types.clothsettings.vertex_group_pressure*", "physics/cloth/settings/physical_properties.html#bpy-types-clothsettings-vertex-group-pressure"),
("bpy.types.cyclesmaterialsettings.displacement*", "render/cycles/material_settings.html#bpy-types-cyclesmaterialsettings-displacement"),
- ("bpy.types.cyclesrendersettings.debug_bvh_type*", "render/cycles/render_settings/debug.html#bpy-types-cyclesrendersettings-debug-bvh-type"),
("bpy.types.cyclesrendersettings.fast_gi_method*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-fast-gi-method"),
("bpy.types.cyclesrendersettings.glossy_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-glossy-bounces"),
("bpy.types.cyclesrendersettings.volume_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-volume-bounces"),
@@ -454,6 +454,7 @@ url_manual_mapping = (
("bpy.types.cyclescamerasettings.panorama_type*", "render/cycles/object_settings/cameras.html#bpy-types-cyclescamerasettings-panorama-type"),
("bpy.types.cyclesrendersettings.dicing_camera*", "render/cycles/render_settings/subdivision.html#bpy-types-cyclesrendersettings-dicing-camera"),
("bpy.types.cyclesrendersettings.film_exposure*", "render/cycles/render_settings/film.html#bpy-types-cyclesrendersettings-film-exposure"),
+ ("bpy.types.cyclesrendersettings.sample_offset*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-sample-offset"),
("bpy.types.cyclesrendersettings.texture_limit*", "render/cycles/render_settings/simplify.html#bpy-types-cyclesrendersettings-texture-limit"),
("bpy.types.cyclesrendersettings.use_denoising*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-use-denoising"),
("bpy.types.editbone.bbone_custom_handle_start*", "animation/armatures/bones/properties/bendy_bones.html#bpy-types-editbone-bbone-custom-handle-start"),
@@ -479,6 +480,8 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.use_dashed_line*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-dashed-line"),
("bpy.types.freestylelinestyle.use_same_object*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-same-object"),
("bpy.types.functionnodeinputspecialcharacters*", "modeling/geometry_nodes/text/special_characters.html#bpy-types-functionnodeinputspecialcharacters"),
+ ("bpy.types.geometrynodeinputmeshedgeneighbors*", "modeling/geometry_nodes/mesh/edge_neighbors.html#bpy-types-geometrynodeinputmeshedgeneighbors"),
+ ("bpy.types.geometrynodeinputmeshfaceneighbors*", "modeling/geometry_nodes/mesh/face_neighbors.html#bpy-types-geometrynodeinputmeshfaceneighbors"),
("bpy.types.gpencilsculptguide.reference_point*", "grease_pencil/modes/draw/guides.html#bpy-types-gpencilsculptguide-reference-point"),
("bpy.types.greasepencil.edit_curve_resolution*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-edit-curve-resolution"),
("bpy.types.linestylegeometrymodifier_2doffset*", "render/freestyle/view_layer/line_style/modifiers/geometry/2d_offset.html#bpy-types-linestylegeometrymodifier-2doffset"),
@@ -491,6 +494,7 @@ url_manual_mapping = (
("bpy.types.sequencertimelineoverlay.show_grid*", "editors/video_sequencer/sequencer/display.html#bpy-types-sequencertimelineoverlay-show-grid"),
("bpy.types.sequencertoolsettings.overlap_mode*", "video_editing/sequencer/editing.html#bpy-types-sequencertoolsettings-overlap-mode"),
("bpy.types.spaceclipeditor.show_green_channel*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-green-channel"),
+ ("bpy.types.spacenodeoverlay.show_context_path*", "interface/controls/nodes/introduction.html#bpy-types-spacenodeoverlay-show-context-path"),
("bpy.types.spaceoutliner.show_restrict_column*", "editors/outliner/interface.html#bpy-types-spaceoutliner-show-restrict-column"),
("bpy.types.spacespreadsheet.object_eval_state*", "editors/spreadsheet.html#bpy-types-spacespreadsheet-object-eval-state"),
("bpy.types.spaceuveditor.display_stretch_type*", "editors/uv/overlays.html#bpy-types-spaceuveditor-display-stretch-type"),
@@ -518,6 +522,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.select_edge_mark*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-select-edge-mark"),
("bpy.types.freestylelinestyle.use_length_max*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-max"),
("bpy.types.freestylelinestyle.use_length_min*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-use-length-min"),
+ ("bpy.types.geometrynodeinputmeshedgevertices*", "modeling/geometry_nodes/mesh/edge_vertices.html#bpy-types-geometrynodeinputmeshedgevertices"),
("bpy.types.geometrynodeinputsplineresolution*", "modeling/geometry_nodes/curve/spline_resolution.html#bpy-types-geometrynodeinputsplineresolution"),
("bpy.types.greasepencil.curve_edit_threshold*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-curve-edit-threshold"),
("bpy.types.materialgpencilstyle.stroke_style*", "grease_pencil/materials/properties.html#bpy-types-materialgpencilstyle-stroke-style"),
@@ -613,6 +618,7 @@ url_manual_mapping = (
("bpy.types.brush.surface_smooth_iterations*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-surface-smooth-iterations"),
("bpy.types.brushgpencilsettings.pen_jitter*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-pen-jitter"),
("bpy.types.brushgpencilsettings.show_lasso*", "grease_pencil/modes/draw/tools/draw.html#bpy-types-brushgpencilsettings-show-lasso"),
+ ("bpy.types.compositornodeconvertcolorspace*", "compositing/types/converter/color_space.html#bpy-types-compositornodeconvertcolorspace"),
("bpy.types.cyclescurverendersettings.shape*", "render/cycles/render_settings/hair.html#bpy-types-cyclescurverendersettings-shape"),
("bpy.types.cyclesrendersettings.ao_bounces*", "render/cycles/render_settings/light_paths.html#bpy-types-cyclesrendersettings-ao-bounces"),
("bpy.types.cyclesrendersettings.time_limit*", "render/cycles/render_settings/sampling.html#bpy-types-cyclesrendersettings-time-limit"),
@@ -709,7 +715,9 @@ url_manual_mapping = (
("bpy.types.geometrynodealigneulertovector*", "modeling/geometry_nodes/utilities/align_euler_to_vector.html#bpy-types-geometrynodealigneulertovector"),
("bpy.types.geometrynodeattributestatistic*", "modeling/geometry_nodes/attribute/attribute_statistic.html#bpy-types-geometrynodeattributestatistic"),
("bpy.types.geometrynodecurvequadrilateral*", "modeling/geometry_nodes/curve_primitives/quadrilateral.html#bpy-types-geometrynodecurvequadrilateral"),
+ ("bpy.types.geometrynodegeometrytoinstance*", "modeling/geometry_nodes/geometry/geometry_to_instance.html#bpy-types-geometrynodegeometrytoinstance"),
("bpy.types.geometrynodeinputmaterialindex*", "modeling/geometry_nodes/material/material_index.html#bpy-types-geometrynodeinputmaterialindex"),
+ ("bpy.types.geometrynodeinputmeshedgeangle*", "modeling/geometry_nodes/mesh/edge_angle.html#bpy-types-geometrynodeinputmeshedgeangle"),
("bpy.types.geometrynodeseparatecomponents*", "modeling/geometry_nodes/geometry/separate_components.html#bpy-types-geometrynodeseparatecomponents"),
("bpy.types.geometrynodesubdivisionsurface*", "modeling/geometry_nodes/mesh/subdivision_surface.html#bpy-types-geometrynodesubdivisionsurface"),
("bpy.types.geometrynodetranslateinstances*", "modeling/geometry_nodes/instances/translate_instances.html#bpy-types-geometrynodetranslateinstances"),
@@ -789,6 +797,7 @@ url_manual_mapping = (
("bpy.types.freestylesettings.use_culling*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-use-culling"),
("bpy.types.geometrynodeendpointselection*", "modeling/geometry_nodes/curve/endpoint_selection.html#bpy-types-geometrynodeendpointselection"),
("bpy.types.geometrynodegeometryproximity*", "modeling/geometry_nodes/geometry/geometry_proximity.html#bpy-types-geometrynodegeometryproximity"),
+ ("bpy.types.geometrynodeinputmeshfacearea*", "modeling/geometry_nodes/mesh/face_area.html#bpy-types-geometrynodeinputmeshfacearea"),
("bpy.types.geometrynodeinputsplinecyclic*", "modeling/geometry_nodes/curve/is_spline_cyclic.html#bpy-types-geometrynodeinputsplinecyclic"),
("bpy.types.geometrynodeinstancestopoints*", "modeling/geometry_nodes/instances/instances_to_points.html#bpy-types-geometrynodeinstancestopoints"),
("bpy.types.geometrynodetransferattribute*", "modeling/geometry_nodes/attribute/transfer_attribute.html#bpy-types-geometrynodetransferattribute"),
@@ -818,6 +827,7 @@ url_manual_mapping = (
("bpy.types.toolsettings.mesh_select_mode*", "modeling/meshes/selecting/introduction.html#bpy-types-toolsettings-mesh-select-mode"),
("bpy.types.toolsettings.use_snap_project*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-project"),
("bpy.types.transformorientationslot.type*", "editors/3dview/controls/orientation.html#bpy-types-transformorientationslot-type"),
+ ("bpy.types.unitsettings.temperature_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-temperature-unit"),
("bpy.types.vertexweightproximitymodifier*", "modeling/modifiers/modify/weight_proximity.html#bpy-types-vertexweightproximitymodifier"),
("bpy.types.view3doverlay.show_wireframes*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-show-wireframes"),
("bpy.types.view3dshading.background_type*", "editors/3dview/display/shading.html#bpy-types-view3dshading-background-type"),
@@ -875,6 +885,7 @@ url_manual_mapping = (
("bpy.types.spacetexteditor.use_find_all*", "editors/text_editor.html#bpy-types-spacetexteditor-use-find-all"),
("bpy.types.toolsettings.snap_uv_element*", "editors/uv/controls/snapping.html#bpy-types-toolsettings-snap-uv-element"),
("bpy.types.toolsettings.use_snap_rotate*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-use-snap-rotate"),
+ ("bpy.types.unitsettings.system_rotation*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system-rotation"),
("bpy.types.view3doverlay.display_handle*", "editors/3dview/display/overlays.html#bpy-types-view3doverlay-display-handle"),
("bpy.types.volumedisplay.wireframe_type*", "modeling/volumes/properties.html#bpy-types-volumedisplay-wireframe-type"),
("bpy.ops.anim.channels_editable_toggle*", "editors/graph_editor/channels.html#bpy-ops-anim-channels-editable-toggle"),
@@ -919,11 +930,15 @@ url_manual_mapping = (
("bpy.types.freestylelineset.visibility*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-visibility"),
("bpy.types.freestylelinestyle.chaining*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-chaining"),
("bpy.types.freestylelinestyle.sort_key*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-sort-key"),
+ ("bpy.types.geometrynodeaccumulatefield*", "modeling/geometry_nodes/utilities/accumulate_field.html#bpy-types-geometrynodeaccumulatefield"),
("bpy.types.geometrynodecurvesethandles*", "modeling/geometry_nodes/curve/set_handle_type.html#bpy-types-geometrynodecurvesethandles"),
("bpy.types.geometrynodecurvesplinetype*", "modeling/geometry_nodes/curve/set_spline_type.html#bpy-types-geometrynodecurvesplinetype"),
+ ("bpy.types.geometrynodeinputmeshisland*", "modeling/geometry_nodes/mesh/mesh_island.html#bpy-types-geometrynodeinputmeshisland"),
+ ("bpy.types.geometrynodemergebydistance*", "modeling/geometry_nodes/geometry/merge_by_distance.html#bpy-types-geometrynodemergebydistance"),
("bpy.types.geometrynodereplacematerial*", "modeling/geometry_nodes/material/replace_material.html#bpy-types-geometrynodereplacematerial"),
("bpy.types.geometrynoderotateinstances*", "modeling/geometry_nodes/instances/rotate_instances.html#bpy-types-geometrynoderotateinstances"),
("bpy.types.geometrynodesetsplinecyclic*", "modeling/geometry_nodes/curve/set_spline_cyclic.html#bpy-types-geometrynodesetsplinecyclic"),
+ ("bpy.types.geometrynodesplineparameter*", "modeling/geometry_nodes/curve/spline_parameter.html#bpy-types-geometrynodesplineparameter"),
("bpy.types.gpencillayer.use_mask_layer*", "grease_pencil/properties/layers.html#bpy-types-gpencillayer-use-mask-layer"),
("bpy.types.greasepencil.use_curve_edit*", "grease_pencil/modes/edit/curve_editing.html#bpy-types-greasepencil-use-curve-edit"),
("bpy.types.imagepaint.screen_grab_size*", "sculpt_paint/texture_paint/tool_settings/options.html#bpy-types-imagepaint-screen-grab-size"),
@@ -993,9 +1008,9 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.use_flow*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-use-flow"),
("bpy.types.fmodifierfunctiongenerator*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierfunctiongenerator"),
("bpy.types.geometrynodecollectioninfo*", "modeling/geometry_nodes/input/collection_info.html#bpy-types-geometrynodecollectioninfo"),
- ("bpy.types.geometrynodecurveparameter*", "modeling/geometry_nodes/curve/curve_parameter.html#bpy-types-geometrynodecurveparameter"),
("bpy.types.geometrynodedeletegeometry*", "modeling/geometry_nodes/geometry/delete_geometry.html#bpy-types-geometrynodedeletegeometry"),
("bpy.types.geometrynodeinputcurvetilt*", "modeling/geometry_nodes/curve/curve_tilt.html#bpy-types-geometrynodeinputcurvetilt"),
+ ("bpy.types.geometrynodeinputscenetime*", "modeling/geometry_nodes/input/scene_time.html#bpy-types-geometrynodeinputscenetime"),
("bpy.types.geometrynodepointstovolume*", "modeling/geometry_nodes/point/points_to_volume.html#bpy-types-geometrynodepointstovolume"),
("bpy.types.geometrynodescaleinstances*", "modeling/geometry_nodes/instances/scale_instances.html#bpy-types-geometrynodescaleinstances"),
("bpy.types.geometrynodesetcurveradius*", "modeling/geometry_nodes/curve/set_curve_radius.html#bpy-types-geometrynodesetcurveradius"),
@@ -1075,7 +1090,6 @@ url_manual_mapping = (
("bpy.types.fluidflowsettings.density*", "physics/fluid/type/flow.html#bpy-types-fluidflowsettings-density"),
("bpy.types.freestylelineset.qi_start*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-qi-start"),
("bpy.types.freestylelinestyle.rounds*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-rounds"),
- ("bpy.types.functionnodecomparefloats*", "modeling/geometry_nodes/utilities/compare_floats.html#bpy-types-functionnodecomparefloats"),
("bpy.types.geometrynodecurvetopoints*", "modeling/geometry_nodes/curve/curve_to_points.html#bpy-types-geometrynodecurvetopoints"),
("bpy.types.geometrynodeinputmaterial*", "modeling/geometry_nodes/input/material.html#bpy-types-geometrynodeinputmaterial"),
("bpy.types.geometrynodeinputposition*", "modeling/geometry_nodes/input/position.html#bpy-types-geometrynodeinputposition"),
@@ -1083,6 +1097,7 @@ url_manual_mapping = (
("bpy.types.geometrynodemeshicosphere*", "modeling/geometry_nodes/mesh_primitives/icosphere.html#bpy-types-geometrynodemeshicosphere"),
("bpy.types.geometrynodereplacestring*", "modeling/geometry_nodes/text/replace_string.html#bpy-types-geometrynodereplacestring"),
("bpy.types.geometrynoderesamplecurve*", "modeling/geometry_nodes/curve/resample_curve.html#bpy-types-geometrynoderesamplecurve"),
+ ("bpy.types.geometrynodescaleelements*", "modeling/geometry_nodes/mesh/scale_elements.html#bpy-types-geometrynodescaleelements"),
("bpy.types.geometrynodesubdividemesh*", "modeling/geometry_nodes/mesh/subdivide_mesh.html#bpy-types-geometrynodesubdividemesh"),
("bpy.types.geometrynodevaluetostring*", "modeling/geometry_nodes/text/value_to_string.html#bpy-types-geometrynodevaluetostring"),
("bpy.types.keyframe.handle_left_type*", "editors/graph_editor/fcurves/properties.html#bpy-types-keyframe-handle-left-type"),
@@ -1106,6 +1121,7 @@ url_manual_mapping = (
("bpy.types.shadernodebsdftranslucent*", "render/shader_nodes/shader/translucent.html#bpy-types-shadernodebsdftranslucent"),
("bpy.types.shadernodebsdftransparent*", "render/shader_nodes/shader/transparent.html#bpy-types-shadernodebsdftransparent"),
("bpy.types.shadernodevectortransform*", "render/shader_nodes/vector/transform.html#bpy-types-shadernodevectortransform"),
+ ("bpy.types.shrinkwrapgpencilmodifier*", "grease_pencil/modifiers/deform/shrinkwrap.html#bpy-types-shrinkwrapgpencilmodifier"),
("bpy.types.spaceclipeditor.show_grid*", "editors/clip/display/clip_display.html#bpy-types-spaceclipeditor-show-grid"),
("bpy.types.spaceoutliner.filter_text*", "editors/outliner/interface.html#bpy-types-spaceoutliner-filter-text"),
("bpy.types.spacetexteditor.find_text*", "editors/text_editor.html#bpy-types-spacetexteditor-find-text"),
@@ -1114,6 +1130,8 @@ url_manual_mapping = (
("bpy.types.spaceuveditor.lock_bounds*", "modeling/meshes/uv/editing.html#bpy-types-spaceuveditor-lock-bounds"),
("bpy.types.spline.tilt_interpolation*", "modeling/curves/properties/active_spline.html#bpy-types-spline-tilt-interpolation"),
("bpy.types.transformorientation.name*", "editors/3dview/controls/orientation.html#bpy-types-transformorientation-name"),
+ ("bpy.types.unitsettings.scale_length*", "scene_layout/scene/properties.html#bpy-types-unitsettings-scale-length"),
+ ("bpy.types.unitsettings.use_separate*", "scene_layout/scene/properties.html#bpy-types-unitsettings-use-separate"),
("bpy.types.viewlayer.use_motion_blur*", "render/layers/introduction.html#bpy-types-viewlayer-use-motion-blur"),
("bpy.types.volumedisplay.slice_depth*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-depth"),
("bpy.types.worldmistsettings.falloff*", "render/cycles/world_settings.html#bpy-types-worldmistsettings-falloff"),
@@ -1146,13 +1164,14 @@ url_manual_mapping = (
("bpy.ops.wm.previews_batch_generate*", "files/blend/previews.html#bpy-ops-wm-previews-batch-generate"),
("bpy.types.assetmetadata.active_tag*", "editors/asset_browser.html#bpy-types-assetmetadata-active-tag"),
("bpy.types.bakesettings.cage_object*", "render/cycles/baking.html#bpy-types-bakesettings-cage-object"),
+ ("bpy.types.bakesettings.margin_type*", "render/cycles/baking.html#bpy-types-bakesettings-margin-type"),
("bpy.types.bone.use_relative_parent*", "animation/armatures/bones/properties/relations.html#bpy-types-bone-use-relative-parent"),
("bpy.types.brush.auto_smooth_factor*", "sculpt_paint/sculpting/tool_settings/brush_settings.html#bpy-types-brush-auto-smooth-factor"),
("bpy.types.brush.smooth_deform_type*", "sculpt_paint/sculpting/tools/smooth.html#bpy-types-brush-smooth-deform-type"),
("bpy.types.brush.use_connected_only*", "sculpt_paint/sculpting/tools/pose.html#bpy-types-brush-use-connected-only"),
("bpy.types.brush.use_cursor_overlay*", "sculpt_paint/brush/cursor.html#bpy-types-brush-use-cursor-overlay"),
("bpy.types.camera.show_passepartout*", "render/cameras.html#bpy-types-camera-show-passepartout"),
- ("bpy.types.collection.lineart_usage*", "scene_layout/collections/properties.html#bpy-types-collection-lineart-usage"),
+ ("bpy.types.collection.lineart_usage*", "scene_layout/collections/collections.html#bpy-types-collection-lineart-usage"),
("bpy.types.colormanagedviewsettings*", "render/color_management.html#bpy-types-colormanagedviewsettings"),
("bpy.types.compositornodebokehimage*", "compositing/types/input/bokeh_image.html#bpy-types-compositornodebokehimage"),
("bpy.types.compositornodecolormatte*", "compositing/types/matte/color_key.html#bpy-types-compositornodecolormatte"),
@@ -1168,6 +1187,7 @@ url_manual_mapping = (
("bpy.types.freestylelineset.exclude*", "render/freestyle/view_layer/line_set.html#bpy-types-freestylelineset-exclude"),
("bpy.types.freestylelinestyle.alpha*", "render/freestyle/view_layer/line_style/alpha.html#bpy-types-freestylelinestyle-alpha"),
("bpy.types.freestylelinestyle.color*", "render/freestyle/view_layer/line_style/color.html#bpy-types-freestylelinestyle-color"),
+ ("bpy.types.geometrynodefieldatindex*", "modeling/geometry_nodes/utilities/field_at_index.html#bpy-types-geometrynodefieldatindex"),
("bpy.types.geometrynodeinputtangent*", "modeling/geometry_nodes/curve/curve_tangent.html#bpy-types-geometrynodeinputtangent"),
("bpy.types.geometrynodejoingeometry*", "modeling/geometry_nodes/geometry/join_geometry.html#bpy-types-geometrynodejoingeometry"),
("bpy.types.geometrynodemeshcylinder*", "modeling/geometry_nodes/mesh_primitives/cylinder.html#bpy-types-geometrynodemeshcylinder"),
@@ -1203,6 +1223,7 @@ url_manual_mapping = (
("bpy.types.thicknessgpencilmodifier*", "grease_pencil/modifiers/deform/thickness.html#bpy-types-thicknessgpencilmodifier"),
("bpy.types.toolsettings.snap_target*", "editors/3dview/controls/snapping.html#bpy-types-toolsettings-snap-target"),
("bpy.types.transformcacheconstraint*", "animation/constraints/transform/transform_cache.html#bpy-types-transformcacheconstraint"),
+ ("bpy.types.unitsettings.length_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-length-unit"),
("bpy.types.vertexweighteditmodifier*", "modeling/modifiers/modify/weight_edit.html#bpy-types-vertexweighteditmodifier"),
("bpy.types.volumedisplay.slice_axis*", "modeling/volumes/properties.html#bpy-types-volumedisplay-slice-axis"),
("bpy.ops.anim.channels_clean_empty*", "editors/nla/editing.html#bpy-ops-anim-channels-clean-empty"),
@@ -1225,7 +1246,7 @@ url_manual_mapping = (
("bpy.ops.object.vertex_group_clean*", "sculpt_paint/weight_paint/editing.html#bpy-ops-object-vertex-group-clean"),
("bpy.ops.poselib.create_pose_asset*", "animation/armatures/posing/editing/pose_library.html#bpy-ops-poselib-create-pose-asset"),
("bpy.ops.preferences.theme_install*", "editors/preferences/themes.html#bpy-ops-preferences-theme-install"),
- ("bpy.ops.render.play-rendered-anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
+ ("bpy.ops.render.play_rendered_anim*", "render/output/animation_player.html#bpy-ops-render-play-rendered-anim"),
("bpy.ops.sculpt.set_pivot_position*", "sculpt_paint/sculpting/editing/sculpt.html#bpy-ops-sculpt-set-pivot-position"),
("bpy.ops.sequencer.image_strip_add*", "video_editing/sequencer/strips/image.html#bpy-ops-sequencer-image-strip-add"),
("bpy.ops.sequencer.movie_strip_add*", "video_editing/sequencer/strips/movie.html#bpy-ops-sequencer-movie-strip-add"),
@@ -1249,6 +1270,7 @@ url_manual_mapping = (
("bpy.types.compositornodemovieclip*", "compositing/types/input/movie_clip.html#bpy-types-compositornodemovieclip"),
("bpy.types.compositornodenormalize*", "compositing/types/vector/normalize.html#bpy-types-compositornodenormalize"),
("bpy.types.compositornodepremulkey*", "compositing/types/converter/alpha_convert.html#bpy-types-compositornodepremulkey"),
+ ("bpy.types.compositornodescenetime*", "compositing/types/input/scene_time.html#bpy-types-compositornodescenetime"),
("bpy.types.compositornodestabilize*", "compositing/types/distort/stabilize_2d.html#bpy-types-compositornodestabilize"),
("bpy.types.compositornodetransform*", "compositing/types/distort/transform.html#bpy-types-compositornodetransform"),
("bpy.types.compositornodetranslate*", "compositing/types/distort/translate.html#bpy-types-compositornodetranslate"),
@@ -1269,6 +1291,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvelength*", "modeling/geometry_nodes/curve/curve_length.html#bpy-types-geometrynodecurvelength"),
("bpy.types.geometrynodecurvespiral*", "modeling/geometry_nodes/curve_primitives/curve_spiral.html#bpy-types-geometrynodecurvespiral"),
("bpy.types.geometrynodecurvetomesh*", "modeling/geometry_nodes/curve/curve_to_mesh.html#bpy-types-geometrynodecurvetomesh"),
+ ("bpy.types.geometrynodeextrudemesh*", "modeling/geometry_nodes/mesh/extrude_mesh.html#bpy-types-geometrynodeextrudemesh"),
("bpy.types.geometrynodefilletcurve*", "modeling/geometry_nodes/curve/fillet_curve.html#bpy-types-geometrynodefilletcurve"),
("bpy.types.geometrynodeinputnormal*", "modeling/geometry_nodes/input/normal.html#bpy-types-geometrynodeinputnormal"),
("bpy.types.geometrynodeinputradius*", "modeling/geometry_nodes/input/radius.html#bpy-types-geometrynodeinputradius"),
@@ -1328,6 +1351,7 @@ url_manual_mapping = (
("bpy.ops.mesh.primitive_plane_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-plane-add"),
("bpy.ops.mesh.primitive_torus_add*", "modeling/meshes/primitives.html#bpy-ops-mesh-primitive-torus-add"),
("bpy.ops.mesh.select_non_manifold*", "modeling/meshes/selecting/all_by_trait.html#bpy-ops-mesh-select-non-manifold"),
+ ("bpy.ops.object.attribute_convert*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-convert"),
("bpy.ops.object.constraints_clear*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-clear"),
("bpy.ops.object.quadriflow_remesh*", "modeling/meshes/retopology.html#bpy-ops-object-quadriflow-remesh"),
("bpy.ops.object.vertex_group_copy*", "modeling/meshes/properties/vertex_groups/vertex_groups.html#bpy-ops-object-vertex-group-copy"),
@@ -1384,6 +1408,7 @@ url_manual_mapping = (
("bpy.types.freestylelinestyle.gap*", "render/freestyle/view_layer/line_style/strokes.html#bpy-types-freestylelinestyle-gap"),
("bpy.types.freestylesettings.mode*", "render/freestyle/view_layer/freestyle.html#bpy-types-freestylesettings-mode"),
("bpy.types.geometrynodeconvexhull*", "modeling/geometry_nodes/geometry/convex_hull.html#bpy-types-geometrynodeconvexhull"),
+ ("bpy.types.geometrynodedomainsize*", "modeling/geometry_nodes/attribute/domain_size.html#bpy-types-geometrynodedomainsize"),
("bpy.types.geometrynodefloattoint*", "modeling/geometry_nodes/utilities/float_to_integer.html#bpy-types-geometrynodefloattoint"),
("bpy.types.geometrynodeinputcolor*", "modeling/geometry_nodes/input/color.html#bpy-types-geometrynodeinputcolor"),
("bpy.types.geometrynodeinputindex*", "modeling/geometry_nodes/input/input_index.html#bpy-types-geometrynodeinputindex"),
@@ -1414,6 +1439,8 @@ url_manual_mapping = (
("bpy.types.sound.use_memory_cache*", "video_editing/sequencer/sidebar/strip.html#bpy-types-sound-use-memory-cache"),
("bpy.types.spaceview3d.show_gizmo*", "editors/3dview/display/gizmo.html#bpy-types-spaceview3d-show-gizmo"),
("bpy.types.texturegpencilmodifier*", "grease_pencil/modifiers/modify/texture_mapping.html#bpy-types-texturegpencilmodifier"),
+ ("bpy.types.unitsettings.mass_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-mass-unit"),
+ ("bpy.types.unitsettings.time_unit*", "scene_layout/scene/properties.html#bpy-types-unitsettings-time-unit"),
("bpy.types.volumedisplacemodifier*", "modeling/modifiers/deform/volume_displace.html#bpy-types-volumedisplacemodifier"),
("bpy.types.volumerender.step_size*", "modeling/volumes/properties.html#bpy-types-volumerender-step-size"),
("bpy.types.weightednormalmodifier*", "modeling/modifiers/modify/weighted_normal.html#bpy-types-weightednormalmodifier"),
@@ -1431,6 +1458,7 @@ url_manual_mapping = (
("bpy.ops.gpencil.stroke_caps_set*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-caps-set"),
("bpy.ops.gpencil.stroke_separate*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-stroke-separate"),
("bpy.ops.gpencil.stroke_simplify*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-simplify"),
+ ("bpy.ops.graph.blend_to_neighbor*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-blend-to-neighbor"),
("bpy.ops.graph.snap_cursor_value*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-snap-cursor-value"),
("bpy.ops.image.save_all_modified*", "editors/image/editing.html#bpy-ops-image-save-all-modified"),
("bpy.ops.mesh.extrude_edges_move*", "modeling/meshes/editing/edge/extrude_edges.html#bpy-ops-mesh-extrude-edges-move"),
@@ -1443,6 +1471,7 @@ url_manual_mapping = (
("bpy.ops.mesh.subdivide_edgering*", "modeling/meshes/editing/edge/subdivide_edge_ring.html#bpy-ops-mesh-subdivide-edgering"),
("bpy.ops.node.hide_socket_toggle*", "interface/controls/nodes/editing.html#bpy-ops-node-hide-socket-toggle"),
("bpy.ops.node.tree_socket_remove*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-remove"),
+ ("bpy.ops.object.attribute_remove*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-remove"),
("bpy.ops.object.constraints_copy*", "animation/constraints/interface/adding_removing.html#bpy-ops-object-constraints-copy"),
("bpy.ops.object.gpencil_modifier*", "grease_pencil/modifiers/index.html#bpy-ops-object-gpencil-modifier"),
("bpy.ops.object.make_links_scene*", "scene_layout/object/editing/link_transfer/link_scene.html#bpy-ops-object-make-links-scene"),
@@ -1505,6 +1534,7 @@ url_manual_mapping = (
("bpy.types.geometrynodecurvestar*", "modeling/geometry_nodes/curve_primitives/star.html#bpy-types-geometrynodecurvestar"),
("bpy.types.geometrynodeedgesplit*", "modeling/geometry_nodes/mesh/split_edges.html#bpy-types-geometrynodeedgesplit"),
("bpy.types.geometrynodefillcurve*", "modeling/geometry_nodes/curve/fill_curve.html#bpy-types-geometrynodefillcurve"),
+ ("bpy.types.geometrynodeflipfaces*", "modeling/geometry_nodes/mesh/flip_faces.html#bpy-types-geometrynodeflipfaces"),
("bpy.types.geometrynodetransform*", "modeling/geometry_nodes/geometry/transform.html#bpy-types-geometrynodetransform"),
("bpy.types.geometrynodetrimcurve*", "modeling/geometry_nodes/curve/trim_curve.html#bpy-types-geometrynodetrimcurve"),
("bpy.types.gpencilsculptsettings*", "grease_pencil/properties/index.html#bpy-types-gpencilsculptsettings"),
@@ -1548,6 +1578,7 @@ url_manual_mapping = (
("bpy.ops.curve.switch_direction*", "modeling/curves/editing/segments.html#bpy-ops-curve-switch-direction"),
("bpy.ops.gpencil.duplicate_move*", "grease_pencil/modes/edit/grease_pencil_menu.html#bpy-ops-gpencil-duplicate-move"),
("bpy.ops.gpencil.stroke_arrange*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-arrange"),
+ ("bpy.ops.graph.equalize_handles*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-equalize-handles"),
("bpy.ops.mesh.bridge-edge-loops*", "modeling/meshes/editing/edge/bridge_edge_loops.html#bpy-ops-mesh-bridge-edge-loops"),
("bpy.ops.mesh.intersect_boolean*", "modeling/meshes/editing/face/intersect_boolean.html#bpy-ops-mesh-intersect-boolean"),
("bpy.ops.mesh.loop_multi_select*", "modeling/meshes/selecting/loops.html#bpy-ops-mesh-loop-multi-select"),
@@ -1612,6 +1643,7 @@ url_manual_mapping = (
("bpy.types.motionpath.frame_end*", "animation/motion_paths.html#bpy-types-motionpath-frame-end"),
("bpy.types.noisegpencilmodifier*", "grease_pencil/modifiers/deform/noise.html#bpy-types-noisegpencilmodifier"),
("bpy.types.object.hide_viewport*", "scene_layout/object/properties/visibility.html#bpy-types-object-hide-viewport"),
+ ("bpy.types.object.rotation_mode*", "scene_layout/object/properties/transforms.html#bpy-types-object-rotation-mode"),
("bpy.types.object.show_in_front*", "scene_layout/object/properties/display.html#bpy-types-object-show-in-front"),
("bpy.types.posebone.rigify_type*", "addons/rigging/rigify/rig_types/index.html#bpy-types-posebone-rigify-type"),
("bpy.types.preferencesfilepaths*", "editors/preferences/file_paths.html#bpy-types-preferencesfilepaths"),
@@ -1714,6 +1746,7 @@ url_manual_mapping = (
("bpy.types.cyclesworldsettings*", "render/cycles/world_settings.html#bpy-types-cyclesworldsettings"),
("bpy.types.dashgpencilmodifier*", "grease_pencil/modifiers/generate/dash.html#bpy-types-dashgpencilmodifier"),
("bpy.types.fluiddomainsettings*", "physics/fluid/type/domain/index.html#bpy-types-fluiddomainsettings"),
+ ("bpy.types.functionnodecompare*", "modeling/geometry_nodes/utilities/compare.html#bpy-types-functionnodecompare"),
("bpy.types.geometrynodeboolean*", "modeling/geometry_nodes/input/boolean.html#bpy-types-geometrynodeboolean"),
("bpy.types.geometrynodeinputid*", "modeling/geometry_nodes/input/id.html#bpy-types-geometrynodeinputid"),
("bpy.types.geometrynodeinteger*", "modeling/geometry_nodes/input/integer.html#bpy-types-geometrynodeinteger"),
@@ -1740,6 +1773,7 @@ url_manual_mapping = (
("bpy.types.shadernodelightpath*", "render/shader_nodes/input/light_path.html#bpy-types-shadernodelightpath"),
("bpy.types.shadernodemixshader*", "render/shader_nodes/shader/mix.html#bpy-types-shadernodemixshader"),
("bpy.types.shadernodenormalmap*", "render/shader_nodes/vector/normal_map.html#bpy-types-shadernodenormalmap"),
+ ("bpy.types.shadernodepointinfo*", "render/shader_nodes/input/point_info.html#bpy-types-shadernodepointinfo"),
("bpy.types.shadernodewireframe*", "render/shader_nodes/input/wireframe.html#bpy-types-shadernodewireframe"),
("bpy.types.spacesequenceeditor*", "video_editing/index.html#bpy-types-spacesequenceeditor"),
("bpy.types.spline.resolution_u*", "modeling/curves/properties/active_spline.html#bpy-types-spline-resolution-u"),
@@ -1752,6 +1786,7 @@ url_manual_mapping = (
("bpy.types.tintgpencilmodifier*", "grease_pencil/modifiers/color/tint.html#bpy-types-tintgpencilmodifier"),
("bpy.types.transformconstraint*", "animation/constraints/transform/transformation.html#bpy-types-transformconstraint"),
("bpy.types.triangulatemodifier*", "modeling/modifiers/generate/triangulate.html#bpy-types-triangulatemodifier"),
+ ("bpy.types.unitsettings.system*", "scene_layout/scene/properties.html#bpy-types-unitsettings-system"),
("bpy.types.viewlayer.use_solid*", "render/layers/introduction.html#bpy-types-viewlayer-use-solid"),
("bpy.types.volume.frame_offset*", "modeling/volumes/properties.html#bpy-types-volume-frame-offset"),
("bpy.types.windowmanager.addon*", "editors/preferences/addons.html#bpy-types-windowmanager-addon"),
@@ -1784,6 +1819,7 @@ url_manual_mapping = (
("bpy.ops.node.node_copy_color*", "interface/controls/nodes/sidebar.html#bpy-ops-node-node-copy-color"),
("bpy.ops.node.read_viewlayers*", "interface/controls/nodes/editing.html#bpy-ops-node-read-viewlayers"),
("bpy.ops.node.tree_socket_add*", "interface/controls/nodes/groups.html#bpy-ops-node-tree-socket-add"),
+ ("bpy.ops.object.attribute_add*", "modeling/geometry_nodes/attributes_reference.html#bpy-ops-object-attribute-add"),
("bpy.ops.object.data_transfer*", "scene_layout/object/editing/link_transfer/transfer_mesh_data.html#bpy-ops-object-data-transfer"),
("bpy.ops.object.modifier_copy*", "modeling/modifiers/introduction.html#bpy-ops-object-modifier-copy"),
("bpy.ops.object.select_camera*", "scene_layout/object/selecting.html#bpy-ops-object-select-camera"),
@@ -1815,12 +1851,12 @@ url_manual_mapping = (
("bpy.types.armature.show_axes*", "animation/armatures/properties/display.html#bpy-types-armature-show-axes"),
("bpy.types.armatureconstraint*", "animation/constraints/relationship/armature.html#bpy-types-armatureconstraint"),
("bpy.types.compositornodeblur*", "compositing/types/filter/blur_node.html#bpy-types-compositornodeblur"),
- ("bpy.types.compositornodecomb*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodecomb"),
+ ("bpy.types.compositornodecomb*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodecomb"),
("bpy.types.compositornodecrop*", "compositing/types/distort/crop.html#bpy-types-compositornodecrop"),
("bpy.types.compositornodeflip*", "compositing/types/distort/flip.html#bpy-types-compositornodeflip"),
("bpy.types.compositornodemask*", "compositing/types/input/mask.html#bpy-types-compositornodemask"),
("bpy.types.compositornodemath*", "compositing/types/converter/math.html#bpy-types-compositornodemath"),
- ("bpy.types.compositornodetime*", "compositing/types/input/time.html#bpy-types-compositornodetime"),
+ ("bpy.types.compositornodetime*", "compositing/types/input/time_curve.html#bpy-types-compositornodetime"),
("bpy.types.constraint.enabled*", "animation/constraints/interface/header.html#bpy-types-constraint-enabled"),
("bpy.types.curve.bevel_object*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-object"),
("bpy.types.curve.resolution_u*", "modeling/curves/properties/shape.html#bpy-types-curve-resolution-u"),
@@ -1888,6 +1924,7 @@ url_manual_mapping = (
("bpy.ops.curve.smooth_weight*", "modeling/curves/editing/control_points.html#bpy-ops-curve-smooth-weight"),
("bpy.ops.file.pack_libraries*", "files/blend/packed_data.html#bpy-ops-file-pack-libraries"),
("bpy.ops.font.change_spacing*", "modeling/texts/editing.html#bpy-ops-font-change-spacing"),
+ ("bpy.ops.gpencil.layer_merge*", "grease_pencil/properties/layers.html#bpy-ops-gpencil-layer-merge"),
("bpy.ops.gpencil.stroke_flip*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-flip"),
("bpy.ops.gpencil.stroke_join*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-join"),
("bpy.ops.gpencil.stroke_trim*", "grease_pencil/modes/edit/stroke_menu.html#bpy-ops-gpencil-stroke-trim"),
@@ -1945,7 +1982,7 @@ url_manual_mapping = (
("bpy.types.collisionmodifier*", "physics/collision.html#bpy-types-collisionmodifier"),
("bpy.types.collisionsettings*", "physics/collision.html#bpy-types-collisionsettings"),
("bpy.types.compositornodergb*", "compositing/types/input/rgb.html#bpy-types-compositornodergb"),
- ("bpy.types.compositornodesep*", "editors/texture_node/types/color/combine_separate.html#bpy-types-compositornodesep"),
+ ("bpy.types.compositornodesep*", "compositing/types/converter/combine_separate.html#bpy-types-compositornodesep"),
("bpy.types.curve.bevel_depth*", "modeling/curves/properties/geometry.html#bpy-types-curve-bevel-depth"),
("bpy.types.curve.use_stretch*", "modeling/curves/properties/shape.html#bpy-types-curve-use-stretch"),
("bpy.types.edgesplitmodifier*", "modeling/modifiers/generate/edge_split.html#bpy-types-edgesplitmodifier"),
@@ -2168,6 +2205,7 @@ url_manual_mapping = (
("bpy.types.floorconstraint*", "animation/constraints/relationship/floor.html#bpy-types-floorconstraint"),
("bpy.types.fmodifiercycles*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifiercycles"),
("bpy.types.fmodifierlimits*", "editors/graph_editor/fcurves/modifiers.html#bpy-types-fmodifierlimits"),
+ ("bpy.types.geometrynodearc*", "modeling/geometry_nodes/curve_primitives/arc.html#bpy-types-geometrynodearc"),
("bpy.types.imagepaint.mode*", "sculpt_paint/texture_paint/tool_settings/texture_slots.html#bpy-types-imagepaint-mode"),
("bpy.types.latticemodifier*", "modeling/modifiers/deform/lattice.html#bpy-types-latticemodifier"),
("bpy.types.materiallineart*", "render/materials/line_art.html#bpy-types-materiallineart"),
@@ -2285,6 +2323,7 @@ url_manual_mapping = (
("bpy.ops.fluid.free_mesh*", "physics/fluid/type/domain/liquid/mesh.html#bpy-ops-fluid-free-mesh"),
("bpy.ops.font.select_all*", "modeling/texts/selecting.html#bpy-ops-font-select-all"),
("bpy.ops.gpencil.convert*", "grease_pencil/modes/object/convert_to_geometry.html#bpy-ops-gpencil-convert"),
+ ("bpy.ops.graph.breakdown*", "editors/graph_editor/fcurves/editing.html#bpy-ops-graph-breakdown"),
("bpy.ops.mask.parent_set*", "movie_clip/masking/editing.html#bpy-ops-mask-parent-set"),
("bpy.ops.mask.select_all*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-all"),
("bpy.ops.mask.select_box*", "movie_clip/masking/selecting.html#bpy-ops-mask-select-box"),
@@ -2471,6 +2510,7 @@ url_manual_mapping = (
("bpy.ops.sculpt.expand*", "sculpt_paint/sculpting/editing/mask.html#bpy-ops-sculpt-expand"),
("bpy.ops.view3d.select*", "editors/3dview/selecting.html#bpy-ops-view3d-select"),
("bpy.ops.wm.debug_menu*", "advanced/operators.html#bpy-ops-wm-debug-menu"),
+ ("bpy.ops.wm.obj_export*", "files/import_export/obj.html#bpy-ops-wm-obj-export"),
("bpy.ops.wm.properties*", "files/data_blocks.html#bpy-ops-wm-properties"),
("bpy.ops.wm.usd_export*", "files/import_export/usd.html#bpy-ops-wm-usd-export"),
("bpy.types.addsequence*", "video_editing/sequencer/strips/effects/add.html#bpy-types-addsequence"),
@@ -2574,6 +2614,7 @@ url_manual_mapping = (
("bpy.types.node.name*", "interface/controls/nodes/sidebar.html#bpy-types-node-name"),
("bpy.types.nodeframe*", "interface/controls/nodes/frame.html#bpy-types-nodeframe"),
("bpy.types.nodegroup*", "interface/controls/nodes/groups.html#bpy-types-nodegroup"),
+ ("bpy.types.scene.muv*", "addons/uv/magic_uv.html#bpy-types-scene-muv"),
("bpy.types.spotlight*", "render/lights/light_object.html#bpy-types-spotlight"),
("bpy.types.textcurve*", "modeling/texts/index.html#bpy-types-textcurve"),
("bpy.types.udimtiles*", "modeling/meshes/uv/workflows/udims.html#bpy-types-udimtiles"),
@@ -2709,6 +2750,7 @@ url_manual_mapping = (
("bpy.ops.render*", "render/index.html#bpy-ops-render"),
("bpy.ops.script*", "advanced/scripting/index.html#bpy-ops-script"),
("bpy.ops.sculpt*", "sculpt_paint/sculpting/index.html#bpy-ops-sculpt"),
+ ("bpy.ops.uv.muv*", "addons/uv/magic_uv.html#bpy-ops-uv-muv"),
("bpy.ops.uv.pin*", "modeling/meshes/uv/editing.html#bpy-ops-uv-pin"),
("bpy.ops.uv.rip*", "modeling/meshes/uv/tools/rip.html#bpy-ops-uv-rip"),
("bpy.ops.view3d*", "editors/3dview/index.html#bpy-ops-view3d"),
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 6980f07eba4..bb2491d7720 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -177,7 +177,7 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
col.label(text="which was replaced by the Asset Browser.")
url = self.get_manual_url()
- col.operator('wm.url_open', text="More Info", icon="URL").url = url
+ col.operator("wm.url_open", text="More Info", icon='URL').url = url
layout.separator()
@@ -188,12 +188,12 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
col.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
if poselib:
- if hasattr(bpy.types, 'POSELIB_OT_convert_old_object_poselib'):
- col.operator('poselib.convert_old_object_poselib',
- text="Convert to Pose Assets", icon="ASSET_MANAGER")
+ if hasattr(bpy.types, "POSELIB_OT_convert_old_object_poselib"):
+ col.operator("poselib.convert_old_object_poselib",
+ text="Convert to Pose Assets", icon='ASSET_MANAGER')
else:
- col.label(text="Enable the Pose Library add-on to convert", icon="ERROR")
- col.label(text="this legacy pose library to pose assets.", icon="BLANK1")
+ col.label(text="Enable the Pose Library add-on to convert", icon='ERROR')
+ col.label(text="this legacy pose library to pose assets.", icon='BLANK1')
# Put the deprecated stuff in its own sub-layout.
@@ -202,7 +202,10 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
# warning about poselib being in an invalid state
if poselib.fcurves and not poselib.pose_markers:
- dep_layout.label(icon='ERROR', text="Error: Potentially corrupt library, run 'Sanitize' operator to fix")
+ dep_layout.label(
+ icon='ERROR',
+ text="Error: Potentially corrupt library, run 'Sanitize' operator to fix",
+ )
# list of poses in pose library
row = dep_layout.row()
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 83e797583ad..44d764f1a2d 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# <pep8 compliant>
-from bpy.types import Panel, UIList
+from bpy.types import Menu, Panel, UIList
class VIEWLAYER_UL_aov(UIList):
@@ -138,7 +138,7 @@ class ViewLayerAOVPanel(ViewLayerButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_list("VIEWLAYER_UL_aov", "aovs", view_layer,
- "aovs", view_layer, "active_aov_index", rows=2)
+ "aovs", view_layer, "active_aov_index", rows=3)
col = row.column()
sub = col.column(align=True)
@@ -187,6 +187,16 @@ class VIEWLAYER_PT_layer_passes_cryptomatte(ViewLayerCryptomattePanel, Panel):
COMPAT_ENGINES = {'BLENDER_EEVEE'}
+class VIEWLAYER_MT_lightgroup_sync(Menu):
+ bl_label = "Lightgroup Sync"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("scene.view_layer_add_used_lightgroups", icon='ADD')
+ layout.operator("scene.view_layer_remove_unused_lightgroups", icon='REMOVE')
+
+
class ViewLayerLightgroupsPanel(ViewLayerButtonsPanel, Panel):
bl_label = "Light Groups"
@@ -201,12 +211,14 @@ class ViewLayerLightgroupsPanel(ViewLayerButtonsPanel, Panel):
row = layout.row()
col = row.column()
col.template_list("UI_UL_list", "lightgroups", view_layer,
- "lightgroups", view_layer, "active_lightgroup_index", rows=2)
+ "lightgroups", view_layer, "active_lightgroup_index", rows=3)
col = row.column()
sub = col.column(align=True)
sub.operator("scene.view_layer_add_lightgroup", icon='ADD', text="")
sub.operator("scene.view_layer_remove_lightgroup", icon='REMOVE', text="")
+ sub.separator()
+ sub.menu("VIEWLAYER_MT_lightgroup_sync", icon='DOWNARROW_HLT', text="")
class VIEWLAYER_PT_layer_passes_lightgroups(ViewLayerLightgroupsPanel):
@@ -215,6 +227,7 @@ class VIEWLAYER_PT_layer_passes_lightgroups(ViewLayerLightgroupsPanel):
classes = (
+ VIEWLAYER_MT_lightgroup_sync,
VIEWLAYER_PT_layer,
VIEWLAYER_PT_layer_passes,
VIEWLAYER_PT_eevee_layer_passes_data,
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 785a841a0e6..1dd50c979e2 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -1453,66 +1453,57 @@ class IMAGE_PT_uv_cursor(Panel):
col.prop(sima, "cursor_location", text="Location")
-class IMAGE_PT_udim_grid(Panel):
+class IMAGE_PT_overlay(Panel):
bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
- bl_category = "View"
- bl_label = "UDIM Grid"
-
- @classmethod
- def poll(cls, context):
- sima = context.space_data
-
- return sima.show_uvedit
+ bl_region_type = 'HEADER'
+ bl_label = "Overlays"
+ bl_ui_units_x = 13
def draw(self, context):
- layout = self.layout
-
- sima = context.space_data
- uvedit = sima.uv_editor
-
- layout.use_property_split = True
- layout.use_property_decorate = False
+ pass
- col = layout.column()
- col.prop(uvedit, "tile_grid_shape", text="Grid Shape")
-class IMAGE_PT_custom_grid(Panel):
+class IMAGE_PT_overlay_guides(Panel):
bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
- bl_category = "View"
- bl_label = "Custom Grid"
+ bl_region_type = 'HEADER'
+ bl_label = "Guides"
+ bl_parent_id = 'IMAGE_PT_overlay'
@classmethod
def poll(cls, context):
sima = context.space_data
- return sima.show_uvedit
- def draw_header(self, context):
- sima = context.space_data
- uvedit = sima.uv_editor
- self.layout.prop(uvedit, "use_custom_grid", text="")
+ return sima.show_uvedit
def draw(self, context):
layout = self.layout
sima = context.space_data
+ overlay = sima.overlay
uvedit = sima.uv_editor
- layout.use_property_split = True
- layout.use_property_decorate = False
+ layout.active = overlay.show_overlays
- col = layout.column()
- col.prop(uvedit, "custom_grid_subdivisions", text="Subdivisions")
+ row = layout.row()
+ row_el = row.column()
+ row_el.prop(overlay, "show_grid_background", text="Grid")
-class IMAGE_PT_overlay(Panel):
- bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'HEADER'
- bl_label = "Overlays"
- bl_ui_units_x = 13
+ if overlay.show_grid_background:
+ layout.use_property_split = True
+ col = layout.column(align=False, heading="Fixed Subdivisions")
+ col.use_property_decorate = False
- def draw(self, context):
- pass
+ row = col.row(align=True)
+ sub = row.row(align=True)
+ sub.prop(uvedit, "use_custom_grid", text="")
+ sub = sub.row(align=True)
+ sub.active = uvedit.use_custom_grid
+ sub.prop(uvedit, "custom_grid_subdivisions", text="")
+
+ row = layout.row()
+ row.use_property_split = True
+ row.use_property_decorate = False
+ row.prop(uvedit, "tile_grid_shape", text="Tiles")
class IMAGE_PT_overlay_uv_edit(Panel):
@@ -1689,9 +1680,8 @@ classes = (
IMAGE_PT_scope_sample,
IMAGE_PT_uv_cursor,
IMAGE_PT_annotation,
- IMAGE_PT_udim_grid,
- IMAGE_PT_custom_grid,
IMAGE_PT_overlay,
+ IMAGE_PT_overlay_guides,
IMAGE_PT_overlay_uv_edit,
IMAGE_PT_overlay_uv_edit_geometry,
IMAGE_PT_overlay_texture_paint,
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 6765fb3ef08..888de38dcc7 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -165,7 +165,7 @@ void BKE_pchan_minmax(const struct Object *ob,
float r_max[3]);
/**
* Calculate the axis aligned bounds of the pose of `ob` in world-space.
-
+ *
* `r_min` and `r_max` are expanded to fit `ob->pose` so the caller must initialize them
* (typically using #INIT_MINMAX).
*
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 34f3b9afacd..8a2693f3f6b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 11
+#define BLENDER_FILE_SUBVERSION 12
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_callbacks.h b/source/blender/blenkernel/BKE_callbacks.h
index 2cd28c4dfa5..8b2af96a063 100644
--- a/source/blender/blenkernel/BKE_callbacks.h
+++ b/source/blender/blenkernel/BKE_callbacks.h
@@ -16,7 +16,7 @@ struct Main;
struct PointerRNA;
/**
- Callbacks for One Off Actions
+ * Callbacks for One Off Actions
* =============================
*
* - `{ACTION}` use in cases where only a single callback is required,
diff --git a/source/blender/blenkernel/BKE_cryptomatte.hh b/source/blender/blenkernel/BKE_cryptomatte.hh
index 0c576e5e48e..cd3f8dc9f58 100644
--- a/source/blender/blenkernel/BKE_cryptomatte.hh
+++ b/source/blender/blenkernel/BKE_cryptomatte.hh
@@ -59,7 +59,7 @@ struct CryptomatteHash {
std::string hex_encoded() const;
/**
- Convert a cryptomatte hash to a float.
+ * Convert a cryptomatte hash to a float.
*
* Cryptomatte hashes are stored in float textures and images. The conversion is taken from the
* cryptomatte specification. See Floating point conversion section in
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 9061bb9fb81..9fd023edcf2 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -40,7 +40,7 @@ namespace curves::nurbs {
struct BasisCache {
/**
* For each evaluated point, the weight for all control points that influences it.
- * The vector's size is the evaluated point count multiplied by the spline's order.
+ * The vector's size is the evaluated point count multiplied by the curve's order.
*/
Vector<float> weights;
/**
@@ -61,7 +61,7 @@ class CurvesGeometryRuntime {
public:
/**
* Cache of offsets into the evaluated array for each curve, accounting for all previous
- * evaluated points, Bezier curve vector segments, different resolutions per spline, etc.
+ * evaluated points, Bezier curve vector segments, different resolutions per curve, etc.
*/
mutable Vector<int> evaluated_offsets_cache;
mutable Vector<int> bezier_evaluated_offsets;
@@ -86,13 +86,13 @@ class CurvesGeometryRuntime {
mutable std::mutex length_cache_mutex;
mutable bool length_cache_dirty = true;
- /** Direction of the spline at each evaluated point. */
- mutable Vector<float3> evaluated_tangents_cache;
+ /** Direction of the curve at each evaluated point. */
+ mutable Vector<float3> evaluated_tangent_cache;
mutable std::mutex tangent_cache_mutex;
mutable bool tangent_cache_dirty = true;
/** Normal direction vectors for each evaluated point. */
- mutable Vector<float3> evaluated_normals_cache;
+ mutable Vector<float3> evaluated_normal_cache;
mutable std::mutex normal_cache_mutex;
mutable bool normal_cache_dirty = true;
};
@@ -158,6 +158,9 @@ class CurvesGeometry : public ::CurvesGeometry {
/** Return the number of curves with each type. */
std::array<int, CURVE_TYPES_NUM> count_curve_types() const;
+ /** Return true if all of the curves have the provided type. */
+ bool is_single_type(CurveType type) const;
+
Span<float3> positions() const;
MutableSpan<float3> positions_for_write();
@@ -175,6 +178,13 @@ class CurvesGeometry : public ::CurvesGeometry {
MutableSpan<int> resolution_for_write();
/**
+ * Which method to use for calculating the normals of evaluated points (#NormalMode).
+ * Call #tag_normals_changed after changes.
+ */
+ VArray<int8_t> normal_mode() const;
+ MutableSpan<int8_t> normal_mode_for_write();
+
+ /**
* Handle types for Bezier control points. Call #tag_topology_changed after changes.
*/
VArray<int8_t> handle_types_left() const;
@@ -280,6 +290,8 @@ class CurvesGeometry : public ::CurvesGeometry {
Span<int> bezier_evaluated_offsets_for_curve(int curve_index) const;
Span<float3> evaluated_positions() const;
+ Span<float3> evaluated_tangents() const;
+ Span<float3> evaluated_normals() const;
/**
* Return a cache of accumulated lengths along the curve. Each item is the length of the
@@ -379,6 +391,31 @@ inline float3 decode_surface_bary_coord(const float2 &v)
return {v.x, v.y, 1.0f - v.x - v.y};
}
+namespace poly {
+
+/**
+ * Calculate the direction at every point, defined as the normalized average of the two neighboring
+ * segments (and if non-cyclic, the direction of the first and last segments). This is different
+ * than evaluating the derivative of the basis functions for curve types like NURBS, Bezier, or
+ * Catmull Rom, though the results may be similar.
+ */
+void calculate_tangents(Span<float3> positions, bool is_cyclic, MutableSpan<float3> tangents);
+
+/**
+ * Calculate directions perpendicular to the tangent at every point by rotating an arbitrary
+ * starting vector by the same rotation of each tangent. If the curve is cylic, propagate a
+ * correction through the entire to make sure the first and last normal align.
+ */
+void calculate_normals_minimum(Span<float3> tangents, bool cyclic, MutableSpan<float3> normals);
+
+/**
+ * Calculate a vector perpendicular to every tangent on the X-Y plane (unless the tangent is
+ * vertical, in that case use the X direction).
+ */
+void calculate_normals_z_up(Span<float3> tangents, MutableSpan<float3> normals);
+
+} // namespace poly
+
namespace bezier {
/**
@@ -515,7 +552,7 @@ int calculate_evaluated_size(
int knots_size(int points_num, int8_t order, bool cyclic);
/**
- * Calculate the knots for a spline given its properties, based on built-in standards defined by
+ * Calculate the knots for a curve given its properties, based on built-in standards defined by
* #KnotsMode.
*
* \note Theoretically any sorted values can be used for NURBS knots, but calculating based
@@ -586,6 +623,11 @@ inline IndexRange CurvesGeometry::curves_range() const
return IndexRange(this->curves_num());
}
+inline bool CurvesGeometry::is_single_type(const CurveType type) const
+{
+ return this->count_curve_types()[type] == this->curves_num();
+}
+
inline IndexRange CurvesGeometry::points_for_curve(const int index) const
{
/* Offsets are not allocated when there are no curves. */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index cdee166251c..382bfd5b7db 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -43,16 +43,16 @@ typedef struct CfraElem {
/* ************** F-Curve Modifiers *************** */
-/* F-Curve Modifier Type-Info (fmi):
- * This struct provides function pointers for runtime, so that functions can be
- * written more generally (with fewer/no special exceptions for various modifiers).
+/**
+ * F-Curve Modifier Type-Info (fmi):
+ * This struct provides function pointers for runtime, so that functions can be
+ * written more generally (with fewer/no special exceptions for various modifiers).
*
- * Callers of these functions must check that they actually point to something useful,
- * as some constraints don't define some of these.
+ * Callers of these functions must check that they actually point to something useful,
+ * as some constraints don't define some of these.
*
- * Warning: it is not too advisable to reorder order of members of this struct,
- * as you'll have to edit quite a few ($FMODIFIER_NUM_TYPES) of these
- * structs.
+ * \warning it is not too advisable to reorder order of members of this struct,
+ * as you'll have to edit quite a few (#FMODIFIER_NUM_TYPES) of these structs.
*/
typedef struct FModifierTypeInfo {
/* admin/ident */
diff --git a/source/blender/blenkernel/BKE_gpencil_update_cache.h b/source/blender/blenkernel/BKE_gpencil_update_cache.h
index f6ae7b53005..32d971ffdb9 100644
--- a/source/blender/blenkernel/BKE_gpencil_update_cache.h
+++ b/source/blender/blenkernel/BKE_gpencil_update_cache.h
@@ -31,16 +31,17 @@ typedef enum eGPUpdateCacheNodeFlag {
} eGPUpdateCacheNodeFlag;
/**
- * Cache for what needs to be updated after bGPdata was modified.
+ * Cache for what needs to be updated after bGPdata was modified.
*
- * Every node holds information about one element that was changed:
- * - the index of where that element is in the linked-list
- * - the pointer to the original element in bGPdata
- * Additionally, nodes also hold other nodes that are one "level" below them.
- * E.g. a node that represents a change on a bGPDframe could contain a set of
- * nodes that represent a change on bGPDstrokes.
- * These nodes are stored in a red-black tree so that they are sorted by their
- * index to make sure they can be processed in the correct order.
+ * Every node holds information about one element that was changed:
+ * - The index of where that element is in the linked-list.
+ * - The pointer to the original element in bGPdata.
+ *
+ * Additionally, nodes also hold other nodes that are one "level" below them.
+ * E.g. a node that represents a change on a bGPDframe could contain a set of
+ * nodes that represent a change on bGPDstrokes.
+ * These nodes are stored in a red-black tree so that they are sorted by their
+ * index to make sure they can be processed in the correct order.
*/
typedef struct GPencilUpdateCache {
/* Mapping from index to a GPencilUpdateCache struct. */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 23f14f9be9d..c9228db9ecc 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -773,9 +773,9 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree);
struct bNode *nodeGetActivePaintCanvas(struct bNodeTree *ntree);
/**
- * @brief Does the given node supports the sub active flag.
+ * \brief Does the given node supports the sub active flag.
*
- * @param sub_active The active flag to check. NODE_ACTIVE_TEXTURE/NODE_ACTIVE_PAINT_CANVAS
+ * \param sub_active: The active flag to check. #NODE_ACTIVE_TEXTURE / #NODE_ACTIVE_PAINT_CANVAS.
*/
bool nodeSupportsActiveFlag(const struct bNode *node, int sub_active);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 83c0f5639c4..9c4bb01c22a 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -124,7 +124,7 @@ void BKE_rigidbody_validate_sim_world(struct Scene *scene,
/**
* Helper function to calculate volume of rigid-body object.
-
+ *
* TODO: allow a parameter to specify method used to calculate this?
*/
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 61131cff06d..aca8cdf916e 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -112,6 +112,7 @@ set(SRC
intern/curve_deform.c
intern/curve_eval.cc
intern/curve_nurbs.cc
+ intern/curve_poly.cc
intern/curve_to_mesh_convert.cc
intern/curveprofile.cc
intern/curves.cc
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 0bab3d826fd..e85524d4bcb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -888,7 +888,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph),
/* This following macro should be used for all standard single-target *_get_tars functions
* to save typing and reduce maintenance woes. It does not do the subtarget related operations
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
- * really just to help this code easier to read)
+ * really just to help this code easier to read)
*/
/* TODO: cope with getting rotation order... */
#define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \
@@ -932,7 +932,7 @@ static void default_get_tarmat_full_bbone(struct Depsgraph *UNUSED(depsgraph),
* to save typing and reduce maintenance woes. It does not do the subtarget related operations.
* NOTE: the pointer to ct will be changed to point to the next in the list (as it gets removed)
* (Hopefully all compilers will be happy with the lines with just a space on them. Those are
- * really just to help this code easier to read)
+ * really just to help this code easier to read)
*/
#define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, no_copy) \
{ \
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 9b1fd510fa8..6e09d1e8f10 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -381,6 +381,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
curves.geometry);
VArray<int> resolution = geometry.resolution();
+ VArray<int8_t> normal_mode = geometry.normal_mode();
VArray_Span<float> nurbs_weights{
src_component.attribute_get_for_read<float>("nurbs_weight", ATTR_DOMAIN_POINT, 0.0f)};
@@ -436,6 +437,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
spline->positions().fill(float3(0));
spline->tilts().fill(0.0f);
spline->radii().fill(1.0f);
+ spline->normal_mode = static_cast<NormalMode>(normal_mode[curve_index]);
curve_eval->add_spline(std::move(spline));
}
@@ -448,6 +450,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
dst_component,
{"curve_type",
"resolution",
+ "normal_mode",
"nurbs_weight",
"nurbs_order",
"knots_mode",
@@ -468,6 +471,8 @@ Curves *curve_eval_to_curves(const CurveEval &curve_eval)
geometry.offsets_for_write().copy_from(curve_eval.control_point_offsets());
MutableSpan<int8_t> curve_types = geometry.curve_types_for_write();
+ OutputAttribute_Typed<int8_t> normal_mode =
+ dst_component.attribute_try_get_for_output_only<int8_t>("normal_mode", ATTR_DOMAIN_CURVE);
OutputAttribute_Typed<float> nurbs_weight;
OutputAttribute_Typed<int> nurbs_order;
OutputAttribute_Typed<int8_t> nurbs_knots_mode;
@@ -491,7 +496,7 @@ Curves *curve_eval_to_curves(const CurveEval &curve_eval)
for (const int curve_index : curve_eval.splines().index_range()) {
const Spline &spline = *curve_eval.splines()[curve_index];
curve_types[curve_index] = curve_eval.splines()[curve_index]->type();
-
+ normal_mode.as_span()[curve_index] = curve_eval.splines()[curve_index]->normal_mode;
const IndexRange point_range = geometry.points_for_curve(curve_index);
switch (spline.type()) {
@@ -517,6 +522,7 @@ Curves *curve_eval_to_curves(const CurveEval &curve_eval)
}
}
+ normal_mode.save();
nurbs_weight.save();
nurbs_order.save();
nurbs_knots_mode.save();
diff --git a/source/blender/blenkernel/intern/curve_poly.cc b/source/blender/blenkernel/intern/curve_poly.cc
new file mode 100644
index 00000000000..b0ed62d38dd
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_poly.cc
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <algorithm>
+
+#include "BLI_math_vector.h"
+#include "BLI_math_vector.hh"
+
+#include "BKE_curves.hh"
+
+namespace blender::bke::curves::poly {
+
+static float3 direction_bisect(const float3 &prev, const float3 &middle, const float3 &next)
+{
+ const float3 dir_prev = math::normalize(middle - prev);
+ const float3 dir_next = math::normalize(next - middle);
+
+ const float3 result = math::normalize(dir_prev + dir_next);
+ if (UNLIKELY(math::is_zero(result))) {
+ return float3(0.0f, 0.0f, 1.0f);
+ }
+ return result;
+}
+
+void calculate_tangents(const Span<float3> positions,
+ const bool is_cyclic,
+ MutableSpan<float3> tangents)
+{
+ BLI_assert(positions.size() == tangents.size());
+
+ if (positions.size() == 1) {
+ tangents.first() = float3(0.0f, 0.0f, 1.0f);
+ return;
+ }
+
+ for (const int i : IndexRange(1, positions.size() - 2)) {
+ tangents[i] = direction_bisect(positions[i - 1], positions[i], positions[i + 1]);
+ }
+
+ if (is_cyclic) {
+ const float3 &second_to_last = positions[positions.size() - 2];
+ const float3 &last = positions.last();
+ const float3 &first = positions.first();
+ const float3 &second = positions[1];
+ tangents.first() = direction_bisect(last, first, second);
+ tangents.last() = direction_bisect(second_to_last, last, first);
+ }
+ else {
+ tangents.first() = math::normalize(positions[1] - positions.first());
+ tangents.last() = math::normalize(positions.last() - positions[positions.size() - 2]);
+ }
+}
+
+static float3 rotate_direction_around_axis(const float3 &direction,
+ const float3 &axis,
+ const float angle)
+{
+ BLI_ASSERT_UNIT_V3(direction);
+ BLI_ASSERT_UNIT_V3(axis);
+
+ const float3 axis_scaled = axis * math::dot(direction, axis);
+ const float3 diff = direction - axis_scaled;
+ const float3 cross = math::cross(axis, diff);
+
+ return axis_scaled + diff * std::cos(angle) + cross * std::sin(angle);
+}
+
+void calculate_normals_z_up(const Span<float3> tangents, MutableSpan<float3> normals)
+{
+ BLI_assert(normals.size() == tangents.size());
+
+ /* Same as in `vec_to_quat`. */
+ const float epsilon = 1e-4f;
+ for (const int i : normals.index_range()) {
+ const float3 &tangent = tangents[i];
+ if (std::abs(tangent.x) + std::abs(tangent.y) < epsilon) {
+ normals[i] = {1.0f, 0.0f, 0.0f};
+ }
+ else {
+ normals[i] = math::normalize(float3(tangent.y, -tangent.x, 0.0f));
+ }
+ }
+}
+
+/**
+ * Rotate the last normal in the same way the tangent has been rotated.
+ */
+static float3 calculate_next_normal(const float3 &last_normal,
+ const float3 &last_tangent,
+ const float3 &current_tangent)
+{
+ if (math::is_zero(last_tangent) || math::is_zero(current_tangent)) {
+ return last_normal;
+ }
+ const float angle = angle_normalized_v3v3(last_tangent, current_tangent);
+ if (angle != 0.0) {
+ const float3 axis = math::normalize(math::cross(last_tangent, current_tangent));
+ return rotate_direction_around_axis(last_normal, axis, angle);
+ }
+ return last_normal;
+}
+
+void calculate_normals_minimum(const Span<float3> tangents,
+ const bool cyclic,
+ MutableSpan<float3> normals)
+{
+ BLI_assert(normals.size() == tangents.size());
+
+ if (normals.is_empty()) {
+ return;
+ }
+
+ const float epsilon = 1e-4f;
+
+ /* Set initial normal. */
+ const float3 &first_tangent = tangents.first();
+ if (fabs(first_tangent.x) + fabs(first_tangent.y) < epsilon) {
+ normals.first() = {1.0f, 0.0f, 0.0f};
+ }
+ else {
+ normals.first() = math::normalize(float3(first_tangent.y, -first_tangent.x, 0.0f));
+ }
+
+ /* Forward normal with minimum twist along the entire spline. */
+ for (const int i : IndexRange(1, normals.size() - 1)) {
+ normals[i] = calculate_next_normal(normals[i - 1], tangents[i - 1], tangents[i]);
+ }
+
+ if (!cyclic) {
+ return;
+ }
+
+ /* Compute how much the first normal deviates from the normal that has been forwarded along the
+ * entire cyclic spline. */
+ const float3 uncorrected_last_normal = calculate_next_normal(
+ normals.last(), tangents.last(), tangents.first());
+ float correction_angle = angle_signed_on_axis_v3v3_v3(
+ normals.first(), uncorrected_last_normal, tangents.first());
+ if (correction_angle > M_PI) {
+ correction_angle = correction_angle - 2 * M_PI;
+ }
+
+ /* Gradually apply correction by rotating all normals slightly. */
+ const float angle_step = correction_angle / normals.size();
+ for (const int i : normals.index_range()) {
+ const float angle = angle_step * i;
+ normals[i] = rotate_direction_around_axis(normals[i], tangents[i], angle);
+ }
+}
+
+} // namespace blender::bke::curves::poly
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index a76d8b08a16..5c89dfd4df5 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -25,6 +25,7 @@ static const std::string ATTR_RADIUS = "radius";
static const std::string ATTR_CURVE_TYPE = "curve_type";
static const std::string ATTR_CYCLIC = "cyclic";
static const std::string ATTR_RESOLUTION = "resolution";
+static const std::string ATTR_NORMAL_MODE = "normal_mode";
static const std::string ATTR_HANDLE_TYPE_LEFT = "handle_type_left";
static const std::string ATTR_HANDLE_TYPE_RIGHT = "handle_type_right";
static const std::string ATTR_HANDLE_POSITION_LEFT = "handle_left";
@@ -202,7 +203,8 @@ static Span<T> get_span_attribute(const CurvesGeometry &curves,
template<typename T>
static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
const AttributeDomain domain,
- const StringRefNull name)
+ const StringRefNull name,
+ const T default_value = T())
{
const int size = domain_size(curves, domain);
const CustomDataType type = cpp_type_to_custom_data_type(CPPType::get<T>());
@@ -215,7 +217,11 @@ static MutableSpan<T> get_mutable_attribute(CurvesGeometry &curves,
}
data = (T *)CustomData_add_layer_named(
&custom_data, type, CD_CALLOC, nullptr, size, name.c_str());
- return {data, size};
+ MutableSpan<T> span = {data, size};
+ if (size > 0 && span.first() != default_value) {
+ span.fill(default_value);
+ }
+ return span;
}
VArray<int8_t> CurvesGeometry::curve_types() const
@@ -303,7 +309,7 @@ VArray<bool> CurvesGeometry::cyclic() const
}
MutableSpan<bool> CurvesGeometry::cyclic_for_write()
{
- return get_mutable_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC);
+ return get_mutable_attribute<bool>(*this, ATTR_DOMAIN_CURVE, ATTR_CYCLIC, false);
}
VArray<int> CurvesGeometry::resolution() const
@@ -312,7 +318,16 @@ VArray<int> CurvesGeometry::resolution() const
}
MutableSpan<int> CurvesGeometry::resolution_for_write()
{
- return get_mutable_attribute<int>(*this, ATTR_DOMAIN_CURVE, ATTR_RESOLUTION);
+ return get_mutable_attribute<int>(*this, ATTR_DOMAIN_CURVE, ATTR_RESOLUTION, 12);
+}
+
+VArray<int8_t> CurvesGeometry::normal_mode() const
+{
+ return get_varray_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE, 0);
+}
+MutableSpan<int8_t> CurvesGeometry::normal_mode_for_write()
+{
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NORMAL_MODE);
}
VArray<int8_t> CurvesGeometry::handle_types_left() const
@@ -321,7 +336,7 @@ VArray<int8_t> CurvesGeometry::handle_types_left() const
}
MutableSpan<int8_t> CurvesGeometry::handle_types_left_for_write()
{
- return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_POINT, ATTR_HANDLE_TYPE_LEFT);
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_POINT, ATTR_HANDLE_TYPE_LEFT, 0);
}
VArray<int8_t> CurvesGeometry::handle_types_right() const
@@ -330,7 +345,7 @@ VArray<int8_t> CurvesGeometry::handle_types_right() const
}
MutableSpan<int8_t> CurvesGeometry::handle_types_right_for_write()
{
- return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_POINT, ATTR_HANDLE_TYPE_RIGHT);
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_POINT, ATTR_HANDLE_TYPE_RIGHT, 0);
}
Span<float3> CurvesGeometry::handle_positions_left() const
@@ -357,7 +372,7 @@ VArray<int8_t> CurvesGeometry::nurbs_orders() const
}
MutableSpan<int8_t> CurvesGeometry::nurbs_orders_for_write()
{
- return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NURBS_ORDER);
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NURBS_ORDER, 4);
}
Span<float> CurvesGeometry::nurbs_weights() const
@@ -375,7 +390,7 @@ VArray<int8_t> CurvesGeometry::nurbs_knots_modes() const
}
MutableSpan<int8_t> CurvesGeometry::nurbs_knots_modes_for_write()
{
- return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NURBS_KNOTS_MODE);
+ return get_mutable_attribute<int8_t>(*this, ATTR_DOMAIN_CURVE, ATTR_NURBS_KNOTS_MODE, 0);
}
VArray<int> CurvesGeometry::surface_triangle_indices() const
@@ -385,7 +400,7 @@ VArray<int> CurvesGeometry::surface_triangle_indices() const
MutableSpan<int> CurvesGeometry::surface_triangle_indices_for_write()
{
- return get_mutable_attribute<int>(*this, ATTR_DOMAIN_CURVE, ATTR_SURFACE_TRIANGLE_INDEX);
+ return get_mutable_attribute<int>(*this, ATTR_DOMAIN_CURVE, ATTR_SURFACE_TRIANGLE_INDEX, -1);
}
Span<float2> CurvesGeometry::surface_triangle_coords() const
@@ -629,9 +644,117 @@ Span<float3> CurvesGeometry::evaluated_positions() const
});
});
+ this->runtime->position_cache_dirty = false;
return this->runtime->evaluated_position_cache;
}
+Span<float3> CurvesGeometry::evaluated_tangents() const
+{
+ if (!this->runtime->tangent_cache_dirty) {
+ return this->runtime->evaluated_tangent_cache;
+ }
+
+ /* A double checked lock. */
+ std::scoped_lock lock{this->runtime->tangent_cache_mutex};
+ if (!this->runtime->tangent_cache_dirty) {
+ return this->runtime->evaluated_tangent_cache;
+ }
+
+ threading::isolate_task([&]() {
+ const Span<float3> evaluated_positions = this->evaluated_positions();
+ const VArray<bool> cyclic = this->cyclic();
+
+ this->runtime->evaluated_tangent_cache.resize(this->evaluated_points_num());
+ MutableSpan<float3> tangents = this->runtime->evaluated_tangent_cache;
+
+ threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
+ for (const int curve_index : curves_range) {
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
+ if (UNLIKELY(evaluated_points.is_empty())) {
+ continue;
+ }
+ curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points),
+ cyclic[curve_index],
+ tangents.slice(evaluated_points));
+ }
+ });
+
+ /* Correct the first and last tangents of Bezier curves so that they align with the inner
+ * handles. This is a separate loop to avoid the cost when Bezier type curves are not used. */
+ Vector<int64_t> bezier_indices;
+ const IndexMask bezier_mask = this->indices_for_curve_type(CURVE_TYPE_BEZIER, bezier_indices);
+ if (!bezier_mask.is_empty()) {
+ const Span<float3> positions = this->positions();
+ const Span<float3> handles_left = this->handle_positions_left();
+ const Span<float3> handles_right = this->handle_positions_right();
+
+ threading::parallel_for(bezier_mask.index_range(), 1024, [&](IndexRange range) {
+ for (const int curve_index : bezier_mask.slice(range)) {
+ const IndexRange points = this->points_for_curve(curve_index);
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
+
+ if (handles_right[points.first()] != positions[points.first()]) {
+ tangents[evaluated_points.first()] = math::normalize(handles_right[points.first()] -
+ positions[points.first()]);
+ }
+ if (handles_left[points.last()] != positions[points.last()]) {
+ tangents[evaluated_points.last()] = math::normalize(positions[points.last()] -
+ handles_left[points.last()]);
+ }
+ }
+ });
+ }
+ });
+
+ this->runtime->tangent_cache_dirty = false;
+ return this->runtime->evaluated_tangent_cache;
+}
+
+Span<float3> CurvesGeometry::evaluated_normals() const
+{
+ if (!this->runtime->normal_cache_dirty) {
+ return this->runtime->evaluated_normal_cache;
+ }
+
+ /* A double checked lock. */
+ std::scoped_lock lock{this->runtime->normal_cache_mutex};
+ if (!this->runtime->normal_cache_dirty) {
+ return this->runtime->evaluated_normal_cache;
+ }
+
+ threading::isolate_task([&]() {
+ const Span<float3> evaluated_tangents = this->evaluated_tangents();
+ const VArray<bool> cyclic = this->cyclic();
+ const VArray<int8_t> normal_mode = this->normal_mode();
+
+ this->runtime->evaluated_normal_cache.resize(this->evaluated_points_num());
+ MutableSpan<float3> evaluated_normals = this->runtime->evaluated_normal_cache;
+
+ threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
+ for (const int curve_index : curves_range) {
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
+ if (UNLIKELY(evaluated_points.is_empty())) {
+ continue;
+ }
+ switch (normal_mode[curve_index]) {
+ case NORMAL_MODE_Z_UP:
+ curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points),
+ evaluated_normals.slice(evaluated_points));
+ break;
+ case NORMAL_MODE_MINIMUM_TWIST:
+ curves::poly::calculate_normals_minimum(evaluated_tangents.slice(evaluated_points),
+ cyclic[curve_index],
+ evaluated_normals.slice(evaluated_points));
+ break;
+ }
+ }
+ });
+ });
+
+ this->runtime->normal_cache_dirty = false;
+ return this->runtime->evaluated_normal_cache;
+}
+
void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
const GSpan src,
GMutableSpan dst) const
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
index 27c1a2f2f33..0bcab0aae7a 100644
--- a/source/blender/blenkernel/intern/geometry_component_curves.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -141,81 +141,97 @@ const Curve *CurveComponent::get_curve_for_render() const
namespace blender::bke {
-static void calculate_bezier_normals(const BezierSpline &spline, MutableSpan<float3> normals)
+static Array<float3> curve_normal_point_domain(const bke::CurvesGeometry &curves)
{
- Span<int> offsets = spline.control_point_offsets();
- Span<float3> evaluated_normals = spline.evaluated_normals();
- for (const int i : IndexRange(spline.size())) {
- normals[i] = evaluated_normals[offsets[i]];
- }
-}
+ const VArray<int8_t> types = curves.curve_types();
+ const VArray<int> resolutions = curves.resolution();
+ const VArray<bool> curves_cyclic = curves.cyclic();
-static void calculate_poly_normals(const PolySpline &spline, MutableSpan<float3> normals)
-{
- normals.copy_from(spline.evaluated_normals());
-}
+ const Span<float3> positions = curves.positions();
+ const VArray<int8_t> normal_modes = curves.normal_mode();
-/**
- * Because NURBS control points are not necessarily on the path, the normal at the control points
- * is not well defined, so create a temporary poly spline to find the normals. This requires extra
- * copying currently, but may be more efficient in the future if attributes have some form of CoW.
- */
-static void calculate_nurbs_normals(const NURBSpline &spline, MutableSpan<float3> normals)
-{
- PolySpline poly_spline;
- poly_spline.resize(spline.size());
- poly_spline.positions().copy_from(spline.positions());
- poly_spline.tilts().copy_from(spline.tilts());
- normals.copy_from(poly_spline.evaluated_normals());
-}
+ const Span<float3> evaluated_normals = curves.evaluated_normals();
-static Array<float3> curve_normal_point_domain(const CurveEval &curve)
-{
- Span<SplinePtr> splines = curve.splines();
- Array<int> offsets = curve.control_point_offsets();
- const int total_size = offsets.last();
- Array<float3> normals(total_size);
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- const Spline &spline = *splines[i];
- MutableSpan spline_normals{normals.as_mutable_span().slice(offsets[i], spline.size())};
- switch (splines[i]->type()) {
- case CURVE_TYPE_BEZIER:
- calculate_bezier_normals(static_cast<const BezierSpline &>(spline), spline_normals);
+ Array<float3> results(curves.points_num());
+
+ threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
+ Vector<float3> nurbs_tangents;
+
+ for (const int i_curve : range) {
+ const IndexRange points = curves.points_for_curve(i_curve);
+ const IndexRange evaluated_points = curves.evaluated_points_for_curve(i_curve);
+
+ MutableSpan<float3> curve_normals = results.as_mutable_span().slice(points);
+
+ switch (types[i_curve]) {
+ case CURVE_TYPE_CATMULL_ROM: {
+ const Span<float3> normals = evaluated_normals.slice(evaluated_points);
+ const int resolution = resolutions[i_curve];
+ for (const int i : IndexRange(points.size())) {
+ curve_normals[i] = normals[resolution * i];
+ }
break;
+ }
case CURVE_TYPE_POLY:
- calculate_poly_normals(static_cast<const PolySpline &>(spline), spline_normals);
+ curve_normals.copy_from(evaluated_normals.slice(evaluated_points));
break;
- case CURVE_TYPE_NURBS:
- calculate_nurbs_normals(static_cast<const NURBSpline &>(spline), spline_normals);
+ case CURVE_TYPE_BEZIER: {
+ const Span<float3> normals = evaluated_normals.slice(evaluated_points);
+ curve_normals.first() = normals.first();
+ const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
+ for (const int i : IndexRange(points.size()).drop_front(1)) {
+ curve_normals[i] = normals[offsets[i - 1]];
+ }
break;
- case CURVE_TYPE_CATMULL_ROM:
- BLI_assert_unreachable();
+ }
+ case CURVE_TYPE_NURBS: {
+ /* For NURBS curves there is no obvious correspondence between specific evaluated points
+ * and control points, so normals are determined by treating them as poly curves. */
+ nurbs_tangents.clear();
+ nurbs_tangents.resize(points.size());
+ const bool cyclic = curves_cyclic[i_curve];
+ const Span<float3> curve_positions = positions.slice(points);
+ bke::curves::poly::calculate_tangents(curve_positions, cyclic, nurbs_tangents);
+ switch (NormalMode(normal_modes[i_curve])) {
+ case NORMAL_MODE_Z_UP:
+ bke::curves::poly::calculate_normals_z_up(nurbs_tangents, curve_normals);
+ break;
+ case NORMAL_MODE_MINIMUM_TWIST:
+ bke::curves::poly::calculate_normals_minimum(nurbs_tangents, cyclic, curve_normals);
+ break;
+ }
break;
+ }
}
}
});
- return normals;
+ return results;
}
VArray<float3> curve_normals_varray(const CurveComponent &component, const AttributeDomain domain)
{
- if (component.is_empty()) {
- return nullptr;
+ if (!component.has_curves()) {
+ return {};
}
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
+
+ const Curves &curves_id = *component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+
+ const VArray<int8_t> types = curves.curve_types();
+ if (curves.is_single_type(CURVE_TYPE_POLY)) {
+ return component.attribute_try_adapt_domain<float3>(
+ VArray<float3>::ForSpan(curves.evaluated_normals()), ATTR_DOMAIN_POINT, domain);
+ }
+
+ Array<float3> normals = curve_normal_point_domain(curves);
if (domain == ATTR_DOMAIN_POINT) {
- Array<float3> normals = curve_normal_point_domain(*curve);
return VArray<float3>::ForContainer(std::move(normals));
}
if (domain == ATTR_DOMAIN_CURVE) {
- Array<float3> point_normals = curve_normal_point_domain(*curve);
- VArray<float3> varray = VArray<float3>::ForContainer(std::move(point_normals));
return component.attribute_try_adapt_domain<float3>(
- std::move(varray), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
+ VArray<float3>::ForContainer(std::move(normals)), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
}
return nullptr;
@@ -456,6 +472,18 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
make_array_write_attribute<int>,
tag_component_topology_changed);
+ static BuiltinCustomDataLayerProvider normal_mode("normal_mode",
+ ATTR_DOMAIN_CURVE,
+ CD_PROP_INT8,
+ CD_PROP_INT8,
+ BuiltinAttributeProvider::Creatable,
+ BuiltinAttributeProvider::Writable,
+ BuiltinAttributeProvider::Deletable,
+ curve_access,
+ make_array_read_attribute<int8_t>,
+ make_array_write_attribute<int8_t>,
+ tag_component_normals_changed);
+
static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
ATTR_DOMAIN_CURVE,
CD_PROP_INT8,
@@ -490,7 +518,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
curve_access,
make_array_read_attribute<int>,
make_array_write_attribute<int>,
- tag_component_positions_changed);
+ tag_component_topology_changed);
static BuiltinCustomDataLayerProvider cyclic("cyclic",
ATTR_DOMAIN_CURVE,
@@ -515,6 +543,7 @@ static ComponentAttributeProviders create_attribute_providers_for_curve()
&handle_left,
&handle_type_right,
&handle_type_left,
+ &normal_mode,
&nurbs_order,
&nurbs_weight,
&curve_type,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 5fcb53acfcc..a2338eb9b39 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -157,6 +157,7 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f
id_us_plus(dst_id->override_library->reference);
dst_id->override_library->hierarchy_root = src_id->override_library->hierarchy_root;
+ dst_id->override_library->flag = src_id->override_library->flag;
if (do_full_copy) {
BLI_duplicatelist(&dst_id->override_library->properties,
diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
index 8a540f48c23..5e9d8e8c4d0 100644
--- a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
+++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
@@ -9,6 +9,11 @@
#include "MEM_guardedalloc.h"
+#include "BLI_linklist.h"
+
+/* Required for proxy to liboverrides conversion code. */
+#define DNA_DEPRECATED_ALLOW
+
#include "DNA_ID.h"
#include "DNA_collection_types.h"
#include "DNA_object_types.h"
@@ -107,23 +112,29 @@ static void lib_override_library_proxy_convert_do(Main *bmain,
void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
{
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LinkNodePair proxy_objects = {NULL};
+
FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy_group == NULL) {
- continue;
+ if (object->proxy_group != NULL) {
+ BLI_linklist_append(&proxy_objects, object);
}
-
- lib_override_library_proxy_convert_do(bmain, scene, object, reports);
}
FOREACH_SCENE_OBJECT_END;
FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy == NULL) {
- continue;
+ if (object->proxy != NULL && object->proxy_group == NULL) {
+ BLI_linklist_append(&proxy_objects, object);
}
-
- lib_override_library_proxy_convert_do(bmain, scene, object, reports);
}
FOREACH_SCENE_OBJECT_END;
+
+ for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
+ proxy_object_iter = proxy_object_iter->next) {
+ Object *proxy_object = proxy_object_iter->link;
+ lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
+ }
+
+ BLI_linklist_free(proxy_objects.list, NULL);
}
LISTBASE_FOREACH (Object *, object, &bmain->objects) {
diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c
index f783121d02c..84aabbc7a9b 100644
--- a/source/blender/blenkernel/intern/mask_rasterize.c
+++ b/source/blender/blenkernel/intern/mask_rasterize.c
@@ -134,6 +134,14 @@ BLI_INLINE unsigned int clampis_uint(const unsigned int v,
return v < min ? min : (v > max ? max : v);
}
+static ScanFillVert *scanfill_vert_add_v2_with_depth(ScanFillContext *sf_ctx,
+ const float co_xy[2],
+ const float co_z)
+{
+ const float co[3] = {co_xy[0], co_xy[1], co_z};
+ return BLI_scanfill_vert_add(sf_ctx, co);
+}
+
/* --------------------------------------------------------------------- */
/* local structs for mask rasterizing */
/* --------------------------------------------------------------------- */
@@ -646,9 +654,6 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
ScanFillVert *sf_vert_prev;
unsigned int j;
- float co[3];
- co[2] = 0.0f;
-
sf_ctx.poly_nr++;
if (do_aspect_correct) {
@@ -704,8 +709,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
spline, diff_feather_points, tot_diff_feather_points);
}
- copy_v2_v2(co, diff_points[0]);
- sf_vert_prev = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert_prev = scanfill_vert_add_v2_with_depth(&sf_ctx, diff_points[0], 0.0f);
sf_vert_prev->tmp.u = sf_vert_tot;
/* Absolute index of feather vert. */
@@ -713,10 +717,8 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
sf_vert_tot++;
- /* TODO: an alternate functions so we can avoid double vector copy! */
for (j = 1; j < tot_diff_point; j++) {
- copy_v2_v2(co, diff_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, diff_points[j], 0.0f);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = sf_vert_tot + tot_diff_point; /* absolute index of feather vert */
sf_vert_tot++;
@@ -741,16 +743,12 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
}
if (diff_feather_points) {
- float co_feather[3];
- co_feather[2] = 1.0f;
-
BLI_assert(tot_diff_feather_points == tot_diff_point);
/* NOTE: only added for convenience, we don't in fact use these to scan-fill,
* only to create feather faces after scan-fill. */
for (j = 0; j < tot_diff_feather_points; j++) {
- copy_v2_v2(co_feather, diff_feather_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, diff_feather_points[j], 1.0f);
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
}
@@ -762,15 +760,11 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
/* unfilled spline */
if (diff_feather_points) {
- float co_diff[2];
-
- float co_feather[3];
- co_feather[2] = 1.0f;
-
if (spline->flag & MASK_SPLINE_NOINTERSECT) {
diff_feather_points_flip = MEM_mallocN(sizeof(float[2]) * tot_diff_feather_points,
"diff_feather_points_flip");
+ float co_diff[2];
for (j = 0; j < tot_diff_point; j++) {
sub_v2_v2v2(co_diff, diff_points[j], diff_feather_points[j]);
add_v2_v2v2(diff_feather_points_flip[j], diff_points[j], co_diff);
@@ -792,29 +786,29 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
for (j = 0; j < tot_diff_point; j++) {
/* center vert */
- copy_v2_v2(co, diff_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, diff_points[j], 0.0f);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
/* feather vert A */
- copy_v2_v2(co_feather, diff_feather_points[j]);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, diff_feather_points[j], 1.0f);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
/* feather vert B */
if (diff_feather_points_flip) {
- copy_v2_v2(co_feather, diff_feather_points_flip[j]);
+ sf_vert = scanfill_vert_add_v2_with_depth(
+ &sf_ctx, diff_feather_points_flip[j], 1.0f);
}
else {
- sub_v2_v2v2(co_diff, co, co_feather);
- add_v2_v2v2(co_feather, co, co_diff);
+ float co_diff[2];
+ sub_v2_v2v2(co_diff, diff_points[j], diff_feather_points[j]);
+ add_v2_v2v2(co_diff, diff_points[j], co_diff);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, co_diff, 1.0f);
}
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
@@ -857,9 +851,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
for (k = 1; k < vertex_total_cap; k++) {
const float angle = (float)k * (1.0f / (float)vertex_total_cap) * (float)M_PI;
+ float co_feather[2];
rotate_point_v2(co_feather, fp_turn, fp_cent, angle, asp_xy);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, co_feather, 1.0f);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
@@ -877,9 +872,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle,
for (k = 1; k < vertex_total_cap; k++) {
const float angle = (float)k * (1.0f / (float)vertex_total_cap) * (float)M_PI;
+ float co_feather[2];
rotate_point_v2(co_feather, fp_turn, fp_cent, -angle, asp_xy);
- sf_vert = BLI_scanfill_vert_add(&sf_ctx, co_feather);
+ sf_vert = scanfill_vert_add_v2_with_depth(&sf_ctx, co_feather, 1.0f);
sf_vert->tmp.u = sf_vert_tot;
sf_vert->keyindex = SF_KEYINDEX_TEMP_ID;
sf_vert_tot++;
diff --git a/source/blender/blenkernel/intern/scene.cc b/source/blender/blenkernel/intern/scene.cc
index 4e6191cca6f..0430269b75a 100644
--- a/source/blender/blenkernel/intern/scene.cc
+++ b/source/blender/blenkernel/intern/scene.cc
@@ -322,6 +322,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
SEQ_DUPE_ALL,
flag_subdata);
BLI_duplicatelist(&scene_dst->ed->channels, &scene_src->ed->channels);
+ scene_dst->ed->displayed_channels = &scene_dst->ed->channels;
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc
index aa79199d668..e84ec5b3890 100644
--- a/source/blender/blenkernel/intern/type_conversions.cc
+++ b/source/blender/blenkernel/intern/type_conversions.cc
@@ -21,7 +21,7 @@ static void add_implicit_conversion(DataTypeConversions &conversions)
static fn::CustomMF_SI_SO<From, To> multi_function{
conversion_name.c_str(),
/* Use lambda instead of passing #ConversionF directly, because otherwise the compiler won't
- inline the function. */
+ * inline the function. */
[](const From &a) { return ConversionF(a); }};
static auto convert_single_to_initialized = [](const void *src, void *dst) {
*(To *)dst = ConversionF(*(const From *)src);
diff --git a/source/blender/blenlib/BLI_delaunay_2d.h b/source/blender/blenlib/BLI_delaunay_2d.h
index 2d8428e164f..53c2ff1c345 100644
--- a/source/blender/blenlib/BLI_delaunay_2d.h
+++ b/source/blender/blenlib/BLI_delaunay_2d.h
@@ -5,8 +5,8 @@
/** \file
* \ingroup bli
*
- * This header file contains both a C interface and a C++ interface
- * to the 2D Constrained Delaunay Triangulation library routine.
+ * This header file contains both a C interface and a C++ interface
+ * to the 2D Constrained Delaunay Triangulation library routine.
*/
#ifdef __cplusplus
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index 04b40904187..3ce2b90e729 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -270,7 +270,7 @@ struct LinkNode *BLI_file_read_as_lines(const char *file) ATTR_WARN_UNUSED_RESUL
void *BLI_file_read_text_as_mem(const char *filepath, size_t pad_bytes, size_t *r_size);
/**
* Return the text file data with:
-
+ *
* - Newlines replaced with '\0'.
* - Optionally trim white-space, replacing trailing <space> & <tab> with '\0'.
*
diff --git a/source/blender/blenlib/BLI_mesh_intersect.hh b/source/blender/blenlib/BLI_mesh_intersect.hh
index ba1d9b293c7..22ea83760aa 100644
--- a/source/blender/blenlib/BLI_mesh_intersect.hh
+++ b/source/blender/blenlib/BLI_mesh_intersect.hh
@@ -5,8 +5,8 @@
/** \file
* \ingroup bli
*
- * Mesh intersection library functions.
- * Uses exact arithmetic, so need GMP.
+ * Mesh intersection library functions.
+ * Uses exact arithmetic, so need GMP.
*/
#ifdef WITH_GMP
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 7d0884f83dc..45abac33795 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -255,7 +255,7 @@ size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, size_t
*
* \param str: Typically this is the first character in a quoted string.
* Where the character before `*str` would be `"`.
-
+ *
* \return The pointer to the first un-escaped quote.
*/
const char *BLI_str_escape_find_quote(const char *str) ATTR_NONNULL();
diff --git a/source/blender/blenlib/intern/delaunay_2d.cc b/source/blender/blenlib/intern/delaunay_2d.cc
index 804ba5c3c80..ece22bcf82e 100644
--- a/source/blender/blenlib/intern/delaunay_2d.cc
+++ b/source/blender/blenlib/intern/delaunay_2d.cc
@@ -2807,7 +2807,7 @@ blender::meshintersect::CDT_result<mpq_class> delaunay_2d_calc(const CDT_input<m
/* C interface. */
/**
- This function uses the double version of #CDT::delaunay_calc.
+ * This function uses the double version of #CDT::delaunay_calc.
* Almost all of the work here is to convert between C++ #Arrays<Vector<int>>
* and a C version that linearizes all the elements and uses a "start"
* and "len" array to say where the individual vectors start and how
diff --git a/source/blender/blenlib/intern/math_boolean.cc b/source/blender/blenlib/intern/math_boolean.cc
index 885d2c13b49..132d5dfda65 100644
--- a/source/blender/blenlib/intern/math_boolean.cc
+++ b/source/blender/blenlib/intern/math_boolean.cc
@@ -1857,23 +1857,23 @@ double incircle(const double *pa, const double *pb, const double *pc, const doub
}
/**
- * inspherefast() Approximate 3D insphere test. Non-robust.
- * insphere() Adaptive exact 3D insphere test. Robust.
+ * inspherefast() Approximate 3D insphere test. Non-robust.
+ * insphere() Adaptive exact 3D insphere test. Robust.
*
- * Return a positive value if the point pe lies inside the
- * sphere passing through pa, pb, pc, and pd; a negative value
- * if it lies outside; and zero if the five points are
- * co-spherical. The points pa, pb, pc, and pd must be ordered
- * so that they have a positive orientation (as defined by
- * orient3d()), or the sign of the result will be reversed.
+ * Return a positive value if the point pe lies inside the
+ * sphere passing through pa, pb, pc, and pd; a negative value
+ * if it lies outside; and zero if the five points are
+ * co-spherical. The points pa, pb, pc, and pd must be ordered
+ * so that they have a positive orientation (as defined by
+ * orient3d()), or the sign of the result will be reversed.
*
- * The second uses exact arithmetic to ensure a correct answer. The
- * result returned is the determinant of a matrix. In insphere() only,
- * this determinant is computed adaptively, in the sense that exact
- * arithmetic is used only to the degree it is needed to ensure that the
- * returned value has the correct sign. Hence, insphere() is usually quite
- * fast, but will run more slowly when the input points are co-spherical or
- * nearly so.
+ * The second uses exact arithmetic to ensure a correct answer. The
+ * result returned is the determinant of a matrix. In insphere() only,
+ * this determinant is computed adaptively, in the sense that exact
+ * arithmetic is used only to the degree it is needed to ensure that the
+ * returned value has the correct sign. Hence, insphere() is usually quite
+ * fast, but will run more slowly when the input points are co-spherical or
+ * nearly so.
*/
double inspherefast(
diff --git a/source/blender/blenloader/intern/versioning_300.c b/source/blender/blenloader/intern/versioning_300.c
index a00bbaec8dd..95851c0e9ff 100644
--- a/source/blender/blenloader/intern/versioning_300.c
+++ b/source/blender/blenloader/intern/versioning_300.c
@@ -2354,6 +2354,21 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 301, 7) ||
+ (bmain->versionfile == 302 && !MAIN_VERSION_ATLEAST(bmain, 302, 4))) {
+ /* Duplicate value for two flags that mistakenly had the same numeric value. */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
+ if (md->type == eModifierType_WeightVGProximity) {
+ WeightVGProximityModifierData *wpmd = (WeightVGProximityModifierData *)md;
+ if (wpmd->proximity_flags & MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK) {
+ wpmd->proximity_flags |= MOD_WVG_PROXIMITY_WEIGHTS_NORMALIZE;
+ }
+ }
+ }
+ }
+ }
+
if (!MAIN_VERSION_ATLEAST(bmain, 302, 2)) {
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (scene->ed != NULL) {
@@ -2552,9 +2567,7 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
- }
- if (!MAIN_VERSION_ATLEAST(bmain, 302, 10)) {
/* While vertex-colors were experimental the smear tool became corrupt due
* to bugs in the wm_toolsystem API (auto-creation of sculpt brushes
* was broken). Go through and reset all smear brushes. */
@@ -2622,17 +2635,18 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- /**
- * Versioning code until next subversion bump goes here.
- *
- * \note Be sure to check when bumping the version:
- * - "versioning_userdef.c", #blo_do_versions_userdef
- * - "versioning_userdef.c", #do_versions_theme
- *
- * \note Keep this message at the bottom of the function.
- */
- {
- /* Keep this block, even when empty. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 302, 12)) {
+ /* UV/Image show background grid option. */
+ LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, space, &area->spacedata) {
+ if (space->spacetype == SPACE_IMAGE) {
+ SpaceImage *sima = (SpaceImage *)space;
+ sima->overlay.flag |= SI_OVERLAY_SHOW_GRID_BACKGROUND;
+ }
+ }
+ }
+ }
/* Add node storage for the merge by distance node. */
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
@@ -2651,4 +2665,17 @@ void blo_do_versions_300(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
FOREACH_NODETREE_END;
}
+
+ /**
+ * Versioning code until next subversion bump goes here.
+ *
+ * \note Be sure to check when bumping the version:
+ * - "versioning_userdef.c", #blo_do_versions_userdef
+ * - "versioning_userdef.c", #do_versions_theme
+ *
+ * \note Keep this message at the bottom of the function.
+ */
+ {
+ /* Keep this block, even when empty. */
+ }
}
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index c38393e9284..5597d496890 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -988,7 +988,7 @@ void discard_edit_mode_pointers(ID *id_cow)
} // namespace
/**
- Free content of the CoW data-block.
+ * Free content of the CoW data-block.
* Notes:
* - Does not recurse into nested ID data-blocks.
* - Does not free data-block itself.
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 58676caa6f9..ee70cebcfd2 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -27,25 +27,12 @@
static void eevee_motion_blur_mesh_data_free(void *val)
{
- EEVEE_GeometryMotionData *geom_mb = (EEVEE_GeometryMotionData *)val;
- EEVEE_HairMotionData *hair_mb = (EEVEE_HairMotionData *)val;
- switch (geom_mb->type) {
- case EEVEE_MOTION_DATA_HAIR:
- for (int j = 0; j < hair_mb->psys_len; j++) {
- for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
- GPU_VERTBUF_DISCARD_SAFE(hair_mb->psys[j].hair_pos[i]);
- }
- for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
- DRW_TEXTURE_FREE_SAFE(hair_mb->psys[j].hair_pos_tx[i]);
- }
- }
- break;
-
- case EEVEE_MOTION_DATA_MESH:
- for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
- GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
- }
- break;
+ EEVEE_ObjectMotionData *mb_data = (EEVEE_ObjectMotionData *)val;
+ if (mb_data->hair_data != NULL) {
+ MEM_freeN(mb_data->hair_data);
+ }
+ if (mb_data->geometry_data != NULL) {
+ MEM_freeN(mb_data->geometry_data);
}
MEM_freeN(val);
}
@@ -84,39 +71,59 @@ static bool eevee_object_key_cmp(const void *a, const void *b)
return false;
}
+void EEVEE_motion_hair_step_free(EEVEE_HairMotionStepData *step_data)
+{
+ GPU_vertbuf_discard(step_data->hair_pos);
+ DRW_texture_free(step_data->hair_pos_tx);
+ MEM_freeN(step_data);
+}
+
void EEVEE_motion_blur_data_init(EEVEE_MotionBlurData *mb)
{
if (mb->object == NULL) {
mb->object = BLI_ghash_new(eevee_object_key_hash, eevee_object_key_cmp, "EEVEE Object Motion");
}
- if (mb->geom == NULL) {
- mb->geom = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE Mesh Motion");
+ for (int i = 0; i < 2; i++) {
+ if (mb->position_vbo_cache[i] == NULL) {
+ mb->position_vbo_cache[i] = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE duplicate vbo cache");
+ }
+ if (mb->hair_motion_step_cache[i] == NULL) {
+ mb->hair_motion_step_cache[i] = BLI_ghash_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE hair motion step cache");
+ }
}
}
void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb)
{
if (mb->object) {
- BLI_ghash_free(mb->object, MEM_freeN, MEM_freeN);
+ BLI_ghash_free(mb->object, MEM_freeN, eevee_motion_blur_mesh_data_free);
mb->object = NULL;
}
- if (mb->geom) {
- BLI_ghash_free(mb->geom, NULL, eevee_motion_blur_mesh_data_free);
- mb->geom = NULL;
+ for (int i = 0; i < 2; i++) {
+ if (mb->position_vbo_cache[i]) {
+ BLI_ghash_free(mb->position_vbo_cache[i], NULL, (GHashValFreeFP)GPU_vertbuf_discard);
+ mb->position_vbo_cache[i] = NULL;
+ }
+ if (mb->hair_motion_step_cache[i]) {
+ BLI_ghash_free(
+ mb->hair_motion_step_cache[i], NULL, (GHashValFreeFP)EEVEE_motion_hair_step_free);
+ mb->hair_motion_step_cache[i] = NULL;
+ }
}
}
-EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb,
- Object *ob,
- bool hair)
+EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob)
{
if (mb->object == NULL) {
return NULL;
}
EEVEE_ObjectKey key, *key_p;
- /* Small hack to avoid another comparison. */
- key.ob = (Object *)((char *)ob + hair);
+ /* Assumes that all instances have the same object pointer. This is currently the case because
+ * instance objects are temporary objects on the stack. */
+ key.ob = ob;
DupliObject *dup = DRW_object_get_dupli(ob);
if (dup) {
key.parent = DRW_object_get_dupli_parent(ob);
@@ -139,53 +146,28 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *
return ob_step;
}
-static void *motion_blur_deform_data_get(EEVEE_MotionBlurData *mb, Object *ob, bool hair)
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_ObjectMotionData *mb_data)
{
- if (mb->geom == NULL) {
- return NULL;
+ if (mb_data->geometry_data == NULL) {
+ EEVEE_GeometryMotionData *geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
+ geom_step->type = EEVEE_MOTION_DATA_MESH;
+ mb_data->geometry_data = geom_step;
}
- DupliObject *dup = DRW_object_get_dupli(ob);
- void *key;
- if (dup) {
- key = dup->ob;
- }
- else {
- key = ob;
- }
- /* Only use data for object that have no modifiers. */
- if (!BKE_object_is_modified(DRW_context_state_get()->scene, ob)) {
- key = ob->data;
- }
- key = (char *)key + (int)hair;
- EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key);
- if (geom_step == NULL) {
- if (hair) {
- EEVEE_HairMotionData *hair_step;
- /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
- int psys_len = (ob->type != OB_CURVES) ? BLI_listbase_count(&ob->modifiers) : 1;
- hair_step = MEM_callocN(sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len,
- __func__);
- hair_step->psys_len = psys_len;
- geom_step = (EEVEE_GeometryMotionData *)hair_step;
- geom_step->type = EEVEE_MOTION_DATA_HAIR;
- }
- else {
- geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
- geom_step->type = EEVEE_MOTION_DATA_MESH;
- }
- BLI_ghash_insert(mb->geom, key, geom_step);
- }
- return geom_step;
+ return mb_data->geometry_data;
}
-EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, Object *ob)
+EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb_data, Object *ob)
{
- return motion_blur_deform_data_get(mb, ob, false);
-}
-
-EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, Object *ob)
-{
- return motion_blur_deform_data_get(mb, ob, true);
+ if (mb_data->hair_data == NULL) {
+ /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
+ int psys_len = (ob->type != OB_CURVES) ? BLI_listbase_count(&ob->modifiers) : 1;
+ EEVEE_HairMotionData *hair_step = MEM_callocN(
+ sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len, __func__);
+ hair_step->psys_len = psys_len;
+ hair_step->type = EEVEE_MOTION_DATA_HAIR;
+ mb_data->hair_data = hair_step;
+ }
+ return mb_data->hair_data;
}
/* View Layer data. */
diff --git a/source/blender/draw/engines/image/image_drawing_mode.hh b/source/blender/draw/engines/image/image_drawing_mode.hh
index ccedff4d1e3..a1cd110e1d8 100644
--- a/source/blender/draw/engines/image/image_drawing_mode.hh
+++ b/source/blender/draw/engines/image/image_drawing_mode.hh
@@ -479,6 +479,9 @@ template<typename TextureMethod> class ScreenSpaceDrawingMode : public AbstractD
method.update_screen_space_bounds(region);
method.update_screen_uv_bounds();
+ /* Check for changes in the image user compared to the last time. */
+ instance_data->update_image_usage(iuser);
+
/* Step: Update the GPU textures based on the changes in the image. */
instance_data->update_gpu_texture_allocations();
update_textures(*instance_data, image, iuser);
diff --git a/source/blender/draw/engines/image/image_space.hh b/source/blender/draw/engines/image/image_space.hh
index 7a11d14b567..03973d892df 100644
--- a/source/blender/draw/engines/image/image_space.hh
+++ b/source/blender/draw/engines/image/image_space.hh
@@ -10,10 +10,10 @@
struct ShaderParameters;
/**
- * Space accessor.
+ * Space accessor.
*
- * Image engine is used to draw the images inside multiple spaces \see SpaceLink.
- * The AbstractSpaceAccessor is an interface to communicate with a space.
+ * Image engine is used to draw the images inside multiple spaces \see SpaceLink.
+ * The #AbstractSpaceAccessor is an interface to communicate with a space.
*/
class AbstractSpaceAccessor {
public:
diff --git a/source/blender/draw/engines/overlay/overlay_grid.c b/source/blender/draw/engines/overlay/overlay_grid.c
index 20403f156a1..ed6db459696 100644
--- a/source/blender/draw/engines/overlay/overlay_grid.c
+++ b/source/blender/draw/engines/overlay/overlay_grid.c
@@ -49,20 +49,29 @@ void OVERLAY_grid_init(OVERLAY_Data *vedata)
if (pd->space_type == SPACE_IMAGE) {
SpaceImage *sima = (SpaceImage *)draw_ctx->space_data;
View2D *v2d = &draw_ctx->region->v2d;
- if (sima->mode == SI_MODE_UV || !ED_space_image_has_buffer(sima)) {
- shd->grid_flag = GRID_BACK | PLANE_IMAGE | SHOW_GRID;
- }
- else {
- shd->grid_flag = 0;
+
+ /* Only UV Edit mode has the various Overlay options for now. */
+ const bool is_uv_edit = sima->mode == SI_MODE_UV;
+
+ const bool background_enabled = is_uv_edit ? (!pd->hide_overlays &&
+ (sima->overlay.flag &
+ SI_OVERLAY_SHOW_GRID_BACKGROUND) != 0) :
+ true;
+ if (background_enabled) {
+ shd->grid_flag = GRID_BACK | PLANE_IMAGE;
}
- if (sima->flag & SI_CUSTOM_GRID) {
- shd->grid_flag |= CUSTOM_GRID;
+ const bool draw_grid = is_uv_edit || !ED_space_image_has_buffer(sima);
+ if (background_enabled && draw_grid) {
+ shd->grid_flag |= SHOW_GRID;
+ if (is_uv_edit && (sima->flag & SI_CUSTOM_GRID) != 0) {
+ shd->grid_flag |= CUSTOM_GRID;
+ }
}
shd->grid_distance = 1.0f;
copy_v3_fl3(shd->grid_size, 1.0f, 1.0f, 1.0f);
- if (sima->mode == SI_MODE_UV) {
+ if (is_uv_edit) {
shd->grid_size[0] = (float)sima->tile_grid_shape[0];
shd->grid_size[1] = (float)sima->tile_grid_shape[1];
}
diff --git a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
index d3766da23cf..e2a54788c72 100644
--- a/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
+++ b/source/blender/draw/engines/workbench/shaders/infos/workbench_prepass_info.hh
@@ -92,7 +92,7 @@ GPU_SHADER_CREATE_INFO(workbench_material)
GPU_SHADER_CREATE_INFO(workbench_transparent_accum)
/* Note: Blending will be skipped on objectId because output is a
- non-normalized integer buffer. */
+ * non-normalized integer buffer. */
.fragment_out(0, Type::VEC4, "transparentAccum")
.fragment_out(1, Type::VEC4, "revealageAccum")
.fragment_out(2, Type::UINT, "objectId")
diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
index 59aa4bc7683..2653035a39f 100644
--- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc
+++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc
@@ -518,6 +518,11 @@ static void draw_patch_map_free(DRWPatchMap *gpu_patch_map)
/** \name DRWSubdivCache
* \{ */
+static bool draw_subdiv_cache_need_polygon_data(const DRWSubdivCache *cache)
+{
+ return cache->subdiv && cache->subdiv->evaluator && cache->num_subdiv_loops != 0;
+}
+
static void draw_subdiv_cache_free_material_data(DRWSubdivCache *cache)
{
GPU_VERTBUF_DISCARD_SAFE(cache->polygon_mat_offset);
@@ -551,6 +556,7 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
cache->num_subdiv_triangles = 0;
cache->num_coarse_poly = 0;
cache->num_subdiv_quads = 0;
+ cache->may_have_loose_geom = false;
draw_subdiv_free_edit_mode_cache(cache);
draw_subdiv_cache_free_material_data(cache);
draw_patch_map_free(&cache->gpu_patch_map);
@@ -558,6 +564,11 @@ void draw_subdiv_cache_free(DRWSubdivCache *cache)
GPU_uniformbuf_free(cache->ubo);
cache->ubo = nullptr;
}
+ MEM_SAFE_FREE(cache->loose_geom.edges);
+ MEM_SAFE_FREE(cache->loose_geom.verts);
+ cache->loose_geom.edge_len = 0;
+ cache->loose_geom.vert_len = 0;
+ cache->loose_geom.loop_len = 0;
}
/* Flags used in #DRWSubdivCache.extra_coarse_face_data. The flags are packed in the upper bits of
@@ -734,19 +745,25 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
const int num_polygons,
const int *subdiv_polygon_offset)
{
- if (num_loops == 0) {
+ /* num_loops does not take into account meshes with only loose geometry, which might be meshes
+ * used as custom bone shapes, so let's check the num_vertices also. */
+ if (num_vertices == 0 && num_loops == 0) {
return false;
}
DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
DRWSubdivCache *cache = ctx->cache;
- /* Set topology information. */
- cache->num_subdiv_edges = (uint)num_edges;
- cache->num_subdiv_loops = (uint)num_loops;
- cache->num_subdiv_verts = (uint)num_vertices;
- cache->num_subdiv_quads = (uint)num_polygons;
- cache->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset));
+ /* Set topology information only if we have loops. */
+ if (num_loops != 0) {
+ cache->num_subdiv_edges = (uint)num_edges;
+ cache->num_subdiv_loops = (uint)num_loops;
+ cache->num_subdiv_verts = (uint)num_vertices;
+ cache->num_subdiv_quads = (uint)num_polygons;
+ cache->subdiv_polygon_offset = static_cast<int *>(MEM_dupallocN(subdiv_polygon_offset));
+ }
+
+ cache->may_have_loose_geom = num_vertices != 0 || num_edges != 0;
/* Initialize cache buffers, prefer dynamic usage so we can reuse memory on the host even after
* it was sent to the device, since we may use the data while building other buffers on the CPU
@@ -789,16 +806,20 @@ static bool draw_subdiv_topology_info_cb(const SubdivForeachContext *foreach_con
ctx->e_origindex = static_cast<int *>(
CustomData_get_layer(&ctx->coarse_mesh->edata, CD_ORIGINDEX));
- ctx->vert_origindex_map = static_cast<int *>(
- MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map"));
- for (int i = 0; i < num_vertices; i++) {
- ctx->vert_origindex_map[i] = -1;
+ if (cache->num_subdiv_verts) {
+ ctx->vert_origindex_map = static_cast<int *>(
+ MEM_mallocN(cache->num_subdiv_verts * sizeof(int), "subdiv_vert_origindex_map"));
+ for (int i = 0; i < num_vertices; i++) {
+ ctx->vert_origindex_map[i] = -1;
+ }
}
- ctx->edge_origindex_map = static_cast<int *>(
- MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map"));
- for (int i = 0; i < num_edges; i++) {
- ctx->edge_origindex_map[i] = -1;
+ if (cache->num_subdiv_edges) {
+ ctx->edge_origindex_map = static_cast<int *>(
+ MEM_mallocN(cache->num_subdiv_edges * sizeof(int), "subdiv_edge_origindex_map"));
+ for (int i = 0; i < num_edges; i++) {
+ ctx->edge_origindex_map[i] = -1;
+ }
}
return true;
@@ -842,6 +863,10 @@ static void draw_subdiv_edge_cb(const SubdivForeachContext *foreach_context,
{
DRWCacheBuildingContext *ctx = (DRWCacheBuildingContext *)(foreach_context->user_data);
+ if (!ctx->edge_origindex_map) {
+ return;
+ }
+
int coarse_index = coarse_edge_index;
if (coarse_index != -1) {
@@ -991,7 +1016,8 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
cache_building_context.cache = cache;
do_subdiv_traversal(&cache_building_context, subdiv);
- if (cache->num_subdiv_loops == 0) {
+ if (cache->num_subdiv_loops == 0 && cache->num_subdiv_verts == 0 &&
+ !cache->may_have_loose_geom) {
/* Either the traversal failed, or we have an empty mesh, either way we cannot go any further.
* The subdiv_polygon_offset cannot then be reliably stored in the cache, so free it directly.
*/
@@ -999,44 +1025,47 @@ static bool draw_subdiv_build_cache(DRWSubdivCache *cache,
return false;
}
- /* Build buffers for the PatchMap. */
- draw_patch_map_build(&cache->gpu_patch_map, subdiv);
+ /* Only build polygon related data if we have polygons. */
+ if (cache->num_subdiv_loops != 0) {
+ /* Build buffers for the PatchMap. */
+ draw_patch_map_build(&cache->gpu_patch_map, subdiv);
+
+ cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
+
+ /* Build patch coordinates for all the face dots. */
+ cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
+ mesh_eval->totpoly);
+ CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)
+ GPU_vertbuf_get_data(cache->fdots_patch_coords);
+ for (int i = 0; i < mesh_eval->totpoly; i++) {
+ const int ptex_face_index = cache->face_ptex_offset[i];
+ if (mesh_eval->mpoly[i].totloop == 4) {
+ /* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */
+ blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f);
+ }
+ else {
+ /* For N-gons, since they are split into quads from the center, and since the center is
+ * chosen to be the top right corner of each quad, the center coordinate of the coarse face
+ * is any one of those top right corners with `u = v = 1.0`. */
+ blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f);
+ }
+ }
- cache->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
+ cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer(
+ cache->subdiv_polygon_offset, mesh_eval->totpoly);
- /* Build patch coordinates for all the face dots. */
- cache->fdots_patch_coords = gpu_vertbuf_create_from_format(get_blender_patch_coords_format(),
- mesh_eval->totpoly);
- CompressedPatchCoord *blender_fdots_patch_coords = (CompressedPatchCoord *)GPU_vertbuf_get_data(
- cache->fdots_patch_coords);
- for (int i = 0; i < mesh_eval->totpoly; i++) {
- const int ptex_face_index = cache->face_ptex_offset[i];
- if (mesh_eval->mpoly[i].totloop == 4) {
- /* For quads, the center coordinate of the coarse face has `u = v = 0.5`. */
- blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 0.5f, 0.5f);
- }
- else {
- /* For N-gons, since they are split into quads from the center, and since the center is
- * chosen to be the top right corner of each quad, the center coordinate of the coarse face
- * is any one of those top right corners with `u = v = 1.0`. */
- blender_fdots_patch_coords[i] = make_patch_coord(ptex_face_index, 1.0f, 1.0f);
- }
+ cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
+ mesh_eval->totpoly + 1);
+
+ build_vertex_face_adjacency_maps(cache);
}
cache->resolution = to_mesh_settings.resolution;
-
- cache->subdiv_polygon_offset_buffer = draw_subdiv_build_origindex_buffer(
- cache->subdiv_polygon_offset, mesh_eval->totpoly);
-
- cache->face_ptex_offset_buffer = draw_subdiv_build_origindex_buffer(cache->face_ptex_offset,
- mesh_eval->totpoly + 1);
cache->num_coarse_poly = mesh_eval->totpoly;
- build_vertex_face_adjacency_maps(cache);
-
/* Cleanup. */
- MEM_freeN(cache_building_context.vert_origindex_map);
- MEM_freeN(cache_building_context.edge_origindex_map);
+ MEM_SAFE_FREE(cache_building_context.vert_origindex_map);
+ MEM_SAFE_FREE(cache_building_context.edge_origindex_map);
return true;
}
@@ -1192,6 +1221,11 @@ static void drw_subdiv_compute_dispatch(const DRWSubdivCache *cache,
void draw_subdiv_extract_pos_nor(const DRWSubdivCache *cache, GPUVertBuf *pos_nor)
{
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
Subdiv *subdiv = cache->subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
@@ -1251,6 +1285,11 @@ void draw_subdiv_extract_uvs(const DRWSubdivCache *cache,
const int face_varying_channel,
const int dst_offset)
{
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
Subdiv *subdiv = cache->subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
@@ -1484,6 +1523,11 @@ void draw_subdiv_build_tris_buffer(const DRWSubdivCache *cache,
GPUIndexBuf *subdiv_tris,
const int material_count)
{
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
const bool do_single_material = material_count <= 1;
const char *defines = "#define SUBDIV_POLYGON_OFFSET\n";
@@ -1527,6 +1571,11 @@ void draw_subdiv_build_fdots_buffers(const DRWSubdivCache *cache,
GPUVertBuf *fdots_nor,
GPUIndexBuf *fdots_indices)
{
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
Subdiv *subdiv = cache->subdiv;
OpenSubdiv_Evaluator *evaluator = subdiv->evaluator;
@@ -1651,6 +1700,11 @@ void draw_subdiv_build_lnor_buffer(const DRWSubdivCache *cache,
GPUVertBuf *pos_nor,
GPUVertBuf *lnor)
{
+ if (!draw_subdiv_cache_need_polygon_data(cache)) {
+ /* Happens on meshes with only loose geometry. */
+ return;
+ }
+
GPUShader *shader = get_subdiv_shader(SHADER_BUFFER_LNOR, "#define SUBDIV_POLYGON_OFFSET\n");
GPU_shader_bind(shader);
@@ -1839,9 +1893,9 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
- const bool UNUSED(use_subsurf_fdots),
+ const bool /*use_subsurf_fdots*/,
const ToolSettings *ts,
- const bool UNUSED(use_hide),
+ const bool /*use_hide*/,
OpenSubdiv_EvaluatorCache *evaluator_cache)
{
SubsurfModifierData *smd = BKE_object_get_last_subsurf_modifier(ob);
@@ -1872,7 +1926,15 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
if (!BKE_subdiv_eval_begin_from_mesh(
subdiv, mesh_eval, nullptr, SUBDIV_EVALUATOR_TYPE_GLSL_COMPUTE, evaluator_cache)) {
- return false;
+ /* This could happen in two situations:
+ * - OpenSubdiv is disabled.
+ * - Something totally bad happened, and OpenSubdiv rejected our
+ * topology.
+ * In either way, we can't safely continue. However, we still have to handle potential loose
+ * geometry, which is done separately. */
+ if (mesh_eval->totpoly) {
+ return false;
+ }
}
DRWSubdivCache *draw_cache = mesh_batch_cache_ensure_subdiv_cache(batch_cache);
@@ -1909,6 +1971,104 @@ static bool draw_subdiv_create_requested_buffers(const Scene *scene,
return true;
}
+void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cache)
+{
+ const int coarse_loose_vert_len = cache->loose_geom.vert_len;
+ const int coarse_loose_edge_len = cache->loose_geom.edge_len;
+
+ if (coarse_loose_vert_len == 0 && coarse_loose_edge_len == 0) {
+ /* Nothing to do. */
+ return;
+ }
+
+ if (subdiv_cache->loose_geom.edges || subdiv_cache->loose_geom.verts) {
+ /* Already processed. */
+ return;
+ }
+
+ const Mesh *coarse_mesh = subdiv_cache->mesh;
+ const bool is_simple = subdiv_cache->subdiv->settings.is_simple;
+ const int resolution = subdiv_cache->resolution;
+ const int resolution_1 = resolution - 1;
+ const float inv_resolution_1 = 1.0f / (float)resolution_1;
+ const int num_subdiv_vertices_per_coarse_edge = resolution - 2;
+
+ const int num_subdivided_edge = coarse_loose_edge_len *
+ (num_subdiv_vertices_per_coarse_edge + 1);
+
+ /* Each edge will store data for its 2 verts, that way we can keep the overall logic simple, here
+ * and in the buffer extractors. Although it duplicates memory (and work), the buffers also store
+ * duplicate values. */
+ const int num_subdivided_verts = num_subdivided_edge * 2;
+
+ DRWSubdivLooseEdge *loose_subd_edges = static_cast<DRWSubdivLooseEdge *>(
+ MEM_callocN(sizeof(DRWSubdivLooseEdge) * num_subdivided_edge, "DRWSubdivLooseEdge"));
+
+ DRWSubdivLooseVertex *loose_subd_verts = static_cast<DRWSubdivLooseVertex *>(
+ MEM_callocN(sizeof(DRWSubdivLooseVertex) * (num_subdivided_verts + coarse_loose_vert_len),
+ "DRWSubdivLooseEdge"));
+
+ int subd_edge_offset = 0;
+ int subd_vert_offset = 0;
+
+ /* Subdivide each loose coarse edge. */
+ for (int i = 0; i < coarse_loose_edge_len; i++) {
+ const int coarse_edge_index = cache->loose_geom.edges[i];
+ const MEdge *coarse_edge = &coarse_mesh->medge[cache->loose_geom.edges[i]];
+
+ /* Perform interpolation of each vertex. */
+ for (int i = 0; i < resolution - 1; i++, subd_edge_offset++) {
+ DRWSubdivLooseEdge &subd_edge = loose_subd_edges[subd_edge_offset];
+ subd_edge.coarse_edge_index = coarse_edge_index;
+
+ /* First vert. */
+ DRWSubdivLooseVertex &subd_v1 = loose_subd_verts[subd_vert_offset];
+ subd_v1.coarse_vertex_index = (i == 0) ? coarse_edge->v1 : -1u;
+ const float u1 = i * inv_resolution_1;
+ BKE_subdiv_mesh_interpolate_position_on_edge(
+ coarse_mesh, coarse_edge, is_simple, u1, subd_v1.co);
+
+ subd_edge.loose_subdiv_v1_index = subd_vert_offset++;
+
+ /* Second vert. */
+ DRWSubdivLooseVertex &subd_v2 = loose_subd_verts[subd_vert_offset];
+ subd_v2.coarse_vertex_index = ((i + 1) == resolution - 1) ? coarse_edge->v2 : -1u;
+ const float u2 = (i + 1) * inv_resolution_1;
+ BKE_subdiv_mesh_interpolate_position_on_edge(
+ coarse_mesh, coarse_edge, is_simple, u2, subd_v2.co);
+
+ subd_edge.loose_subdiv_v2_index = subd_vert_offset++;
+ }
+ }
+
+ /* Copy the remaining loose_verts. */
+ for (int i = 0; i < coarse_loose_vert_len; i++) {
+ const int coarse_vertex_index = cache->loose_geom.verts[i];
+ const MVert &coarse_vertex = coarse_mesh->mvert[coarse_vertex_index];
+
+ DRWSubdivLooseVertex &subd_v = loose_subd_verts[subd_vert_offset++];
+ subd_v.coarse_vertex_index = cache->loose_geom.verts[i];
+ copy_v3_v3(subd_v.co, coarse_vertex.co);
+ }
+
+ subdiv_cache->loose_geom.edges = loose_subd_edges;
+ subdiv_cache->loose_geom.verts = loose_subd_verts;
+ subdiv_cache->loose_geom.edge_len = num_subdivided_edge;
+ subdiv_cache->loose_geom.vert_len = coarse_loose_vert_len;
+ subdiv_cache->loose_geom.loop_len = num_subdivided_edge * 2 + coarse_loose_vert_len;
+}
+
+blender::Span<DRWSubdivLooseEdge> draw_subdiv_cache_get_loose_edges(const DRWSubdivCache *cache)
+{
+ return {cache->loose_geom.edges, static_cast<int64_t>(cache->loose_geom.edge_len)};
+}
+
+blender::Span<DRWSubdivLooseVertex> draw_subdiv_cache_get_loose_verts(const DRWSubdivCache *cache)
+{
+ return {cache->loose_geom.verts + cache->loose_geom.edge_len * 2,
+ static_cast<int64_t>(cache->loose_geom.vert_len)};
+}
+
static OpenSubdiv_EvaluatorCache *g_evaluator_cache = nullptr;
void DRW_create_subdivision(const Scene *scene,
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index cf04cdba859..0efa32ec63a 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -8,20 +8,20 @@
* ====================
*
* - Push & Relax, Breakdowner
-
+ *
* These tools provide the animator with various capabilities
* for interactively controlling the spacing of poses, but also
* for 'pushing' and/or 'relaxing' extremes as they see fit.
*
* - Propagate
-
+ *
* This tool copies elements of the selected pose to successive
* keyframes, allowing the animator to go back and modify the poses
* for some "static" pose controls, without having to repeatedly
* doing a "next paste" dance.
*
* - Pose Sculpting (TODO)
-
+ *
* This is yet to be implemented, but the idea here is to use
* sculpting techniques to make it easier to pose rigs by allowing
* rigs to be manipulated using a familiar paint-based interface.
diff --git a/source/blender/editors/asset/intern/asset_list.cc b/source/blender/editors/asset/intern/asset_list.cc
index 4941e11a7b3..55167c1ed2d 100644
--- a/source/blender/editors/asset/intern/asset_list.cc
+++ b/source/blender/editors/asset/intern/asset_list.cc
@@ -41,7 +41,7 @@ namespace blender::ed::asset {
/* -------------------------------------------------------------------- */
/** \name Asset list API
*
- * Internally re-uses #FileList from the File Browser. It does all the heavy lifting already.
+ * Internally re-uses #FileList from the File Browser. It does all the heavy lifting already.
* \{ */
/**
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 9df8c099819..3f06dbfdbb3 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -1239,7 +1239,7 @@ static bool contract_shape(ImBuf *ibuf)
const float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const int max_size = (ibuf->x * ibuf->y) - 1;
- /* Detect if pixel is near of no green pixels and mark green to be cleared. */
+ /* Detect if pixel is near of no green pixels and mark green pixel to be cleared. */
for (int row = 0; row < ibuf->y; row++) {
if (!is_row_filled(ibuf, row)) {
continue;
diff --git a/source/blender/editors/gpencil/gpencil_sculpt_paint.c b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
index 7de579993c1..3cdf364e4b2 100644
--- a/source/blender/editors/gpencil/gpencil_sculpt_paint.c
+++ b/source/blender/editors/gpencil/gpencil_sculpt_paint.c
@@ -1627,7 +1627,7 @@ static bool gpencil_sculpt_brush_do_frame(bContext *C,
*/
gpencil_brush_grab_stroke_init(gso, gps_active);
changed |= gpencil_sculpt_brush_do_stroke(
- gso, gps_active, diff_mat, gpencil_brush_grab_store_points);
+ gso, gps_active, bound_mat, gpencil_brush_grab_store_points);
}
else {
/* Apply effect to the stored points */
diff --git a/source/blender/editors/include/ED_paint.h b/source/blender/editors/include/ED_paint.h
index 6b015895b60..cd28fbe9687 100644
--- a/source/blender/editors/include/ED_paint.h
+++ b/source/blender/editors/include/ED_paint.h
@@ -12,6 +12,7 @@
extern "C" {
#endif
+struct bToolRef;
struct PaintModeSettings;
struct ImBuf;
struct Image;
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 40a57a321d8..4c01c75e06c 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -325,7 +325,7 @@ struct UVPackIsland_Params {
};
/**
- * Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image.
+ * Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image.
*/
bool uv_coords_isect_udim(const struct Image *image,
const int udim_grid[2],
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index ad5aeb1c29f..05acdac3597 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -1028,7 +1028,7 @@ void ui_draw_but_CURVE(struct ARegion *region,
const struct uiWidgetColors *wcol,
const rcti *rect);
/**
- * Draws the curve profile widget. Somewhat similar to ui_draw_but_CURVE.
+ * Draws the curve profile widget. Somewhat similar to ui_draw_but_CURVE.
*/
void ui_draw_but_CURVEPROFILE(struct ARegion *region,
uiBut *but,
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c
index d93edd2776b..d469efbd0a1 100644
--- a/source/blender/editors/object/object_bake.c
+++ b/source/blender/editors/object/object_bake.c
@@ -359,7 +359,12 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
/* copy data stored in job descriptor */
bkr.scene = scene;
bkr.bake_margin = scene->r.bake_margin;
- bkr.bake_margin_type = scene->r.bake_margin_type;
+ if (scene->r.bake_mode == RE_BAKE_NORMALS) {
+ bkr.bake_margin_type = R_BAKE_EXTEND;
+ }
+ else {
+ bkr.bake_margin_type = scene->r.bake_margin_type;
+ }
bkr.mode = scene->r.bake_mode;
bkr.use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
bkr.bias = scene->r.bake_biasdist;
@@ -404,7 +409,12 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
/* backup scene settings, so their changing in UI would take no effect on baker */
bkj->scene = scene;
bkj->bake_margin = scene->r.bake_margin;
- bkj->bake_margin_type = scene->r.bake_margin_type;
+ if (scene->r.bake_mode == RE_BAKE_NORMALS) {
+ bkj->bake_margin_type = R_BAKE_EXTEND;
+ }
+ else {
+ bkj->bake_margin_type = scene->r.bake_margin_type;
+ }
bkj->mode = scene->r.bake_mode;
bkj->use_lores_mesh = scene->r.bake_flag & R_BAKE_LORES_MESH;
bkj->bake_clear = scene->r.bake_flag & R_BAKE_CLEAR;
diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c
index fec87fbfa95..3060a1ecf62 100644
--- a/source/blender/editors/object/object_bake_api.c
+++ b/source/blender/editors/object/object_bake_api.c
@@ -1670,6 +1670,11 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr)
if (bkr->save_mode == R_BAKE_SAVE_EXTERNAL) {
bkr->save_mode = R_BAKE_SAVE_INTERNAL;
}
+
+ if (((bkr->pass_type == SCE_PASS_NORMAL) && (bkr->normal_space == R_BAKE_SPACE_TANGENT)) ||
+ bkr->pass_type == SCE_PASS_UV) {
+ bkr->margin_type = R_BAKE_EXTEND;
+ }
}
static int bake_exec(bContext *C, wmOperator *op)
diff --git a/source/blender/editors/render/render_intern.hh b/source/blender/editors/render/render_intern.hh
index 85d917ae8e8..a4056f3dab3 100644
--- a/source/blender/editors/render/render_intern.hh
+++ b/source/blender/editors/render/render_intern.hh
@@ -35,6 +35,8 @@ void SCENE_OT_view_layer_add_aov(struct wmOperatorType *ot);
void SCENE_OT_view_layer_remove_aov(struct wmOperatorType *ot);
void SCENE_OT_view_layer_add_lightgroup(struct wmOperatorType *ot);
void SCENE_OT_view_layer_remove_lightgroup(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_add_used_lightgroups(struct wmOperatorType *ot);
+void SCENE_OT_view_layer_remove_unused_lightgroups(struct wmOperatorType *ot);
void SCENE_OT_light_cache_bake(struct wmOperatorType *ot);
void SCENE_OT_light_cache_free(struct wmOperatorType *ot);
diff --git a/source/blender/editors/render/render_ops.cc b/source/blender/editors/render/render_ops.cc
index f671b2f950d..def220fb4fc 100644
--- a/source/blender/editors/render/render_ops.cc
+++ b/source/blender/editors/render/render_ops.cc
@@ -41,6 +41,8 @@ void ED_operatortypes_render()
WM_operatortype_append(SCENE_OT_view_layer_remove_aov);
WM_operatortype_append(SCENE_OT_view_layer_add_lightgroup);
WM_operatortype_append(SCENE_OT_view_layer_remove_lightgroup);
+ WM_operatortype_append(SCENE_OT_view_layer_add_used_lightgroups);
+ WM_operatortype_append(SCENE_OT_view_layer_remove_unused_lightgroups);
WM_operatortype_append(SCENE_OT_render_view_add);
WM_operatortype_append(SCENE_OT_render_view_remove);
diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc
index 4c885d50b4c..f5bd60df2b4 100644
--- a/source/blender/editors/render/render_shading.cc
+++ b/source/blender/editors/render/render_shading.cc
@@ -1217,6 +1217,114 @@ void SCENE_OT_view_layer_remove_lightgroup(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name View Layer Add Used Lightgroups Operator
+ * \{ */
+
+static GSet *get_used_lightgroups(Scene *scene)
+{
+ GSet *used_lightgroups = BLI_gset_str_new(__func__);
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
+ if (ob->lightgroup && ob->lightgroup->name[0]) {
+ BLI_gset_add(used_lightgroups, ob->lightgroup->name);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ if (scene->world && scene->world->lightgroup && scene->world->lightgroup->name[0]) {
+ BLI_gset_add(used_lightgroups, scene->world->lightgroup->name);
+ }
+
+ return used_lightgroups;
+}
+
+static int view_layer_add_used_lightgroups_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ GSet *used_lightgroups = get_used_lightgroups(scene);
+ GSET_FOREACH_BEGIN (const char *, used_lightgroup, used_lightgroups) {
+ if (!BLI_findstring(
+ &view_layer->lightgroups, used_lightgroup, offsetof(ViewLayerLightgroup, name))) {
+ BKE_view_layer_add_lightgroup(view_layer, used_lightgroup);
+ }
+ }
+ GSET_FOREACH_END();
+ BLI_gset_free(used_lightgroups, nullptr);
+
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_view_layer_add_used_lightgroups(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Used Lightgroups";
+ ot->idname = "SCENE_OT_view_layer_add_used_lightgroups";
+ ot->description = "Add all used Light Groups";
+
+ /* api callbacks */
+ ot->exec = view_layer_add_used_lightgroups_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Layer Remove Unused Lightgroups Operator
+ * \{ */
+
+static int view_layer_remove_unused_lightgroups_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ GSet *used_lightgroups = get_used_lightgroups(scene);
+ LISTBASE_FOREACH_MUTABLE (ViewLayerLightgroup *, lightgroup, &view_layer->lightgroups) {
+ if (!BLI_gset_haskey(used_lightgroups, lightgroup->name)) {
+ BKE_view_layer_remove_lightgroup(view_layer, lightgroup);
+ }
+ }
+ BLI_gset_free(used_lightgroups, nullptr);
+
+ if (scene->nodetree) {
+ ntreeCompositUpdateRLayers(scene->nodetree);
+ }
+
+ DEG_id_tag_update(&scene->id, 0);
+ DEG_relations_tag_update(CTX_data_main(C));
+ WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SCENE_OT_view_layer_remove_unused_lightgroups(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Unused Lightgroups";
+ ot->idname = "SCENE_OT_view_layer_remove_unused_lightgroups";
+ ot->description = "Remove all unused Light Groups";
+
+ /* api callbacks */
+ ot->exec = view_layer_remove_unused_lightgroups_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Light Cache Bake Operator
* \{ */
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 50b994be710..30bf23e0987 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -3443,7 +3443,6 @@ ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int x
{
bScreen *screen = CTX_wm_screen(C);
wmWindow *win = CTX_wm_window(C);
- wmWindowManager *wm = CTX_wm_manager(C);
ScrArea *area = NULL;
@@ -3455,8 +3454,8 @@ ScrArea *ED_area_find_under_cursor(const bContext *C, int spacetype, const int x
if (!area) {
/* Check all windows except the active one. */
int scr_pos[2];
- wmWindow *r_win = WM_window_find_under_cursor(wm, win, win, xy, scr_pos);
- if (r_win) {
+ wmWindow *r_win = WM_window_find_under_cursor(win, xy, scr_pos);
+ if (r_win && r_win != win) {
win = r_win;
screen = WM_window_get_active_screen(win);
area = BKE_screen_find_area_xy(screen, spacetype, scr_pos);
diff --git a/source/blender/editors/sculpt_paint/paint_canvas.cc b/source/blender/editors/sculpt_paint/paint_canvas.cc
index 9a1a61cf3ab..5683e3ff741 100644
--- a/source/blender/editors/sculpt_paint/paint_canvas.cc
+++ b/source/blender/editors/sculpt_paint/paint_canvas.cc
@@ -19,6 +19,8 @@
#include "WM_toolsystem.h"
+#include "ED_paint.h"
+
namespace blender::ed::sculpt_paint::canvas {
static TexPaintSlot *get_active_slot(Object *ob)
{
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 73fc5bd68f3..38905b50c59 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -201,13 +201,11 @@ struct SculptRakeData {
float follow_co[3];
};
-/*
-Generic thread data. The size of this struct
-has gotten a little out of hand; normally we would
-split it up, but it might be better to see if we can't
-eliminate it altogether after moving to C++ (where
-we'll be able to use lambdas).
-*/
+/**
+ * Generic thread data. The size of this struct has gotten a little out of hand;
+ * normally we would split it up, but it might be better to see if we can't eliminate it
+ * altogether after moving to C++ (where we'll be able to use lambdas).
+ */
typedef struct SculptThreadedTaskData {
struct bContext *C;
struct Sculpt *sd;
diff --git a/source/blender/editors/sculpt_paint/sculpt_paint_color.c b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
index fe83fade055..e7a713efa14 100644
--- a/source/blender/editors/sculpt_paint/sculpt_paint_color.c
+++ b/source/blender/editors/sculpt_paint/sculpt_paint_color.c
@@ -454,7 +454,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
}
/* Multiply weight with edge lengths (in the future this will be
- cotangent weights or face areas). */
+ * cotangent weights or face areas). */
w *= len;
/* Build directional weight. */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 03ec018fbe8..bc047a00ae1 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -100,7 +100,7 @@ static SpaceLink *image_create(const ScrArea *UNUSED(area), const Scene *UNUSED(
simage->lock = true;
simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS;
simage->uv_opacity = 1.0f;
- simage->overlay.flag = SI_OVERLAY_SHOW_OVERLAYS;
+ simage->overlay.flag = SI_OVERLAY_SHOW_OVERLAYS | SI_OVERLAY_SHOW_GRID_BACKGROUND;
BKE_imageuser_default(&simage->iuser);
simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS | IMA_SHOW_MAX_RESOLUTION;
diff --git a/source/blender/editors/space_node/node_intern.hh b/source/blender/editors/space_node/node_intern.hh
index 433efb79b77..44163cd5ae3 100644
--- a/source/blender/editors/space_node/node_intern.hh
+++ b/source/blender/editors/space_node/node_intern.hh
@@ -117,6 +117,8 @@ ENUM_OPERATORS(NodeResizeDirection, NODE_RESIZE_LEFT);
*/
float2 space_node_group_offset(const SpaceNode &snode);
+rctf node_frame_rect_inside(const bNode &node);
+
int node_get_resize_cursor(NodeResizeDirection directions);
/**
* Usual convention here would be #node_socket_get_color(),
diff --git a/source/blender/editors/space_outliner/outliner_tools.cc b/source/blender/editors/space_outliner/outliner_tools.cc
index 50c85a907a6..67bc0e91053 100644
--- a/source/blender/editors/space_outliner/outliner_tools.cc
+++ b/source/blender/editors/space_outliner/outliner_tools.cc
@@ -47,6 +47,7 @@
#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_object.h"
#include "BKE_report.h"
@@ -810,6 +811,13 @@ static void id_override_library_create_fn(bContext *C,
void *user_data)
{
BLI_assert(TSE_IS_REAL_ID(tselem));
+
+ /* We can only safely apply this operation on one item at a time, so only do it on the active
+ * one. */
+ if ((tselem->flag & TSE_ACTIVE) == 0) {
+ return;
+ }
+
ID *id_root_reference = tselem->id;
OutlinerLibOverrideData *data = reinterpret_cast<OutlinerLibOverrideData *>(user_data);
const bool do_hierarchy = data->do_hierarchy;
@@ -1000,6 +1008,23 @@ static void id_override_library_create_hierarchy_post_process(bContext *C,
FOREACH_MAIN_ID_END;
}
+static void id_override_library_toggle_flag_fn(bContext *UNUSED(C),
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *user_data)
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ ID *id = tselem->id;
+
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ const uint flag = POINTER_AS_UINT(user_data);
+ id->override_library->flag ^= flag;
+ }
+}
+
static void id_override_library_reset_fn(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
@@ -1017,10 +1042,10 @@ static void id_override_library_reset_fn(bContext *C,
Main *bmain = CTX_data_main(C);
if (do_hierarchy) {
- BKE_lib_override_library_id_hierarchy_reset(bmain, id_root);
+ BKE_lib_override_library_id_hierarchy_reset(bmain, id_root, false);
}
else {
- BKE_lib_override_library_id_reset(bmain, id_root);
+ BKE_lib_override_library_id_reset(bmain, id_root, false);
}
WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, nullptr);
@@ -1072,40 +1097,75 @@ static void id_override_library_resync_fn(bContext *C,
}
}
-static void id_override_library_delete_fn(bContext *C,
- ReportList *UNUSED(reports),
- Scene *UNUSED(scene),
- TreeElement *te,
- TreeStoreElem *UNUSED(tsep),
- TreeStoreElem *tselem,
- void *UNUSED(user_data))
+static void id_override_library_clear_hierarchy_fn(bContext *C,
+ ReportList *UNUSED(reports),
+ Scene *UNUSED(scene),
+ TreeElement *te,
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
{
BLI_assert(TSE_IS_REAL_ID(tselem));
ID *id_root = tselem->id;
- if (ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
- Main *bmain = CTX_data_main(C);
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id_root)) {
+ CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ return;
+ }
- id_root->tag |= LIB_TAG_DOIT;
+ Main *bmain = CTX_data_main(C);
- /* Tag all linked parents in tree hierarchy to be also overridden. */
- while ((te = te->parent) != nullptr) {
- if (!TSE_IS_REAL_ID(te->store_elem)) {
- continue;
- }
- if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
- break;
- }
- te->store_elem->id->tag |= LIB_TAG_DOIT;
+ id_root->tag |= LIB_TAG_DOIT;
+
+ /* Tag all override parents in tree hierarchy to be also processed. */
+ while ((te = te->parent) != nullptr) {
+ if (!TSE_IS_REAL_ID(te->store_elem)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(te->store_elem->id)) {
+ break;
}
+ te->store_elem->id->tag |= LIB_TAG_DOIT;
+ }
- BKE_lib_override_library_delete(bmain, id_root);
+ BKE_lib_override_library_delete(bmain, id_root);
- WM_event_add_notifier(C, NC_WINDOW, nullptr);
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
+}
+
+static void id_override_library_clear_single_fn(bContext *C,
+ ReportList *reports,
+ Scene *UNUSED(scene),
+ TreeElement *UNUSED(te),
+ TreeStoreElem *UNUSED(tsep),
+ TreeStoreElem *tselem,
+ void *UNUSED(user_data))
+{
+ BLI_assert(TSE_IS_REAL_ID(tselem));
+ Main *bmain = CTX_data_main(C);
+ ID *id = tselem->id;
+
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Cannot clear embedded library override id '%s', only overrides of real "
+ "data-blocks can be directly deleted",
+ id->name);
+ return;
+ }
+
+ /* If given ID is not using any other override (it's a 'leaf' in the override hierarchy),
+ * delete it and remap its usages to its linked reference. Otherwise, keep it as a reset system
+ * override. */
+ if (BKE_lib_override_library_is_hierarchy_leaf(bmain, id)) {
+ BKE_libblock_remap(bmain, id, id->override_library->reference, ID_REMAP_SKIP_INDIRECT_USAGE);
+ BKE_id_delete(bmain, id);
}
else {
- CLOG_WARN(&LOG, "Could not delete library override of data block '%s'", id_root->name);
+ BKE_lib_override_library_id_reset(bmain, id, true);
}
+
+ WM_event_add_notifier(C, NC_WINDOW, nullptr);
}
static void id_fake_user_set_fn(bContext *UNUSED(C),
@@ -1751,11 +1811,11 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot)
using OutlinerDeleteFn = void (*)(bContext *C, ReportList *reports, Scene *scene, Object *ob);
-typedef struct ObjectEditData {
+using ObjectEditData = struct ObjectEditData {
GSet *objects_set;
bool is_liboverride_allowed;
bool is_liboverride_hierarchy_root_allowed;
-} ObjectEditData;
+};
static void outliner_do_object_delete(bContext *C,
ReportList *reports,
@@ -1903,11 +1963,13 @@ enum eOutlinerIdOpTypes {
OUTLINER_IDOP_LOCAL,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY,
OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE,
- OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
OUTLINER_IDOP_SINGLE,
OUTLINER_IDOP_DELETE,
OUTLINER_IDOP_REMAP,
@@ -1937,13 +1999,20 @@ static const EnumPropertyItem prop_id_op_types[] = {
{OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE,
"OVERRIDE_LIBRARY_CREATE",
0,
- "Make Library Override",
- "Make a local override of this linked data-block"},
+ "Make Library Override Single",
+ "Make a single, out-of-hierarchy local override of this linked data-block - only applies to "
+ "active Outliner item"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_CREATE_HIERARCHY,
"OVERRIDE_LIBRARY_CREATE_HIERARCHY",
0,
"Make Library Override Hierarchy",
- "Make a local override of this linked data-block, and its hierarchy of dependencies"},
+ "Make a local override of this linked data-block, and its hierarchy of dependencies - only "
+ "applies to active Outliner item"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE,
+ "OVERRIDE_LIBRARY_MAKE_EDITABLE",
+ 0,
+ "Make Library Override Editable",
+ "Make the library override data-block editable"},
{OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET,
"OVERRIDE_LIBRARY_RESET",
0,
@@ -1967,12 +2036,18 @@ static const EnumPropertyItem prop_id_op_types[] = {
"Rebuild this local override from its linked reference, as well as its hierarchy of "
"dependencies, enforcing that hierarchy to match the linked data (i.e. ignoring exiting "
"overrides on data-blocks pointer properties)"},
- {OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY,
- "OVERRIDE_LIBRARY_DELETE_HIERARCHY",
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY,
+ "OVERRIDE_LIBRARY_CLEAR_HIERARCHY",
0,
- "Delete Library Override Hierarchy",
+ "Clear Library Override Hierarchy",
"Delete this local override (including its hierarchy of override dependencies) and relink "
"its usages to the linked data-blocks"},
+ {OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE,
+ "OVERRIDE_LIBRARY_CLEAR_SINGLE",
+ 0,
+ "Clear Single Library Override",
+ "Delete this local override if possible, else reset it and mark it as non editable, and "
+ "relink its usages to the linked data-blocks"},
{0, "", 0, nullptr, nullptr},
{OUTLINER_IDOP_COPY, "COPY", ICON_COPYDOWN, "Copy", ""},
{OUTLINER_IDOP_PASTE, "PASTE", ICON_PASTEDOWN, "Paste", ""},
@@ -2016,11 +2091,19 @@ static bool outliner_id_operation_item_poll(bContext *C,
return true;
}
return false;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE:
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
+ if (tselem->id->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED) {
+ return true;
+ }
+ }
+ return false;
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY:
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESYNC_HIERARCHY_ENFORCE:
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY:
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE:
if (ID_IS_OVERRIDE_LIBRARY_REAL(tselem->id) && !ID_IS_LINKED(tselem->id)) {
return true;
}
@@ -2201,6 +2284,18 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Overridden Data Hierarchy");
break;
}
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_MAKE_EDITABLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_toggle_flag_fn,
+ POINTER_FROM_UINT(IDOVERRIDE_LIBRARY_FLAG_SYSTEM_DEFINED));
+
+ ED_undo_push(C, "Make Overridden Data Editable");
+ break;
+ }
case OUTLINER_IDOP_OVERRIDE_LIBRARY_RESET: {
OutlinerLibOverrideData override_data{};
outliner_do_libdata_operation(C,
@@ -2253,17 +2348,26 @@ static int outliner_id_operation_exec(bContext *C, wmOperator *op)
ED_undo_push(C, "Resync Overridden Data Hierarchy");
break;
}
- case OUTLINER_IDOP_OVERRIDE_LIBRARY_DELETE_HIERARCHY: {
- OutlinerLibOverrideData override_data{};
- override_data.do_hierarchy = true;
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_HIERARCHY: {
outliner_do_libdata_operation(C,
op->reports,
scene,
space_outliner,
&space_outliner->tree,
- id_override_library_delete_fn,
- &override_data);
- ED_undo_push(C, "Delete Overridden Data Hierarchy");
+ id_override_library_clear_hierarchy_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
+ break;
+ }
+ case OUTLINER_IDOP_OVERRIDE_LIBRARY_CLEAR_SINGLE: {
+ outliner_do_libdata_operation(C,
+ op->reports,
+ scene,
+ space_outliner,
+ &space_outliner->tree,
+ id_override_library_clear_single_fn,
+ nullptr);
+ ED_undo_push(C, "Clear Overridden Data Hierarchy");
break;
}
case OUTLINER_IDOP_SINGLE: {
diff --git a/source/blender/editors/transform/transform_convert_sequencer.c b/source/blender/editors/transform/transform_convert_sequencer.c
index 990d3680057..c7f086e7d4b 100644
--- a/source/blender/editors/transform/transform_convert_sequencer.c
+++ b/source/blender/editors/transform/transform_convert_sequencer.c
@@ -66,6 +66,9 @@ typedef struct TransSeq {
/* Initial rect of the view2d, used for computing offset during edge panning */
rctf initial_v2d_cur;
View2DEdgePanData edge_pan;
+
+ /* Strips that aren't selected, but their position entirely depends on transformed strips. */
+ SeqCollection *time_dependent_strips;
} TransSeq;
/* -------------------------------------------------------------------- */
@@ -256,6 +259,7 @@ static void free_transform_custom_data(TransCustomData *custom_data)
{
if ((custom_data->data != NULL) && custom_data->use_free) {
TransSeq *ts = custom_data->data;
+ SEQ_collection_free(ts->time_dependent_strips);
MEM_freeN(ts->tdseq);
MEM_freeN(custom_data->data);
custom_data->data = NULL;
@@ -630,10 +634,114 @@ static void freeSeqData(TransInfo *t, TransDataContainer *tc, TransCustomData *c
free_transform_custom_data(custom_data);
}
-void createTransSeqData(TransInfo *t)
+static SeqCollection *query_selected_strips_no_handles(ListBase *seqbase)
{
-#define XXX_DURIAN_ANIM_TX_HACK
+ SeqCollection *strips = SEQ_collection_create(__func__);
+ LISTBASE_FOREACH (Sequence *, seq, seqbase) {
+ if ((seq->flag & SELECT) != 0 && ((seq->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) == 0)) {
+ SEQ_collection_append_strip(seq, strips);
+ }
+ }
+ return strips;
+}
+
+typedef enum SeqInputSide {
+ SEQ_INPUT_LEFT = -1,
+ SEQ_INPUT_RIGHT = 1,
+} SeqInputSide;
+static Sequence *effect_input_get(Sequence *effect, SeqInputSide side)
+{
+ Sequence *input = effect->seq1;
+ if (effect->seq2 && (effect->seq2->startdisp - effect->seq1->startdisp) * side > 0) {
+ input = effect->seq2;
+ }
+ return input;
+}
+
+static Sequence *effect_base_input_get(Sequence *effect, SeqInputSide side)
+{
+ Sequence *input = effect, *seq_iter = effect;
+ while (seq_iter != NULL) {
+ input = seq_iter;
+ seq_iter = effect_input_get(seq_iter, side);
+ }
+ return input;
+}
+
+/* Strips that aren't selected, but their position entirely depends on transformed strips.
+ * This collection is used to offset animation.*/
+static SeqCollection *query_time_dependent_strips_strips(TransInfo *t)
+{
+ ListBase *seqbase = seqbase_active_get(t);
+
+ /* Query dependent strips where used strips do not have handles selected.
+ * If all inputs of any effect even indirectly(through another effect) points to selected strip,
+ * it's position will change. */
+
+ SeqCollection *strips_no_handles = query_selected_strips_no_handles(seqbase);
+ /* Selection is needed as reference for related strips. */
+ SeqCollection *dependent = SEQ_collection_duplicate(strips_no_handles);
+ SEQ_collection_expand(seqbase, strips_no_handles, SEQ_query_strip_effect_chain);
+ bool strip_added = true;
+
+ while (strip_added) {
+ strip_added = false;
+
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, strips_no_handles) {
+ if (SEQ_collection_has_strip(seq, dependent)) {
+ continue; /* Strip is already in collection, skip it. */
+ }
+
+ /* If both seq1 and seq2 exist, both must be selected. */
+ if (seq->seq1 && SEQ_collection_has_strip(seq->seq1, dependent)) {
+ if (seq->seq2 && !SEQ_collection_has_strip(seq->seq2, dependent)) {
+ continue;
+ }
+ strip_added = true;
+ SEQ_collection_append_strip(seq, dependent);
+ }
+ }
+ }
+
+ SEQ_collection_free(strips_no_handles);
+
+ /* Query dependent strips where used strips do have handles selected.
+ * If any 2-input effect changes position because handles were moved, animation should be offset.
+ * With single input effect, it is less likely desirable to move animation. */
+
+ SeqCollection *selected_strips = SEQ_query_selected_strips(seqbase);
+ SEQ_collection_expand(seqbase, selected_strips, SEQ_query_strip_effect_chain);
+ Sequence *seq;
+ SEQ_ITERATOR_FOREACH (seq, selected_strips) {
+ /* Check only 2 input effects. */
+ if (seq->seq1 == NULL || seq->seq2 == NULL) {
+ continue;
+ }
+
+ /* Find immediate base inputs(left and right side). */
+ Sequence *input_left = effect_base_input_get(seq, SEQ_INPUT_LEFT);
+ Sequence *input_right = effect_base_input_get(seq, SEQ_INPUT_RIGHT);
+
+ if ((input_left->flag & SEQ_RIGHTSEL) != 0 && (input_right->flag & SEQ_LEFTSEL) != 0) {
+ SEQ_collection_append_strip(seq, dependent);
+ }
+ }
+ SEQ_collection_free(selected_strips);
+
+ /* Remove all non-effects. */
+ SEQ_ITERATOR_FOREACH (seq, dependent) {
+ if (SEQ_transform_sequence_can_be_translated(seq)) {
+ SEQ_collection_remove_strip(seq, dependent);
+ }
+ }
+
+ return dependent;
+}
+
+void createTransSeqData(TransInfo *t)
+{
Scene *scene = t->scene;
Editing *ed = SEQ_editing_get(t->scene);
TransData *td = NULL;
@@ -653,26 +761,6 @@ void createTransSeqData(TransInfo *t)
tc->custom.type.free_cb = freeSeqData;
t->frame_side = transform_convert_frame_side_dir_get(t, (float)CFRA);
-#ifdef XXX_DURIAN_ANIM_TX_HACK
- {
- Sequence *seq;
- for (seq = ed->seqbasep->first; seq; seq = seq->next) {
- /* hack */
- if ((seq->flag & SELECT) == 0 && seq->type & SEQ_TYPE_EFFECT) {
- Sequence *seq_user;
- int i;
- for (i = 0; i < 3; i++) {
- seq_user = *((&seq->seq1) + i);
- if (seq_user && (seq_user->flag & SELECT) && !(seq_user->flag & SEQ_LOCK) &&
- !(seq_user->flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL))) {
- seq->flag |= SELECT;
- }
- }
- }
- }
- }
-#endif
-
count = SeqTransCount(t, ed->seqbasep);
/* allocate memory for data */
@@ -712,7 +800,7 @@ void createTransSeqData(TransInfo *t)
}
}
-#undef XXX_DURIAN_ANIM_TX_HACK
+ ts->time_dependent_strips = query_time_dependent_strips_strips(t);
}
/** \} */
@@ -771,7 +859,8 @@ static void flushTransSeq(TransInfo *t)
/* Editing null check already done */
ListBase *seqbasep = seqbase_active_get(t);
- int a, new_frame;
+ int a, new_frame, offset;
+
TransData *td = NULL;
TransData2D *td2d = NULL;
TransDataSeq *tdsq = NULL;
@@ -779,6 +868,15 @@ static void flushTransSeq(TransInfo *t)
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
+ /* This is calculated for offsetting animation of effects that change position with inputs.
+ * Maximum(positive or negative) value is used, because individual strips can be clamped. This
+ * works fairly well in most scenarios, but there can be some edge cases.
+ *
+ * Better solution would be to store effect position and calculate real offset. However with many
+ * (>5) effects in chain, there is visible lag in strip position update, because during
+ * recalculation, hierarchy is not taken into account. */
+ int max_offset = 0;
+
/* Flush to 2D vector from internally used 3D vector. */
for (a = 0, td = tc->data, td2d = tc->data_2d; a < tc->data_len; a++, td++, td2d++) {
tdsq = (TransDataSeq *)td->extra;
@@ -788,31 +886,49 @@ static void flushTransSeq(TransInfo *t)
new_frame = round_fl_to_int(loc[0]);
switch (tdsq->sel_flag) {
- case SELECT:
+ case SELECT: {
if (SEQ_transform_sequence_can_be_translated(seq)) {
- const int offset = new_frame - tdsq->start_offset - seq->start;
+ offset = new_frame - tdsq->start_offset - seq->start;
SEQ_transform_translate_sequence(t->scene, seq, offset);
+ if (abs(offset) > abs(max_offset)) {
+ max_offset = offset;
+ }
}
seq->machine = round_fl_to_int(loc[1]);
CLAMP(seq->machine, 1, MAXSEQ);
break;
-
- case SEQ_LEFTSEL: /* No vertical transform. */
+ }
+ case SEQ_LEFTSEL: { /* No vertical transform. */
+ int old_startdisp = seq->startdisp;
SEQ_transform_set_left_handle_frame(seq, new_frame);
SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
SEQ_transform_fix_single_image_seq_offsets(seq);
SEQ_time_update_sequence(t->scene, seqbasep, seq);
+ if (abs(seq->startdisp - old_startdisp) > abs(max_offset)) {
+ max_offset = seq->startdisp - old_startdisp;
+ }
break;
- case SEQ_RIGHTSEL: /* No vertical transform. */
+ }
+ case SEQ_RIGHTSEL: { /* No vertical transform. */
+ int old_enddisp = seq->enddisp;
SEQ_transform_set_right_handle_frame(seq, new_frame);
SEQ_transform_handle_xlimits(seq, tdsq->flag & SEQ_LEFTSEL, tdsq->flag & SEQ_RIGHTSEL);
SEQ_transform_fix_single_image_seq_offsets(seq);
SEQ_time_update_sequence(t->scene, seqbasep, seq);
+ if (abs(seq->enddisp - old_enddisp) > abs(max_offset)) {
+ max_offset = seq->enddisp - old_enddisp;
+ }
break;
+ }
}
}
- /* Update all effects. */
+ /* Update animation for effects. */
+ SEQ_ITERATOR_FOREACH (seq, ts->time_dependent_strips) {
+ SEQ_offset_animdata(t->scene, seq, max_offset);
+ }
+
+ /* Update effect length and position. */
if (ELEM(t->mode, TFM_SEQ_SLIDE, TFM_TIME_TRANSLATE)) {
for (seq = seqbasep->first; seq; seq = seq->next) {
if (seq->seq1 || seq->seq2 || seq->seq3) {
diff --git a/source/blender/freestyle/intern/view_map/Interface1D.h b/source/blender/freestyle/intern/view_map/Interface1D.h
index 5ab6fc794f9..47b3e827439 100644
--- a/source/blender/freestyle/intern/view_map/Interface1D.h
+++ b/source/blender/freestyle/intern/view_map/Interface1D.h
@@ -27,31 +27,46 @@ using namespace std;
namespace Freestyle {
// Integration method
-/** The different integration methods that can be invoked to integrate into a single value the set
+/**
+ * The different integration methods that can be invoked to integrate into a single value the set
* of values obtained from each 0D element of a 1D element.
*/
typedef enum {
- MEAN, /**< The value computed for the 1D element is the mean of the values obtained for the 0D
- elements. */
- MIN, /**< The value computed for the 1D element is the minimum of the values obtained for the 0D
- elements. */
- MAX, /**< The value computed for the 1D element is the maximum of the values obtained for the 0D
- elements. */
- FIRST, /**< The value computed for the 1D element is the first of the values obtained for the 0D
- elements. */
- LAST, /**< The value computed for the 1D element is the last of the values obtained for the 0D
- elements. */
+ /**
+ * The value computed for the 1D element is the mean of the values obtained for the 0D elements.
+ */
+ MEAN,
+ /**
+ * The value computed for the 1D element is the minimum of the values obtained for the 0D
+ * elements.
+ */
+ MIN,
+ /**
+ * The value computed for the 1D element is the maximum of the values obtained for the 0D
+ * elements.
+ */
+ MAX,
+ /**
+ * The value computed for the 1D element is the first of the values obtained for the 0D
+ * elements.
+ */
+ FIRST,
+ /**
+ * The value computed for the 1D element is the last of the values obtained for the 0D
+ * elements.
+ */
+ LAST,
} IntegrationType;
-/** Returns a single value from a set of values evaluated at each 0D element of this 1D element.
- * \param fun:
- * The UnaryFunction0D used to compute a value at each Interface0D.
- * \param it:
- * The Interface0DIterator used to iterate over the 0D elements of this 1D element. The
- * integration will occur over the 0D elements starting from the one pointed by it. \param it_end:
- * The Interface0DIterator pointing the end of the 0D elements of the 1D element.
- * \param integration_type:
- * The integration method used to compute a single value from a set of values.
+/**
+ * Returns a single value from a set of values evaluated at each 0D element of this 1D element.
+ *
+ * \param fun: The UnaryFunction0D used to compute a value at each Interface0D.
+ * \param it: The Interface0DIterator used to iterate over the 0D elements of this 1D element.
+ * The integration will occur over the 0D elements starting from the one pointed by it.
+ * \param it_end: The Interface0DIterator pointing the end of the 0D elements of the 1D element.
+ * \param integration_type: The integration method used to compute a single value from a set of
+ * values.
* \return the single value obtained for the 1D element.
*/
template<class T>
diff --git a/source/blender/functions/FN_multi_function_builder.hh b/source/blender/functions/FN_multi_function_builder.hh
index ed587a87695..e0ccd2a482d 100644
--- a/source/blender/functions/FN_multi_function_builder.hh
+++ b/source/blender/functions/FN_multi_function_builder.hh
@@ -20,7 +20,7 @@ namespace blender::fn {
* 2. single output (SO) of type Out1
*
* This example creates a function that adds 10 to the incoming values:
- * CustomMF_SI_SO<int, int> fn("add 10", [](int value) { return value + 10; });
+ * `CustomMF_SI_SO<int, int> fn("add 10", [](int value) { return value + 10; });`
*/
template<typename In1, typename Out1> class CustomMF_SI_SO : public MultiFunction {
private:
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c
index d9881f5b7ae..efbec4222aa 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilenvelope.c
@@ -218,10 +218,12 @@ static void apply_stroke_envelope(
max_ii(0, i + j - spread_left);
const int i2 = is_cyclic ? (i + j + spread_right) % gps->totpoints :
min_ii(gps->totpoints - 1, i + j + spread_right);
- /*bool side = dot_v3v3(&old_points[i1].x, plane_no) < dot_v3v3(plane_no, &old_points[i2].x);
+#if 0
+ bool side = dot_v3v3(&old_points[i1].x, plane_no) < dot_v3v3(plane_no, &old_points[i2].x);
if (side) {
continue;
- }*/
+ }
+#endif
float lambda = line_plane_factor_v3(
&point->x, plane_no, &old_points[i1].x, &old_points[i2].x);
if (lambda <= 0.0f || lambda >= 1.0f) {
diff --git a/source/blender/io/usd/intern/usd_reader_material.h b/source/blender/io/usd/intern/usd_reader_material.h
index 0f922dca47f..24d80e99c38 100644
--- a/source/blender/io/usd/intern/usd_reader_material.h
+++ b/source/blender/io/usd/intern/usd_reader_material.h
@@ -40,7 +40,7 @@ struct NodePlacementContext {
/* Converts USD materials to Blender representation. */
/**
- By default, the #USDMaterialReader creates a Blender material with
+ * By default, the #USDMaterialReader creates a Blender material with
* the same name as the USD material. If the USD material has a
* #UsdPreviewSurface source, the Blender material's viewport display
* color, roughness and metallic properties are set to the corresponding
diff --git a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
index eb9c2f13c29..f78ef334d4d 100644
--- a/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
+++ b/source/blender/io/wavefront_obj/exporter/obj_export_file_writer.cc
@@ -425,11 +425,25 @@ void OBJWriter::write_nurbs_curve(FormatHandler<eFileType::OBJ> &fh,
/**
* In `parm u 0 0.1 ..` line:, (total control points + 2) equidistant numbers in the
- * parameter range are inserted.
+ * parameter range are inserted. However for curves with endpoint flag,
+ * first degree+1 numbers are zeroes, and last degree+1 numbers are ones
*/
+
+ const short flagsu = obj_nurbs_data.get_nurbs_flagu(spline_idx);
+ const bool cyclic = flagsu & CU_NURB_CYCLIC;
+ const bool endpoint = !cyclic && (flagsu & CU_NURB_ENDPOINT);
fh.write<eOBJSyntaxElement::nurbs_parameter_begin>();
for (int i = 1; i <= total_control_points + 2; i++) {
- fh.write<eOBJSyntaxElement::nurbs_parameters>(1.0f * i / (total_control_points + 2 + 1));
+ float parm = 1.0f * i / (total_control_points + 2 + 1);
+ if (endpoint) {
+ if (i <= nurbs_degree) {
+ parm = 0;
+ }
+ else if (i > total_control_points + 2 - nurbs_degree) {
+ parm = 1;
+ }
+ }
+ fh.write<eOBJSyntaxElement::nurbs_parameters>(parm);
}
fh.write<eOBJSyntaxElement::nurbs_parameter_end>();
diff --git a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
index 61699c78ace..8599b38d55b 100644
--- a/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
+++ b/source/blender/io/wavefront_obj/tests/obj_exporter_tests.cc
@@ -265,7 +265,7 @@ o abcdef
o 012345678901234567890123456789abcd
o 123
curv 0.0 1.0
-parm 0.0
+parm u 0.0
)";
ASSERT_EQ(got_string, expected);
}
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index e3a6f50531d..17d783d3ebf 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -349,8 +349,10 @@ typedef struct ID_Runtime_Remap {
int status;
/** During ID remapping the number of skipped use cases that refcount the data-block. */
int skipped_refcounted;
- /** During ID remapping the number of direct use cases that could be remapped (e.g. obdata when
-in edit mode). */
+ /**
+ * During ID remapping the number of direct use cases that could be remapped
+ * (e.g. obdata when in edit mode).
+ */
int skipped_direct;
/** During ID remapping, the number of indirect use cases that could not be remapped. */
int skipped_indirect;
diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h
index 0aa4ebc61d0..bb53dbafdc8 100644
--- a/source/blender/makesdna/DNA_curves_types.h
+++ b/source/blender/makesdna/DNA_curves_types.h
@@ -51,8 +51,8 @@ typedef enum KnotsMode {
/** Method used to calculate the normals of a curve's evaluated points. */
typedef enum NormalMode {
- NORMAL_MODE_Z_UP = 0,
- NORMAL_MODE_MINIMUM_TWIST = 1,
+ NORMAL_MODE_MINIMUM_TWIST = 0,
+ NORMAL_MODE_Z_UP = 1,
} NormalMode;
/**
@@ -84,7 +84,7 @@ typedef struct CurvesGeometry {
/**
* The start index of each curve in the point data. The size of each curve can be calculated by
* subtracting the offset from the next offset. That is valid even for the last curve because
- * this array is allocated with a length one larger than the number of splines. This is allowed
+ * this array is allocated with a length one larger than the number of curves. This is allowed
* to be null when there are no curves.
*
* \note This is *not* stored in #CustomData because its size is one larger than #curve_data.
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 806c989100d..bcf54ee47a0 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1318,6 +1318,7 @@ typedef enum eSpaceImage_Flag {
typedef enum eSpaceImageOverlay_Flag {
SI_OVERLAY_SHOW_OVERLAYS = (1 << 0),
+ SI_OVERLAY_SHOW_GRID_BACKGROUND = (1 << 1),
} eSpaceImageOverlay_Flag;
/** Keep in sync with `STEPS_LEN` in `grid_frag.glsl`. */
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 118589332ea..794f08d850e 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -481,7 +481,7 @@ void RNA_def_camera(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem prop_lens_unit_items[] = {
- {0, "MILLIMETERS", 0, "Millimeters", "Specify the lens in millimeters"},
+ {0, "MILLIMETERS", 0, "Millimeters", "Specify focal length of the lens in millimeters"},
{CAM_ANGLETOGGLE,
"FOV",
0,
@@ -564,7 +564,7 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "lens");
RNA_def_property_range(prop, 1.0f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 5000.0f, 100, 4);
- RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters");
+ RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera focal length value in millimeters");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update");
prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_DISTANCE_CAMERA);
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index ba040f88b55..b941245bcfc 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -365,9 +365,9 @@ void rna_ViewLayer_active_lightgroup_index_range(
int rna_ViewLayer_active_lightgroup_index_get(PointerRNA *ptr);
void rna_ViewLayer_active_lightgroup_index_set(PointerRNA *ptr, int value);
/**
- * Set `r_rna_path` with the base view-layer path.
- * `rna_path_buffer_size` should be at least `sizeof(ViewLayer.name) * 3`.
- * \return actual length of the generated RNA path.
+ * Set `r_rna_path` with the base view-layer path.
+ * `rna_path_buffer_size` should be at least `sizeof(ViewLayer.name) * 3`.
+ * \return actual length of the generated RNA path.
*/
size_t rna_ViewLayer_path_buffer_get(struct ViewLayer *view_layer,
char *r_rna_path,
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 24d50a0300f..4db438f04b4 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -30,14 +30,16 @@ typedef struct IDProperty IDProperty;
/* Function Callbacks */
-/** Update callback for an RNA property.
+/**
+ * Update callback for an RNA property.
*
- * \note This is NOT called automatically when writing into the property, it needs to be called
+ * \note This is NOT called automatically when writing into the property, it needs to be called
* manually (through #RNA_property_update or #RNA_property_update_main) when needed.
*
- * \param bmain: the Main data-base to which `ptr` data belongs.
- * \param active_scene: The current active scene (may be NULL in some cases).
- * \param ptr: The RNA pointer data to update. */
+ * \param bmain: the Main data-base to which `ptr` data belongs.
+ * \param active_scene: The current active scene (may be NULL in some cases).
+ * \param ptr: The RNA pointer data to update.
+ */
typedef void (*UpdateFunc)(struct Main *bmain, struct Scene *active_scene, struct PointerRNA *ptr);
typedef void (*ContextPropUpdateFunc)(struct bContext *C,
struct PointerRNA *ptr,
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index a74019f9569..d2b8eb203aa 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -3497,7 +3497,7 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Faces", "Display faces over the image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
- prop = RNA_def_property(srna, "tile_grid_shape", PROP_INT, PROP_NONE);
+ prop = RNA_def_property(srna, "tile_grid_shape", PROP_INT, PROP_XYZ);
RNA_def_property_int_sdna(prop, NULL, "tile_grid_shape");
RNA_def_property_array(prop, 2);
RNA_def_property_int_default(prop, 1);
@@ -5264,6 +5264,11 @@ static void rna_def_space_image_overlay(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_overlays", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SI_OVERLAY_SHOW_OVERLAYS);
RNA_def_property_ui_text(prop, "Show Overlays", "Display overlays like UV Maps and Metadata");
+
+ prop = RNA_def_property(srna, "show_grid_background", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", SI_OVERLAY_SHOW_GRID_BACKGROUND);
+ RNA_def_property_ui_text(prop, "Display Background", "Show the grid background and borders");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
}
static void rna_def_space_image(BlenderRNA *brna)
diff --git a/source/blender/nodes/NOD_math_functions.hh b/source/blender/nodes/NOD_math_functions.hh
index c1f0f043c92..e58c1068368 100644
--- a/source/blender/nodes/NOD_math_functions.hh
+++ b/source/blender/nodes/NOD_math_functions.hh
@@ -28,15 +28,15 @@ const FloatMathOperationInfo *get_float_compare_operation_info(int operation);
/**
* This calls the `callback` with two arguments:
- * 1. The math function that takes a float as input and outputs a new float.
- * 2. A #FloatMathOperationInfo struct reference.
+ * 1. The math function that takes a float as input and outputs a new float.
+ * 2. A #FloatMathOperationInfo struct reference.
* Returns true when the callback has been called, otherwise false.
*
* The math function that is passed to the callback is actually a lambda function that is different
* for every operation. Therefore, if the callback is templated on the math function, it will get
* instantiated for every operation separately. This has two benefits:
- * - The compiler can optimize the callback for every operation separately.
- * - A static variable declared in the callback will be generated for every operation separately.
+ * - The compiler can optimize the callback for every operation separately.
+ * - A static variable declared in the callback will be generated for every operation separately.
*
* If separate instantiations are not desired, the callback can also take a function pointer with
* the following signature as input instead: float (*math_function)(float a).
diff --git a/source/blender/nodes/NOD_socket_search_link.hh b/source/blender/nodes/NOD_socket_search_link.hh
index 7a1aff13020..8d80da229a7 100644
--- a/source/blender/nodes/NOD_socket_search_link.hh
+++ b/source/blender/nodes/NOD_socket_search_link.hh
@@ -120,8 +120,8 @@ class GatherLinkSearchOpParams {
/**
* This callback can be used for a node type when a few things are true about its inputs.
* To avoid creating more boilerplate, it is the default callback for node types.
- * - Either all declared sockets are visible in the default state of the node, *OR* the node's
- * type's declaration has been extended with #make_available functions for those sockets.
+ * - Either all declared sockets are visible in the default state of the node, *OR* the node's
+ * type's declaration has been extended with #make_available functions for those sockets.
*
* If a node type does not meet these criteria, the function will do nothing in a release build.
* In a debug build, an assert will most likely be hit.
diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
index be17918609f..5d97720a4f8 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_spline_parameter.cc
@@ -59,11 +59,10 @@ static Array<float> curve_length_point_domain(const bke::CurvesGeometry &curves)
{
curves.ensure_evaluated_lengths();
const VArray<int8_t> types = curves.curve_types();
- const VArray<int> resolution = curves.resolution();
+ const VArray<int> resolutions = curves.resolution();
const VArray<bool> cyclic = curves.cyclic();
Array<float> result(curves.points_num());
- VArray<int> resolutions = curves.resolution();
threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
for (const int i_curve : range) {
diff --git a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
index 5a2c32a6c8e..2894e608819 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
@@ -627,7 +627,7 @@ static void calc_dual_mesh(GeometrySet &geometry_set,
calc_boundaries(mesh_in, vertex_types, edge_types);
/* Stores the indices of the polygons connected to the vertex. Because the polygons are looped
* over in order of their indices, the polygon's indices will be sorted in ascending order.
- (This can change once they are sorted using `sort_vertex_polys`). */
+ * (This can change once they are sorted using `sort_vertex_polys`). */
Array<Vector<int>> vertex_poly_indices(mesh_in.totvert);
Array<Array<int>> vertex_shared_edges(mesh_in.totvert);
Array<Array<int>> vertex_corners(mesh_in.totvert);
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
index 435dd969c03..039d6b69585 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_tangent.cc
@@ -2,7 +2,7 @@
#include "BLI_task.hh"
-#include "BKE_spline.hh"
+#include "BKE_curves.hh"
#include "node_geometry_util.hh"
@@ -13,65 +13,54 @@ static void node_declare(NodeDeclarationBuilder &b)
b.add_output<decl::Vector>(N_("Tangent")).field_source();
}
-static void calculate_bezier_tangents(const BezierSpline &spline, MutableSpan<float3> tangents)
+static Array<float3> curve_tangent_point_domain(const bke::CurvesGeometry &curves)
{
- Span<int> offsets = spline.control_point_offsets();
- Span<float3> evaluated_tangents = spline.evaluated_tangents();
- for (const int i : IndexRange(spline.size())) {
- tangents[i] = evaluated_tangents[offsets[i]];
- }
-}
+ const VArray<int8_t> types = curves.curve_types();
+ const VArray<int> resolutions = curves.resolution();
+ const VArray<bool> cyclic = curves.cyclic();
+ const Span<float3> positions = curves.positions();
-static void calculate_poly_tangents(const PolySpline &spline, MutableSpan<float3> tangents)
-{
- tangents.copy_from(spline.evaluated_tangents());
-}
+ const Span<float3> evaluated_tangents = curves.evaluated_tangents();
-/**
- * Because NURBS control points are not necessarily on the path, the tangent at the control points
- * is not well defined, so create a temporary poly spline to find the tangents. This requires extra
- * copying currently, but may be more efficient in the future if attributes have some form of CoW.
- */
-static void calculate_nurbs_tangents(const NURBSpline &spline, MutableSpan<float3> tangents)
-{
- PolySpline poly_spline;
- poly_spline.resize(spline.size());
- poly_spline.positions().copy_from(spline.positions());
- tangents.copy_from(poly_spline.evaluated_tangents());
-}
+ Array<float3> results(curves.points_num());
-static Array<float3> curve_tangent_point_domain(const CurveEval &curve)
-{
- Span<SplinePtr> splines = curve.splines();
- Array<int> offsets = curve.control_point_offsets();
- const int total_size = offsets.last();
- Array<float3> tangents(total_size);
-
- threading::parallel_for(splines.index_range(), 128, [&](IndexRange range) {
- for (const int i : range) {
- const Spline &spline = *splines[i];
- MutableSpan spline_tangents{tangents.as_mutable_span().slice(offsets[i], spline.size())};
- switch (splines[i]->type()) {
- case CURVE_TYPE_BEZIER: {
- calculate_bezier_tangents(static_cast<const BezierSpline &>(spline), spline_tangents);
+ threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
+ for (const int i_curve : range) {
+ const IndexRange points = curves.points_for_curve(i_curve);
+ const IndexRange evaluated_points = curves.evaluated_points_for_curve(i_curve);
+
+ MutableSpan<float3> curve_tangents = results.as_mutable_span().slice(points);
+
+ switch (types[i_curve]) {
+ case CURVE_TYPE_CATMULL_ROM: {
+ Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
+ const int resolution = resolutions[i_curve];
+ for (const int i : IndexRange(points.size())) {
+ curve_tangents[i] = tangents[resolution * i];
+ }
break;
}
- case CURVE_TYPE_POLY: {
- calculate_poly_tangents(static_cast<const PolySpline &>(spline), spline_tangents);
+ case CURVE_TYPE_POLY:
+ curve_tangents.copy_from(evaluated_tangents.slice(evaluated_points));
break;
- }
- case CURVE_TYPE_NURBS: {
- calculate_nurbs_tangents(static_cast<const NURBSpline &>(spline), spline_tangents);
+ case CURVE_TYPE_BEZIER: {
+ Span<float3> tangents = evaluated_tangents.slice(evaluated_points);
+ curve_tangents.first() = tangents.first();
+ const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
+ for (const int i : IndexRange(points.size()).drop_front(1)) {
+ curve_tangents[i] = tangents[offsets[i - 1]];
+ }
break;
}
- case CURVE_TYPE_CATMULL_ROM: {
- BLI_assert_unreachable();
+ case CURVE_TYPE_NURBS: {
+ const Span<float3> curve_positions = positions.slice(points);
+ bke::curves::poly::calculate_tangents(curve_positions, cyclic[i_curve], curve_tangents);
break;
}
}
}
});
- return tangents;
+ return results;
}
static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &component,
@@ -80,19 +69,25 @@ static VArray<float3> construct_curve_tangent_gvarray(const CurveComponent &comp
if (!component.has_curves()) {
return {};
}
- const std::unique_ptr<CurveEval> curve = curves_to_curve_eval(*component.get_for_read());
+
+ const Curves &curves_id = *component.get_for_read();
+ const bke::CurvesGeometry &curves = bke::CurvesGeometry::wrap(curves_id.geometry);
+
+ const VArray<int8_t> types = curves.curve_types();
+ if (curves.is_single_type(CURVE_TYPE_POLY)) {
+ return component.attribute_try_adapt_domain<float3>(
+ VArray<float3>::ForSpan(curves.evaluated_tangents()), ATTR_DOMAIN_POINT, domain);
+ }
+
+ Array<float3> tangents = curve_tangent_point_domain(curves);
if (domain == ATTR_DOMAIN_POINT) {
- Array<float3> tangents = curve_tangent_point_domain(*curve);
return VArray<float3>::ForContainer(std::move(tangents));
}
if (domain == ATTR_DOMAIN_CURVE) {
- Array<float3> point_tangents = curve_tangent_point_domain(*curve);
return component.attribute_try_adapt_domain<float3>(
- VArray<float3>::ForContainer(std::move(point_tangents)),
- ATTR_DOMAIN_POINT,
- ATTR_DOMAIN_CURVE);
+ VArray<float3>::ForContainer(std::move(tangents)), ATTR_DOMAIN_POINT, ATTR_DOMAIN_CURVE);
}
return nullptr;
diff --git a/source/blender/python/BPY_extern_run.h b/source/blender/python/BPY_extern_run.h
index 6bedf533af1..7c0707477da 100644
--- a/source/blender/python/BPY_extern_run.h
+++ b/source/blender/python/BPY_extern_run.h
@@ -11,7 +11,7 @@
* strings more cumbersome as otherwise small expressions become multi-line code-blocks.
* Optional (ignored when NULL), otherwise this is a NULL terminated array of module names.
*
- Failure to import any modules prevents any further execution.
+ * Failure to import any modules prevents any further execution.
*
* - `err_info` #BPy_RunErrInfo is passed to some functions so errors can be forwarded to the UI.
* Option (when NULL errors are printed to the `stdout` and cleared).
diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c
index 2ce1da81a2a..748a501ef76 100644
--- a/source/blender/python/intern/bpy.c
+++ b/source/blender/python/intern/bpy.c
@@ -189,7 +189,7 @@ static PyObject *bpy_flip_name(PyObject *UNUSED(self), PyObject *args, PyObject
}
/* Worst case we gain one extra byte (besides null-terminator) by changing
- "Left" to "Right", because only the first appearance of "Left" gets replaced. */
+ * "Left" to "Right", because only the first appearance of "Left" gets replaced. */
const size_t size = name_src_len + 2;
char *name_dst = PyMem_MALLOC(size);
const size_t name_dst_len = BLI_string_flip_side_name(name_dst, name_src, strip_digits, size);
diff --git a/source/blender/sequencer/intern/image_cache.c b/source/blender/sequencer/intern/image_cache.c
index 5f4916e640c..e1ff0ff64b3 100644
--- a/source/blender/sequencer/intern/image_cache.c
+++ b/source/blender/sequencer/intern/image_cache.c
@@ -49,10 +49,11 @@
* Function:
* All images created during rendering are added to cache, even if the cache is already full.
* This is because:
- * - one image may be needed multiple times during rendering.
- * - keeping the last rendered frame allows us for faster re-render when user edits strip in stack
- * - we can decide if we keep frame only when it's completely rendered. Otherwise we risk having
- * "holes" in the cache, which can be annoying
+ * - One image may be needed multiple times during rendering.
+ * - Keeping the last rendered frame allows us for faster re-render when user edits strip in stack.
+ * - We can decide if we keep frame only when it's completely rendered. Otherwise we risk having
+ * "holes" in the cache, which can be annoying.
+ *
* If the cache is full all entries for pending frame will have is_temp_cache set.
*
* Linking: We use links to reduce number of iterations over entries needed to manage cache.
diff --git a/source/tools b/source/tools
-Subproject 26bc78162ec89f21453ce3ded7b999bc6649f32
+Subproject 1e658ca996f11e5ff3398d89bd81f5b719304a5