From 3e23af4c4915f1ea5cb61c60e58cdfba41df1b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Barschkis?= Date: Mon, 6 Sep 2021 17:17:31 +0200 Subject: Fluid: Clang-format cleanups Just cleanup. --- extern/mantaflow/UPDATE.sh | 2 +- extern/mantaflow/helper/pwrapper/pconvert.cpp | 6 ++++-- extern/mantaflow/helper/pwrapper/pvec3.cpp | 6 ++++-- extern/mantaflow/helper/pwrapper/registry.cpp | 3 ++- extern/mantaflow/preprocessed/gitinfo.h | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/extern/mantaflow/UPDATE.sh b/extern/mantaflow/UPDATE.sh index aed4e2a9b71..1158ff13455 100644 --- a/extern/mantaflow/UPDATE.sh +++ b/extern/mantaflow/UPDATE.sh @@ -8,7 +8,7 @@ # YOUR INSTALLATION PATHS GO HERE: MANTA_INSTALLATION=/Users/sebbas/Developer/Mantaflow/mantaflowDevelop -BLENDER_INSTALLATION=/Users/sebbas/Developer/Blender/fluid-mantaflow +BLENDER_INSTALLATION=/Users/sebbas/Developer/Blender # Try to check out Mantaflow repository before building? CLEAN_REPOSITORY=0 diff --git a/extern/mantaflow/helper/pwrapper/pconvert.cpp b/extern/mantaflow/helper/pwrapper/pconvert.cpp index 7c66cdc7e72..5a7a32c5a73 100644 --- a/extern/mantaflow/helper/pwrapper/pconvert.cpp +++ b/extern/mantaflow/helper/pwrapper/pconvert.cpp @@ -28,11 +28,13 @@ extern PyTypeObject PbVec3Type; extern PyTypeObject PbVec4Type; struct PbVec3 { - PyObject_HEAD float data[3]; + PyObject_HEAD + float data[3]; }; struct PbVec4 { - PyObject_HEAD float data[4]; + PyObject_HEAD + float data[4]; }; PyObject *getPyNone() diff --git a/extern/mantaflow/helper/pwrapper/pvec3.cpp b/extern/mantaflow/helper/pwrapper/pvec3.cpp index 1dca44d5e5c..4d07a201cfe 100644 --- a/extern/mantaflow/helper/pwrapper/pvec3.cpp +++ b/extern/mantaflow/helper/pwrapper/pvec3.cpp @@ -25,7 +25,8 @@ namespace Manta { extern PyTypeObject PbVec3Type; struct PbVec3 { - PyObject_HEAD float data[3]; + PyObject_HEAD + float data[3]; }; static void PbVec3Dealloc(PbVec3 *self) @@ -293,7 +294,8 @@ inline PyObject *castPy(PyTypeObject *p) extern PyTypeObject PbVec4Type; struct PbVec4 { - PyObject_HEAD float data[4]; + PyObject_HEAD + float data[4]; }; static PyMethodDef PbVec4Methods[] = { diff --git a/extern/mantaflow/helper/pwrapper/registry.cpp b/extern/mantaflow/helper/pwrapper/registry.cpp index f88c2aa708e..5196c0409f8 100644 --- a/extern/mantaflow/helper/pwrapper/registry.cpp +++ b/extern/mantaflow/helper/pwrapper/registry.cpp @@ -76,7 +76,8 @@ struct ClassData { }; struct PbObject { - PyObject_HEAD Manta::PbClass *instance; + PyObject_HEAD + Manta::PbClass *instance; ClassData *classdef; }; diff --git a/extern/mantaflow/preprocessed/gitinfo.h b/extern/mantaflow/preprocessed/gitinfo.h index 6bc92278a33..6d367b764af 100644 --- a/extern/mantaflow/preprocessed/gitinfo.h +++ b/extern/mantaflow/preprocessed/gitinfo.h @@ -1,3 +1,3 @@ -#define MANTA_GIT_VERSION "commit 8fbebe02459b7f72575872c20961f7cb757db408" +#define MANTA_GIT_VERSION "commit d5d9a6c28daa8f21426d7a285f48639c0d8fd13f" -- cgit v1.2.3 From 5a02d0da7a88e31422b61d6e4e69c9f464290241 Mon Sep 17 00:00:00 2001 From: Erik Abrahamsson Date: Mon, 6 Sep 2021 17:26:55 +0200 Subject: Fluid: Parallelizations for Mantaflow functions (D12002) This update includes part of a performance boost from D12002. Contributed by @erik85 --- extern/mantaflow/preprocessed/fastmarch.cpp | 202 +++++++++++++++++++--------- 1 file changed, 140 insertions(+), 62 deletions(-) diff --git a/extern/mantaflow/preprocessed/fastmarch.cpp b/extern/mantaflow/preprocessed/fastmarch.cpp index 956725e523c..31e43483b49 100644 --- a/extern/mantaflow/preprocessed/fastmarch.cpp +++ b/extern/mantaflow/preprocessed/fastmarch.cpp @@ -874,6 +874,136 @@ static const Vec3i nb[6] = {Vec3i(1, 0, 0), Vec3i(0, 0, 1), Vec3i(0, 0, -1)}; +struct knMarkSkipCells : public KernelBase { + knMarkSkipCells(Grid &phi, Grid &tmp, bool inside) + : KernelBase(&phi, 1), phi(phi), tmp(tmp), inside(inside) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, Grid &phi, Grid &tmp, bool inside) const + { + if (!inside && phi(i, j, k) < 0.) { + tmp(i, j, k) = 1; + } + if (inside && phi(i, j, k) > 0.) { + tmp(i, j, k) = 1; + } + } + inline Grid &getArg0() + { + return phi; + } + typedef Grid type0; + inline Grid &getArg1() + { + return tmp; + } + typedef Grid type1; + inline bool &getArg2() + { + return inside; + } + typedef bool type2; + void runMessage() + { + debMsg("Executing kernel knMarkSkipCells ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 1; j < _maxY; j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, phi, tmp, inside); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, phi, tmp, inside); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range(1, maxY), *this); + } + Grid φ + Grid &tmp; + bool inside; +}; + +struct knSetFirstLayer : public KernelBase { + knSetFirstLayer(Grid &tmp, int dim) : KernelBase(&tmp, 1), tmp(tmp), dim(dim) + { + runMessage(); + run(); + } + inline void op(int i, int j, int k, Grid &tmp, int dim) const + { + Vec3i p(i, j, k); + if (tmp(p)) + return; + for (int n = 0; n < 2 * dim; ++n) { + if (tmp(p + nb[n]) == 1) { + tmp(i, j, k) = 2; + break; + } + } + } + inline Grid &getArg0() + { + return tmp; + } + typedef Grid type0; + inline int &getArg1() + { + return dim; + } + typedef int type1; + void runMessage() + { + debMsg("Executing kernel knSetFirstLayer ", 3); + debMsg("Kernel range" + << " x " << maxX << " y " << maxY << " z " << minZ << " - " << maxZ << " ", + 4); + }; + void operator()(const tbb::blocked_range &__r) const + { + const int _maxX = maxX; + const int _maxY = maxY; + if (maxZ > 1) { + for (int k = __r.begin(); k != (int)__r.end(); k++) + for (int j = 1; j < _maxY; j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, tmp, dim); + } + else { + const int k = 0; + for (int j = __r.begin(); j != (int)__r.end(); j++) + for (int i = 1; i < _maxX; i++) + op(i, j, k, tmp, dim); + } + } + void run() + { + if (maxZ > 1) + tbb::parallel_for(tbb::blocked_range(minZ, maxZ), *this); + else + tbb::parallel_for(tbb::blocked_range(1, maxY), *this); + } + Grid &tmp; + int dim; +}; + template struct knExtrapolateLsSimple : public KernelBase { knExtrapolateLsSimple(Grid &val, int distance, Grid &tmp, const int d, S direction) : KernelBase(&val, 1), val(val), distance(distance), tmp(tmp), d(d), direction(direction) @@ -1043,39 +1173,12 @@ void extrapolateLsSimple(Grid &phi, int distance = 4, bool inside = false) tmp.clear(); const int dim = (phi.is3D() ? 3 : 2); - // by default, march outside - Real direction = 1.; - if (!inside) { - // mark all inside - FOR_IJK_BND(phi, 1) - { - if (phi(i, j, k) < 0.) { - tmp(i, j, k) = 1; - } - } - } - else { - direction = -1.; - FOR_IJK_BND(phi, 1) - { - if (phi(i, j, k) > 0.) { - tmp(i, j, k) = 1; - } - } - } + // by default, march outside (ie mark all inside to be skipped) + Real direction = (inside) ? -1. : 1.; + knMarkSkipCells(phi, tmp, inside); + // + first layer around - FOR_IJK_BND(phi, 1) - { - Vec3i p(i, j, k); - if (tmp(p)) - continue; - for (int n = 0; n < 2 * dim; ++n) { - if (tmp(p + nb[n]) == 1) { - tmp(i, j, k) = 2; - n = 2 * dim; - } - } - } + knSetFirstLayer(tmp, dim); // extrapolate for distance for (int d = 2; d < 1 + distance; ++d) { @@ -1126,37 +1229,12 @@ void extrapolateVec3Simple(Grid &vel, Grid &phi, int distance = 4, b tmp.clear(); const int dim = (vel.is3D() ? 3 : 2); - // mark initial cells, by default, march outside - if (!inside) { - // mark all inside - FOR_IJK_BND(phi, 1) - { - if (phi(i, j, k) < 0.) { - tmp(i, j, k) = 1; - } - } - } - else { - FOR_IJK_BND(phi, 1) - { - if (phi(i, j, k) > 0.) { - tmp(i, j, k) = 1; - } - } - } + // mark initial cells, by default, march outside (ie mark all inside to be skipped) + Real direction = (inside) ? -1. : 1.; + knMarkSkipCells(phi, tmp, inside); + // + first layer next to initial cells - FOR_IJK_BND(vel, 1) - { - Vec3i p(i, j, k); - if (tmp(p)) - continue; - for (int n = 0; n < 2 * dim; ++n) { - if (tmp(p + nb[n]) == 1) { - tmp(i, j, k) = 2; - n = 2 * dim; - } - } - } + knSetFirstLayer(tmp, dim); for (int d = 2; d < 1 + distance; ++d) { knExtrapolateLsSimple(vel, distance, tmp, d, Vec3(0.)); -- cgit v1.2.3 From ce71357711eb0d79916045f1e67523af21b1791e Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Mon, 6 Sep 2021 17:34:59 +0200 Subject: Fix T90414: New GPencil icons Designed by @mendio The new icons are: * Dot-Dash modifier * Length Modifier * Line Art modifier --- release/datafiles/blender_icons.svg | 52 +++++++++++++++++++++ .../datafiles/blender_icons16/icon16_mod_dash.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_mod_length.dat | Bin 0 -> 1048 bytes .../blender_icons16/icon16_mod_lineart.dat | Bin 0 -> 1048 bytes .../datafiles/blender_icons32/icon32_mod_dash.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_mod_length.dat | Bin 0 -> 4120 bytes .../blender_icons32/icon32_mod_lineart.dat | Bin 0 -> 4120 bytes source/blender/editors/datafiles/CMakeLists.txt | 3 ++ source/blender/editors/include/UI_icons.h | 6 +-- 9 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 release/datafiles/blender_icons16/icon16_mod_dash.dat create mode 100644 release/datafiles/blender_icons16/icon16_mod_length.dat create mode 100644 release/datafiles/blender_icons16/icon16_mod_lineart.dat create mode 100644 release/datafiles/blender_icons32/icon32_mod_dash.dat create mode 100644 release/datafiles/blender_icons32/icon32_mod_length.dat create mode 100644 release/datafiles/blender_icons32/icon32_mod_lineart.dat diff --git a/release/datafiles/blender_icons.svg b/release/datafiles/blender_icons.svg index c3461fd1bea..70bd7dc8085 100644 --- a/release/datafiles/blender_icons.svg +++ b/release/datafiles/blender_icons.svg @@ -17321,6 +17321,58 @@ style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new" d="m 368.30892,141.58547 c -0.27613,4e-5 -0.49997,0.22388 -0.5,0.5 v 1.26473 h -4.76715 v 1.4911 h 4.76715 v 1.24417 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 0.63583,0.004 3.43318,-0.006 3.9995,-0.006 0.24106,0 0.46127,-0.0485 0.46127,-0.50967 4e-5,-0.85242 -8.9e-4,-2.98571 -8.9e-4,-3.95935 0,-0.30244 -0.19636,-0.51552 -0.46153,-0.51552 -0.82724,0 -3.36276,-0.009 -3.99823,-0.009 v 2e-5 z m 2.30359,-4.68113 -0.005,4.25868 c 0.48989,0.002 1.39549,0.005 1.88538,0.007 0.44541,0.0357 0.71675,0.47423 0.71675,0.85988 -6.6e-4,1.00616 -0.009,2.97018 -0.009,4.15122 0,0.46073 -0.24756,0.84994 -0.6533,0.84994 -0.48399,0.0143 -1.44986,-1.1e-4 -1.93405,-1.6e-4 v 3.87356 l -7.75691,-0.0669 v -14.00001 z" sodipodi:nodetypes="cccccccccccccccccccccccccc" /> + + + + + + + + + + + + + Date: Mon, 6 Sep 2021 17:58:38 +0200 Subject: make.bat: Fix missing quotes in python detection --- build_files/windows/icons.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/windows/icons.cmd b/build_files/windows/icons.cmd index 473a40885a8..d51b27d8953 100644 --- a/build_files/windows/icons.cmd +++ b/build_files/windows/icons.cmd @@ -1,4 +1,4 @@ -if EXIST %PYTHON% ( +if EXIST "%PYTHON%" ( goto detect_python_done ) -- cgit v1.2.3 From d9ad77fa58eb6301e3fedc709c946b7349c057b2 Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Mon, 6 Sep 2021 18:00:50 +0200 Subject: GPencil: Replace temp icons for final design New icons for LIneArt and Length modifier --- source/blender/makesrna/intern/rna_gpencil_modifier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 4e95174e42b..06e8f7db0af 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -70,7 +70,7 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { "Create duplication of strokes"}, {eGpencilModifierType_Lineart, "GP_LINEART", - ICON_MOD_EDGESPLIT, /* TODO: Use a proper icon. */ + ICON_MOD_LINEART, "Line Art", "Generate line art strokes from selected source"}, {eGpencilModifierType_Mirror, @@ -116,7 +116,7 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { "Deform strokes using lattice"}, {eGpencilModifierType_Length, "GP_LENGTH", - ICON_MOD_EDGESPLIT, + ICON_MOD_LENGTH, "Length", "Extend or shrink strokes"}, {eGpencilModifierType_Noise, "GP_NOISE", ICON_MOD_NOISE, "Noise", "Add noise to strokes"}, -- cgit v1.2.3 From 5a9a16334c573c4566dc9b2a314cf0d0ccdcb54f Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 6 Sep 2021 18:22:24 +0200 Subject: Geometry Nodes: support for geometry instancing Previously, the Point Instance node in geometry nodes could only instance existing objects or collections. The reason was that large parts of Blender worked under the assumption that objects are the main unit of instancing. Now we also want to instance geometry within an object, so a slightly larger refactor was necessary. This should not affect files that do not use the new kind of instances. The main change is a redefinition of what "instanced data" is. Now, an instances is a cow-object + object-data (the geometry). This can be nicely seen in `struct DupliObject`. This allows the same object to generate multiple geometries of different types which can be instanced individually. A nice side effect of this refactor is that having multiple geometry components is not a special case in the depsgraph object iterator anymore, because those components are integrated with the `DupliObject` system. Unfortunately, different systems that work with instances in Blender (e.g. render engines and exporters) often work under the assumption that objects are the main unit of instancing. So those have to be updated as well to be able to handle the new instances. This patch updates Cycles, EEVEE and other viewport engines. Exporters have not been updated yet. Some minimal (not master-ready) changes to update the obj and alembic exporters can be found in P2336 and P2335. Different file formats may want to handle these new instances in different ways. For users, the only thing that changed is that the Point Instance node now has a geometry mode. This also fixes T88454. Differential Revision: https://developer.blender.org/D11841 --- intern/cycles/blender/blender_curves.cpp | 42 ++++--- intern/cycles/blender/blender_geometry.cpp | 42 +++---- intern/cycles/blender/blender_light.cpp | 15 ++- intern/cycles/blender/blender_mesh.cpp | 61 +++++---- intern/cycles/blender/blender_object.cpp | 26 ++-- intern/cycles/blender/blender_sync.h | 29 +++-- intern/cycles/blender/blender_util.h | 49 ++++++-- intern/cycles/blender/blender_volume.cpp | 21 ++-- source/blender/blenkernel/BKE_duplilist.h | 4 + source/blender/blenkernel/BKE_geometry_set.h | 2 +- source/blender/blenkernel/BKE_geometry_set.hh | 45 ++++++- source/blender/blenkernel/BKE_object.h | 2 + .../intern/geometry_component_instances.cc | 15 ++- source/blender/blenkernel/intern/geometry_set.cc | 37 +++++- .../blenkernel/intern/geometry_set_instances.cc | 12 ++ source/blender/blenkernel/intern/object.c | 13 +- source/blender/blenkernel/intern/object_dupli.cc | 97 ++++++++++++--- source/blender/blenlib/BLI_user_counter.hh | 12 ++ source/blender/depsgraph/DEG_depsgraph_query.h | 10 +- .../depsgraph/intern/depsgraph_query_iter.cc | 138 ++------------------- source/blender/draw/intern/draw_manager.c | 64 ++++++++-- source/blender/draw/intern/draw_manager.h | 15 ++- source/blender/editors/object/object_add.c | 10 +- .../space_spreadsheet/spreadsheet_cell_value.hh | 5 + .../spreadsheet_data_source_geometry.cc | 5 + .../space_spreadsheet/spreadsheet_layout.cc | 17 +++ .../editors/transform/transform_snap_object.c | 4 +- source/blender/makesdna/DNA_node_types.h | 1 + source/blender/makesrna/intern/rna_nodetree.c | 5 + .../geometry/nodes/node_geo_point_instance.cc | 17 ++- 30 files changed, 501 insertions(+), 314 deletions(-) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 85d886fd850..6fe5ea41fff 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -526,8 +526,13 @@ bool BlenderSync::object_has_particle_hair(BL::Object b_ob) /* Old particle hair. */ void BlenderSync::sync_particle_hair( - Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step) + Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step) { + if (!b_ob_info.is_real_object_data()) { + return; + } + BL::Object b_ob = b_ob_info.real_object; + /* obtain general settings */ if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) { return; @@ -788,10 +793,10 @@ static void export_hair_curves_motion(Hair *hair, BL::Hair b_hair, int motion_st } /* Hair object. */ -void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step) +void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step) { /* Convert Blender hair to Cycles curves. */ - BL::Hair b_hair(b_ob.data()); + BL::Hair b_hair(b_ob_info.object_data); if (motion) { export_hair_curves_motion(hair, b_hair, motion_step); } @@ -800,16 +805,16 @@ void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motio } } #else -void BlenderSync::sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step) +void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step) { (void)hair; - (void)b_ob; + (void)b_ob_info; (void)motion; (void)motion_step; } #endif -void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair) +void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair) { /* make a copy of the shaders as the caller in the main thread still need them for syncing the * attributes */ @@ -819,19 +824,19 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha new_hair.set_used_shaders(used_shaders); if (view_layer.use_hair) { - if (b_ob.type() == BL::Object::type_HAIR) { + if (b_ob_info.object_data.is_a(&RNA_Hair)) { /* Hair object. */ - sync_hair(&new_hair, b_ob, false); + sync_hair(&new_hair, b_ob_info, false); } else { /* Particle hair. */ bool need_undeformed = new_hair.need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh( - b_data, b_ob, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE); + b_data, b_ob_info, b_depsgraph, need_undeformed, Mesh::SUBDIVISION_NONE); if (b_mesh) { - sync_particle_hair(&new_hair, b_mesh, b_ob, false); - free_object_to_mesh(b_data, b_ob, b_mesh); + sync_particle_hair(&new_hair, b_mesh, b_ob_info, false); + free_object_to_mesh(b_data, b_ob_info, b_mesh); } } } @@ -859,7 +864,7 @@ void BlenderSync::sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *ha } void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph, - BL::Object b_ob, + BObjectInfo &b_ob_info, Hair *hair, int motion_step) { @@ -869,18 +874,19 @@ void BlenderSync::sync_hair_motion(BL::Depsgraph b_depsgraph, } /* Export deformed coordinates. */ - if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { - if (b_ob.type() == BL::Object::type_HAIR) { + if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) { + if (b_ob_info.object_data.is_a(&RNA_Hair)) { /* Hair object. */ - sync_hair(hair, b_ob, true, motion_step); + sync_hair(hair, b_ob_info, true, motion_step); return; } else { /* Particle hair. */ - BL::Mesh b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE); + BL::Mesh b_mesh = object_to_mesh( + b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE); if (b_mesh) { - sync_particle_hair(hair, b_mesh, b_ob, true, motion_step); - free_object_to_mesh(b_data, b_ob, b_mesh); + sync_particle_hair(hair, b_mesh, b_ob_info, true, motion_step); + free_object_to_mesh(b_data, b_ob_info, b_mesh); return; } } diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp index a009018f357..acc089a286c 100644 --- a/intern/cycles/blender/blender_geometry.cpp +++ b/intern/cycles/blender/blender_geometry.cpp @@ -29,13 +29,15 @@ CCL_NAMESPACE_BEGIN -static Geometry::Type determine_geom_type(BL::Object &b_ob, bool use_particle_hair) +static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_particle_hair) { - if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) { + if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) { return Geometry::HAIR; } - if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) { + if (b_ob_info.object_data.is_a(&RNA_Volume) || + (b_ob_info.object_data == b_ob_info.real_object.data() && + object_fluid_gas_domain_find(b_ob_info.real_object))) { return Geometry::VOLUME; } @@ -71,20 +73,17 @@ array BlenderSync::find_used_shaders(BL::Object &b_ob) } Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, - BL::Object &b_ob_instance, + BObjectInfo &b_ob_info, bool object_updated, bool use_particle_hair, TaskPool *task_pool) { /* Test if we can instance or if the object is modified. */ - BL::ID b_ob_data = b_ob.data(); - BL::ID b_key_id = (BKE_object_is_modified(b_ob)) ? b_ob_instance : b_ob_data; - Geometry::Type geom_type = determine_geom_type(b_ob, use_particle_hair); - GeometryKey key(b_key_id.ptr.data, geom_type); + Geometry::Type geom_type = determine_geom_type(b_ob_info, use_particle_hair); + GeometryKey key(b_ob_info.object_data, geom_type); /* Find shader indices. */ - array used_shaders = find_used_shaders(b_ob); + array used_shaders = find_used_shaders(b_ob_info.iter_object); /* Ensure we only sync instanced geometry once. */ Geometry *geom = geometry_map.find(key); @@ -111,7 +110,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, } else { /* Test if we need to update existing geometry. */ - sync = geometry_map.update(geom, b_key_id); + sync = geometry_map.update(geom, b_ob_info.object_data); } if (!sync) { @@ -144,7 +143,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, geometry_synced.insert(geom); - geom->name = ustring(b_ob_data.name().c_str()); + geom->name = ustring(b_ob_info.object_data.name().c_str()); /* Store the shaders immediately for the object attribute code. */ geom->set_used_shaders(used_shaders); @@ -153,19 +152,19 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, if (progress.get_cancel()) return; - progress.set_sync_status("Synchronizing object", b_ob.name()); + progress.set_sync_status("Synchronizing object", b_ob_info.real_object.name()); if (geom_type == Geometry::HAIR) { Hair *hair = static_cast(geom); - sync_hair(b_depsgraph, b_ob, hair); + sync_hair(b_depsgraph, b_ob_info, hair); } else if (geom_type == Geometry::VOLUME) { Volume *volume = static_cast(geom); - sync_volume(b_ob, volume); + sync_volume(b_ob_info, volume); } else { Mesh *mesh = static_cast(geom); - sync_mesh(b_depsgraph, b_ob, mesh); + sync_mesh(b_depsgraph, b_ob_info, mesh); } }; @@ -181,7 +180,7 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, } void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, + BObjectInfo &b_ob_info, Object *object, float motion_time, bool use_particle_hair, @@ -210,16 +209,17 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, if (progress.get_cancel()) return; - if (b_ob.type() == BL::Object::type_HAIR || use_particle_hair) { + if (b_ob_info.object_data.is_a(&RNA_Hair) || use_particle_hair) { Hair *hair = static_cast(geom); - sync_hair_motion(b_depsgraph, b_ob, hair, motion_step); + sync_hair_motion(b_depsgraph, b_ob_info, hair, motion_step); } - else if (b_ob.type() == BL::Object::type_VOLUME || object_fluid_gas_domain_find(b_ob)) { + else if (b_ob_info.object_data.is_a(&RNA_Volume) || + object_fluid_gas_domain_find(b_ob_info.real_object)) { /* No volume motion blur support yet. */ } else { Mesh *mesh = static_cast(geom); - sync_mesh_motion(b_depsgraph, b_ob, mesh, motion_step); + sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step); } }; diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp index 50cd9e3db5c..542028f4b2f 100644 --- a/intern/cycles/blender/blender_light.cpp +++ b/intern/cycles/blender/blender_light.cpp @@ -27,15 +27,14 @@ CCL_NAMESPACE_BEGIN void BlenderSync::sync_light(BL::Object &b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::Object &b_ob, - BL::Object &b_ob_instance, + BObjectInfo &b_ob_info, int random_id, Transform &tfm, bool *use_portal) { /* test if we need to sync */ - ObjectKey key(b_parent, persistent_id, b_ob_instance, false); - BL::Light b_light(b_ob.data()); + ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, false); + BL::Light b_light(b_ob_info.object_data); Light *light = light_map.find(key); @@ -44,7 +43,7 @@ void BlenderSync::sync_light(BL::Object &b_parent, const bool tfm_updated = (light && light->get_tfm() != tfm); /* Update if either object or light data changed. */ - if (!light_map.add_or_update(&light, b_ob, b_parent, key) && !tfm_updated) { + if (!light_map.add_or_update(&light, b_ob_info.real_object, b_parent, key) && !tfm_updated) { Shader *shader; if (!shader_map.add_or_update(&shader, b_light)) { if (light->get_is_portal()) @@ -139,11 +138,11 @@ void BlenderSync::sync_light(BL::Object &b_parent, light->set_max_bounces(get_int(clight, "max_bounces")); - if (b_ob != b_ob_instance) { + if (b_ob_info.real_object != b_ob_info.iter_object) { light->set_random_id(random_id); } else { - light->set_random_id(hash_uint2(hash_string(b_ob.name().c_str()), 0)); + light->set_random_id(hash_uint2(hash_string(b_ob_info.real_object.name().c_str()), 0)); } if (light->get_light_type() == LIGHT_AREA) @@ -155,7 +154,7 @@ void BlenderSync::sync_light(BL::Object &b_parent, *use_portal = true; /* visibility */ - uint visibility = object_ray_visibility(b_ob); + uint visibility = object_ray_visibility(b_ob_info.real_object); light->set_use_diffuse((visibility & PATH_RAY_DIFFUSE) != 0); light->set_use_glossy((visibility & PATH_RAY_GLOSSY) != 0); light->set_use_transmission((visibility & PATH_RAY_TRANSMIT) != 0); diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index ebba6981502..9bb3447f56b 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -999,12 +999,14 @@ static void create_mesh(Scene *scene, static void create_subd_mesh(Scene *scene, Mesh *mesh, - BL::Object &b_ob, + BObjectInfo &b_ob_info, BL::Mesh &b_mesh, const array &used_shaders, float dicing_rate, int max_subdivisions) { + BL::Object b_ob = b_ob_info.real_object; + BL::SubsurfModifier subsurf_mod(b_ob.modifiers[b_ob.modifiers.length() - 1]); bool subdivide_uvs = subsurf_mod.uv_smooth() != BL::SubsurfModifier::uv_smooth_NONE; @@ -1043,7 +1045,7 @@ static void create_subd_mesh(Scene *scene, * * NOTE: This code is run prior to object motion blur initialization. so can not access properties * set by `sync_object_motion_init()`. */ -static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene) +static bool mesh_need_motion_attribute(BObjectInfo &b_ob_info, Scene *scene) { const Scene::MotionType need_motion = scene->need_motion(); if (need_motion == Scene::MOTION_NONE) { @@ -1060,7 +1062,7 @@ static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene) * - Motion attribute expects non-zero time steps. * * Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */ - PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); + PointerRNA cobject = RNA_pointer_get(&b_ob_info.real_object.ptr, "cycles"); const bool use_motion = get_boolean(cobject, "use_motion_blur"); if (!use_motion) { return false; @@ -1072,12 +1074,13 @@ static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene) return true; } -static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *mesh) +static void sync_mesh_cached_velocities(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh) { - if (!mesh_need_motion_attribute(b_ob, scene)) { + if (!mesh_need_motion_attribute(b_ob_info, scene)) { return; } + BL::Object b_ob = b_ob_info.real_object; BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, true, nullptr); if (!b_mesh_cache) { @@ -1118,12 +1121,16 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me } } -static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) +static void sync_mesh_fluid_motion(BObjectInfo &b_ob_info, Scene *scene, Mesh *mesh) { - if (!mesh_need_motion_attribute(b_ob, scene)) { + if (!b_ob_info.is_real_object_data()) { + return; + } + if (!mesh_need_motion_attribute(b_ob_info, scene)) { return; } + BL::Object b_ob = b_ob_info.real_object; BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob); if (!b_fluid_domain) @@ -1157,7 +1164,7 @@ static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) } } -void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh) +void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh) { /* make a copy of the shaders as the caller in the main thread still need them for syncing the * attributes */ @@ -1170,20 +1177,21 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me /* Adaptive subdivision setup. Not for baking since that requires * exact mapping to the Blender mesh. */ if (!scene->bake_manager->get_baking()) { - new_mesh.set_subdivision_type(object_subdivision_type(b_ob, preview, experimental)); + new_mesh.set_subdivision_type( + object_subdivision_type(b_ob_info.real_object, preview, experimental)); } /* For some reason, meshes do not need this... */ bool need_undeformed = new_mesh.need_attribute(scene, ATTR_STD_GENERATED); BL::Mesh b_mesh = object_to_mesh( - b_data, b_ob, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type()); + b_data, b_ob_info, b_depsgraph, need_undeformed, new_mesh.get_subdivision_type()); if (b_mesh) { /* Sync mesh itself. */ if (new_mesh.get_subdivision_type() != Mesh::SUBDIVISION_NONE) create_subd_mesh(scene, &new_mesh, - b_ob, + b_ob_info, b_mesh, new_mesh.get_used_shaders(), dicing_rate, @@ -1191,15 +1199,15 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me else create_mesh(scene, &new_mesh, b_mesh, new_mesh.get_used_shaders(), false); - free_object_to_mesh(b_data, b_ob, b_mesh); + free_object_to_mesh(b_data, b_ob_info, b_mesh); } } /* cached velocities (e.g. from alembic archive) */ - sync_mesh_cached_velocities(b_ob, scene, &new_mesh); + sync_mesh_cached_velocities(b_ob_info, scene, &new_mesh); /* mesh fluid motion mantaflow */ - sync_mesh_fluid_motion(b_ob, scene, &new_mesh); + sync_mesh_fluid_motion(b_ob_info, scene, &new_mesh); /* update original sockets */ @@ -1230,18 +1238,19 @@ void BlenderSync::sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *me } void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, - BL::Object b_ob, + BObjectInfo &b_ob_info, Mesh *mesh, int motion_step) { /* Fluid motion blur already exported. */ - BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob); + BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob_info.real_object); if (b_fluid_domain) { return; } /* Cached motion blur already exported. */ - BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, true, nullptr); + BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find( + b_ob_info.real_object, true, nullptr); if (mesh_cache) { return; } @@ -1255,11 +1264,13 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, /* Skip objects without deforming modifiers. this is not totally reliable, * would need a more extensive check to see which objects are animated. */ BL::Mesh b_mesh(PointerRNA_NULL); - if (ccl::BKE_object_is_deform_modified(b_ob, b_scene, preview)) { + if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) { /* get derived mesh */ - b_mesh = object_to_mesh(b_data, b_ob, b_depsgraph, false, Mesh::SUBDIVISION_NONE); + b_mesh = object_to_mesh(b_data, b_ob_info, b_depsgraph, false, Mesh::SUBDIVISION_NONE); } + const std::string ob_name = b_ob_info.real_object.name(); + /* TODO(sergey): Perform preliminary check for number of vertices. */ if (b_mesh) { /* Export deformed coordinates. */ @@ -1295,17 +1306,17 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, memcmp(mP, &mesh->get_verts()[0], sizeof(float3) * numverts) == 0) { /* no motion, remove attributes again */ if (b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, disabling motion blur for object " << b_ob.name(); + VLOG(1) << "Topology differs, disabling motion blur for object " << ob_name; } else { - VLOG(1) << "No actual deformation motion for object " << b_ob.name(); + VLOG(1) << "No actual deformation motion for object " << ob_name; } mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mN) mesh->attributes.remove(ATTR_STD_MOTION_VERTEX_NORMAL); } else if (motion_step > 0) { - VLOG(1) << "Filling deformation motion for object " << b_ob.name(); + VLOG(1) << "Filling deformation motion for object " << ob_name; /* motion, fill up previous steps that we might have skipped because * they had no motion, but we need them anyway now */ float3 *P = &mesh->get_verts()[0]; @@ -1319,8 +1330,8 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, } else { if (b_mesh.vertices.length() != numverts) { - VLOG(1) << "Topology differs, discarding motion blur for object " << b_ob.name() - << " at time " << motion_step; + VLOG(1) << "Topology differs, discarding motion blur for object " << ob_name << " at time " + << motion_step; memcpy(mP, &mesh->get_verts()[0], sizeof(float3) * numverts); if (mN != NULL) { memcpy(mN, attr_N->data_float3(), sizeof(float3) * numverts); @@ -1328,7 +1339,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, } } - free_object_to_mesh(b_data, b_ob, b_mesh); + free_object_to_mesh(b_data, b_ob_info, b_mesh); return; } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 5d98b61b409..2243baca0b2 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -154,7 +154,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, const bool is_instance = b_instance.is_instance(); BL::Object b_ob = b_instance.object(); BL::Object b_parent = is_instance ? b_instance.parent() : b_instance.object(); - BL::Object b_ob_instance = is_instance ? b_instance.instance_object() : b_ob; + BObjectInfo b_ob_info{b_ob, is_instance ? b_instance.instance_object() : b_ob, b_ob.data()}; const bool motion = motion_time != 0.0f; /*const*/ Transform tfm = get_transform(b_ob.matrix_world()); int *persistent_id = NULL; @@ -178,8 +178,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, { sync_light(b_parent, persistent_id, - b_ob, - b_ob_instance, + b_ob_info, is_instance ? b_instance.random_id() : 0, tfm, use_portal); @@ -231,7 +230,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, TaskPool *object_geom_task_pool = (is_instance) ? NULL : geom_task_pool; /* key to lookup object */ - ObjectKey key(b_parent, persistent_id, b_ob_instance, use_particle_hair); + ObjectKey key(b_parent, persistent_id, b_ob_info.real_object, use_particle_hair); Object *object; /* motion vector case */ @@ -249,12 +248,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, /* mesh deformation */ if (object->get_geometry()) - sync_geometry_motion(b_depsgraph, - b_ob_instance, - object, - motion_time, - use_particle_hair, - object_geom_task_pool); + sync_geometry_motion( + b_depsgraph, b_ob_info, object, motion_time, use_particle_hair, object_geom_task_pool); } return object; @@ -265,15 +260,8 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, (tfm != object->get_tfm()); /* mesh sync */ - /* b_ob is owned by the iterator and will go out of scope at the end of the block. - * b_ob_instance is the original object and will remain valid for deferred geometry - * sync. */ - Geometry *geometry = sync_geometry(b_depsgraph, - b_ob_instance, - b_ob_instance, - object_updated, - use_particle_hair, - object_geom_task_pool); + Geometry *geometry = sync_geometry( + b_depsgraph, b_ob_info, object_updated, use_particle_hair, object_geom_task_pool); object->set_geometry(geometry); /* special case not tracked by object update flags */ diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 44322dda6b9..76e8f23864c 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -23,6 +23,7 @@ #include "RNA_types.h" #include "blender/blender_id_map.h" +#include "blender/blender_util.h" #include "blender/blender_viewport.h" #include "render/scene.h" @@ -158,18 +159,24 @@ class BlenderSync { bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object); /* Volume */ - void sync_volume(BL::Object &b_ob, Volume *volume); + void sync_volume(BObjectInfo &b_ob_info, Volume *volume); /* Mesh */ - void sync_mesh(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh); - void sync_mesh_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Mesh *mesh, int motion_step); + void sync_mesh(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Mesh *mesh); + void sync_mesh_motion(BL::Depsgraph b_depsgraph, + BObjectInfo &b_ob_info, + Mesh *mesh, + int motion_step); /* Hair */ - void sync_hair(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair); - void sync_hair_motion(BL::Depsgraph b_depsgraph, BL::Object b_ob, Hair *hair, int motion_step); - void sync_hair(Hair *hair, BL::Object &b_ob, bool motion, int motion_step = 0); + void sync_hair(BL::Depsgraph b_depsgraph, BObjectInfo &b_ob_info, Hair *hair); + void sync_hair_motion(BL::Depsgraph b_depsgraph, + BObjectInfo &b_ob_info, + Hair *hair, + int motion_step); + void sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int motion_step = 0); void sync_particle_hair( - Hair *hair, BL::Mesh &b_mesh, BL::Object &b_ob, bool motion, int motion_step = 0); + Hair *hair, BL::Mesh &b_mesh, BObjectInfo &b_ob_info, bool motion, int motion_step = 0); bool object_has_particle_hair(BL::Object b_ob); /* Camera */ @@ -178,14 +185,13 @@ class BlenderSync { /* Geometry */ Geometry *sync_geometry(BL::Depsgraph &b_depsgrpah, - BL::Object &b_ob, - BL::Object &b_ob_instance, + BObjectInfo &b_ob_info, bool object_updated, bool use_particle_hair, TaskPool *task_pool); void sync_geometry_motion(BL::Depsgraph &b_depsgraph, - BL::Object &b_ob, + BObjectInfo &b_ob_info, Object *object, float motion_time, bool use_particle_hair, @@ -194,8 +200,7 @@ class BlenderSync { /* Light */ void sync_light(BL::Object &b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::Object &b_ob, - BL::Object &b_ob_instance, + BObjectInfo &b_ob_info, int random_id, Transform &tfm, bool *use_portal); diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index f6824f31b7b..e69531ea707 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -40,6 +40,28 @@ float *BKE_image_get_float_pixels_for_frame(void *image, int frame, int tile); CCL_NAMESPACE_BEGIN +struct BObjectInfo { + /* Object directly provided by the depsgraph iterator. This object is only valid during one + * iteration and must not be accessed afterwards. Transforms and visibility should be checked on + * this object. */ + BL::Object iter_object; + + /* This object remains alive even after the object iterator is done. It corresponds to one + * original object. It is the object that owns the object data below. */ + BL::Object real_object; + + /* The object-data referenced by the iter object. This is still valid after the depsgraph + * iterator is done. It might have a different type compared to real_object.data(). */ + BL::ID object_data; + + /* True when the current geometry is the data of the referenced object. False when it is a + * geometry instance that does not have a 1-to-1 relationship with an object. */ + bool is_real_object_data() const + { + return const_cast(real_object).data() == object_data; + } +}; + typedef BL::ShaderNodeAttribute::attribute_type_enum BlenderAttributeType; BlenderAttributeType blender_attribute_name_split_type(ustring name, string *r_real_name); @@ -47,7 +69,7 @@ void python_thread_state_save(void **python_thread_state); void python_thread_state_restore(void **python_thread_state); static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, - BL::Object &object, + BObjectInfo &b_ob_info, BL::Depsgraph & /*depsgraph*/, bool /*calc_undeformed*/, Mesh::SubdivisionType subdivision_type) @@ -69,9 +91,9 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, #endif BL::Mesh mesh(PointerRNA_NULL); - if (object.type() == BL::Object::type_MESH) { + if (b_ob_info.object_data.is_a(&RNA_Mesh)) { /* TODO: calc_undeformed is not used. */ - mesh = BL::Mesh(object.data()); + mesh = BL::Mesh(b_ob_info.object_data); /* Make a copy to split faces if we use autosmooth, otherwise not needed. * Also in edit mode do we need to make a copy, to ensure data layers like @@ -79,12 +101,15 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, if (mesh.is_editmode() || (mesh.use_auto_smooth() && subdivision_type == Mesh::SUBDIVISION_NONE)) { BL::Depsgraph depsgraph(PointerRNA_NULL); - mesh = object.to_mesh(false, depsgraph); + assert(b_ob_info.is_real_object_data()); + mesh = b_ob_info.real_object.to_mesh(false, depsgraph); } } else { BL::Depsgraph depsgraph(PointerRNA_NULL); - mesh = object.to_mesh(false, depsgraph); + if (b_ob_info.is_real_object_data()) { + mesh = b_ob_info.real_object.to_mesh(false, depsgraph); + } } #if 0 @@ -108,10 +133,14 @@ static inline BL::Mesh object_to_mesh(BL::BlendData & /*data*/, } static inline void free_object_to_mesh(BL::BlendData & /*data*/, - BL::Object &object, + BObjectInfo &b_ob_info, BL::Mesh &mesh) { + if (!b_ob_info.is_real_object_data()) { + return; + } /* Free mesh if we didn't just use the existing one. */ + BL::Object object = b_ob_info.real_object; if (object.data().ptr.data != mesh.ptr.data) { object.to_mesh_clear(); } @@ -219,9 +248,13 @@ static inline bool BKE_object_is_modified(BL::Object &self, BL::Scene &scene, bo return self.is_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false; } -static inline bool BKE_object_is_deform_modified(BL::Object &self, BL::Scene &scene, bool preview) +static inline bool BKE_object_is_deform_modified(BObjectInfo &self, BL::Scene &scene, bool preview) { - return self.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : false; + if (!self.is_real_object_data()) { + return false; + } + return self.real_object.is_deform_modified(scene, (preview) ? (1 << 0) : (1 << 1)) ? true : + false; } static inline int render_resolution_x(BL::RenderSettings &b_render) diff --git a/intern/cycles/blender/blender_volume.cpp b/intern/cycles/blender/blender_volume.cpp index 772ab9f5c8a..0a5b19d7d4c 100644 --- a/intern/cycles/blender/blender_volume.cpp +++ b/intern/cycles/blender/blender_volume.cpp @@ -181,9 +181,12 @@ class BlenderSmokeLoader : public ImageLoader { AttributeStandard attribute; }; -static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, float frame) +static void sync_smoke_volume(Scene *scene, BObjectInfo &b_ob_info, Volume *volume, float frame) { - BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob); + if (!b_ob_info.is_real_object_data()) { + return; + } + BL::FluidDomainSettings b_domain = object_fluid_gas_domain_find(b_ob_info.real_object); if (!b_domain) { return; } @@ -206,7 +209,7 @@ static void sync_smoke_volume(Scene *scene, BL::Object &b_ob, Volume *volume, fl Attribute *attr = volume->attributes.add(std); - ImageLoader *loader = new BlenderSmokeLoader(b_ob, std); + ImageLoader *loader = new BlenderSmokeLoader(b_ob_info.real_object, std); ImageParams params; params.frame = frame; @@ -244,11 +247,11 @@ class BlenderVolumeLoader : public VDBImageLoader { }; static void sync_volume_object(BL::BlendData &b_data, - BL::Object &b_ob, + BObjectInfo &b_ob_info, Scene *scene, Volume *volume) { - BL::Volume b_volume(b_ob.data()); + BL::Volume b_volume(b_ob_info.object_data); b_volume.grids.load(b_data.ptr.data); BL::VolumeRender b_render(b_volume.render()); @@ -296,19 +299,19 @@ static void sync_volume_object(BL::BlendData &b_data, } } -void BlenderSync::sync_volume(BL::Object &b_ob, Volume *volume) +void BlenderSync::sync_volume(BObjectInfo &b_ob_info, Volume *volume) { volume->clear(true); if (view_layer.use_volumes) { - if (b_ob.type() == BL::Object::type_VOLUME) { + if (b_ob_info.object_data.is_a(&RNA_Volume)) { /* Volume object. Create only attributes, bounding mesh will then * be automatically generated later. */ - sync_volume_object(b_data, b_ob, scene, volume); + sync_volume_object(b_data, b_ob_info, scene, volume); } else { /* Smoke domain. */ - sync_smoke_volume(scene, b_ob, volume, b_scene.frame_current()); + sync_smoke_volume(scene, b_ob_info, volume, b_scene.frame_current()); } } diff --git a/source/blender/blenkernel/BKE_duplilist.h b/source/blender/blenkernel/BKE_duplilist.h index c142d5338d1..989b68f4ccb 100644 --- a/source/blender/blenkernel/BKE_duplilist.h +++ b/source/blender/blenkernel/BKE_duplilist.h @@ -31,6 +31,7 @@ struct ListBase; struct Object; struct ParticleSystem; struct Scene; +struct ID; /* ---------------------------------------------------- */ /* Dupli-Geometry */ @@ -42,7 +43,10 @@ void free_object_duplilist(struct ListBase *lb); typedef struct DupliObject { struct DupliObject *next, *prev; + /* Object whose geometry is instanced. */ struct Object *ob; + /* Data owned by the object above that is instanced. This might not be the same as `ob->data`. */ + struct ID *ob_data; float mat[4][4]; float orco[3], uv[2]; diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h index 5f6a9ec7b91..17cdb9d6a42 100644 --- a/source/blender/blenkernel/BKE_geometry_set.h +++ b/source/blender/blenkernel/BKE_geometry_set.h @@ -41,7 +41,7 @@ typedef enum GeometryComponentType { void BKE_geometry_set_free(struct GeometrySet *geometry_set); -bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set); +bool BKE_object_has_geometry_set_instances(const struct Object *ob); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh index 42e9ce82278..08b6cb951a8 100644 --- a/source/blender/blenkernel/BKE_geometry_set.hh +++ b/source/blender/blenkernel/BKE_geometry_set.hh @@ -283,6 +283,7 @@ struct GeometrySet { void clear(); + bool owns_direct_data() const; void ensure_owns_direct_data(); /* Utility methods for creation. */ @@ -447,12 +448,14 @@ class InstanceReference { None, Object, Collection, + GeometrySet, }; private: Type type_ = Type::None; /** Depending on the type this is either null, an Object or Collection pointer. */ void *data_ = nullptr; + std::unique_ptr geometry_set_; public: InstanceReference() = default; @@ -465,6 +468,19 @@ class InstanceReference { { } + InstanceReference(GeometrySet geometry_set) + : type_(Type::GeometrySet), + geometry_set_(std::make_unique(std::move(geometry_set))) + { + } + + InstanceReference(const InstanceReference &src) : type_(src.type_), data_(src.data_) + { + if (src.type_ == Type::GeometrySet) { + geometry_set_ = std::make_unique(*src.geometry_set_); + } + } + Type type() const { return type_; @@ -482,14 +498,37 @@ class InstanceReference { return *(Collection *)data_; } + const GeometrySet &geometry_set() const + { + BLI_assert(type_ == Type::GeometrySet); + return *geometry_set_; + } + + bool owns_direct_data() const + { + if (type_ != Type::GeometrySet) { + /* The object and collection instances are not direct data. */ + return true; + } + return geometry_set_->owns_direct_data(); + } + + void ensure_owns_direct_data() + { + if (type_ != Type::GeometrySet) { + return; + } + geometry_set_->ensure_owns_direct_data(); + } + uint64_t hash() const { - return blender::get_default_hash(data_); + return blender::get_default_hash_2(data_, geometry_set_.get()); } friend bool operator==(const InstanceReference &a, const InstanceReference &b) { - return a.data_ == b.data_; + return a.data_ == b.data_ && a.geometry_set_.get() == b.geometry_set_.get(); } }; @@ -529,7 +568,7 @@ class InstancesComponent : public GeometryComponent { void reserve(int min_capacity); void resize(int capacity); - int add_reference(InstanceReference reference); + int add_reference(const InstanceReference &reference); void add_instance(int instance_handle, const blender::float4x4 &transform, const int id = -1); blender::Span references() const; diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index a823602e341..31b3cd66cbb 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -458,6 +458,8 @@ void BKE_object_modifiers_lib_link_common(void *userData, struct ID **idpoin, int cb_flag); +void BKE_object_replace_data_on_shallow_copy(struct Object *ob, struct ID *new_data); + struct PartEff; struct PartEff *BKE_object_do_version_give_parteff_245(struct Object *ob); diff --git a/source/blender/blenkernel/intern/geometry_component_instances.cc b/source/blender/blenkernel/intern/geometry_component_instances.cc index 3b1b7456162..26ef827d36d 100644 --- a/source/blender/blenkernel/intern/geometry_component_instances.cc +++ b/source/blender/blenkernel/intern/geometry_component_instances.cc @@ -122,7 +122,7 @@ blender::Span InstancesComponent::instance_ids() const * If the reference exists already, the handle of the existing reference is returned. * Otherwise a new handle is added. */ -int InstancesComponent::add_reference(InstanceReference reference) +int InstancesComponent::add_reference(const InstanceReference &reference) { return references_.index_of_or_add_as(reference); } @@ -144,14 +144,23 @@ bool InstancesComponent::is_empty() const bool InstancesComponent::owns_direct_data() const { - /* The object and collection instances are not direct data. Instance transforms are direct data - * and are always owned. Therefore, instance components always own all their direct data. */ + for (const InstanceReference &reference : references_) { + if (!reference.owns_direct_data()) { + return false; + } + } return true; } void InstancesComponent::ensure_owns_direct_data() { BLI_assert(this->is_mutable()); + for (const InstanceReference &const_reference : references_) { + /* Const cast is fine because we are not changing anything that would change the hash of the + * reference. */ + InstanceReference &reference = const_cast(const_reference); + reference.ensure_owns_direct_data(); + } } static blender::Array generate_unique_instance_ids(Span original_ids) diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc index 07b4e715ea9..dafebef1812 100644 --- a/source/blender/blenkernel/intern/geometry_set.cc +++ b/source/blender/blenkernel/intern/geometry_set.cc @@ -218,6 +218,16 @@ void GeometrySet::ensure_owns_direct_data() } } +bool GeometrySet::owns_direct_data() const +{ + for (const GeometryComponentPtr &component : components_.values()) { + if (!component->owns_direct_data()) { + return false; + } + } + return true; +} + /* Returns a read-only mesh or null. */ const Mesh *GeometrySet::get_mesh_for_read() const { @@ -376,9 +386,32 @@ void BKE_geometry_set_free(GeometrySet *geometry_set) delete geometry_set; } -bool BKE_geometry_set_has_instances(const GeometrySet *geometry_set) +bool BKE_object_has_geometry_set_instances(const Object *ob) { - return geometry_set->get_component_for_read() != nullptr; + const GeometrySet *geometry_set = ob->runtime.geometry_set_eval; + if (geometry_set == nullptr) { + return false; + } + if (geometry_set->has_instances()) { + return true; + } + const bool has_mesh = geometry_set->has_mesh(); + const bool has_pointcloud = geometry_set->has_pointcloud(); + const bool has_volume = geometry_set->has_volume(); + const bool has_curve = geometry_set->has_curve(); + if (ob->type == OB_MESH) { + return has_pointcloud || has_volume || has_curve; + } + if (ob->type == OB_POINTCLOUD) { + return has_mesh || has_volume || has_curve; + } + if (ob->type == OB_VOLUME) { + return has_mesh || has_pointcloud || has_curve; + } + if (ob->type == OB_CURVE) { + return has_mesh || has_pointcloud || has_volume; + } + return false; } /** \} */ diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 32a65ab47bf..376792b9b96 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -168,6 +168,11 @@ static void geometry_set_collect_recursive(const GeometrySet &geometry_set, collection, instance_transform, r_sets); break; } + case InstanceReference::Type::GeometrySet: { + const GeometrySet &geometry_set = reference.geometry_set(); + geometry_set_collect_recursive(geometry_set, instance_transform, r_sets); + break; + } case InstanceReference::Type::None: { break; } @@ -290,6 +295,13 @@ static bool instances_attribute_foreach_recursive(const GeometrySet &geometry_se } break; } + case InstanceReference::Type::GeometrySet: { + const GeometrySet &geometry_set = reference.geometry_set(); + if (!instances_attribute_foreach_recursive(geometry_set, callback, limit, count)) { + return false; + } + break; + } case InstanceReference::Type::None: { break; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 062264c5729..bca1afbf101 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1979,8 +1979,7 @@ int BKE_object_visibility(const Object *ob, const int dag_eval_mode) visibility |= OB_VISIBLE_INSTANCES; } - if (ob->runtime.geometry_set_eval != NULL && - BKE_geometry_set_has_instances(ob->runtime.geometry_set_eval)) { + if (BKE_object_has_geometry_set_instances(ob)) { visibility |= OB_VISIBLE_INSTANCES; } @@ -5737,3 +5736,13 @@ void BKE_object_modifiers_lib_link_common(void *userData, id_us_plus_no_lib(*idpoin); } } + +void BKE_object_replace_data_on_shallow_copy(Object *ob, ID *new_data) +{ + ob->type = BKE_object_obdata_to_type(new_data); + ob->data = new_data; + ob->runtime.geometry_set_eval = NULL; + ob->runtime.data_eval = NULL; + ob->runtime.bb->flag |= BOUNDBOX_DIRTY; + ob->id.py_instance = NULL; +} diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index a46ac4b1175..47d4d03d1e1 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -194,6 +194,7 @@ static DupliObject *make_dupli(const DupliContext *ctx, } dob->ob = ob; + dob->ob_data = (ID *)ob->data; mul_m4_m4m4(dob->mat, (float(*)[4])ctx->space_mat, mat); dob->type = ctx->gen->type; @@ -834,14 +835,59 @@ static const DupliGenerator gen_dupli_verts_pointcloud = { /** \name Instances Geometry Component Implementation * \{ */ -static void make_duplis_instances_component(const DupliContext *ctx) +static void make_duplis_geometry_set_impl(const DupliContext *ctx, + const GeometrySet &geometry_set, + const float parent_transform[4][4], + bool geometry_set_is_instance) { - const InstancesComponent *component = - ctx->object->runtime.geometry_set_eval->get_component_for_read(); + int component_index = 0; + if (ctx->object->type != OB_MESH || geometry_set_is_instance) { + const Mesh *mesh = geometry_set.get_mesh_for_read(); + if (mesh != nullptr) { + DupliObject *dupli = make_dupli(ctx, ctx->object, parent_transform, component_index++); + dupli->ob_data = (ID *)mesh; + } + } + if (ctx->object->type != OB_VOLUME || geometry_set_is_instance) { + const Volume *volume = geometry_set.get_volume_for_read(); + if (volume != nullptr) { + DupliObject *dupli = make_dupli(ctx, ctx->object, parent_transform, component_index++); + dupli->ob_data = (ID *)volume; + } + } + if (ctx->object->type != OB_CURVE || geometry_set_is_instance) { + const CurveComponent *curve_component = geometry_set.get_component_for_read(); + if (curve_component != nullptr) { + const Curve *curve = curve_component->get_curve_for_render(); + if (curve != nullptr) { + DupliObject *dupli = make_dupli(ctx, ctx->object, parent_transform, component_index++); + dupli->ob_data = (ID *)curve; + } + } + } + if (ctx->object->type != OB_POINTCLOUD || geometry_set_is_instance) { + const PointCloud *pointcloud = geometry_set.get_pointcloud_for_read(); + if (pointcloud != nullptr) { + DupliObject *dupli = make_dupli(ctx, ctx->object, parent_transform, component_index++); + dupli->ob_data = (ID *)pointcloud; + } + } + const bool creates_duplis_for_components = component_index >= 1; + + const InstancesComponent *component = geometry_set.get_component_for_read(); if (component == nullptr) { return; } + const DupliContext *instances_ctx = ctx; + /* Create a sub-context if some duplis were created above. This is to avoid dupli id collisions + * between the instances component below and the other components above. */ + DupliContext new_instances_ctx; + if (creates_duplis_for_components) { + copy_dupli_context(&new_instances_ctx, ctx, ctx->object, nullptr, component_index); + instances_ctx = &new_instances_ctx; + } + Span instance_offset_matrices = component->instance_transforms(); Span instance_reference_handles = component->instance_reference_handles(); Span almost_unique_ids = component->almost_unique_ids(); @@ -855,13 +901,13 @@ static void make_duplis_instances_component(const DupliContext *ctx) case InstanceReference::Type::Object: { Object &object = reference.object(); float matrix[4][4]; - mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrices[i].values); - make_dupli(ctx, &object, matrix, id); + mul_m4_m4m4(matrix, parent_transform, instance_offset_matrices[i].values); + make_dupli(instances_ctx, &object, matrix, id); float space_matrix[4][4]; mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object.imat); - mul_m4_m4_pre(space_matrix, ctx->object->obmat); - make_recursive_duplis(ctx, &object, space_matrix, id); + mul_m4_m4_pre(space_matrix, parent_transform); + make_recursive_duplis(instances_ctx, &object, space_matrix, id); break; } case InstanceReference::Type::Collection: { @@ -870,23 +916,36 @@ static void make_duplis_instances_component(const DupliContext *ctx) unit_m4(collection_matrix); sub_v3_v3(collection_matrix[3], collection.instance_offset); mul_m4_m4_pre(collection_matrix, instance_offset_matrices[i].values); - mul_m4_m4_pre(collection_matrix, ctx->object->obmat); + mul_m4_m4_pre(collection_matrix, parent_transform); + + DupliContext sub_ctx; + copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id); - eEvaluationMode mode = DEG_get_mode(ctx->depsgraph); + eEvaluationMode mode = DEG_get_mode(instances_ctx->depsgraph); + int object_id = 0; FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (&collection, object, mode) { - if (object == ctx->object) { + if (object == instances_ctx->object) { continue; } float instance_matrix[4][4]; mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat); - make_dupli(ctx, object, instance_matrix, id); - make_recursive_duplis(ctx, object, collection_matrix, id); + make_dupli(&sub_ctx, object, instance_matrix, object_id++); + make_recursive_duplis(&sub_ctx, object, collection_matrix, object_id++); } FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; break; } + case InstanceReference::Type::GeometrySet: { + float new_transform[4][4]; + mul_m4_m4m4(new_transform, parent_transform, instance_offset_matrices[i].values); + + DupliContext sub_ctx; + copy_dupli_context(&sub_ctx, instances_ctx, instances_ctx->object, nullptr, id); + make_duplis_geometry_set_impl(&sub_ctx, reference.geometry_set(), new_transform, true); + break; + } case InstanceReference::Type::None: { break; } @@ -894,9 +953,15 @@ static void make_duplis_instances_component(const DupliContext *ctx) } } -static const DupliGenerator gen_dupli_instances_component = { +static void make_duplis_geometry_set(const DupliContext *ctx) +{ + const GeometrySet *geometry_set = ctx->object->runtime.geometry_set_eval; + make_duplis_geometry_set_impl(ctx, *geometry_set, ctx->object->obmat, false); +} + +static const DupliGenerator gen_dupli_geometry_set = { 0, - make_duplis_instances_component, + make_duplis_geometry_set, }; /** \} */ @@ -1567,8 +1632,8 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) } if (ctx->object->runtime.geometry_set_eval != nullptr) { - if (BKE_geometry_set_has_instances(ctx->object->runtime.geometry_set_eval)) { - return &gen_dupli_instances_component; + if (BKE_object_has_geometry_set_instances(ctx->object)) { + return &gen_dupli_geometry_set; } } diff --git a/source/blender/blenlib/BLI_user_counter.hh b/source/blender/blenlib/BLI_user_counter.hh index 3e6d5af4c3f..8cebadeac4c 100644 --- a/source/blender/blenlib/BLI_user_counter.hh +++ b/source/blender/blenlib/BLI_user_counter.hh @@ -84,12 +84,24 @@ template class UserCounter { return data_; } + const T *operator->() const + { + BLI_assert(data_ != nullptr); + return data_; + } + T &operator*() { BLI_assert(data_ != nullptr); return *data_; } + const T &operator*() const + { + BLI_assert(data_ != nullptr); + return *data_; + } + operator bool() const { return data_ != nullptr; diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 17f5ca0db79..e9195a1eb26 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -145,15 +145,7 @@ typedef struct DEGObjectIterData { eEvaluationMode eval_mode; - /* **** Iteration over geometry components **** */ - - /* The object whose components we currently iterate over. - * This might point to #temp_dupli_object. */ - struct Object *geometry_component_owner; - /* Some identifier that is used to determine which geometry component should be returned next. */ - int geometry_component_id; - /* Temporary storage for an object that is created from a component. */ - struct Object temp_geometry_component_object; + struct Object *next_object; /* **** Iteration over dupli-list. *** */ diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index 770d9775dd3..7af3d03d478 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -120,130 +120,6 @@ bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject return false; } -void deg_iterator_components_init(DEGObjectIterData *data, Object *object) -{ - data->geometry_component_owner = object; - data->geometry_component_id = 0; -} - -/* Returns false when iterator is exhausted. */ -bool deg_iterator_components_step(BLI_Iterator *iter) -{ - DEGObjectIterData *data = (DEGObjectIterData *)iter->data; - if (data->geometry_component_owner == nullptr) { - return false; - } - - if (data->geometry_component_owner->runtime.geometry_set_eval == nullptr) { - /* Return the object itself, if it does not have a geometry set yet. */ - iter->current = data->geometry_component_owner; - data->geometry_component_owner = nullptr; - return true; - } - - GeometrySet *geometry_set = data->geometry_component_owner->runtime.geometry_set_eval; - if (geometry_set == nullptr) { - data->geometry_component_owner = nullptr; - return false; - } - - /* The mesh component. */ - if (data->geometry_component_id == 0) { - data->geometry_component_id++; - - /* Don't use a temporary object for this component, when the owner is a mesh object. */ - if (data->geometry_component_owner->type == OB_MESH) { - iter->current = data->geometry_component_owner; - return true; - } - - const Mesh *mesh = geometry_set->get_mesh_for_read(); - if (mesh != nullptr) { - Object *temp_object = &data->temp_geometry_component_object; - *temp_object = *data->geometry_component_owner; - temp_object->type = OB_MESH; - temp_object->data = (void *)mesh; - temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; - iter->current = temp_object; - return true; - } - } - - /* The pointcloud component. */ - if (data->geometry_component_id == 1) { - data->geometry_component_id++; - - /* Don't use a temporary object for this component, when the owner is a point cloud object. */ - if (data->geometry_component_owner->type == OB_POINTCLOUD) { - iter->current = data->geometry_component_owner; - return true; - } - - const PointCloud *pointcloud = geometry_set->get_pointcloud_for_read(); - if (pointcloud != nullptr) { - Object *temp_object = &data->temp_geometry_component_object; - *temp_object = *data->geometry_component_owner; - temp_object->type = OB_POINTCLOUD; - temp_object->data = (void *)pointcloud; - temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; - iter->current = temp_object; - return true; - } - } - - /* The volume component. */ - if (data->geometry_component_id == 2) { - data->geometry_component_id++; - - /* Don't use a temporary object for this component, when the owner is a volume object. */ - if (data->geometry_component_owner->type == OB_VOLUME) { - iter->current = data->geometry_component_owner; - return true; - } - - const VolumeComponent *component = geometry_set->get_component_for_read(); - if (component != nullptr) { - const Volume *volume = component->get_for_read(); - - if (volume != nullptr) { - Object *temp_object = &data->temp_geometry_component_object; - *temp_object = *data->geometry_component_owner; - temp_object->type = OB_VOLUME; - temp_object->data = (void *)volume; - temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; - iter->current = temp_object; - return true; - } - } - } - - /* The curve component. */ - if (data->geometry_component_id == 3) { - data->geometry_component_id++; - - const CurveComponent *component = geometry_set->get_component_for_read(); - if (component != nullptr) { - const Curve *curve = component->get_curve_for_render(); - - if (curve != nullptr) { - Object *temp_object = &data->temp_geometry_component_object; - *temp_object = *data->geometry_component_owner; - temp_object->type = OB_CURVE; - temp_object->data = (void *)curve; - /* Assign data_eval here too, because curve rendering code tries - * to use a mesh if it can find one in this pointer. */ - temp_object->runtime.data_eval = (ID *)curve; - temp_object->runtime.select_id = data->geometry_component_owner->runtime.select_id; - iter->current = temp_object; - return true; - } - } - } - - data->geometry_component_owner = nullptr; - return false; -} - void deg_iterator_duplis_init(DEGObjectIterData *data, Object *object) { if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && @@ -292,6 +168,9 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) temp_dupli_object->dt = MIN2(temp_dupli_object->dt, dupli_parent->dt); copy_v4_v4(temp_dupli_object->color, dupli_parent->color); temp_dupli_object->runtime.select_id = dupli_parent->runtime.select_id; + if (dob->ob->data != dob->ob_data) { + BKE_object_replace_data_on_shallow_copy(temp_dupli_object, dob->ob_data); + } /* Duplicated elements shouldn't care whether their original collection is visible or not. */ temp_dupli_object->base_flag |= BASE_VISIBLE_DEPSGRAPH; @@ -308,7 +187,7 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data) copy_m4_m4(data->temp_dupli_object.obmat, dob->mat); invert_m4_m4(data->temp_dupli_object.imat, data->temp_dupli_object.obmat); - deg_iterator_components_init(data, &data->temp_dupli_object); + data->next_object = &data->temp_dupli_object; BLI_assert(deg::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id)); return true; } @@ -377,7 +256,7 @@ bool deg_iterator_objects_step(DEGObjectIterData *data) } if (ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) { - deg_iterator_components_init(data, object); + data->next_object = object; } data->id_node_index++; return true; @@ -400,6 +279,7 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) return; } + data->next_object = nullptr; data->dupli_parent = nullptr; data->dupli_list = nullptr; data->dupli_object_next = nullptr; @@ -408,8 +288,6 @@ void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) data->id_node_index = 0; data->num_id_nodes = num_id_nodes; data->eval_mode = DEG_get_mode(depsgraph); - data->geometry_component_id = 0; - data->geometry_component_owner = nullptr; deg_invalidate_iterator_work_data(data); DEG_iterator_objects_next(iter); @@ -419,7 +297,9 @@ void DEG_iterator_objects_next(BLI_Iterator *iter) { DEGObjectIterData *data = (DEGObjectIterData *)iter->data; while (true) { - if (deg_iterator_components_step(iter)) { + if (data->next_object != nullptr) { + iter->current = data->next_object; + data->next_object = nullptr; return; } if (deg_iterator_duplis_step(data)) { diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 7f850435a64..9590a4aa7ee 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -632,14 +632,29 @@ void DRW_viewport_request_redraw(void) /** \name Duplis * \{ */ -static void drw_duplidata_load(DupliObject *dupli) +static uint dupli_key_hash(const void *key) { + const DupliKey *dupli_key = (const DupliKey *)key; + return BLI_ghashutil_ptrhash(dupli_key->ob) ^ BLI_ghashutil_ptrhash(dupli_key->ob_data); +} + +static bool dupli_key_cmp(const void *key1, const void *key2) +{ + const DupliKey *dupli_key1 = (const DupliKey *)key1; + const DupliKey *dupli_key2 = (const DupliKey *)key2; + return dupli_key1->ob != dupli_key2->ob || dupli_key1->ob_data != dupli_key2->ob_data; +} + +static void drw_duplidata_load(Object *ob) +{ + DupliObject *dupli = DST.dupli_source; if (dupli == NULL) { return; } - if (DST.dupli_origin != dupli->ob) { + if (DST.dupli_origin != dupli->ob || (DST.dupli_origin_data != dupli->ob_data)) { DST.dupli_origin = dupli->ob; + DST.dupli_origin_data = dupli->ob_data; } else { /* Same data as previous iter. No need to poll ghash for this. */ @@ -647,16 +662,23 @@ static void drw_duplidata_load(DupliObject *dupli) } if (DST.dupli_ghash == NULL) { - DST.dupli_ghash = BLI_ghash_ptr_new(__func__); + DST.dupli_ghash = BLI_ghash_new(dupli_key_hash, dupli_key_cmp, __func__); } + DupliKey *key = MEM_callocN(sizeof(DupliKey), __func__); + key->ob = dupli->ob; + key->ob_data = dupli->ob_data; + void **value; - if (!BLI_ghash_ensure_p(DST.dupli_ghash, DST.dupli_origin, &value)) { + if (!BLI_ghash_ensure_p(DST.dupli_ghash, key, &value)) { *value = MEM_callocN(sizeof(void *) * DST.enabled_engine_count, __func__); /* TODO: Meh a bit out of place but this is nice as it is - * only done once per "original" object. */ - drw_batch_cache_validate(DST.dupli_origin); + * only done once per instance type. */ + drw_batch_cache_validate(ob); + } + else { + MEM_freeN(key); } DST.dupli_datas = *(void ***)value; } @@ -670,12 +692,24 @@ static void duplidata_value_free(void *val) MEM_freeN(val); } +static void duplidata_key_free(void *key) +{ + DupliKey *dupli_key = (DupliKey *)key; + if (dupli_key->ob_data == NULL) { + drw_batch_cache_generate_requested(dupli_key->ob); + } + else { + Object temp_object = *dupli_key->ob; + BKE_object_replace_data_on_shallow_copy(&temp_object, dupli_key->ob_data); + drw_batch_cache_generate_requested(&temp_object); + } + MEM_freeN(key); +} + static void drw_duplidata_free(void) { if (DST.dupli_ghash != NULL) { - BLI_ghash_free(DST.dupli_ghash, - (void (*)(void *key))drw_batch_cache_generate_requested, - duplidata_value_free); + BLI_ghash_free(DST.dupli_ghash, duplidata_key_free, duplidata_value_free); DST.dupli_ghash = NULL; } } @@ -1523,6 +1557,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, /* Only iterate over objects for internal engines or when overlays are enabled */ if (do_populate_loop) { DST.dupli_origin = NULL; + DST.dupli_origin_data = NULL; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; @@ -1532,7 +1567,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, } DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; - drw_duplidata_load(DST.dupli_source); + drw_duplidata_load(ob); drw_engines_cache_populate(ob); } DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; @@ -1881,12 +1916,13 @@ void DRW_render_object_iter( draw_ctx->v3d->object_type_exclude_viewport : 0; DST.dupli_origin = NULL; + DST.dupli_origin_data = NULL; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { if ((object_type_exclude_viewport & (1 << ob->type)) == 0) { DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; DST.ob_handle = 0; - drw_duplidata_load(DST.dupli_source); + drw_duplidata_load(ob); if (!DST.dupli_source) { drw_batch_cache_validate(ob); @@ -2330,6 +2366,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, v3d->object_type_exclude_select); bool filter_exclude = false; DST.dupli_origin = NULL; + DST.dupli_origin_data = NULL; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (depsgraph, ob) { if (!BKE_object_is_visible_in_viewport(v3d, ob)) { continue; @@ -2362,7 +2399,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, DRW_select_load_id(ob->runtime.select_id); DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; - drw_duplidata_load(DST.dupli_source); + drw_duplidata_load(ob); drw_engines_cache_populate(ob); } } @@ -2475,6 +2512,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; DST.dupli_origin = NULL; + DST.dupli_origin_data = NULL; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN (DST.draw_ctx.depsgraph, ob) { if ((object_type_exclude_viewport & (1 << ob->type)) != 0) { continue; @@ -2484,7 +2522,7 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, } DST.dupli_parent = data_.dupli_parent; DST.dupli_source = data_.dupli_object_current; - drw_duplidata_load(DST.dupli_source); + drw_duplidata_load(ob); drw_engines_cache_populate(ob); } DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END; diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h index 33e1a57198c..1747ca752c7 100644 --- a/source/blender/draw/intern/draw_manager.h +++ b/source/blender/draw/intern/draw_manager.h @@ -497,6 +497,11 @@ typedef struct DRWDebugSphere { /* ------------- DRAW MANAGER ------------ */ +typedef struct DupliKey { + struct Object *ob; + struct ID *ob_data; +} DupliKey; + #define DST_MAX_SLOTS 64 /* Cannot be changed without modifying RST.bound_tex_slots */ #define MAX_CLIP_PLANES 6 /* GL_MAX_CLIP_PLANES is at least 6 */ #define STENCIL_UNDEFINED 256 @@ -515,15 +520,19 @@ typedef struct DRWManager { /** Handle of next DRWPass to be allocated. */ DRWResourceHandle pass_handle; - /** Dupli state. NULL if not dupli. */ + /** Dupli object that corresponds to the current object. */ struct DupliObject *dupli_source; + /** Object that created the dupli-list the current object is part of. */ struct Object *dupli_parent; + /** Object referenced by the current dupli object. */ struct Object *dupli_origin; - /** Ghash containing original objects. */ + /** Object-data referenced by the current dupli object. */ + struct ID *dupli_origin_data; + /** Ghash: #DupliKey -> void pointer for each enabled engine. */ struct GHash *dupli_ghash; /** TODO(fclem): try to remove usage of this. */ DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE]; - /* Array of dupli_data (one for each enabled engine) to handle duplis. */ + /* Dupli data for the current dupli for each enabled engine. */ void **dupli_datas; /* Rendering state */ diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 2e34284f46e..f95e3f3b236 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -2246,13 +2246,6 @@ static bool dupliobject_instancer_cmp(const void *a_, const void *b_) return false; } -static bool object_has_geometry_set_instances(const Object *object_eval) -{ - struct GeometrySet *geometry_set = object_eval->runtime.geometry_set_eval; - - return (geometry_set != NULL) && BKE_geometry_set_has_instances(geometry_set); -} - static void make_object_duplilist_real(bContext *C, Depsgraph *depsgraph, Scene *scene, @@ -2266,7 +2259,8 @@ static void make_object_duplilist_real(bContext *C, Object *object_eval = DEG_get_evaluated_object(depsgraph, base->object); - if (!(base->object->transflag & OB_DUPLI) && !object_has_geometry_set_instances(object_eval)) { + if (!(base->object->transflag & OB_DUPLI) && + !BKE_object_has_geometry_set_instances(object_eval)) { return; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh index 680da9b6794..97170693cb3 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh @@ -35,6 +35,10 @@ struct CollectionCellValue { const Collection *collection; }; +struct GeometrySetCellValue { + const GeometrySet *geometry_set; +}; + /** * This is a type that can hold the value of a cell in a spreadsheet. This type allows us to * decouple the drawing of individual cells from the code that generates the data to be displayed. @@ -53,6 +57,7 @@ class CellValue { std::optional value_color; std::optional value_object; std::optional value_collection; + std::optional value_geometry_set; }; } // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index e38c70afd0f..12815c2c7e9 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -332,6 +332,11 @@ std::unique_ptr InstancesDataSource::get_column_values( r_cell_value.value_collection = CollectionCellValue{&collection}; break; } + case InstanceReference::Type::GeometrySet: { + const GeometrySet &geometry_set = reference.geometry_set(); + r_cell_value.value_geometry_set = GeometrySetCellValue{&geometry_set}; + break; + } case InstanceReference::Type::None: { break; } diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index 8079763a339..1a5eac53306 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -209,6 +209,23 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { 0, nullptr); } + else if (cell_value.value_geometry_set.has_value()) { + uiDefIconTextBut(params.block, + UI_BTYPE_LABEL, + 0, + ICON_MESH_DATA, + "Geometry", + params.xmin, + params.ymin, + params.width, + params.height, + nullptr, + 0, + 0, + 0, + 0, + nullptr); + } } void draw_float_vector(const CellDrawParams ¶ms, const Span values) const diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index bb04f557074..811f30c96e5 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -501,9 +501,7 @@ static void iter_snap_objects(SnapObjectContext *sctx, } Object *obj_eval = DEG_get_evaluated_object(depsgraph, base->object); - if (obj_eval->transflag & OB_DUPLI || - (obj_eval->runtime.geometry_set_eval != NULL && - BKE_geometry_set_has_instances(obj_eval->runtime.geometry_set_eval))) { + if (obj_eval->transflag & OB_DUPLI || BKE_object_has_geometry_set_instances(obj_eval)) { ListBase *lb = object_duplilist(depsgraph, sctx->scene, obj_eval); for (DupliObject *dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { BLI_assert(DEG_is_evaluated_object(dupli_ob->ob)); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 43dd4b4270e..fd67150811d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -1889,6 +1889,7 @@ typedef enum GeometryNodeTriangulateQuads { typedef enum GeometryNodePointInstanceType { GEO_NODE_POINT_INSTANCE_TYPE_OBJECT = 0, GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION = 1, + GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY = 2, } GeometryNodePointInstanceType; typedef enum GeometryNodePointInstanceFlag { diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 9e24a36915e..a7c0372f309 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -9295,6 +9295,11 @@ static void def_geo_point_instance(StructRNA *srna) ICON_NONE, "Collection", "Instance an entire collection on all points"}, + {GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY, + "GEOMETRY", + ICON_NONE, + "Geometry", + "Copy geometry to all points"}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index 36017307739..9f67638de7e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -31,13 +31,14 @@ static void geo_node_point_instance_declare(NodeDeclarationBuilder &b) b.add_input("Geometry"); b.add_input("Object").hide_label(true); b.add_input("Collection").hide_label(true); + b.add_input("Instance Geometry"); b.add_input("Seed").min(-10000).max(10000); b.add_output("Geometry"); } static void geo_node_point_instance_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "instance_type", UI_ITEM_R_EXPAND, nullptr, ICON_NONE); + uiItemR(layout, ptr, "instance_type", 0, nullptr, ICON_NONE); if (RNA_enum_get(ptr, "instance_type") == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { uiItemR(layout, ptr, "use_whole_collection", 0, nullptr, ICON_NONE); } @@ -56,7 +57,8 @@ static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) { bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1); bNodeSocket *collection_socket = object_socket->next; - bNodeSocket *seed_socket = collection_socket->next; + bNodeSocket *instance_geometry_socket = collection_socket->next; + bNodeSocket *seed_socket = instance_geometry_socket->next; NodeGeometryPointInstance *node_storage = (NodeGeometryPointInstance *)node->storage; GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node_storage->instance_type; @@ -65,6 +67,8 @@ static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); + nodeSetSocketAvailability(instance_geometry_socket, + type == GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY); nodeSetSocketAvailability( seed_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION && !use_whole_collection); } @@ -114,6 +118,12 @@ static Vector get_instance_references__collection(GeoNodeExec return references; } +static Vector get_instance_references__geometry(GeoNodeExecParams ¶ms) +{ + GeometrySet geometry_set = params.extract_input("Instance Geometry"); + return {std::move(geometry_set)}; +} + static Vector get_instance_references(GeoNodeExecParams ¶ms) { const bNode &node = params.node(); @@ -128,6 +138,9 @@ static Vector get_instance_references(GeoNodeExecParams ¶ case GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION: { return get_instance_references__collection(params); } + case GEO_NODE_POINT_INSTANCE_TYPE_GEOMETRY: { + return get_instance_references__geometry(params); + } } return {}; } -- cgit v1.2.3 From 3b1a16833b5834d768eacbcfdff4ee000a8d1af5 Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Mon, 6 Sep 2021 09:40:06 -0700 Subject: UI: Area Split and Join Mouse Cursor Feedback This patch just changes the mouse cursor to a "stop sign" when dragging to an unsupported location during Join or Split operations. See D11396 for details and examples. Differential Revision: https://developer.blender.org/D11396 Reviewed by Campbell Barton --- source/blender/editors/screen/screen_ops.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 75f1baf30bb..5d6f21f4854 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1134,14 +1134,22 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) if ((ED_area_actionzone_find_xy(sad->sa1, &event->x) != sad->az) && (screen_geom_area_map_find_active_scredge( AREAMAP_FROM_SCREEN(screen), &screen_rect, event->x, event->y) == NULL)) { - /* Are we still in same area? */ - if (BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y) == sad->sa1) { + + /* What area are we now in? */ + ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, event->x, event->y); + + if (area == sad->sa1) { /* Same area, so possible split. */ WM_cursor_set(win, SCREEN_DIR_IS_VERTICAL(sad->gesture_dir) ? WM_CURSOR_H_SPLIT : WM_CURSOR_V_SPLIT); is_gesture = (delta_max > split_threshold); } + else if (!area || area->global) { + /* No area or Top bar or Status bar. */ + WM_cursor_set(win, WM_CURSOR_STOP); + is_gesture = false; + } else { /* Different area, so possible join. */ if (sad->gesture_dir == SCREEN_DIR_N) { @@ -1161,7 +1169,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else { - WM_cursor_set(CTX_wm_window(C), WM_CURSOR_CROSS); + WM_cursor_set(win, WM_CURSOR_CROSS); is_gesture = false; } } -- cgit v1.2.3 From 08593e46a3392a78420f3ec2a871aec9228c9d42 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Mon, 6 Sep 2021 18:46:13 +0200 Subject: Fix T91187: incorrect socket identifier --- source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc index 582b1a88221..5d3d75b4678 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc @@ -31,7 +31,11 @@ static void geo_node_mix_attribute_declare(NodeDeclarationBuilder &b) { b.add_input("Geometry"); b.add_input("Factor"); - b.add_input("Factor").default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR); + b.add_input("Factor", "Factor_001") + .default_value(0.5f) + .min(0.0f) + .max(1.0f) + .subtype(PROP_FACTOR); b.add_input("A"); b.add_input("A", "A_001"); b.add_input("A", "A_002"); -- cgit v1.2.3 From d7d8eb7de468dc2b3940d1ebb81cb16cdadbce3f Mon Sep 17 00:00:00 2001 From: Antonio Vazquez Date: Mon, 6 Sep 2021 18:56:01 +0200 Subject: GPencil: Change icons missing in previous commit It was missing to change the modifier itself, not only RNA enum list. --- source/blender/makesrna/intern/rna_gpencil_modifier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 06e8f7db0af..55fe74cab4f 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -2902,7 +2902,7 @@ static void rna_def_modifier_gpencillineart(BlenderRNA *brna) RNA_def_struct_ui_text( srna, "Line Art Modifier", "Generate line art strokes from selected source"); RNA_def_struct_sdna(srna, "LineartGpencilModifierData"); - RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT); + RNA_def_struct_ui_icon(srna, ICON_MOD_LINEART); RNA_define_lib_overridable(true); @@ -3199,7 +3199,7 @@ static void rna_def_modifier_gpencillength(BlenderRNA *brna) srna = RNA_def_struct(brna, "LengthGpencilModifier", "GpencilModifier"); RNA_def_struct_ui_text(srna, "Length Modifier", "Stretch or shrink strokes"); RNA_def_struct_sdna(srna, "LengthGpencilModifierData"); - RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT); + RNA_def_struct_ui_icon(srna, ICON_MOD_LENGTH); RNA_define_lib_overridable(true); -- cgit v1.2.3