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:
authorJacques Lucke <jacques@blender.org>2021-09-06 20:42:52 +0300
committerJacques Lucke <jacques@blender.org>2021-09-06 20:42:52 +0300
commit8ba889a4be4f97098cb60605531eed8841e52484 (patch)
tree3c8f5e6e311934bd01a2b97a45863a989fb89bc6
parent5cd7e557ae112ec9f3649a6d2a6d0f19c75211c9 (diff)
parentd7d8eb7de468dc2b3940d1ebb81cb16cdadbce3f (diff)
Merge branch 'master' into temp-geometry-nodes-fields
-rw-r--r--build_files/windows/icons.cmd2
-rw-r--r--extern/mantaflow/UPDATE.sh2
-rw-r--r--extern/mantaflow/helper/pwrapper/pconvert.cpp6
-rw-r--r--extern/mantaflow/helper/pwrapper/pvec3.cpp6
-rw-r--r--extern/mantaflow/helper/pwrapper/registry.cpp3
-rw-r--r--extern/mantaflow/preprocessed/fastmarch.cpp202
-rw-r--r--extern/mantaflow/preprocessed/gitinfo.h2
-rw-r--r--intern/cycles/blender/blender_curves.cpp42
-rw-r--r--intern/cycles/blender/blender_geometry.cpp42
-rw-r--r--intern/cycles/blender/blender_light.cpp15
-rw-r--r--intern/cycles/blender/blender_mesh.cpp61
-rw-r--r--intern/cycles/blender/blender_object.cpp26
-rw-r--r--intern/cycles/blender/blender_sync.h29
-rw-r--r--intern/cycles/blender/blender_util.h49
-rw-r--r--intern/cycles/blender/blender_volume.cpp21
-rw-r--r--release/datafiles/blender_icons.svg52
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_dash.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_length.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons16/icon16_mod_lineart.datbin0 -> 1048 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_dash.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_length.datbin0 -> 4120 bytes
-rw-r--r--release/datafiles/blender_icons32/icon32_mod_lineart.datbin0 -> 4120 bytes
-rw-r--r--source/blender/blenkernel/BKE_duplilist.h4
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.h2
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh45
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/intern/geometry_component_instances.cc15
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc37
-rw-r--r--source/blender/blenkernel/intern/geometry_set_instances.cc12
-rw-r--r--source/blender/blenkernel/intern/object.c13
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc97
-rw-r--r--source/blender/blenlib/BLI_user_counter.hh12
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h10
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc138
-rw-r--r--source/blender/draw/intern/draw_manager.c64
-rw-r--r--source/blender/draw/intern/draw_manager.h15
-rw-r--r--source/blender/editors/datafiles/CMakeLists.txt3
-rw-r--r--source/blender/editors/include/UI_icons.h6
-rw-r--r--source/blender/editors/object/object_add.c10
-rw-r--r--source/blender/editors/screen/screen_ops.c14
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_cell_value.hh5
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc5
-rw-r--r--source/blender/editors/space_spreadsheet/spreadsheet_layout.cc17
-rw-r--r--source/blender/editors/transform/transform_snap_object.c4
-rw-r--r--source/blender/makesdna/DNA_node_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c8
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c5
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc6
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_point_instance.cc17
49 files changed, 732 insertions, 395 deletions
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
)
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/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<Real> &phi, Grid<int> &tmp, bool inside)
+ : KernelBase(&phi, 1), phi(phi), tmp(tmp), inside(inside)
+ {
+ runMessage();
+ run();
+ }
+ inline void op(int i, int j, int k, Grid<Real> &phi, Grid<int> &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<Real> &getArg0()
+ {
+ return phi;
+ }
+ typedef Grid<Real> type0;
+ inline Grid<int> &getArg1()
+ {
+ return tmp;
+ }
+ typedef Grid<int> 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<IndexInt> &__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<IndexInt>(minZ, maxZ), *this);
+ else
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
+ }
+ Grid<Real> &phi;
+ Grid<int> &tmp;
+ bool inside;
+};
+
+struct knSetFirstLayer : public KernelBase {
+ knSetFirstLayer(Grid<int> &tmp, int dim) : KernelBase(&tmp, 1), tmp(tmp), dim(dim)
+ {
+ runMessage();
+ run();
+ }
+ inline void op(int i, int j, int k, Grid<int> &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<int> &getArg0()
+ {
+ return tmp;
+ }
+ typedef Grid<int> 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<IndexInt> &__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<IndexInt>(minZ, maxZ), *this);
+ else
+ tbb::parallel_for(tbb::blocked_range<IndexInt>(1, maxY), *this);
+ }
+ Grid<int> &tmp;
+ int dim;
+};
+
template<class S> struct knExtrapolateLsSimple : public KernelBase {
knExtrapolateLsSimple(Grid<S> &val, int distance, Grid<int> &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<Real> &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<Vec3> &vel, Grid<Real> &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<Vec3>(vel, distance, tmp, d, Vec3(0.));
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"
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<Node *> 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<Node *> used_shaders = find_used_shaders(b_ob);
+ array<Node *> 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<Hair *>(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<Volume *>(geom);
- sync_volume(b_ob, volume);
+ sync_volume(b_ob_info, volume);
}
else {
Mesh *mesh = static_cast<Mesh *>(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<Hair *>(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<Mesh *>(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<Node *> &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<BL::Object &>(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/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" />
+ <g
+ transform="translate(230.76791,210.17135)"
+ style="display:inline;enable-background:new"
+ id="g4087_GP_lineart">
+ <g
+ id="g4082">
+ <path
+ sodipodi:nodetypes="cccccccccccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path12456-6"
+ mask="none"
+ d="m 198.0253,98.27163 v 1.5 h 1 v -1.5 z m 0,2.5 v 2 h 1 v -2 z m 0,3 v 1.2793 l -2.58594,2.35156 0.67188,0.73828 2.60351,-2.36719 0.49027,-0.002 c 0.82475,0 0.82408,-1 0,-1 h -0.17972 v -1 z"
+ 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:0.6;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:evenodd;stroke:none;stroke-width:1px;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ id="path4185"
+ 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;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:evenodd;stroke:none;stroke-width:1.10423;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 207.2397,99.568306 c -0.33768,-0.02992 -0.70751,0.105959 -1.01625,0.406518 l -0.51139,0.495896 c -0.13287,0.12942 -0.13287,0.34092 0,0.47035 l 2.04339,1.98784 c 0.13292,0.12938 0.3479,0.12938 0.48082,0 l 0.50922,-0.49802 c 0.3087,-0.30067 0.44811,-0.65869 0.41741,-0.98755 -0.0307,-0.32884 -0.20718,-0.60186 -0.41741,-0.80663 l -0.67969,-0.661886 c -0.21026,-0.204768 -0.48842,-0.37662 -0.8261,-0.406518 z m -2.31222,1.800554 c -0.0883,9.4e-4 -0.17353,0.0367 -0.23603,0.0979 l -4.25293,4.14168 c -0.0434,0.0426 -0.0749,0.095 -0.0896,0.15324 l -0.67969,2.65189 c -0.0614,0.24217 0.16235,0.46285 0.41088,0.40225 l 2.72308,-0.66402 c 0.0599,-0.0144 0.11363,-0.0428 0.15735,-0.0851 l 4.2551,-4.14382 c 0.13286,-0.12943 0.13286,-0.33881 0,-0.46825 l -2.0434,-1.98784 c -0.0651,-0.0634 -0.15267,-0.0994 -0.24478,-0.0979 z" />
+ <path
+ id="path12458-7"
+ 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;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:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 198.52539,94.771484 c -0.1326,2.7e-5 -0.25978,0.05272 -0.35351,0.146485 l -3,3 c -0.0938,0.09376 -0.14646,0.220915 -0.14649,0.353515 v 9.999996 c 3e-5,0.27613 0.22387,0.49997 0.5,0.5 h 2.50158 c 0.72806,0 0.76638,-1.01916 0,-1 h -2.00158 v -8.999996 h 9 v 0.186392 c 0,0.766385 1,0.767345 1,0 v -0.47936 l 2,-2 v 0.907841 c 0,0.708905 1,0.709935 1,0 v -2.114873 c -3e-5,-0.276131 -0.22387,-0.499972 -0.5,-0.5 z m 0.20703,1 h 8.58594 l -2,2 h -8.58594 z"
+ sodipodi:nodetypes="ccccccsccccssccsscccccccc" />
+ </g>
+ </g>
+ <g
+ transform="translate(167.42608,209.69482)"
+ style="display:inline;enable-background:new"
+ id="g7880_GP_lenght">
+ <path
+ 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.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+ d="m 224.38607,100.78271 c -0.15574,0.005 -0.30353,0.0699 -0.41211,0.18164 l -2.05673,2.00254 c -0.62065,0.56444 0.28322,1.46831 0.84766,0.84765 l 2.05673,-2.00254 c 0.39088,-0.38144 0.1104,-1.04428 -0.43555,-1.02929 z"
+ id="path15289-7-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path15289-7-6-5"
+ d="m 225.6621,95.349988 c -0.67621,-0.0096 -0.67621,1.009611 0,1 h 2.79493 c -1.0479,1.117288 -1.7641,1.668027 -2.82812,2.732043 -0.62065,0.56444 0.28321,1.468319 0.84765,0.847657 1.06063,-1.101282 1.59202,-1.777197 2.68554,-2.870716 v 2.791016 c -0.01,0.676162 1.00956,0.676162 1,0 v -4 c -3e-5,-0.276131 -0.22387,-0.499973 -0.5,-0.5 z"
+ 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.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ <path
+ sodipodi:nodetypes="ccccccccccc"
+ inkscape:connector-curvature="0"
+ id="path15289-7-6-5-2"
+ d="m 221.03217,109.33958 c 0.67621,0.01 0.67621,-1.00961 0,-1 h -2.79493 c 1.0479,-1.11729 1.7641,-1.66802 2.82812,-2.73204 0.62065,-0.56444 -0.28321,-1.46832 -0.84765,-0.84766 -1.06063,1.10128 -1.59202,1.7772 -2.68554,2.87072 v -2.79102 c 0.01,-0.67616 -1.00956,-0.67616 -1,0 v 4 c 3e-5,0.27613 0.22387,0.49998 0.5,0.5 z"
+ 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.2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
+ </g>
+ <path
+ sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+ d="m 417.92349,304.73964 c -0.7818,-0.0644 -0.86293,1.09626 -0.0796,1.1383 l 0.41758,0.0202 c 0.78182,0.0644 0.86296,-1.09626 0.0796,-1.13831 z m -7.87437,1.29265 c -0.65325,0.42724 0.0163,1.38626 0.65667,0.94062 l 0.34001,-0.23929 c 0.65327,-0.42727 -0.0163,-1.38631 -0.65662,-0.94061 z m 5.26412,-0.10772 c 0.785,-0.0185 0.73895,-1.18175 -0.0451,-1.14009 -0.6811,-0.0652 -1.43225,-0.0213 -2.22341,0.0851 -0.785,0.0185 -0.73896,1.18176 0.0451,1.14011 0.8585,-0.10954 1.60282,-0.14009 2.22342,-0.0852 z m -5.74172,5.34858 c -0.17789,-0.75187 -1.32618,-0.47161 -1.12597,0.27482 -0.008,0.72815 0.18352,1.43475 0.53595,2.12392 0.17789,0.75187 1.32617,0.47159 1.12598,-0.27483 -0.40688,-0.70818 -0.47775,-1.41605 -0.53596,-2.12391 z m 1.14987,4.81425 c 0.55238,0.5479 1.3799,-0.2833 0.81165,-0.81524 l -0.30437,-0.28193 c -0.55238,-0.54789 -1.37991,0.2833 -0.81163,0.81524 z m 2.55883,0.11471 c -0.78112,0.0716 -0.65484,1.22767 0.12391,1.13446 0.79706,0.0708 1.5429,0.0136 2.2124,-0.23372 0.7811,-0.0716 0.65482,-1.22768 -0.12391,-1.13445 -0.66955,0.35373 -1.42049,0.37687 -2.2124,0.23371 z m 4.35036,-1.24066 c 0.39775,-0.66505 -0.63058,-1.23994 -1.00859,-0.56384 l -0.19953,0.36135 c -0.39776,0.66506 0.63057,1.23995 1.00857,0.56383 z m -1.53457,-4.82813 c -0.44444,-0.63566 -1.409,0.0364 -0.94666,0.65956 0.53116,0.53126 0.99257,1.10609 1.28624,1.78569 0.44445,0.63565 1.40902,-0.0364 0.94667,-0.65956 -0.24301,-0.74231 -0.69323,-1.32054 -1.28625,-1.78569 z m -2.73483,-1.49223 c -0.72218,-0.30138 -1.16808,0.7761 -0.43732,1.05681 l 0.39025,0.14758 c 0.7222,0.30141 1.1681,-0.7761 0.43732,-1.0568 z m -7.60223,1.91562 c -0.52109,0.57678 0.37464,1.33651 0.87855,0.74515 l 0.26685,-0.31654 c 0.52111,-0.57679 -0.37465,-1.33654 -0.87854,-0.74516 z m 1.15912,7.09355 c -0.1906,-0.74845 -1.33363,-0.44917 -1.12109,0.29354 l 0.11543,0.39523 c 0.19062,0.74845 1.33365,0.44917 1.12109,-0.29354 z m -0.68592,-4.36328 c -0.0858,-0.76698 -1.25912,-0.62352 -1.15127,0.14077 -0.065,0.75431 -0.008,1.50847 0.28594,2.26232 0.0859,0.76696 1.25912,0.62352 1.15129,-0.14076 -0.28468,-0.81162 -0.29126,-1.53878 -0.28596,-2.26233 z m 1.97398,-4.7241 c -0.77314,0.13162 -0.55483,1.27463 0.21417,1.12135 0.7762,-0.30633 1.5005,-0.42412 2.18687,-0.40397 0.77313,-0.13163 0.55482,-1.27462 -0.21418,-1.12137 -0.74152,0.0229 -1.4733,0.13255 -2.18686,0.40399 z"
+ 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;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.15052;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:2.2;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:new"
+ id="path4101-2-6-9-1_GP_dotdash" />
</g>
<g
inkscape:groupmode="layer"
diff --git a/release/datafiles/blender_icons16/icon16_mod_dash.dat b/release/datafiles/blender_icons16/icon16_mod_dash.dat
new file mode 100644
index 00000000000..a8419db8c16
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_dash.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_mod_length.dat b/release/datafiles/blender_icons16/icon16_mod_length.dat
new file mode 100644
index 00000000000..0e1e25fcd71
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_length.dat
Binary files differ
diff --git a/release/datafiles/blender_icons16/icon16_mod_lineart.dat b/release/datafiles/blender_icons16/icon16_mod_lineart.dat
new file mode 100644
index 00000000000..3478b14fdab
--- /dev/null
+++ b/release/datafiles/blender_icons16/icon16_mod_lineart.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_dash.dat b/release/datafiles/blender_icons32/icon32_mod_dash.dat
new file mode 100644
index 00000000000..cca56b0c9de
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_dash.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_length.dat b/release/datafiles/blender_icons32/icon32_mod_length.dat
new file mode 100644
index 00000000000..0d1cf1f33aa
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_length.dat
Binary files differ
diff --git a/release/datafiles/blender_icons32/icon32_mod_lineart.dat b/release/datafiles/blender_icons32/icon32_mod_lineart.dat
new file mode 100644
index 00000000000..a8e9c976a9f
--- /dev/null
+++ b/release/datafiles/blender_icons32/icon32_mod_lineart.dat
Binary files differ
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 dd921d0d373..c3d594d7dcd 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -289,6 +289,7 @@ struct GeometrySet {
void clear();
+ bool owns_direct_data() const;
void ensure_owns_direct_data();
/* Utility methods for creation. */
@@ -453,12 +454,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<GeometrySet> geometry_set_;
public:
InstanceReference() = default;
@@ -471,6 +474,19 @@ class InstanceReference {
{
}
+ InstanceReference(GeometrySet geometry_set)
+ : type_(Type::GeometrySet),
+ geometry_set_(std::make_unique<GeometrySet>(std::move(geometry_set)))
+ {
+ }
+
+ InstanceReference(const InstanceReference &src) : type_(src.type_), data_(src.data_)
+ {
+ if (src.type_ == Type::GeometrySet) {
+ geometry_set_ = std::make_unique<GeometrySet>(*src.geometry_set_);
+ }
+ }
+
Type type() const
{
return type_;
@@ -488,14 +504,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();
}
};
@@ -535,7 +574,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<InstanceReference> 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<int> 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<InstanceReference &>(const_reference);
+ reference.ensure_owns_direct_data();
+ }
}
static blender::Array<int> generate_unique_instance_ids(Span<int> 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<InstancesComponent>() != 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 d281407dd5a..0e19324a3c1 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<InstancesComponent>();
+ 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<CurveComponent>();
+ 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<InstancesComponent>();
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<float4x4> instance_offset_matrices = component->instance_transforms();
Span<int> instance_reference_handles = component->instance_reference_handles();
Span<int> 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<typename T> 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<VolumeComponent>();
- 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<CurveComponent>();
- 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/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt
index c4916b9182f..669ceb37328 100644
--- a/source/blender/editors/datafiles/CMakeLists.txt
+++ b/source/blender/editors/datafiles/CMakeLists.txt
@@ -390,6 +390,9 @@ set(ICON_NAMES
small_caps
modifier
con_action
+ mod_length
+ mod_dash
+ mod_lineart
holdout_off
holdout_on
indirect_only_off
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 1708c3598b1..ddd9ca4a98c 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -490,9 +490,9 @@ DEF_ICON_MODIFIER(CON_ACTION)
DEF_ICON_BLANK(745)
DEF_ICON_BLANK(746)
DEF_ICON_BLANK(747)
-DEF_ICON_BLANK(748)
-DEF_ICON_BLANK(749)
-DEF_ICON_BLANK(750)
+DEF_ICON_MODIFIER(MOD_LENGTH)
+DEF_ICON_MODIFIER(MOD_DASH)
+DEF_ICON_MODIFIER(MOD_LINEART)
DEF_ICON_BLANK(751)
DEF_ICON(HOLDOUT_OFF)
DEF_ICON(HOLDOUT_ON)
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/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;
}
}
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<ColorGeometry4f> value_color;
std::optional<ObjectCellValue> value_object;
std::optional<CollectionCellValue> value_collection;
+ std::optional<GeometrySetCellValue> 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 f3ca246c78c..f5fef5e4486 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
@@ -337,6 +337,11 @@ std::unique_ptr<ColumnValues> 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 &params, const Span<float> 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 174101771b2..82eabf6995c 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1896,6 +1896,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_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 4e95174e42b..55fe74cab4f 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"},
@@ -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);
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index b13745a0809..aa9fb410a14 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_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<decl::Geometry>("Geometry");
b.add_input<decl::String>("Factor");
- b.add_input<decl::Float>("Factor").default_value(0.5f).min(0.0f).max(1.0f).subtype(PROP_FACTOR);
+ b.add_input<decl::Float>("Factor", "Factor_001")
+ .default_value(0.5f)
+ .min(0.0f)
+ .max(1.0f)
+ .subtype(PROP_FACTOR);
b.add_input<decl::String>("A");
b.add_input<decl::Float>("A", "A_001");
b.add_input<decl::Vector>("A", "A_002");
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<decl::Geometry>("Geometry");
b.add_input<decl::Object>("Object").hide_label(true);
b.add_input<decl::Collection>("Collection").hide_label(true);
+ b.add_input<decl::Geometry>("Instance Geometry");
b.add_input<decl::Int>("Seed").min(-10000).max(10000);
b.add_output<decl::Geometry>("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<InstanceReference> get_instance_references__collection(GeoNodeExec
return references;
}
+static Vector<InstanceReference> get_instance_references__geometry(GeoNodeExecParams &params)
+{
+ GeometrySet geometry_set = params.extract_input<GeometrySet>("Instance Geometry");
+ return {std::move(geometry_set)};
+}
+
static Vector<InstanceReference> get_instance_references(GeoNodeExecParams &params)
{
const bNode &node = params.node();
@@ -128,6 +138,9 @@ static Vector<InstanceReference> get_instance_references(GeoNodeExecParams &para
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 {};
}